diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-06-16 20:53:43 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-06-16 20:53:43 +0100 |
commit | d6b8af44829521a9f925c4d87599efa3fef38edc (patch) | |
tree | 47119538effd381ecd8e15d422103512f2b47406 /crates/ide_completion/src | |
parent | f38770cd2606148bfe764351849ea7ebea45132c (diff) | |
parent | aa644b55859c6b5c6695a5d4fb35d1b6efbbebcc (diff) |
Merge #9301
9301: internal: Start refactoring ide_completion tests r=Veykril a=Veykril
Our current completion test infra resovles around usually just checking a specific `CompletionKind` which is suboptimal. We only see what we want to see in tests with this causing us to miss a lot of incorrect completions we are doing. Instead we should test for different cursor locations for all kinds(sans the magic kind maybe? not sure yet). This way we will also see potential duplicate completions that merely different in their kind.
Also since most completion submodules complete things in tests of other modules due to the tests overlapping it makes more sense to group these tests differently which implies moving them to a new module. Exceptions for this might be stuff like attribute completion as these cannot currently interfere.
I only wrote a few tests to check for completions in `ItemList` position so far and I already found a few incorrect/irrelevant completions as these haven't been tested properly due to them being hidden by the `CompletionKind` filtering.
I think `CompletionKind` doesn't really seem to be beneficial to me as to I can't think of a occasion where we would want to only check a specific completion kind.
Co-authored-by: Lukas Wirth <[email protected]>
Diffstat (limited to 'crates/ide_completion/src')
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 | } | ||