[[package]]
name = "cmake"
-version = "0.1.44"
+version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e56268c17a6248366d66d4a47a3381369d068cce8409bb1716ed77ea32163bb"
+checksum = "eb6210b637171dfba4cda12e579ac6dc73f5165ad56133e5d72ef3131f320855"
dependencies = [
"cc",
]
dependencies = [
"assists",
"base_db",
+ "either",
"expect-test",
"hir",
"ide_db",
[[package]]
name = "once_cell"
-version = "1.5.1"
+version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f53cef67919d7d247eb9a2f128ca9e522789967ef1eb4ccd8c71a95a8aedf596"
+checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
[[package]]
name = "oorandom"
[[package]]
name = "tinyvec"
-version = "0.3.4"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117"
+checksum = "b78a366903f506d2ad52ca8dc552102ffdd3e937ba8a227f024dc1d1eae28575"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "toolchain"
[[package]]
name = "unicode-normalization"
-version = "0.1.13"
+version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977"
+checksum = "b7f98e67a4d84f730d343392f9bfff7d21e3fca562b9cb7a43b768350beeddc6"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
-version = "1.6.0"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
+checksum = "db8716a166f290ff49dabc18b44aa407cb7c6dbe1aa0971b44b8a24b0ca35aae"
[[package]]
name = "unicode-xid"
let range = ctx.sema.original_range(import_assets.syntax_under_caret()).range;
let group = import_group_message(import_assets.import_candidate());
- let scope = ImportScope::find_insert_use_container(import_assets.syntax_under_caret(), ctx)?;
+ let scope =
+ ImportScope::find_insert_use_container(import_assets.syntax_under_caret(), &ctx.sema)?;
for (import, _) in proposed_imports {
acc.add_group(
&group,
if let Some(mut mod_path) = mod_path {
mod_path.segments.pop();
mod_path.segments.push(variant_hir_name.clone());
- let scope = ImportScope::find_insert_use_container(scope_node, ctx)?;
-
+ let scope = ImportScope::find_insert_use_container(scope_node, &ctx.sema)?;
*rewriter += insert_use(&scope, mod_path_to_ast(&mod_path), ctx.config.insert_use.merge);
}
Some(())
let current_module = ctx.sema.scope(annotated_name.syntax()).module()?;
let current_crate = current_module.krate();
- let found_traits = imports_locator::find_imports(&ctx.sema, current_crate, trait_token.text())
- .into_iter()
- .filter_map(|candidate: either::Either<hir::ModuleDef, hir::MacroDef>| match candidate {
- either::Either::Left(hir::ModuleDef::Trait(trait_)) => Some(trait_),
- _ => None,
- })
- .flat_map(|trait_| {
- current_module
- .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_))
- .as_ref()
- .map(mod_path_to_ast)
- .zip(Some(trait_))
- });
+ let found_traits =
+ imports_locator::find_exact_imports(&ctx.sema, current_crate, trait_token.text())
+ .filter_map(
+ |candidate: either::Either<hir::ModuleDef, hir::MacroDef>| match candidate {
+ either::Either::Left(hir::ModuleDef::Trait(trait_)) => Some(trait_),
+ _ => None,
+ },
+ )
+ .flat_map(|trait_| {
+ current_module
+ .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_))
+ .as_ref()
+ .map(mod_path_to_ast)
+ .zip(Some(trait_))
+ });
let mut no_traits_found = true;
for (trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) {
}
let target = path.syntax().text_range();
- let scope = ImportScope::find_insert_use_container(path.syntax(), ctx)?;
+ let scope = ImportScope::find_insert_use_container(path.syntax(), &ctx.sema)?;
let syntax = scope.as_syntax_node();
acc.add(
AssistId("replace_qualified_name_with_use", AssistKind::RefactorRewrite),
ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams},
};
-pub use insert_use::MergeBehaviour;
-pub(crate) use insert_use::{insert_use, ImportScope};
+pub use insert_use::{insert_use, ImportScope, MergeBehaviour};
pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
let mut segments = Vec::new();
}
};
- let mut res = imports_locator::find_imports(sema, current_crate, &self.get_search_query())
- .into_iter()
- .filter_map(filter)
- .filter_map(|candidate| {
- let item: hir::ItemInNs = candidate.either(Into::into, Into::into);
- if let Some(prefix_kind) = prefixed {
- self.module_with_name_to_import.find_use_path_prefixed(db, item, prefix_kind)
- } else {
- self.module_with_name_to_import.find_use_path(db, item)
- }
- .map(|path| (path, item))
- })
- .filter(|(use_path, _)| !use_path.segments.is_empty())
- .take(20)
- .collect::<Vec<_>>();
+ let mut res =
+ imports_locator::find_exact_imports(sema, current_crate, &self.get_search_query())
+ .filter_map(filter)
+ .filter_map(|candidate| {
+ let item: hir::ItemInNs = candidate.either(Into::into, Into::into);
+ if let Some(prefix_kind) = prefixed {
+ self.module_with_name_to_import.find_use_path_prefixed(
+ db,
+ item,
+ prefix_kind,
+ )
+ } else {
+ self.module_with_name_to_import.find_use_path(db, item)
+ }
+ .map(|path| (path, item))
+ })
+ .filter(|(use_path, _)| use_path.len() > 1)
+ .take(20)
+ .collect::<Vec<_>>();
res.sort_by_key(|(path, _)| path.clone());
res
}
//! Handle syntactic aspects of inserting a new `use`.
use std::{cmp::Ordering, iter::successors};
+use hir::Semantics;
+use ide_db::RootDatabase;
use itertools::{EitherOrBoth, Itertools};
use syntax::{
algo::SyntaxRewriter,
};
use test_utils::mark;
-#[derive(Debug)]
-pub(crate) enum ImportScope {
+#[derive(Debug, Clone)]
+pub enum ImportScope {
File(ast::SourceFile),
Module(ast::ItemList),
}
}
/// Determines the containing syntax node in which to insert a `use` statement affecting `position`.
- pub(crate) fn find_insert_use_container(
+ pub fn find_insert_use_container(
position: &SyntaxNode,
- ctx: &crate::assist_context::AssistContext,
+ sema: &Semantics<'_, RootDatabase>,
) -> Option<Self> {
- ctx.sema.ancestors_with_macros(position.clone()).find_map(Self::from)
+ sema.ancestors_with_macros(position.clone()).find_map(Self::from)
}
- pub(crate) fn as_syntax_node(&self) -> &SyntaxNode {
+ pub fn as_syntax_node(&self) -> &SyntaxNode {
match self {
ImportScope::File(file) => file.syntax(),
ImportScope::Module(item_list) => item_list.syntax(),
}
/// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur.
-pub(crate) fn insert_use<'a>(
+pub fn insert_use<'a>(
scope: &ImportScope,
path: ast::Path,
merge: Option<MergeBehaviour>,
self.enabled.insert(CfgAtom::KeyValue { key, value });
}
- pub fn append(&mut self, other: &CfgOptions) {
- for atom in &other.enabled {
- self.enabled.insert(atom.clone());
- }
- }
-
pub fn apply_diff(&mut self, diff: CfgDiff) {
for atom in diff.enable {
self.enabled.insert(atom);
itertools = "0.9.0"
log = "0.4.8"
rustc-hash = "1.1.0"
+either = "1.6.1"
assists = { path = "../assists", version = "0.0.0" }
stdx = { path = "../stdx", version = "0.0.0" }
Some(it) => it,
None => return,
};
- if let Some(item) = render_macro(RenderContext::new(ctx), name, macro_) {
+ if let Some(item) = render_macro(RenderContext::new(ctx), None, name, macro_) {
self.add(item);
}
}
func: hir::Function,
local_name: Option<String>,
) {
- let item = render_fn(RenderContext::new(ctx), local_name, func);
+ let item = render_fn(RenderContext::new(ctx), None, local_name, func);
self.add(item)
}
variant: hir::EnumVariant,
path: ModPath,
) {
- let item = render_enum_variant(RenderContext::new(ctx), None, variant, Some(path));
+ let item = render_enum_variant(RenderContext::new(ctx), None, None, variant, Some(path));
self.add(item);
}
variant: hir::EnumVariant,
local_name: Option<String>,
) {
- let item = render_enum_variant(RenderContext::new(ctx), local_name, variant, None);
+ let item = render_enum_variant(RenderContext::new(ctx), None, local_name, variant, None);
self.add(item);
}
}
//! Completion of names from the current scope, e.g. locals and imported items.
+use assists::utils::ImportScope;
+use either::Either;
use hir::{Adt, ModuleDef, ScopeDef, Type};
+use ide_db::imports_locator;
use syntax::AstNode;
use test_utils::mark;
-use crate::{CompletionContext, Completions};
+use crate::{
+ render::{render_resolution_with_import, RenderContext},
+ CompletionContext, Completions,
+};
pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
if !(ctx.is_trivial_path || ctx.is_pat_binding_or_const) {
}
acc.add_resolution(ctx, name.to_string(), &res)
});
+
+ fuzzy_completion(acc, ctx).unwrap_or_default()
}
fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) {
}
}
+fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
+ let _p = profile::span("fuzzy_completion");
+ let current_module = ctx.scope.module()?;
+ let anchor = ctx.name_ref_syntax.as_ref()?;
+ let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?;
+
+ let potential_import_name = ctx.token.to_string();
+
+ let possible_imports =
+ imports_locator::find_similar_imports(&ctx.sema, ctx.krate?, &potential_import_name, 400)
+ .filter_map(|import_candidate| match import_candidate {
+ // when completing outside the use declaration, modules are pretty useless
+ // and tend to bloat the completion suggestions a lot
+ Either::Left(ModuleDef::Module(_)) => None,
+ Either::Left(module_def) => Some((
+ current_module.find_use_path(ctx.db, module_def)?,
+ ScopeDef::ModuleDef(module_def),
+ )),
+ Either::Right(macro_def) => Some((
+ current_module.find_use_path(ctx.db, macro_def)?,
+ ScopeDef::MacroDef(macro_def),
+ )),
+ })
+ .filter(|(mod_path, _)| mod_path.len() > 1)
+ .filter_map(|(import_path, definition)| {
+ render_resolution_with_import(
+ RenderContext::new(ctx),
+ import_path.clone(),
+ import_scope.clone(),
+ ctx.config.merge,
+ &definition,
+ )
+ })
+ .take(20);
+
+ acc.add_all(possible_imports);
+ Some(())
+}
+
#[cfg(test)]
mod tests {
use expect_test::{expect, Expect};
"#]],
)
}
+
+ #[test]
+ fn function_fuzzy_completion() {
+ check_edit(
+ "stdin",
+ r#"
+//- /lib.rs crate:dep
+pub mod io {
+ pub fn stdin() {}
+};
+
+//- /main.rs crate:main deps:dep
+fn main() {
+ stdi<|>
+}
+"#,
+ r#"
+use dep::io::stdin;
+
+fn main() {
+ stdin()$0
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn macro_fuzzy_completion() {
+ check_edit(
+ "macro_with_curlies!",
+ r#"
+//- /lib.rs crate:dep
+/// Please call me as macro_with_curlies! {}
+#[macro_export]
+macro_rules! macro_with_curlies {
+ () => {}
+}
+
+//- /main.rs crate:main deps:dep
+fn main() {
+ curli<|>
+}
+"#,
+ r#"
+use dep::macro_with_curlies;
+
+fn main() {
+ macro_with_curlies! {$0}
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn struct_fuzzy_completion() {
+ check_edit(
+ "ThirdStruct",
+ r#"
+//- /lib.rs crate:dep
+pub struct FirstStruct;
+pub mod some_module {
+ pub struct SecondStruct;
+ pub struct ThirdStruct;
+}
+
+//- /main.rs crate:main deps:dep
+use dep::{FirstStruct, some_module::SecondStruct};
+
+fn main() {
+ this<|>
+}
+"#,
+ r#"
+use dep::{FirstStruct, some_module::{SecondStruct, ThirdStruct}};
+
+fn main() {
+ ThirdStruct
+}
+"#,
+ );
+ }
}
//! module, and we use to statically check that we only produce snippet
//! completions if we are allowed to.
+use assists::utils::MergeBehaviour;
+
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CompletionConfig {
pub enable_postfix_completions: bool,
pub add_call_parenthesis: bool,
pub add_call_argument_snippets: bool,
pub snippet_cap: Option<SnippetCap>,
+ pub merge: Option<MergeBehaviour>,
}
impl CompletionConfig {
add_call_parenthesis: true,
add_call_argument_snippets: true,
snippet_cap: Some(SnippetCap { _private: () }),
+ merge: Some(MergeBehaviour::Full),
}
}
}
use std::fmt;
-use hir::{Documentation, Mutability};
-use syntax::TextRange;
+use assists::utils::{insert_use, mod_path_to_ast, ImportScope, MergeBehaviour};
+use hir::{Documentation, ModPath, Mutability};
+use syntax::{algo, TextRange};
use text_edit::TextEdit;
use crate::config::SnippetCap;
///
/// Typically, replaces `source_range` with new identifier.
text_edit: TextEdit,
+
insert_text_format: InsertTextFormat,
/// What item (struct, function, etc) are we completing.
trigger_call_info: None,
score: None,
ref_match: None,
+ import_data: None,
}
}
+
/// What user sees in pop-up in the UI.
pub fn label(&self) -> &str {
&self.label
pub(crate) struct Builder {
source_range: TextRange,
completion_kind: CompletionKind,
+ import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
label: String,
insert_text: Option<String>,
insert_text_format: InsertTextFormat,
impl Builder {
pub(crate) fn build(self) -> CompletionItem {
- let label = self.label;
- let text_edit = match self.text_edit {
+ let mut label = self.label;
+ let mut lookup = self.lookup;
+ let mut insert_text = self.insert_text;
+ let mut text_edits = TextEdit::builder();
+
+ if let Some((import_path, import_scope, merge_behaviour)) = self.import_data {
+ let import = mod_path_to_ast(&import_path);
+ let mut import_path_without_last_segment = import_path;
+ let _ = import_path_without_last_segment.segments.pop();
+
+ if !import_path_without_last_segment.segments.is_empty() {
+ if lookup.is_none() {
+ lookup = Some(label.clone());
+ }
+ if insert_text.is_none() {
+ insert_text = Some(label.clone());
+ }
+ label = format!("{}::{}", import_path_without_last_segment, label);
+ }
+
+ let rewriter = insert_use(&import_scope, import, merge_behaviour);
+ if let Some(old_ast) = rewriter.rewrite_root() {
+ algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut text_edits);
+ }
+ }
+
+ let original_edit = match self.text_edit {
Some(it) => it,
- None => TextEdit::replace(
- self.source_range,
- self.insert_text.unwrap_or_else(|| label.clone()),
- ),
+ None => {
+ TextEdit::replace(self.source_range, insert_text.unwrap_or_else(|| label.clone()))
+ }
};
+ let mut resulting_edit = text_edits.finish();
+ resulting_edit.union(original_edit).expect("Failed to unite text edits");
+
CompletionItem {
source_range: self.source_range,
label,
insert_text_format: self.insert_text_format,
- text_edit,
+ text_edit: resulting_edit,
detail: self.detail,
documentation: self.documentation,
- lookup: self.lookup,
+ lookup,
kind: self.kind,
completion_kind: self.completion_kind,
deprecated: self.deprecated.unwrap_or(false),
self.trigger_call_info = Some(true);
self
}
+ pub(crate) fn import_data(
+ mut self,
+ import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
+ ) -> Builder {
+ self.import_data = import_data;
+ self
+ }
pub(crate) fn set_ref_match(
mut self,
ref_match: Option<(Mutability, CompletionScore)>,
mod builder_ext;
-use hir::{Documentation, HasAttrs, HirDisplay, Mutability, ScopeDef, Type};
+use assists::utils::{ImportScope, MergeBehaviour};
+use hir::{Documentation, HasAttrs, HirDisplay, ModPath, Mutability, ScopeDef, Type};
use ide_db::RootDatabase;
use syntax::TextRange;
use test_utils::mark;
local_name: String,
resolution: &ScopeDef,
) -> Option<CompletionItem> {
- Render::new(ctx).render_resolution(local_name, resolution)
+ Render::new(ctx).render_resolution(local_name, None, resolution)
+}
+
+pub(crate) fn render_resolution_with_import<'a>(
+ ctx: RenderContext<'a>,
+ import: ModPath,
+ import_scope: ImportScope,
+ merge_behaviour: Option<MergeBehaviour>,
+ resolution: &ScopeDef,
+) -> Option<CompletionItem> {
+ let local_name = import.segments.last()?.to_string();
+ Render::new(ctx).render_resolution(
+ local_name,
+ Some((import, import_scope, merge_behaviour)),
+ resolution,
+ )
}
/// Interface for data and methods required for items rendering.
fn render_resolution(
self,
local_name: String,
+ import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
resolution: &ScopeDef,
) -> Option<CompletionItem> {
use hir::ModuleDef::*;
let kind = match resolution {
ScopeDef::ModuleDef(Function(func)) => {
- let item = render_fn(self.ctx, Some(local_name), *func);
+ let item = render_fn(self.ctx, import_data, Some(local_name), *func);
return Some(item);
}
ScopeDef::ModuleDef(EnumVariant(var)) => {
- let item = render_enum_variant(self.ctx, Some(local_name), *var, None);
+ let item = render_enum_variant(self.ctx, import_data, Some(local_name), *var, None);
return Some(item);
}
ScopeDef::MacroDef(mac) => {
- let item = render_macro(self.ctx, local_name, *mac);
+ let item = render_macro(self.ctx, import_data, local_name, *mac);
return item;
}
local_name,
)
.kind(CompletionItemKind::UnresolvedReference)
+ .import_data(import_data)
.build();
return Some(item);
}
}
}
- let item = item.kind(kind).set_documentation(docs).set_ref_match(ref_match).build();
+ let item = item
+ .kind(kind)
+ .import_data(import_data)
+ .set_documentation(docs)
+ .set_ref_match(ref_match)
+ .build();
Some(item)
}
insert: "m",
kind: Module,
},
+ CompletionItem {
+ label: "m::Spam",
+ source_range: 75..76,
+ text_edit: TextEdit {
+ indels: [
+ Indel {
+ insert: "use m::Spam;",
+ delete: 0..0,
+ },
+ Indel {
+ insert: "\n\n",
+ delete: 0..0,
+ },
+ Indel {
+ insert: "Spam",
+ delete: 75..76,
+ },
+ ],
+ },
+ kind: Enum,
+ lookup: "Spam",
+ },
CompletionItem {
label: "m::Spam::Foo",
source_range: 75..76,
//! Renderer for `enum` variants.
+use assists::utils::{ImportScope, MergeBehaviour};
use hir::{HasAttrs, HirDisplay, ModPath, StructKind};
use itertools::Itertools;
use test_utils::mark;
pub(crate) fn render_enum_variant<'a>(
ctx: RenderContext<'a>,
+ import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
local_name: Option<String>,
variant: hir::EnumVariant,
path: Option<ModPath>,
) -> CompletionItem {
- EnumVariantRender::new(ctx, local_name, variant, path).render()
+ EnumVariantRender::new(ctx, local_name, variant, path).render(import_data)
}
#[derive(Debug)]
}
}
- fn render(self) -> CompletionItem {
+ fn render(
+ self,
+ import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
+ ) -> CompletionItem {
let mut builder = CompletionItem::new(
CompletionKind::Reference,
self.ctx.source_range(),
.kind(CompletionItemKind::EnumVariant)
.set_documentation(self.variant.docs(self.ctx.db()))
.set_deprecated(self.ctx.is_deprecated(self.variant))
+ .import_data(import_data)
.detail(self.detail());
if self.variant_kind == StructKind::Tuple {
//! Renderer for function calls.
-use hir::{HasSource, Type};
+use assists::utils::{ImportScope, MergeBehaviour};
+use hir::{HasSource, ModPath, Type};
use syntax::{ast::Fn, display::function_declaration};
use crate::{
pub(crate) fn render_fn<'a>(
ctx: RenderContext<'a>,
+ import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
local_name: Option<String>,
fn_: hir::Function,
) -> CompletionItem {
- FunctionRender::new(ctx, local_name, fn_).render()
+ FunctionRender::new(ctx, local_name, fn_).render(import_data)
}
#[derive(Debug)]
FunctionRender { ctx, name, fn_, ast_node }
}
- fn render(self) -> CompletionItem {
+ fn render(
+ self,
+ import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
+ ) -> CompletionItem {
let params = self.params();
CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), self.name.clone())
.kind(self.kind())
.set_deprecated(self.ctx.is_deprecated(self.fn_))
.detail(self.detail())
.add_call_parens(self.ctx.completion, self.name, params)
+ .import_data(import_data)
.build()
}
//! Renderer for macro invocations.
-use hir::{Documentation, HasSource};
+use assists::utils::{ImportScope, MergeBehaviour};
+use hir::{Documentation, HasSource, ModPath};
use syntax::display::macro_label;
use test_utils::mark;
pub(crate) fn render_macro<'a>(
ctx: RenderContext<'a>,
+ import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
name: String,
macro_: hir::MacroDef,
) -> Option<CompletionItem> {
- MacroRender::new(ctx, name, macro_).render()
+ MacroRender::new(ctx, name, macro_).render(import_data)
}
#[derive(Debug)]
MacroRender { ctx, name, macro_, docs, bra, ket }
}
- fn render(&self) -> Option<CompletionItem> {
+ fn render(
+ &self,
+ import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
+ ) -> Option<CompletionItem> {
// FIXME: Currently proc-macro do not have ast-node,
// such that it does not have source
if self.macro_.is_proc_macro() {
.kind(CompletionItemKind::Macro)
.set_documentation(self.docs.clone())
.set_deprecated(self.ctx.is_deprecated(self.macro_))
+ .import_data(import_data)
.detail(self.detail());
let needs_bang = self.needs_bang();
pub fn query_external_importables(
self,
db: &dyn DefDatabase,
- query: &str,
+ query: import_map::Query,
) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
- import_map::search_dependencies(
- db,
- self.into(),
- import_map::Query::new(query).anchor_end().case_sensitive().limit(40),
- )
- .into_iter()
- .map(|item| match item {
+ import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| match item {
ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()),
ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()),
})
//! FIXME: write short doc here
pub use hir_def::diagnostics::{InactiveCode, UnresolvedModule};
-pub use hir_expand::diagnostics::{Diagnostic, DiagnosticSink, DiagnosticSinkBuilder};
+pub use hir_expand::diagnostics::{
+ Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder,
+};
pub use hir_ty::diagnostics::{
IncorrectCase, MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr,
NoSuchField,
builtin_type::BuiltinType,
docs::Documentation,
find_path::PrefixKind,
+ import_map,
item_scope::ItemInNs,
nameres::ModuleSource,
path::{ModPath, PathKind},
use crate::InFile;
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq)]
pub struct DiagnosticCode(pub &'static str);
impl DiagnosticCode {
use std::cell::RefCell;
use hir::{
- diagnostics::{Diagnostic as _, DiagnosticSinkBuilder},
+ diagnostics::{Diagnostic as _, DiagnosticCode, DiagnosticSinkBuilder},
Semantics,
};
use ide_db::base_db::SourceDatabase;
pub severity: Severity,
pub fix: Option<Fix>,
pub unused: bool,
+ pub code: Option<DiagnosticCode>,
}
impl Diagnostic {
fn error(range: TextRange, message: String) -> Self {
- Self { message, range, severity: Severity::Error, fix: None, unused: false }
+ Self { message, range, severity: Severity::Error, fix: None, unused: false, code: None }
}
fn hint(range: TextRange, message: String) -> Self {
- Self { message, range, severity: Severity::WeakWarning, fix: None, unused: false }
+ Self {
+ message,
+ range,
+ severity: Severity::WeakWarning,
+ fix: None,
+ unused: false,
+ code: None,
+ }
}
fn with_fix(self, fix: Option<Fix>) -> Self {
fn with_unused(self, unused: bool) -> Self {
Self { unused, ..self }
}
+
+ fn with_code(self, code: Option<DiagnosticCode>) -> Self {
+ Self { code, ..self }
+ }
}
#[derive(Debug)]
// Override severity and mark as unused.
res.borrow_mut().push(
Diagnostic::hint(sema.diagnostics_display_range(d).range, d.message())
- .with_unused(true),
+ .with_unused(true)
+ .with_code(Some(d.code())),
);
})
// Only collect experimental diagnostics when they're enabled.
let mut sink = sink_builder
// Diagnostics not handled above get no fix and default treatment.
.build(|d| {
- res.borrow_mut()
- .push(Diagnostic::error(sema.diagnostics_display_range(d).range, d.message()));
+ res.borrow_mut().push(
+ Diagnostic::error(sema.diagnostics_display_range(d).range, d.message())
+ .with_code(Some(d.code())),
+ );
});
if let Some(m) = sema.to_module_def(file_id) {
}
fn diagnostic_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic {
- Diagnostic::error(sema.diagnostics_display_range(d).range, d.message()).with_fix(d.fix(&sema))
+ Diagnostic::error(sema.diagnostics_display_range(d).range, d.message())
+ .with_fix(d.fix(&sema))
+ .with_code(Some(d.code()))
}
fn warning_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic {
- Diagnostic::hint(sema.diagnostics_display_range(d).range, d.message()).with_fix(d.fix(&sema))
+ Diagnostic::hint(sema.diagnostics_display_range(d).range, d.message())
+ .with_fix(d.fix(&sema))
+ .with_code(Some(d.code()))
}
fn check_unnecessary_braces_in_use_statement(
},
),
unused: false,
+ code: Some(
+ DiagnosticCode(
+ "unresolved-module",
+ ),
+ ),
},
]
"#]],
//! This module contains an import search funcionality that is provided to the assists module.
//! Later, this should be moved away to a separate crate that is accessible from the assists module.
-use hir::{Crate, MacroDef, ModuleDef, Semantics};
+use hir::{import_map, Crate, MacroDef, ModuleDef, Semantics};
use syntax::{ast, AstNode, SyntaxKind::NAME};
use crate::{
defs::{Definition, NameClass},
- symbol_index::{self, FileSymbol, Query},
+ symbol_index::{self, FileSymbol},
RootDatabase,
};
use either::Either;
use rustc_hash::FxHashSet;
-pub fn find_imports<'a>(
+pub fn find_exact_imports<'a>(
sema: &Semantics<'a, RootDatabase>,
krate: Crate,
name_to_import: &str,
-) -> Vec<Either<ModuleDef, MacroDef>> {
- let _p = profile::span("search_for_imports");
+) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
+ let _p = profile::span("find_exact_imports");
+ find_imports(
+ sema,
+ krate,
+ {
+ let mut local_query = symbol_index::Query::new(name_to_import.to_string());
+ local_query.exact();
+ local_query.limit(40);
+ local_query
+ },
+ import_map::Query::new(name_to_import).anchor_end().case_sensitive().limit(40),
+ )
+}
+
+pub fn find_similar_imports<'a>(
+ sema: &Semantics<'a, RootDatabase>,
+ krate: Crate,
+ name_to_import: &str,
+ limit: usize,
+) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
+ let _p = profile::span("find_similar_imports");
+ find_imports(
+ sema,
+ krate,
+ {
+ let mut local_query = symbol_index::Query::new(name_to_import.to_string());
+ local_query.limit(limit);
+ local_query
+ },
+ import_map::Query::new(name_to_import).limit(limit),
+ )
+}
+
+fn find_imports<'a>(
+ sema: &Semantics<'a, RootDatabase>,
+ krate: Crate,
+ local_query: symbol_index::Query,
+ external_query: import_map::Query,
+) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
+ let _p = profile::span("find_similar_imports");
let db = sema.db;
// Query dependencies first.
let mut candidates: FxHashSet<_> =
- krate.query_external_importables(db, name_to_import).collect();
+ krate.query_external_importables(db, external_query).collect();
// Query the local crate using the symbol index.
- let local_results = {
- let mut query = Query::new(name_to_import.to_string());
- query.exact();
- query.limit(40);
- symbol_index::crate_symbols(db, krate.into(), query)
- };
+ let local_results = symbol_index::crate_symbols(db, krate.into(), local_query);
candidates.extend(
local_results
}),
);
- candidates.into_iter().collect()
+ candidates.into_iter()
}
fn get_name_definition<'a>(
proc_macro_client: &ProcMacroClient,
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
) -> CrateGraph {
- let mut crate_graph = CrateGraph::default();
- match self {
+ let mut crate_graph = match self {
ProjectWorkspace::Json { project, sysroot } => {
- let sysroot_dps = sysroot
- .as_ref()
- .map(|sysroot| sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load));
-
- let mut cfg_cache: FxHashMap<Option<&str>, Vec<CfgFlag>> = FxHashMap::default();
- let crates: FxHashMap<_, _> = project
- .crates()
- .filter_map(|(crate_id, krate)| {
- let file_path = &krate.root_module;
- let file_id = match load(&file_path) {
- Some(id) => id,
- None => {
- log::error!("failed to load crate root {}", file_path.display());
- return None;
- }
- };
-
- let env = krate.env.clone().into_iter().collect();
- let proc_macro = krate
- .proc_macro_dylib_path
- .clone()
- .map(|it| proc_macro_client.by_dylib_path(&it));
-
- let target = krate.target.as_deref().or(target);
- let target_cfgs = cfg_cache
- .entry(target)
- .or_insert_with(|| get_rustc_cfg_options(target));
-
- let mut cfg_options = CfgOptions::default();
- cfg_options.extend(target_cfgs.iter().chain(krate.cfg.iter()).cloned());
-
- Some((
- crate_id,
- crate_graph.add_crate_root(
- file_id,
- krate.edition,
- krate.display_name.clone(),
- cfg_options,
- env,
- proc_macro.unwrap_or_default(),
- ),
- ))
- })
- .collect();
-
- for (from, krate) in project.crates() {
- if let Some(&from) = crates.get(&from) {
- if let Some((public_deps, _proc_macro)) = &sysroot_dps {
- for (name, to) in public_deps.iter() {
- add_dep(&mut crate_graph, from, name.clone(), *to)
- }
- }
-
- for dep in &krate.deps {
- let to_crate_id = dep.crate_id;
- if let Some(&to) = crates.get(&to_crate_id) {
- add_dep(&mut crate_graph, from, dep.name.clone(), to)
- }
- }
- }
- }
+ project_json_to_crate_graph(target, proc_macro_client, load, project, sysroot)
}
ProjectWorkspace::Cargo { cargo, sysroot, rustc } => {
- let (public_deps, libproc_macro) =
- sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load);
+ cargo_to_crate_graph(target, proc_macro_client, load, cargo, sysroot, rustc)
+ }
+ };
+ if crate_graph.patch_cfg_if() {
+ log::debug!("Patched std to depend on cfg-if")
+ } else {
+ log::debug!("Did not patch std to depend on cfg-if")
+ }
+ crate_graph
+ }
+}
- let mut cfg_options = CfgOptions::default();
- cfg_options.extend(get_rustc_cfg_options(target));
+fn project_json_to_crate_graph(
+ target: Option<&str>,
+ proc_macro_client: &ProcMacroClient,
+ load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
+ project: &ProjectJson,
+ sysroot: &Option<Sysroot>,
+) -> CrateGraph {
+ let mut crate_graph = CrateGraph::default();
+ let sysroot_deps = sysroot
+ .as_ref()
+ .map(|sysroot| sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load));
+
+ let mut cfg_cache: FxHashMap<Option<&str>, Vec<CfgFlag>> = FxHashMap::default();
+ let crates: FxHashMap<CrateId, CrateId> = project
+ .crates()
+ .filter_map(|(crate_id, krate)| {
+ let file_path = &krate.root_module;
+ let file_id = load(&file_path)?;
+ Some((crate_id, krate, file_id))
+ })
+ .map(|(crate_id, krate, file_id)| {
+ let env = krate.env.clone().into_iter().collect();
+ let proc_macro =
+ krate.proc_macro_dylib_path.clone().map(|it| proc_macro_client.by_dylib_path(&it));
+
+ let target = krate.target.as_deref().or(target);
+ let target_cfgs =
+ cfg_cache.entry(target).or_insert_with(|| get_rustc_cfg_options(target));
+
+ let mut cfg_options = CfgOptions::default();
+ cfg_options.extend(target_cfgs.iter().chain(krate.cfg.iter()).cloned());
+ (
+ crate_id,
+ crate_graph.add_crate_root(
+ file_id,
+ krate.edition,
+ krate.display_name.clone(),
+ cfg_options,
+ env,
+ proc_macro.unwrap_or_default(),
+ ),
+ )
+ })
+ .collect();
- let mut pkg_to_lib_crate = FxHashMap::default();
+ for (from, krate) in project.crates() {
+ if let Some(&from) = crates.get(&from) {
+ if let Some((public_deps, _proc_macro)) = &sysroot_deps {
+ for (name, to) in public_deps.iter() {
+ add_dep(&mut crate_graph, from, name.clone(), *to)
+ }
+ }
+
+ for dep in &krate.deps {
+ if let Some(&to) = crates.get(&dep.crate_id) {
+ add_dep(&mut crate_graph, from, dep.name.clone(), to)
+ }
+ }
+ }
+ }
+ crate_graph
+}
- // Add test cfg for non-sysroot crates
- cfg_options.insert_atom("test".into());
- cfg_options.insert_atom("debug_assertions".into());
+fn cargo_to_crate_graph(
+ target: Option<&str>,
+ proc_macro_client: &ProcMacroClient,
+ load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
+ cargo: &CargoWorkspace,
+ sysroot: &Sysroot,
+ rustc: &Option<CargoWorkspace>,
+) -> CrateGraph {
+ let mut crate_graph = CrateGraph::default();
+ let (public_deps, libproc_macro) =
+ sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load);
- let mut pkg_crates = FxHashMap::default();
+ let mut cfg_options = CfgOptions::default();
+ cfg_options.extend(get_rustc_cfg_options(target));
- // Next, create crates for each package, target pair
- for pkg in cargo.packages() {
- let mut lib_tgt = None;
- for &tgt in cargo[pkg].targets.iter() {
- if let Some(crate_id) = add_target_crate_root(
+ let mut pkg_to_lib_crate = FxHashMap::default();
+
+ // Add test cfg for non-sysroot crates
+ cfg_options.insert_atom("test".into());
+ cfg_options.insert_atom("debug_assertions".into());
+
+ let mut pkg_crates = FxHashMap::default();
+
+ // Next, create crates for each package, target pair
+ for pkg in cargo.packages() {
+ let mut lib_tgt = None;
+ for &tgt in cargo[pkg].targets.iter() {
+ if let Some(file_id) = load(&cargo[tgt].root) {
+ let crate_id = add_target_crate_root(
+ &mut crate_graph,
+ &cargo[pkg],
+ &cfg_options,
+ proc_macro_client,
+ file_id,
+ );
+ if cargo[tgt].kind == TargetKind::Lib {
+ lib_tgt = Some((crate_id, cargo[tgt].name.clone()));
+ pkg_to_lib_crate.insert(pkg, crate_id);
+ }
+ if cargo[tgt].is_proc_macro {
+ if let Some(proc_macro) = libproc_macro {
+ add_dep(
&mut crate_graph,
- &cargo[pkg],
- &cargo[tgt],
- &cfg_options,
- proc_macro_client,
- load,
- ) {
- if cargo[tgt].kind == TargetKind::Lib {
- lib_tgt = Some((crate_id, cargo[tgt].name.clone()));
- pkg_to_lib_crate.insert(pkg, crate_id);
- }
- if cargo[tgt].is_proc_macro {
- if let Some(proc_macro) = libproc_macro {
- add_dep(
- &mut crate_graph,
- crate_id,
- CrateName::new("proc_macro").unwrap(),
- proc_macro,
- );
- }
- }
-
- pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
- }
+ crate_id,
+ CrateName::new("proc_macro").unwrap(),
+ proc_macro,
+ );
}
+ }
- // Set deps to the core, std and to the lib target of the current package
- for &from in pkg_crates.get(&pkg).into_iter().flatten() {
- if let Some((to, name)) = lib_tgt.clone() {
- // For root projects with dashes in their name,
- // cargo metadata does not do any normalization,
- // so we do it ourselves currently
- let name = CrateName::normalize_dashes(&name);
- if to != from {
- add_dep(&mut crate_graph, from, name, to);
- }
- }
- for (name, krate) in public_deps.iter() {
- add_dep(&mut crate_graph, from, name.clone(), *krate);
- }
- }
+ pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
+ }
+ }
+
+ // Set deps to the core, std and to the lib target of the current package
+ for &from in pkg_crates.get(&pkg).into_iter().flatten() {
+ if let Some((to, name)) = lib_tgt.clone() {
+ if to != from {
+ // For root projects with dashes in their name,
+ // cargo metadata does not do any normalization,
+ // so we do it ourselves currently
+ let name = CrateName::normalize_dashes(&name);
+ add_dep(&mut crate_graph, from, name, to);
}
+ }
+ for (name, krate) in public_deps.iter() {
+ add_dep(&mut crate_graph, from, name.clone(), *krate);
+ }
+ }
+ }
- // Now add a dep edge from all targets of upstream to the lib
- // target of downstream.
- for pkg in cargo.packages() {
- for dep in cargo[pkg].dependencies.iter() {
- let name = CrateName::new(&dep.name).unwrap();
- if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
- for &from in pkg_crates.get(&pkg).into_iter().flatten() {
- add_dep(&mut crate_graph, from, name.clone(), to)
- }
- }
- }
+ // Now add a dep edge from all targets of upstream to the lib
+ // target of downstream.
+ for pkg in cargo.packages() {
+ for dep in cargo[pkg].dependencies.iter() {
+ let name = CrateName::new(&dep.name).unwrap();
+ if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
+ for &from in pkg_crates.get(&pkg).into_iter().flatten() {
+ add_dep(&mut crate_graph, from, name.clone(), to)
+ }
+ }
+ }
+ }
+
+ let mut rustc_pkg_crates = FxHashMap::default();
+
+ // If the user provided a path to rustc sources, we add all the rustc_private crates
+ // and create dependencies on them for the crates in the current workspace
+ if let Some(rustc_workspace) = rustc {
+ for pkg in rustc_workspace.packages() {
+ for &tgt in rustc_workspace[pkg].targets.iter() {
+ if rustc_workspace[tgt].kind != TargetKind::Lib {
+ continue;
+ }
+ // Exclude alloc / core / std
+ if rustc_workspace[tgt]
+ .root
+ .components()
+ .any(|c| c == Component::Normal("library".as_ref()))
+ {
+ continue;
}
- let mut rustc_pkg_crates = FxHashMap::default();
-
- // If the user provided a path to rustc sources, we add all the rustc_private crates
- // and create dependencies on them for the crates in the current workspace
- if let Some(rustc_workspace) = rustc {
- for pkg in rustc_workspace.packages() {
- for &tgt in rustc_workspace[pkg].targets.iter() {
- if rustc_workspace[tgt].kind != TargetKind::Lib {
- continue;
- }
- // Exclude alloc / core / std
- if rustc_workspace[tgt]
- .root
- .components()
- .any(|c| c == Component::Normal("library".as_ref()))
- {
- continue;
- }
-
- if let Some(crate_id) = add_target_crate_root(
- &mut crate_graph,
- &rustc_workspace[pkg],
- &rustc_workspace[tgt],
- &cfg_options,
- proc_macro_client,
- load,
- ) {
- pkg_to_lib_crate.insert(pkg, crate_id);
- // Add dependencies on the core / std / alloc for rustc
- for (name, krate) in public_deps.iter() {
- add_dep(&mut crate_graph, crate_id, name.clone(), *krate);
- }
- rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
- }
- }
+ if let Some(file_id) = load(&rustc_workspace[tgt].root) {
+ let crate_id = add_target_crate_root(
+ &mut crate_graph,
+ &rustc_workspace[pkg],
+ &cfg_options,
+ proc_macro_client,
+ file_id,
+ );
+ pkg_to_lib_crate.insert(pkg, crate_id);
+ // Add dependencies on the core / std / alloc for rustc
+ for (name, krate) in public_deps.iter() {
+ add_dep(&mut crate_graph, crate_id, name.clone(), *krate);
}
- // Now add a dep edge from all targets of upstream to the lib
- // target of downstream.
- for pkg in rustc_workspace.packages() {
- for dep in rustc_workspace[pkg].dependencies.iter() {
- let name = CrateName::new(&dep.name).unwrap();
- if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
- for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() {
- add_dep(&mut crate_graph, from, name.clone(), to);
- }
- }
- }
+ rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
+ }
+ }
+ }
+ // Now add a dep edge from all targets of upstream to the lib
+ // target of downstream.
+ for pkg in rustc_workspace.packages() {
+ for dep in rustc_workspace[pkg].dependencies.iter() {
+ let name = CrateName::new(&dep.name).unwrap();
+ if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
+ for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() {
+ add_dep(&mut crate_graph, from, name.clone(), to);
}
+ }
+ }
+ }
- // Add dependencies for all the crates of the current workspace to rustc_private libraries
- for dep in rustc_workspace.packages() {
- let name = CrateName::normalize_dashes(&rustc_workspace[dep].name);
-
- if let Some(&to) = pkg_to_lib_crate.get(&dep) {
- for pkg in cargo.packages() {
- if !cargo[pkg].is_member {
- continue;
- }
- for &from in pkg_crates.get(&pkg).into_iter().flatten() {
- add_dep(&mut crate_graph, from, name.clone(), to);
- }
- }
- }
+ // Add dependencies for all the crates of the current workspace to rustc_private libraries
+ for dep in rustc_workspace.packages() {
+ let name = CrateName::normalize_dashes(&rustc_workspace[dep].name);
+
+ if let Some(&to) = pkg_to_lib_crate.get(&dep) {
+ for pkg in cargo.packages() {
+ if !cargo[pkg].is_member {
+ continue;
+ }
+ for &from in pkg_crates.get(&pkg).into_iter().flatten() {
+ add_dep(&mut crate_graph, from, name.clone(), to);
}
}
}
}
- if crate_graph.patch_cfg_if() {
- log::debug!("Patched std to depend on cfg-if")
- } else {
- log::debug!("Did not patch std to depend on cfg-if")
- }
- crate_graph
}
+ crate_graph
}
fn add_target_crate_root(
crate_graph: &mut CrateGraph,
pkg: &cargo_workspace::PackageData,
- tgt: &cargo_workspace::TargetData,
cfg_options: &CfgOptions,
proc_macro_client: &ProcMacroClient,
- load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
-) -> Option<CrateId> {
- let root = tgt.root.as_path();
- if let Some(file_id) = load(root) {
- let edition = pkg.edition;
- let cfg_options = {
- let mut opts = cfg_options.clone();
- for feature in pkg.features.iter() {
- opts.insert_key_value("feature".into(), feature.into());
- }
- opts.extend(pkg.cfgs.iter().cloned());
- opts
- };
- let mut env = Env::default();
- if let Some(out_dir) = &pkg.out_dir {
- // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!()
- if let Some(out_dir) = out_dir.to_str().map(|s| s.to_owned()) {
- env.set("OUT_DIR", out_dir);
- }
+ file_id: FileId,
+) -> CrateId {
+ let edition = pkg.edition;
+ let cfg_options = {
+ let mut opts = cfg_options.clone();
+ for feature in pkg.features.iter() {
+ opts.insert_key_value("feature".into(), feature.into());
+ }
+ opts.extend(pkg.cfgs.iter().cloned());
+ opts
+ };
+ let mut env = Env::default();
+ if let Some(out_dir) = &pkg.out_dir {
+ // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!()
+ if let Some(out_dir) = out_dir.to_str().map(|s| s.to_owned()) {
+ env.set("OUT_DIR", out_dir);
}
- let proc_macro = pkg
- .proc_macro_dylib_path
- .as_ref()
- .map(|it| proc_macro_client.by_dylib_path(&it))
- .unwrap_or_default();
-
- let display_name = CrateDisplayName::from_canonical_name(pkg.name.clone());
- let crate_id = crate_graph.add_crate_root(
- file_id,
- edition,
- Some(display_name),
- cfg_options,
- env,
- proc_macro.clone(),
- );
-
- return Some(crate_id);
}
- None
+ let proc_macro = pkg
+ .proc_macro_dylib_path
+ .as_ref()
+ .map(|it| proc_macro_client.by_dylib_path(&it))
+ .unwrap_or_default();
+
+ let display_name = CrateDisplayName::from_canonical_name(pkg.name.clone());
+ let crate_id = crate_graph.add_crate_root(
+ file_id,
+ edition,
+ Some(display_name),
+ cfg_options,
+ env,
+ proc_macro.clone(),
+ );
+
+ crate_id
}
+
fn sysroot_to_crate_graph(
crate_graph: &mut CrateGraph,
sysroot: &Sysroot,
max_length: data.inlayHints_maxLength,
};
- self.completion.enable_postfix_completions = data.completion_postfix_enable;
- self.completion.add_call_parenthesis = data.completion_addCallParenthesis;
- self.completion.add_call_argument_snippets = data.completion_addCallArgumentSnippets;
-
self.assist.insert_use.merge = match data.assist_importMergeBehaviour {
MergeBehaviourDef::None => None,
MergeBehaviourDef::Full => Some(MergeBehaviour::Full),
ImportPrefixDef::BySelf => PrefixKind::BySelf,
};
+ self.completion.enable_postfix_completions = data.completion_postfix_enable;
+ self.completion.add_call_parenthesis = data.completion_addCallParenthesis;
+ self.completion.add_call_argument_snippets = data.completion_addCallArgumentSnippets;
+ self.completion.merge = self.assist.insert_use.merge;
+
self.call_info_full = data.callInfo_full;
self.lens = LensConfig {
CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams,
CodeActionKind, CodeLens, Command, CompletionItem, Diagnostic, DiagnosticTag,
DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange, FoldingRangeParams,
- HoverContents, Location, Position, PrepareRenameResponse, Range, RenameParams,
+ HoverContents, Location, NumberOrString, Position, PrepareRenameResponse, Range, RenameParams,
SemanticTokensDeltaParams, SemanticTokensFullDeltaResult, SemanticTokensParams,
SemanticTokensRangeParams, SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation,
SymbolTag, TextDocumentIdentifier, Url, WorkspaceEdit,
.flat_map(|item| to_proto::completion_item(&line_index, line_endings, item))
.collect();
- let completion_list = lsp_types::CompletionList { is_incomplete: false, items };
+ let completion_list = lsp_types::CompletionList { is_incomplete: true, items };
Ok(Some(completion_list.into()))
}
.map(|d| Diagnostic {
range: to_proto::range(&line_index, d.range),
severity: Some(to_proto::diagnostic_severity(d.severity)),
- code: None,
+ code: d.code.map(|d| d.as_str().to_owned()).map(NumberOrString::String),
code_description: None,
source: Some("rust-analyzer".to_string()),
message: d.message,
let contents = loader.handle.load_sync(path);
vfs.set_file_contents(vfs_path.clone(), contents);
}
- vfs.file_id(&vfs_path)
+ let res = vfs.file_id(&vfs_path);
+ if res.is_none() {
+ log::error!("failed to load {}", path.display())
+ }
+ res
};
for ws in workspaces.iter() {
crate_graph.extend(ws.to_crate_graph(
"integrity": "sha512-1nG+6cuTtpzmXe7yYfO9GCkYlyV6Ai+jDnwidHiT2T7zhc+bJM+VTtc0T/CdTlDyTNTqIcCj0V1nD4TcVjJ7Ug=="
},
"vscode-languageclient": {
- "version": "7.0.0-next.12",
- "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0-next.12.tgz",
- "integrity": "sha512-OrzvOvhS5o26C0KctTJC7hkwh3avCwkVhllzy42AqwpIUZ3p2aVqkSG2uVxaeodq8ThBb3TLgtg50vxyWs6FEg==",
+ "version": "7.0.0-next.14",
+ "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0-next.14.tgz",
+ "integrity": "sha512-QUccfXK2F6AXXRFR8QJCaIz7N2BhJK6ok8E1aO8LHq2IBU33+5hTSJBXs7nEqrqZ/cY2VlDDbMWtMvCxz+/y1w==",
"requires": {
"semver": "^6.3.0",
- "vscode-languageserver-protocol": "3.16.0-next.10"
+ "vscode-languageserver-protocol": "3.16.0-next.11"
}
},
"vscode-languageserver-protocol": {
- "version": "3.16.0-next.10",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0-next.10.tgz",
- "integrity": "sha512-YRTctHUZvts0Z1xXKNYU0ha0o+Tlgtwr+6O8OmDquM086N8exiSKBMwMC+Ra1QtIE+1mfW43Wxsme2FnMkAS9A==",
+ "version": "3.16.0-next.11",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0-next.11.tgz",
+ "integrity": "sha512-31FmupmSmfznuMuGp7qN6h3d/hKUbexbvcwTvrUE/igqRlzFU542s8MtGICx1ERbVuDOLGp96W2Z92qbUbmBPA==",
"requires": {
"vscode-jsonrpc": "6.0.0-next.7",
- "vscode-languageserver-types": "3.16.0-next.4"
+ "vscode-languageserver-types": "3.16.0-next.5"
}
},
"vscode-languageserver-types": {
- "version": "3.16.0-next.4",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.4.tgz",
- "integrity": "sha512-NlKJyGcET/ZBCCLBYIPaGo2c37R03bPYeWXozUtnjyye7+9dhlbMSODyoG2INcQf8zFmB4qhm2UOJjgYEgPCNA=="
+ "version": "3.16.0-next.5",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.5.tgz",
+ "integrity": "sha512-lf8Y1XXMtF1r2oDDAmJe+drizNXkybSRXAQQk5dPy2rYJsY9SPXYNO074L3THu9zNYepzV5fRJZUPo/V/TLBRQ=="
},
"vscode-test": {
"version": "1.4.0",
"Programming Languages"
],
"engines": {
- "vscode": "^1.47.1"
+ "vscode": "^1.51.0"
},
"enableProposedApi": true,
"scripts": {
},
"dependencies": {
"node-fetch": "^2.6.1",
- "vscode-languageclient": "7.0.0-next.12"
+ "vscode-languageclient": "7.0.0-next.14"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^13.0.2",
}
initialize(_capabilities: lc.ServerCapabilities<any>, _documentSelector: lc.DocumentSelector | undefined): void {
}
+ dispose(): void {
+ }
}
function isCodeActionWithoutEditsAndCommands(value: any): boolean {
MIT
MIT / Apache-2.0
MIT OR Apache-2.0
+MIT OR Apache-2.0 OR Zlib
MIT OR Zlib OR Apache-2.0
MIT/Apache-2.0
Unlicense OR MIT