use crate::{
completions::module_or_attr,
- context::{CompletionContext, IdentContext, PathCompletionCtx, PathKind, PathQualifierCtx},
+ context::{
+ CompletionContext, IdentContext, PathCompletionCtx, PathKind, PathQualifierCtx, Qualified,
+ },
item::CompletionItem,
Completions,
};
}
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::");
}
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);
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::");
}
}
}
}
- 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))
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),
};
use crate::{
context::{
CompletionContext, DotAccess, DotAccessKind, NameRefContext, NameRefKind,
- PathCompletionCtx, PathKind,
+ PathCompletionCtx, PathKind, Qualified,
},
CompletionItem, CompletionItemKind, Completions,
};
match ctx.path_context() {
Some(
path_ctx @ PathCompletionCtx {
- is_absolute_path: false,
- qualifier: None,
+ qualified: Qualified::No,
kind: PathKind::Expr { .. },
..
},
use ide_db::FxHashSet;
use crate::{
- context::{NameRefContext, NameRefKind, PathCompletionCtx, PathKind, PathQualifierCtx},
+ context::{
+ NameRefContext, NameRefKind, PathCompletionCtx, PathKind, PathQualifierCtx, Qualified,
+ },
CompletionContext, Completions,
};
let _p = profile::span("complete_expr_path");
let (
- is_absolute_path,
- qualifier,
+ qualified,
in_block_expr,
in_loop_body,
is_func_update,
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(),
}
};
- 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
_ => (),
}
}
- 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())
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");
}
use crate::{
context::{
IdentContext, NameContext, NameKind, NameRefContext, NameRefKind, PathCompletionCtx,
- PathKind, TypeLocation,
+ PathKind, Qualified, TypeLocation,
},
CompletionContext, Completions,
};
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,
use crate::{
completions::module_or_fn_macro,
- context::{ItemListKind, PathCompletionCtx, PathKind, PathQualifierCtx},
+ context::{ItemListKind, PathCompletionCtx, PathKind, PathQualifierCtx, Qualified},
CompletionContext, Completions,
};
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,
};
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) {
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);
});
acc.add_nameref_keywords_with_colon(ctx);
}
- None => {}
+ Qualified::No => {}
}
}
use syntax::ast::Pat;
use crate::{
- context::{PathCompletionCtx, PathQualifierCtx, PatternRefutability},
+ context::{PathCompletionCtx, PathQualifierCtx, PatternRefutability, Qualified},
CompletionContext, Completions,
};
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::");
}
}
}
// 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 {
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,
};
NameRefKind::RecordExpr(record_expr)
| NameRefKind::Path(PathCompletionCtx {
kind: PathKind::Expr { is_func_update: Some(record_expr), .. },
- qualifier: None,
+ qualified: Qualified::No,
..
}),
),
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,
};
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,
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,
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,
};
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,
};
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
_ => (),
}
}
- 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| {
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::");
}
}
}
// 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 {
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
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);
}
- _ => {}
}
}
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,
PathCompletionCtx {
has_call_parens: false,
has_macro_bang: false,
- is_absolute_path: false,
- qualifier: None,
+ qualified: Qualified::No,
parent: None,
has_type_args: false,
..
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 {
}
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.
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,
};
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,
// 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;
}
}