mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 21:43:37 +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 fn_param;
|
||||
pub(crate) mod format_string;
|
||||
pub(crate) mod item_list;
|
||||
pub(crate) mod keyword;
|
||||
pub(crate) mod lifetime;
|
||||
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() {
|
||||
return;
|
||||
}
|
||||
if ctx.has_impl_or_trait_prev_sibling() {
|
||||
if ctx.has_unfinished_impl_or_trait_prev_sibling() {
|
||||
add_keyword("where", "where");
|
||||
if ctx.has_impl_prev_sibling() {
|
||||
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
|
||||
None if *is_absolute_path => acc.add_crate_roots(ctx),
|
||||
None => {
|
||||
cov_mark::hit!(unqualified_path_only_modules_in_import);
|
||||
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_nameref_keywords_with_colon(ctx);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,14 +5,12 @@ use ide_db::FxHashSet;
|
|||
use syntax::ast;
|
||||
|
||||
use crate::{
|
||||
completions::module_or_fn_macro,
|
||||
context::{PathCompletionCtx, PathKind},
|
||||
patterns::ImmediateLocation,
|
||||
CompletionContext, Completions,
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
if ctx.pattern_ctx.is_some() {
|
||||
|
@ -54,26 +52,13 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
|||
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 {
|
||||
Some(
|
||||
PathKind::Pat
|
||||
| PathKind::Attr { .. }
|
||||
| PathKind::Vis { .. }
|
||||
| PathKind::Use
|
||||
| PathKind::Item
|
||||
| PathKind::Derive,
|
||||
) => {
|
||||
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())
|
||||
|| ctx.previous_token_is(T![unsafe])
|
||||
|| ctx.path_qual().is_some()
|
||||
|| ctx.has_impl_or_trait_prev_sibling()
|
||||
|| ctx.has_unfinished_impl_or_trait_prev_sibling()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -547,12 +547,7 @@ impl Test for T {
|
|||
type Test = fn $0;
|
||||
}
|
||||
",
|
||||
expect![[r#"
|
||||
sp Self
|
||||
st T
|
||||
tt Test
|
||||
bt u32
|
||||
"#]],
|
||||
expect![[r#""#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ use hir::ScopeDef;
|
|||
use syntax::{ast, AstNode};
|
||||
|
||||
use crate::{
|
||||
completions::module_or_fn_macro,
|
||||
context::{PathCompletionCtx, PathKind},
|
||||
patterns::ImmediateLocation,
|
||||
CompletionContext, Completions,
|
||||
|
@ -12,14 +11,15 @@ use crate::{
|
|||
|
||||
pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
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;
|
||||
}
|
||||
match ctx.path_context {
|
||||
|
||||
match &ctx.path_context {
|
||||
Some(PathCompletionCtx {
|
||||
is_absolute_path: false,
|
||||
qualifier: None,
|
||||
kind: None | Some(PathKind::Expr | PathKind::Type | PathKind::Item),
|
||||
kind: None | Some(PathKind::Expr | PathKind::Type),
|
||||
..
|
||||
}) => (),
|
||||
_ => return,
|
||||
|
@ -28,15 +28,6 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
|||
acc.add_nameref_keywords(ctx);
|
||||
|
||||
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) => {
|
||||
ctx.process_all_names(&mut |name, res| {
|
||||
let add_resolution = match res {
|
||||
|
|
|
@ -270,13 +270,17 @@ impl<'a> CompletionContext<'a> {
|
|||
|| 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!(
|
||||
self.prev_sibling,
|
||||
Some(ImmediatePrevSibling::ImplDefType | ImmediatePrevSibling::TraitDefName)
|
||||
)
|
||||
}
|
||||
|
||||
// FIXME: This probably shouldn't exist
|
||||
pub(crate) fn has_impl_prev_sibling(&self) -> bool {
|
||||
matches!(self.prev_sibling, Some(ImmediatePrevSibling::ImplDefType))
|
||||
}
|
||||
|
@ -289,6 +293,7 @@ impl<'a> CompletionContext<'a> {
|
|||
matches!(self.prev_sibling, Some(ImmediatePrevSibling::IfExpr))
|
||||
}
|
||||
|
||||
// FIXME: This shouldn't exist
|
||||
pub(crate) fn is_path_disallowed(&self) -> bool {
|
||||
self.previous_token_is(T![unsafe])
|
||||
|| matches!(
|
||||
|
|
|
@ -155,6 +155,7 @@ pub fn completions(
|
|||
completions::flyimport::import_on_the_fly(&mut acc, &ctx);
|
||||
completions::fn_param::complete_fn_param(&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::keyword::complete_expr_keyword(&mut acc, &ctx);
|
||||
completions::lifetime::complete_label(&mut acc, &ctx);
|
||||
|
|
|
@ -95,7 +95,7 @@ fn after_struct_name() {
|
|||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
kw const
|
||||
kw crate
|
||||
kw crate::
|
||||
kw enum
|
||||
kw extern
|
||||
kw fn
|
||||
|
@ -104,10 +104,10 @@ fn after_struct_name() {
|
|||
kw pub
|
||||
kw pub(crate)
|
||||
kw pub(super)
|
||||
kw self
|
||||
kw self::
|
||||
kw static
|
||||
kw struct
|
||||
kw super
|
||||
kw super::
|
||||
kw trait
|
||||
kw type
|
||||
kw union
|
||||
|
@ -129,7 +129,7 @@ fn after_fn_name() {
|
|||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
kw const
|
||||
kw crate
|
||||
kw crate::
|
||||
kw enum
|
||||
kw extern
|
||||
kw fn
|
||||
|
@ -138,10 +138,10 @@ fn after_fn_name() {
|
|||
kw pub
|
||||
kw pub(crate)
|
||||
kw pub(super)
|
||||
kw self
|
||||
kw self::
|
||||
kw static
|
||||
kw struct
|
||||
kw super
|
||||
kw super::
|
||||
kw trait
|
||||
kw type
|
||||
kw union
|
||||
|
|
|
@ -15,7 +15,7 @@ fn in_mod_item_list() {
|
|||
expect![[r#"
|
||||
ma makro!(…) macro_rules! makro
|
||||
kw const
|
||||
kw crate
|
||||
kw crate::
|
||||
kw enum
|
||||
kw extern
|
||||
kw fn
|
||||
|
@ -24,10 +24,10 @@ fn in_mod_item_list() {
|
|||
kw pub
|
||||
kw pub(crate)
|
||||
kw pub(super)
|
||||
kw self
|
||||
kw self::
|
||||
kw static
|
||||
kw struct
|
||||
kw super
|
||||
kw super::
|
||||
kw trait
|
||||
kw type
|
||||
kw union
|
||||
|
@ -48,7 +48,7 @@ fn in_source_file_item_list() {
|
|||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
kw const
|
||||
kw crate
|
||||
kw crate::
|
||||
kw enum
|
||||
kw extern
|
||||
kw fn
|
||||
|
@ -57,10 +57,10 @@ fn in_source_file_item_list() {
|
|||
kw pub
|
||||
kw pub(crate)
|
||||
kw pub(super)
|
||||
kw self
|
||||
kw self::
|
||||
kw static
|
||||
kw struct
|
||||
kw super
|
||||
kw super::
|
||||
kw trait
|
||||
kw type
|
||||
kw union
|
||||
|
@ -166,13 +166,13 @@ fn in_impl_assoc_item_list() {
|
|||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
kw const
|
||||
kw crate
|
||||
kw crate::
|
||||
kw fn
|
||||
kw pub
|
||||
kw pub(crate)
|
||||
kw pub(super)
|
||||
kw self
|
||||
kw super
|
||||
kw self::
|
||||
kw super::
|
||||
kw type
|
||||
kw unsafe
|
||||
"#]],
|
||||
|
@ -203,10 +203,10 @@ fn in_trait_assoc_item_list() {
|
|||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
kw const
|
||||
kw crate
|
||||
kw crate::
|
||||
kw fn
|
||||
kw self
|
||||
kw super
|
||||
kw self::
|
||||
kw super::
|
||||
kw type
|
||||
kw unsafe
|
||||
"#]],
|
||||
|
@ -240,13 +240,13 @@ impl Test for () {
|
|||
md module
|
||||
ta type Type1 =
|
||||
kw const
|
||||
kw crate
|
||||
kw crate::
|
||||
kw fn
|
||||
kw pub
|
||||
kw pub(crate)
|
||||
kw pub(super)
|
||||
kw self
|
||||
kw super
|
||||
kw self::
|
||||
kw super::
|
||||
kw type
|
||||
kw unsafe
|
||||
"#]],
|
||||
|
|
|
@ -394,6 +394,9 @@ fn foo() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn foo() fn()
|
||||
st Bar
|
||||
bt u32
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
|
@ -403,19 +406,18 @@ fn foo() {
|
|||
r#"
|
||||
struct Foo { bar: u32 }
|
||||
fn foo() {
|
||||
match Foo { bar: 0 } {
|
||||
match (Foo { bar: 0 }) {
|
||||
F$0 { bar } => {}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn foo() fn()
|
||||
fn foo() fn()
|
||||
st Foo
|
||||
bt u32
|
||||
kw crate
|
||||
kw return
|
||||
kw self
|
||||
kw super
|
||||
kw crate::
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
);
|
||||
check_empty(
|
||||
|
|
Loading…
Reference in a new issue