Introduce NameRefKind for completions

This commit is contained in:
Lukas Wirth 2022-06-17 10:45:19 +02:00
parent 7322a982f9
commit 6e07b17f69
12 changed files with 134 additions and 95 deletions

View file

@ -4,7 +4,8 @@ use ide_db::FxHashSet;
use crate::{ use crate::{
context::{ context::{
CompletionContext, DotAccess, DotAccessKind, NameRefContext, PathCompletionCtx, PathKind, CompletionContext, DotAccess, DotAccessKind, NameRefContext, NameRefKind,
PathCompletionCtx, PathKind,
}, },
CompletionItem, CompletionItemKind, Completions, CompletionItem, CompletionItemKind, Completions,
}; };
@ -13,7 +14,8 @@ use crate::{
pub(crate) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { pub(crate) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
let (dot_access, receiver_ty) = match ctx.nameref_ctx() { let (dot_access, receiver_ty) = match ctx.nameref_ctx() {
Some(NameRefContext { Some(NameRefContext {
dot_access: Some(access @ DotAccess { receiver_ty: Some(receiver_ty), .. }), kind:
Some(NameRefKind::DotAccess(access @ DotAccess { receiver_ty: Some(receiver_ty), .. })),
.. ..
}) => (access, &receiver_ty.original), }) => (access, &receiver_ty.original),
_ => return complete_undotted_self(acc, ctx), _ => return complete_undotted_self(acc, ctx),

View file

@ -5,7 +5,7 @@ use ide_db::FxHashSet;
use syntax::T; use syntax::T;
use crate::{ use crate::{
context::{NameRefContext, PathCompletionCtx, PathKind, PathQualifierCtx}, context::{NameRefContext, NameRefKind, PathCompletionCtx, PathKind, PathQualifierCtx},
CompletionContext, Completions, CompletionContext, Completions,
}; };
@ -21,24 +21,29 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
after_if_expr, after_if_expr,
wants_mut_token, wants_mut_token,
) = match ctx.nameref_ctx() { ) = match ctx.nameref_ctx() {
Some(NameRefContext { Some(&NameRefContext {
path_ctx:
Some(PathCompletionCtx {
kind: kind:
PathKind::Expr { in_block_expr, in_loop_body, after_if_expr, ref_expr_parent }, Some(NameRefKind::Path(PathCompletionCtx {
kind:
PathKind::Expr {
in_block_expr,
in_loop_body,
after_if_expr,
ref ref_expr_parent,
ref is_func_update,
},
is_absolute_path, is_absolute_path,
qualifier, ref qualifier,
.. ..
}), })),
record_expr,
.. ..
}) if ctx.qualifier_ctx.none() => ( }) if ctx.qualifier_ctx.none() => (
*is_absolute_path, is_absolute_path,
qualifier, qualifier,
*in_block_expr, in_block_expr,
*in_loop_body, in_loop_body,
record_expr.as_ref().map_or(false, |&(_, it)| it), is_func_update.is_some(),
*after_if_expr, after_if_expr,
ref_expr_parent.as_ref().map(|it| it.mut_token().is_none()).unwrap_or(false), ref_expr_parent.as_ref().map(|it| it.mut_token().is_none()).unwrap_or(false),
), ),
_ => return, _ => return,

View file

@ -1,7 +1,10 @@
//! Completion of field list position. //! Completion of field list position.
use crate::{ use crate::{
context::{IdentContext, NameContext, NameKind, NameRefContext, PathCompletionCtx, PathKind}, context::{
IdentContext, NameContext, NameKind, NameRefContext, NameRefKind, PathCompletionCtx,
PathKind,
},
CompletionContext, Completions, CompletionContext, Completions,
}; };
@ -9,8 +12,8 @@ pub(crate) fn complete_field_list(acc: &mut Completions, ctx: &CompletionContext
match &ctx.ident_ctx { match &ctx.ident_ctx {
IdentContext::Name(NameContext { kind: NameKind::RecordField, .. }) IdentContext::Name(NameContext { kind: NameKind::RecordField, .. })
| IdentContext::NameRef(NameRefContext { | IdentContext::NameRef(NameRefContext {
path_ctx: kind:
Some(PathCompletionCtx { Some(NameRefKind::Path(PathCompletionCtx {
has_macro_bang: false, has_macro_bang: false,
is_absolute_path: false, is_absolute_path: false,
qualifier: None, qualifier: None,
@ -18,7 +21,7 @@ pub(crate) fn complete_field_list(acc: &mut Completions, ctx: &CompletionContext
kind: PathKind::Type { in_tuple_struct: true }, kind: PathKind::Type { in_tuple_struct: true },
has_type_args: false, has_type_args: false,
.. ..
}), })),
.. ..
}) => { }) => {
if ctx.qualifier_ctx.vis_node.is_none() { if ctx.qualifier_ctx.vis_node.is_none() {

View file

@ -8,7 +8,9 @@ use itertools::Itertools;
use syntax::{AstNode, SyntaxNode, T}; use syntax::{AstNode, SyntaxNode, T};
use crate::{ use crate::{
context::{CompletionContext, NameRefContext, PathCompletionCtx, PathKind, PatternContext}, context::{
CompletionContext, NameRefContext, NameRefKind, PathCompletionCtx, PathKind, PatternContext,
},
patterns::ImmediateLocation, patterns::ImmediateLocation,
render::{render_resolution_with_import, RenderContext}, render::{render_resolution_with_import, RenderContext},
}; };
@ -110,20 +112,21 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext)
if !ctx.config.enable_imports_on_the_fly { if !ctx.config.enable_imports_on_the_fly {
return None; return None;
} }
let path_kind = match ctx.nameref_ctx() { let path_kind = match dbg!(ctx.nameref_ctx()) {
Some(NameRefContext { path_ctx: Some(PathCompletionCtx { kind, .. }), .. }) Some(NameRefContext {
if matches!( kind:
kind, Some(NameRefKind::Path(PathCompletionCtx {
PathKind::Expr { .. } kind:
kind @ (PathKind::Expr { .. }
| PathKind::Type { .. } | PathKind::Type { .. }
| PathKind::Attr { .. } | PathKind::Attr { .. }
| PathKind::Derive | PathKind::Derive
| PathKind::Pat | PathKind::Pat),
) => ..
{ })),
Some(kind) ..
} }) => Some(kind),
Some(NameRefContext { dot_access: Some(_), .. }) => None, Some(NameRefContext { kind: Some(NameRefKind::DotAccess(_)), .. }) => None,
None if matches!(ctx.pattern_ctx, Some(PatternContext { record_pat: None, .. })) => { None if matches!(ctx.pattern_ctx, Some(PatternContext { record_pat: None, .. })) => {
Some(&PathKind::Pat) Some(&PathKind::Pat)
} }

View file

@ -44,8 +44,8 @@ use text_edit::TextEdit;
use crate::{ use crate::{
context::{ context::{
IdentContext, ItemListKind, NameContext, NameKind, NameRefContext, PathCompletionCtx, IdentContext, ItemListKind, NameContext, NameKind, NameRefContext, NameRefKind,
PathKind, PathCompletionCtx, PathKind,
}, },
CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance, Completions, CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance, Completions,
}; };
@ -106,14 +106,13 @@ fn completion_match(ctx: &CompletionContext) -> Option<(ImplCompletionKind, Text
} }
IdentContext::NameRef(NameRefContext { IdentContext::NameRef(NameRefContext {
nameref, nameref,
path_ctx: kind:
Some( Some(NameRefKind::Path(
path_ctx @ PathCompletionCtx { path_ctx @ PathCompletionCtx {
kind: PathKind::Item { kind: ItemListKind::TraitImpl }, kind: PathKind::Item { kind: ItemListKind::TraitImpl },
.. ..
}, },
), )),
..
}) if path_ctx.is_trivial_path() => Some(( }) if path_ctx.is_trivial_path() => Some((
ImplCompletionKind::All, ImplCompletionKind::All,
match nameref { match nameref {

View file

@ -4,11 +4,14 @@
use syntax::ast::Item; use syntax::ast::Item;
use crate::{context::NameRefContext, CompletionContext, Completions}; use crate::{
context::{NameRefContext, NameRefKind},
CompletionContext, Completions,
};
pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
let item = match ctx.nameref_ctx() { let item = match ctx.nameref_ctx() {
Some(NameRefContext { keyword: Some(item), record_expr: None, .. }) => item, Some(NameRefContext { kind: Some(NameRefKind::Keyword(item)), .. }) => item,
_ => return, _ => return,
}; };

View file

@ -13,7 +13,7 @@ use text_edit::TextEdit;
use crate::{ use crate::{
completions::postfix::format_like::add_format_like_completions, completions::postfix::format_like::add_format_like_completions,
context::{CompletionContext, DotAccess, DotAccessKind, NameRefContext}, context::{CompletionContext, DotAccess, DotAccessKind, NameRefContext, NameRefKind},
item::{Builder, CompletionRelevancePostfixMatch}, item::{Builder, CompletionRelevancePostfixMatch},
CompletionItem, CompletionItemKind, CompletionRelevance, Completions, SnippetScope, CompletionItem, CompletionItemKind, CompletionRelevance, Completions, SnippetScope,
}; };
@ -25,7 +25,13 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
let (dot_receiver, receiver_ty, receiver_is_ambiguous_float_literal) = match ctx.nameref_ctx() { let (dot_receiver, receiver_ty, receiver_is_ambiguous_float_literal) = match ctx.nameref_ctx() {
Some(NameRefContext { Some(NameRefContext {
dot_access: Some(DotAccess { receiver_ty: Some(ty), receiver: Some(it), kind, .. }), kind:
Some(NameRefKind::DotAccess(DotAccess {
receiver_ty: Some(ty),
receiver: Some(it),
kind,
..
})),
.. ..
}) => ( }) => (
it, it,

View file

@ -3,7 +3,7 @@ use ide_db::SymbolKind;
use syntax::{ast::Expr, T}; use syntax::{ast::Expr, T};
use crate::{ use crate::{
context::{NameRefContext, PatternContext}, context::{NameRefContext, NameRefKind, PathCompletionCtx, PathKind, PatternContext},
CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance, CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance,
CompletionRelevancePostfixMatch, Completions, CompletionRelevancePostfixMatch, Completions,
}; };
@ -13,8 +13,18 @@ pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) ->
&ctx.pattern_ctx &ctx.pattern_ctx
{ {
ctx.sema.record_pattern_missing_fields(record_pat) ctx.sema.record_pattern_missing_fields(record_pat)
} else if let Some(NameRefContext { record_expr: Some((record_expr, _)), .. }) = } else if let Some(NameRefContext {
ctx.nameref_ctx() kind:
Some(
NameRefKind::RecordExpr(record_expr)
| NameRefKind::Path(PathCompletionCtx {
kind: PathKind::Expr { is_func_update: Some(record_expr), .. },
qualifier: None,
..
}),
),
..
}) = ctx.nameref_ctx()
{ {
let ty = ctx.sema.type_of_expr(&Expr::RecordExpr(record_expr.clone())); let ty = ctx.sema.type_of_expr(&Expr::RecordExpr(record_expr.clone()));
@ -39,7 +49,7 @@ pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) ->
ty.original.impls_trait(ctx.db, default_trait, &[]) ty.original.impls_trait(ctx.db, default_trait, &[])
}); });
if impl_default_trait && !missing_fields.is_empty() && ctx.path_qual().is_none() { if impl_default_trait && !missing_fields.is_empty() {
let completion_text = "..Default::default()"; let completion_text = "..Default::default()";
let mut item = let mut item =
CompletionItem::new(SymbolKind::Field, ctx.source_range(), completion_text); CompletionItem::new(SymbolKind::Field, ctx.source_range(), completion_text);

View file

@ -5,7 +5,10 @@ use ide_db::{FxHashSet, SymbolKind};
use syntax::{ast, AstNode}; use syntax::{ast, AstNode};
use crate::{ use crate::{
context::{CompletionContext, NameRefContext, PathCompletionCtx, PathKind, PathQualifierCtx}, context::{
CompletionContext, NameRefContext, NameRefKind, PathCompletionCtx, PathKind,
PathQualifierCtx,
},
item::Builder, item::Builder,
CompletionItem, CompletionItemKind, CompletionRelevance, Completions, CompletionItem, CompletionItemKind, CompletionRelevance, Completions,
}; };
@ -13,8 +16,13 @@ use crate::{
pub(crate) fn complete_use_tree(acc: &mut Completions, ctx: &CompletionContext) { pub(crate) fn complete_use_tree(acc: &mut Completions, ctx: &CompletionContext) {
let (&is_absolute_path, qualifier, name_ref) = match ctx.nameref_ctx() { let (&is_absolute_path, qualifier, name_ref) = match ctx.nameref_ctx() {
Some(NameRefContext { Some(NameRefContext {
path_ctx: kind:
Some(PathCompletionCtx { kind: PathKind::Use, is_absolute_path, qualifier, .. }), Some(NameRefKind::Path(PathCompletionCtx {
kind: PathKind::Use,
is_absolute_path,
qualifier,
..
})),
nameref, nameref,
.. ..
}) => (is_absolute_path, qualifier, nameref), }) => (is_absolute_path, qualifier, nameref),

View file

@ -50,6 +50,7 @@ pub(super) enum PathKind {
in_loop_body: bool, in_loop_body: bool,
after_if_expr: bool, after_if_expr: bool,
ref_expr_parent: Option<ast::RefExpr>, ref_expr_parent: Option<ast::RefExpr>,
is_func_update: Option<ast::RecordExpr>,
}, },
Type { Type {
in_tuple_struct: bool, in_tuple_struct: bool,
@ -199,13 +200,17 @@ pub(super) enum NameKind {
pub(super) struct NameRefContext { pub(super) struct NameRefContext {
/// NameRef syntax in the original file /// NameRef syntax in the original file
pub(super) nameref: Option<ast::NameRef>, pub(super) nameref: Option<ast::NameRef>,
// FIXME: these fields are actually disjoint -> enum pub(super) kind: Option<NameRefKind>,
pub(super) dot_access: Option<DotAccess>, }
pub(super) path_ctx: Option<PathCompletionCtx>,
#[derive(Debug)]
pub(super) enum NameRefKind {
Path(PathCompletionCtx),
DotAccess(DotAccess),
/// Position where we are only interested in keyword completions /// Position where we are only interested in keyword completions
pub(super) keyword: Option<ast::Item>, Keyword(ast::Item),
/// The record expression this nameref is a field of /// The record expression this nameref is a field of
pub(super) record_expr: Option<(ast::RecordExpr, bool)>, RecordExpr(ast::RecordExpr),
} }
#[derive(Debug)] #[derive(Debug)]
@ -341,9 +346,10 @@ impl<'a> CompletionContext<'a> {
pub(crate) fn dot_receiver(&self) -> Option<&ast::Expr> { pub(crate) fn dot_receiver(&self) -> Option<&ast::Expr> {
match self.nameref_ctx() { match self.nameref_ctx() {
Some(NameRefContext { dot_access: Some(DotAccess { receiver, .. }), .. }) => { Some(NameRefContext {
receiver.as_ref() kind: Some(NameRefKind::DotAccess(DotAccess { receiver, .. })),
} ..
}) => receiver.as_ref(),
_ => None, _ => None,
} }
} }
@ -358,7 +364,10 @@ impl<'a> CompletionContext<'a> {
} }
pub(crate) fn path_context(&self) -> Option<&PathCompletionCtx> { pub(crate) fn path_context(&self) -> Option<&PathCompletionCtx> {
self.nameref_ctx().and_then(|ctx| ctx.path_ctx.as_ref()) self.nameref_ctx().and_then(|ctx| match &ctx.kind {
Some(NameRefKind::Path(path)) => Some(path),
_ => None,
})
} }
pub(crate) fn path_qual(&self) -> Option<&ast::Path> { pub(crate) fn path_qual(&self) -> Option<&ast::Path> {
@ -857,7 +866,7 @@ impl<'a> CompletionContext<'a> {
let parent = name_ref.syntax().parent()?; let parent = name_ref.syntax().parent()?;
let (mut nameref_ctx, _, _) = let (mut nameref_ctx, _, _) =
Self::classify_name_ref(&self.sema, &original_file, name_ref, parent); Self::classify_name_ref(&self.sema, &original_file, name_ref, parent);
if let Some(path_ctx) = &mut nameref_ctx.path_ctx { if let Some(NameRefKind::Path(path_ctx)) = &mut nameref_ctx.kind {
path_ctx.kind = PathKind::Derive; path_ctx.kind = PathKind::Derive;
} }
self.ident_ctx = IdentContext::NameRef(nameref_ctx); self.ident_ctx = IdentContext::NameRef(nameref_ctx);
@ -1026,23 +1035,13 @@ impl<'a> CompletionContext<'a> {
) -> (NameRefContext, Option<PatternContext>, QualifierCtx) { ) -> (NameRefContext, Option<PatternContext>, QualifierCtx) {
let nameref = find_node_at_offset(&original_file, name_ref.syntax().text_range().start()); let nameref = find_node_at_offset(&original_file, name_ref.syntax().text_range().start());
let mut res = ( let mut res = (NameRefContext { nameref, kind: None }, None, QualifierCtx::default());
NameRefContext {
dot_access: None,
path_ctx: None,
nameref,
record_expr: None,
keyword: None,
},
None,
QualifierCtx::default(),
);
let (nameref_ctx, pattern_ctx, qualifier_ctx) = &mut res; let (nameref_ctx, pattern_ctx, qualifier_ctx) = &mut res;
if let Some(record_field) = ast::RecordExprField::for_field_name(&name_ref) { if let Some(record_field) = ast::RecordExprField::for_field_name(&name_ref) {
nameref_ctx.record_expr = nameref_ctx.kind =
find_node_in_file_compensated(original_file, &record_field.parent_record_lit()) find_node_in_file_compensated(original_file, &record_field.parent_record_lit())
.zip(Some(false)); .map(NameRefKind::RecordExpr);
return res; return res;
} }
if let Some(record_field) = ast::RecordPatField::for_field_name_ref(&name_ref) { if let Some(record_field) = ast::RecordPatField::for_field_name_ref(&name_ref) {
@ -1075,20 +1074,20 @@ impl<'a> CompletionContext<'a> {
}, },
_ => false, _ => false,
}; };
nameref_ctx.dot_access = Some(DotAccess { nameref_ctx.kind = Some(NameRefKind::DotAccess(DotAccess {
receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)), receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)),
kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal }, kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal },
receiver receiver
}); }));
return res; return res;
}, },
ast::MethodCallExpr(method) => { ast::MethodCallExpr(method) => {
let receiver = find_in_original_file(method.receiver(), original_file); let receiver = find_in_original_file(method.receiver(), original_file);
nameref_ctx.dot_access = Some(DotAccess { nameref_ctx.kind = Some(NameRefKind::DotAccess(DotAccess {
receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)), 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()) }, kind: DotAccessKind::Method { has_parens: method.arg_list().map_or(false, |it| it.l_paren_token().is_some()) },
receiver receiver
}); }));
return res; return res;
}, },
_ => return res, _ => return res,
@ -1113,10 +1112,11 @@ impl<'a> CompletionContext<'a> {
}) })
.unwrap_or(false) .unwrap_or(false)
}; };
let mut fill_record_expr = |syn: &SyntaxNode| { let func_update_record = |syn: &SyntaxNode| {
if let Some(record_expr) = syn.ancestors().nth(2).and_then(ast::RecordExpr::cast) { if let Some(record_expr) = syn.ancestors().nth(2).and_then(ast::RecordExpr::cast) {
nameref_ctx.record_expr = find_node_in_file_compensated(original_file, &record_expr)
find_node_in_file_compensated(original_file, &record_expr).zip(Some(true)); } else {
None
} }
}; };
let after_if_expr = |node: SyntaxNode| { let after_if_expr = |node: SyntaxNode| {
@ -1172,22 +1172,21 @@ impl<'a> CompletionContext<'a> {
if let Some(p) = it.syntax().parent() { if let Some(p) = it.syntax().parent() {
if ast::ExprStmt::can_cast(p.kind()) { if ast::ExprStmt::can_cast(p.kind()) {
if let Some(kind) = inbetween_body_and_decl_check(p) { if let Some(kind) = inbetween_body_and_decl_check(p) {
nameref_ctx.keyword = Some(kind); nameref_ctx.kind = Some(NameRefKind::Keyword(kind));
return None; return None;
} }
} }
} }
fill_record_expr(it.syntax());
path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind())); path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
let in_block_expr = is_in_block(it.syntax()); let in_block_expr = is_in_block(it.syntax());
let in_loop_body = is_in_loop_body(it.syntax()); let in_loop_body = is_in_loop_body(it.syntax());
let after_if_expr = after_if_expr(it.syntax().clone()); let after_if_expr = after_if_expr(it.syntax().clone());
let ref_expr_parent = path.as_single_name_ref() let ref_expr_parent = path.as_single_name_ref()
.and_then(|_| it.syntax().parent()).and_then(ast::RefExpr::cast); .and_then(|_| it.syntax().parent()).and_then(ast::RefExpr::cast);
let is_func_update = func_update_record(it.syntax());
Some(PathKind::Expr { in_block_expr, in_loop_body, after_if_expr, ref_expr_parent }) Some(PathKind::Expr { in_block_expr, in_loop_body, after_if_expr, ref_expr_parent, is_func_update })
}, },
ast::TupleStructPat(it) => { ast::TupleStructPat(it) => {
path_ctx.has_call_parens = true; path_ctx.has_call_parens = true;
@ -1205,7 +1204,7 @@ impl<'a> CompletionContext<'a> {
}, },
ast::MacroCall(it) => { ast::MacroCall(it) => {
if let Some(kind) = inbetween_body_and_decl_check(it.syntax().clone()) { if let Some(kind) = inbetween_body_and_decl_check(it.syntax().clone()) {
nameref_ctx.keyword = Some(kind); nameref_ctx.kind = Some(NameRefKind::Keyword(kind));
return None; return None;
} }
@ -1236,10 +1235,10 @@ impl<'a> CompletionContext<'a> {
let in_loop_body = is_in_loop_body(it.syntax()); let in_loop_body = is_in_loop_body(it.syntax());
let in_block_expr = is_in_block(it.syntax()); let in_block_expr = is_in_block(it.syntax());
let after_if_expr = after_if_expr(it.syntax().clone()); let after_if_expr = after_if_expr(it.syntax().clone());
fill_record_expr(it.syntax());
let ref_expr_parent = path.as_single_name_ref() let ref_expr_parent = path.as_single_name_ref()
.and_then(|_| it.syntax().parent()).and_then(ast::RefExpr::cast); .and_then(|_| it.syntax().parent()).and_then(ast::RefExpr::cast);
PathKind::Expr { in_block_expr, in_loop_body, after_if_expr, ref_expr_parent } let is_func_update = func_update_record(it.syntax());
PathKind::Expr { in_block_expr, in_loop_body, after_if_expr, ref_expr_parent, is_func_update }
}); });
}, },
} }
@ -1365,7 +1364,7 @@ impl<'a> CompletionContext<'a> {
} }
} }
} }
nameref_ctx.path_ctx = Some(path_ctx); nameref_ctx.kind = Some(NameRefKind::Path(path_ctx));
res res
} }
} }

