aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/hir_def/src/nameres/tests/incremental.rs74
-rw-r--r--crates/hir_ty/src/tests.rs45
-rw-r--r--crates/hir_ty/src/tests/incremental.rs51
-rw-r--r--crates/ide/src/annotations.rs34
-rwxr-xr-xcrates/ide/src/folding_ranges.rs17
-rw-r--r--crates/ide_completion/src/completions/keyword.rs15
-rw-r--r--crates/ide_completion/src/completions/unqualified_path.rs30
-rw-r--r--crates/ide_completion/src/context.rs4
-rw-r--r--crates/ide_completion/src/patterns.rs29
-rw-r--r--crates/ide_completion/src/render/macro_.rs6
-rw-r--r--crates/rust-analyzer/src/caps.rs8
-rw-r--r--crates/rust-analyzer/src/to_proto.rs1
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 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use base_db::SourceDatabaseExt; 3use base_db::{salsa::SweepStrategy, SourceDatabaseExt};
4
5use crate::{AdtId, ModuleDefId};
4 6
5use super::*; 7use 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]
170fn 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#"
177pub struct S;
178pub union U {}
179pub enum E {
180 Variant,
181}
182pub fn f(_: S) { $0 }
183pub trait Tr {}
184impl Tr for () {}
185pub const C: u8 = 0;
186pub static ST: u8 = 0;
187pub 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;
7mod method_resolution; 7mod method_resolution;
8mod macros; 8mod macros;
9mod display_source_code; 9mod display_source_code;
10mod incremental;
10 11
11use std::{env, sync::Arc}; 12use 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]
321fn 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
364fn check_infer(ra_fixture: &str, expect: Expect) { 321fn 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 @@
1use std::sync::Arc;
2
3use base_db::{fixture::WithFixture, SourceDatabaseExt};
4
5use crate::{db::HirDatabase, test_db::TestDB};
6
7use super::visit_module;
8
9#[test]
10fn 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#"
571fn foo()<fold returntype>-> (
572 bool,
573 bool,
574)</fold> { (true, true) }
575
576fn 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
3use hir::ScopeDef; 3use hir::ScopeDef;
4use syntax::AstNode;
5 4
6use crate::{CompletionContext, Completions}; 5use 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#"
75use foo$0 75use f$0
76use std::collections; 76
77struct Foo;
78mod 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)]
16pub(crate) enum ImmediateLocation { 16pub(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
26pub(crate) fn determine_location(tok: SyntaxToken) -> Option<ImmediateLocation> { 27pub(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]
107fn test_has_use_parent() {
108 check_location(r"use f$0", ImmediateLocation::Use);
109}
110
111#[test]
91fn test_has_impl_parent() { 112fn 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.
2use std::env;
3
4use lsp_types::{ 2use 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