internal: Lift out item list path completions from (un)qualified_path

This commit is contained in:
Lukas Wirth 2022-05-05 12:08:40 +02:00
parent 52a58f672e
commit 25d133e3b8
13 changed files with 97 additions and 68 deletions

View file

@ -6,6 +6,7 @@ pub(crate) mod extern_abi;
pub(crate) mod flyimport; pub(crate) mod flyimport;
pub(crate) mod fn_param; pub(crate) mod fn_param;
pub(crate) mod format_string; pub(crate) mod format_string;
pub(crate) mod item_list;
pub(crate) mod keyword; pub(crate) mod keyword;
pub(crate) mod lifetime; pub(crate) mod lifetime;
pub(crate) mod mod_; pub(crate) mod mod_;

View file

@ -0,0 +1,48 @@
//! Completion of paths and keywords at item list position.
use crate::{
completions::module_or_fn_macro,
context::{PathCompletionCtx, PathKind, PathQualifierCtx},
CompletionContext, Completions,
};
pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext) {
let _p = profile::span("complete_unqualified_path");
if ctx.is_path_disallowed() || ctx.has_unfinished_impl_or_trait_prev_sibling() {
return;
}
let (&is_absolute_path, qualifier) = match &ctx.path_context {
Some(PathCompletionCtx {
kind: Some(PathKind::Item), is_absolute_path, qualifier, ..
}) => (is_absolute_path, qualifier),
_ => return,
};
match qualifier {
Some(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_resolution(ctx, name, def);
}
}
}
if *is_super_chain {
acc.add_keyword(ctx, "super::");
}
}
None if is_absolute_path => {
acc.add_crate_roots(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);
}
}
}

View file

