internal: Move most remaining keyword completions to item list completions
This commit is contained in:
parent
4f5c7aafff
commit
519ac81b57
@ -2,22 +2,98 @@
|
||||
|
||||
use crate::{
|
||||
completions::module_or_fn_macro,
|
||||
context::{PathCompletionCtx, PathKind, PathQualifierCtx},
|
||||
CompletionContext, Completions,
|
||||
context::{ItemListKind, PathCompletionCtx, PathKind, PathQualifierCtx},
|
||||
CompletionContext, CompletionItem, CompletionItemKind, Completions,
|
||||
};
|
||||
|
||||
pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
let _p = profile::span("complete_item_list");
|
||||
|
||||
let (&is_absolute_path, path_qualifier, _kind) = match ctx.path_context() {
|
||||
let (&is_absolute_path, path_qualifier, kind) = match ctx.path_context() {
|
||||
Some(PathCompletionCtx {
|
||||
kind: PathKind::Item { kind },
|
||||
is_absolute_path,
|
||||
qualifier,
|
||||
..
|
||||
}) => (is_absolute_path, qualifier, kind),
|
||||
}) => (is_absolute_path, qualifier, Some(kind)),
|
||||
Some(PathCompletionCtx {
|
||||
kind: PathKind::Expr { in_block_expr: true, .. },
|
||||
is_absolute_path,
|
||||
qualifier,
|
||||
..
|
||||
}) => (is_absolute_path, qualifier, None),
|
||||
_ => return,
|
||||
};
|
||||
let mut add_keyword = |kw, snippet| add_keyword(acc, ctx, kw, snippet);
|
||||
|
||||
let in_item_list = matches!(kind, Some(ItemListKind::SourceFile | ItemListKind::Module) | None);
|
||||
let in_assoc_non_trait_impl = matches!(kind, Some(ItemListKind::Impl | ItemListKind::Trait));
|
||||
let in_extern_block = matches!(kind, Some(ItemListKind::ExternBlock));
|
||||
let in_trait = matches!(kind, Some(ItemListKind::Trait));
|
||||
let in_trait_impl = matches!(kind, Some(ItemListKind::TraitImpl));
|
||||
let in_inherent_impl = matches!(kind, Some(ItemListKind::Impl));
|
||||
let no_qualifiers = ctx.qualifier_ctx.vis_node.is_none();
|
||||
let in_block = matches!(kind, None);
|
||||
|
||||
'block: loop {
|
||||
if path_qualifier.is_some() {
|
||||
break 'block;
|
||||
}
|
||||
if !in_trait_impl {
|
||||
if ctx.qualifier_ctx.unsafe_tok.is_some() {
|
||||
if in_item_list || in_assoc_non_trait_impl {
|
||||
add_keyword("fn", "fn $1($2) {\n $0\n}");
|
||||
}
|
||||
if in_item_list {
|
||||
add_keyword("trait", "trait $1 {\n $0\n}");
|
||||
if no_qualifiers {
|
||||
add_keyword("impl", "impl $1 {\n $0\n}");
|
||||
}
|
||||
}
|
||||
break 'block;
|
||||
}
|
||||
|
||||
if in_item_list {
|
||||
add_keyword("enum", "enum $1 {\n $0\n}");
|
||||
add_keyword("mod", "mod $0");
|
||||
add_keyword("static", "static $0");
|
||||
add_keyword("struct", "struct $0");
|
||||
add_keyword("trait", "trait $1 {\n $0\n}");
|
||||
add_keyword("union", "union $1 {\n $0\n}");
|
||||
add_keyword("use", "use $0");
|
||||
if no_qualifiers {
|
||||
add_keyword("impl", "impl $1 {\n $0\n}");
|
||||
}
|
||||
}
|
||||
|
||||
if !in_trait && !in_block && no_qualifiers {
|
||||
add_keyword("pub(crate)", "pub(crate)");
|
||||
add_keyword("pub(super)", "pub(super)");
|
||||
add_keyword("pub", "pub");
|
||||
}
|
||||
|
||||
if in_extern_block {
|
||||
add_keyword("fn", "fn $1($2);");
|
||||
} else {
|
||||
if !in_inherent_impl {
|
||||
if !in_trait {
|
||||
add_keyword("extern", "extern $0");
|
||||
}
|
||||
add_keyword("type", "type $0");
|
||||
}
|
||||
|
||||
add_keyword("fn", "fn $1($2) {\n $0\n}");
|
||||
add_keyword("unsafe", "unsafe");
|
||||
add_keyword("const", "const $0");
|
||||
}
|
||||
}
|
||||
break 'block;
|
||||
}
|
||||
|
||||
if kind.is_none() {
|
||||
// this is already handled by expression
|
||||
return;
|
||||
}
|
||||
|
||||
match path_qualifier {
|
||||
Some(PathQualifierCtx { resolution, is_super_chain, .. }) => {
|
||||
@ -33,9 +109,7 @@ 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 is_absolute_path => acc.add_crate_roots(ctx),
|
||||
None if ctx.qualifier_ctx.none() => {
|
||||
ctx.process_all_names(&mut |name, def| {
|
||||
if let Some(def) = module_or_fn_macro(ctx.db, def) {
|
||||
@ -47,3 +121,23 @@ pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext)
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn add_keyword(acc: &mut Completions, ctx: &CompletionContext, kw: &str, snippet: &str) {
|
||||
let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw);
|
||||
|
||||
match ctx.config.snippet_cap {
|
||||
Some(cap) => {
|
||||
if snippet.ends_with('}') && ctx.incomplete_let {
|
||||
// complete block expression snippets with a trailing semicolon, if inside an incomplete let
|
||||
cov_mark::hit!(let_semi);
|
||||
item.insert_snippet(cap, format!("{};", snippet));
|
||||
} else {
|
||||
item.insert_snippet(cap, snippet);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
item.insert_text(if snippet.contains('$') { kw } else { snippet });
|
||||
}
|
||||
};
|
||||
item.add_to(acc);
|
||||
}
|
||||
|
@ -2,8 +2,6 @@
|
||||
//! - `self`, `super` and `crate`, as these are considered part of path completions.
|
||||
//! - `await`, as this is a postfix completion we handle this in the postfix completions.
|
||||
|
||||
use syntax::T;
|
||||
|
||||
use crate::{
|
||||
context::{NameRefContext, PathKind},
|
||||
CompletionContext, CompletionItem, CompletionItemKind, Completions,
|
||||
@ -24,10 +22,6 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
|
||||
|
||||
let mut add_keyword = |kw, snippet| add_keyword(acc, ctx, kw, snippet);
|
||||
|
||||
let expects_assoc_item = ctx.expects_assoc_item();
|
||||
let has_block_expr_parent = ctx.has_block_expr_parent();
|
||||
let expects_item = ctx.expects_item();
|
||||
|
||||
if let Some(PathKind::Vis { .. }) = ctx.path_kind() {
|
||||
return;
|
||||
}
|
||||
@ -38,50 +32,6 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ctx.previous_token_is(T![unsafe]) {
|
||||
if expects_item || expects_assoc_item || has_block_expr_parent {
|
||||
add_keyword("fn", "fn $1($2) {\n $0\n}")
|
||||
}
|
||||
|
||||
if expects_item || has_block_expr_parent {
|
||||
add_keyword("trait", "trait $1 {\n $0\n}");
|
||||
add_keyword("impl", "impl $1 {\n $0\n}");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ctx.qualifier_ctx.vis_node.is_none()
|
||||
&& (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_field())
|
||||
{
|
||||
add_keyword("pub(crate)", "pub(crate)");
|
||||
add_keyword("pub(super)", "pub(super)");
|
||||
add_keyword("pub", "pub");
|
||||
}
|
||||
|
||||
if expects_item || expects_assoc_item || has_block_expr_parent {
|
||||
add_keyword("unsafe", "unsafe");
|
||||
add_keyword("fn", "fn $1($2) {\n $0\n}");
|
||||
add_keyword("const", "const $0");
|
||||
add_keyword("type", "type $0");
|
||||
}
|
||||
|
||||
if expects_item || has_block_expr_parent {
|
||||
if ctx.qualifier_ctx.vis_node.is_none() {
|
||||
add_keyword("impl", "impl $1 {\n $0\n}");
|
||||
add_keyword("extern", "extern $0");
|
||||
}
|
||||
add_keyword("use", "use $0");
|
||||
add_keyword("trait", "trait $1 {\n $0\n}");
|
||||
add_keyword("static", "static $0");
|
||||
add_keyword("mod", "mod $0");
|
||||
}
|
||||
|
||||
if expects_item || has_block_expr_parent {
|
||||
add_keyword("enum", "enum $1 {\n $0\n}");
|
||||
add_keyword("struct", "struct $0");
|
||||
add_keyword("union", "union $1 {\n $0\n}");
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn add_keyword(acc: &mut Completions, ctx: &CompletionContext, kw: &str, snippet: &str) {
|
||||
|
@ -71,6 +71,7 @@ pub(super) enum ItemListKind {
|
||||
SourceFile,
|
||||
Module,
|
||||
Impl,
|
||||
TraitImpl,
|
||||
Trait,
|
||||
ExternBlock,
|
||||
}
|
||||
@ -335,10 +336,6 @@ impl<'a> CompletionContext<'a> {
|
||||
matches!(self.completion_location, Some(ImmediateLocation::Trait | ImmediateLocation::Impl))
|
||||
}
|
||||
|
||||
pub(crate) fn expects_non_trait_assoc_item(&self) -> bool {
|
||||
matches!(self.completion_location, Some(ImmediateLocation::Impl))
|
||||
}
|
||||
|
||||
pub(crate) fn expects_item(&self) -> bool {
|
||||
matches!(self.completion_location, Some(ImmediateLocation::ItemList))
|
||||
}
|
||||
@ -348,19 +345,10 @@ impl<'a> CompletionContext<'a> {
|
||||
matches!(self.completion_location, Some(ImmediateLocation::GenericArgList(_)))
|
||||
}
|
||||
|
||||
pub(crate) fn has_block_expr_parent(&self) -> bool {
|
||||
matches!(self.completion_location, Some(ImmediateLocation::StmtList))
|
||||
}
|
||||
|
||||
pub(crate) fn expects_ident_ref_expr(&self) -> bool {
|
||||
matches!(self.completion_location, Some(ImmediateLocation::RefExpr))
|
||||
}
|
||||
|
||||
pub(crate) fn expect_field(&self) -> bool {
|
||||
matches!(self.completion_location, Some(ImmediateLocation::TupleField))
|
||||
|| matches!(self.name_ctx(), Some(NameContext { kind: NameKind::RecordField, .. }))
|
||||
}
|
||||
|
||||
/// Whether the cursor is right after a trait or impl header.
|
||||
/// trait Foo ident$0
|
||||
// FIXME: This probably shouldn't exist
|
||||
@ -1276,10 +1264,19 @@ impl<'a> CompletionContext<'a> {
|
||||
Some(SyntaxKind::MACRO_PAT) => Some(PathKind::Pat),
|
||||
Some(SyntaxKind::MACRO_TYPE) => Some(PathKind::Type),
|
||||
Some(SyntaxKind::ITEM_LIST) => Some(PathKind::Item { kind: ItemListKind::Module }),
|
||||
Some(SyntaxKind::ASSOC_ITEM_LIST) => Some(PathKind::Item { kind: match parent.and_then(|it| it.parent()).map(|it| it.kind()) {
|
||||
Some(SyntaxKind::TRAIT) => ItemListKind::Trait,
|
||||
Some(SyntaxKind::IMPL) => ItemListKind::Impl,
|
||||
_ => return Some(None),
|
||||
Some(SyntaxKind::ASSOC_ITEM_LIST) => Some(PathKind::Item { kind: match parent.and_then(|it| it.parent()) {
|
||||
Some(it) => match_ast! {
|
||||
match it {
|
||||
ast::Trait(_) => ItemListKind::Trait,
|
||||
ast::Impl(it) => if it.trait_().is_some() {
|
||||
ItemListKind::TraitImpl
|
||||
} else {
|
||||
ItemListKind::Impl
|
||||
},
|
||||
_ => return Some(None)
|
||||
}
|
||||
},
|
||||
None => return Some(None),
|
||||
} }),
|
||||
Some(SyntaxKind::EXTERN_ITEM_LIST) => Some(PathKind::Item { kind: ItemListKind::ExternBlock }),
|
||||
Some(SyntaxKind::SOURCE_FILE) => Some(PathKind::Item { kind: ItemListKind::SourceFile }),
|
||||
@ -1313,12 +1310,18 @@ impl<'a> CompletionContext<'a> {
|
||||
ast::UseTree(_) => Some(PathKind::Use),
|
||||
ast::ItemList(_) => Some(PathKind::Item { kind: ItemListKind::Module }),
|
||||
ast::AssocItemList(it) => Some(PathKind::Item { kind: {
|
||||
match it.syntax().parent()?.kind() {
|
||||
SyntaxKind::TRAIT => ItemListKind::Trait,
|
||||
SyntaxKind::IMPL => ItemListKind::Impl,
|
||||
_ => return None,
|
||||
match_ast! {
|
||||
match (it.syntax().parent()?) {
|
||||
ast::Trait(_) => ItemListKind::Trait,
|
||||
ast::Impl(it) => if it.trait_().is_some() {
|
||||
ItemListKind::TraitImpl
|
||||
} else {
|
||||
ItemListKind::Impl
|
||||
},
|
||||
_ => return None
|
||||
}
|
||||
}}),
|
||||
}
|
||||
}}),
|
||||
ast::ExternItemList(_) => Some(PathKind::Item { kind: ItemListKind::ExternBlock }),
|
||||
ast::SourceFile(_) => Some(PathKind::Item { kind: ItemListKind::SourceFile }),
|
||||
_ => return None,
|
||||
|
@ -88,58 +88,19 @@ fn after_target_name_in_impl() {
|
||||
|
||||
#[test]
|
||||
fn after_struct_name() {
|
||||
// FIXME: This should emit `kw where` only
|
||||
check(
|
||||
r"struct Struct $0",
|
||||
expect![[r#"
|
||||
kw const
|
||||
kw enum
|
||||
kw extern
|
||||
kw fn
|
||||
kw impl
|
||||
kw mod
|
||||
kw pub
|
||||
kw pub(crate)
|
||||
kw pub(super)
|
||||
kw static
|
||||
kw struct
|
||||
kw trait
|
||||
kw type
|
||||
kw union
|
||||
kw unsafe
|
||||
kw use
|
||||
"#]],
|
||||
);
|
||||
// FIXME: This should emit `kw where`
|
||||
check(r"struct Struct $0", expect![[r#""#]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_fn_name() {
|
||||
// FIXME: This should emit `kw where` only
|
||||
check(
|
||||
r"fn func() $0",
|
||||
expect![[r#"
|
||||
kw const
|
||||
kw enum
|
||||
kw extern
|
||||
kw fn
|
||||
kw impl
|
||||
kw mod
|
||||
kw pub
|
||||
kw pub(crate)
|
||||
kw pub(super)
|
||||
kw static
|
||||
kw struct
|
||||
kw trait
|
||||
kw type
|
||||
kw union
|
||||
kw unsafe
|
||||
kw use
|
||||
"#]],
|
||||
);
|
||||
// FIXME: This should emit `kw where`
|
||||
check(r"fn func() $0", expect![[r#""#]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn before_record_field() {
|
||||
// FIXME: This should emit visibility qualifiers
|
||||
check(
|
||||
r#"
|
||||
struct Foo {
|
||||
@ -147,10 +108,6 @@ struct Foo {
|
||||
pub f: i32,
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
kw pub
|
||||
kw pub(crate)
|
||||
kw pub(super)
|
||||
"#]],
|
||||
expect![[r#""#]],
|
||||
)
|
||||
}
|
||||
|
@ -137,6 +137,7 @@ fn after_visibility() {
|
||||
expect![[r#"
|
||||
kw const
|
||||
kw enum
|
||||
kw extern
|
||||
kw fn
|
||||
kw mod
|
||||
kw static
|
||||
@ -152,12 +153,10 @@ fn after_visibility() {
|
||||
|
||||
#[test]
|
||||
fn after_visibility_unsafe() {
|
||||
// FIXME this shouldn't show `impl`
|
||||
check(
|
||||
r#"pub unsafe $0"#,
|
||||
expect![[r#"
|
||||
kw fn
|
||||
kw impl
|
||||
kw trait
|
||||
"#]],
|
||||
);
|
||||
@ -178,7 +177,6 @@ fn in_impl_assoc_item_list() {
|
||||
kw pub(super)
|
||||
kw self::
|
||||
kw super::
|
||||
kw type
|
||||
kw unsafe
|
||||
"#]],
|
||||
)
|
||||
@ -199,7 +197,6 @@ fn in_impl_assoc_item_list_after_attr() {
|
||||
kw pub(super)
|
||||
kw self::
|
||||
kw super::
|
||||
kw type
|
||||
kw unsafe
|
||||
"#]],
|
||||
)
|
||||
@ -249,16 +246,9 @@ impl Test for () {
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
ta type Type1 =
|
||||
kw const
|
||||
kw crate::
|
||||
kw fn
|
||||
kw pub
|
||||
kw pub(crate)
|
||||
kw pub(super)
|
||||
kw self::
|
||||
kw super::
|
||||
kw type
|
||||
kw unsafe
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -38,13 +38,14 @@ struct Foo<'lt, T, const C: usize> {
|
||||
|
||||
#[test]
|
||||
fn tuple_struct_field() {
|
||||
// FIXME: This should emit visibility qualifiers
|
||||
check(
|
||||
r#"
|
||||
struct Foo<'lt, T, const C: usize>(f$0);
|
||||
"#,
|
||||
expect![[r#"
|
||||
en Enum
|
||||
ma makro!(…) macro_rules! makro
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
sp Self
|
||||
st Foo<…>
|
||||
@ -56,9 +57,6 @@ struct Foo<'lt, T, const C: usize>(f$0);
|
||||
un Union
|
||||
bt u32
|
||||
kw crate::
|
||||
kw pub
|
||||
kw pub(crate)
|
||||
kw pub(super)
|
||||
kw self::
|
||||
kw super::
|
||||
"#]],
|
||||
|
Loading…
x
Reference in New Issue
Block a user