diff options
6 files changed, 180 insertions, 7 deletions
diff --git a/crates/ra_ide/src/completion/complete_pattern.rs b/crates/ra_ide/src/completion/complete_pattern.rs index cb84bb934..bc8fade6f 100644 --- a/crates/ra_ide/src/completion/complete_pattern.rs +++ b/crates/ra_ide/src/completion/complete_pattern.rs | |||
@@ -56,6 +56,20 @@ mod tests { | |||
56 | assert_debug_snapshot!(completions, @r###" | 56 | assert_debug_snapshot!(completions, @r###" |
57 | [ | 57 | [ |
58 | CompletionItem { | 58 | CompletionItem { |
59 | label: "Bar", | ||
60 | source_range: [246; 246), | ||
61 | delete: [246; 246), | ||
62 | insert: "Bar", | ||
63 | kind: Struct, | ||
64 | }, | ||
65 | CompletionItem { | ||
66 | label: "E", | ||
67 | source_range: [246; 246), | ||
68 | delete: [246; 246), | ||
69 | insert: "E", | ||
70 | kind: Enum, | ||
71 | }, | ||
72 | CompletionItem { | ||
59 | label: "E", | 73 | label: "E", |
60 | source_range: [246; 246), | 74 | source_range: [246; 246), |
61 | delete: [246; 246), | 75 | delete: [246; 246), |
@@ -70,6 +84,20 @@ mod tests { | |||
70 | kind: EnumVariant, | 84 | kind: EnumVariant, |
71 | }, | 85 | }, |
72 | CompletionItem { | 86 | CompletionItem { |
87 | label: "X", | ||
88 | source_range: [246; 246), | ||
89 | delete: [246; 246), | ||
90 | insert: "X", | ||
91 | kind: EnumVariant, | ||
92 | }, | ||
93 | CompletionItem { | ||
94 | label: "Z", | ||
95 | source_range: [246; 246), | ||
96 | delete: [246; 246), | ||
97 | insert: "Z", | ||
98 | kind: Const, | ||
99 | }, | ||
100 | CompletionItem { | ||
73 | label: "Z", | 101 | label: "Z", |
74 | source_range: [246; 246), | 102 | source_range: [246; 246), |
75 | delete: [246; 246), | 103 | delete: [246; 246), |
@@ -83,6 +111,13 @@ mod tests { | |||
83 | insert: "m", | 111 | insert: "m", |
84 | kind: Module, | 112 | kind: Module, |
85 | }, | 113 | }, |
114 | CompletionItem { | ||
115 | label: "m", | ||
116 | source_range: [246; 246), | ||
117 | delete: [246; 246), | ||
118 | insert: "m", | ||
119 | kind: Module, | ||
120 | }, | ||
86 | ] | 121 | ] |
87 | "###); | 122 | "###); |
88 | } | 123 | } |
@@ -110,6 +145,21 @@ mod tests { | |||
110 | insert: "E", | 145 | insert: "E", |
111 | kind: Enum, | 146 | kind: Enum, |
112 | }, | 147 | }, |
148 | CompletionItem { | ||
149 | label: "E", | ||
150 | source_range: [151; 151), | ||
151 | delete: [151; 151), | ||
152 | insert: "E", | ||
153 | kind: Enum, | ||
154 | }, | ||
155 | CompletionItem { | ||
156 | label: "m!", | ||
157 | source_range: [151; 151), | ||
158 | delete: [151; 151), | ||
159 | insert: "m!($0)", | ||
160 | kind: Macro, | ||
161 | detail: "macro_rules! m", | ||
162 | }, | ||
113 | ] | 163 | ] |
114 | "###); | 164 | "###); |
115 | } | 165 | } |
diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs index 81d3cc1b6..2ca552733 100644 --- a/crates/ra_ide/src/completion/complete_scope.rs +++ b/crates/ra_ide/src/completion/complete_scope.rs | |||
@@ -1,13 +1,19 @@ | |||
1 | //! Completion of names from the current scope, e.g. locals and imported items. | 1 | //! Completion of names from the current scope, e.g. locals and imported items. |
2 | 2 | ||
3 | use crate::completion::{CompletionContext, Completions}; | 3 | use crate::completion::{CompletionContext, Completions}; |
4 | use hir::{ModuleDef, ScopeDef}; | ||
4 | 5 | ||
5 | pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { | 6 | pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { |
6 | if !ctx.is_trivial_path { | 7 | if !ctx.is_trivial_path && !ctx.is_pat_binding_and_path { |
7 | return; | 8 | return; |
8 | } | 9 | } |
9 | 10 | ||
10 | ctx.scope().process_all_names(&mut |name, res| acc.add_resolution(ctx, name.to_string(), &res)); | 11 | ctx.scope().process_all_names(&mut |name, res| match (ctx.is_pat_binding_and_path, &res) { |
12 | (true, ScopeDef::ModuleDef(ModuleDef::Function(..))) => (), | ||
13 | (true, ScopeDef::ModuleDef(ModuleDef::Static(..))) => (), | ||
14 | (true, ScopeDef::Local(..)) => (), | ||
15 | _ => acc.add_resolution(ctx, name.to_string(), &res), | ||
16 | }); | ||
11 | } | 17 | } |
12 | 18 | ||
13 | #[cfg(test)] | 19 | #[cfg(test)] |
@@ -21,6 +27,79 @@ mod tests { | |||
21 | } | 27 | } |
22 | 28 | ||
23 | #[test] | 29 | #[test] |
30 | fn bind_pat_and_path_ignore_at() { | ||
31 | assert_debug_snapshot!( | ||
32 | do_reference_completion( | ||
33 | r" | ||
34 | enum Enum { | ||
35 | A, | ||
36 | B, | ||
37 | } | ||
38 | fn quux(x: Option<Enum>) { | ||
39 | match x { | ||
40 | None => (), | ||
41 | Some(en<|> @ Enum::A) => (), | ||
42 | } | ||
43 | } | ||
44 | " | ||
45 | ), | ||
46 | @r###"[]"### | ||
47 | ); | ||
48 | } | ||
49 | |||
50 | #[test] | ||
51 | fn bind_pat_and_path_ignore_ref() { | ||
52 | assert_debug_snapshot!( | ||
53 | do_reference_completion( | ||
54 | r" | ||
55 | enum Enum { | ||
56 | A, | ||
57 | B, | ||
58 | } | ||
59 | fn quux(x: Option<Enum>) { | ||
60 | match x { | ||
61 | None => (), | ||
62 | Some(ref en<|>) => (), | ||
63 | } | ||
64 | } | ||
65 | " | ||
66 | ), | ||
67 | @r###"[]"### | ||
68 | ); | ||
69 | } | ||
70 | |||
71 | #[test] | ||
72 | fn bind_pat_and_path() { | ||
73 | assert_debug_snapshot!( | ||
74 | do_reference_completion( | ||
75 | r" | ||
76 | enum Enum { | ||
77 | A, | ||
78 | B, | ||
79 | } | ||
80 | fn quux(x: Option<Enum>) { | ||
81 | match x { | ||
82 | None => (), | ||
83 | Some(En<|>) => (), | ||
84 | } | ||
85 | } | ||
86 | " | ||
87 | ), | ||
88 | @r###" | ||
89 | [ | ||
90 | CompletionItem { | ||
91 | label: "Enum", | ||
92 | source_range: [231; 233), | ||
93 | delete: [231; 233), | ||
94 | insert: "Enum", | ||
95 | kind: Enum, | ||
96 | }, | ||
97 | ] | ||
98 | "### | ||
99 | ); | ||
100 | } | ||
101 | |||
102 | #[test] | ||
24 | fn completes_bindings_from_let() { | 103 | fn completes_bindings_from_let() { |
25 | assert_debug_snapshot!( | 104 | assert_debug_snapshot!( |
26 | do_reference_completion( | 105 | do_reference_completion( |
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index 54589a2a8..319e33b61 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs | |||
@@ -36,6 +36,9 @@ pub(crate) struct CompletionContext<'a> { | |||
36 | /// If a name-binding or reference to a const in a pattern. | 36 | /// If a name-binding or reference to a const in a pattern. |
37 | /// Irrefutable patterns (like let) are excluded. | 37 | /// Irrefutable patterns (like let) are excluded. |
38 | pub(super) is_pat_binding: bool, | 38 | pub(super) is_pat_binding: bool, |
39 | // A bind battern which may also be part of a path. | ||
40 | // if let Some(En<|>) = Some(Enum::A) | ||
41 | pub(super) is_pat_binding_and_path: bool, | ||
39 | /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path. | 42 | /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path. |
40 | pub(super) is_trivial_path: bool, | 43 | pub(super) is_trivial_path: bool, |
41 | /// If not a trivial path, the prefix (qualifier). | 44 | /// If not a trivial path, the prefix (qualifier). |
@@ -95,6 +98,7 @@ impl<'a> CompletionContext<'a> { | |||
95 | impl_def: None, | 98 | impl_def: None, |
96 | is_param: false, | 99 | is_param: false, |
97 | is_pat_binding: false, | 100 | is_pat_binding: false, |
101 | is_pat_binding_and_path: false, | ||
98 | is_trivial_path: false, | 102 | is_trivial_path: false, |
99 | path_prefix: None, | 103 | path_prefix: None, |
100 | after_if: false, | 104 | after_if: false, |
@@ -188,10 +192,17 @@ impl<'a> CompletionContext<'a> { | |||
188 | if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) { | 192 | if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) { |
189 | let parent = bind_pat.syntax().parent(); | 193 | let parent = bind_pat.syntax().parent(); |
190 | if parent.clone().and_then(ast::MatchArm::cast).is_some() | 194 | if parent.clone().and_then(ast::MatchArm::cast).is_some() |
191 | || parent.and_then(ast::Condition::cast).is_some() | 195 | || parent.clone().and_then(ast::Condition::cast).is_some() |
192 | { | 196 | { |
193 | self.is_pat_binding = true; | 197 | self.is_pat_binding = true; |
194 | } | 198 | } |
199 | |||
200 | if parent.and_then(ast::RecordFieldPatList::cast).is_none() | ||
201 | && bind_pat.pat().is_none() | ||
202 | && !bind_pat.is_ref() | ||
203 | { | ||
204 | self.is_pat_binding_and_path = true; | ||
205 | } | ||
195 | } | 206 | } |
196 | if is_node::<ast::Param>(name.syntax()) { | 207 | if is_node::<ast::Param>(name.syntax()) { |
197 | self.is_param = true; | 208 | self.is_param = true; |
diff --git a/crates/ra_parser/src/grammar/items/adt.rs b/crates/ra_parser/src/grammar/items/adt.rs index c777bc9d0..74b9f514b 100644 --- a/crates/ra_parser/src/grammar/items/adt.rs +++ b/crates/ra_parser/src/grammar/items/adt.rs | |||
@@ -83,12 +83,14 @@ pub(crate) fn enum_variant_list(p: &mut Parser) { | |||
83 | match p.current() { | 83 | match p.current() { |
84 | T!['{'] => record_field_def_list(p), | 84 | T!['{'] => record_field_def_list(p), |
85 | T!['('] => tuple_field_def_list(p), | 85 | T!['('] => tuple_field_def_list(p), |
86 | T![=] => { | ||
87 | p.bump(T![=]); | ||
88 | expressions::expr(p); | ||
89 | } | ||
90 | _ => (), | 86 | _ => (), |
91 | } | 87 | } |
88 | |||
89 | // test variant_discriminant | ||
90 | // enum E { X(i32) = 10 } | ||
91 | if p.eat(T![=]) { | ||
92 | expressions::expr(p); | ||
93 | } | ||
92 | var.complete(p, ENUM_VARIANT); | 94 | var.complete(p, ENUM_VARIANT); |
93 | } else { | 95 | } else { |
94 | var.abandon(p); | 96 | var.abandon(p); |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0157_variant_discriminant.rs b/crates/ra_syntax/test_data/parser/inline/ok/0157_variant_discriminant.rs new file mode 100644 index 000000000..c8c5c0f17 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0157_variant_discriminant.rs | |||
@@ -0,0 +1 @@ | |||
enum E { X(i32) = 10 } | |||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0157_variant_discriminant.txt b/crates/ra_syntax/test_data/parser/inline/ok/0157_variant_discriminant.txt new file mode 100644 index 000000000..a378dd80b --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0157_variant_discriminant.txt | |||
@@ -0,0 +1,30 @@ | |||
1 | SOURCE_FILE@[0; 23) | ||
2 | ENUM_DEF@[0; 22) | ||
3 | ENUM_KW@[0; 4) "enum" | ||
4 | WHITESPACE@[4; 5) " " | ||
5 | NAME@[5; 6) | ||
6 | IDENT@[5; 6) "E" | ||
7 | WHITESPACE@[6; 7) " " | ||
8 | ENUM_VARIANT_LIST@[7; 22) | ||
9 | L_CURLY@[7; 8) "{" | ||
10 | WHITESPACE@[8; 9) " " | ||
11 | ENUM_VARIANT@[9; 20) | ||
12 | NAME@[9; 10) | ||
13 | IDENT@[9; 10) "X" | ||
14 | TUPLE_FIELD_DEF_LIST@[10; 15) | ||
15 | L_PAREN@[10; 11) "(" | ||
16 | TUPLE_FIELD_DEF@[11; 14) | ||
17 | PATH_TYPE@[11; 14) | ||
18 | PATH@[11; 14) | ||
19 | PATH_SEGMENT@[11; 14) | ||
20 | NAME_REF@[11; 14) | ||
21 | IDENT@[11; 14) "i32" | ||
22 | R_PAREN@[14; 15) ")" | ||
23 | WHITESPACE@[15; 16) " " | ||
24 | EQ@[16; 17) "=" | ||
25 | WHITESPACE@[17; 18) " " | ||
26 | LITERAL@[18; 20) | ||
27 | INT_NUMBER@[18; 20) "10" | ||
28 | WHITESPACE@[20; 21) " " | ||
29 | R_CURLY@[21; 22) "}" | ||
30 | WHITESPACE@[22; 23) "\n" | ||