@ -40,7 +40,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
if let Some(PathKind::Vis { .. }) = ctx.path_kind() { if let Some(PathKind::Vis { .. }) = ctx.path_kind() {
return; return;
} }
if ctx.has_impl_or_trait_prev_sibling() { if ctx.has_unfinished_impl_or_trait_prev_sibling() {
add_keyword("where", "where"); add_keyword("where", "where");
if ctx.has_impl_prev_sibling() { if ctx.has_impl_prev_sibling() {
add_keyword("for", "for"); add_keyword("for", "for");

View file

@ -196,12 +196,13 @@ 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 // 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 if *is_absolute_path => acc.add_crate_roots(ctx),
None => { None => {
cov_mark::hit!(unqualified_path_only_modules_in_import);
ctx.process_all_names(&mut |name, res| { ctx.process_all_names(&mut |name, res| {
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res { // FIXME: properly filter here
if let ScopeDef::ModuleDef(_) = res {
acc.add_resolution(ctx, name, res); acc.add_resolution(ctx, name, res);
} }
}); });
acc.add_nameref_keywords_with_colon(ctx); acc.add_nameref_keywords_with_colon(ctx);
} }
} }

View file

@ -5,14 +5,12 @@ use ide_db::FxHashSet;
use syntax::ast; use syntax::ast;
use crate::{ use crate::{
completions::module_or_fn_macro,
context::{PathCompletionCtx, PathKind}, context::{PathCompletionCtx, PathKind},
patterns::ImmediateLocation,
CompletionContext, Completions, CompletionContext, Completions,
}; };
pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) { pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
if ctx.is_path_disallowed() || ctx.has_impl_or_trait_prev_sibling() { if ctx.is_path_disallowed() || ctx.has_unfinished_impl_or_trait_prev_sibling() {
return; return;
} }
if ctx.pattern_ctx.is_some() { if ctx.pattern_ctx.is_some() {
@ -54,26 +52,13 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
None => return, None => return,
}; };
match ctx.completion_location {
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
if let 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_resolution(ctx, name, def);
}
}
}
return;
}
_ => (),
}
match kind { match kind {
Some( Some(
PathKind::Pat PathKind::Pat
| PathKind::Attr { .. } | PathKind::Attr { .. }
| PathKind::Vis { .. } | PathKind::Vis { .. }
| PathKind::Use | PathKind::Use
| PathKind::Item
| PathKind::Derive, | PathKind::Derive,
) => { ) => {
return; return;

View file

@ -46,7 +46,7 @@ pub(crate) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionConte
if !(ctx.expects_item() || ctx.has_block_expr_parent()) if !(ctx.expects_item() || ctx.has_block_expr_parent())
|| ctx.previous_token_is(T![unsafe]) || ctx.previous_token_is(T![unsafe])
|| ctx.path_qual().is_some() || ctx.path_qual().is_some()
|| ctx.has_impl_or_trait_prev_sibling() || ctx.has_unfinished_impl_or_trait_prev_sibling()
{ {
return; return;
} }

View file

@ -547,12 +547,7 @@ impl Test for T {
type Test = fn $0; type Test = fn $0;
} }
", ",
expect![[r#" expect![[r#""#]],
sp Self
st T
tt Test
bt u32
"#]],
); );
} }

View file

@ -4,7 +4,6 @@ use hir::ScopeDef;
use syntax::{ast, AstNode}; use syntax::{ast, AstNode};
use crate::{ use crate::{
completions::module_or_fn_macro,
context::{PathCompletionCtx, PathKind}, context::{PathCompletionCtx, PathKind},
patterns::ImmediateLocation, patterns::ImmediateLocation,
CompletionContext, Completions, CompletionContext, Completions,
@ -12,14 +11,15 @@ use crate::{
pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
let _p = profile::span("complete_unqualified_path"); let _p = profile::span("complete_unqualified_path");
if ctx.is_path_disallowed() || ctx.has_impl_or_trait_prev_sibling() { if ctx.is_path_disallowed() || ctx.has_unfinished_impl_or_trait_prev_sibling() {
return; return;
} }
match ctx.path_context {
match &ctx.path_context {
Some(PathCompletionCtx { Some(PathCompletionCtx {
is_absolute_path: false, is_absolute_path: false,
qualifier: None, qualifier: None,
kind: None | Some(PathKind::Expr | PathKind::Type | PathKind::Item), kind: None | Some(PathKind::Expr | PathKind::Type),
.. ..
}) => (), }) => (),
_ => return, _ => return,
@ -28,15 +28,6 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
acc.add_nameref_keywords(ctx); acc.add_nameref_keywords(ctx);
match &ctx.completion_location { match &ctx.completion_location {
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
// only show macros in {Assoc}ItemList
ctx.process_all_names(&mut |name, def| {
if let Some(def) = module_or_fn_macro(ctx.db, def) {
acc.add_resolution(ctx, name, def);
}
});
return;
}
Some(ImmediateLocation::TypeBound) => { Some(ImmediateLocation::TypeBound) => {
ctx.process_all_names(&mut |name, res| { ctx.process_all_names(&mut |name, res| {
let add_resolution = match res { let add_resolution = match res {

View file

@ -270,13 +270,17 @@ impl<'a> CompletionContext<'a> {
|| matches!(self.name_ctx, Some(NameContext::RecordField)) || matches!(self.name_ctx, Some(NameContext::RecordField))
} }
pub(crate) fn has_impl_or_trait_prev_sibling(&self) -> bool { /// Whether the cursor is right after a trait or impl header.
/// trait Foo ident$0
// FIXME: This probably shouldn't exist
pub(crate) fn has_unfinished_impl_or_trait_prev_sibling(&self) -> bool {
matches!( matches!(
self.prev_sibling, self.prev_sibling,
Some(ImmediatePrevSibling::ImplDefType | ImmediatePrevSibling::TraitDefName) Some(ImmediatePrevSibling::ImplDefType | ImmediatePrevSibling::TraitDefName)
) )
} }
// FIXME: This probably shouldn't exist
pub(crate) fn has_impl_prev_sibling(&self) -> bool { pub(crate) fn has_impl_prev_sibling(&self) -> bool {
matches!(self.prev_sibling, Some(ImmediatePrevSibling::ImplDefType)) matches!(self.prev_sibling, Some(ImmediatePrevSibling::ImplDefType))
} }
@ -289,6 +293,7 @@ impl<'a> CompletionContext<'a> {
matches!(self.prev_sibling, Some(ImmediatePrevSibling::IfExpr)) matches!(self.prev_sibling, Some(ImmediatePrevSibling::IfExpr))
} }
// FIXME: This shouldn't exist
pub(crate) fn is_path_disallowed(&self) -> bool { pub(crate) fn is_path_disallowed(&self) -> bool {
self.previous_token_is(T![unsafe]) self.previous_token_is(T![unsafe])
|| matches!( || matches!(

View file

@ -155,6 +155,7 @@ pub fn completions(
completions::flyimport::import_on_the_fly(&mut acc, &ctx); completions::flyimport::import_on_the_fly(&mut acc, &ctx);
completions::fn_param::complete_fn_param(&mut acc, &ctx); completions::fn_param::complete_fn_param(&mut acc, &ctx);
completions::format_string::format_string(&mut acc, &ctx); completions::format_string::format_string(&mut acc, &ctx);
completions::item_list::complete_item_list(&mut acc, &ctx);
completions::inferred_type(&mut acc, &ctx); completions::inferred_type(&mut acc, &ctx);
completions::keyword::complete_expr_keyword(&mut acc, &ctx); completions::keyword::complete_expr_keyword(&mut acc, &ctx);
completions::lifetime::complete_label(&mut acc, &ctx); completions::lifetime::complete_label(&mut acc, &ctx);

View file

@ -95,7 +95,7 @@ fn after_struct_name() {
ma makro!() macro_rules! makro ma makro!() macro_rules! makro
md module md module
kw const kw const
kw crate kw crate::
kw enum kw enum
kw extern kw extern
kw fn kw fn
@ -104,10 +104,10 @@ fn after_struct_name() {
kw pub kw pub
kw pub(crate) kw pub(crate)
kw pub(super) kw pub(super)
kw self kw self::
kw static kw static
kw struct kw struct
kw super kw super::
kw trait kw trait
kw type kw type
kw union kw union
@ -129,7 +129,7 @@ fn after_fn_name() {
ma makro!() macro_rules! makro ma makro!() macro_rules! makro
md module md module
kw const kw const
kw crate kw crate::
kw enum kw enum
kw extern kw extern
kw fn kw fn
@ -138,10 +138,10 @@ fn after_fn_name() {
kw pub kw pub
kw pub(crate) kw pub(crate)
kw pub(super) kw pub(super)
kw self kw self::
kw static kw static
kw struct kw struct
kw super kw super::
kw trait kw trait
kw type kw type
kw union kw union

View file

@ -15,7 +15,7 @@ fn in_mod_item_list() {
expect![[r#" expect![[r#"
ma makro!() macro_rules! makro ma makro!() macro_rules! makro
kw const kw const
kw crate kw crate::
kw enum kw enum
kw extern kw extern
kw fn kw fn
@ -24,10 +24,10 @@ fn in_mod_item_list() {
kw pub kw pub
kw pub(crate) kw pub(crate)
kw pub(super) kw pub(super)
kw self kw self::
kw static kw static
kw struct kw struct
kw super kw super::
kw trait kw trait
kw type kw type
kw union kw union
@ -48,7 +48,7 @@ fn in_source_file_item_list() {
ma makro!() macro_rules! makro ma makro!() macro_rules! makro
md module md module
kw const kw const
kw crate kw crate::
kw enum kw enum
kw extern kw extern
kw fn kw fn
@ -57,10 +57,10 @@ fn in_source_file_item_list() {
kw pub kw pub
kw pub(crate) kw pub(crate)
kw pub(super) kw pub(super)
kw self kw self::
kw static kw static
kw struct kw struct
kw super kw super::
kw trait kw trait
kw type kw type
kw union kw union
@ -166,13 +166,13 @@ fn in_impl_assoc_item_list() {
ma makro!() macro_rules! makro ma makro!() macro_rules! makro
md module md module
kw const kw const
kw crate kw crate::
kw fn kw fn
kw pub kw pub
kw pub(crate) kw pub(crate)
kw pub(super) kw pub(super)
kw self kw self::
kw super kw super::
kw type kw type
kw unsafe kw unsafe
"#]], "#]],
@ -203,10 +203,10 @@ fn in_trait_assoc_item_list() {
ma makro!() macro_rules! makro ma makro!() macro_rules! makro
md module md module
kw const kw const
kw crate kw crate::
kw fn kw fn
kw self kw self::
kw super kw super::
kw type kw type
kw unsafe kw unsafe
"#]], "#]],
@ -240,13 +240,13 @@ impl Test for () {
md module md module
ta type Type1 = ta type Type1 =
kw const kw const
kw crate kw crate::
kw fn kw fn
kw pub kw pub
kw pub(crate) kw pub(crate)
kw pub(super) kw pub(super)
kw self kw self::
kw super kw super::
kw type kw type
kw unsafe kw unsafe
"#]], "#]],

View file

@ -394,6 +394,9 @@ fn foo() {
} }
"#, "#,
expect![[r#" expect![[r#"
fn foo() fn()
st Bar
bt u32
kw crate:: kw crate::
kw self:: kw self::
kw super:: kw super::
@ -403,7 +406,7 @@ fn foo() {
r#" r#"
struct Foo { bar: u32 } struct Foo { bar: u32 }
fn foo() { fn foo() {
match Foo { bar: 0 } { match (Foo { bar: 0 }) {
F$0 { bar } => {} F$0 { bar } => {}
} }
} }
@ -412,10 +415,9 @@ fn foo() {
fn foo() fn() fn foo() fn()
st Foo st Foo
bt u32 bt u32
kw crate kw crate::
kw return kw self::
kw self kw super::
kw super
"#]], "#]],
); );
check_empty( check_empty(