mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-29 06:23:25 +00:00
internal: Lift out item list path completions from (un)qualified_path
This commit is contained in:
parent
52a58f672e
commit
25d133e3b8
13 changed files with 97 additions and 68 deletions
|
@ -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_;
|
||||||
|
|
48
crates/ide-completion/src/completions/item_list.rs
Normal file
48
crates/ide-completion/src/completions/item_list.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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");
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
"#]],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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!(
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
"#]],
|
"#]],
|
||||||
|
|
|
@ -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(
|
||||||
|
|
Loading…
Reference in a new issue