Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/ide-completion/src/completions.rs69
-rw-r--r--crates/ide-completion/src/completions/attribute.rs6
-rw-r--r--crates/ide-completion/src/completions/attribute/derive.rs8
-rw-r--r--crates/ide-completion/src/completions/dot.rs14
-rw-r--r--crates/ide-completion/src/completions/expr.rs59
-rw-r--r--crates/ide-completion/src/completions/flyimport.rs110
-rw-r--r--crates/ide-completion/src/completions/item_list.rs4
-rw-r--r--crates/ide-completion/src/completions/pattern.rs47
-rw-r--r--crates/ide-completion/src/completions/type.rs8
-rw-r--r--crates/ide-completion/src/completions/use_.rs6
-rw-r--r--crates/ide-completion/src/context.rs15
-rw-r--r--crates/ide-completion/src/context/analysis.rs95
-rw-r--r--crates/ide-completion/src/context/tests.rs2
-rw-r--r--crates/ide-completion/src/item.rs7
-rw-r--r--crates/ide-completion/src/lib.rs37
-rw-r--r--crates/ide-completion/src/render.rs97
-rw-r--r--crates/ide-completion/src/render/function.rs87
-rw-r--r--crates/ide-completion/src/render/literal.rs26
-rw-r--r--crates/ide-completion/src/render/macro_.rs22
-rw-r--r--crates/ide-completion/src/render/pattern.rs68
-rw-r--r--crates/ide-completion/src/tests/flyimport.rs10
21 files changed, 451 insertions, 346 deletions
diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index 3f9314bbb3..a0725198f7 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -23,13 +23,13 @@ pub(crate) mod vis;
use std::iter;
use hir::{known, ScopeDef};
-use ide_db::SymbolKind;
+use ide_db::{imports::import_assets::LocatedImport, SymbolKind};
use syntax::ast;
use crate::{
context::{
- ItemListKind, NameContext, NameKind, NameRefContext, NameRefKind, PathKind, PatternContext,
- TypeLocation, Visible,
+ DotAccess, ItemListKind, NameContext, NameKind, NameRefContext, NameRefKind,
+ PathCompletionCtx, PathKind, PatternContext, TypeLocation, Visible,
},
item::Builder,
render::{
@@ -38,7 +38,7 @@ use crate::{
literal::{render_struct_literal, render_variant_lit},
macro_::render_macro,
pattern::{render_struct_pat, render_variant_pat},
- render_field, render_resolution, render_resolution_simple, render_tuple_field,
+ render_field, render_path_resolution, render_resolution_simple, render_tuple_field,
type_alias::{render_type_alias, render_type_alias_with_eq},
union_literal::render_union_literal,
RenderContext,
@@ -137,15 +137,16 @@ impl Completions {
pub(crate) fn add_crate_roots(&mut self, ctx: &CompletionContext) {
ctx.process_all_names(&mut |name, res| match res {
ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) if m.is_crate_root(ctx.db) => {
- self.add_resolution(ctx, name, res);
+ self.add_module(ctx, m, name);
}
_ => (),
});
}
- pub(crate) fn add_resolution(
+ pub(crate) fn add_path_resolution(
&mut self,
ctx: &CompletionContext,
+ path_ctx: &PathCompletionCtx,
local_name: hir::Name,
resolution: hir::ScopeDef,
) {
@@ -153,7 +154,10 @@ impl Completions {
cov_mark::hit!(qualified_path_doc_hidden);
return;
}
- self.add(render_resolution(RenderContext::new(ctx), local_name, resolution).build());
+ self.add(
+ render_path_resolution(RenderContext::new(ctx), path_ctx, local_name, resolution)
+ .build(),
+ );
}
pub(crate) fn add_resolution_simple(
@@ -174,12 +178,13 @@ impl Completions {
module: hir::Module,
local_name: hir::Name,
) {
- self.add_resolution(ctx, local_name, hir::ScopeDef::ModuleDef(module.into()));
+ self.add_resolution_simple(ctx, local_name, hir::ScopeDef::ModuleDef(module.into()));
}
pub(crate) fn add_macro(
&mut self,
ctx: &CompletionContext,
+ path_ctx: &PathCompletionCtx,
mac: hir::Macro,
local_name: hir::Name,
) {
@@ -191,6 +196,7 @@ impl Completions {
self.add(
render_macro(
RenderContext::new(ctx).private_editable(is_private_editable),
+ path_ctx,
local_name,
mac,
)
@@ -201,6 +207,7 @@ impl Completions {
pub(crate) fn add_function(
&mut self,
ctx: &CompletionContext,
+ path_ctx: &PathCompletionCtx,
func: hir::Function,
local_name: Option<hir::Name>,
) {
@@ -212,6 +219,7 @@ impl Completions {
self.add(
render_fn(
RenderContext::new(ctx).private_editable(is_private_editable),
+ path_ctx,
local_name,
func,
)
@@ -222,6 +230,7 @@ impl Completions {
pub(crate) fn add_method(
&mut self,
ctx: &CompletionContext,
+ dot_access: &DotAccess,
func: hir::Function,
receiver: Option<hir::Name>,
local_name: Option<hir::Name>,
@@ -234,6 +243,7 @@ impl Completions {
self.add(
render_method(
RenderContext::new(ctx).private_editable(is_private_editable),
+ dot_access,
receiver,
local_name,
func,
@@ -242,6 +252,32 @@ impl Completions {
);
}
+ pub(crate) fn add_method_with_import(
+ &mut self,
+ ctx: &CompletionContext,
+ dot_access: &DotAccess,
+ func: hir::Function,
+ import: LocatedImport,
+ ) {
+ let is_private_editable = match ctx.is_visible(&func) {
+ Visible::Yes => false,
+ Visible::Editable => true,
+ Visible::No => return,
+ };
+ self.add(
+ render_method(
+ RenderContext::new(ctx)
+ .private_editable(is_private_editable)
+ .import_to_add(Some(import)),
+ dot_access,
+ None,
+ None,
+ func,
+ )
+ .build(),
+ );
+ }
+
pub(crate) fn add_const(&mut self, ctx: &CompletionContext, konst: hir::Const) {
let is_private_editable = match ctx.is_visible(&konst) {
Visible::Yes => false,
@@ -277,11 +313,12 @@ impl Completions {
pub(crate) fn add_qualified_enum_variant(
&mut self,
ctx: &CompletionContext,
+ path_ctx: &PathCompletionCtx,
variant: hir::Variant,
path: hir::ModPath,
) {
if let Some(builder) =
- render_variant_lit(RenderContext::new(ctx), None, variant, Some(path))
+ render_variant_lit(RenderContext::new(ctx), path_ctx, None, variant, Some(path))
{
self.add(builder.build());
}
@@ -290,11 +327,12 @@ impl Completions {
pub(crate) fn add_enum_variant(
&mut self,
ctx: &CompletionContext,
+ path_ctx: &PathCompletionCtx,
variant: hir::Variant,
local_name: Option<hir::Name>,
) {
if let Some(builder) =
- render_variant_lit(RenderContext::new(ctx), local_name, variant, None)
+ render_variant_lit(RenderContext::new(ctx), path_ctx, local_name, variant, None)
{
self.add(builder.build());
}
@@ -324,12 +362,13 @@ impl Completions {
pub(crate) fn add_struct_literal(
&mut self,
ctx: &CompletionContext,
+ path_ctx: &PathCompletionCtx,
strukt: hir::Struct,
path: Option<hir::ModPath>,
local_name: Option<hir::Name>,
) {
if let Some(builder) =
- render_struct_literal(RenderContext::new(ctx), strukt, path, local_name)
+ render_struct_literal(RenderContext::new(ctx), path_ctx, strukt, path, local_name)
{
self.add(builder.build());
}
@@ -369,11 +408,13 @@ impl Completions {
pub(crate) fn add_variant_pat(
&mut self,
ctx: &CompletionContext,
+ pattern_ctx: &PatternContext,
variant: hir::Variant,
local_name: Option<hir::Name>,
) {
self.add_opt(render_variant_pat(
RenderContext::new(ctx),
+ pattern_ctx,
variant,
local_name.clone(),
None,
@@ -383,20 +424,22 @@ impl Completions {
pub(crate) fn add_qualified_variant_pat(
&mut self,
ctx: &CompletionContext,
+ pattern_ctx: &PatternContext,
variant: hir::Variant,
path: hir::ModPath,
) {
let path = Some(&path);
- self.add_opt(render_variant_pat(RenderContext::new(ctx), variant, None, path));
+ self.add_opt(render_variant_pat(RenderContext::new(ctx), pattern_ctx, variant, None, path));
}
pub(crate) fn add_struct_pat(
&mut self,
ctx: &CompletionContext,
+ pattern_ctx: &PatternContext,
strukt: hir::Struct,
local_name: Option<hir::Name>,
) {
- self.add_opt(render_struct_pat(RenderContext::new(ctx), strukt, local_name));
+ self.add_opt(render_struct_pat(RenderContext::new(ctx), pattern_ctx, strukt, local_name));
}
}
diff --git a/crates/ide-completion/src/completions/attribute.rs b/crates/ide-completion/src/completions/attribute.rs
index 3115971c85..1c4f9a3113 100644
--- a/crates/ide-completion/src/completions/attribute.rs
+++ b/crates/ide-completion/src/completions/attribute.rs
@@ -74,7 +74,7 @@ pub(crate) fn complete_known_attribute_input(
pub(crate) fn complete_attribute_path(
acc: &mut Completions,
ctx: &CompletionContext,
- PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
+ path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
&AttrCtx { kind, annotated_item_kind }: &AttrCtx,
) {
let is_inner = kind == AttrKind::Inner;
@@ -92,7 +92,7 @@ pub(crate) fn complete_attribute_path(
for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
match def {
hir::ScopeDef::ModuleDef(hir::ModuleDef::Macro(m)) if m.is_attr(ctx.db) => {
- acc.add_macro(ctx, m, name)
+ acc.add_macro(ctx, path_ctx, m, name)
}
hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => {
acc.add_module(ctx, m, name)
@@ -108,7 +108,7 @@ pub(crate) fn complete_attribute_path(
Qualified::No => {
ctx.process_all_names(&mut |name, def| match def {
hir::ScopeDef::ModuleDef(hir::ModuleDef::Macro(m)) if m.is_attr(ctx.db) => {
- acc.add_macro(ctx, m, name)
+ acc.add_macro(ctx, path_ctx, m, name)
}
hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => acc.add_module(ctx, m, name),
_ => (),
diff --git a/crates/ide-completion/src/completions/attribute/derive.rs b/crates/ide-completion/src/completions/attribute/derive.rs
index 0e10f38153..21298b6ca5 100644
--- a/crates/ide-completion/src/completions/attribute/derive.rs
+++ b/crates/ide-completion/src/completions/attribute/derive.rs
@@ -13,7 +13,7 @@ use crate::{
pub(crate) fn complete_derive_path(
acc: &mut Completions,
ctx: &CompletionContext,
- PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
+ path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
existing_derives: &ExistingDerives,
) {
let core = ctx.famous_defs().core();
@@ -33,7 +33,7 @@ pub(crate) fn complete_derive_path(
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac))
if !existing_derives.contains(&mac) && mac.is_derive(ctx.db) =>
{
- acc.add_macro(ctx, mac, name)
+ acc.add_macro(ctx, path_ctx, mac, name)
}
ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => acc.add_module(ctx, m, name),
_ => (),
@@ -59,7 +59,7 @@ pub(crate) fn complete_derive_path(
match (core, mac.module(ctx.db).krate()) {
// show derive dependencies for `core`/`std` derives
(Some(core), mac_krate) if core == mac_krate => {}
- _ => return acc.add_macro(ctx, mac, name),
+ _ => return acc.add_macro(ctx, path_ctx, mac, name),
};
let name_ = name.to_smol_str();
@@ -92,7 +92,7 @@ pub(crate) fn complete_derive_path(
item.lookup_by(lookup);
item.add_to(acc);
}
- None => acc.add_macro(ctx, mac, name),
+ None => acc.add_macro(ctx, path_ctx, mac, name),
}
});
acc.add_nameref_keywords_with_colon(ctx);
diff --git a/crates/ide-completion/src/completions/dot.rs b/crates/ide-completion/src/completions/dot.rs
index a8a57c0c7d..b58a9f39f2 100644
--- a/crates/ide-completion/src/completions/dot.rs
+++ b/crates/ide-completion/src/completions/dot.rs
@@ -33,7 +33,7 @@ pub(crate) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext, dot_a
|acc, field, ty| acc.add_tuple_field(ctx, None, field, &ty),
);
}
- complete_methods(ctx, &receiver_ty, |func| acc.add_method(ctx, func, None, None));
+ complete_methods(ctx, &receiver_ty, |func| acc.add_method(ctx, dot_access, func, None, None));
}
pub(crate) fn complete_undotted_self(
@@ -68,7 +68,17 @@ pub(crate) fn complete_undotted_self(
|acc, field, ty| acc.add_tuple_field(ctx, Some(hir::known::SELF_PARAM), field, &ty),
);
complete_methods(ctx, &ty, |func| {
- acc.add_method(ctx, func, Some(hir::known::SELF_PARAM), None)
+ acc.add_method(
+ ctx,
+ &DotAccess {
+ receiver: None,
+ receiver_ty: None,
+ kind: DotAccessKind::Method { has_parens: false },
+ },
+ func,
+ Some(hir::known::SELF_PARAM),
+ None,
+ )
});
}
diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs
index 84ae596a8d..9c003be6af 100644
--- a/crates/ide-completion/src/completions/expr.rs
+++ b/crates/ide-completion/src/completions/expr.rs
@@ -11,7 +11,7 @@ use crate::{
pub(crate) fn complete_expr_path(
acc: &mut Completions,
ctx: &CompletionContext,
- PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
+ path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
&ExprCtx {
in_block_expr,
in_loop_body,
@@ -34,11 +34,12 @@ pub(crate) fn complete_expr_path(
ref_expr_parent.as_ref().map(|it| it.mut_token().is_none()).unwrap_or(false);
let scope_def_applicable = |def| {
- use hir::{GenericParam::*, ModuleDef::*};
match def {
- ScopeDef::GenericParam(LifetimeParam(_)) | ScopeDef::Label(_) => false,
+ ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_) => {
+ false
+ }
// Don't suggest attribute macros and derives.
- ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db),
+ ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => mac.is_fn_like(ctx.db),
_ => true,
}
};
@@ -49,7 +50,7 @@ pub(crate) fn complete_expr_path(
.0
.into_iter()
.flat_map(|it| hir::Trait::from(it).items(ctx.sema.db))
- .for_each(|item| add_assoc_item(acc, ctx, item)),
+ .for_each(|item| add_assoc_item(acc, ctx, path_ctx, item)),
Qualified::With { resolution: None, .. } => {}
Qualified::With { resolution: Some(resolution), .. } => {
// Add associated types on type parameters and `Self`.
@@ -62,7 +63,7 @@ pub(crate) fn complete_expr_path(
let module_scope = module.scope(ctx.db, Some(ctx.module));
for (name, def) in module_scope {
if scope_def_applicable(def) {
- acc.add_resolution(ctx, name, def);
+ acc.add_path_resolution(ctx, path_ctx, name, def);
}
}
}
@@ -73,7 +74,7 @@ pub(crate) fn complete_expr_path(
| hir::ModuleDef::BuiltinType(_)),
) => {
if let &hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def {
- add_enum_variants(acc, ctx, e);
+ add_enum_variants(acc, ctx, path_ctx, e);
}
let ty = match def {
hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
@@ -81,7 +82,7 @@ pub(crate) fn complete_expr_path(
let ty = a.ty(ctx.db);
if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
cov_mark::hit!(completes_variant_through_alias);
- add_enum_variants(acc, ctx, e);
+ add_enum_variants(acc, ctx, path_ctx, e);
}
ty
}
@@ -102,7 +103,7 @@ pub(crate) fn complete_expr_path(
Some(ctx.module),
None,
|item| {
- add_assoc_item(acc, ctx, item);
+ add_assoc_item(acc, ctx, path_ctx, item);
None::<()>
},
);
@@ -118,7 +119,7 @@ pub(crate) fn complete_expr_path(
hir::PathResolution::Def(hir::ModuleDef::Trait(t)) => {
// Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
for item in t.items(ctx.db) {
- add_assoc_item(acc, ctx, item);
+ add_assoc_item(acc, ctx, path_ctx, item);
}
}
hir::PathResolution::TypeParam(_) | hir::PathResolution::SelfType(_) => {
@@ -129,7 +130,7 @@ pub(crate) fn complete_expr_path(
};
if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
- add_enum_variants(acc, ctx, e);
+ add_enum_variants(acc, ctx, path_ctx, e);
}
let mut seen = FxHashSet::default();
ty.iterate_path_candidates(
@@ -142,7 +143,7 @@ pub(crate) fn complete_expr_path(
// We might iterate candidates of a trait multiple times here, so deduplicate
// them.
if seen.insert(item) {
- add_assoc_item(acc, ctx, item);
+ add_assoc_item(acc, ctx, path_ctx, item);
}
None::<()>
},
@@ -167,10 +168,16 @@ pub(crate) fn complete_expr_path(
.find_use_path(ctx.db, hir::ModuleDef::from(strukt))
.filter(|it| it.len() > 1);
- acc.add_struct_literal(ctx, strukt, path, None);
+ acc.add_struct_literal(ctx, path_ctx, strukt, path, None);
if complete_self {
- acc.add_struct_literal(ctx, strukt, None, Some(hir::known::SELF_TYPE));
+ acc.add_struct_literal(
+ ctx,
+ path_ctx,
+ strukt,
+ None,
+ Some(hir::known::SELF_TYPE),
+ );
}
}
hir::Adt::Union(un) => {
@@ -191,7 +198,7 @@ pub(crate) fn complete_expr_path(
e,
impl_,
|acc, ctx, variant, path| {
- acc.add_qualified_enum_variant(ctx, variant, path)
+ acc.add_qualified_enum_variant(ctx, path_ctx, variant, path)
},
);
}
@@ -199,7 +206,7 @@ pub(crate) fn complete_expr_path(
}
ctx.process_all_names(&mut |name, def| {
if scope_def_applicable(def) {
- acc.add_resolution(ctx, name, def);
+ acc.add_path_resolution(ctx, path_ctx, name, def);
}
});
@@ -259,14 +266,26 @@ pub(crate) fn complete_expr_path(
}
}
-fn add_assoc_item(acc: &mut Completions, ctx: &CompletionContext, item: hir::AssocItem) {
+fn add_assoc_item(
+ acc: &mut Completions,
+ ctx: &CompletionContext,
+ path_ctx: &PathCompletionCtx,
+ item: hir::AssocItem,
+) {
match item {
- hir::AssocItem::Function(func) => acc.add_function(ctx, func, None),
+ hir::AssocItem::Function(func) => acc.add_function(ctx, path_ctx, func, None),
hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
}
}
-fn add_enum_variants(acc: &mut Completions, ctx: &CompletionContext, e: hir::Enum) {
- e.variants(ctx.db).into_iter().for_each(|variant| acc.add_enum_variant(ctx, variant, None));
+fn add_enum_variants(
+ acc: &mut Completions,
+ ctx: &CompletionContext,
+ path_ctx: &PathCompletionCtx,
+ e: hir::Enum,
+) {
+ e.variants(ctx.db)
+ .into_iter()
+ .for_each(|variant| acc.add_enum_variant(ctx, path_ctx, variant, None));
}
diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs
index 608a74dc15..129910465c 100644
--- a/crates/ide-completion/src/completions/flyimport.rs
+++ b/crates/ide-completion/src/completions/flyimport.rs
@@ -116,17 +116,17 @@ pub(crate) fn import_on_the_fly_path(
if !ctx.config.enable_imports_on_the_fly {
return None;
}
- let (kind, qualified) = match path_ctx {
+ let qualified = match path_ctx {
PathCompletionCtx {
kind:
- kind @ (PathKind::Expr { .. }
+ PathKind::Expr { .. }
| PathKind::Type { .. }
| PathKind::Attr { .. }
| PathKind::Derive { .. }
- | PathKind::Pat { .. }),
+ | PathKind::Pat { .. },
qualified,
..
- } => (Some(kind), qualified),
+ } => qualified,
_ => return None,
};
let potential_import_name = import_name(ctx);
@@ -139,63 +139,70 @@ pub(crate) fn import_on_the_fly_path(
import_on_the_fly(
acc,
ctx,
- kind,
+ path_ctx,
import_assets,
qualifier.map(|it| it.syntax().clone()).or_else(|| ctx.original_token.parent())?,
potential_import_name,
)
}
-pub(crate) fn import_on_the_fly_dot(
+pub(crate) fn import_on_the_fly_pat(
acc: &mut Completions,
ctx: &CompletionContext,
- dot_access: &DotAccess,
+ pat_ctx: &PatternContext,
) -> Option<()> {
if !ctx.config.enable_imports_on_the_fly {
return None;
}
- let receiver = dot_access.receiver.as_ref()?;
- let ty = dot_access.receiver_ty.as_ref()?;
+ if let PatternContext { record_pat: Some(_), .. } = pat_ctx {
+ return None;
+ }
+
let potential_import_name = import_name(ctx);
- let import_assets = ImportAssets::for_fuzzy_method_call(
- ctx.module,
- ty.original.clone(),
- potential_import_name.clone(),
- receiver.syntax().clone(),
- )?;
+ let import_assets = import_assets_for_path(ctx, &potential_import_name, None)?;
import_on_the_fly(
acc,
ctx,
- None,
+ &PathCompletionCtx {
+ has_call_parens: false,
+ has_macro_bang: false,
+ qualified: Qualified::No,
+ parent: None,
+ kind: crate::context::PathKind::Pat { pat_ctx: pat_ctx.clone() },
+ has_type_args: false,
+ use_tree_parent: false,
+ },
import_assets,
- receiver.syntax().clone(),
+ ctx.original_token.parent()?,
potential_import_name,
)
}
-pub(crate) fn import_on_the_fly_pat(
+pub(crate) fn import_on_the_fly_dot(
acc: &mut Completions,
ctx: &CompletionContext,
- pat_ctx: &PatternContext,
+ dot_access: &DotAccess,
) -> Option<()> {
if !ctx.config.enable_imports_on_the_fly {
return None;
}
- let kind = match pat_ctx {
- PatternContext { record_pat: None, .. } => PathKind::Pat { pat_ctx: pat_ctx.clone() },
- _ => return None,
- };
-
+ let receiver = dot_access.receiver.as_ref()?;
+ let ty = dot_access.receiver_ty.as_ref()?;
let potential_import_name = import_name(ctx);
- let import_assets = import_assets_for_path(ctx, &potential_import_name, None)?;
+ let import_assets = ImportAssets::for_fuzzy_method_call(
+ ctx.module,
+ ty.original.clone(),
+ potential_import_name.clone(),
+ receiver.syntax().clone(),
+ )?;
- import_on_the_fly(
+ import_on_the_fly_method(
acc,
ctx,
- Some(&kind),
+ dot_access,
import_assets,
- ctx.original_token.parent()?,
+ receiver.syntax().clone(),
potential_import_name,
)
}
@@ -203,7 +210,7 @@ pub(crate) fn import_on_the_fly_pat(
fn import_on_the_fly(
acc: &mut Completions,
ctx: &CompletionContext,
- path_kind: Option<&PathKind>,
+ path_ctx @ PathCompletionCtx { kind, .. }: &PathCompletionCtx,
import_assets: ImportAssets,
position: SyntaxNode,
potential_import_name: String,
@@ -215,11 +222,7 @@ fn import_on_the_fly(
}
let ns_filter = |import: &LocatedImport| {
- let path_kind = match path_kind {
- Some(it) => it,
- None => return true,
- };
- match (path_kind, import.original_item) {
+ match (kind, import.original_item) {
// Aren't handled in flyimport
(PathKind::Vis { .. } | PathKind::Use, _) => false,
// modules are always fair game
@@ -276,12 +279,49 @@ fn import_on_the_fly(
&user_input_lowercased,
)
})
- .filter_map(|import| render_resolution_with_import(RenderContext::new(ctx), import))
+ .filter_map(|import| {
+ render_resolution_with_import(RenderContext::new(ctx), path_ctx, import)
+ })
.map(|builder| builder.build()),
);
Some(())
}
+fn import_on_the_fly_method(
+ acc: &mut Completions,
+ ctx: &CompletionContext,
+ dot_access: &DotAccess,
+ import_assets: ImportAssets,
+ position: SyntaxNode,
+ potential_import_name: String,
+) -> Option<()> {
+ let _p = profile::span("import_on_the_fly").detail(|| potential_import_name.clone());
+
+ if ImportScope::find_insert_use_container(&position, &ctx.sema).is_none() {
+ return None;
+ }
+
+ let user_input_lowercased = potential_import_name.to_lowercase();
+
+ import_assets
+ .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind)
+ .into_iter()
+ .filter(|import| {
+ !ctx.is_item_hidden(&import.item_to_import)
+ && !ctx.is_item_hidden(&import.original_item)
+ })
+ .sorted_by_key(|located_import| {
+ compute_fuzzy_completion_order_key(&located_import.import_path, &user_input_lowercased)
+ })
+ .for_each(|import| match import.original_item {
+ ItemInNs::Values(hir::ModuleDef::Function(f)) => {
+ acc.add_method_with_import(ctx, dot_access, f, import);
+ }
+ _ => (),
+ });
+ Some(())
+}
+
fn import_name(ctx: &CompletionContext) -> String {
let token_kind = ctx.token.kind();
if matches!(token_kind, T![.] | T![::]) {
diff --git a/crates/ide-completion/src/completions/item_list.rs b/crates/ide-completion/src/completions/item_list.rs
index e697e1971e..329d08a9e7 100644
--- a/crates/ide-completion/src/completions/item_list.rs
+++ b/crates/ide-completion/src/completions/item_list.rs
@@ -42,7 +42,7 @@ pub(crate) fn complete_item_list(
for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
match def {
hir::ScopeDef::ModuleDef(hir::ModuleDef::Macro(m)) if m.is_fn_like(ctx.db) => {
- acc.add_macro(ctx, m, name)
+ acc.add_macro(ctx, path_ctx, m, name)
}
hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => {
acc.add_module(ctx, m, name)
@@ -59,7 +59,7 @@ pub(crate) fn complete_item_list(
Qualified::No if ctx.qualifier_ctx.none() => {
ctx.process_all_names(&mut |name, def| match def {
hir::ScopeDef::ModuleDef(hir::ModuleDef::Macro(m)) if m.is_fn_like(ctx.db) => {
- acc.add_macro(ctx, m, name)
+ acc.add_macro(ctx, path_ctx, m, name)
}
hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => acc.add_module(ctx, m, name),
_ => (),
diff --git a/crates/ide-completion/src/completions/pattern.rs b/crates/ide-completion/src/completions/pattern.rs
index e2e8d3f205..91d5356541 100644
--- a/crates/ide-completion/src/completions/pattern.rs
+++ b/crates/ide-completion/src/completions/pattern.rs
@@ -13,9 +13,9 @@ use crate::{
pub(crate) fn complete_pattern(
acc: &mut Completions,
ctx: &CompletionContext,
- patctx: &PatternContext,
+ pattern_ctx: &PatternContext,
) {
- match patctx.parent_pat.as_ref() {
+ match pattern_ctx.parent_pat.as_ref() {
Some(Pat::RangePat(_) | Pat::BoxPat(_)) => (),
Some(Pat::RefPat(r)) => {
if r.mut_token().is_none() {
@@ -24,7 +24,7 @@ pub(crate) fn complete_pattern(
}
_ => {
let tok = ctx.token.text_range().start();
- match (patctx.ref_token.as_ref(), patctx.mut_token.as_ref()) {
+ match (pattern_ctx.ref_token.as_ref(), pattern_ctx.mut_token.as_ref()) {
(None, None) => {
acc.add_keyword(ctx, "ref");
acc.add_keyword(ctx, "mut");
@@ -40,11 +40,11 @@ pub(crate) fn complete_pattern(
}
}
- if patctx.record_pat.is_some() {
+ if pattern_ctx.record_pat.is_some() {
return;
}
- let refutable = patctx.refutability == PatternRefutability::Refutable;
+ let refutable = pattern_ctx.refutability == PatternRefutability::Refutable;
let single_variant_enum = |enum_: hir::Enum| ctx.db.enum_data(enum_.into()).variants.len() == 1;
if let Some(hir::Adt::Enum(e)) =
@@ -55,9 +55,9 @@ pub(crate) fn complete_pattern(
acc,
ctx,
e,
- &patctx.impl_,
+ &pattern_ctx.impl_,
|acc, ctx, variant, path| {
- acc.add_qualified_variant_pat(ctx, variant, path);
+ acc.add_qualified_variant_pat(ctx, pattern_ctx, variant, path);
},
);
}
@@ -69,26 +69,39 @@ pub(crate) fn complete_pattern(
let add_simple_path = match res {
hir::ScopeDef::ModuleDef(def) => match def {
hir::ModuleDef::Adt(hir::Adt::Struct(strukt)) => {
- acc.add_struct_pat(ctx, strukt, Some(name.clone()));
+ acc.add_struct_pat(ctx, pattern_ctx, strukt, Some(name.clone()));
true
}
hir::ModuleDef::Variant(variant)
if refutable || single_variant_enum(variant.parent_enum(ctx.db)) =>
{
- acc.add_variant_pat(ctx, variant, Some(name.clone()));
+ acc.add_variant_pat(ctx, pattern_ctx, variant, Some(name.clone()));
true
}
hir::ModuleDef::Adt(hir::Adt::Enum(e)) => refutable || single_variant_enum(e),
hir::ModuleDef::Const(..) => refutable,
hir::ModuleDef::Module(..) => true,
hir::ModuleDef::Macro(mac) if mac.is_fn_like(ctx.db) => {
- return acc.add_macro(ctx, mac, name)
+ return acc.add_macro(
+ ctx,
+ &PathCompletionCtx {
+ has_call_parens: false,
+ has_macro_bang: false,
+ qualified: Qualified::No,
+ parent: None,
+ kind: crate::context::PathKind::Pat { pat_ctx: pattern_ctx.clone() },
+ has_type_args: false,
+ use_tree_parent: false,
+ },
+ mac,
+ name,
+ )
}
_ => false,
},
hir::ScopeDef::ImplSelfType(impl_) => match impl_.self_ty(ctx.db).as_adt() {
Some(hir::Adt::Struct(strukt)) => {
- acc.add_struct_pat(ctx, strukt, Some(name.clone()));
+ acc.add_struct_pat(ctx, pattern_ctx, strukt, Some(name.clone()));
true
}
Some(hir::Adt::Enum(e)) => refutable || single_variant_enum(e),
@@ -111,7 +124,7 @@ pub(crate) fn complete_pattern(
pub(crate) fn complete_pattern_path(
acc: &mut Completions,
ctx: &CompletionContext,
- PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
+ path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
) {
match qualified {
Qualified::With { resolution: Some(resolution), is_super_chain, .. } => {
@@ -132,7 +145,7 @@ pub(crate) fn complete_pattern_path(
};
if add_resolution {
- acc.add_resolution(ctx, name, def);
+ acc.add_path_resolution(ctx, path_ctx, name, def);
}
}
}
@@ -150,9 +163,9 @@ pub(crate) fn complete_pattern_path(
}
hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Enum(e))) => {
cov_mark::hit!(enum_plain_qualified_use_tree);
- e.variants(ctx.db)
- .into_iter()
- .for_each(|variant| acc.add_enum_variant(ctx, variant, None));
+ e.variants(ctx.db).into_iter().for_each(|variant| {
+ acc.add_enum_variant(ctx, path_ctx, variant, None)
+ });
e.ty(ctx.db)
}
hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Union(u))) => {
@@ -197,7 +210,7 @@ pub(crate) fn complete_pattern_path(
ctx.process_all_names(&mut |name, res| {
// FIXME: properly filter here
if let ScopeDef::ModuleDef(_) = res {
- acc.add_resolution(ctx, name, res);
+ acc.add_path_resolution(ctx, path_ctx, name, res);
}
});
diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs
index 0f7ca75868..dea0c701b8 100644
--- a/crates/ide-completion/src/completions/type.rs
+++ b/crates/ide-completion/src/completions/type.rs
@@ -13,7 +13,7 @@ use crate::{
pub(crate) fn complete_type_path(
acc: &mut Completions,
ctx: &CompletionContext,
- PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
+ path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
location: &TypeLocation,
) {
let _p = profile::span("complete_type_path");
@@ -69,7 +69,7 @@ pub(crate) fn complete_type_path(
let module_scope = module.scope(ctx.db, Some(ctx.module));
for (name, def) in module_scope {
if scope_def_applicable(def) {
- acc.add_resolution(ctx, name, def);
+ acc.add_path_resolution(ctx, path_ctx, name, def);
}
}
}
@@ -154,7 +154,7 @@ pub(crate) fn complete_type_path(
_ => false,
};
if add_resolution {
- acc.add_resolution(ctx, name, res);
+ acc.add_path_resolution(ctx, path_ctx, name, res);
}
});
return;
@@ -178,7 +178,7 @@ pub(crate) fn complete_type_path(
}
ctx.process_all_names(&mut |name, def| {
if scope_def_applicable(def) {
- acc.add_resolution(ctx, name, def);
+ acc.add_path_resolution(ctx, path_ctx, name, def);
}
});
}
diff --git a/crates/ide-completion/src/completions/use_.rs b/crates/ide-completion/src/completions/use_.rs
index f262355fc0..2c039d5018 100644
--- a/crates/ide-completion/src/completions/use_.rs
+++ b/crates/ide-completion/src/completions/use_.rs
@@ -13,7 +13,7 @@ use crate::{
pub(crate) fn complete_use_path(
acc: &mut Completions,
ctx: &CompletionContext,
- PathCompletionCtx { qualified, use_tree_parent, .. }: &PathCompletionCtx,
+ path_ctx @ PathCompletionCtx { qualified, use_tree_parent, .. }: &PathCompletionCtx,
name_ref: &Option<ast::NameRef>,
) {
match qualified {
@@ -68,7 +68,7 @@ pub(crate) fn complete_use_path(
};
if add_resolution {
- let mut builder = Builder::from_resolution(ctx, name, def);
+ let mut builder = Builder::from_resolution(ctx, path_ctx, name, def);
builder.set_relevance(CompletionRelevance {
is_name_already_imported,
..Default::default()
@@ -81,7 +81,7 @@ pub(crate) fn complete_use_path(
cov_mark::hit!(enum_plain_qualified_use_tree);
e.variants(ctx.db)
.into_iter()
- .for_each(|variant| acc.add_enum_variant(ctx, variant, None));
+ .for_each(|variant| acc.add_enum_variant(ctx, path_ctx, variant, None));
}
_ => {}
}
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 9aee1e8b49..441f7ad70b 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -269,7 +269,7 @@ pub(super) enum NameRefKind {
/// The identifier we are currently completing.
#[derive(Debug)]
-pub(super) enum IdentContext {
+pub(super) enum CompletionAnalysis {
Name(NameContext),
NameRef(NameRefContext),
Lifetime(LifetimeContext),
@@ -338,8 +338,6 @@ pub(crate) struct CompletionContext<'a> {
/// The expected type of what we are completing.
pub(super) expected_type: Option<Type>,
- // We might wanna split these out of CompletionContext
- pub(super) ident_ctx: IdentContext,
pub(super) qualifier_ctx: QualifierCtx,
pub(super) locals: FxHashMap<Name, Local>,
@@ -461,7 +459,7 @@ impl<'a> CompletionContext<'a> {
db: &'a RootDatabase,
position @ FilePosition { file_id, offset }: FilePosition,
config: &'a CompletionConfig,
- ) -> Option<CompletionContext<'a>> {
+ ) -> Option<(CompletionContext<'a>, CompletionAnalysis)> {
let _p = profile::span("CompletionContext::new");
let sema = Semantics::new(db);
@@ -503,21 +501,16 @@ impl<'a> CompletionContext<'a> {
module,
expected_name: None,
expected_type: None,
- // dummy value, will be overwritten
- ident_ctx: IdentContext::UnexpandedAttrTT {
- fake_attribute_under_caret: None,
- colon_prefix: false,
- },
qualifier_ctx: Default::default(),
locals,
};
- ctx.expand_and_fill(
+ let ident_ctx = ctx.expand_and_analyze(
original_file.syntax().clone(),
file_with_fake_ident.syntax().clone(),
offset,
fake_ident_token,
)?;
- Some(ctx)
+ Some((ctx, ident_ctx))
}
}
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index 1f691f3baf..7e6c842b1e 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -11,23 +11,23 @@ use syntax::{
};
use crate::context::{
- AttrCtx, CompletionContext, DotAccess, DotAccessKind, ExprCtx, IdentContext, ItemListKind,
- LifetimeContext, LifetimeKind, NameContext, NameKind, NameRefContext, NameRefKind, ParamKind,
- PathCompletionCtx, PathKind, PatternContext, PatternRefutability, Qualified, QualifierCtx,
- TypeAscriptionTarget, TypeLocation, COMPLETION_MARKER,
+ AttrCtx, CompletionAnalysis, CompletionContext, DotAccess, DotAccessKind, ExprCtx,
+ ItemListKind, LifetimeContext, LifetimeKind, NameContext, NameKind, NameRefContext,
+ NameRefKind, ParamKind, PathCompletionCtx, PathKind, PatternContext, PatternRefutability,
+ Qualified, QualifierCtx, TypeAscriptionTarget, TypeLocation, COMPLETION_MARKER,
};
impl<'a> CompletionContext<'a> {
/// Expand attributes and macro calls at the current cursor position for both the original file
/// and fake file repeatedly. As soon as one of the two expansions fail we stop so the original
/// and speculative states stay in sync.
- pub(super) fn expand_and_fill(
+ pub(super) fn expand_and_analyze(
&mut self,
mut original_file: SyntaxNode,
mut speculative_file: SyntaxNode,
mut offset: TextSize,
mut fake_ident_token: SyntaxToken,
- ) -> Option<()> {
+ ) -> Option<CompletionAnalysis> {
let _p = profile::span("CompletionContext::expand_and_fill");
let mut derive_ctx = None;
@@ -157,7 +157,7 @@ impl<'a> CompletionContext<'a> {
break 'expansion;
}
- self.fill(&original_file, speculative_file, offset, derive_ctx)
+ self.analyze(&original_file, speculative_file, offset, derive_ctx)
}
/// Calculate the expected type and name of the cursor position.
@@ -311,13 +311,13 @@ impl<'a> CompletionContext<'a> {
/// Fill the completion context, this is what does semantic reasoning about the surrounding context
/// of the completion location.
- fn fill(
+ fn analyze(
&mut self,
original_file: &SyntaxNode,
file_with_fake_ident: SyntaxNode,
offset: TextSize,
derive_ctx: Option<(SyntaxNode, SyntaxNode, TextSize, ast::Attr)>,
- ) -> Option<()> {
+ ) -> Option<CompletionAnalysis> {
let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased()?;
let syntax_element = NodeOrToken::Token(fake_ident_token);
if is_in_token_of_for_loop(syntax_element.clone()) {
@@ -350,8 +350,7 @@ impl<'a> CompletionContext<'a> {
.collect(),
};
}
- self.ident_ctx = IdentContext::NameRef(nameref_ctx);
- return Some(());
+ return Some(CompletionAnalysis::NameRef(nameref_ctx));
}
return None;
}
@@ -359,58 +358,54 @@ impl<'a> CompletionContext<'a> {
let name_like = match find_node_at_offset(&file_with_fake_ident, offset) {
Some(it) => it,
None => {
- if let Some(original) = ast::String::cast(self.original_token.clone()) {
- self.ident_ctx = IdentContext::String {
- original,
- expanded: ast::String::cast(self.token.clone()),
- };
- } else {
- // Fix up trailing whitespace problem
- // #[attr(foo = $0
- let token =
- syntax::algo::skip_trivia_token(self.token.clone(), Direction::Prev)?;
- let p = token.parent()?;
- if p.kind() == SyntaxKind::TOKEN_TREE
- && p.ancestors().any(|it| it.kind() == SyntaxKind::META)
- {
- let colon_prefix = previous_non_trivia_token(self.token.clone())
- .map_or(false, |it| T![:] == it.kind());
- self.ident_ctx = IdentContext::UnexpandedAttrTT {
- fake_attribute_under_caret: syntax_element
- .ancestors()
- .find_map(ast::Attr::cast),
- colon_prefix,
- };
+ let analysis =
+ if let Some(original) = ast::String::cast(self.original_token.clone()) {
+ CompletionAnalysis::String {
+ original,
+ expanded: ast::String::cast(self.token.clone()),
+ }
} else {
- return None;
- }
- }
- return Some(());
+ // Fix up trailing whitespace problem
+ // #[attr(foo = $0
+ let token =
+ syntax::algo::skip_trivia_token(self.token.clone(), Direction::Prev)?;
+ let p = token.parent()?;
+ if p.kind() == SyntaxKind::TOKEN_TREE
+ && p.ancestors().any(|it| it.kind() == SyntaxKind::META)
+ {
+ let colon_prefix = previous_non_trivia_token(self.token.clone())
+ .map_or(false, |it| T![:] == it.kind());
+ CompletionAnalysis::UnexpandedAttrTT {
+ fake_attribute_under_caret: syntax_element
+ .ancestors()
+ .find_map(ast::Attr::cast),
+ colon_prefix,
+ }
+ } else {
+ return None;
+ }
+ };
+ return Some(analysis);
}
};
-
- match name_like {
- ast::NameLike::Lifetime(lifetime) => {
- self.ident_ctx = IdentContext::Lifetime(Self::classify_lifetime(
- &self.sema,
- original_file,
- lifetime,
- )?);
- }
+ let analysis = match name_like {
+ ast::NameLike::Lifetime(lifetime) => CompletionAnalysis::Lifetime(
+ Self::classify_lifetime(&self.sema, original_file, lifetime)?,
+ ),
ast::NameLike::NameRef(name_ref) => {
let parent = name_ref.syntax().parent()?;
let (nameref_ctx, qualifier_ctx) =
Self::classify_name_ref(&self.sema, &original_file, name_ref, parent.clone())?;
self.qualifier_ctx = qualifier_ctx;
- self.ident_ctx = IdentContext::NameRef(nameref_ctx);
+ CompletionAnalysis::NameRef(nameref_ctx)
}
ast::NameLike::Name(name) => {
let name_ctx = Self::classify_name(&self.sema, original_file, name)?;
- self.ident_ctx = IdentContext::Name(name_ctx);
+ CompletionAnalysis::Name(name_ctx)
}
- }
- Some(())
+ };
+ Some(analysis)
}
fn classify_lifetime(
diff --git a/crates/ide-completion/src/context/tests.rs b/crates/ide-completion/src/context/tests.rs
index ce9357270b..c5557bdafb 100644
--- a/crates/ide-completion/src/context/tests.rs
+++ b/crates/ide-completion/src/context/tests.rs
@@ -9,7 +9,7 @@ use crate::{
fn check_expected_type_and_name(ra_fixture: &str, expect: Expect) {
let (db, pos) = position(ra_fixture);
let config = TEST_CONFIG;
- let completion_context = CompletionContext::new(&db, pos, &config).unwrap();
+ let (completion_context, _analysis) = CompletionContext::new(&db, pos, &config).unwrap();
let ty = completion_context
.expected_type
diff --git a/crates/ide-completion/src/item.rs b/crates/ide-completion/src/item.rs
index 6e5c2a9386..4774fe9db7 100644
--- a/crates/ide-completion/src/item.rs
+++ b/crates/ide-completion/src/item.rs
@@ -10,8 +10,8 @@ use syntax::{SmolStr, TextRange};
use text_edit::TextEdit;
use crate::{
- context::CompletionContext,
- render::{render_resolution, RenderContext},
+ context::{CompletionContext, PathCompletionCtx},
+ render::{render_path_resolution, RenderContext},
};
/// `CompletionItem` describes a single completion variant in the editor pop-up.
@@ -434,10 +434,11 @@ pub(crate) struct Builder {
impl Builder {
pub(crate) fn from_resolution(
ctx: &CompletionContext,
+ path_ctx: &PathCompletionCtx,
local_name: hir::Name,
resolution: hir::ScopeDef,
) -> Self {
- render_resolution(RenderContext::new(ctx), local_name, resolution)
+ render_path_resolution(RenderContext::new(ctx), path_ctx, local_name, resolution)
}
pub(crate) fn build(self) -> CompletionItem {
diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs
index bf75dcf26b..fe02f05fd1 100644
--- a/crates/ide-completion/src/lib.rs
+++ b/crates/ide-completion/src/lib.rs
@@ -25,7 +25,8 @@ use text_edit::TextEdit;
use crate::{
completions::Completions,
context::{
- CompletionContext, IdentContext, NameRefContext, NameRefKind, PathCompletionCtx, PathKind,
+ CompletionAnalysis, CompletionContext, NameRefContext, NameRefKind, PathCompletionCtx,
+ PathKind,
},
};
@@ -148,12 +149,12 @@ pub fn completions(
position: FilePosition,
trigger_character: Option<char>,
) -> Option<Completions> {
- let ctx = &CompletionContext::new(db, position, config)?;
+ let (ctx, analysis) = &CompletionContext::new(db, position, config)?;
let mut completions = Completions::default();
// prevent `(` from triggering unwanted completion noise
if trigger_character == Some('(') {
- if let IdentContext::NameRef(NameRefContext { kind, .. }) = &ctx.ident_ctx {
+ if let CompletionAnalysis::NameRef(NameRefContext { kind, .. }) = &analysis {
if let NameRefKind::Path(
path_ctx @ PathCompletionCtx { kind: PathKind::Vis { has_in_token }, .. },
) = kind
@@ -168,20 +169,20 @@ pub fn completions(
{
let acc = &mut completions;
- match &ctx.ident_ctx {
- IdentContext::Name(name_ctx) => completions::complete_name(acc, ctx, name_ctx),
- IdentContext::NameRef(name_ref_ctx) => {
+ match &analysis {
+ CompletionAnalysis::Name(name_ctx) => completions::complete_name(acc, ctx, name_ctx),
+ CompletionAnalysis::NameRef(name_ref_ctx) => {
completions::complete_name_ref(acc, ctx, name_ref_ctx)
}
- IdentContext::Lifetime(lifetime_ctx) => {
+ CompletionAnalysis::Lifetime(lifetime_ctx) => {
completions::lifetime::complete_label(acc, ctx, lifetime_ctx);
completions::lifetime::complete_lifetime(acc, ctx, lifetime_ctx);
}
- IdentContext::String { original, expanded: Some(expanded) } => {
+ CompletionAnalysis::String { original, expanded: Some(expanded) } => {
completions::extern_abi::complete_extern_abi(acc, ctx, expanded);
completions::format_string::format_string(acc, ctx, original, expanded);
}
- IdentContext::UnexpandedAttrTT {
+ CompletionAnalysis::UnexpandedAttrTT {
colon_prefix,
fake_attribute_under_caret: Some(attr),
} => {
@@ -192,7 +193,7 @@ pub fn completions(
attr,
);
}
- IdentContext::UnexpandedAttrTT { .. } | IdentContext::String { .. } => (),
+ CompletionAnalysis::UnexpandedAttrTT { .. } | CompletionAnalysis::String { .. } => (),
}
}
@@ -204,22 +205,26 @@ pub fn completions(
pub fn resolve_completion_edits(
db: &RootDatabase,
config: &CompletionConfig,
- position: FilePosition,
+ FilePosition { file_id, offset }: FilePosition,
imports: impl IntoIterator<Item = (String, String)>,
) -> Option<Vec<TextEdit>> {
let _p = profile::span("resolve_completion_edits");
- let ctx = CompletionContext::new(db, position, config)?;
- let position_for_import = &ctx.original_token.parent()?;
- let scope = ImportScope::find_insert_use_container(position_for_import, &ctx.sema)?;
+ let sema = hir::Semantics::new(db);
+
+ let original_file = sema.parse(file_id);
+ let original_token =
+ syntax::AstNode::syntax(&original_file).token_at_offset(offset).left_biased()?;
+ let position_for_import = &original_token.parent()?;
+ let scope = ImportScope::find_insert_use_container(position_for_import, &sema)?;
- let current_module = ctx.sema.scope(position_for_import)?.module();
+ let current_module = sema.scope(position_for_import)?.module();
let current_crate = current_module.krate();
let new_ast = scope.clone_for_update();
let mut import_insert = TextEdit::builder();
imports.into_iter().for_each(|(full_import_path, imported_name)| {
let items_with_name = items_locator::items_with_name(
- &ctx.sema,
+ &sema,
current_crate,
NameToImport::exact_case_sensitive(imported_name),
items_locator::AssocItemSearch::Include,
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index c6091645ca..9c339a13e7 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -17,7 +17,7 @@ use ide_db::{
use syntax::{SmolStr, SyntaxKind, TextRange};
use crate::{
- context::{IdentContext, NameRefContext, NameRefKind, PathCompletionCtx, PathKind},
+ context::{PathCompletionCtx, PathKind},
item::{Builder, CompletionRelevanceTypeMatch},
render::{function::render_fn, literal::render_variant_lit, macro_::render_macro},
CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance,
@@ -74,16 +74,6 @@ impl<'a> RenderContext<'a> {
.map_or(false, |it| it.kind() == SyntaxKind::MACRO_CALL)
}
- pub(crate) fn path_is_call(&self) -> bool {
- matches!(
- self.completion.ident_ctx,
- IdentContext::NameRef(NameRefContext {
- kind: NameRefKind::Path(PathCompletionCtx { has_call_parens: true, .. }),
- ..
- })
- )
- }
-
fn is_deprecated(&self, def: impl HasAttrs) -> bool {
let attrs = def.attrs(self.db());
attrs.by_key("deprecated").exists()
@@ -163,12 +153,13 @@ pub(crate) fn render_tuple_field(
item.build()
}
-pub(crate) fn render_resolution(
+pub(crate) fn render_path_resolution(
ctx: RenderContext<'_>,
+ path_ctx: &PathCompletionCtx,
local_name: hir::Name,
resolution: ScopeDef,
) -> Builder {
- render_resolution_(ctx, local_name, None, resolution)
+ render_resolution_(ctx, path_ctx, local_name, None, resolution)
}
pub(crate) fn render_resolution_simple(
@@ -181,6 +172,7 @@ pub(crate) fn render_resolution_simple(
pub(crate) fn render_resolution_with_import(
ctx: RenderContext<'_>,
+ path_ctx: &PathCompletionCtx,
import_edit: LocatedImport,
) -> Option<Builder> {
let resolution = ScopeDef::from(import_edit.original_item);
@@ -190,7 +182,7 @@ pub(crate) fn render_resolution_with_import(
ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db),
_ => item_name(ctx.db(), import_edit.original_item)?,
};
- Some(render_resolution_(ctx, local_name, Some(import_edit), resolution))
+ Some(render_resolution_(ctx, path_ctx, local_name, Some(import_edit), resolution))
}
pub(crate) fn render_type_inference(ty_string: String, ctx: &CompletionContext) -> CompletionItem {
@@ -202,6 +194,7 @@ pub(crate) fn render_type_inference(ty_string: String, ctx: &CompletionContext)
fn render_resolution_(
ctx: RenderContext<'_>,
+ path_ctx: &PathCompletionCtx,
local_name: hir::Name,
import_to_add: Option<LocatedImport>,
resolution: ScopeDef,
@@ -212,21 +205,61 @@ fn render_resolution_(
match resolution {
ScopeDef::ModuleDef(Macro(mac)) => {
let ctx = ctx.import_to_add(import_to_add);
- return render_macro(ctx, local_name, mac);
+ return render_macro(ctx, path_ctx, local_name, mac);
}
ScopeDef::ModuleDef(Function(func)) => {
let ctx = ctx.import_to_add(import_to_add);
- return render_fn(ctx, Some(local_name), func);
+ return render_fn(ctx, path_ctx, Some(local_name), func);
}
ScopeDef::ModuleDef(Variant(var)) => {
let ctx = ctx.clone().import_to_add(import_to_add.clone());
- if let Some(item) = render_variant_lit(ctx, Some(local_name.clone()), var, None) {
+ if let Some(item) =
+ render_variant_lit(ctx, path_ctx, Some(local_name.clone()), var, None)
+ {
return item;
}
}
_ => (),
}
- render_resolution_simple_(ctx, local_name, import_to_add, resolution)
+ render_resolution_simple_type(ctx, path_ctx, local_name, import_to_add, resolution)
+}
+
+fn render_resolution_simple_type(
+ ctx: RenderContext<'_>,
+ path_ctx: &PathCompletionCtx,
+ local_name: hir::Name,
+ import_to_add: Option<LocatedImport>,
+ resolution: ScopeDef,
+) -> Builder {
+ let cap = ctx.snippet_cap();
+ let db = ctx.completion.db;
+ let config = ctx.completion.config;
+ let name = local_name.to_smol_str();
+ let mut item = render_resolution_simple_(ctx, local_name, import_to_add, resolution);
+ // Add `<>` for generic types
+ let type_path_no_ty_args = matches!(
+ path_ctx,
+ PathCompletionCtx { kind: PathKind::Type { .. }, has_type_args: false, .. }
+ ) && config.callable.is_some();
+ if type_path_no_ty_args {
+ if let Some(cap) = cap {
+ let has_non_default_type_params = match resolution {
+ ScopeDef::ModuleDef(hir::ModuleDef::Adt(it)) => it.has_non_default_type_params(db),
+ ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(it)) => {
+ it.has_non_default_type_params(db)
+ }
+ _ => false,
+ };
+ if has_non_default_type_params {
+ cov_mark::hit!(inserts_angle_brackets_for_generics);
+ item.lookup_by(name.clone())
+ .label(SmolStr::from_iter([&name, "<…>"]))
+ .trigger_call_info()
+ .insert_snippet(cap, format!("{}<$0>", name));
+ }
+ }
+ }
+ item
}
fn render_resolution_simple_(
@@ -289,34 +322,6 @@ fn render_resolution_simple_(
}
};
- // Add `<>` for generic types
- let type_path_no_ty_args = matches!(
- ctx.completion.ident_ctx,
- IdentContext::NameRef(NameRefContext {
- kind: NameRefKind::Path(PathCompletionCtx {
- kind: PathKind::Type { .. },
- has_type_args: false,
- ..
- }),
- ..
- })
- ) && ctx.completion.config.callable.is_some();
- if type_path_no_ty_args {
- if let Some(cap) = ctx.snippet_cap() {
- let has_non_default_type_params = match resolution {
- ScopeDef::ModuleDef(Adt(it)) => it.has_non_default_type_params(db),
- ScopeDef::ModuleDef(TypeAlias(it)) => it.has_non_default_type_params(db),
- _ => false,
- };
- if has_non_default_type_params {
- cov_mark::hit!(inserts_angle_brackets_for_generics);
- item.lookup_by(local_name.clone())
- .label(SmolStr::from_iter([&local_name, "<…>"]))
- .trigger_call_info()
- .insert_snippet(cap, format!("{}<$0>", local_name));
- }
- }
- }
item.set_documentation(scope_def_docs(db, resolution))
.set_deprecated(scope_def_is_deprecated(&ctx, resolution));
diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs
index 48539a03b1..3666ee40e2 100644
--- a/crates/ide-completion/src/render/function.rs
+++ b/crates/ide-completion/src/render/function.rs
@@ -8,8 +8,7 @@ use syntax::SmolStr;
use crate::{
context::{
- CompletionContext, DotAccess, DotAccessKind, IdentContext, NameRefContext, NameRefKind,
- PathCompletionCtx, PathKind, Qualified,
+ CompletionContext, DotAccess, DotAccessKind, PathCompletionCtx, PathKind, Qualified,
},
item::{Builder, CompletionItem, CompletionItemKind, CompletionRelevance},
render::{compute_exact_name_match, compute_ref_match, compute_type_match, RenderContext},
@@ -23,21 +22,54 @@ enum FuncKind {
pub(crate) fn render_fn(
ctx: RenderContext<'_>,
+ path_ctx: &PathCompletionCtx,
local_name: Option<hir::Name>,
func: hir::Function,
) -> Builder {
let _p = profile::span("render_fn");
- render(ctx, local_name, func, FuncKind::Function)
+ let func_kind = FuncKind::Function;
+ let params = match ctx.completion.config.snippet_cap {
+ Some(_) => {
+ if !matches!(
+ path_ctx,
+ PathCompletionCtx { kind: PathKind::Expr { .. }, has_call_parens: true, .. }
+ | PathCompletionCtx { kind: PathKind::Use | PathKind::Type { .. }, .. }
+ ) {
+ params(ctx.completion, func, &func_kind, false)
+ } else {
+ None
+ }
+ }
+ _ => None,
+ };
+ render(
+ ctx,
+ local_name,
+ func,
+ func_kind,
+ params,
+ matches!(path_ctx.qualified, Qualified::With { .. }),
+ )
}
pub(crate) fn render_method(
ctx: RenderContext<'_>,
+ dot_access: &DotAccess,
receiver: Option<hir::Name>,
local_name: Option<hir::Name>,
func: hir::Function,
) -> Builder {
let _p = profile::span("render_method");
- render(ctx, local_name, func, FuncKind::Method(receiver))
+ let func_kind = FuncKind::Method(receiver);
+ let params = match ctx.completion.config.snippet_cap {
+ Some(_) => match dot_access {
+ DotAccess { kind: DotAccessKind::Method { has_parens: true }, .. } => None,
+ _ => params(ctx.completion, func, &func_kind, true),
+ },
+ _ => None,
+ };
+
+ render(ctx, local_name, func, func_kind, params, false)
}
fn render(
@@ -45,6 +77,8 @@ fn render(
local_name: Option<hir::Name>,
func: hir::Function,
func_kind: FuncKind,
+ params: Option<(Option<hir::SelfParam>, Vec<hir::Param>)>,
+ qualified_path: bool,
) -> Builder {
let db = completion.db;
@@ -80,16 +114,6 @@ fn render(
// FIXME For now we don't properly calculate the edits for ref match
// completions on methods or qualified paths, so we've disabled them.
// See #8058.
- let qualified_path = matches!(
- ctx.completion.ident_ctx,
- IdentContext::NameRef(NameRefContext {
- kind: NameRefKind::Path(PathCompletionCtx {
- qualified: Qualified::With { .. },
- ..
- }),
- ..
- })
- );
if matches!(func_kind, FuncKind::Function) && !qualified_path {
item.ref_match(ref_match);
}
@@ -100,11 +124,9 @@ fn render(
.detail(detail(db, func))
.lookup_by(name.to_smol_str());
- match completion.config.snippet_cap {
- Some(cap) => {
- if let Some((self_param, params)) = params(completion, func, &func_kind) {
- add_call_parens(&mut item, completion, cap, call, self_param, params);
- }
+ match completion.config.snippet_cap.zip(params) {
+ Some((cap, (self_param, params))) => {
+ add_call_parens(&mut item, completion, cap, call, self_param, params);
}
_ => (),
}
@@ -254,37 +276,12 @@ fn params(
ctx: &CompletionContext<'_>,
func: hir::Function,
func_kind: &FuncKind,
+ has_dot_receiver: bool,
) -> Option<(Option<hir::SelfParam>, Vec<hir::Param>)> {
if ctx.config.callable.is_none() {
return None;
}
- let has_dot_receiver = match ctx.ident_ctx {
- IdentContext::NameRef(NameRefContext {
- kind:
- NameRefKind::DotAccess(DotAccess {
- kind: DotAccessKind::Method { has_parens: true },
- ..
- }),
- ..
- }) => return None,
- IdentContext::NameRef(NameRefContext {
- kind: NameRefKind::DotAccess(DotAccess { .. }),
- ..
- }) => true,
- IdentContext::NameRef(NameRefContext {
- kind:
- NameRefKind::Path(
- PathCompletionCtx {
- kind: PathKind::Expr { .. }, has_call_parens: true, ..
- }
- | PathCompletionCtx { kind: PathKind::Use | PathKind::Type { .. }, .. },
- ),
- ..
- }) => return None,
- _ => false,
- };
-
// Don't add parentheses if the expected type is some function reference.
if let Some(ty) = &ctx.expected_type {
// FIXME: check signature matches?
diff --git a/crates/ide-completion/src/render/literal.rs b/crates/ide-completion/src/render/literal.rs
index 042c974257..b89030990e 100644
--- a/crates/ide-completion/src/render/literal.rs
+++ b/crates/ide-completion/src/render/literal.rs
@@ -4,9 +4,7 @@ use hir::{db::HirDatabase, Documentation, HasAttrs, StructKind};
use ide_db::SymbolKind;
use crate::{
- context::{
- CompletionContext, IdentContext, NameRefContext, NameRefKind, PathCompletionCtx, PathKind,
- },
+ context::{CompletionContext, PathCompletionCtx, PathKind},
item::{Builder, CompletionItem},
render::{
compute_ref_match, compute_type_match,
@@ -21,6 +19,7 @@ use crate::{
pub(crate) fn render_variant_lit(
ctx: RenderContext<'_>,
+ path_ctx: &PathCompletionCtx,
local_name: Option<hir::Name>,
variant: hir::Variant,
path: Option<hir::ModPath>,
@@ -29,11 +28,12 @@ pub(crate) fn render_variant_lit(
let db = ctx.db();
let name = local_name.unwrap_or_else(|| variant.name(db));
- render(ctx, Variant::EnumVariant(variant), name, path)
+ render(ctx, path_ctx, Variant::EnumVariant(variant), name, path)
}
pub(crate) fn render_struct_literal(
ctx: RenderContext<'_>,
+ path_ctx: &PathCompletionCtx,
strukt: hir::Struct,
path: Option<hir::ModPath>,
local_name: Option<hir::Name>,
@@ -42,29 +42,21 @@ pub(crate) fn render_struct_literal(
let db = ctx.db();
let name = local_name.unwrap_or_else(|| strukt.name(db));
- render(ctx, Variant::Struct(strukt), name, path)
+ render(ctx, path_ctx, Variant::Struct(strukt), name, path)
}
fn render(
ctx @ RenderContext { completion, .. }: RenderContext<'_>,
+ path_ctx: &PathCompletionCtx,
thing: Variant,
name: hir::Name,
path: Option<hir::ModPath>,
) -> Option<Builder> {
let db = completion.db;
let mut kind = thing.kind(db);
- let should_add_parens = match &completion.ident_ctx {
- IdentContext::NameRef(NameRefContext {
- kind: NameRefKind::Path(PathCompletionCtx { has_call_parens: true, .. }),
- ..
- }) => false,
- IdentContext::NameRef(NameRefContext {
- kind:
- NameRefKind::Path(PathCompletionCtx {
- kind: PathKind::Use | PathKind::Type { .. }, ..
- }),
- ..
- }) => false,
+ let should_add_parens = match &path_ctx {
+ PathCompletionCtx { has_call_parens: true, .. } => false,
+ PathCompletionCtx { kind: PathKind::Use | PathKind::Type { .. }, .. } => false,
_ => true,
};
diff --git a/crates/ide-completion/src/render/macro_.rs b/crates/ide-completion/src/render/macro_.rs
index 0c9c65f423..6da7bb3193 100644
--- a/crates/ide-completion/src/render/macro_.rs
+++ b/crates/ide-completion/src/render/macro_.rs
@@ -5,18 +5,24 @@ use ide_db::SymbolKind;
use syntax::SmolStr;
use crate::{
- context::{IdentContext, NameRefContext, NameRefKind, PathCompletionCtx, PathKind},
+ context::{PathCompletionCtx, PathKind},
item::{Builder, CompletionItem},
render::RenderContext,
};
-pub(crate) fn render_macro(ctx: RenderContext<'_>, name: hir::Name, macro_: hir::Macro) -> Builder {
+pub(crate) fn render_macro(
+ ctx: RenderContext<'_>,
+ path_ctx: &PathCompletionCtx,
+ name: hir::Name,
+ macro_: hir::Macro,
+) -> Builder {
let _p = profile::span("render_macro");
- render(ctx, name, macro_)
+ render(ctx, path_ctx, name, macro_)
}
fn render(
ctx @ RenderContext { completion, .. }: RenderContext<'_>,
+ PathCompletionCtx { kind, has_macro_bang, has_call_parens, .. }: &PathCompletionCtx,
name: hir::Name,
macro_: hir::Macro,
) -> Builder {
@@ -33,13 +39,7 @@ fn render(
let is_fn_like = macro_.is_fn_like(completion.db);
let (bra, ket) = if is_fn_like { guess_macro_braces(&name, docs_str) } else { ("", "") };
- let needs_bang = match &completion.ident_ctx {
- IdentContext::NameRef(NameRefContext {
- kind: NameRefKind::Path(PathCompletionCtx { kind, has_macro_bang, .. }),
- ..
- }) => is_fn_like && *kind != PathKind::Use && !has_macro_bang,
- _ => is_fn_like,
- };
+ let needs_bang = is_fn_like && *kind != PathKind::Use && !has_macro_bang;
let mut item = CompletionItem::new(
SymbolKind::from(macro_.kind(completion.db)),
@@ -53,7 +53,7 @@ fn render(
let name = &*name;
match ctx.snippet_cap() {
- Some(cap) if needs_bang && !ctx.path_is_call() => {
+ Some(cap) if needs_bang && !has_call_parens => {
let snippet = format!("{}!{}$0{}", name, bra, ket);
let lookup = banged_name(name);
item.insert_snippet(cap, snippet).lookup_by(lookup);
diff --git a/crates/ide-completion/src/render/pattern.rs b/crates/ide-completion/src/render/pattern.rs
index 74564bb3aa..463d292955 100644
--- a/crates/ide-completion/src/render/pattern.rs
+++ b/crates/ide-completion/src/render/pattern.rs
@@ -6,16 +6,14 @@ use itertools::Itertools;
use syntax::SmolStr;
use crate::{
- context::{
- IdentContext, NameContext, NameKind, NameRefContext, NameRefKind, ParamKind,
- PathCompletionCtx, PathKind, PatternContext,
- },
+ context::{ParamKind, PatternContext},
render::{variant::visible_fields, RenderContext},
CompletionItem, CompletionItemKind,
};
pub(crate) fn render_struct_pat(
ctx: RenderContext<'_>,
+ pattern_ctx: &PatternContext,
strukt: hir::Struct,
local_name: Option<Name>,
) -> Option<CompletionItem> {
@@ -30,13 +28,21 @@ pub(crate) fn render_struct_pat(
}
let name = local_name.unwrap_or_else(|| strukt.name(ctx.db())).to_smol_str();
- let pat = render_pat(&ctx, &name, strukt.kind(ctx.db()), &visible_fields, fields_omitted)?;
+ let pat = render_pat(
+ &ctx,
+ pattern_ctx,
+ &name,
+ strukt.kind(ctx.db()),
+ &visible_fields,
+ fields_omitted,
+ )?;
Some(build_completion(ctx, name, pat, strukt))
}
pub(crate) fn render_variant_pat(
ctx: RenderContext<'_>,
+ pattern_ctx: &PatternContext,
variant: hir::Variant,
local_name: Option<Name>,
path: Option<&hir::ModPath>,
@@ -50,7 +56,14 @@ pub(crate) fn render_variant_pat(
Some(path) => path.to_string().into(),
None => local_name.unwrap_or_else(|| variant.name(ctx.db())).to_smol_str(),
};
- let pat = render_pat(&ctx, &name, variant.kind(ctx.db()), &visible_fields, fields_omitted)?;
+ let pat = render_pat(
+ &ctx,
+ pattern_ctx,
+ &name,
+ variant.kind(ctx.db()),
+ &visible_fields,
+ fields_omitted,
+ )?;
Some(build_completion(ctx, name, pat, variant))
}
@@ -75,49 +88,28 @@ fn build_completion(
fn render_pat(
ctx: &RenderContext<'_>,
+ pattern_ctx: &PatternContext,
name: &str,
kind: StructKind,
fields: &[hir::Field],
fields_omitted: bool,
) -> Option<String> {
- let has_call_parens = matches!(
- ctx.completion.ident_ctx,
- IdentContext::NameRef(NameRefContext {
- kind: NameRefKind::Path(PathCompletionCtx { has_call_parens: true, .. }),
- ..
- })
- );
let mut pat = match kind {
- StructKind::Tuple if !has_call_parens => {
- render_tuple_as_pat(ctx.snippet_cap(), fields, name, fields_omitted)
- }
- StructKind::Record if !has_call_parens => {
+ StructKind::Tuple => render_tuple_as_pat(ctx.snippet_cap(), fields, name, fields_omitted),
+ StructKind::Record => {
render_record_as_pat(ctx.db(), ctx.snippet_cap(), fields, name, fields_omitted)
}
StructKind::Unit => return None,
- _ => name.to_owned(),
};
- let needs_ascription = !has_call_parens
- && matches!(
- &ctx.completion.ident_ctx,
- IdentContext::NameRef(NameRefContext {
- kind: NameRefKind::Path(PathCompletionCtx {
- kind: PathKind::Pat {
- pat_ctx
- },
- ..
- }),
- ..
- }) | IdentContext::Name(NameContext {
- kind: NameKind::IdentPat(pat_ctx), ..}
- )
- if matches!(pat_ctx, PatternContext {
- param_ctx: Some((.., ParamKind::Function(_))),
- has_type_ascription: false,
- ..
- })
- );
+ let needs_ascription = matches!(
+ pattern_ctx,
+ PatternContext {
+ param_ctx: Some((.., ParamKind::Function(_))),
+ has_type_ascription: false,
+ ..
+ }
+ );
if needs_ascription {
pat.push(':');
pat.push(' ');
diff --git a/crates/ide-completion/src/tests/flyimport.rs b/crates/ide-completion/src/tests/flyimport.rs
index a3bc1025e9..c393e16e7a 100644
--- a/crates/ide-completion/src/tests/flyimport.rs
+++ b/crates/ide-completion/src/tests/flyimport.rs
@@ -1,22 +1,22 @@
use expect_test::{expect, Expect};
use crate::{
- context::{IdentContext, NameContext, NameKind, NameRefKind},
+ context::{CompletionAnalysis, NameContext, NameKind, NameRefKind},
tests::{check_edit, check_edit_with_config, TEST_CONFIG},
};
fn check(ra_fixture: &str, expect: Expect) {
let config = TEST_CONFIG;
let (db, position) = crate::tests::position(ra_fixture);
- let ctx = crate::context::CompletionContext::new(&db, position, &config).unwrap();
+ let (ctx, analysis) = crate::context::CompletionContext::new(&db, position, &config).unwrap();
let mut acc = crate::completions::Completions::default();
- if let IdentContext::Name(NameContext { kind: NameKind::IdentPat(pat_ctx), .. }) =
- &ctx.ident_ctx
+ if let CompletionAnalysis::Name(NameContext { kind: NameKind::IdentPat(pat_ctx), .. }) =
+ &analysis
{
crate::completions::flyimport::import_on_the_fly_pat(&mut acc, &ctx, pat_ctx);
}
- if let IdentContext::NameRef(name_ref_ctx) = &ctx.ident_ctx {
+ if let CompletionAnalysis::NameRef(name_ref_ctx) = &analysis {
match &name_ref_ctx.kind {
NameRefKind::Path(path) => {
crate::completions::flyimport::import_on_the_fly_path(&mut acc, &ctx, path);