mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 21:05:02 +00:00
Introduce NameRefKind for completions
This commit is contained in:
parent
7322a982f9
commit
6e07b17f69
12 changed files with 134 additions and 95 deletions
|
@ -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),
|
||||||
|
|
|
@ -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:
|
kind:
|
||||||
Some(PathCompletionCtx {
|
Some(NameRefKind::Path(PathCompletionCtx {
|
||||||
kind:
|
kind:
|
||||||
PathKind::Expr { in_block_expr, in_loop_body, after_if_expr, ref_expr_parent },
|
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,
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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:
|
||||||
| PathKind::Type { .. }
|
kind @ (PathKind::Expr { .. }
|
||||||
| PathKind::Attr { .. }
|
| PathKind::Type { .. }
|
||||||
| PathKind::Derive
|
| PathKind::Attr { .. }
|
||||||
| PathKind::Pat
|
| PathKind::Derive
|
||||||
) =>
|
| PathKind::Pat),
|
||||||
{
|
..
|
||||||
Some(kind)
|
})),
|
||||||
}
|
..
|
||||||
Some(NameRefContext { dot_access: Some(_), .. }) => None,
|
}) => Some(kind),
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 },
|
||||||
|
..
|
||||||
|
})),
|
||||||
..
|
..
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -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
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue