diff options
26 files changed, 430 insertions, 414 deletions
diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs index 783305005..cba5eb0c6 100644 --- a/crates/ide_completion/src/completions.rs +++ b/crates/ide_completion/src/completions.rs | |||
@@ -41,9 +41,9 @@ pub struct Completions { | |||
41 | buf: Vec<CompletionItem>, | 41 | buf: Vec<CompletionItem>, |
42 | } | 42 | } |
43 | 43 | ||
44 | impl Into<Vec<CompletionItem>> for Completions { | 44 | impl From<Completions> for Vec<CompletionItem> { |
45 | fn into(self) -> Vec<CompletionItem> { | 45 | fn from(val: Completions) -> Self { |
46 | self.buf | 46 | val.buf |
47 | } | 47 | } |
48 | } | 48 | } |
49 | 49 | ||
@@ -74,35 +74,6 @@ impl Completions { | |||
74 | items.into_iter().for_each(|item| self.add(item.into())) | 74 | items.into_iter().for_each(|item| self.add(item.into())) |
75 | } | 75 | } |
76 | 76 | ||
77 | pub(crate) fn add_field( | ||
78 | &mut self, | ||
79 | ctx: &CompletionContext, | ||
80 | receiver: Option<hir::Name>, | ||
81 | field: hir::Field, | ||
82 | ty: &hir::Type, | ||
83 | ) { | ||
84 | let item = render_field(RenderContext::new(ctx), receiver, field, ty); | ||
85 | self.add(item); | ||
86 | } | ||
87 | |||
88 | pub(crate) fn add_tuple_field( | ||
89 | &mut self, | ||
90 | ctx: &CompletionContext, | ||
91 | receiver: Option<hir::Name>, | ||
92 | field: usize, | ||
93 | ty: &hir::Type, | ||
94 | ) { | ||
95 | let item = render_tuple_field(RenderContext::new(ctx), receiver, field, ty); | ||
96 | self.add(item); | ||
97 | } | ||
98 | |||
99 | pub(crate) fn add_static_lifetime(&mut self, ctx: &CompletionContext) { | ||
100 | let mut item = | ||
101 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), "'static"); | ||
102 | item.kind(CompletionItemKind::SymbolKind(SymbolKind::LifetimeParam)); | ||
103 | self.add(item.build()); | ||
104 | } | ||
105 | |||
106 | pub(crate) fn add_resolution( | 77 | pub(crate) fn add_resolution( |
107 | &mut self, | 78 | &mut self, |
108 | ctx: &CompletionContext, | 79 | ctx: &CompletionContext, |
@@ -144,72 +115,102 @@ impl Completions { | |||
144 | self.add_opt(render_method(RenderContext::new(ctx), None, receiver, local_name, func)); | 115 | self.add_opt(render_method(RenderContext::new(ctx), None, receiver, local_name, func)); |
145 | } | 116 | } |
146 | 117 | ||
147 | pub(crate) fn add_variant_pat( | 118 | pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) { |
119 | self.add_opt(render_const(RenderContext::new(ctx), constant)); | ||
120 | } | ||
121 | |||
122 | pub(crate) fn add_type_alias(&mut self, ctx: &CompletionContext, type_alias: hir::TypeAlias) { | ||
123 | self.add_opt(render_type_alias(RenderContext::new(ctx), type_alias)); | ||
124 | } | ||
125 | |||
126 | pub(crate) fn add_type_alias_with_eq( | ||
148 | &mut self, | 127 | &mut self, |
149 | ctx: &CompletionContext, | 128 | ctx: &CompletionContext, |
150 | variant: hir::Variant, | 129 | type_alias: hir::TypeAlias, |
151 | local_name: Option<hir::Name>, | ||
152 | ) { | 130 | ) { |
153 | self.add_opt(render_variant_pat(RenderContext::new(ctx), variant, local_name, None)); | 131 | self.add_opt(render_type_alias_with_eq(RenderContext::new(ctx), type_alias)); |
154 | } | 132 | } |
155 | 133 | ||
156 | pub(crate) fn add_qualified_variant_pat( | 134 | pub(crate) fn add_qualified_enum_variant( |
157 | &mut self, | 135 | &mut self, |
158 | ctx: &CompletionContext, | 136 | ctx: &CompletionContext, |
159 | variant: hir::Variant, | 137 | variant: hir::Variant, |
160 | path: hir::ModPath, | 138 | path: hir::ModPath, |
161 | ) { | 139 | ) { |
162 | self.add_opt(render_variant_pat(RenderContext::new(ctx), variant, None, Some(path))); | 140 | let item = render_variant(RenderContext::new(ctx), None, None, variant, Some(path)); |
141 | self.add(item); | ||
163 | } | 142 | } |
164 | 143 | ||
165 | pub(crate) fn add_struct_pat( | 144 | pub(crate) fn add_enum_variant( |
166 | &mut self, | 145 | &mut self, |
167 | ctx: &CompletionContext, | 146 | ctx: &CompletionContext, |
168 | strukt: hir::Struct, | 147 | variant: hir::Variant, |
169 | local_name: Option<hir::Name>, | 148 | local_name: Option<hir::Name>, |
170 | ) { | 149 | ) { |
171 | self.add_opt(render_struct_pat(RenderContext::new(ctx), strukt, local_name)); | 150 | let item = render_variant(RenderContext::new(ctx), None, local_name, variant, None); |
151 | self.add(item); | ||
172 | } | 152 | } |
173 | 153 | ||
174 | pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) { | 154 | pub(crate) fn add_field( |
175 | self.add_opt(render_const(RenderContext::new(ctx), constant)); | 155 | &mut self, |
156 | ctx: &CompletionContext, | ||
157 | receiver: Option<hir::Name>, | ||
158 | field: hir::Field, | ||
159 | ty: &hir::Type, | ||
160 | ) { | ||
161 | let item = render_field(RenderContext::new(ctx), receiver, field, ty); | ||
162 | self.add(item); | ||
176 | } | 163 | } |
177 | 164 | ||
178 | pub(crate) fn add_type_alias(&mut self, ctx: &CompletionContext, type_alias: hir::TypeAlias) { | 165 | pub(crate) fn add_tuple_field( |
179 | self.add_opt(render_type_alias(RenderContext::new(ctx), type_alias)); | 166 | &mut self, |
167 | ctx: &CompletionContext, | ||
168 | receiver: Option<hir::Name>, | ||
169 | field: usize, | ||
170 | ty: &hir::Type, | ||
171 | ) { | ||
172 | let item = render_tuple_field(RenderContext::new(ctx), receiver, field, ty); | ||
173 | self.add(item); | ||
180 | } | 174 | } |
181 | 175 | ||
182 | pub(crate) fn add_type_alias_with_eq( | 176 | pub(crate) fn add_static_lifetime(&mut self, ctx: &CompletionContext) { |
177 | let mut item = | ||
178 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), "'static"); | ||
179 | item.kind(CompletionItemKind::SymbolKind(SymbolKind::LifetimeParam)); | ||
180 | self.add(item.build()); | ||
181 | } | ||
182 | |||
183 | pub(crate) fn add_variant_pat( | ||
183 | &mut self, | 184 | &mut self, |
184 | ctx: &CompletionContext, | 185 | ctx: &CompletionContext, |
185 | type_alias: hir::TypeAlias, | 186 | variant: hir::Variant, |
187 | local_name: Option<hir::Name>, | ||
186 | ) { | 188 | ) { |
187 | self.add_opt(render_type_alias_with_eq(RenderContext::new(ctx), type_alias)); | 189 | self.add_opt(render_variant_pat(RenderContext::new(ctx), variant, local_name, None)); |
188 | } | 190 | } |
189 | 191 | ||
190 | pub(crate) fn add_qualified_enum_variant( | 192 | pub(crate) fn add_qualified_variant_pat( |
191 | &mut self, | 193 | &mut self, |
192 | ctx: &CompletionContext, | 194 | ctx: &CompletionContext, |
193 | variant: hir::Variant, | 195 | variant: hir::Variant, |
194 | path: hir::ModPath, | 196 | path: hir::ModPath, |
195 | ) { | 197 | ) { |
196 | let item = render_variant(RenderContext::new(ctx), None, None, variant, Some(path)); | 198 | self.add_opt(render_variant_pat(RenderContext::new(ctx), variant, None, Some(path))); |
197 | self.add(item); | ||
198 | } | 199 | } |
199 | 200 | ||
200 | pub(crate) fn add_enum_variant( | 201 | pub(crate) fn add_struct_pat( |
201 | &mut self, | 202 | &mut self, |
202 | ctx: &CompletionContext, | 203 | ctx: &CompletionContext, |
203 | variant: hir::Variant, | 204 | strukt: hir::Struct, |
204 | local_name: Option<hir::Name>, | 205 | local_name: Option<hir::Name>, |
205 | ) { | 206 | ) { |
206 | let item = render_variant(RenderContext::new(ctx), None, local_name, variant, None); | 207 | self.add_opt(render_struct_pat(RenderContext::new(ctx), strukt, local_name)); |
207 | self.add(item); | ||
208 | } | 208 | } |
209 | } | 209 | } |
210 | 210 | ||
211 | /// Calls the callback for each variant of the provided enum with the path to the variant. | 211 | /// Calls the callback for each variant of the provided enum with the path to the variant. |
212 | fn complete_enum_variants( | 212 | /// Skips variants that are visible with single segment paths. |
213 | fn enum_variants_with_paths( | ||
213 | acc: &mut Completions, | 214 | acc: &mut Completions, |
214 | ctx: &CompletionContext, | 215 | ctx: &CompletionContext, |
215 | enum_: hir::Enum, | 216 | enum_: hir::Enum, |
diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs index 6df569c2a..3866c5917 100644 --- a/crates/ide_completion/src/completions/attribute.rs +++ b/crates/ide_completion/src/completions/attribute.rs | |||
@@ -322,7 +322,7 @@ mod tests { | |||
322 | 322 | ||
323 | use expect_test::{expect, Expect}; | 323 | use expect_test::{expect, Expect}; |
324 | 324 | ||
325 | use crate::{test_utils::completion_list, CompletionKind}; | 325 | use crate::{tests::filtered_completion_list, CompletionKind}; |
326 | 326 | ||
327 | #[test] | 327 | #[test] |
328 | fn attributes_are_sorted() { | 328 | fn attributes_are_sorted() { |
@@ -341,7 +341,7 @@ mod tests { | |||
341 | } | 341 | } |
342 | 342 | ||
343 | fn check(ra_fixture: &str, expect: Expect) { | 343 | fn check(ra_fixture: &str, expect: Expect) { |
344 | let actual = completion_list(ra_fixture, CompletionKind::Attribute); | 344 | let actual = filtered_completion_list(ra_fixture, CompletionKind::Attribute); |
345 | expect.assert_eq(&actual); | 345 | expect.assert_eq(&actual); |
346 | } | 346 | } |
347 | 347 | ||
diff --git a/crates/ide_completion/src/completions/attribute/derive.rs b/crates/ide_completion/src/completions/attribute/derive.rs index 20bbbba46..5201095e8 100644 --- a/crates/ide_completion/src/completions/attribute/derive.rs +++ b/crates/ide_completion/src/completions/attribute/derive.rs | |||
@@ -82,7 +82,7 @@ const DEFAULT_DERIVE_COMPLETIONS: &[DeriveDependencies] = &[ | |||
82 | mod tests { | 82 | mod tests { |
83 | use expect_test::{expect, Expect}; | 83 | use expect_test::{expect, Expect}; |
84 | 84 | ||
85 | use crate::{test_utils::completion_list, CompletionKind}; | 85 | use crate::{tests::filtered_completion_list, CompletionKind}; |
86 | 86 | ||
87 | fn check(ra_fixture: &str, expect: Expect) { | 87 | fn check(ra_fixture: &str, expect: Expect) { |
88 | let builtin_derives = r#" | 88 | let builtin_derives = r#" |
@@ -106,7 +106,7 @@ pub macro PartialOrd {} | |||
106 | pub macro Ord {} | 106 | pub macro Ord {} |
107 | 107 | ||
108 | "#; | 108 | "#; |
109 | let actual = completion_list( | 109 | let actual = filtered_completion_list( |
110 | &format!("{} {}", builtin_derives, ra_fixture), | 110 | &format!("{} {}", builtin_derives, ra_fixture), |
111 | CompletionKind::Attribute, | 111 | CompletionKind::Attribute, |
112 | ); | 112 | ); |
diff --git a/crates/ide_completion/src/completions/attribute/lint.rs b/crates/ide_completion/src/completions/attribute/lint.rs index ca99e9759..4812b075c 100644 --- a/crates/ide_completion/src/completions/attribute/lint.rs +++ b/crates/ide_completion/src/completions/attribute/lint.rs | |||
@@ -34,7 +34,7 @@ pub(super) fn complete_lint( | |||
34 | #[cfg(test)] | 34 | #[cfg(test)] |
35 | mod tests { | 35 | mod tests { |
36 | 36 | ||
37 | use crate::test_utils::check_edit; | 37 | use crate::tests::check_edit; |
38 | 38 | ||
39 | #[test] | 39 | #[test] |
40 | fn check_empty() { | 40 | fn check_empty() { |
diff --git a/crates/ide_completion/src/completions/dot.rs b/crates/ide_completion/src/completions/dot.rs index 9552875c1..7f75d4298 100644 --- a/crates/ide_completion/src/completions/dot.rs +++ b/crates/ide_completion/src/completions/dot.rs | |||
@@ -101,10 +101,10 @@ fn complete_methods( | |||
101 | mod tests { | 101 | mod tests { |
102 | use expect_test::{expect, Expect}; | 102 | use expect_test::{expect, Expect}; |
103 | 103 | ||
104 | use crate::{test_utils::completion_list, CompletionKind}; | 104 | use crate::{tests::filtered_completion_list, CompletionKind}; |
105 | 105 | ||
106 | fn check(ra_fixture: &str, expect: Expect) { | 106 | fn check(ra_fixture: &str, expect: Expect) { |
107 | let actual = completion_list(ra_fixture, CompletionKind::Reference); | 107 | let actual = filtered_completion_list(ra_fixture, CompletionKind::Reference); |
108 | expect.assert_eq(&actual); | 108 | expect.assert_eq(&actual); |
109 | } | 109 | } |
110 | 110 | ||
diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs index 30b8d44bd..4604feb5d 100644 --- a/crates/ide_completion/src/completions/flyimport.rs +++ b/crates/ide_completion/src/completions/flyimport.rs | |||
@@ -227,11 +227,11 @@ mod tests { | |||
227 | 227 | ||
228 | use crate::{ | 228 | use crate::{ |
229 | item::CompletionKind, | 229 | item::CompletionKind, |
230 | test_utils::{check_edit, check_edit_with_config, completion_list, TEST_CONFIG}, | 230 | tests::{check_edit, check_edit_with_config, filtered_completion_list, TEST_CONFIG}, |
231 | }; | 231 | }; |
232 | 232 | ||
233 | fn check(ra_fixture: &str, expect: Expect) { | 233 | fn check(ra_fixture: &str, expect: Expect) { |
234 | let actual = completion_list(ra_fixture, CompletionKind::Magic); | 234 | let actual = filtered_completion_list(ra_fixture, CompletionKind::Magic); |
235 | expect.assert_eq(&actual); | 235 | expect.assert_eq(&actual); |
236 | } | 236 | } |
237 | 237 | ||
diff --git a/crates/ide_completion/src/completions/fn_param.rs b/crates/ide_completion/src/completions/fn_param.rs index cb90e8a3e..c9f0e2473 100644 --- a/crates/ide_completion/src/completions/fn_param.rs +++ b/crates/ide_completion/src/completions/fn_param.rs | |||
@@ -64,10 +64,10 @@ pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) | |||
64 | mod tests { | 64 | mod tests { |
65 | use expect_test::{expect, Expect}; | 65 | use expect_test::{expect, Expect}; |
66 | 66 | ||
67 | use crate::{test_utils::completion_list, CompletionKind}; | 67 | use crate::{tests::filtered_completion_list, CompletionKind}; |
68 | 68 | ||
69 | fn check(ra_fixture: &str, expect: Expect) { | 69 | fn check(ra_fixture: &str, expect: Expect) { |
70 | let actual = completion_list(ra_fixture, CompletionKind::Magic); | 70 | let actual = filtered_completion_list(ra_fixture, CompletionKind::Magic); |
71 | expect.assert_eq(&actual); | 71 | expect.assert_eq(&actual); |
72 | } | 72 | } |
73 | 73 | ||
diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs index 0fccbeccf..73bbc4345 100644 --- a/crates/ide_completion/src/completions/keyword.rs +++ b/crates/ide_completion/src/completions/keyword.rs | |||
@@ -75,7 +75,9 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte | |||
75 | return; | 75 | return; |
76 | } | 76 | } |
77 | 77 | ||
78 | if expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_record_field() { | 78 | if !ctx.has_visibility_prev_sibling() |
79 | && (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_record_field()) | ||
80 | { | ||
79 | add_keyword("pub(crate)", "pub(crate) "); | 81 | add_keyword("pub(crate)", "pub(crate) "); |
80 | add_keyword("pub", "pub "); | 82 | add_keyword("pub", "pub "); |
81 | } | 83 | } |
@@ -88,11 +90,13 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte | |||
88 | } | 90 | } |
89 | 91 | ||
90 | if expects_item || has_block_expr_parent { | 92 | if expects_item || has_block_expr_parent { |
93 | if !ctx.has_visibility_prev_sibling() { | ||
94 | add_keyword("impl", "impl $1 {\n $0\n}"); | ||
95 | add_keyword("extern", "extern $0"); | ||
96 | } | ||
91 | add_keyword("use", "use $0"); | 97 | add_keyword("use", "use $0"); |
92 | add_keyword("impl", "impl $1 {\n $0\n}"); | ||
93 | add_keyword("trait", "trait $1 {\n $0\n}"); | 98 | add_keyword("trait", "trait $1 {\n $0\n}"); |
94 | add_keyword("static", "static $0"); | 99 | add_keyword("static", "static $0"); |
95 | add_keyword("extern", "extern $0"); | ||
96 | add_keyword("mod", "mod $0"); | 100 | add_keyword("mod", "mod $0"); |
97 | } | 101 | } |
98 | 102 | ||
@@ -186,12 +190,12 @@ mod tests { | |||
186 | use expect_test::{expect, Expect}; | 190 | use expect_test::{expect, Expect}; |
187 | 191 | ||
188 | use crate::{ | 192 | use crate::{ |
189 | test_utils::{check_edit, completion_list}, | 193 | tests::{check_edit, filtered_completion_list}, |
190 | CompletionKind, | 194 | CompletionKind, |
191 | }; | 195 | }; |
192 | 196 | ||
193 | fn check(ra_fixture: &str, expect: Expect) { | 197 | fn check(ra_fixture: &str, expect: Expect) { |
194 | let actual = completion_list(ra_fixture, CompletionKind::Keyword); | 198 | let actual = filtered_completion_list(ra_fixture, CompletionKind::Keyword); |
195 | expect.assert_eq(&actual) | 199 | expect.assert_eq(&actual) |
196 | } | 200 | } |
197 | 201 | ||
@@ -231,30 +235,6 @@ mod tests { | |||
231 | } | 235 | } |
232 | 236 | ||
233 | #[test] | 237 | #[test] |
234 | fn test_keywords_at_source_file_level() { | ||
235 | check( | ||
236 | r"m$0", | ||
237 | expect![[r#" | ||
238 | kw pub(crate) | ||
239 | kw pub | ||
240 | kw unsafe | ||
241 | kw fn | ||
242 | kw const | ||
243 | kw type | ||
244 | kw use | ||
245 | kw impl | ||
246 | kw trait | ||
247 | kw static | ||
248 | kw extern | ||
249 | kw mod | ||
250 | kw enum | ||
251 | kw struct | ||
252 | kw union | ||
253 | "#]], | ||
254 | ); | ||
255 | } | ||
256 | |||
257 | #[test] | ||
258 | fn test_keywords_in_function() { | 238 | fn test_keywords_in_function() { |
259 | check( | 239 | check( |
260 | r"fn quux() { $0 }", | 240 | r"fn quux() { $0 }", |
@@ -263,11 +243,11 @@ mod tests { | |||
263 | kw fn | 243 | kw fn |
264 | kw const | 244 | kw const |
265 | kw type | 245 | kw type |
266 | kw use | ||
267 | kw impl | 246 | kw impl |
247 | kw extern | ||
248 | kw use | ||
268 | kw trait | 249 | kw trait |
269 | kw static | 250 | kw static |
270 | kw extern | ||
271 | kw mod | 251 | kw mod |
272 | kw match | 252 | kw match |
273 | kw while | 253 | kw while |
@@ -291,11 +271,11 @@ mod tests { | |||
291 | kw fn | 271 | kw fn |
292 | kw const | 272 | kw const |
293 | kw type | 273 | kw type |
294 | kw use | ||
295 | kw impl | 274 | kw impl |
275 | kw extern | ||
276 | kw use | ||
296 | kw trait | 277 | kw trait |
297 | kw static | 278 | kw static |
298 | kw extern | ||
299 | kw mod | 279 | kw mod |
300 | kw match | 280 | kw match |
301 | kw while | 281 | kw while |
@@ -319,11 +299,11 @@ mod tests { | |||
319 | kw fn | 299 | kw fn |
320 | kw const | 300 | kw const |
321 | kw type | 301 | kw type |
322 | kw use | ||
323 | kw impl | 302 | kw impl |
303 | kw extern | ||
304 | kw use | ||
324 | kw trait | 305 | kw trait |
325 | kw static | 306 | kw static |
326 | kw extern | ||
327 | kw mod | 307 | kw mod |
328 | kw match | 308 | kw match |
329 | kw while | 309 | kw while |
@@ -370,49 +350,6 @@ fn quux() -> i32 { | |||
370 | } | 350 | } |
371 | 351 | ||
372 | #[test] | 352 | #[test] |
373 | fn test_keywords_in_trait_def() { | ||
374 | check( | ||
375 | r"trait My { $0 }", | ||
376 | expect![[r#" | ||
377 | kw unsafe | ||
378 | kw fn | ||
379 | kw const | ||
380 | kw type | ||
381 | "#]], | ||
382 | ); | ||
383 | } | ||
384 | |||
385 | #[test] | ||
386 | fn test_keywords_in_impl_def() { | ||
387 | check( | ||
388 | r"impl My { $0 }", | ||
389 | expect![[r#" | ||
390 | kw pub(crate) | ||
391 | kw pub | ||
392 | kw unsafe | ||
393 | kw fn | ||
394 | kw const | ||
395 | kw type | ||
396 | "#]], | ||
397 | ); | ||
398 | } | ||
399 | |||
400 | #[test] | ||
401 | fn test_keywords_in_impl_def_with_attr() { | ||
402 | check( | ||
403 | r"impl My { #[foo] $0 }", | ||
404 | expect![[r#" | ||
405 | kw pub(crate) | ||
406 | kw pub | ||
407 | kw unsafe | ||
408 | kw fn | ||
409 | kw const | ||
410 | kw type | ||
411 | "#]], | ||
412 | ); | ||
413 | } | ||
414 | |||
415 | #[test] | ||
416 | fn test_keywords_in_loop() { | 353 | fn test_keywords_in_loop() { |
417 | check( | 354 | check( |
418 | r"fn my() { loop { $0 } }", | 355 | r"fn my() { loop { $0 } }", |
@@ -421,11 +358,11 @@ fn quux() -> i32 { | |||
421 | kw fn | 358 | kw fn |
422 | kw const | 359 | kw const |
423 | kw type | 360 | kw type |
424 | kw use | ||
425 | kw impl | 361 | kw impl |
362 | kw extern | ||
363 | kw use | ||
426 | kw trait | 364 | kw trait |
427 | kw static | 365 | kw static |
428 | kw extern | ||
429 | kw mod | 366 | kw mod |
430 | kw match | 367 | kw match |
431 | kw while | 368 | kw while |
@@ -443,18 +380,6 @@ fn quux() -> i32 { | |||
443 | } | 380 | } |
444 | 381 | ||
445 | #[test] | 382 | #[test] |
446 | fn test_keywords_after_unsafe_in_item_list() { | ||
447 | check( | ||
448 | r"unsafe $0", | ||
449 | expect![[r#" | ||
450 | kw fn | ||
451 | kw trait | ||
452 | kw impl | ||
453 | "#]], | ||
454 | ); | ||
455 | } | ||
456 | |||
457 | #[test] | ||
458 | fn test_keywords_after_unsafe_in_block_expr() { | 383 | fn test_keywords_after_unsafe_in_block_expr() { |
459 | check( | 384 | check( |
460 | r"fn my_fn() { unsafe $0 }", | 385 | r"fn my_fn() { unsafe $0 }", |
diff --git a/crates/ide_completion/src/completions/lifetime.rs b/crates/ide_completion/src/completions/lifetime.rs index 8ccccb646..36f595164 100644 --- a/crates/ide_completion/src/completions/lifetime.rs +++ b/crates/ide_completion/src/completions/lifetime.rs | |||
@@ -50,7 +50,7 @@ mod tests { | |||
50 | use expect_test::{expect, Expect}; | 50 | use expect_test::{expect, Expect}; |
51 | 51 | ||
52 | use crate::{ | 52 | use crate::{ |
53 | test_utils::{check_edit, completion_list_with_config, TEST_CONFIG}, | 53 | tests::{check_edit, filtered_completion_list_with_config, TEST_CONFIG}, |
54 | CompletionConfig, CompletionKind, | 54 | CompletionConfig, CompletionKind, |
55 | }; | 55 | }; |
56 | 56 | ||
@@ -59,7 +59,8 @@ mod tests { | |||
59 | } | 59 | } |
60 | 60 | ||
61 | fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) { | 61 | fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) { |
62 | let actual = completion_list_with_config(config, ra_fixture, CompletionKind::Reference); | 62 | let actual = |
63 | filtered_completion_list_with_config(config, ra_fixture, CompletionKind::Reference); | ||
63 | expect.assert_eq(&actual) | 64 | expect.assert_eq(&actual) |
64 | } | 65 | } |
65 | 66 | ||
diff --git a/crates/ide_completion/src/completions/mod_.rs b/crates/ide_completion/src/completions/mod_.rs index 6a5746fb9..5def0d06a 100644 --- a/crates/ide_completion/src/completions/mod_.rs +++ b/crates/ide_completion/src/completions/mod_.rs | |||
@@ -141,11 +141,11 @@ fn module_chain_to_containing_module_file( | |||
141 | 141 | ||
142 | #[cfg(test)] | 142 | #[cfg(test)] |
143 | mod tests { | 143 | mod tests { |
144 | use crate::{test_utils::completion_list, CompletionKind}; | 144 | use crate::{tests::filtered_completion_list, CompletionKind}; |
145 | use expect_test::{expect, Expect}; | 145 | use expect_test::{expect, Expect}; |
146 | 146 | ||
147 | fn check(ra_fixture: &str, expect: Expect) { | 147 | fn check(ra_fixture: &str, expect: Expect) { |
148 | let actual = completion_list(ra_fixture, CompletionKind::Magic); | 148 | let actual = filtered_completion_list(ra_fixture, CompletionKind::Magic); |
149 | expect.assert_eq(&actual); | 149 | expect.assert_eq(&actual); |
150 | } | 150 | } |
151 | 151 | ||
diff --git a/crates/ide_completion/src/completions/pattern.rs b/crates/ide_completion/src/completions/pattern.rs index 1daa8595a..efe3c957a 100644 --- a/crates/ide_completion/src/completions/pattern.rs +++ b/crates/ide_completion/src/completions/pattern.rs | |||
@@ -13,7 +13,7 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { | |||
13 | if let Some(hir::Adt::Enum(e)) = | 13 | if let Some(hir::Adt::Enum(e)) = |
14 | ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) | 14 | ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) |
15 | { | 15 | { |
16 | super::complete_enum_variants(acc, ctx, e, |acc, ctx, variant, path| { | 16 | super::enum_variants_with_paths(acc, ctx, e, |acc, ctx, variant, path| { |
17 | acc.add_qualified_variant_pat(ctx, variant, path.clone()); | 17 | acc.add_qualified_variant_pat(ctx, variant, path.clone()); |
18 | acc.add_qualified_enum_variant(ctx, variant, path); | 18 | acc.add_qualified_enum_variant(ctx, variant, path); |
19 | }); | 19 | }); |
@@ -61,17 +61,17 @@ mod tests { | |||
61 | use expect_test::{expect, Expect}; | 61 | use expect_test::{expect, Expect}; |
62 | 62 | ||
63 | use crate::{ | 63 | use crate::{ |
64 | test_utils::{check_edit, completion_list}, | 64 | tests::{check_edit, filtered_completion_list}, |
65 | CompletionKind, | 65 | CompletionKind, |
66 | }; | 66 | }; |
67 | 67 | ||
68 | fn check(ra_fixture: &str, expect: Expect) { | 68 | fn check(ra_fixture: &str, expect: Expect) { |
69 | let actual = completion_list(ra_fixture, CompletionKind::Reference); | 69 | let actual = filtered_completion_list(ra_fixture, CompletionKind::Reference); |
70 | expect.assert_eq(&actual) | 70 | expect.assert_eq(&actual) |
71 | } | 71 | } |
72 | 72 | ||
73 | fn check_snippet(ra_fixture: &str, expect: Expect) { | 73 | fn check_snippet(ra_fixture: &str, expect: Expect) { |
74 | let actual = completion_list(ra_fixture, CompletionKind::Snippet); | 74 | let actual = filtered_completion_list(ra_fixture, CompletionKind::Snippet); |
75 | expect.assert_eq(&actual) | 75 | expect.assert_eq(&actual) |
76 | } | 76 | } |
77 | 77 | ||
diff --git a/crates/ide_completion/src/completions/postfix.rs b/crates/ide_completion/src/completions/postfix.rs index 9f98b21be..c3c7e4589 100644 --- a/crates/ide_completion/src/completions/postfix.rs +++ b/crates/ide_completion/src/completions/postfix.rs | |||
@@ -307,12 +307,12 @@ mod tests { | |||
307 | use expect_test::{expect, Expect}; | 307 | use expect_test::{expect, Expect}; |
308 | 308 | ||
309 | use crate::{ | 309 | use crate::{ |
310 | test_utils::{check_edit, completion_list}, | 310 | tests::{check_edit, filtered_completion_list}, |
311 | CompletionKind, | 311 | CompletionKind, |
312 | }; | 312 | }; |
313 | 313 | ||
314 | fn check(ra_fixture: &str, expect: Expect) { | 314 | fn check(ra_fixture: &str, expect: Expect) { |
315 | let actual = completion_list(ra_fixture, CompletionKind::Postfix); | 315 | let actual = filtered_completion_list(ra_fixture, CompletionKind::Postfix); |
316 | expect.assert_eq(&actual) | 316 | expect.assert_eq(&actual) |
317 | } | 317 | } |
318 | 318 | ||
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs index 1643eeed4..9432caa22 100644 --- a/crates/ide_completion/src/completions/qualified_path.rs +++ b/crates/ide_completion/src/completions/qualified_path.rs | |||
@@ -198,17 +198,17 @@ mod tests { | |||
198 | use expect_test::{expect, Expect}; | 198 | use expect_test::{expect, Expect}; |
199 | 199 | ||
200 | use crate::{ | 200 | use crate::{ |
201 | test_utils::{check_edit, completion_list}, | 201 | tests::{check_edit, filtered_completion_list}, |
202 | CompletionKind, | 202 | CompletionKind, |
203 | }; | 203 | }; |
204 | 204 | ||
205 | fn check(ra_fixture: &str, expect: Expect) { | 205 | fn check(ra_fixture: &str, expect: Expect) { |
206 | let actual = completion_list(ra_fixture, CompletionKind::Reference); | 206 | let actual = filtered_completion_list(ra_fixture, CompletionKind::Reference); |
207 | expect.assert_eq(&actual); | 207 | expect.assert_eq(&actual); |
208 | } | 208 | } |
209 | 209 | ||
210 | fn check_builtin(ra_fixture: &str, expect: Expect) { | 210 | fn check_builtin(ra_fixture: &str, expect: Expect) { |
211 | let actual = completion_list(ra_fixture, CompletionKind::BuiltinType); | 211 | let actual = filtered_completion_list(ra_fixture, CompletionKind::BuiltinType); |
212 | expect.assert_eq(&actual); | 212 | expect.assert_eq(&actual); |
213 | } | 213 | } |
214 | 214 | ||
@@ -714,24 +714,6 @@ impl MyStruct { | |||
714 | } | 714 | } |
715 | 715 | ||
716 | #[test] | 716 | #[test] |
717 | fn completes_in_item_list() { | ||
718 | check( | ||
719 | r#" | ||
720 | struct MyStruct {} | ||
721 | #[macro_export] | ||
722 | macro_rules! foo {} | ||
723 | mod bar {} | ||
724 | |||
725 | crate::$0 | ||
726 | "#, | ||
727 | expect![[r#" | ||
728 | md bar | ||
729 | ma foo!(…) #[macro_export] macro_rules! foo | ||
730 | "#]], | ||
731 | ) | ||
732 | } | ||
733 | |||
734 | #[test] | ||
735 | fn test_super_super_completion() { | 717 | fn test_super_super_completion() { |
736 | check( | 718 | check( |
737 | r#" | 719 | r#" |
diff --git a/crates/ide_completion/src/completions/record.rs b/crates/ide_completion/src/completions/record.rs index 0ac47cdbe..47523f72f 100644 --- a/crates/ide_completion/src/completions/record.rs +++ b/crates/ide_completion/src/completions/record.rs | |||
@@ -51,17 +51,17 @@ mod tests { | |||
51 | use ide_db::helpers::FamousDefs; | 51 | use ide_db::helpers::FamousDefs; |
52 | 52 | ||
53 | use crate::{ | 53 | use crate::{ |
54 | test_utils::{self, completion_list}, | 54 | tests::{self, filtered_completion_list}, |
55 | CompletionKind, | 55 | CompletionKind, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | fn check(ra_fixture: &str, expect: Expect) { | 58 | fn check(ra_fixture: &str, expect: Expect) { |
59 | let actual = completion_list(ra_fixture, CompletionKind::Reference); | 59 | let actual = filtered_completion_list(ra_fixture, CompletionKind::Reference); |
60 | expect.assert_eq(&actual); | 60 | expect.assert_eq(&actual); |
61 | } | 61 | } |
62 | 62 | ||
63 | fn check_snippet(ra_fixture: &str, expect: Expect) { | 63 | fn check_snippet(ra_fixture: &str, expect: Expect) { |
64 | let actual = completion_list( | 64 | let actual = filtered_completion_list( |
65 | &format!("//- /main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE), | 65 | &format!("//- /main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE), |
66 | CompletionKind::Snippet, | 66 | CompletionKind::Snippet, |
67 | ); | 67 | ); |
@@ -69,7 +69,7 @@ mod tests { | |||
69 | } | 69 | } |
70 | 70 | ||
71 | fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) { | 71 | fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) { |
72 | test_utils::check_edit( | 72 | tests::check_edit( |
73 | what, | 73 | what, |
74 | &format!( | 74 | &format!( |
75 | "//- /main.rs crate:main deps:core{}\n{}", | 75 | "//- /main.rs crate:main deps:core{}\n{}", |
diff --git a/crates/ide_completion/src/completions/snippet.rs b/crates/ide_completion/src/completions/snippet.rs index b9862de67..81ddfa34f 100644 --- a/crates/ide_completion/src/completions/snippet.rs +++ b/crates/ide_completion/src/completions/snippet.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | //! This file provides snippet completions, like `pd` => `eprintln!(...)`. | 1 | //! This file provides snippet completions, like `pd` => `eprintln!(...)`. |
2 | 2 | ||
3 | use ide_db::helpers::SnippetCap; | 3 | use ide_db::helpers::SnippetCap; |
4 | use syntax::T; | ||
4 | 5 | ||
5 | use crate::{ | 6 | use crate::{ |
6 | context::PathCompletionContext, item::Builder, CompletionContext, CompletionItem, | 7 | context::PathCompletionContext, item::Builder, CompletionContext, CompletionItem, |
@@ -35,9 +36,13 @@ pub(crate) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionConte | |||
35 | } | 36 | } |
36 | 37 | ||
37 | pub(crate) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionContext) { | 38 | pub(crate) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionContext) { |
38 | if !ctx.expects_item() { | 39 | if !ctx.expects_item() || ctx.previous_token_is(T![unsafe]) || ctx.path_qual().is_some() { |
39 | return; | 40 | return; |
40 | } | 41 | } |
42 | if ctx.has_visibility_prev_sibling() { | ||
43 | return; // technically we could do some of these snippet completions if we were to put the | ||
44 | // attributes before the vis node. | ||
45 | } | ||
41 | let cap = match ctx.config.snippet_cap { | 46 | let cap = match ctx.config.snippet_cap { |
42 | Some(it) => it, | 47 | Some(it) => it, |
43 | None => return, | 48 | None => return, |
@@ -82,10 +87,10 @@ fn ${1:feature}() { | |||
82 | mod tests { | 87 | mod tests { |
83 | use expect_test::{expect, Expect}; | 88 | use expect_test::{expect, Expect}; |
84 | 89 | ||
85 | use crate::{test_utils::completion_list, CompletionKind}; | 90 | use crate::{tests::filtered_completion_list, CompletionKind}; |
86 | 91 | ||
87 | fn check(ra_fixture: &str, expect: Expect) { | 92 | fn check(ra_fixture: &str, expect: Expect) { |
88 | let actual = completion_list(ra_fixture, CompletionKind::Snippet); | 93 | let actual = filtered_completion_list(ra_fixture, CompletionKind::Snippet); |
89 | expect.assert_eq(&actual) | 94 | expect.assert_eq(&actual) |
90 | } | 95 | } |
91 | 96 | ||
@@ -105,21 +110,4 @@ mod tests { | |||
105 | check(r#"fn foo(x: i32) { ::foo$0 }"#, expect![[""]]); | 110 | check(r#"fn foo(x: i32) { ::foo$0 }"#, expect![[""]]); |
106 | check(r#"fn foo(x: i32) { ::$0 }"#, expect![[""]]); | 111 | check(r#"fn foo(x: i32) { ::$0 }"#, expect![[""]]); |
107 | } | 112 | } |
108 | |||
109 | #[test] | ||
110 | fn completes_snippets_in_items() { | ||
111 | check( | ||
112 | r#" | ||
113 | #[cfg(test)] | ||
114 | mod tests { | ||
115 | $0 | ||
116 | } | ||
117 | "#, | ||
118 | expect![[r#" | ||
119 | sn tmod (Test module) | ||
120 | sn tfn (Test function) | ||
121 | sn macro_rules | ||
122 | "#]], | ||
123 | ) | ||
124 | } | ||
125 | } | 113 | } |
diff --git a/crates/ide_completion/src/completions/trait_impl.rs b/crates/ide_completion/src/completions/trait_impl.rs index a60e5f43c..dc1d198cc 100644 --- a/crates/ide_completion/src/completions/trait_impl.rs +++ b/crates/ide_completion/src/completions/trait_impl.rs | |||
@@ -246,12 +246,12 @@ mod tests { | |||
246 | use expect_test::{expect, Expect}; | 246 | use expect_test::{expect, Expect}; |
247 | 247 | ||
248 | use crate::{ | 248 | use crate::{ |
249 | test_utils::{check_edit, completion_list}, | 249 | tests::{check_edit, filtered_completion_list}, |
250 | CompletionKind, | 250 | CompletionKind, |
251 | }; | 251 | }; |
252 | 252 | ||
253 | fn check(ra_fixture: &str, expect: Expect) { | 253 | fn check(ra_fixture: &str, expect: Expect) { |
254 | let actual = completion_list(ra_fixture, CompletionKind::Magic); | 254 | let actual = filtered_completion_list(ra_fixture, CompletionKind::Magic); |
255 | expect.assert_eq(&actual) | 255 | expect.assert_eq(&actual) |
256 | } | 256 | } |
257 | 257 | ||
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index b5af1c810..2868d9b18 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs | |||
@@ -40,7 +40,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC | |||
40 | if let Some(hir::Adt::Enum(e)) = | 40 | if let Some(hir::Adt::Enum(e)) = |
41 | ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) | 41 | ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) |
42 | { | 42 | { |
43 | super::complete_enum_variants(acc, ctx, e, |acc, ctx, variant, path| { | 43 | super::enum_variants_with_paths(acc, ctx, e, |acc, ctx, variant, path| { |
44 | acc.add_qualified_enum_variant(ctx, variant, path) | 44 | acc.add_qualified_enum_variant(ctx, variant, path) |
45 | }); | 45 | }); |
46 | } | 46 | } |
@@ -93,7 +93,7 @@ mod tests { | |||
93 | use expect_test::{expect, Expect}; | 93 | use expect_test::{expect, Expect}; |
94 | 94 | ||
95 | use crate::{ | 95 | use crate::{ |
96 | test_utils::{check_edit, completion_list_with_config, TEST_CONFIG}, | 96 | tests::{check_edit, filtered_completion_list_with_config, TEST_CONFIG}, |
97 | CompletionConfig, CompletionKind, | 97 | CompletionConfig, CompletionKind, |
98 | }; | 98 | }; |
99 | 99 | ||
@@ -102,7 +102,8 @@ mod tests { | |||
102 | } | 102 | } |
103 | 103 | ||
104 | fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) { | 104 | fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) { |
105 | let actual = completion_list_with_config(config, ra_fixture, CompletionKind::Reference); | 105 | let actual = |
106 | filtered_completion_list_with_config(config, ra_fixture, CompletionKind::Reference); | ||
106 | expect.assert_eq(&actual) | 107 | expect.assert_eq(&actual) |
107 | } | 108 | } |
108 | 109 | ||
@@ -500,18 +501,6 @@ fn f() {$0} | |||
500 | check( | 501 | check( |
501 | r#" | 502 | r#" |
502 | #[rustc_builtin_macro] | 503 | #[rustc_builtin_macro] |
503 | pub macro Clone {} | ||
504 | |||
505 | struct S; | ||
506 | impl S { | ||
507 | $0 | ||
508 | } | ||
509 | "#, | ||
510 | expect![[r#""#]], | ||
511 | ); | ||
512 | check( | ||
513 | r#" | ||
514 | #[rustc_builtin_macro] | ||
515 | pub macro bench {} | 504 | pub macro bench {} |
516 | 505 | ||
517 | fn f() {$0} | 506 | fn f() {$0} |
@@ -773,42 +762,6 @@ impl My$0 | |||
773 | } | 762 | } |
774 | 763 | ||
775 | #[test] | 764 | #[test] |
776 | fn completes_in_assoc_item_list() { | ||
777 | check( | ||
778 | r#" | ||
779 | macro_rules! foo {} | ||
780 | mod bar {} | ||
781 | |||
782 | struct MyStruct {} | ||
783 | impl MyStruct { | ||
784 | $0 | ||
785 | } | ||
786 | "#, | ||
787 | expect![[r#" | ||
788 | md bar | ||
789 | ma foo!(…) macro_rules! foo | ||
790 | "#]], | ||
791 | ) | ||
792 | } | ||
793 | |||
794 | #[test] | ||
795 | fn completes_in_item_list() { | ||
796 | check( | ||
797 | r#" | ||
798 | struct MyStruct {} | ||
799 | macro_rules! foo {} | ||
800 | mod bar {} | ||
801 | |||
802 | $0 | ||
803 | "#, | ||
804 | expect![[r#" | ||
805 | md bar | ||
806 | ma foo!(…) macro_rules! foo | ||
807 | "#]], | ||
808 | ) | ||
809 | } | ||
810 | |||
811 | #[test] | ||
812 | fn completes_types_and_const_in_arg_list() { | 765 | fn completes_types_and_const_in_arg_list() { |
813 | check( | 766 | check( |
814 | r#" | 767 | r#" |
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index a8437d81c..121909857 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs | |||
@@ -302,18 +302,28 @@ impl<'a> CompletionContext<'a> { | |||
302 | ) | 302 | ) |
303 | } | 303 | } |
304 | 304 | ||
305 | pub(crate) fn has_visibility_prev_sibling(&self) -> bool { | ||
306 | matches!(self.prev_sibling, Some(ImmediatePrevSibling::Visibility)) | ||
307 | } | ||
308 | |||
305 | pub(crate) fn after_if(&self) -> bool { | 309 | pub(crate) fn after_if(&self) -> bool { |
306 | matches!(self.prev_sibling, Some(ImmediatePrevSibling::IfExpr)) | 310 | matches!(self.prev_sibling, Some(ImmediatePrevSibling::IfExpr)) |
307 | } | 311 | } |
308 | 312 | ||
309 | pub(crate) fn is_path_disallowed(&self) -> bool { | 313 | pub(crate) fn is_path_disallowed(&self) -> bool { |
310 | matches!( | 314 | self.attribute_under_caret.is_some() |
311 | self.completion_location, | 315 | || self.previous_token_is(T![unsafe]) |
312 | Some(ImmediateLocation::Attribute(_)) | 316 | || matches!( |
313 | | Some(ImmediateLocation::ModDeclaration(_)) | 317 | self.prev_sibling, |
314 | | Some(ImmediateLocation::RecordPat(_)) | 318 | Some(ImmediatePrevSibling::Attribute) | Some(ImmediatePrevSibling::Visibility) |
315 | | Some(ImmediateLocation::RecordExpr(_)) | 319 | ) |
316 | ) || self.attribute_under_caret.is_some() | 320 | || matches!( |
321 | self.completion_location, | ||
322 | Some(ImmediateLocation::Attribute(_)) | ||
323 | | Some(ImmediateLocation::ModDeclaration(_)) | ||
324 | | Some(ImmediateLocation::RecordPat(_)) | ||
325 | | Some(ImmediateLocation::RecordExpr(_)) | ||
326 | ) | ||
317 | } | 327 | } |
318 | 328 | ||
319 | pub(crate) fn expects_expression(&self) -> bool { | 329 | pub(crate) fn expects_expression(&self) -> bool { |
@@ -685,7 +695,7 @@ mod tests { | |||
685 | use expect_test::{expect, Expect}; | 695 | use expect_test::{expect, Expect}; |
686 | use hir::HirDisplay; | 696 | use hir::HirDisplay; |
687 | 697 | ||
688 | use crate::test_utils::{position, TEST_CONFIG}; | 698 | use crate::tests::{position, TEST_CONFIG}; |
689 | 699 | ||
690 | use super::CompletionContext; | 700 | use super::CompletionContext; |
691 | 701 | ||
diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs index 18983aa01..bf73818dc 100644 --- a/crates/ide_completion/src/lib.rs +++ b/crates/ide_completion/src/lib.rs | |||
@@ -1,14 +1,14 @@ | |||
1 | //! `completions` crate provides utilities for generating completions of user input. | 1 | //! `completions` crate provides utilities for generating completions of user input. |
2 | 2 | ||
3 | mod completions; | ||
3 | mod config; | 4 | mod config; |
4 | mod item; | ||
5 | mod context; | 5 | mod context; |
6 | mod item; | ||
6 | mod patterns; | 7 | mod patterns; |
7 | #[cfg(test)] | ||
8 | mod test_utils; | ||
9 | mod render; | 8 | mod render; |
10 | 9 | ||
11 | mod completions; | 10 | #[cfg(test)] |
11 | mod tests; | ||
12 | 12 | ||
13 | use completions::flyimport::position_for_import; | 13 | use completions::flyimport::position_for_import; |
14 | use ide_db::{ | 14 | use ide_db::{ |
@@ -141,6 +141,7 @@ pub fn completions( | |||
141 | let ctx = CompletionContext::new(db, position, config)?; | 141 | let ctx = CompletionContext::new(db, position, config)?; |
142 | 142 | ||
143 | if ctx.no_completion_required() { | 143 | if ctx.no_completion_required() { |
144 | cov_mark::hit!(no_completion_required); | ||
144 | // No work required here. | 145 | // No work required here. |
145 | return None; | 146 | return None; |
146 | } | 147 | } |
@@ -200,117 +201,3 @@ pub fn resolve_completion_edits( | |||
200 | 201 | ||
201 | ImportEdit { import, scope }.to_text_edit(config.insert_use).map(|edit| vec![edit]) | 202 | ImportEdit { import, scope }.to_text_edit(config.insert_use).map(|edit| vec![edit]) |
202 | } | 203 | } |
203 | |||
204 | #[cfg(test)] | ||
205 | mod tests { | ||
206 | use crate::test_utils::{self, TEST_CONFIG}; | ||
207 | |||
208 | struct DetailAndDocumentation<'a> { | ||
209 | detail: &'a str, | ||
210 | documentation: &'a str, | ||
211 | } | ||
212 | |||
213 | fn check_detail_and_documentation(ra_fixture: &str, expected: DetailAndDocumentation) { | ||
214 | let (db, position) = test_utils::position(ra_fixture); | ||
215 | let config = TEST_CONFIG; | ||
216 | let completions: Vec<_> = crate::completions(&db, &config, position).unwrap().into(); | ||
217 | for item in completions { | ||
218 | if item.detail() == Some(expected.detail) { | ||
219 | let opt = item.documentation(); | ||
220 | let doc = opt.as_ref().map(|it| it.as_str()); | ||
221 | assert_eq!(doc, Some(expected.documentation)); | ||
222 | return; | ||
223 | } | ||
224 | } | ||
225 | panic!("completion detail not found: {}", expected.detail) | ||
226 | } | ||
227 | |||
228 | fn check_no_completion(ra_fixture: &str) { | ||
229 | let (db, position) = test_utils::position(ra_fixture); | ||
230 | let config = TEST_CONFIG; | ||
231 | |||
232 | let completions: Option<Vec<String>> = crate::completions(&db, &config, position) | ||
233 | .and_then(|completions| { | ||
234 | let completions: Vec<_> = completions.into(); | ||
235 | if completions.is_empty() { | ||
236 | None | ||
237 | } else { | ||
238 | Some(completions) | ||
239 | } | ||
240 | }) | ||
241 | .map(|completions| { | ||
242 | completions.into_iter().map(|completion| format!("{:?}", completion)).collect() | ||
243 | }); | ||
244 | |||
245 | // `assert_eq` instead of `assert!(completions.is_none())` to get the list of completions if test will panic. | ||
246 | assert_eq!(completions, None, "Completions were generated, but weren't expected"); | ||
247 | } | ||
248 | |||
249 | #[test] | ||
250 | fn test_completion_detail_from_macro_generated_struct_fn_doc_attr() { | ||
251 | check_detail_and_documentation( | ||
252 | r#" | ||
253 | macro_rules! bar { | ||
254 | () => { | ||
255 | struct Bar; | ||
256 | impl Bar { | ||
257 | #[doc = "Do the foo"] | ||
258 | fn foo(&self) {} | ||
259 | } | ||
260 | } | ||
261 | } | ||
262 | |||
263 | bar!(); | ||
264 | |||
265 | fn foo() { | ||
266 | let bar = Bar; | ||
267 | bar.fo$0; | ||
268 | } | ||
269 | "#, | ||
270 | DetailAndDocumentation { detail: "fn(&self)", documentation: "Do the foo" }, | ||
271 | ); | ||
272 | } | ||
273 | |||
274 | #[test] | ||
275 | fn test_completion_detail_from_macro_generated_struct_fn_doc_comment() { | ||
276 | check_detail_and_documentation( | ||
277 | r#" | ||
278 | macro_rules! bar { | ||
279 | () => { | ||
280 | struct Bar; | ||
281 | impl Bar { | ||
282 | /// Do the foo | ||
283 | fn foo(&self) {} | ||
284 | } | ||
285 | } | ||
286 | } | ||
287 | |||
288 | bar!(); | ||
289 | |||
290 | fn foo() { | ||
291 | let bar = Bar; | ||
292 | bar.fo$0; | ||
293 | } | ||
294 | "#, | ||
295 | DetailAndDocumentation { detail: "fn(&self)", documentation: "Do the foo" }, | ||
296 | ); | ||
297 | } | ||
298 | |||
299 | #[test] | ||
300 | fn test_no_completions_required() { | ||
301 | // There must be no hint for 'in' keyword. | ||
302 | check_no_completion(r#"fn foo() { for i i$0 }"#); | ||
303 | // After 'in' keyword hints may be spawned. | ||
304 | check_detail_and_documentation( | ||
305 | r#" | ||
306 | /// Do the foo | ||
307 | fn foo() -> &'static str { "foo" } | ||
308 | |||
309 | fn bar() { | ||
310 | for c in fo$0 | ||
311 | } | ||
312 | "#, | ||
313 | DetailAndDocumentation { detail: "fn() -> &str", documentation: "Do the foo" }, | ||
314 | ); | ||
315 | } | ||
316 | } | ||
diff --git a/crates/ide_completion/src/patterns.rs b/crates/ide_completion/src/patterns.rs index 72e67e3c4..62e4334de 100644 --- a/crates/ide_completion/src/patterns.rs +++ b/crates/ide_completion/src/patterns.rs | |||
@@ -11,7 +11,7 @@ use syntax::{ | |||
11 | }; | 11 | }; |
12 | 12 | ||
13 | #[cfg(test)] | 13 | #[cfg(test)] |
14 | use crate::test_utils::{check_pattern_is_applicable, check_pattern_is_not_applicable}; | 14 | use crate::tests::{check_pattern_is_applicable, check_pattern_is_not_applicable}; |
15 | 15 | ||
16 | /// Immediate previous node to what we are completing. | 16 | /// Immediate previous node to what we are completing. |
17 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | 17 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
@@ -19,6 +19,8 @@ pub(crate) enum ImmediatePrevSibling { | |||
19 | IfExpr, | 19 | IfExpr, |
20 | TraitDefName, | 20 | TraitDefName, |
21 | ImplDefType, | 21 | ImplDefType, |
22 | Visibility, | ||
23 | Attribute, | ||
22 | } | 24 | } |
23 | 25 | ||
24 | /// Direct parent "thing" of what we are currently completing. | 26 | /// Direct parent "thing" of what we are currently completing. |
@@ -79,6 +81,17 @@ pub(crate) fn determine_prev_sibling(name_like: &ast::NameLike) -> Option<Immedi | |||
79 | _ => node, | 81 | _ => node, |
80 | }; | 82 | }; |
81 | let prev_sibling = non_trivia_sibling(node.into(), Direction::Prev)?.into_node()?; | 83 | let prev_sibling = non_trivia_sibling(node.into(), Direction::Prev)?.into_node()?; |
84 | if prev_sibling.kind() == ERROR { | ||
85 | let prev_sibling = prev_sibling.first_child()?; | ||
86 | let res = match_ast! { | ||
87 | match prev_sibling { | ||
88 | // vis followed by random ident will always error the parser | ||
89 | ast::Visibility(_it) => ImmediatePrevSibling::Visibility, | ||
90 | _ => return None, | ||
91 | } | ||
92 | }; | ||
93 | return Some(res); | ||
94 | } | ||
82 | let res = match_ast! { | 95 | let res = match_ast! { |
83 | match prev_sibling { | 96 | match prev_sibling { |
84 | ast::ExprStmt(it) => { | 97 | ast::ExprStmt(it) => { |
@@ -101,6 +114,7 @@ pub(crate) fn determine_prev_sibling(name_like: &ast::NameLike) -> Option<Immedi | |||
101 | } else { | 114 | } else { |
102 | return None | 115 | return None |
103 | }, | 116 | }, |
117 | ast::Attr(_it) => ImmediatePrevSibling::Attribute, | ||
104 | _ => return None, | 118 | _ => return None, |
105 | } | 119 | } |
106 | }; | 120 | }; |
@@ -310,7 +324,7 @@ fn previous_non_trivia_token(token: SyntaxToken) -> Option<SyntaxToken> { | |||
310 | mod tests { | 324 | mod tests { |
311 | use syntax::algo::find_node_at_offset; | 325 | use syntax::algo::find_node_at_offset; |
312 | 326 | ||
313 | use crate::test_utils::position; | 327 | use crate::tests::position; |
314 | 328 | ||
315 | use super::*; | 329 | use super::*; |
316 | 330 | ||
@@ -421,4 +435,14 @@ mod tests { | |||
421 | check_prev_sibling(r"fn foo() { if true {} w$0", ImmediatePrevSibling::IfExpr); | 435 | check_prev_sibling(r"fn foo() { if true {} w$0", ImmediatePrevSibling::IfExpr); |
422 | check_prev_sibling(r"fn foo() { if true {}; w$0", None); | 436 | check_prev_sibling(r"fn foo() { if true {}; w$0", None); |
423 | } | 437 | } |
438 | |||
439 | #[test] | ||
440 | fn test_vis_prev_sibling() { | ||
441 | check_prev_sibling(r"pub w$0", ImmediatePrevSibling::Visibility); | ||
442 | } | ||
443 | |||
444 | #[test] | ||
445 | fn test_attr_prev_sibling() { | ||
446 | check_prev_sibling(r"#[attr] w$0", ImmediatePrevSibling::Attribute); | ||
447 | } | ||
424 | } | 448 | } |
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index 2bd2c44d0..4b55f7504 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs | |||
@@ -335,7 +335,7 @@ mod tests { | |||
335 | 335 | ||
336 | use crate::{ | 336 | use crate::{ |
337 | item::CompletionRelevanceTypeMatch, | 337 | item::CompletionRelevanceTypeMatch, |
338 | test_utils::{check_edit, do_completion, get_all_items, TEST_CONFIG}, | 338 | tests::{check_edit, do_completion, get_all_items, TEST_CONFIG}, |
339 | CompletionKind, CompletionRelevance, | 339 | CompletionKind, CompletionRelevance, |
340 | }; | 340 | }; |
341 | 341 | ||
diff --git a/crates/ide_completion/src/render/enum_variant.rs b/crates/ide_completion/src/render/enum_variant.rs index 28f056e77..91dc178f3 100644 --- a/crates/ide_completion/src/render/enum_variant.rs +++ b/crates/ide_completion/src/render/enum_variant.rs | |||
@@ -121,7 +121,7 @@ impl<'a> EnumRender<'a> { | |||
121 | 121 | ||
122 | #[cfg(test)] | 122 | #[cfg(test)] |
123 | mod tests { | 123 | mod tests { |
124 | use crate::test_utils::check_edit; | 124 | use crate::tests::check_edit; |
125 | 125 | ||
126 | #[test] | 126 | #[test] |
127 | fn inserts_parens_for_tuple_enums() { | 127 | fn inserts_parens_for_tuple_enums() { |
diff --git a/crates/ide_completion/src/render/function.rs b/crates/ide_completion/src/render/function.rs index 1357b9f4a..19f2c86e9 100644 --- a/crates/ide_completion/src/render/function.rs +++ b/crates/ide_completion/src/render/function.rs | |||
@@ -191,7 +191,7 @@ impl<'a> FunctionRender<'a> { | |||
191 | #[cfg(test)] | 191 | #[cfg(test)] |
192 | mod tests { | 192 | mod tests { |
193 | use crate::{ | 193 | use crate::{ |
194 | test_utils::{check_edit, check_edit_with_config, TEST_CONFIG}, | 194 | tests::{check_edit, check_edit_with_config, TEST_CONFIG}, |
195 | CompletionConfig, | 195 | CompletionConfig, |
196 | }; | 196 | }; |
197 | 197 | ||
diff --git a/crates/ide_completion/src/render/macro_.rs b/crates/ide_completion/src/render/macro_.rs index 3a7238bb8..d5a1f45d3 100644 --- a/crates/ide_completion/src/render/macro_.rs +++ b/crates/ide_completion/src/render/macro_.rs | |||
@@ -133,7 +133,7 @@ fn guess_macro_braces(macro_name: &str, docs: &str) -> (&'static str, &'static s | |||
133 | 133 | ||
134 | #[cfg(test)] | 134 | #[cfg(test)] |
135 | mod tests { | 135 | mod tests { |
136 | use crate::test_utils::check_edit; | 136 | use crate::tests::check_edit; |
137 | 137 | ||
138 | #[test] | 138 | #[test] |
139 | fn dont_insert_macro_call_parens_unncessary() { | 139 | fn dont_insert_macro_call_parens_unncessary() { |
diff --git a/crates/ide_completion/src/test_utils.rs b/crates/ide_completion/src/tests.rs index b0a4b2026..1495924ea 100644 --- a/crates/ide_completion/src/test_utils.rs +++ b/crates/ide_completion/src/tests.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! Runs completion for testing purposes. | 1 | mod item_list; |
2 | 2 | ||
3 | use hir::{PrefixKind, Semantics}; | 3 | use hir::{PrefixKind, Semantics}; |
4 | use ide_db::{ | 4 | use ide_db::{ |
@@ -31,6 +31,14 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig { | |||
31 | }, | 31 | }, |
32 | }; | 32 | }; |
33 | 33 | ||
34 | fn completion_list(code: &str) -> String { | ||
35 | completion_list_with_config(TEST_CONFIG, code) | ||
36 | } | ||
37 | |||
38 | fn completion_list_with_config(config: CompletionConfig, code: &str) -> String { | ||
39 | render_completion_list(get_all_items(config, code)) | ||
40 | } | ||
41 | |||
34 | /// Creates analysis from a multi-file fixture, returns positions marked with $0. | 42 | /// Creates analysis from a multi-file fixture, returns positions marked with $0. |
35 | pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) { | 43 | pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) { |
36 | let change_fixture = ChangeFixture::parse(ra_fixture); | 44 | let change_fixture = ChangeFixture::parse(ra_fixture); |
@@ -57,24 +65,27 @@ pub(crate) fn do_completion_with_config( | |||
57 | .collect() | 65 | .collect() |
58 | } | 66 | } |
59 | 67 | ||
60 | pub(crate) fn completion_list(code: &str, kind: CompletionKind) -> String { | 68 | pub(crate) fn filtered_completion_list(code: &str, kind: CompletionKind) -> String { |
61 | completion_list_with_config(TEST_CONFIG, code, kind) | 69 | filtered_completion_list_with_config(TEST_CONFIG, code, kind) |
62 | } | 70 | } |
63 | 71 | ||
64 | pub(crate) fn completion_list_with_config( | 72 | pub(crate) fn filtered_completion_list_with_config( |
65 | config: CompletionConfig, | 73 | config: CompletionConfig, |
66 | code: &str, | 74 | code: &str, |
67 | kind: CompletionKind, | 75 | kind: CompletionKind, |
68 | ) -> String { | 76 | ) -> String { |
69 | let kind_completions: Vec<CompletionItem> = | 77 | let kind_completions: Vec<CompletionItem> = |
70 | get_all_items(config, code).into_iter().filter(|c| c.completion_kind == kind).collect(); | 78 | get_all_items(config, code).into_iter().filter(|c| c.completion_kind == kind).collect(); |
71 | let label_width = kind_completions | 79 | render_completion_list(kind_completions) |
72 | .iter() | 80 | } |
73 | .map(|it| monospace_width(it.label())) | 81 | |
74 | .max() | 82 | fn render_completion_list(completions: Vec<CompletionItem>) -> String { |
75 | .unwrap_or_default() | 83 | fn monospace_width(s: &str) -> usize { |
76 | .min(16); | 84 | s.chars().count() |
77 | kind_completions | 85 | } |
86 | let label_width = | ||
87 | completions.iter().map(|it| monospace_width(it.label())).max().unwrap_or_default().min(16); | ||
88 | completions | ||
78 | .into_iter() | 89 | .into_iter() |
79 | .map(|it| { | 90 | .map(|it| { |
80 | let tag = it.kind().unwrap().tag(); | 91 | let tag = it.kind().unwrap().tag(); |
@@ -93,10 +104,6 @@ pub(crate) fn completion_list_with_config( | |||
93 | .collect() | 104 | .collect() |
94 | } | 105 | } |
95 | 106 | ||
96 | fn monospace_width(s: &str) -> usize { | ||
97 | s.chars().count() | ||
98 | } | ||
99 | |||
100 | pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) { | 107 | pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) { |
101 | check_edit_with_config(TEST_CONFIG, what, ra_fixture_before, ra_fixture_after) | 108 | check_edit_with_config(TEST_CONFIG, what, ra_fixture_before, ra_fixture_after) |
102 | } | 109 | } |
@@ -152,3 +159,18 @@ pub(crate) fn get_all_items(config: CompletionConfig, code: &str) -> Vec<Complet | |||
152 | let (db, position) = position(code); | 159 | let (db, position) = position(code); |
153 | crate::completions(&db, &config, position).unwrap().into() | 160 | crate::completions(&db, &config, position).unwrap().into() |
154 | } | 161 | } |
162 | |||
163 | fn check_no_completion(ra_fixture: &str) { | ||
164 | let (db, position) = position(ra_fixture); | ||
165 | |||
166 | assert!( | ||
167 | crate::completions(&db, &TEST_CONFIG, position).is_none(), | ||
168 | "Completions were generated, but weren't expected" | ||
169 | ); | ||
170 | } | ||
171 | |||
172 | #[test] | ||
173 | fn test_no_completions_required() { | ||
174 | cov_mark::check!(no_completion_required); | ||
175 | check_no_completion(r#"fn foo() { for i i$0 }"#); | ||
176 | } | ||
diff --git a/crates/ide_completion/src/tests/item_list.rs b/crates/ide_completion/src/tests/item_list.rs new file mode 100644 index 000000000..7c124ac37 --- /dev/null +++ b/crates/ide_completion/src/tests/item_list.rs | |||
@@ -0,0 +1,223 @@ | |||
1 | use expect_test::{expect, Expect}; | ||
2 | |||
3 | use crate::tests::completion_list; | ||
4 | |||
5 | fn check(ra_fixture: &str, expect: Expect) { | ||
6 | let base = r#"#[rustc_builtin_macro] | ||
7 | pub macro Clone {} | ||
8 | enum Enum { Variant } | ||
9 | struct Struct {} | ||
10 | #[macro_export] | ||
11 | macro_rules! foo {} | ||
12 | mod bar {} | ||
13 | const CONST: () = (); | ||
14 | trait Trait {} | ||
15 | "#; | ||
16 | let actual = completion_list(&format!("{}{}", base, ra_fixture)); | ||
17 | expect.assert_eq(&actual) | ||
18 | } | ||
19 | |||
20 | #[test] | ||
21 | fn in_mod_item_list() { | ||
22 | check( | ||
23 | r#"mod tests { $0 }"#, | ||
24 | expect![[r##" | ||
25 | kw pub(crate) | ||
26 | kw pub | ||
27 | kw unsafe | ||
28 | kw fn | ||
29 | kw const | ||
30 | kw type | ||
31 | kw impl | ||
32 | kw extern | ||
33 | kw use | ||
34 | kw trait | ||
35 | kw static | ||
36 | kw mod | ||
37 | kw enum | ||
38 | kw struct | ||
39 | kw union | ||
40 | sn tmod (Test module) | ||
41 | sn tfn (Test function) | ||
42 | sn macro_rules | ||
43 | ma foo!(…) #[macro_export] macro_rules! foo | ||
44 | "##]], | ||
45 | ) | ||
46 | } | ||
47 | |||
48 | #[test] | ||
49 | fn in_source_file_item_list() { | ||
50 | check( | ||
51 | r#"$0"#, | ||
52 | expect![[r##" | ||
53 | kw pub(crate) | ||
54 | kw pub | ||
55 | kw unsafe | ||
56 | kw fn | ||
57 | kw const | ||
58 | kw type | ||
59 | kw impl | ||
60 | kw extern | ||
61 | kw use | ||
62 | kw trait | ||
63 | kw static | ||
64 | kw mod | ||
65 | kw enum | ||
66 | kw struct | ||
67 | kw union | ||
68 | sn tmod (Test module) | ||
69 | sn tfn (Test function) | ||
70 | sn macro_rules | ||
71 | md bar | ||
72 | ma foo!(…) #[macro_export] macro_rules! foo | ||
73 | ma foo!(…) #[macro_export] macro_rules! foo | ||
74 | "##]], | ||
75 | ) | ||
76 | } | ||
77 | |||
78 | #[test] | ||
79 | fn in_item_list_after_attr() { | ||
80 | check( | ||
81 | r#"#[attr] $0"#, | ||
82 | expect![[r#" | ||
83 | kw pub(crate) | ||
84 | kw pub | ||
85 | kw unsafe | ||
86 | kw fn | ||
87 | kw const | ||
88 | kw type | ||
89 | kw impl | ||
90 | kw extern | ||
91 | kw use | ||
92 | kw trait | ||
93 | kw static | ||
94 | kw mod | ||
95 | kw enum | ||
96 | kw struct | ||
97 | kw union | ||
98 | sn tmod (Test module) | ||
99 | sn tfn (Test function) | ||
100 | sn macro_rules | ||
101 | "#]], | ||
102 | ) | ||
103 | } | ||
104 | |||
105 | #[test] | ||
106 | fn in_qualified_path() { | ||
107 | check( | ||
108 | r#"crate::$0"#, | ||
109 | expect![[r##" | ||
110 | kw pub(crate) | ||
111 | kw pub | ||
112 | kw unsafe | ||
113 | kw fn | ||
114 | kw const | ||
115 | kw type | ||
116 | kw impl | ||
117 | kw extern | ||
118 | kw use | ||
119 | kw trait | ||
120 | kw static | ||
121 | kw mod | ||
122 | kw enum | ||
123 | kw struct | ||
124 | kw union | ||
125 | md bar | ||
126 | ma foo!(…) #[macro_export] macro_rules! foo | ||
127 | "##]], | ||
128 | ) | ||
129 | } | ||
130 | |||
131 | #[test] | ||
132 | fn after_unsafe_token() { | ||
133 | check( | ||
134 | r#"unsafe $0"#, | ||
135 | expect![[r#" | ||
136 | kw fn | ||
137 | kw trait | ||
138 | kw impl | ||
139 | "#]], | ||
140 | ); | ||
141 | } | ||
142 | |||
143 | #[test] | ||
144 | fn after_visibility() { | ||
145 | check( | ||
146 | r#"pub $0"#, | ||
147 | expect![[r#" | ||
148 | kw unsafe | ||
149 | kw fn | ||
150 | kw const | ||
151 | kw type | ||
152 | kw use | ||
153 | kw trait | ||
154 | kw static | ||
155 | kw mod | ||
156 | kw enum | ||
157 | kw struct | ||
158 | kw union | ||
159 | "#]], | ||
160 | ); | ||
161 | } | ||
162 | |||
163 | #[test] | ||
164 | fn after_visibility_unsafe() { | ||
165 | // FIXME this shouldn't show `impl` | ||
166 | check( | ||
167 | r#"pub unsafe $0"#, | ||
168 | expect![[r#" | ||
169 | kw fn | ||
170 | kw trait | ||
171 | kw impl | ||
172 | "#]], | ||
173 | ); | ||
174 | } | ||
175 | |||
176 | #[test] | ||
177 | fn in_impl_assoc_item_list() { | ||
178 | check( | ||
179 | r#"impl Struct { $0 }"#, | ||
180 | expect![[r##" | ||
181 | kw pub(crate) | ||
182 | kw pub | ||
183 | kw unsafe | ||
184 | kw fn | ||
185 | kw const | ||
186 | kw type | ||
187 | md bar | ||
188 | ma foo!(…) #[macro_export] macro_rules! foo | ||
189 | ma foo!(…) #[macro_export] macro_rules! foo | ||
190 | "##]], | ||
191 | ) | ||
192 | } | ||
193 | |||
194 | #[test] | ||
195 | fn in_impl_assoc_item_list_after_attr() { | ||
196 | check( | ||
197 | r#"impl Struct { #[attr] $0 }"#, | ||
198 | expect![[r#" | ||
199 | kw pub(crate) | ||
200 | kw pub | ||
201 | kw unsafe | ||
202 | kw fn | ||
203 | kw const | ||
204 | kw type | ||
205 | "#]], | ||
206 | ) | ||
207 | } | ||
208 | |||
209 | #[test] | ||
210 | fn in_trait_assoc_item_list() { | ||
211 | check( | ||
212 | r"trait Foo { $0 }", | ||
213 | expect![[r##" | ||
214 | kw unsafe | ||
215 | kw fn | ||
216 | kw const | ||
217 | kw type | ||
218 | md bar | ||
219 | ma foo!(…) #[macro_export] macro_rules! foo | ||
220 | ma foo!(…) #[macro_export] macro_rules! foo | ||
221 | "##]], | ||
222 | ); | ||
223 | } | ||