internal: Collapse completion ctx path qualifier and is_absolute_path into enum

This commit is contained in:
Lukas Wirth 2022-06-17 16:36:22 +02:00
parent 85363d18e8
commit 531060f103
14 changed files with 141 additions and 151 deletions

View File

@ -18,7 +18,9 @@ use syntax::{
use crate::{
completions::module_or_attr,
context::{CompletionContext, IdentContext, PathCompletionCtx, PathKind, PathQualifierCtx},
context::{
CompletionContext, IdentContext, PathCompletionCtx, PathKind, PathQualifierCtx, Qualified,
},
item::CompletionItem,
Completions,
};
@ -72,18 +74,17 @@ pub(crate) fn complete_known_attribute_input(
}
pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) {
let (is_absolute_path, qualifier, is_inner, annotated_item_kind) = match ctx.path_context() {
let (qualified, is_inner, annotated_item_kind) = match ctx.path_context() {
Some(&PathCompletionCtx {
kind: PathKind::Attr { kind, annotated_item_kind },
is_absolute_path,
ref qualifier,
ref qualified,
..
}) => (is_absolute_path, qualifier, kind == AttrKind::Inner, annotated_item_kind),
}) => (qualified, kind == AttrKind::Inner, annotated_item_kind),
_ => return,
};
match qualifier {
Some(PathQualifierCtx { resolution, is_super_chain, .. }) => {
match qualified {
Qualified::With(PathQualifierCtx { resolution, is_super_chain, .. }) => {
if *is_super_chain {
acc.add_keyword(ctx, "super::");
}
@ -101,9 +102,9 @@ pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext)
return;
}
// fresh use tree with leading colon2, only show crate roots
None if is_absolute_path => acc.add_crate_roots(ctx),
Qualified::Absolute => acc.add_crate_roots(ctx),
// only show modules in a fresh UseTree
None => {
Qualified::No => {
ctx.process_all_names(&mut |name, def| {
if let Some(def) = module_or_attr(ctx.db, def) {
acc.add_resolution(ctx, name, def);

View File

@ -5,26 +5,21 @@ use itertools::Itertools;
use syntax::SmolStr;
use crate::{
context::{CompletionContext, PathCompletionCtx, PathKind, PathQualifierCtx},
context::{CompletionContext, PathCompletionCtx, PathKind, PathQualifierCtx, Qualified},
item::CompletionItem,
Completions,
};
pub(crate) fn complete_derive(acc: &mut Completions, ctx: &CompletionContext) {
let (qualifier, is_absolute_path) = match ctx.path_context() {
Some(&PathCompletionCtx {
kind: PathKind::Derive,
ref qualifier,
is_absolute_path,
..
}) => (qualifier, is_absolute_path),
let qualified = match ctx.path_context() {
Some(&PathCompletionCtx { kind: PathKind::Derive, ref qualified, .. }) => qualified,
_ => return,
};
let core = ctx.famous_defs().core();
match qualifier {
Some(PathQualifierCtx { resolution, is_super_chain, .. }) => {
match qualified {
Qualified::With(PathQualifierCtx { resolution, is_super_chain, .. }) => {
if *is_super_chain {
acc.add_keyword(ctx, "super::");
}
@ -47,9 +42,9 @@ pub(crate) fn complete_derive(acc: &mut Completions, ctx: &CompletionContext) {
}
}
}
None if is_absolute_path => acc.add_crate_roots(ctx),
Qualified::Absolute => acc.add_crate_roots(ctx),
// only show modules in a fresh UseTree
None => {
Qualified::No => {
ctx.process_all_names(&mut |name, def| {
let mac = match def {
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac))
@ -65,7 +60,7 @@ pub(crate) fn complete_derive(acc: &mut Completions, ctx: &CompletionContext) {
match (core, mac.module(ctx.db).krate()) {
// show derive dependencies for `core`/`std` derives
(Some(core), mac_krate) if core == mac_krate && qualifier.is_none() => {}
(Some(core), mac_krate) if core == mac_krate => {}
_ => return acc.add_resolution(ctx, name, def),
};

View File

@ -5,7 +5,7 @@ use ide_db::FxHashSet;
use crate::{
context::{
CompletionContext, DotAccess, DotAccessKind, NameRefContext, NameRefKind,
PathCompletionCtx, PathKind,
PathCompletionCtx, PathKind, Qualified,
},
CompletionItem, CompletionItemKind, Completions,
};
@ -50,8 +50,7 @@ fn complete_undotted_self(acc: &mut Completions, ctx: &CompletionContext) {
match ctx.path_context() {
Some(
path_ctx @ PathCompletionCtx {
is_absolute_path: false,
qualifier: None,
qualified: Qualified::No,
kind: PathKind::Expr { .. },
..
},

View File

@ -4,7 +4,9 @@ use hir::ScopeDef;
use ide_db::FxHashSet;
use crate::{
context::{NameRefContext, NameRefKind, PathCompletionCtx, PathKind, PathQualifierCtx},
context::{
NameRefContext, NameRefKind, PathCompletionCtx, PathKind, PathQualifierCtx, Qualified,
},
CompletionContext, Completions,
};
@ -12,8 +14,7 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
let _p = profile::span("complete_expr_path");
let (
is_absolute_path,
qualifier,
qualified,
in_block_expr,
in_loop_body,
is_func_update,
@ -33,14 +34,12 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
ref ref_expr_parent,
ref is_func_update,
},
is_absolute_path,
ref qualifier,
ref qualified,
..
})),
..
}) if ctx.qualifier_ctx.none() => (
is_absolute_path,
qualifier,
qualified,
in_block_expr,
in_loop_body,
is_func_update.is_some(),
@ -61,8 +60,8 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
}
};
match qualifier {
Some(PathQualifierCtx { is_infer_qualifier, resolution, .. }) => {
match qualified {
Qualified::With(PathQualifierCtx { is_infer_qualifier, resolution, .. }) => {
if *is_infer_qualifier {
ctx.traits_in_scope()
.0
@ -174,8 +173,8 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
_ => (),
}
}
None if is_absolute_path => acc.add_crate_roots(ctx),
None => {
Qualified::Absolute => acc.add_crate_roots(ctx),
Qualified::No => {
acc.add_nameref_keywords_with_colon(ctx);
if let Some(adt) =
ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())
@ -237,7 +236,7 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
add_keyword("true", "true");
add_keyword("false", "false");
if (in_condition && !is_absolute_path) || in_block_expr {
if in_condition || in_block_expr {
add_keyword("let", "let");
}

View File

@ -3,7 +3,7 @@
use crate::{
context::{
IdentContext, NameContext, NameKind, NameRefContext, NameRefKind, PathCompletionCtx,
PathKind, TypeLocation,
PathKind, Qualified, TypeLocation,
},
CompletionContext, Completions,
};
@ -15,8 +15,7 @@ pub(crate) fn complete_field_list(acc: &mut Completions, ctx: &CompletionContext
kind:
Some(NameRefKind::Path(PathCompletionCtx {
has_macro_bang: false,
is_absolute_path: false,
qualifier: None,
qualified: Qualified::No,
parent: None,
kind: PathKind::Type { location: TypeLocation::TupleField },
has_type_args: false,

View File

@ -2,7 +2,7 @@
use crate::{
completions::module_or_fn_macro,
context::{ItemListKind, PathCompletionCtx, PathKind, PathQualifierCtx},
context::{ItemListKind, PathCompletionCtx, PathKind, PathQualifierCtx, Qualified},
CompletionContext, Completions,
};
@ -16,23 +16,17 @@ pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext)
return;
}
let (&is_absolute_path, path_qualifier, kind, is_trivial_path) = match ctx.path_context() {
Some(
ctx @ PathCompletionCtx {
kind: PathKind::Item { kind },
is_absolute_path,
qualifier,
..
},
) => (is_absolute_path, qualifier, Some(kind), ctx.is_trivial_path()),
let (qualified, kind, is_trivial_path) = match ctx.path_context() {
Some(ctx @ PathCompletionCtx { kind: PathKind::Item { kind }, qualified, .. }) => {
(qualified, Some(kind), ctx.is_trivial_path())
}
Some(
ctx @ PathCompletionCtx {
kind: PathKind::Expr { in_block_expr: true, .. },
is_absolute_path,
qualifier,
qualified,
..
},
) => (is_absolute_path, qualifier, None, ctx.is_trivial_path()),
) => (qualified, None, ctx.is_trivial_path()),
_ => return,
};
@ -49,8 +43,8 @@ pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext)
return;
}
match path_qualifier {
Some(PathQualifierCtx { resolution, is_super_chain, .. }) => {
match qualified {
Qualified::With(PathQualifierCtx { resolution, is_super_chain, .. }) => {
if let Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) = resolution {
for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
if let Some(def) = module_or_fn_macro(ctx.db, def) {
@ -63,8 +57,8 @@ pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext)
acc.add_keyword(ctx, "super::");
}
}
None if is_absolute_path => acc.add_crate_roots(ctx),
None if ctx.qualifier_ctx.none() => {
Qualified::Absolute => acc.add_crate_roots(ctx),
Qualified::No if ctx.qualifier_ctx.none() => {
ctx.process_all_names(&mut |name, def| {
if let Some(def) = module_or_fn_macro(ctx.db, def) {
acc.add_resolution(ctx, name, def);
@ -72,7 +66,7 @@ pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext)
});
acc.add_nameref_keywords_with_colon(ctx);
}
None => {}
Qualified::No => {}
}
}

View File

@ -5,7 +5,7 @@ use ide_db::FxHashSet;
use syntax::ast::Pat;
use crate::{
context::{PathCompletionCtx, PathQualifierCtx, PatternRefutability},
context::{PathCompletionCtx, PathQualifierCtx, PatternRefutability, Qualified},
CompletionContext, Completions,
};
@ -111,10 +111,10 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
fn pattern_path_completion(
acc: &mut Completions,
ctx: &CompletionContext,
PathCompletionCtx { qualifier, is_absolute_path, .. }: &PathCompletionCtx,
PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
) {
match qualifier {
Some(PathQualifierCtx { resolution, is_super_chain, .. }) => {
match qualified {
Qualified::With(PathQualifierCtx { resolution, is_super_chain, .. }) => {
if *is_super_chain {
acc.add_keyword(ctx, "super::");
}
@ -197,8 +197,8 @@ fn pattern_path_completion(
}
}
// qualifier can only be none here if we are in a TuplePat or RecordPat in which case special characters have to follow the path
None if *is_absolute_path => acc.add_crate_roots(ctx),
None => {
Qualified::Absolute => acc.add_crate_roots(ctx),
Qualified::No => {
ctx.process_all_names(&mut |name, res| {
// FIXME: properly filter here
if let ScopeDef::ModuleDef(_) = res {

View File

@ -3,7 +3,9 @@ use ide_db::SymbolKind;
use syntax::{ast::Expr, T};
use crate::{
context::{NameRefContext, NameRefKind, PathCompletionCtx, PathKind, PatternContext},
context::{
NameRefContext, NameRefKind, PathCompletionCtx, PathKind, PatternContext, Qualified,
},
CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance,
CompletionRelevancePostfixMatch, Completions,
};
@ -19,7 +21,7 @@ pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) ->
NameRefKind::RecordExpr(record_expr)
| NameRefKind::Path(PathCompletionCtx {
kind: PathKind::Expr { is_func_update: Some(record_expr), .. },
qualifier: None,
qualified: Qualified::No,
..
}),
),

View File

@ -4,7 +4,7 @@ use hir::Documentation;
use ide_db::{imports::insert_use::ImportScope, SnippetCap};
use crate::{
context::{ItemListKind, PathCompletionCtx, PathKind},
context::{ItemListKind, PathCompletionCtx, PathKind, Qualified},
item::Builder,
CompletionContext, CompletionItem, CompletionItemKind, Completions, SnippetScope,
};
@ -18,8 +18,7 @@ fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str)
pub(crate) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionContext) {
let &can_be_stmt = match ctx.path_context() {
Some(PathCompletionCtx {
is_absolute_path: false,
qualifier: None,
qualified: Qualified::No,
kind: PathKind::Expr { in_block_expr, .. },
..
}) => in_block_expr,
@ -44,8 +43,7 @@ pub(crate) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionConte
pub(crate) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionContext) {
let path_kind = match ctx.path_context() {
Some(PathCompletionCtx {
is_absolute_path: false,
qualifier: None,
qualified: Qualified::No,
kind: kind @ (PathKind::Item { .. } | PathKind::Expr { in_block_expr: true, .. }),
..
}) => kind,

View File

@ -5,7 +5,10 @@ use ide_db::FxHashSet;
use syntax::{ast, AstNode};
use crate::{
context::{PathCompletionCtx, PathKind, PathQualifierCtx, TypeAscriptionTarget, TypeLocation},
context::{
PathCompletionCtx, PathKind, PathQualifierCtx, Qualified, TypeAscriptionTarget,
TypeLocation,
},
render::render_type_inference,
CompletionContext, Completions,
};
@ -13,13 +16,10 @@ use crate::{
pub(crate) fn complete_type_path(acc: &mut Completions, ctx: &CompletionContext) {
let _p = profile::span("complete_type_path");
let (&is_absolute_path, location, qualifier) = match ctx.path_context() {
Some(PathCompletionCtx {
kind: PathKind::Type { location },
is_absolute_path,
qualifier,
..
}) => (is_absolute_path, location, qualifier),
let (location, qualified) = match ctx.path_context() {
Some(PathCompletionCtx { kind: PathKind::Type { location }, qualified, .. }) => {
(location, qualified)
}
_ => return,
};
@ -54,8 +54,8 @@ pub(crate) fn complete_type_path(acc: &mut Completions, ctx: &CompletionContext)
hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
};
match qualifier {
Some(PathQualifierCtx { is_infer_qualifier, resolution, .. }) => {
match qualified {
Qualified::With(PathQualifierCtx { is_infer_qualifier, resolution, .. }) => {
if *is_infer_qualifier {
ctx.traits_in_scope()
.0
@ -151,8 +151,8 @@ pub(crate) fn complete_type_path(acc: &mut Completions, ctx: &CompletionContext)
_ => (),
}
}
None if is_absolute_path => acc.add_crate_roots(ctx),
None => {
Qualified::Absolute => acc.add_crate_roots(ctx),
Qualified::No => {
acc.add_nameref_keywords_with_colon(ctx);
if let TypeLocation::TypeBound = location {
ctx.process_all_names(&mut |name, res| {

View File

@ -7,30 +7,30 @@ use syntax::{ast, AstNode};
use crate::{
context::{
CompletionContext, NameRefContext, NameRefKind, PathCompletionCtx, PathKind,
PathQualifierCtx,
PathQualifierCtx, Qualified,
},
item::Builder,
CompletionItem, CompletionItemKind, CompletionRelevance, Completions,
};
pub(crate) fn complete_use_tree(acc: &mut Completions, ctx: &CompletionContext) {
let (&is_absolute_path, qualifier, name_ref) = match ctx.nameref_ctx() {
let (qualified, name_ref) = match ctx.nameref_ctx() {
Some(NameRefContext {
kind:
Some(NameRefKind::Path(PathCompletionCtx {
kind: PathKind::Use,
is_absolute_path,
qualifier,
..
})),
kind: Some(NameRefKind::Path(PathCompletionCtx { kind: PathKind::Use, qualified, .. })),
nameref,
..
}) => (is_absolute_path, qualifier, nameref),
}) => (qualified, nameref),
_ => return,
};
match qualifier {
Some(PathQualifierCtx { path, resolution, is_super_chain, use_tree_parent, .. }) => {
match qualified {
Qualified::With(PathQualifierCtx {
path,
resolution,
is_super_chain,
use_tree_parent,
..
}) => {
if *is_super_chain {
acc.add_keyword(ctx, "super::");
}
@ -105,12 +105,12 @@ pub(crate) fn complete_use_tree(acc: &mut Completions, ctx: &CompletionContext)
}
}
// fresh use tree with leading colon2, only show crate roots
None if is_absolute_path => {
Qualified::Absolute => {
cov_mark::hit!(use_tree_crate_roots_only);
acc.add_crate_roots(ctx);
}
// only show modules and non-std enum in a fresh UseTree
None => {
Qualified::No => {
cov_mark::hit!(unqualified_path_selected_only);
ctx.process_all_names(&mut |name, res| {
match res {

View File

@ -3,23 +3,20 @@
use hir::ScopeDef;
use crate::{
context::{CompletionContext, PathCompletionCtx, PathKind, PathQualifierCtx},
context::{CompletionContext, PathCompletionCtx, PathKind, PathQualifierCtx, Qualified},
Completions,
};
pub(crate) fn complete_vis_path(acc: &mut Completions, ctx: &CompletionContext) {
let (&is_absolute_path, qualifier, &has_in_token) = match ctx.path_context() {
Some(PathCompletionCtx {
kind: PathKind::Vis { has_in_token },
is_absolute_path,
qualifier,
..
}) => (is_absolute_path, qualifier, has_in_token),
let (qualified, &has_in_token) = match ctx.path_context() {
Some(PathCompletionCtx { kind: PathKind::Vis { has_in_token }, qualified, .. }) => {
(qualified, has_in_token)
}
_ => return,
};
match qualifier {
Some(PathQualifierCtx { resolution, is_super_chain, .. }) => {
match qualified {
Qualified::With(PathQualifierCtx { resolution, is_super_chain, .. }) => {
// Try completing next child module of the path that is still a parent of the current module
if let Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) = resolution {
let next_towards_current = ctx
@ -40,13 +37,13 @@ pub(crate) fn complete_vis_path(acc: &mut Completions, ctx: &CompletionContext)
acc.add_keyword(ctx, "super::");
}
}
None if !is_absolute_path => {
Qualified::Absolute => {}
Qualified::No => {
if !has_in_token {
cov_mark::hit!(kw_completion_in);
acc.add_keyword(ctx, "in");
}
acc.add_nameref_keywords(ctx);
}
_ => {}
}
}

View File

@ -57,10 +57,8 @@ pub(crate) struct PathCompletionCtx {
pub(super) has_call_parens: bool,
/// If this has a macro call bang !
pub(super) has_macro_bang: bool,
/// Whether this path stars with a `::`.
pub(super) is_absolute_path: bool,
/// The qualifier of the current path if it exists.
pub(super) qualifier: Option<PathQualifierCtx>,
/// The qualifier of the current path.
pub(super) qualified: Qualified,
/// The parent of the path we are completing.
pub(super) parent: Option<ast::Path>,
pub(super) kind: PathKind,
@ -75,8 +73,7 @@ impl PathCompletionCtx {
PathCompletionCtx {
has_call_parens: false,
has_macro_bang: false,
is_absolute_path: false,
qualifier: None,
qualified: Qualified::No,
parent: None,
has_type_args: false,
..
@ -147,6 +144,14 @@ pub(super) enum ItemListKind {
ExternBlock,
}
#[derive(Debug)]
pub(super) enum Qualified {
No,
With(PathQualifierCtx),
/// Whether the path is an absolute path
Absolute,
}
/// The path qualifier state of the path we are completing.
#[derive(Debug)]
pub(crate) struct PathQualifierCtx {
@ -400,7 +405,10 @@ impl<'a> CompletionContext<'a> {
}
pub(crate) fn path_qual(&self) -> Option<&ast::Path> {
self.path_context().and_then(|it| it.qualifier.as_ref().map(|it| &it.path))
self.path_context().and_then(|it| match &it.qualified {
Qualified::With(it) => Some(&it.path),
_ => None,
})
}
/// Checks if an item is visible and not `doc(hidden)` at the completion site.

View File

@ -13,7 +13,7 @@ use syntax::{
use crate::context::{
CompletionContext, DotAccess, DotAccessKind, IdentContext, ItemListKind, LifetimeContext,
LifetimeKind, NameContext, NameKind, NameRefContext, NameRefKind, ParamKind, PathCompletionCtx,
PathKind, PathQualifierCtx, PatternContext, PatternRefutability, QualifierCtx,
PathKind, PathQualifierCtx, PatternContext, PatternRefutability, Qualified, QualifierCtx,
TypeAscriptionTarget, TypeLocation, COMPLETION_MARKER,
};
@ -585,8 +585,7 @@ impl<'a> CompletionContext<'a> {
let mut path_ctx = PathCompletionCtx {
has_call_parens: false,
has_macro_bang: false,
is_absolute_path: false,
qualifier: None,
qualified: Qualified::No,
parent: path.parent_path(),
kind: PathKind::Item { kind: ItemListKind::SourceFile },
has_type_args: false,
@ -854,41 +853,40 @@ impl<'a> CompletionContext<'a> {
// calculate the qualifier context
if let Some((path, use_tree_parent)) = path_or_use_tree_qualifier(&path) {
if !use_tree_parent {
path_ctx.is_absolute_path =
path.top_path().segment().map_or(false, |it| it.coloncolon_token().is_some());
if !use_tree_parent && segment.coloncolon_token().is_some() {
path_ctx.qualified = Qualified::Absolute;
} else {
let path = path
.segment()
.and_then(|it| find_node_in_file(original_file, &it))
.map(|it| it.parent_path());
if let Some(path) = path {
let res = sema.resolve_path(&path);
let is_super_chain = iter::successors(Some(path.clone()), |p| p.qualifier())
.all(|p| p.segment().and_then(|s| s.super_token()).is_some());
// `<_>::$0`
let is_infer_qualifier = path.qualifier().is_none()
&& matches!(
path.segment().and_then(|it| it.kind()),
Some(ast::PathSegmentKind::Type {
type_ref: Some(ast::Type::InferType(_)),
trait_ref: None,
})
);
path_ctx.qualified = Qualified::With(PathQualifierCtx {
path,
resolution: res,
is_super_chain,
use_tree_parent,
is_infer_qualifier,
})
};
}
let path = path
.segment()
.and_then(|it| find_node_in_file(original_file, &it))
.map(|it| it.parent_path());
path_ctx.qualifier = path.map(|path| {
let res = sema.resolve_path(&path);
let is_super_chain = iter::successors(Some(path.clone()), |p| p.qualifier())
.all(|p| p.segment().and_then(|s| s.super_token()).is_some());
// `<_>::$0`
let is_infer_qualifier = path.qualifier().is_none()
&& matches!(
path.segment().and_then(|it| it.kind()),
Some(ast::PathSegmentKind::Type {
type_ref: Some(ast::Type::InferType(_)),
trait_ref: None,
})
);
PathQualifierCtx {
path,
resolution: res,
is_super_chain,
use_tree_parent,
is_infer_qualifier,
}
});
} else if let Some(segment) = path.segment() {
if segment.coloncolon_token().is_some() {
path_ctx.is_absolute_path = true;
path_ctx.qualified = Qualified::Absolute;
}
}