Unnamed repository; edit this file 'description' to name the repository.
Fix visibility mods not being completed for field defs
Lukas Wirth 2022-06-03
parent 519ac81 · commit c5dcc77
-rw-r--r--crates/ide-completion/src/completions.rs1
-rw-r--r--crates/ide-completion/src/completions/field.rs53
-rw-r--r--crates/ide-completion/src/completions/flyimport.rs9
-rw-r--r--crates/ide-completion/src/completions/type.rs9
-rw-r--r--crates/ide-completion/src/context.rs10
-rw-r--r--crates/ide-completion/src/lib.rs1
-rw-r--r--crates/ide-completion/src/render.rs2
-rw-r--r--crates/ide-completion/src/render/function.rs2
-rw-r--r--crates/ide-completion/src/tests/item.rs7
-rw-r--r--crates/ide-completion/src/tests/type_pos.rs6
10 files changed, 85 insertions, 15 deletions
diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index 931b92dec3..d020b49cde 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -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;
diff --git a/crates/ide-completion/src/completions/field.rs b/crates/ide-completion/src/completions/field.rs
new file mode 100644
index 0000000000..d81e48cbab
--- /dev/null
+++ b/crates/ide-completion/src/completions/field.rs
@@ -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);
+}
diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs
index 873db300b8..c3bf298bc6 100644
--- a/crates/ide-completion/src/completions/flyimport.rs
+++ b/crates/ide-completion/src/completions/flyimport.rs
@@ -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,
diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs
index 91414c8bf6..bc8c070c14 100644
--- a/crates/ide-completion/src/completions/type.rs
+++ b/crates/ide-completion/src/completions/type.rs
@@ -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,
};
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 4eac86162a..a4b38d3f24 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -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! {
diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs
index 9659efad61..c100dd63ea 100644
--- a/crates/ide-completion/src/lib.rs
+++ b/crates/ide-completion/src/lib.rs
@@ -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);
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index d51bc517d6..ca2b3ad343 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -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() {
diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs
index 5e1fbfa4a2..0be51b0e3f 100644
--- a/crates/ide-completion/src/render/function.rs
+++ b/crates/ide-completion/src/render/function.rs
@@ -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;
}
diff --git a/crates/ide-completion/src/tests/item.rs b/crates/ide-completion/src/tests/item.rs
index d1f5d2a33c..9e50e00ab7 100644
--- a/crates/ide-completion/src/tests/item.rs
+++ b/crates/ide-completion/src/tests/item.rs
@@ -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)
+ "#]],
)
}
diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs
index 76942110f8..1e5e86eef5 100644
--- a/crates/ide-completion/src/tests/type_pos.rs
+++ b/crates/ide-completion/src/tests/type_pos.rs
@@ -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::
"#]],