From 18b667cfcb31b2c5e421d12a34b34e83165603f4 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 25 Aug 2020 17:20:29 +0200 Subject: Complete `pub` in fields --- crates/ide/src/completion/complete_keyword.rs | 23 ++++++++++++++-- crates/ide/src/completion/complete_snippet.rs | 2 -- crates/ide/src/completion/completion_context.rs | 10 ++++--- crates/ide/src/completion/patterns.rs | 8 ++++++ crates/parser/src/grammar/types.rs | 9 ++++++- .../inline/err/0014_struct_field_recover.rast | 31 ++++++++++++++++++++++ .../parser/inline/err/0014_struct_field_recover.rs | 1 + 7 files changed, 76 insertions(+), 8 deletions(-) create mode 100644 crates/syntax/test_data/parser/inline/err/0014_struct_field_recover.rast create mode 100644 crates/syntax/test_data/parser/inline/err/0014_struct_field_recover.rs diff --git a/crates/ide/src/completion/complete_keyword.rs b/crates/ide/src/completion/complete_keyword.rs index 95e4ff1ac..53ba76e0e 100644 --- a/crates/ide/src/completion/complete_keyword.rs +++ b/crates/ide/src/completion/complete_keyword.rs @@ -129,8 +129,9 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte add_keyword(ctx, acc, "break", "break"); } } - if ctx.has_item_list_or_source_file_parent || ctx.has_impl_parent { - add_keyword(ctx, acc, "pub", "pub ") + if ctx.has_item_list_or_source_file_parent || ctx.has_impl_parent | ctx.has_field_list_parent { + add_keyword(ctx, acc, "pub(crate)", "pub(crate) "); + add_keyword(ctx, acc, "pub", "pub "); } if !ctx.is_trivial_path { @@ -227,6 +228,7 @@ mod tests { kw impl kw mod kw pub + kw pub(crate) kw static kw struct kw trait @@ -364,6 +366,7 @@ fn quux() -> i32 { kw const kw fn kw pub + kw pub(crate) kw type kw unsafe "#]], @@ -524,4 +527,20 @@ pub mod future { "#]], ) } + + #[test] + fn before_field() { + check( + r#" +struct Foo { + <|> + pub f: i32, +} +"#, + expect![[r#" + kw pub + kw pub(crate) + "#]], + ) + } } diff --git a/crates/ide/src/completion/complete_snippet.rs b/crates/ide/src/completion/complete_snippet.rs index c3b03b199..4837d2910 100644 --- a/crates/ide/src/completion/complete_snippet.rs +++ b/crates/ide/src/completion/complete_snippet.rs @@ -65,7 +65,6 @@ fn ${1:feature}() { .add_to(acc); snippet(ctx, cap, "macro_rules", "macro_rules! $1 {\n\t($2) => {\n\t\t$0\n\t};\n}").add_to(acc); - snippet(ctx, cap, "pub(crate)", "pub(crate) $0").add_to(acc); } #[cfg(test)] @@ -107,7 +106,6 @@ mod tests { "#, expect![[r#" sn macro_rules - sn pub(crate) sn tfn (Test function) sn tmod (Test module) "#]], diff --git a/crates/ide/src/completion/completion_context.rs b/crates/ide/src/completion/completion_context.rs index 5adac7ebc..47355d5dc 100644 --- a/crates/ide/src/completion/completion_context.rs +++ b/crates/ide/src/completion/completion_context.rs @@ -16,9 +16,10 @@ use crate::{ call_info::ActiveParameter, completion::{ patterns::{ - has_bind_pat_parent, has_block_expr_parent, has_impl_as_prev_sibling, has_impl_parent, - has_item_list_or_source_file_parent, has_ref_parent, has_trait_as_prev_sibling, - has_trait_parent, if_is_prev, is_in_loop_body, is_match_arm, unsafe_is_prev, + has_bind_pat_parent, has_block_expr_parent, has_field_list_parent, + has_impl_as_prev_sibling, has_impl_parent, has_item_list_or_source_file_parent, + has_ref_parent, has_trait_as_prev_sibling, has_trait_parent, if_is_prev, + is_in_loop_body, is_match_arm, unsafe_is_prev, }, CompletionConfig, }, @@ -84,6 +85,7 @@ pub(crate) struct CompletionContext<'a> { pub(super) in_loop_body: bool, pub(super) has_trait_parent: bool, pub(super) has_impl_parent: bool, + pub(super) has_field_list_parent: bool, pub(super) trait_as_prev_sibling: bool, pub(super) impl_as_prev_sibling: bool, pub(super) is_match_arm: bool, @@ -157,6 +159,7 @@ impl<'a> CompletionContext<'a> { block_expr_parent: false, has_trait_parent: false, has_impl_parent: false, + has_field_list_parent: false, trait_as_prev_sibling: false, impl_as_prev_sibling: false, if_is_prev: false, @@ -230,6 +233,7 @@ impl<'a> CompletionContext<'a> { self.in_loop_body = is_in_loop_body(syntax_element.clone()); self.has_trait_parent = has_trait_parent(syntax_element.clone()); self.has_impl_parent = has_impl_parent(syntax_element.clone()); + self.has_field_list_parent = has_field_list_parent(syntax_element.clone()); self.impl_as_prev_sibling = has_impl_as_prev_sibling(syntax_element.clone()); self.trait_as_prev_sibling = has_trait_as_prev_sibling(syntax_element.clone()); self.is_match_arm = is_match_arm(syntax_element.clone()); diff --git a/crates/ide/src/completion/patterns.rs b/crates/ide/src/completion/patterns.rs index ffc97c076..c6ae589db 100644 --- a/crates/ide/src/completion/patterns.rs +++ b/crates/ide/src/completion/patterns.rs @@ -34,6 +34,14 @@ pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool { fn test_has_impl_parent() { check_pattern_is_applicable(r"impl A { f<|> }", has_impl_parent); } +pub(crate) fn has_field_list_parent(element: SyntaxElement) -> bool { + not_same_range_ancestor(element).filter(|it| it.kind() == RECORD_FIELD_LIST).is_some() +} +#[test] +fn test_has_field_list_parent() { + check_pattern_is_applicable(r"struct Foo { f<|> }", has_field_list_parent); + check_pattern_is_applicable(r"struct Foo { f<|> pub f: i32}", has_field_list_parent); +} pub(crate) fn has_block_expr_parent(element: SyntaxElement) -> bool { not_same_range_ancestor(element).filter(|it| it.kind() == BLOCK_EXPR).is_some() diff --git a/crates/parser/src/grammar/types.rs b/crates/parser/src/grammar/types.rs index c876545f4..9d00eb9b9 100644 --- a/crates/parser/src/grammar/types.rs +++ b/crates/parser/src/grammar/types.rs @@ -18,7 +18,14 @@ pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(token_set![ T![dyn], ]); -const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA, L_DOLLAR]; +const TYPE_RECOVERY_SET: TokenSet = token_set![ + T![')'], + T![,], + L_DOLLAR, + // test_err struct_field_recover + // struct S { f pub g: () } + T![pub], +]; pub(crate) fn type_(p: &mut Parser) { type_with_bounds_cond(p, true); diff --git a/crates/syntax/test_data/parser/inline/err/0014_struct_field_recover.rast b/crates/syntax/test_data/parser/inline/err/0014_struct_field_recover.rast new file mode 100644 index 000000000..ba8e50993 --- /dev/null +++ b/crates/syntax/test_data/parser/inline/err/0014_struct_field_recover.rast @@ -0,0 +1,31 @@ +SOURCE_FILE@0..25 + STRUCT@0..24 + STRUCT_KW@0..6 "struct" + WHITESPACE@6..7 " " + NAME@7..8 + IDENT@7..8 "S" + WHITESPACE@8..9 " " + RECORD_FIELD_LIST@9..24 + L_CURLY@9..10 "{" + WHITESPACE@10..11 " " + RECORD_FIELD@11..12 + NAME@11..12 + IDENT@11..12 "f" + WHITESPACE@12..13 " " + RECORD_FIELD@13..22 + VISIBILITY@13..16 + PUB_KW@13..16 "pub" + WHITESPACE@16..17 " " + NAME@17..18 + IDENT@17..18 "g" + COLON@18..19 ":" + WHITESPACE@19..20 " " + TUPLE_TYPE@20..22 + L_PAREN@20..21 "(" + R_PAREN@21..22 ")" + WHITESPACE@22..23 " " + R_CURLY@23..24 "}" + WHITESPACE@24..25 "\n" +error 12..12: expected COLON +error 12..12: expected type +error 12..12: expected COMMA diff --git a/crates/syntax/test_data/parser/inline/err/0014_struct_field_recover.rs b/crates/syntax/test_data/parser/inline/err/0014_struct_field_recover.rs new file mode 100644 index 000000000..da32227ad --- /dev/null +++ b/crates/syntax/test_data/parser/inline/err/0014_struct_field_recover.rs @@ -0,0 +1 @@ +struct S { f pub g: () } -- cgit v1.2.3