mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-16 07:03:57 +00:00
Auto merge of #12577 - Veykril:completion, r=Veykril
internal: NameRefKind classification is not optional
This commit is contained in:
commit
b1f9efa65c
13 changed files with 145 additions and 144 deletions
|
@ -123,7 +123,7 @@ pub(crate) fn import_on_the_fly_path(
|
|||
| PathKind::Type { .. }
|
||||
| PathKind::Attr { .. }
|
||||
| PathKind::Derive { .. }
|
||||
| PathKind::Pat),
|
||||
| PathKind::Pat { .. }),
|
||||
qualified,
|
||||
..
|
||||
} => (Some(kind), qualified),
|
||||
|
@ -183,7 +183,7 @@ pub(crate) fn import_on_the_fly_pat(
|
|||
return None;
|
||||
}
|
||||
let kind = match pat_ctx {
|
||||
PatternContext { record_pat: None, .. } => PathKind::Pat,
|
||||
PatternContext { record_pat: None, .. } => PathKind::Pat { pat_ctx: pat_ctx.clone() },
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
|
@ -229,15 +229,17 @@ fn import_on_the_fly(
|
|||
PathKind::Expr { .. }
|
||||
| PathKind::Type { .. }
|
||||
| PathKind::Item { .. }
|
||||
| PathKind::Pat,
|
||||
| PathKind::Pat { .. },
|
||||
ItemInNs::Macros(mac),
|
||||
) => mac.is_fn_like(ctx.db),
|
||||
(PathKind::Item { .. }, _) => true,
|
||||
|
||||
(PathKind::Expr { .. }, ItemInNs::Types(_) | ItemInNs::Values(_)) => true,
|
||||
|
||||
(PathKind::Pat, ItemInNs::Types(_)) => true,
|
||||
(PathKind::Pat, ItemInNs::Values(def)) => matches!(def, hir::ModuleDef::Const(_)),
|
||||
(PathKind::Pat { .. }, ItemInNs::Types(_)) => true,
|
||||
(PathKind::Pat { .. }, ItemInNs::Values(def)) => {
|
||||
matches!(def, hir::ModuleDef::Const(_))
|
||||
}
|
||||
|
||||
(PathKind::Type { location }, ItemInNs::Types(ty)) => {
|
||||
if matches!(location, TypeLocation::TypeBound) {
|
||||
|
|
|
@ -95,12 +95,12 @@ pub(crate) fn complete_trait_impl_name_ref(
|
|||
NameRefContext {
|
||||
nameref,
|
||||
kind:
|
||||
Some(NameRefKind::Path(
|
||||
NameRefKind::Path(
|
||||
path_ctx @ PathCompletionCtx {
|
||||
kind: PathKind::Item { kind: ItemListKind::TraitImpl },
|
||||
..
|
||||
},
|
||||
)),
|
||||
),
|
||||
} if path_ctx.is_trivial_path() => complete_trait_impl(
|
||||
acc,
|
||||
ctx,
|
||||
|
|
|
@ -107,7 +107,7 @@ pub(crate) fn pattern_path_completion(
|
|||
ctx: &CompletionContext,
|
||||
PathCompletionCtx { qualified, kind, .. }: &PathCompletionCtx,
|
||||
) {
|
||||
if !matches!(kind, PathKind::Pat) {
|
||||
if !matches!(kind, PathKind::Pat { .. }) {
|
||||
return;
|
||||
}
|
||||
match qualified {
|
||||
|
|
|
@ -20,12 +20,12 @@ pub(crate) fn complete_use_tree(
|
|||
let (qualified, name_ref, use_tree_parent) = match name_ref_ctx {
|
||||
NameRefContext {
|
||||
kind:
|
||||
Some(NameRefKind::Path(PathCompletionCtx {
|
||||
NameRefKind::Path(PathCompletionCtx {
|
||||
kind: PathKind::Use,
|
||||
qualified,
|
||||
use_tree_parent,
|
||||
..
|
||||
})),
|
||||
}),
|
||||
nameref,
|
||||
..
|
||||
} => (qualified, nameref, use_tree_parent),
|
||||
|
|
|
@ -85,7 +85,7 @@ impl PathCompletionCtx {
|
|||
}
|
||||
|
||||
/// The kind of path we are completing right now.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub(super) enum PathKind {
|
||||
Expr {
|
||||
in_block_expr: bool,
|
||||
|
@ -110,7 +110,9 @@ pub(super) enum PathKind {
|
|||
Item {
|
||||
kind: ItemListKind,
|
||||
},
|
||||
Pat,
|
||||
Pat {
|
||||
pat_ctx: PatternContext,
|
||||
},
|
||||
Vis {
|
||||
has_in_token: bool,
|
||||
},
|
||||
|
@ -164,7 +166,7 @@ pub(super) enum Qualified {
|
|||
}
|
||||
|
||||
/// The state of the pattern we are completing.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(super) struct PatternContext {
|
||||
pub(super) refutability: PatternRefutability,
|
||||
pub(super) param_ctx: Option<(ast::ParamList, ast::Param, ParamKind)>,
|
||||
|
@ -208,7 +210,7 @@ pub(super) enum NameKind {
|
|||
ConstParam,
|
||||
Enum,
|
||||
Function,
|
||||
IdentPat,
|
||||
IdentPat(PatternContext),
|
||||
MacroDef,
|
||||
MacroRules,
|
||||
/// Fake node
|
||||
|
@ -230,8 +232,7 @@ pub(super) enum NameKind {
|
|||
pub(super) struct NameRefContext {
|
||||
/// NameRef syntax in the original file
|
||||
pub(super) nameref: Option<ast::NameRef>,
|
||||
// FIXME: This shouldn't be an Option
|
||||
pub(super) kind: Option<NameRefKind>,
|
||||
pub(super) kind: NameRefKind,
|
||||
}
|
||||
|
||||
/// The kind of the NameRef we are completing.
|
||||
|
@ -243,6 +244,7 @@ pub(super) enum NameRefKind {
|
|||
Keyword(ast::Item),
|
||||
/// The record expression this nameref is a field of
|
||||
RecordExpr(ast::RecordExpr),
|
||||
Pattern(PatternContext),
|
||||
}
|
||||
|
||||
/// The identifier we are currently completing.
|
||||
|
@ -330,7 +332,6 @@ pub(crate) struct CompletionContext<'a> {
|
|||
|
||||
// We might wanna split these out of CompletionContext
|
||||
pub(super) ident_ctx: IdentContext,
|
||||
pub(super) pattern_ctx: Option<PatternContext>,
|
||||
pub(super) qualifier_ctx: QualifierCtx,
|
||||
|
||||
pub(super) locals: FxHashMap<Name, Local>,
|
||||
|
@ -505,7 +506,6 @@ impl<'a> CompletionContext<'a> {
|
|||
previous_token: None,
|
||||
// dummy value, will be overwritten
|
||||
ident_ctx: IdentContext::UnexpandedAttrTT { fake_attribute_under_caret: None },
|
||||
pattern_ctx: None,
|
||||
qualifier_ctx: Default::default(),
|
||||
locals,
|
||||
};
|
||||
|
|
|
@ -343,9 +343,9 @@ impl<'a> CompletionContext<'a> {
|
|||
find_node_at_offset(&file_with_fake_ident, offset)
|
||||
{
|
||||
let parent = name_ref.syntax().parent()?;
|
||||
let (mut nameref_ctx, _, _) =
|
||||
Self::classify_name_ref(&self.sema, &original_file, name_ref, parent);
|
||||
if let Some(NameRefKind::Path(path_ctx)) = &mut nameref_ctx.kind {
|
||||
let (mut nameref_ctx, _) =
|
||||
Self::classify_name_ref(&self.sema, &original_file, name_ref, parent)?;
|
||||
if let NameRefKind::Path(path_ctx) = &mut nameref_ctx.kind {
|
||||
path_ctx.kind = PathKind::Derive {
|
||||
existing_derives: self
|
||||
.sema
|
||||
|
@ -427,19 +427,14 @@ impl<'a> CompletionContext<'a> {
|
|||
}
|
||||
ast::NameLike::NameRef(name_ref) => {
|
||||
let parent = name_ref.syntax().parent()?;
|
||||
let (nameref_ctx, pat_ctx, qualifier_ctx) =
|
||||
Self::classify_name_ref(&self.sema, &original_file, name_ref, parent.clone());
|
||||
let (nameref_ctx, qualifier_ctx) =
|
||||
Self::classify_name_ref(&self.sema, &original_file, name_ref, parent.clone())?;
|
||||
|
||||
if !matches!(nameref_ctx.kind, Some(NameRefKind::Path(_))) {
|
||||
// FIXME: Pattern context should probably be part of ident_ctx
|
||||
self.pattern_ctx = pat_ctx;
|
||||
}
|
||||
self.qualifier_ctx = qualifier_ctx;
|
||||
self.ident_ctx = IdentContext::NameRef(nameref_ctx);
|
||||
}
|
||||
ast::NameLike::Name(name) => {
|
||||
let (name_ctx, pat_ctx) = Self::classify_name(&self.sema, original_file, name)?;
|
||||
self.pattern_ctx = pat_ctx;
|
||||
let name_ctx = Self::classify_name(&self.sema, original_file, name)?;
|
||||
self.ident_ctx = IdentContext::Name(name_ctx);
|
||||
}
|
||||
}
|
||||
|
@ -477,9 +472,8 @@ impl<'a> CompletionContext<'a> {
|
|||
_sema: &Semantics<RootDatabase>,
|
||||
original_file: &SyntaxNode,
|
||||
name: ast::Name,
|
||||
) -> Option<(NameContext, Option<PatternContext>)> {
|
||||
) -> Option<NameContext> {
|
||||
let parent = name.syntax().parent()?;
|
||||
let mut pat_ctx = None;
|
||||
let kind = match_ast! {
|
||||
match parent {
|
||||
ast::Const(_) => NameKind::Const,
|
||||
|
@ -487,15 +481,12 @@ impl<'a> CompletionContext<'a> {
|
|||
ast::Enum(_) => NameKind::Enum,
|
||||
ast::Fn(_) => NameKind::Function,
|
||||
ast::IdentPat(bind_pat) => {
|
||||
pat_ctx = Some({
|
||||
let mut pat_ctx = pattern_context_for(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());
|
||||
}
|
||||
pat_ctx
|
||||
});
|
||||
let mut pat_ctx = pattern_context_for(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());
|
||||
}
|
||||
|
||||
NameKind::IdentPat
|
||||
NameKind::IdentPat(pat_ctx)
|
||||
},
|
||||
ast::MacroDef(_) => NameKind::MacroDef,
|
||||
ast::MacroRules(_) => NameKind::MacroRules,
|
||||
|
@ -514,7 +505,7 @@ impl<'a> CompletionContext<'a> {
|
|||
}
|
||||
};
|
||||
let name = find_node_at_offset(&original_file, name.syntax().text_range().start());
|
||||
Some((NameContext { name, kind }, pat_ctx))
|
||||
Some(NameContext { name, kind })
|
||||
}
|
||||
|
||||
fn classify_name_ref(
|
||||
|
@ -522,20 +513,19 @@ impl<'a> CompletionContext<'a> {
|
|||
original_file: &SyntaxNode,
|
||||
name_ref: ast::NameRef,
|
||||
parent: SyntaxNode,
|
||||
) -> (NameRefContext, Option<PatternContext>, QualifierCtx) {
|
||||
) -> Option<(NameRefContext, QualifierCtx)> {
|
||||
let nameref = find_node_at_offset(&original_file, name_ref.syntax().text_range().start());
|
||||
|
||||
let mut res = (NameRefContext { nameref, kind: None }, None, QualifierCtx::default());
|
||||
let (nameref_ctx, pattern_ctx, qualifier_ctx) = &mut res;
|
||||
let make_res =
|
||||
|kind| (NameRefContext { nameref: nameref.clone(), kind }, Default::default());
|
||||
|
||||
if let Some(record_field) = ast::RecordExprField::for_field_name(&name_ref) {
|
||||
nameref_ctx.kind =
|
||||
find_node_in_file_compensated(original_file, &record_field.parent_record_lit())
|
||||
.map(NameRefKind::RecordExpr);
|
||||
return res;
|
||||
return find_node_in_file_compensated(original_file, &record_field.parent_record_lit())
|
||||
.map(NameRefKind::RecordExpr)
|
||||
.map(make_res);
|
||||
}
|
||||
if let Some(record_field) = ast::RecordPatField::for_field_name_ref(&name_ref) {
|
||||
*pattern_ctx = Some(PatternContext {
|
||||
let kind = NameRefKind::Pattern(PatternContext {
|
||||
param_ctx: None,
|
||||
has_type_ascription: false,
|
||||
ref_token: None,
|
||||
|
@ -549,7 +539,7 @@ impl<'a> CompletionContext<'a> {
|
|||
record_field.parent_record_pat().clone().into(),
|
||||
)
|
||||
});
|
||||
return res;
|
||||
return Some(make_res(kind));
|
||||
}
|
||||
|
||||
let segment = match_ast! {
|
||||
|
@ -564,23 +554,23 @@ impl<'a> CompletionContext<'a> {
|
|||
},
|
||||
_ => false,
|
||||
};
|
||||
nameref_ctx.kind = Some(NameRefKind::DotAccess(DotAccess {
|
||||
let kind = NameRefKind::DotAccess(DotAccess {
|
||||
receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)),
|
||||
kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal },
|
||||
receiver
|
||||
}));
|
||||
return res;
|
||||
});
|
||||
return Some(make_res(kind));
|
||||
},
|
||||
ast::MethodCallExpr(method) => {
|
||||
let receiver = find_opt_node_in_file(original_file, method.receiver());
|
||||
nameref_ctx.kind = Some(NameRefKind::DotAccess(DotAccess {
|
||||
let kind = NameRefKind::DotAccess(DotAccess {
|
||||
receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)),
|
||||
kind: DotAccessKind::Method { has_parens: method.arg_list().map_or(false, |it| it.l_paren_token().is_some()) },
|
||||
receiver
|
||||
}));
|
||||
return res;
|
||||
});
|
||||
return Some(make_res(kind));
|
||||
},
|
||||
_ => return res,
|
||||
_ => return None,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -755,52 +745,47 @@ impl<'a> CompletionContext<'a> {
|
|||
};
|
||||
|
||||
// Infer the path kind
|
||||
let kind = path.syntax().parent().and_then(|it| {
|
||||
match_ast! {
|
||||
match it {
|
||||
ast::PathType(it) => Some(make_path_kind_type(it.into())),
|
||||
let parent = path.syntax().parent()?;
|
||||
let kind = match_ast! {
|
||||
match parent {
|
||||
ast::PathType(it) => make_path_kind_type(it.into()),
|
||||
ast::PathExpr(it) => {
|
||||
if let Some(p) = it.syntax().parent() {
|
||||
if ast::ExprStmt::can_cast(p.kind()) {
|
||||
if let Some(kind) = inbetween_body_and_decl_check(p) {
|
||||
nameref_ctx.kind = Some(NameRefKind::Keyword(kind));
|
||||
return None;
|
||||
return Some(make_res(NameRefKind::Keyword(kind)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
|
||||
|
||||
Some(make_path_kind_expr(it.into()))
|
||||
make_path_kind_expr(it.into())
|
||||
},
|
||||
ast::TupleStructPat(it) => {
|
||||
path_ctx.has_call_parens = true;
|
||||
*pattern_ctx = Some(pattern_context_for(original_file, it.into()));
|
||||
Some(PathKind::Pat)
|
||||
PathKind::Pat { pat_ctx: pattern_context_for(original_file, it.into())}
|
||||
},
|
||||
ast::RecordPat(it) => {
|
||||
path_ctx.has_call_parens = true;
|
||||
*pattern_ctx = Some(pattern_context_for(original_file, it.into()));
|
||||
Some(PathKind::Pat)
|
||||
PathKind::Pat { pat_ctx: pattern_context_for(original_file, it.into())}
|
||||
},
|
||||
ast::PathPat(it) => {
|
||||
*pattern_ctx = Some(pattern_context_for(original_file, it.into()));
|
||||
Some(PathKind::Pat)
|
||||
PathKind::Pat { pat_ctx: pattern_context_for(original_file, it.into())}
|
||||
},
|
||||
ast::MacroCall(it) => {
|
||||
// A macro call in this position is usually a result of parsing recovery, so check that
|
||||
if let Some(kind) = inbetween_body_and_decl_check(it.syntax().clone()) {
|
||||
nameref_ctx.kind = Some(NameRefKind::Keyword(kind));
|
||||
return None;
|
||||
return Some(make_res(NameRefKind::Keyword(kind)));
|
||||
}
|
||||
|
||||
path_ctx.has_macro_bang = it.excl_token().is_some();
|
||||
let parent = it.syntax().parent()?;
|
||||
// Any path in an item list will be treated as a macro call by the parser
|
||||
let res = match_ast! {
|
||||
match_ast! {
|
||||
match parent {
|
||||
ast::MacroExpr(expr) => make_path_kind_expr(expr.into()),
|
||||
ast::MacroPat(_) => PathKind::Pat,
|
||||
ast::MacroPat(it) => PathKind::Pat { pat_ctx: pattern_context_for(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() {
|
||||
|
@ -821,10 +806,9 @@ impl<'a> CompletionContext<'a> {
|
|||
ast::SourceFile(_) => PathKind::Item { kind: ItemListKind::SourceFile },
|
||||
_ => return None,
|
||||
}
|
||||
};
|
||||
Some(res)
|
||||
}
|
||||
},
|
||||
ast::Meta(meta) => (|| {
|
||||
ast::Meta(meta) => {
|
||||
let attr = meta.parent_attr()?;
|
||||
let kind = attr.kind();
|
||||
let attached = attr.syntax().parent()?;
|
||||
|
@ -835,24 +819,19 @@ impl<'a> CompletionContext<'a> {
|
|||
} else {
|
||||
Some(attached.kind())
|
||||
};
|
||||
Some(PathKind::Attr {
|
||||
PathKind::Attr {
|
||||
kind,
|
||||
annotated_item_kind,
|
||||
})
|
||||
})(),
|
||||
ast::Visibility(it) => Some(PathKind::Vis { has_in_token: it.in_token().is_some() }),
|
||||
ast::UseTree(_) => Some(PathKind::Use),
|
||||
}
|
||||
},
|
||||
ast::Visibility(it) => PathKind::Vis { has_in_token: it.in_token().is_some() },
|
||||
ast::UseTree(_) => PathKind::Use,
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
match kind {
|
||||
Some(kind) => path_ctx.kind = kind,
|
||||
// unresolved path kind, so this isn't really a path we should be completing,
|
||||
// just some random identifier which might be in keyword position
|
||||
None => return res,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
path_ctx.kind = kind;
|
||||
path_ctx.has_type_args = segment.generic_arg_list().is_some();
|
||||
|
||||
// calculate the qualifier context
|
||||
|
@ -893,6 +872,7 @@ impl<'a> CompletionContext<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
let mut qualifier_ctx = QualifierCtx::default();
|
||||
if path_ctx.is_trivial_path() {
|
||||
// fetch the full expression that may have qualifiers attached to it
|
||||
let top_node = match path_ctx.kind {
|
||||
|
@ -937,8 +917,8 @@ impl<'a> CompletionContext<'a> {
|
|||
if ![T![;], T!['}'], T!['{']].contains(&prev.kind()) {
|
||||
// This was inferred to be an item position path, but it seems
|
||||
// to be part of some other broken node which leaked into an item
|
||||
// list, so return without setting the path context
|
||||
return res;
|
||||
// list
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -946,8 +926,7 @@ impl<'a> CompletionContext<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
nameref_ctx.kind = Some(NameRefKind::Path(path_ctx));
|
||||
res
|
||||
Some((NameRefContext { nameref, kind: NameRefKind::Path(path_ctx) }, qualifier_ctx))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ use text_edit::TextEdit;
|
|||
|
||||
use crate::{
|
||||
completions::Completions,
|
||||
context::{CompletionContext, IdentContext, NameRefContext, NameRefKind},
|
||||
context::{CompletionContext, IdentContext, NameKind, NameRefContext, NameRefKind},
|
||||
};
|
||||
|
||||
pub use crate::{
|
||||
|
@ -151,10 +151,8 @@ pub fn completions(
|
|||
|
||||
// prevent `(` from triggering unwanted completion noise
|
||||
if trigger_character == Some('(') {
|
||||
if let IdentContext::NameRef(NameRefContext {
|
||||
kind: Some(NameRefKind::Path(path_ctx)),
|
||||
..
|
||||
}) = &ctx.ident_ctx
|
||||
if let IdentContext::NameRef(NameRefContext { kind: NameRefKind::Path(path_ctx), .. }) =
|
||||
&ctx.ident_ctx
|
||||
{
|
||||
completions::vis::complete_vis_path(&mut completions, ctx, path_ctx);
|
||||
}
|
||||
|
@ -170,6 +168,12 @@ pub fn completions(
|
|||
completions::field::complete_field_list_record_variant(acc, ctx, name_ctx);
|
||||
completions::item_list::trait_impl::complete_trait_impl_name(acc, ctx, name_ctx);
|
||||
completions::mod_::complete_mod(acc, ctx, name_ctx);
|
||||
if let NameKind::IdentPat(pattern_ctx) = &name_ctx.kind {
|
||||
completions::flyimport::import_on_the_fly_pat(acc, ctx, pattern_ctx);
|
||||
completions::fn_param::complete_fn_param(acc, ctx, pattern_ctx);
|
||||
completions::pattern::complete_pattern(acc, ctx, pattern_ctx);
|
||||
completions::record::complete_record_pattern_fields(acc, ctx, pattern_ctx);
|
||||
}
|
||||
}
|
||||
IdentContext::NameRef(name_ctx @ NameRefContext { kind, .. }) => {
|
||||
completions::item_list::trait_impl::complete_trait_impl_name_ref(
|
||||
|
@ -178,7 +182,7 @@ pub fn completions(
|
|||
completions::use_::complete_use_tree(acc, ctx, name_ctx);
|
||||
|
||||
match kind {
|
||||
Some(NameRefKind::Path(path_ctx)) => {
|
||||
NameRefKind::Path(path_ctx) => {
|
||||
completions::attribute::complete_attribute(acc, ctx, path_ctx);
|
||||
completions::attribute::complete_derive(acc, ctx, path_ctx);
|
||||
completions::dot::complete_undotted_self(acc, ctx, path_ctx);
|
||||
|
@ -194,22 +198,27 @@ pub fn completions(
|
|||
completions::snippet::complete_item_snippet(acc, ctx, path_ctx);
|
||||
completions::vis::complete_vis_path(acc, ctx, path_ctx);
|
||||
}
|
||||
Some(NameRefKind::DotAccess(dot_access)) => {
|
||||
NameRefKind::DotAccess(dot_access) => {
|
||||
completions::flyimport::import_on_the_fly_dot(acc, ctx, dot_access);
|
||||
completions::dot::complete_dot(acc, ctx, dot_access);
|
||||
completions::postfix::complete_postfix(acc, ctx, dot_access);
|
||||
}
|
||||
Some(NameRefKind::Keyword(item)) => {
|
||||
NameRefKind::Keyword(item) => {
|
||||
completions::keyword::complete_special_keywords(acc, ctx, item);
|
||||
}
|
||||
Some(NameRefKind::RecordExpr(record_expr)) => {
|
||||
NameRefKind::RecordExpr(record_expr) => {
|
||||
completions::record::complete_record_expr_fields_record_expr(
|
||||
acc,
|
||||
ctx,
|
||||
record_expr,
|
||||
);
|
||||
}
|
||||
None => (),
|
||||
NameRefKind::Pattern(pattern_ctx) => {
|
||||
completions::flyimport::import_on_the_fly_pat(acc, ctx, pattern_ctx);
|
||||
completions::fn_param::complete_fn_param(acc, ctx, pattern_ctx);
|
||||
completions::pattern::complete_pattern(acc, ctx, pattern_ctx);
|
||||
completions::record::complete_record_pattern_fields(acc, ctx, pattern_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
IdentContext::Lifetime(lifetime_ctx) => {
|
||||
|
@ -225,13 +234,6 @@ pub fn completions(
|
|||
}
|
||||
IdentContext::UnexpandedAttrTT { .. } | IdentContext::String { .. } => (),
|
||||
}
|
||||
|
||||
if let Some(pattern_ctx) = &ctx.pattern_ctx {
|
||||
completions::flyimport::import_on_the_fly_pat(acc, ctx, pattern_ctx);
|
||||
completions::fn_param::complete_fn_param(acc, ctx, pattern_ctx);
|
||||
completions::pattern::complete_pattern(acc, ctx, pattern_ctx);
|
||||
completions::record::complete_record_pattern_fields(acc, ctx, pattern_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
Some(completions)
|
||||
|
|
|
@ -78,7 +78,7 @@ impl<'a> RenderContext<'a> {
|
|||
matches!(
|
||||
self.completion.ident_ctx,
|
||||
IdentContext::NameRef(NameRefContext {
|
||||
kind: Some(NameRefKind::Path(PathCompletionCtx { has_call_parens: true, .. })),
|
||||
kind: NameRefKind::Path(PathCompletionCtx { has_call_parens: true, .. }),
|
||||
..
|
||||
})
|
||||
)
|
||||
|
@ -218,7 +218,7 @@ fn render_resolution_(
|
|||
let ctx = ctx.import_to_add(import_to_add);
|
||||
return render_fn(ctx, Some(local_name), func);
|
||||
}
|
||||
ScopeDef::ModuleDef(Variant(var)) if ctx.completion.pattern_ctx.is_none() => {
|
||||
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) {
|
||||
return item;
|
||||
|
@ -293,11 +293,11 @@ fn render_resolution_simple_(
|
|||
let type_path_no_ty_args = matches!(
|
||||
ctx.completion.ident_ctx,
|
||||
IdentContext::NameRef(NameRefContext {
|
||||
kind: Some(NameRefKind::Path(PathCompletionCtx {
|
||||
kind: NameRefKind::Path(PathCompletionCtx {
|
||||
kind: PathKind::Type { .. },
|
||||
has_type_args: false,
|
||||
..
|
||||
})),
|
||||
}),
|
||||
..
|
||||
})
|
||||
) && ctx.completion.config.callable.is_some();
|
||||
|
|
|
@ -83,10 +83,10 @@ fn render(
|
|||
let qualified_path = matches!(
|
||||
ctx.completion.ident_ctx,
|
||||
IdentContext::NameRef(NameRefContext {
|
||||
kind: Some(NameRefKind::Path(PathCompletionCtx {
|
||||
kind: NameRefKind::Path(PathCompletionCtx {
|
||||
qualified: Qualified::With { .. },
|
||||
..
|
||||
})),
|
||||
}),
|
||||
..
|
||||
})
|
||||
);
|
||||
|
@ -262,24 +262,24 @@ fn params(
|
|||
let has_dot_receiver = match ctx.ident_ctx {
|
||||
IdentContext::NameRef(NameRefContext {
|
||||
kind:
|
||||
Some(NameRefKind::DotAccess(DotAccess {
|
||||
NameRefKind::DotAccess(DotAccess {
|
||||
kind: DotAccessKind::Method { has_parens: true },
|
||||
..
|
||||
})),
|
||||
}),
|
||||
..
|
||||
}) => return None,
|
||||
IdentContext::NameRef(NameRefContext {
|
||||
kind: Some(NameRefKind::DotAccess(DotAccess { .. })),
|
||||
kind: NameRefKind::DotAccess(DotAccess { .. }),
|
||||
..
|
||||
}) => true,
|
||||
IdentContext::NameRef(NameRefContext {
|
||||
kind:
|
||||
Some(NameRefKind::Path(
|
||||
NameRefKind::Path(
|
||||
PathCompletionCtx {
|
||||
kind: PathKind::Expr { .. }, has_call_parens: true, ..
|
||||
}
|
||||
| PathCompletionCtx { kind: PathKind::Use | PathKind::Type { .. }, .. },
|
||||
)),
|
||||
),
|
||||
..
|
||||
}) => return None,
|
||||
_ => false,
|
||||
|
|
|
@ -55,15 +55,14 @@ fn render(
|
|||
let mut kind = thing.kind(db);
|
||||
let should_add_parens = match &completion.ident_ctx {
|
||||
IdentContext::NameRef(NameRefContext {
|
||||
kind: Some(NameRefKind::Path(PathCompletionCtx { has_call_parens: true, .. })),
|
||||
kind: NameRefKind::Path(PathCompletionCtx { has_call_parens: true, .. }),
|
||||
..
|
||||
}) => false,
|
||||
IdentContext::NameRef(NameRefContext {
|
||||
kind:
|
||||
Some(NameRefKind::Path(PathCompletionCtx {
|
||||
kind: PathKind::Use | PathKind::Type { .. },
|
||||
..
|
||||
})),
|
||||
NameRefKind::Path(PathCompletionCtx {
|
||||
kind: PathKind::Use | PathKind::Type { .. }, ..
|
||||
}),
|
||||
..
|
||||
}) => false,
|
||||
_ => true,
|
||||
|
|
|
@ -35,7 +35,7 @@ fn render(
|
|||
|
||||
let needs_bang = match &completion.ident_ctx {
|
||||
IdentContext::NameRef(NameRefContext {
|
||||
kind: Some(NameRefKind::Path(PathCompletionCtx { kind, has_macro_bang, .. })),
|
||||
kind: NameRefKind::Path(PathCompletionCtx { kind, has_macro_bang, .. }),
|
||||
..
|
||||
}) => is_fn_like && *kind != PathKind::Use && !has_macro_bang,
|
||||
_ => is_fn_like,
|
||||
|
|
|
@ -7,7 +7,8 @@ use syntax::SmolStr;
|
|||
|
||||
use crate::{
|
||||
context::{
|
||||
IdentContext, NameRefContext, NameRefKind, ParamKind, PathCompletionCtx, PatternContext,
|
||||
IdentContext, NameContext, NameKind, NameRefContext, NameRefKind, ParamKind,
|
||||
PathCompletionCtx, PathKind, PatternContext,
|
||||
},
|
||||
render::{variant::visible_fields, RenderContext},
|
||||
CompletionItem, CompletionItemKind,
|
||||
|
@ -82,7 +83,7 @@ fn render_pat(
|
|||
let has_call_parens = matches!(
|
||||
ctx.completion.ident_ctx,
|
||||
IdentContext::NameRef(NameRefContext {
|
||||
kind: Some(NameRefKind::Path(PathCompletionCtx { has_call_parens: true, .. })),
|
||||
kind: NameRefKind::Path(PathCompletionCtx { has_call_parens: true, .. }),
|
||||
..
|
||||
})
|
||||
);
|
||||
|
@ -97,14 +98,27 @@ fn render_pat(
|
|||
_ => name.to_owned(),
|
||||
};
|
||||
|
||||
if matches!(
|
||||
ctx.completion.pattern_ctx,
|
||||
Some(PatternContext {
|
||||
param_ctx: Some((.., ParamKind::Function(_))),
|
||||
has_type_ascription: false,
|
||||
..
|
||||
}) if !has_call_parens
|
||||
) {
|
||||
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,
|
||||
..
|
||||
})
|
||||
);
|
||||
if needs_ascription {
|
||||
pat.push(':');
|
||||
pat.push(' ');
|
||||
pat.push_str(name);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use expect_test::{expect, Expect};
|
||||
|
||||
use crate::{
|
||||
context::NameRefKind,
|
||||
context::{IdentContext, NameContext, NameKind, NameRefKind},
|
||||
tests::{check_edit, check_edit_with_config, TEST_CONFIG},
|
||||
};
|
||||
|
||||
|
@ -11,17 +11,22 @@ fn check(ra_fixture: &str, expect: Expect) {
|
|||
let ctx = crate::context::CompletionContext::new(&db, position, &config).unwrap();
|
||||
|
||||
let mut acc = crate::completions::Completions::default();
|
||||
if let Some(pattern_ctx) = &ctx.pattern_ctx {
|
||||
crate::completions::flyimport::import_on_the_fly_pat(&mut acc, &ctx, pattern_ctx);
|
||||
if let IdentContext::Name(NameContext { kind: NameKind::IdentPat(pat_ctx), .. }) =
|
||||
&ctx.ident_ctx
|
||||
{
|
||||
crate::completions::flyimport::import_on_the_fly_pat(&mut acc, &ctx, pat_ctx);
|
||||
}
|
||||
if let crate::context::IdentContext::NameRef(name_ref_ctx) = &ctx.ident_ctx {
|
||||
if let IdentContext::NameRef(name_ref_ctx) = &ctx.ident_ctx {
|
||||
match &name_ref_ctx.kind {
|
||||
Some(NameRefKind::Path(path)) => {
|
||||
NameRefKind::Path(path) => {
|
||||
crate::completions::flyimport::import_on_the_fly_path(&mut acc, &ctx, path);
|
||||
}
|
||||
Some(NameRefKind::DotAccess(dot_access)) => {
|
||||
NameRefKind::DotAccess(dot_access) => {
|
||||
crate::completions::flyimport::import_on_the_fly_dot(&mut acc, &ctx, dot_access);
|
||||
}
|
||||
NameRefKind::Pattern(pattern) => {
|
||||
crate::completions::flyimport::import_on_the_fly_pat(&mut acc, &ctx, pattern);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue