diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_def/src/nameres/tests/incremental.rs | 74 | ||||
-rw-r--r-- | crates/hir_ty/src/tests.rs | 45 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/incremental.rs | 51 | ||||
-rw-r--r-- | crates/ide/src/annotations.rs | 34 | ||||
-rwxr-xr-x | crates/ide/src/folding_ranges.rs | 17 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/keyword.rs | 15 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/unqualified_path.rs | 30 | ||||
-rw-r--r-- | crates/ide_completion/src/context.rs | 4 | ||||
-rw-r--r-- | crates/ide_completion/src/patterns.rs | 29 | ||||
-rw-r--r-- | crates/ide_completion/src/render/macro_.rs | 6 | ||||
-rw-r--r-- | crates/rust-analyzer/src/caps.rs | 8 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 1 |
12 files changed, 226 insertions, 88 deletions
diff --git a/crates/hir_def/src/nameres/tests/incremental.rs b/crates/hir_def/src/nameres/tests/incremental.rs index d884a6eb4..7bf152e26 100644 --- a/crates/hir_def/src/nameres/tests/incremental.rs +++ b/crates/hir_def/src/nameres/tests/incremental.rs | |||
@@ -1,6 +1,8 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use base_db::SourceDatabaseExt; | 3 | use base_db::{salsa::SweepStrategy, SourceDatabaseExt}; |
4 | |||
5 | use crate::{AdtId, ModuleDefId}; | ||
4 | 6 | ||
5 | use super::*; | 7 | use super::*; |
6 | 8 | ||
@@ -163,3 +165,73 @@ m!(Z); | |||
163 | assert_eq!(n_reparsed_macros, 0); | 165 | assert_eq!(n_reparsed_macros, 0); |
164 | } | 166 | } |
165 | } | 167 | } |
168 | |||
169 | #[test] | ||
170 | fn item_tree_prevents_reparsing() { | ||
171 | // The `ItemTree` is used by both name resolution and the various queries in `adt.rs` and | ||
172 | // `data.rs`. After computing the `ItemTree` and deleting the parse tree, we should be able to | ||
173 | // run those other queries without triggering a reparse. | ||
174 | |||
175 | let (db, pos) = TestDB::with_position( | ||
176 | r#" | ||
177 | pub struct S; | ||
178 | pub union U {} | ||
179 | pub enum E { | ||
180 | Variant, | ||
181 | } | ||
182 | pub fn f(_: S) { $0 } | ||
183 | pub trait Tr {} | ||
184 | impl Tr for () {} | ||
185 | pub const C: u8 = 0; | ||
186 | pub static ST: u8 = 0; | ||
187 | pub type Ty = (); | ||
188 | "#, | ||
189 | ); | ||
190 | let krate = db.test_crate(); | ||
191 | { | ||
192 | let events = db.log_executed(|| { | ||
193 | db.file_item_tree(pos.file_id.into()); | ||
194 | }); | ||
195 | let n_calculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count(); | ||
196 | assert_eq!(n_calculated_item_trees, 1); | ||
197 | let n_parsed_files = events.iter().filter(|it| it.contains("parse(")).count(); | ||
198 | assert_eq!(n_parsed_files, 1); | ||
199 | } | ||
200 | |||
201 | // Delete the parse tree. | ||
202 | let sweep = SweepStrategy::default().discard_values().sweep_all_revisions(); | ||
203 | base_db::ParseQuery.in_db(&db).sweep(sweep); | ||
204 | |||
205 | { | ||
206 | let events = db.log_executed(|| { | ||
207 | let crate_def_map = db.crate_def_map(krate); | ||
208 | let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); | ||
209 | assert_eq!(module_data.scope.resolutions().count(), 8); | ||
210 | assert_eq!(module_data.scope.impls().count(), 1); | ||
211 | |||
212 | for imp in module_data.scope.impls() { | ||
213 | db.impl_data(imp); | ||
214 | } | ||
215 | |||
216 | for (_, res) in module_data.scope.resolutions() { | ||
217 | match res.values.or(res.types).unwrap().0 { | ||
218 | ModuleDefId::FunctionId(f) => drop(db.function_data(f)), | ||
219 | ModuleDefId::AdtId(adt) => match adt { | ||
220 | AdtId::StructId(it) => drop(db.struct_data(it)), | ||
221 | AdtId::UnionId(it) => drop(db.union_data(it)), | ||
222 | AdtId::EnumId(it) => drop(db.enum_data(it)), | ||
223 | }, | ||
224 | ModuleDefId::ConstId(it) => drop(db.const_data(it)), | ||
225 | ModuleDefId::StaticId(it) => drop(db.static_data(it)), | ||
226 | ModuleDefId::TraitId(it) => drop(db.trait_data(it)), | ||
227 | ModuleDefId::TypeAliasId(it) => drop(db.type_alias_data(it)), | ||
228 | ModuleDefId::EnumVariantId(_) | ||
229 | | ModuleDefId::ModuleId(_) | ||
230 | | ModuleDefId::BuiltinType(_) => unreachable!(), | ||
231 | } | ||
232 | } | ||
233 | }); | ||
234 | let n_reparsed_files = events.iter().filter(|it| it.contains("parse(")).count(); | ||
235 | assert_eq!(n_reparsed_files, 0); | ||
236 | } | ||
237 | } | ||
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs index cc819373c..9d726b024 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs | |||
@@ -7,6 +7,7 @@ mod traits; | |||
7 | mod method_resolution; | 7 | mod method_resolution; |
8 | mod macros; | 8 | mod macros; |
9 | mod display_source_code; | 9 | mod display_source_code; |
10 | mod incremental; | ||
10 | 11 | ||
11 | use std::{env, sync::Arc}; | 12 | use std::{env, sync::Arc}; |
12 | 13 | ||
@@ -317,50 +318,6 @@ fn ellipsize(mut text: String, max_len: usize) -> String { | |||
317 | text | 318 | text |
318 | } | 319 | } |
319 | 320 | ||
320 | #[test] | ||
321 | fn typing_whitespace_inside_a_function_should_not_invalidate_types() { | ||
322 | let (mut db, pos) = TestDB::with_position( | ||
323 | " | ||
324 | //- /lib.rs | ||
325 | fn foo() -> i32 { | ||
326 | $01 + 1 | ||
327 | } | ||
328 | ", | ||
329 | ); | ||
330 | { | ||
331 | let events = db.log_executed(|| { | ||
332 | let module = db.module_for_file(pos.file_id); | ||
333 | let crate_def_map = module.def_map(&db); | ||
334 | visit_module(&db, &crate_def_map, module.local_id, &mut |def| { | ||
335 | db.infer(def); | ||
336 | }); | ||
337 | }); | ||
338 | assert!(format!("{:?}", events).contains("infer")) | ||
339 | } | ||
340 | |||
341 | let new_text = " | ||
342 | fn foo() -> i32 { | ||
343 | 1 | ||
344 | + | ||
345 | 1 | ||
346 | } | ||
347 | " | ||
348 | .to_string(); | ||
349 | |||
350 | db.set_file_text(pos.file_id, Arc::new(new_text)); | ||
351 | |||
352 | { | ||
353 | let events = db.log_executed(|| { | ||
354 | let module = db.module_for_file(pos.file_id); | ||
355 | let crate_def_map = module.def_map(&db); | ||
356 | visit_module(&db, &crate_def_map, module.local_id, &mut |def| { | ||
357 | db.infer(def); | ||
358 | }); | ||
359 | }); | ||
360 | assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events) | ||
361 | } | ||
362 | } | ||
363 | |||
364 | fn check_infer(ra_fixture: &str, expect: Expect) { | 321 | fn check_infer(ra_fixture: &str, expect: Expect) { |
365 | let mut actual = infer(ra_fixture); | 322 | let mut actual = infer(ra_fixture); |
366 | actual.push('\n'); | 323 | actual.push('\n'); |
diff --git a/crates/hir_ty/src/tests/incremental.rs b/crates/hir_ty/src/tests/incremental.rs new file mode 100644 index 000000000..3e08e83e8 --- /dev/null +++ b/crates/hir_ty/src/tests/incremental.rs | |||
@@ -0,0 +1,51 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
3 | use base_db::{fixture::WithFixture, SourceDatabaseExt}; | ||
4 | |||
5 | use crate::{db::HirDatabase, test_db::TestDB}; | ||
6 | |||
7 | use super::visit_module; | ||
8 | |||
9 | #[test] | ||
10 | fn typing_whitespace_inside_a_function_should_not_invalidate_types() { | ||
11 | let (mut db, pos) = TestDB::with_position( | ||
12 | " | ||
13 | //- /lib.rs | ||
14 | fn foo() -> i32 { | ||
15 | $01 + 1 | ||
16 | } | ||
17 | ", | ||
18 | ); | ||
19 | { | ||
20 | let events = db.log_executed(|| { | ||
21 | let module = db.module_for_file(pos.file_id); | ||
22 | let crate_def_map = module.def_map(&db); | ||
23 | visit_module(&db, &crate_def_map, module.local_id, &mut |def| { | ||
24 | db.infer(def); | ||
25 | }); | ||
26 | }); | ||
27 | assert!(format!("{:?}", events).contains("infer")) | ||
28 | } | ||
29 | |||
30 | let new_text = " | ||
31 | fn foo() -> i32 { | ||
32 | 1 | ||
33 | + | ||
34 | 1 | ||
35 | } | ||
36 | " | ||
37 | .to_string(); | ||
38 | |||
39 | db.set_file_text(pos.file_id, Arc::new(new_text)); | ||
40 | |||
41 | { | ||
42 | let events = db.log_executed(|| { | ||
43 | let module = db.module_for_file(pos.file_id); | ||
44 | let crate_def_map = module.def_map(&db); | ||
45 | visit_module(&db, &crate_def_map, module.local_id, &mut |def| { | ||
46 | db.infer(def); | ||
47 | }); | ||
48 | }); | ||
49 | assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events) | ||
50 | } | ||
51 | } | ||
diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs index b0c4ed60a..8d68dce05 100644 --- a/crates/ide/src/annotations.rs +++ b/crates/ide/src/annotations.rs | |||
@@ -58,7 +58,7 @@ pub(crate) fn annotations( | |||
58 | } | 58 | } |
59 | 59 | ||
60 | let action = runnable.action(); | 60 | let action = runnable.action(); |
61 | let range = runnable.nav.full_range; | 61 | let range = runnable.nav.focus_or_full_range(); |
62 | 62 | ||
63 | if config.run { | 63 | if config.run { |
64 | annotations.push(Annotation { | 64 | annotations.push(Annotation { |
@@ -224,7 +224,7 @@ fn main() { | |||
224 | expect![[r#" | 224 | expect![[r#" |
225 | [ | 225 | [ |
226 | Annotation { | 226 | Annotation { |
227 | range: 50..85, | 227 | range: 53..57, |
228 | kind: Runnable { | 228 | kind: Runnable { |
229 | debug: false, | 229 | debug: false, |
230 | runnable: Runnable { | 230 | runnable: Runnable { |
@@ -243,7 +243,7 @@ fn main() { | |||
243 | }, | 243 | }, |
244 | }, | 244 | }, |
245 | Annotation { | 245 | Annotation { |
246 | range: 50..85, | 246 | range: 53..57, |
247 | kind: Runnable { | 247 | kind: Runnable { |
248 | debug: true, | 248 | debug: true, |
249 | runnable: Runnable { | 249 | runnable: Runnable { |
@@ -328,7 +328,7 @@ fn main() { | |||
328 | expect![[r#" | 328 | expect![[r#" |
329 | [ | 329 | [ |
330 | Annotation { | 330 | Annotation { |
331 | range: 14..48, | 331 | range: 17..21, |
332 | kind: Runnable { | 332 | kind: Runnable { |
333 | debug: false, | 333 | debug: false, |
334 | runnable: Runnable { | 334 | runnable: Runnable { |
@@ -347,7 +347,7 @@ fn main() { | |||
347 | }, | 347 | }, |
348 | }, | 348 | }, |
349 | Annotation { | 349 | Annotation { |
350 | range: 14..48, | 350 | range: 17..21, |
351 | kind: Runnable { | 351 | kind: Runnable { |
352 | debug: true, | 352 | debug: true, |
353 | runnable: Runnable { | 353 | runnable: Runnable { |
@@ -436,7 +436,7 @@ fn main() { | |||
436 | expect![[r#" | 436 | expect![[r#" |
437 | [ | 437 | [ |
438 | Annotation { | 438 | Annotation { |
439 | range: 66..100, | 439 | range: 69..73, |
440 | kind: Runnable { | 440 | kind: Runnable { |
441 | debug: false, | 441 | debug: false, |
442 | runnable: Runnable { | 442 | runnable: Runnable { |
@@ -455,7 +455,7 @@ fn main() { | |||
455 | }, | 455 | }, |
456 | }, | 456 | }, |
457 | Annotation { | 457 | Annotation { |
458 | range: 66..100, | 458 | range: 69..73, |
459 | kind: Runnable { | 459 | kind: Runnable { |
460 | debug: true, | 460 | debug: true, |
461 | runnable: Runnable { | 461 | runnable: Runnable { |
@@ -597,7 +597,7 @@ fn main() {} | |||
597 | expect![[r#" | 597 | expect![[r#" |
598 | [ | 598 | [ |
599 | Annotation { | 599 | Annotation { |
600 | range: 0..12, | 600 | range: 3..7, |
601 | kind: Runnable { | 601 | kind: Runnable { |
602 | debug: false, | 602 | debug: false, |
603 | runnable: Runnable { | 603 | runnable: Runnable { |
@@ -616,7 +616,7 @@ fn main() {} | |||
616 | }, | 616 | }, |
617 | }, | 617 | }, |
618 | Annotation { | 618 | Annotation { |
619 | range: 0..12, | 619 | range: 3..7, |
620 | kind: Runnable { | 620 | kind: Runnable { |
621 | debug: true, | 621 | debug: true, |
622 | runnable: Runnable { | 622 | runnable: Runnable { |
@@ -670,7 +670,7 @@ fn main() { | |||
670 | expect![[r#" | 670 | expect![[r#" |
671 | [ | 671 | [ |
672 | Annotation { | 672 | Annotation { |
673 | range: 58..95, | 673 | range: 61..65, |
674 | kind: Runnable { | 674 | kind: Runnable { |
675 | debug: false, | 675 | debug: false, |
676 | runnable: Runnable { | 676 | runnable: Runnable { |
@@ -689,7 +689,7 @@ fn main() { | |||
689 | }, | 689 | }, |
690 | }, | 690 | }, |
691 | Annotation { | 691 | Annotation { |
692 | range: 58..95, | 692 | range: 61..65, |
693 | kind: Runnable { | 693 | kind: Runnable { |
694 | debug: true, | 694 | debug: true, |
695 | runnable: Runnable { | 695 | runnable: Runnable { |
@@ -812,7 +812,7 @@ mod tests { | |||
812 | expect![[r#" | 812 | expect![[r#" |
813 | [ | 813 | [ |
814 | Annotation { | 814 | Annotation { |
815 | range: 0..12, | 815 | range: 3..7, |
816 | kind: Runnable { | 816 | kind: Runnable { |
817 | debug: false, | 817 | debug: false, |
818 | runnable: Runnable { | 818 | runnable: Runnable { |
@@ -831,7 +831,7 @@ mod tests { | |||
831 | }, | 831 | }, |
832 | }, | 832 | }, |
833 | Annotation { | 833 | Annotation { |
834 | range: 0..12, | 834 | range: 3..7, |
835 | kind: Runnable { | 835 | kind: Runnable { |
836 | debug: true, | 836 | debug: true, |
837 | runnable: Runnable { | 837 | runnable: Runnable { |
@@ -850,7 +850,7 @@ mod tests { | |||
850 | }, | 850 | }, |
851 | }, | 851 | }, |
852 | Annotation { | 852 | Annotation { |
853 | range: 14..64, | 853 | range: 18..23, |
854 | kind: Runnable { | 854 | kind: Runnable { |
855 | debug: false, | 855 | debug: false, |
856 | runnable: Runnable { | 856 | runnable: Runnable { |
@@ -871,7 +871,7 @@ mod tests { | |||
871 | }, | 871 | }, |
872 | }, | 872 | }, |
873 | Annotation { | 873 | Annotation { |
874 | range: 14..64, | 874 | range: 18..23, |
875 | kind: Runnable { | 875 | kind: Runnable { |
876 | debug: true, | 876 | debug: true, |
877 | runnable: Runnable { | 877 | runnable: Runnable { |
@@ -892,7 +892,7 @@ mod tests { | |||
892 | }, | 892 | }, |
893 | }, | 893 | }, |
894 | Annotation { | 894 | Annotation { |
895 | range: 30..62, | 895 | range: 45..57, |
896 | kind: Runnable { | 896 | kind: Runnable { |
897 | debug: false, | 897 | debug: false, |
898 | runnable: Runnable { | 898 | runnable: Runnable { |
@@ -918,7 +918,7 @@ mod tests { | |||
918 | }, | 918 | }, |
919 | }, | 919 | }, |
920 | Annotation { | 920 | Annotation { |
921 | range: 30..62, | 921 | range: 45..57, |
922 | kind: Runnable { | 922 | kind: Runnable { |
923 | debug: true, | 923 | debug: true, |
924 | runnable: Runnable { | 924 | runnable: Runnable { |
diff --git a/crates/ide/src/folding_ranges.rs b/crates/ide/src/folding_ranges.rs index b893c1c54..c5015a345 100755 --- a/crates/ide/src/folding_ranges.rs +++ b/crates/ide/src/folding_ranges.rs | |||
@@ -19,6 +19,7 @@ pub enum FoldKind { | |||
19 | Statics, | 19 | Statics, |
20 | Array, | 20 | Array, |
21 | WhereClause, | 21 | WhereClause, |
22 | ReturnType, | ||
22 | } | 23 | } |
23 | 24 | ||
24 | #[derive(Debug)] | 25 | #[derive(Debug)] |
@@ -131,6 +132,7 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> { | |||
131 | COMMENT => Some(FoldKind::Comment), | 132 | COMMENT => Some(FoldKind::Comment), |
132 | ARG_LIST | PARAM_LIST => Some(FoldKind::ArgList), | 133 | ARG_LIST | PARAM_LIST => Some(FoldKind::ArgList), |
133 | ARRAY_EXPR => Some(FoldKind::Array), | 134 | ARRAY_EXPR => Some(FoldKind::Array), |
135 | RET_TYPE => Some(FoldKind::ReturnType), | ||
134 | ASSOC_ITEM_LIST | 136 | ASSOC_ITEM_LIST |
135 | | RECORD_FIELD_LIST | 137 | | RECORD_FIELD_LIST |
136 | | RECORD_PAT_FIELD_LIST | 138 | | RECORD_PAT_FIELD_LIST |
@@ -300,6 +302,7 @@ mod tests { | |||
300 | FoldKind::Statics => "statics", | 302 | FoldKind::Statics => "statics", |
301 | FoldKind::Array => "array", | 303 | FoldKind::Array => "array", |
302 | FoldKind::WhereClause => "whereclause", | 304 | FoldKind::WhereClause => "whereclause", |
305 | FoldKind::ReturnType => "returntype", | ||
303 | }; | 306 | }; |
304 | assert_eq!(kind, &attr.unwrap()); | 307 | assert_eq!(kind, &attr.unwrap()); |
305 | } | 308 | } |
@@ -560,4 +563,18 @@ where | |||
560 | "#, | 563 | "#, |
561 | ) | 564 | ) |
562 | } | 565 | } |
566 | |||
567 | #[test] | ||
568 | fn fold_return_type() { | ||
569 | check( | ||
570 | r#" | ||
571 | fn foo()<fold returntype>-> ( | ||
572 | bool, | ||
573 | bool, | ||
574 | )</fold> { (true, true) } | ||
575 | |||
576 | fn bar() -> (bool, bool) { (true, true) } | ||
577 | "#, | ||
578 | ) | ||
579 | } | ||
563 | } | 580 | } |
diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs index 96447a603..c9673df85 100644 --- a/crates/ide_completion/src/completions/keyword.rs +++ b/crates/ide_completion/src/completions/keyword.rs | |||
@@ -395,6 +395,21 @@ fn quux() -> i32 { | |||
395 | } | 395 | } |
396 | 396 | ||
397 | #[test] | 397 | #[test] |
398 | fn test_keywords_in_impl_def_with_attr() { | ||
399 | check( | ||
400 | r"impl My { #[foo] $0 }", | ||
401 | expect![[r#" | ||
402 | kw fn | ||
403 | kw const | ||
404 | kw type | ||
405 | kw unsafe | ||
406 | kw pub(crate) | ||
407 | kw pub | ||
408 | "#]], | ||
409 | ); | ||
410 | } | ||
411 | |||
412 | #[test] | ||
398 | fn test_keywords_in_loop() { | 413 | fn test_keywords_in_loop() { |
399 | check( | 414 | check( |
400 | r"fn my() { loop { $0 } }", | 415 | r"fn my() { loop { $0 } }", |
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index c901b358b..ede07f605 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs | |||
@@ -1,7 +1,6 @@ | |||
1 | //! Completion of names from the current scope, e.g. locals and imported items. | 1 | //! Completion of names from the current scope, e.g. locals and imported items. |
2 | 2 | ||
3 | use hir::ScopeDef; | 3 | use hir::ScopeDef; |
4 | use syntax::AstNode; | ||
5 | 4 | ||
6 | use crate::{CompletionContext, Completions}; | 5 | use crate::{CompletionContext, Completions}; |
7 | 6 | ||
@@ -24,6 +23,15 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC | |||
24 | return; | 23 | return; |
25 | } | 24 | } |
26 | 25 | ||
26 | if ctx.expects_use_tree() { | ||
27 | cov_mark::hit!(only_completes_modules_in_import); | ||
28 | ctx.scope.process_all_names(&mut |name, res| { | ||
29 | if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res { | ||
30 | acc.add_resolution(ctx, name.to_string(), &res); | ||
31 | } | ||
32 | }); | ||
33 | return; | ||
34 | } | ||
27 | if let Some(hir::Adt::Enum(e)) = | 35 | if let Some(hir::Adt::Enum(e)) = |
28 | ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) | 36 | ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) |
29 | { | 37 | { |
@@ -37,14 +45,6 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC | |||
37 | cov_mark::hit!(skip_lifetime_completion); | 45 | cov_mark::hit!(skip_lifetime_completion); |
38 | return; | 46 | return; |
39 | } | 47 | } |
40 | if ctx.use_item_syntax.is_some() { | ||
41 | if let (ScopeDef::Unknown, Some(name_ref)) = (&res, &ctx.name_ref_syntax) { | ||
42 | if name_ref.syntax().text() == name.to_string().as_str() { | ||
43 | cov_mark::hit!(self_fulfilling_completion); | ||
44 | return; | ||
45 | } | ||
46 | } | ||
47 | } | ||
48 | acc.add_resolution(ctx, name.to_string(), &res); | 48 | acc.add_resolution(ctx, name.to_string(), &res); |
49 | }); | 49 | }); |
50 | } | 50 | } |
@@ -68,15 +68,17 @@ mod tests { | |||
68 | } | 68 | } |
69 | 69 | ||
70 | #[test] | 70 | #[test] |
71 | fn self_fulfilling_completion() { | 71 | fn only_completes_modules_in_import() { |
72 | cov_mark::check!(self_fulfilling_completion); | 72 | cov_mark::check!(only_completes_modules_in_import); |
73 | check( | 73 | check( |
74 | r#" | 74 | r#" |
75 | use foo$0 | 75 | use f$0 |
76 | use std::collections; | 76 | |
77 | struct Foo; | ||
78 | mod foo {} | ||
77 | "#, | 79 | "#, |
78 | expect![[r#" | 80 | expect![[r#" |
79 | ?? collections | 81 | md foo |
80 | "#]], | 82 | "#]], |
81 | ); | 83 | ); |
82 | } | 84 | } |
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index fbef54408..923e35dbb 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs | |||
@@ -276,6 +276,10 @@ impl<'a> CompletionContext<'a> { | |||
276 | ) | 276 | ) |
277 | } | 277 | } |
278 | 278 | ||
279 | pub(crate) fn expects_use_tree(&self) -> bool { | ||
280 | matches!(self.completion_location, Some(ImmediateLocation::Use)) | ||
281 | } | ||
282 | |||
279 | pub(crate) fn expects_non_trait_assoc_item(&self) -> bool { | 283 | pub(crate) fn expects_non_trait_assoc_item(&self) -> bool { |
280 | matches!(self.completion_location, Some(ImmediateLocation::Impl)) | 284 | matches!(self.completion_location, Some(ImmediateLocation::Impl)) |
281 | } | 285 | } |
diff --git a/crates/ide_completion/src/patterns.rs b/crates/ide_completion/src/patterns.rs index 19e42ba43..c8a88367d 100644 --- a/crates/ide_completion/src/patterns.rs +++ b/crates/ide_completion/src/patterns.rs | |||
@@ -14,6 +14,7 @@ use crate::test_utils::{check_pattern_is_applicable, check_pattern_is_not_applic | |||
14 | /// Direct parent container of the cursor position | 14 | /// Direct parent container of the cursor position |
15 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | 15 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
16 | pub(crate) enum ImmediateLocation { | 16 | pub(crate) enum ImmediateLocation { |
17 | Use, | ||
17 | Impl, | 18 | Impl, |
18 | Trait, | 19 | Trait, |
19 | RecordField, | 20 | RecordField, |
@@ -24,9 +25,10 @@ pub(crate) enum ImmediateLocation { | |||
24 | } | 25 | } |
25 | 26 | ||
26 | pub(crate) fn determine_location(tok: SyntaxToken) -> Option<ImmediateLocation> { | 27 | pub(crate) fn determine_location(tok: SyntaxToken) -> Option<ImmediateLocation> { |
27 | // First "expand" the element we are completing to its maximum so that we can check in what | 28 | // First walk the element we are completing up to its highest node that has the same text range |
28 | // context it immediately lies. This for example means if the token is a NameRef at the end of | 29 | // as the element so that we can check in what context it immediately lies. We only do this for |
29 | // a path, we want to look at where the path is in the tree. | 30 | // NameRef -> Path as that's the only thing that makes sense to being "expanded" semantically. |
31 | // We only wanna do this if the NameRef is the last segment of the path. | ||
30 | let node = match tok.parent().and_then(ast::NameLike::cast)? { | 32 | let node = match tok.parent().and_then(ast::NameLike::cast)? { |
31 | ast::NameLike::NameRef(name_ref) => { | 33 | ast::NameLike::NameRef(name_ref) => { |
32 | if let Some(segment) = name_ref.syntax().parent().and_then(ast::PathSegment::cast) { | 34 | if let Some(segment) = name_ref.syntax().parent().and_then(ast::PathSegment::cast) { |
@@ -46,7 +48,20 @@ pub(crate) fn determine_location(tok: SyntaxToken) -> Option<ImmediateLocation> | |||
46 | it @ ast::NameLike::Name(_) | it @ ast::NameLike::Lifetime(_) => it.syntax().clone(), | 48 | it @ ast::NameLike::Name(_) | it @ ast::NameLike::Lifetime(_) => it.syntax().clone(), |
47 | }; | 49 | }; |
48 | let parent = match node.parent() { | 50 | let parent = match node.parent() { |
49 | Some(parent) => parent, | 51 | Some(parent) => match ast::MacroCall::cast(parent.clone()) { |
52 | // When a path is being typed in an (Assoc)ItemList the parser will always emit a macro_call. | ||
53 | // This is usually fine as the node expansion code above already accounts for that with | ||
54 | // the ancestors call, but there is one exception to this which is that when an attribute | ||
55 | // precedes it the code above will not walk the Path to the parent MacroCall as their ranges differ. | ||
56 | Some(call) | ||
57 | if call.excl_token().is_none() | ||
58 | && call.token_tree().is_none() | ||
59 | && call.semicolon_token().is_none() => | ||
60 | { | ||
61 | call.syntax().parent()? | ||
62 | } | ||
63 | _ => parent, | ||
64 | }, | ||
50 | // SourceFile | 65 | // SourceFile |
51 | None => { | 66 | None => { |
52 | return match node.kind() { | 67 | return match node.kind() { |
@@ -58,6 +73,7 @@ pub(crate) fn determine_location(tok: SyntaxToken) -> Option<ImmediateLocation> | |||
58 | let res = match_ast! { | 73 | let res = match_ast! { |
59 | match parent { | 74 | match parent { |
60 | ast::IdentPat(_it) => ImmediateLocation::IdentPat, | 75 | ast::IdentPat(_it) => ImmediateLocation::IdentPat, |
76 | ast::Use(_it) => ImmediateLocation::Use, | ||
61 | ast::BlockExpr(_it) => ImmediateLocation::BlockExpr, | 77 | ast::BlockExpr(_it) => ImmediateLocation::BlockExpr, |
62 | ast::SourceFile(_it) => ImmediateLocation::ItemList, | 78 | ast::SourceFile(_it) => ImmediateLocation::ItemList, |
63 | ast::ItemList(_it) => ImmediateLocation::ItemList, | 79 | ast::ItemList(_it) => ImmediateLocation::ItemList, |
@@ -88,6 +104,11 @@ fn test_has_trait_parent() { | |||
88 | } | 104 | } |
89 | 105 | ||
90 | #[test] | 106 | #[test] |
107 | fn test_has_use_parent() { | ||
108 | check_location(r"use f$0", ImmediateLocation::Use); | ||
109 | } | ||
110 | |||
111 | #[test] | ||
91 | fn test_has_impl_parent() { | 112 | fn test_has_impl_parent() { |
92 | check_location(r"impl A { f$0 }", ImmediateLocation::Impl); | 113 | check_location(r"impl A { f$0 }", ImmediateLocation::Impl); |
93 | } | 114 | } |
diff --git a/crates/ide_completion/src/render/macro_.rs b/crates/ide_completion/src/render/macro_.rs index 7578ad50b..b90fd3890 100644 --- a/crates/ide_completion/src/render/macro_.rs +++ b/crates/ide_completion/src/render/macro_.rs | |||
@@ -74,7 +74,11 @@ impl<'a> MacroRender<'a> { | |||
74 | if self.needs_bang() && self.ctx.snippet_cap().is_some() { | 74 | if self.needs_bang() && self.ctx.snippet_cap().is_some() { |
75 | format!("{}!{}…{}", self.name, self.bra, self.ket) | 75 | format!("{}!{}…{}", self.name, self.bra, self.ket) |
76 | } else { | 76 | } else { |
77 | self.banged_name() | 77 | if self.macro_.kind() == hir::MacroKind::Derive { |
78 | self.name.to_string() | ||
79 | } else { | ||
80 | self.banged_name() | ||
81 | } | ||
78 | } | 82 | } |
79 | } | 83 | } |
80 | 84 | ||
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs index 6b9753521..fe5255240 100644 --- a/crates/rust-analyzer/src/caps.rs +++ b/crates/rust-analyzer/src/caps.rs | |||
@@ -1,6 +1,4 @@ | |||
1 | //! Advertises the capabilities of the LSP Server. | 1 | //! Advertises the capabilities of the LSP Server. |
2 | use std::env; | ||
3 | |||
4 | use lsp_types::{ | 2 | use lsp_types::{ |
5 | CallHierarchyServerCapability, ClientCapabilities, CodeActionKind, CodeActionOptions, | 3 | CallHierarchyServerCapability, ClientCapabilities, CodeActionKind, CodeActionOptions, |
6 | CodeActionProviderCapability, CodeLensOptions, CompletionOptions, | 4 | CodeActionProviderCapability, CodeLensOptions, CompletionOptions, |
@@ -22,11 +20,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { | |||
22 | ServerCapabilities { | 20 | ServerCapabilities { |
23 | text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { | 21 | text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { |
24 | open_close: Some(true), | 22 | open_close: Some(true), |
25 | change: Some(if env::var("RA_NO_INCREMENTAL_SYNC").is_ok() { | 23 | change: Some(TextDocumentSyncKind::Incremental), |
26 | TextDocumentSyncKind::Full | ||
27 | } else { | ||
28 | TextDocumentSyncKind::Incremental | ||
29 | }), | ||
30 | will_save: None, | 24 | will_save: None, |
31 | will_save_wait_until: None, | 25 | will_save_wait_until: None, |
32 | save: Some(SaveOptions::default().into()), | 26 | save: Some(SaveOptions::default().into()), |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 6d18d0ffc..f5c8535a2 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -534,6 +534,7 @@ pub(crate) fn folding_range( | |||
534 | | FoldKind::Consts | 534 | | FoldKind::Consts |
535 | | FoldKind::Statics | 535 | | FoldKind::Statics |
536 | | FoldKind::WhereClause | 536 | | FoldKind::WhereClause |
537 | | FoldKind::ReturnType | ||
537 | | FoldKind::Array => None, | 538 | | FoldKind::Array => None, |
538 | }; | 539 | }; |
539 | 540 | ||