View file

@ -8,7 +8,8 @@ use syntax::SmolStr;
use crate::{ use crate::{
context::{ context::{
CompletionContext, DotAccess, DotAccessKind, NameRefContext, PathCompletionCtx, PathKind, CompletionContext, DotAccess, DotAccessKind, NameRefContext, NameRefKind,
PathCompletionCtx, PathKind,
}, },
item::{Builder, CompletionItem, CompletionItemKind, CompletionRelevance}, item::{Builder, CompletionItem, CompletionItemKind, CompletionRelevance},
render::{compute_exact_name_match, compute_ref_match, compute_type_match, RenderContext}, render::{compute_exact_name_match, compute_ref_match, compute_type_match, RenderContext},
@ -212,7 +213,10 @@ fn should_add_parens(ctx: &CompletionContext) -> bool {
if matches!( if matches!(
ctx.nameref_ctx(), ctx.nameref_ctx(),
Some(NameRefContext { Some(NameRefContext {
dot_access: Some(DotAccess { kind: DotAccessKind::Method { has_parens: true }, .. }), kind: Some(NameRefKind::DotAccess(DotAccess {
kind: DotAccessKind::Method { has_parens: true },
..
})),
.. ..
}) })
) { ) {

View file

@ -105,7 +105,6 @@ fn foo(f: Struct) {
#[test] #[test]
fn functional_update() { fn functional_update() {
// FIXME: This should filter out all completions that do not have the type `Foo` // FIXME: This should filter out all completions that do not have the type `Foo`
// FIXME: Fields should not show up after `.`
check( check(
r#" r#"
//- minicore:default //- minicore:default
@ -192,8 +191,6 @@ fn main() {
} }
"#, "#,
expect![[r#" expect![[r#"
fd foo1 u32
fd foo2 u32
fn default() (as Default) fn() -> Self fn default() (as Default) fn() -> Self
"#]], "#]],
); );