aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_ide/src/completion/complete_pattern.rs50
-rw-r--r--crates/ra_ide/src/completion/complete_scope.rs83
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs13
-rw-r--r--crates/ra_parser/src/grammar/items/adt.rs10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0157_variant_discriminant.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0157_variant_discriminant.txt30
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
3use crate::completion::{CompletionContext, Completions}; 3use crate::completion::{CompletionContext, Completions};
4use hir::{ModuleDef, ScopeDef};
4 5
5pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { 6pub(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 @@
1SOURCE_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"