Fix visibility mods not being completed for field defs
This commit is contained in:
parent
519ac81b57
commit
c5dcc77b40
@ -4,6 +4,7 @@ pub(crate) mod attribute;
|
||||
pub(crate) mod dot;
|
||||
pub(crate) mod expr;
|
||||
pub(crate) mod extern_abi;
|
||||
pub(crate) mod field;
|
||||
pub(crate) mod flyimport;
|
||||
pub(crate) mod fn_param;
|
||||
pub(crate) mod format_string;
|
||||
|
53
crates/ide-completion/src/completions/field.rs
Normal file
53
crates/ide-completion/src/completions/field.rs
Normal file
@ -0,0 +1,53 @@
|
||||
//! Completion of field list position.
|
||||
|
||||
use crate::{
|
||||
context::{IdentContext, NameContext, NameKind, NameRefContext, PathCompletionCtx, PathKind},
|
||||
CompletionContext, CompletionItem, CompletionItemKind, Completions,
|
||||
};
|
||||
|
||||
pub(crate) fn complete_field_list(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
match &ctx.ident_ctx {
|
||||
IdentContext::Name(NameContext { kind: NameKind::RecordField, .. })
|
||||
| IdentContext::NameRef(NameRefContext {
|
||||
path_ctx:
|
||||
Some(PathCompletionCtx {
|
||||
has_macro_bang: false,
|
||||
is_absolute_path: false,
|
||||
qualifier: None,
|
||||
parent: None,
|
||||
kind: PathKind::Type { in_tuple_struct: true },
|
||||
has_type_args: false,
|
||||
..
|
||||
}),
|
||||
..
|
||||
}) => {
|
||||
if ctx.qualifier_ctx.vis_node.is_none() {
|
||||
let mut add_keyword = |kw, snippet| add_keyword(acc, ctx, kw, snippet);
|
||||
add_keyword("pub(crate)", "pub(crate)");
|
||||
add_keyword("pub(super)", "pub(super)");
|
||||
add_keyword("pub", "pub");
|
||||
}
|
||||
}
|
||||
_ => return,
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
@ -160,7 +160,10 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext)
|
||||
(_, ItemInNs::Types(hir::ModuleDef::Module(_))) => true,
|
||||
// and so are macros(except for attributes)
|
||||
(
|
||||
PathKind::Expr { .. } | PathKind::Type | PathKind::Item { .. } | PathKind::Pat,
|
||||
PathKind::Expr { .. }
|
||||
| PathKind::Type { .. }
|
||||
| PathKind::Item { .. }
|
||||
| PathKind::Pat,
|
||||
ItemInNs::Macros(mac),
|
||||
) => mac.is_fn_like(ctx.db),
|
||||
(PathKind::Item { .. }, _) => true,
|
||||
@ -170,14 +173,14 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext)
|
||||
(PathKind::Pat, ItemInNs::Types(_)) => true,
|
||||
(PathKind::Pat, ItemInNs::Values(def)) => matches!(def, hir::ModuleDef::Const(_)),
|
||||
|
||||
(PathKind::Type, ItemInNs::Types(ty)) => {
|
||||
(PathKind::Type { .. }, ItemInNs::Types(ty)) => {
|
||||
if matches!(ctx.completion_location, Some(ImmediateLocation::TypeBound)) {
|
||||
matches!(ty, ModuleDef::Trait(_))
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
(PathKind::Type, ItemInNs::Values(_)) => false,
|
||||
(PathKind::Type { .. }, ItemInNs::Values(_)) => false,
|
||||
|
||||
(PathKind::Attr { .. }, ItemInNs::Macros(mac)) => mac.is_attr(ctx.db),
|
||||
(PathKind::Attr { .. }, _) => false,
|
||||
|
@ -18,9 +18,12 @@ pub(crate) fn complete_type_path(acc: &mut Completions, ctx: &CompletionContext)
|
||||
}
|
||||
|
||||
let (&is_absolute_path, qualifier) = match ctx.path_context() {
|
||||
Some(PathCompletionCtx { kind: PathKind::Type, is_absolute_path, qualifier, .. }) => {
|
||||
(is_absolute_path, qualifier)
|
||||
}
|
||||
Some(PathCompletionCtx {
|
||||
kind: PathKind::Type { .. },
|
||||
is_absolute_path,
|
||||
qualifier,
|
||||
..
|
||||
}) => (is_absolute_path, qualifier),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
|
@ -49,7 +49,9 @@ pub(super) enum PathKind {
|
||||
in_block_expr: bool,
|
||||
in_loop_body: bool,
|
||||
},
|
||||
Type,
|
||||
Type {
|
||||
in_tuple_struct: bool,
|
||||
},
|
||||
Attr {
|
||||
kind: AttrKind,
|
||||
annotated_item_kind: Option<SyntaxKind>,
|
||||
@ -1222,7 +1224,9 @@ impl<'a> CompletionContext<'a> {
|
||||
// using Option<Option<PathKind>> as extra controlflow
|
||||
let kind = match_ast! {
|
||||
match it {
|
||||
ast::PathType(_) => Some(PathKind::Type),
|
||||
ast::PathType(it) => Some(PathKind::Type {
|
||||
in_tuple_struct: it.syntax().parent().map_or(false, |it| ast::TupleField::can_cast(it.kind()))
|
||||
}),
|
||||
ast::PathExpr(it) => {
|
||||
if let Some(p) = it.syntax().parent() {
|
||||
if ast::ExprStmt::can_cast(p.kind()) {
|
||||
@ -1262,7 +1266,7 @@ impl<'a> CompletionContext<'a> {
|
||||
let parent = it.syntax().parent();
|
||||
match parent.as_ref().map(|it| it.kind()) {
|
||||
Some(SyntaxKind::MACRO_PAT) => Some(PathKind::Pat),
|
||||
Some(SyntaxKind::MACRO_TYPE) => Some(PathKind::Type),
|
||||
Some(SyntaxKind::MACRO_TYPE) => Some(PathKind::Type { in_tuple_struct: false }),
|
||||
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()) {
|
||||
Some(it) => match_ast! {
|
||||
|
@ -158,6 +158,7 @@ pub fn completions(
|
||||
completions::dot::complete_dot(acc, ctx);
|
||||
completions::expr::complete_expr_path(acc, ctx);
|
||||
completions::extern_abi::complete_extern_abi(acc, ctx);
|
||||
completions::field::complete_field_list(acc, ctx);
|
||||
completions::flyimport::import_on_the_fly(acc, ctx);
|
||||
completions::fn_param::complete_fn_param(acc, ctx);
|
||||
completions::format_string::format_string(acc, ctx);
|
||||
|
@ -286,7 +286,7 @@ fn render_resolution_simple_(
|
||||
// Add `<>` for generic types
|
||||
let type_path_no_ty_args = matches!(
|
||||
ctx.completion.path_context(),
|
||||
Some(PathCompletionCtx { kind: PathKind::Type, has_type_args: false, .. })
|
||||
Some(PathCompletionCtx { kind: PathKind::Type { .. }, has_type_args: false, .. })
|
||||
) && ctx.completion.config.callable.is_some();
|
||||
if type_path_no_ty_args {
|
||||
if let Some(cap) = ctx.snippet_cap() {
|
||||
|
@ -202,7 +202,7 @@ fn should_add_parens(ctx: &CompletionContext) -> bool {
|
||||
Some(PathCompletionCtx { kind: PathKind::Expr { .. }, has_call_parens: true, .. }) => {
|
||||
return false
|
||||
}
|
||||
Some(PathCompletionCtx { kind: PathKind::Use | PathKind::Type, .. }) => {
|
||||
Some(PathCompletionCtx { kind: PathKind::Use | PathKind::Type { .. }, .. }) => {
|
||||
cov_mark::hit!(no_parens_in_use_item);
|
||||
return false;
|
||||
}
|
||||
|
@ -100,7 +100,6 @@ fn after_fn_name() {
|
||||
|
||||
#[test]
|
||||
fn before_record_field() {
|
||||
// FIXME: This should emit visibility qualifiers
|
||||
check(
|
||||
r#"
|
||||
struct Foo {
|
||||
@ -108,6 +107,10 @@ struct Foo {
|
||||
pub f: i32,
|
||||
}
|
||||
"#,
|
||||
expect![[r#""#]],
|
||||
expect![[r#"
|
||||
kw pub
|
||||
kw pub(crate)
|
||||
kw pub(super)
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
@ -38,14 +38,13 @@ 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<…>
|
||||
@ -57,6 +56,9 @@ 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