Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/context/analysis.rs')
-rw-r--r--crates/ide-completion/src/context/analysis.rs72
1 files changed, 54 insertions, 18 deletions
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index d416d8251d..e08fa6bdd3 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -389,16 +389,6 @@ impl<'a> CompletionContext<'a> {
return Some(());
}
};
- self.impl_def = self
- .sema
- .token_ancestors_with_macros(self.token.clone())
- .take_while(|it| it.kind() != SyntaxKind::SOURCE_FILE)
- .filter_map(ast::Item::cast)
- .take(2)
- .find_map(|it| match it {
- ast::Item::Impl(impl_) => Some(impl_),
- _ => None,
- });
match name_like {
ast::NameLike::Lifetime(lifetime) => {
@@ -452,7 +442,7 @@ impl<'a> CompletionContext<'a> {
}
fn classify_name(
- _sema: &Semantics<RootDatabase>,
+ sema: &Semantics<RootDatabase>,
original_file: &SyntaxNode,
name: ast::Name,
) -> Option<NameContext> {
@@ -464,7 +454,7 @@ impl<'a> CompletionContext<'a> {
ast::Enum(_) => NameKind::Enum,
ast::Fn(_) => NameKind::Function,
ast::IdentPat(bind_pat) => {
- let mut pat_ctx = pattern_context_for(original_file, bind_pat.into());
+ let mut pat_ctx = pattern_context_for(sema, original_file, bind_pat.into());
if let Some(record_field) = ast::RecordPatField::for_field_name(&name) {
pat_ctx.record_pat = find_node_in_file_compensated(original_file, &record_field.parent_record_pat());
}
@@ -518,6 +508,7 @@ impl<'a> CompletionContext<'a> {
&record_field.parent_record_pat(),
),
..pattern_context_for(
+ sema,
original_file,
record_field.parent_record_pat().clone().into(),
)
@@ -766,6 +757,7 @@ impl<'a> CompletionContext<'a> {
.parent()
.and_then(ast::LetStmt::cast)
.map_or(false, |it| it.semicolon_token().is_none());
+ let impl_ = fetch_immediate_impl(sema, original_file, &expr);
PathKind::Expr {
in_block_expr,
@@ -777,6 +769,7 @@ impl<'a> CompletionContext<'a> {
innermost_ret_ty,
self_param,
incomplete_let,
+ impl_,
}
};
let make_path_kind_type = |ty: ast::Type| {
@@ -804,14 +797,14 @@ impl<'a> CompletionContext<'a> {
},
ast::TupleStructPat(it) => {
path_ctx.has_call_parens = true;
- PathKind::Pat { pat_ctx: pattern_context_for(original_file, it.into())}
+ PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())}
},
ast::RecordPat(it) => {
path_ctx.has_call_parens = true;
- PathKind::Pat { pat_ctx: pattern_context_for(original_file, it.into())}
+ PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())}
},
ast::PathPat(it) => {
- PathKind::Pat { pat_ctx: pattern_context_for(original_file, it.into())}
+ PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())}
},
ast::MacroCall(it) => {
// A macro call in this position is usually a result of parsing recovery, so check that
@@ -825,7 +818,7 @@ impl<'a> CompletionContext<'a> {
match_ast! {
match parent {
ast::MacroExpr(expr) => make_path_kind_expr(expr.into()),
- ast::MacroPat(it) => PathKind::Pat { pat_ctx: pattern_context_for(original_file, it.into())},
+ ast::MacroPat(it) => PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())},
ast::MacroType(ty) => make_path_kind_type(ty.into()),
ast::ItemList(_) => PathKind::Item { kind: ItemListKind::Module },
ast::AssocItemList(_) => PathKind::Item { kind: match parent.parent() {
@@ -833,7 +826,7 @@ impl<'a> CompletionContext<'a> {
match it {
ast::Trait(_) => ItemListKind::Trait,
ast::Impl(it) => if it.trait_().is_some() {
- ItemListKind::TraitImpl
+ ItemListKind::TraitImpl(find_node_in_file_compensated(original_file, &it))
} else {
ItemListKind::Impl
},
@@ -970,7 +963,11 @@ impl<'a> CompletionContext<'a> {
}
}
-fn pattern_context_for(original_file: &SyntaxNode, pat: ast::Pat) -> PatternContext {
+fn pattern_context_for(
+ sema: &Semantics<RootDatabase>,
+ original_file: &SyntaxNode,
+ pat: ast::Pat,
+) -> PatternContext {
let mut is_param = None;
let (refutability, has_type_ascription) =
pat
@@ -1011,6 +1008,7 @@ fn pattern_context_for(original_file: &SyntaxNode, pat: ast::Pat) -> PatternCont
ast::Pat::IdentPat(it) => (it.ref_token(), it.mut_token()),
_ => (None, None),
};
+
PatternContext {
refutability,
param_ctx: is_param,
@@ -1019,6 +1017,44 @@ fn pattern_context_for(original_file: &SyntaxNode, pat: ast::Pat) -> PatternCont
mut_token,
ref_token,
record_pat: None,
+ impl_: fetch_immediate_impl(sema, original_file, &pat),
+ }
+}
+
+fn fetch_immediate_impl(
+ sema: &Semantics<RootDatabase>,
+ original_file: &SyntaxNode,
+ node: &impl AstNode,
+) -> Option<ast::Impl> {
+ // FIXME: The fallback here could be done better
+ let (f, s) = match find_node_in_file_compensated(original_file, node) {
+ Some(node) => {
+ let mut items = sema
+ .ancestors_with_macros(node.syntax().clone())
+ .filter_map(ast::Item::cast)
+ .filter(|it| !matches!(it, ast::Item::MacroCall(_)))
+ .take(2);
+ (items.next(), items.next())
+ }
+ None => {
+ let mut items = node
+ .syntax()
+ .ancestors()
+ .filter_map(ast::Item::cast)
+ .filter(|it| !matches!(it, ast::Item::MacroCall(_)))
+ .take(2);
+ (items.next(), items.next())
+ }
+ };
+
+ match f? {
+ ast::Item::Const(_) | ast::Item::Fn(_) | ast::Item::TypeAlias(_) => (),
+ ast::Item::Impl(it) => return Some(it),
+ _ => return None,
+ }
+ match s? {
+ ast::Item::Impl(it) => Some(it),
+ _ => None,
}
}