diff options
Diffstat (limited to 'crates')
217 files changed, 5643 insertions, 4842 deletions
diff --git a/crates/assists/src/assist_config.rs b/crates/assists/src/assist_config.rs index c458d9054..4fe8ea761 100644 --- a/crates/assists/src/assist_config.rs +++ b/crates/assists/src/assist_config.rs | |||
@@ -4,8 +4,7 @@ | |||
4 | //! module, and we use to statically check that we only produce snippet | 4 | //! module, and we use to statically check that we only produce snippet |
5 | //! assists if we are allowed to. | 5 | //! assists if we are allowed to. |
6 | 6 | ||
7 | use hir::PrefixKind; | 7 | use ide_db::helpers::{insert_use::MergeBehavior, SnippetCap}; |
8 | use ide_db::helpers::insert_use::MergeBehavior; | ||
9 | 8 | ||
10 | use crate::AssistKind; | 9 | use crate::AssistKind; |
11 | 10 | ||
@@ -16,35 +15,8 @@ pub struct AssistConfig { | |||
16 | pub insert_use: InsertUseConfig, | 15 | pub insert_use: InsertUseConfig, |
17 | } | 16 | } |
18 | 17 | ||
19 | impl AssistConfig { | ||
20 | pub fn allow_snippets(&mut self, yes: bool) { | ||
21 | self.snippet_cap = if yes { Some(SnippetCap { _private: () }) } else { None } | ||
22 | } | ||
23 | } | ||
24 | |||
25 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||
26 | pub struct SnippetCap { | ||
27 | _private: (), | ||
28 | } | ||
29 | |||
30 | impl Default for AssistConfig { | ||
31 | fn default() -> Self { | ||
32 | AssistConfig { | ||
33 | snippet_cap: Some(SnippetCap { _private: () }), | ||
34 | allowed: None, | ||
35 | insert_use: InsertUseConfig::default(), | ||
36 | } | ||
37 | } | ||
38 | } | ||
39 | |||
40 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] | 18 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
41 | pub struct InsertUseConfig { | 19 | pub struct InsertUseConfig { |
42 | pub merge: Option<MergeBehavior>, | 20 | pub merge: Option<MergeBehavior>, |
43 | pub prefix_kind: PrefixKind, | 21 | pub prefix_kind: hir::PrefixKind, |
44 | } | ||
45 | |||
46 | impl Default for InsertUseConfig { | ||
47 | fn default() -> Self { | ||
48 | InsertUseConfig { merge: Some(MergeBehavior::Full), prefix_kind: PrefixKind::Plain } | ||
49 | } | ||
50 | } | 22 | } |
diff --git a/crates/assists/src/assist_context.rs b/crates/assists/src/assist_context.rs index 4f59d39a9..91cc63427 100644 --- a/crates/assists/src/assist_context.rs +++ b/crates/assists/src/assist_context.rs | |||
@@ -4,7 +4,10 @@ use std::mem; | |||
4 | 4 | ||
5 | use algo::find_covering_element; | 5 | use algo::find_covering_element; |
6 | use hir::Semantics; | 6 | use hir::Semantics; |
7 | use ide_db::base_db::{AnchoredPathBuf, FileId, FileRange}; | 7 | use ide_db::{ |
8 | base_db::{AnchoredPathBuf, FileId, FileRange}, | ||
9 | helpers::SnippetCap, | ||
10 | }; | ||
8 | use ide_db::{ | 11 | use ide_db::{ |
9 | label::Label, | 12 | label::Label, |
10 | source_change::{FileSystemEdit, SourceChange, SourceFileEdit}, | 13 | source_change::{FileSystemEdit, SourceChange, SourceFileEdit}, |
@@ -17,10 +20,7 @@ use syntax::{ | |||
17 | }; | 20 | }; |
18 | use text_edit::{TextEdit, TextEditBuilder}; | 21 | use text_edit::{TextEdit, TextEditBuilder}; |
19 | 22 | ||
20 | use crate::{ | 23 | use crate::{assist_config::AssistConfig, Assist, AssistId, AssistKind, GroupLabel}; |
21 | assist_config::{AssistConfig, SnippetCap}, | ||
22 | Assist, AssistId, AssistKind, GroupLabel, | ||
23 | }; | ||
24 | 24 | ||
25 | /// `AssistContext` allows to apply an assist or check if it could be applied. | 25 | /// `AssistContext` allows to apply an assist or check if it could be applied. |
26 | /// | 26 | /// |
diff --git a/crates/assists/src/handlers/add_explicit_type.rs b/crates/assists/src/handlers/add_explicit_type.rs index 563cbf505..cb1548cef 100644 --- a/crates/assists/src/handlers/add_explicit_type.rs +++ b/crates/assists/src/handlers/add_explicit_type.rs | |||
@@ -12,7 +12,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
12 | // | 12 | // |
13 | // ``` | 13 | // ``` |
14 | // fn main() { | 14 | // fn main() { |
15 | // let x<|> = 92; | 15 | // let x$0 = 92; |
16 | // } | 16 | // } |
17 | // ``` | 17 | // ``` |
18 | // -> | 18 | // -> |
@@ -81,21 +81,17 @@ mod tests { | |||
81 | 81 | ||
82 | #[test] | 82 | #[test] |
83 | fn add_explicit_type_target() { | 83 | fn add_explicit_type_target() { |
84 | check_assist_target(add_explicit_type, "fn f() { let a<|> = 1; }", "a"); | 84 | check_assist_target(add_explicit_type, "fn f() { let a$0 = 1; }", "a"); |
85 | } | 85 | } |
86 | 86 | ||
87 | #[test] | 87 | #[test] |
88 | fn add_explicit_type_works_for_simple_expr() { | 88 | fn add_explicit_type_works_for_simple_expr() { |
89 | check_assist(add_explicit_type, "fn f() { let a<|> = 1; }", "fn f() { let a: i32 = 1; }"); | 89 | check_assist(add_explicit_type, "fn f() { let a$0 = 1; }", "fn f() { let a: i32 = 1; }"); |
90 | } | 90 | } |
91 | 91 | ||
92 | #[test] | 92 | #[test] |
93 | fn add_explicit_type_works_for_underscore() { | 93 | fn add_explicit_type_works_for_underscore() { |
94 | check_assist( | 94 | check_assist(add_explicit_type, "fn f() { let a$0: _ = 1; }", "fn f() { let a: i32 = 1; }"); |
95 | add_explicit_type, | ||
96 | "fn f() { let a<|>: _ = 1; }", | ||
97 | "fn f() { let a: i32 = 1; }", | ||
98 | ); | ||
99 | } | 95 | } |
100 | 96 | ||
101 | #[test] | 97 | #[test] |
@@ -109,7 +105,7 @@ mod tests { | |||
109 | } | 105 | } |
110 | 106 | ||
111 | fn f() { | 107 | fn f() { |
112 | let a<|>: Option<_> = Option::Some(1); | 108 | let a$0: Option<_> = Option::Some(1); |
113 | }"#, | 109 | }"#, |
114 | r#" | 110 | r#" |
115 | enum Option<T> { | 111 | enum Option<T> { |
@@ -127,7 +123,7 @@ mod tests { | |||
127 | fn add_explicit_type_works_for_macro_call() { | 123 | fn add_explicit_type_works_for_macro_call() { |
128 | check_assist( | 124 | check_assist( |
129 | add_explicit_type, | 125 | add_explicit_type, |
130 | r"macro_rules! v { () => {0u64} } fn f() { let a<|> = v!(); }", | 126 | r"macro_rules! v { () => {0u64} } fn f() { let a$0 = v!(); }", |
131 | r"macro_rules! v { () => {0u64} } fn f() { let a: u64 = v!(); }", | 127 | r"macro_rules! v { () => {0u64} } fn f() { let a: u64 = v!(); }", |
132 | ); | 128 | ); |
133 | } | 129 | } |
@@ -136,31 +132,31 @@ mod tests { | |||
136 | fn add_explicit_type_works_for_macro_call_recursive() { | 132 | fn add_explicit_type_works_for_macro_call_recursive() { |
137 | check_assist( | 133 | check_assist( |
138 | add_explicit_type, | 134 | add_explicit_type, |
139 | r#"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a<|> = v!(); }"#, | 135 | r#"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a$0 = v!(); }"#, |
140 | r#"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a: u64 = v!(); }"#, | 136 | r#"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a: u64 = v!(); }"#, |
141 | ); | 137 | ); |
142 | } | 138 | } |
143 | 139 | ||
144 | #[test] | 140 | #[test] |
145 | fn add_explicit_type_not_applicable_if_ty_not_inferred() { | 141 | fn add_explicit_type_not_applicable_if_ty_not_inferred() { |
146 | check_assist_not_applicable(add_explicit_type, "fn f() { let a<|> = None; }"); | 142 | check_assist_not_applicable(add_explicit_type, "fn f() { let a$0 = None; }"); |
147 | } | 143 | } |
148 | 144 | ||
149 | #[test] | 145 | #[test] |
150 | fn add_explicit_type_not_applicable_if_ty_already_specified() { | 146 | fn add_explicit_type_not_applicable_if_ty_already_specified() { |
151 | check_assist_not_applicable(add_explicit_type, "fn f() { let a<|>: i32 = 1; }"); | 147 | check_assist_not_applicable(add_explicit_type, "fn f() { let a$0: i32 = 1; }"); |
152 | } | 148 | } |
153 | 149 | ||
154 | #[test] | 150 | #[test] |
155 | fn add_explicit_type_not_applicable_if_specified_ty_is_tuple() { | 151 | fn add_explicit_type_not_applicable_if_specified_ty_is_tuple() { |
156 | check_assist_not_applicable(add_explicit_type, "fn f() { let a<|>: (i32, i32) = (3, 4); }"); | 152 | check_assist_not_applicable(add_explicit_type, "fn f() { let a$0: (i32, i32) = (3, 4); }"); |
157 | } | 153 | } |
158 | 154 | ||
159 | #[test] | 155 | #[test] |
160 | fn add_explicit_type_not_applicable_if_cursor_after_equals() { | 156 | fn add_explicit_type_not_applicable_if_cursor_after_equals() { |
161 | check_assist_not_applicable( | 157 | check_assist_not_applicable( |
162 | add_explicit_type, | 158 | add_explicit_type, |
163 | "fn f() {let a =<|> match 1 {2 => 3, 3 => 5};}", | 159 | "fn f() {let a =$0 match 1 {2 => 3, 3 => 5};}", |
164 | ) | 160 | ) |
165 | } | 161 | } |
166 | 162 | ||
@@ -168,7 +164,7 @@ mod tests { | |||
168 | fn add_explicit_type_not_applicable_if_cursor_before_let() { | 164 | fn add_explicit_type_not_applicable_if_cursor_before_let() { |
169 | check_assist_not_applicable( | 165 | check_assist_not_applicable( |
170 | add_explicit_type, | 166 | add_explicit_type, |
171 | "fn f() <|>{let a = match 1 {2 => 3, 3 => 5};}", | 167 | "fn f() $0{let a = match 1 {2 => 3, 3 => 5};}", |
172 | ) | 168 | ) |
173 | } | 169 | } |
174 | 170 | ||
@@ -178,7 +174,7 @@ mod tests { | |||
178 | add_explicit_type, | 174 | add_explicit_type, |
179 | r#" | 175 | r#" |
180 | fn main() { | 176 | fn main() { |
181 | let multiply_by_two<|> = |i| i * 3; | 177 | let multiply_by_two$0 = |i| i * 3; |
182 | let six = multiply_by_two(2); | 178 | let six = multiply_by_two(2); |
183 | }"#, | 179 | }"#, |
184 | ) | 180 | ) |
@@ -195,7 +191,7 @@ struct Test<K, T = u8> { | |||
195 | } | 191 | } |
196 | 192 | ||
197 | fn main() { | 193 | fn main() { |
198 | let test<|> = Test { t: 23u8, k: 33 }; | 194 | let test$0 = Test { t: 23u8, k: 33 }; |
199 | }"#, | 195 | }"#, |
200 | r#" | 196 | r#" |
201 | struct Test<K, T = u8> { | 197 | struct Test<K, T = u8> { |
diff --git a/crates/assists/src/handlers/add_missing_impl_members.rs b/crates/assists/src/handlers/add_missing_impl_members.rs index 7df05b841..63cea754d 100644 --- a/crates/assists/src/handlers/add_missing_impl_members.rs +++ b/crates/assists/src/handlers/add_missing_impl_members.rs | |||
@@ -20,7 +20,7 @@ use crate::{ | |||
20 | // fn bar(&self) {} | 20 | // fn bar(&self) {} |
21 | // } | 21 | // } |
22 | // | 22 | // |
23 | // impl Trait<u32> for () {<|> | 23 | // impl Trait<u32> for () {$0 |
24 | // | 24 | // |
25 | // } | 25 | // } |
26 | // ``` | 26 | // ``` |
@@ -63,7 +63,7 @@ pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext) - | |||
63 | // | 63 | // |
64 | // impl Trait for () { | 64 | // impl Trait for () { |
65 | // type X = (); | 65 | // type X = (); |
66 | // fn foo(&self) {}<|> | 66 | // fn foo(&self) {}$0 |
67 | // | 67 | // |
68 | // } | 68 | // } |
69 | // ``` | 69 | // ``` |
@@ -166,7 +166,7 @@ struct S; | |||
166 | 166 | ||
167 | impl Foo for S { | 167 | impl Foo for S { |
168 | fn bar(&self) {} | 168 | fn bar(&self) {} |
169 | <|> | 169 | $0 |
170 | }"#, | 170 | }"#, |
171 | r#" | 171 | r#" |
172 | trait Foo { | 172 | trait Foo { |
@@ -214,7 +214,7 @@ struct S; | |||
214 | 214 | ||
215 | impl Foo for S { | 215 | impl Foo for S { |
216 | fn bar(&self) {} | 216 | fn bar(&self) {} |
217 | <|> | 217 | $0 |
218 | }"#, | 218 | }"#, |
219 | r#" | 219 | r#" |
220 | trait Foo { | 220 | trait Foo { |
@@ -242,7 +242,7 @@ impl Foo for S { | |||
242 | r#" | 242 | r#" |
243 | trait Foo { fn foo(&self); } | 243 | trait Foo { fn foo(&self); } |
244 | struct S; | 244 | struct S; |
245 | impl Foo for S { <|> }"#, | 245 | impl Foo for S { $0 }"#, |
246 | r#" | 246 | r#" |
247 | trait Foo { fn foo(&self); } | 247 | trait Foo { fn foo(&self); } |
248 | struct S; | 248 | struct S; |
@@ -261,7 +261,7 @@ impl Foo for S { | |||
261 | r#" | 261 | r#" |
262 | trait Foo { fn foo(&self); } | 262 | trait Foo { fn foo(&self); } |
263 | struct S; | 263 | struct S; |
264 | impl Foo for S<|>"#, | 264 | impl Foo for S$0"#, |
265 | r#" | 265 | r#" |
266 | trait Foo { fn foo(&self); } | 266 | trait Foo { fn foo(&self); } |
267 | struct S; | 267 | struct S; |
@@ -280,7 +280,7 @@ impl Foo for S { | |||
280 | r#" | 280 | r#" |
281 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | 281 | trait Foo<T> { fn foo(&self, t: T) -> &T; } |
282 | struct S; | 282 | struct S; |
283 | impl Foo<u32> for S { <|> }"#, | 283 | impl Foo<u32> for S { $0 }"#, |
284 | r#" | 284 | r#" |
285 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | 285 | trait Foo<T> { fn foo(&self, t: T) -> &T; } |
286 | struct S; | 286 | struct S; |
@@ -299,7 +299,7 @@ impl Foo<u32> for S { | |||
299 | r#" | 299 | r#" |
300 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | 300 | trait Foo<T> { fn foo(&self, t: T) -> &T; } |
301 | struct S; | 301 | struct S; |
302 | impl<U> Foo<U> for S { <|> }"#, | 302 | impl<U> Foo<U> for S { $0 }"#, |
303 | r#" | 303 | r#" |
304 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | 304 | trait Foo<T> { fn foo(&self, t: T) -> &T; } |
305 | struct S; | 305 | struct S; |
@@ -318,7 +318,7 @@ impl<U> Foo<U> for S { | |||
318 | r#" | 318 | r#" |
319 | trait Foo { fn foo(&self); } | 319 | trait Foo { fn foo(&self); } |
320 | struct S; | 320 | struct S; |
321 | impl Foo for S {}<|>"#, | 321 | impl Foo for S {}$0"#, |
322 | r#" | 322 | r#" |
323 | trait Foo { fn foo(&self); } | 323 | trait Foo { fn foo(&self); } |
324 | struct S; | 324 | struct S; |
@@ -340,7 +340,7 @@ mod foo { | |||
340 | trait Foo { fn foo(&self, bar: Bar); } | 340 | trait Foo { fn foo(&self, bar: Bar); } |
341 | } | 341 | } |
342 | struct S; | 342 | struct S; |
343 | impl foo::Foo for S { <|> }"#, | 343 | impl foo::Foo for S { $0 }"#, |
344 | r#" | 344 | r#" |
345 | mod foo { | 345 | mod foo { |
346 | pub struct Bar; | 346 | pub struct Bar; |
@@ -370,7 +370,7 @@ mod foo { | |||
370 | use foo::bar; | 370 | use foo::bar; |
371 | 371 | ||
372 | struct S; | 372 | struct S; |
373 | impl bar::Foo for S { <|> }"#, | 373 | impl bar::Foo for S { $0 }"#, |
374 | r#" | 374 | r#" |
375 | mod foo { | 375 | mod foo { |
376 | pub mod bar { | 376 | pub mod bar { |
@@ -400,7 +400,7 @@ mod foo { | |||
400 | trait Foo { fn foo(&self, bar: Bar<u32>); } | 400 | trait Foo { fn foo(&self, bar: Bar<u32>); } |
401 | } | 401 | } |
402 | struct S; | 402 | struct S; |
403 | impl foo::Foo for S { <|> }"#, | 403 | impl foo::Foo for S { $0 }"#, |
404 | r#" | 404 | r#" |
405 | mod foo { | 405 | mod foo { |
406 | pub struct Bar<T>; | 406 | pub struct Bar<T>; |
@@ -425,7 +425,7 @@ mod foo { | |||
425 | trait Foo<T> { fn foo(&self, bar: Bar<T>); } | 425 | trait Foo<T> { fn foo(&self, bar: Bar<T>); } |
426 | } | 426 | } |
427 | struct S; | 427 | struct S; |
428 | impl foo::Foo<u32> for S { <|> }"#, | 428 | impl foo::Foo<u32> for S { $0 }"#, |
429 | r#" | 429 | r#" |
430 | mod foo { | 430 | mod foo { |
431 | pub struct Bar<T>; | 431 | pub struct Bar<T>; |
@@ -452,7 +452,7 @@ mod foo { | |||
452 | } | 452 | } |
453 | struct Param; | 453 | struct Param; |
454 | struct S; | 454 | struct S; |
455 | impl foo::Foo<Param> for S { <|> }"#, | 455 | impl foo::Foo<Param> for S { $0 }"#, |
456 | r#" | 456 | r#" |
457 | mod foo { | 457 | mod foo { |
458 | trait Foo<T> { fn foo(&self, bar: T); } | 458 | trait Foo<T> { fn foo(&self, bar: T); } |
@@ -479,7 +479,7 @@ mod foo { | |||
479 | trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); } | 479 | trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); } |
480 | } | 480 | } |
481 | struct S; | 481 | struct S; |
482 | impl foo::Foo for S { <|> }"#, | 482 | impl foo::Foo for S { $0 }"#, |
483 | r#" | 483 | r#" |
484 | mod foo { | 484 | mod foo { |
485 | pub struct Bar<T>; | 485 | pub struct Bar<T>; |
@@ -506,7 +506,7 @@ mod foo { | |||
506 | trait Foo { fn foo(&self, bar: Bar<Baz>); } | 506 | trait Foo { fn foo(&self, bar: Bar<Baz>); } |
507 | } | 507 | } |
508 | struct S; | 508 | struct S; |
509 | impl foo::Foo for S { <|> }"#, | 509 | impl foo::Foo for S { $0 }"#, |
510 | r#" | 510 | r#" |
511 | mod foo { | 511 | mod foo { |
512 | pub struct Bar<T>; | 512 | pub struct Bar<T>; |
@@ -532,7 +532,7 @@ mod foo { | |||
532 | trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); } | 532 | trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); } |
533 | } | 533 | } |
534 | struct S; | 534 | struct S; |
535 | impl foo::Foo for S { <|> }"#, | 535 | impl foo::Foo for S { $0 }"#, |
536 | r#" | 536 | r#" |
537 | mod foo { | 537 | mod foo { |
538 | pub trait Fn<Args> { type Output; } | 538 | pub trait Fn<Args> { type Output; } |
@@ -554,7 +554,7 @@ impl foo::Foo for S { | |||
554 | r#" | 554 | r#" |
555 | trait Foo; | 555 | trait Foo; |
556 | struct S; | 556 | struct S; |
557 | impl Foo for S { <|> }"#, | 557 | impl Foo for S { $0 }"#, |
558 | ) | 558 | ) |
559 | } | 559 | } |
560 | 560 | ||
@@ -568,7 +568,7 @@ trait Foo { | |||
568 | fn valid(some: u32) -> bool { false } | 568 | fn valid(some: u32) -> bool { false } |
569 | } | 569 | } |
570 | struct S; | 570 | struct S; |
571 | impl Foo for S { <|> }"#, | 571 | impl Foo for S { $0 }"#, |
572 | ) | 572 | ) |
573 | } | 573 | } |
574 | 574 | ||
@@ -586,7 +586,7 @@ trait Foo { | |||
586 | fn foo(&self); | 586 | fn foo(&self); |
587 | } | 587 | } |
588 | struct S; | 588 | struct S; |
589 | impl Foo for S {}<|>"#, | 589 | impl Foo for S {}$0"#, |
590 | r#" | 590 | r#" |
591 | #[doc(alias = "test alias")] | 591 | #[doc(alias = "test alias")] |
592 | trait Foo { | 592 | trait Foo { |
@@ -621,7 +621,7 @@ trait Foo { | |||
621 | fn foo(some: u32) -> bool; | 621 | fn foo(some: u32) -> bool; |
622 | } | 622 | } |
623 | struct S; | 623 | struct S; |
624 | impl Foo for S { <|> }"#, | 624 | impl Foo for S { $0 }"#, |
625 | r#" | 625 | r#" |
626 | trait Foo { | 626 | trait Foo { |
627 | type Output; | 627 | type Output; |
@@ -648,7 +648,7 @@ trait Foo<T = Self> { | |||
648 | } | 648 | } |
649 | 649 | ||
650 | struct S; | 650 | struct S; |
651 | impl Foo for S { <|> }"#, | 651 | impl Foo for S { $0 }"#, |
652 | r#" | 652 | r#" |
653 | trait Foo<T = Self> { | 653 | trait Foo<T = Self> { |
654 | fn bar(&self, other: &T); | 654 | fn bar(&self, other: &T); |
@@ -673,7 +673,7 @@ trait Foo<T1, T2 = Self> { | |||
673 | } | 673 | } |
674 | 674 | ||
675 | struct S<T>; | 675 | struct S<T>; |
676 | impl Foo<T> for S<T> { <|> }"#, | 676 | impl Foo<T> for S<T> { $0 }"#, |
677 | r#" | 677 | r#" |
678 | trait Foo<T1, T2 = Self> { | 678 | trait Foo<T1, T2 = Self> { |
679 | fn bar(&self, this: &T1, that: &T2); | 679 | fn bar(&self, this: &T1, that: &T2); |
@@ -697,7 +697,7 @@ trait Tr { | |||
697 | type Ty: Copy + 'static; | 697 | type Ty: Copy + 'static; |
698 | } | 698 | } |
699 | 699 | ||
700 | impl Tr for ()<|> { | 700 | impl Tr for ()$0 { |
701 | }"#, | 701 | }"#, |
702 | r#" | 702 | r#" |
703 | trait Tr { | 703 | trait Tr { |
@@ -719,7 +719,7 @@ trait Tr { | |||
719 | fn foo(); | 719 | fn foo(); |
720 | } | 720 | } |
721 | 721 | ||
722 | impl Tr for ()<|> { | 722 | impl Tr for ()$0 { |
723 | +++ | 723 | +++ |
724 | }"#, | 724 | }"#, |
725 | r#" | 725 | r#" |
@@ -745,7 +745,7 @@ trait Tr { | |||
745 | fn foo(); | 745 | fn foo(); |
746 | } | 746 | } |
747 | 747 | ||
748 | impl Tr for ()<|> { | 748 | impl Tr for ()$0 { |
749 | // very important | 749 | // very important |
750 | }"#, | 750 | }"#, |
751 | r#" | 751 | r#" |
@@ -771,7 +771,7 @@ trait Test { | |||
771 | fn foo(&self, x: crate) | 771 | fn foo(&self, x: crate) |
772 | } | 772 | } |
773 | impl Test for () { | 773 | impl Test for () { |
774 | <|> | 774 | $0 |
775 | } | 775 | } |
776 | "#, | 776 | "#, |
777 | r#" | 777 | r#" |
@@ -796,7 +796,7 @@ trait Foo<BAR> { | |||
796 | fn foo(&self, bar: BAR); | 796 | fn foo(&self, bar: BAR); |
797 | } | 797 | } |
798 | impl Foo for () { | 798 | impl Foo for () { |
799 | <|> | 799 | $0 |
800 | } | 800 | } |
801 | "#, | 801 | "#, |
802 | r#" | 802 | r#" |
diff --git a/crates/assists/src/handlers/add_turbo_fish.rs b/crates/assists/src/handlers/add_turbo_fish.rs index 1f486c013..8e9ea4fad 100644 --- a/crates/assists/src/handlers/add_turbo_fish.rs +++ b/crates/assists/src/handlers/add_turbo_fish.rs | |||
@@ -14,7 +14,7 @@ use crate::{ | |||
14 | // ``` | 14 | // ``` |
15 | // fn make<T>() -> T { todo!() } | 15 | // fn make<T>() -> T { todo!() } |
16 | // fn main() { | 16 | // fn main() { |
17 | // let x = make<|>(); | 17 | // let x = make$0(); |
18 | // } | 18 | // } |
19 | // ``` | 19 | // ``` |
20 | // -> | 20 | // -> |
@@ -77,7 +77,7 @@ mod tests { | |||
77 | r#" | 77 | r#" |
78 | fn make<T>() -> T {} | 78 | fn make<T>() -> T {} |
79 | fn main() { | 79 | fn main() { |
80 | make<|>(); | 80 | make$0(); |
81 | } | 81 | } |
82 | "#, | 82 | "#, |
83 | r#" | 83 | r#" |
@@ -97,7 +97,7 @@ fn main() { | |||
97 | r#" | 97 | r#" |
98 | fn make<T>() -> T {} | 98 | fn make<T>() -> T {} |
99 | fn main() { | 99 | fn main() { |
100 | make()<|>; | 100 | make()$0; |
101 | } | 101 | } |
102 | "#, | 102 | "#, |
103 | r#" | 103 | r#" |
@@ -119,7 +119,7 @@ impl S { | |||
119 | fn make<T>(&self) -> T {} | 119 | fn make<T>(&self) -> T {} |
120 | } | 120 | } |
121 | fn main() { | 121 | fn main() { |
122 | S.make<|>(); | 122 | S.make$0(); |
123 | } | 123 | } |
124 | "#, | 124 | "#, |
125 | r#" | 125 | r#" |
@@ -142,7 +142,7 @@ fn main() { | |||
142 | r#" | 142 | r#" |
143 | fn make<T>() -> T {} | 143 | fn make<T>() -> T {} |
144 | fn main() { | 144 | fn main() { |
145 | make<|>::<()>(); | 145 | make$0::<()>(); |
146 | } | 146 | } |
147 | "#, | 147 | "#, |
148 | ); | 148 | ); |
@@ -156,7 +156,7 @@ fn main() { | |||
156 | r#" | 156 | r#" |
157 | fn make() -> () {} | 157 | fn make() -> () {} |
158 | fn main() { | 158 | fn main() { |
159 | make<|>(); | 159 | make$0(); |
160 | } | 160 | } |
161 | "#, | 161 | "#, |
162 | ); | 162 | ); |
diff --git a/crates/assists/src/handlers/apply_demorgan.rs b/crates/assists/src/handlers/apply_demorgan.rs index 1a6fdafda..ed4d11455 100644 --- a/crates/assists/src/handlers/apply_demorgan.rs +++ b/crates/assists/src/handlers/apply_demorgan.rs | |||
@@ -12,7 +12,7 @@ use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKin | |||
12 | // | 12 | // |
13 | // ``` | 13 | // ``` |
14 | // fn main() { | 14 | // fn main() { |
15 | // if x != 4 ||<|> !y {} | 15 | // if x != 4 ||$0 !y {} |
16 | // } | 16 | // } |
17 | // ``` | 17 | // ``` |
18 | // -> | 18 | // -> |
@@ -68,26 +68,26 @@ mod tests { | |||
68 | 68 | ||
69 | #[test] | 69 | #[test] |
70 | fn demorgan_turns_and_into_or() { | 70 | fn demorgan_turns_and_into_or() { |
71 | check_assist(apply_demorgan, "fn f() { !x &&<|> !x }", "fn f() { !(x || x) }") | 71 | check_assist(apply_demorgan, "fn f() { !x &&$0 !x }", "fn f() { !(x || x) }") |
72 | } | 72 | } |
73 | 73 | ||
74 | #[test] | 74 | #[test] |
75 | fn demorgan_turns_or_into_and() { | 75 | fn demorgan_turns_or_into_and() { |
76 | check_assist(apply_demorgan, "fn f() { !x ||<|> !x }", "fn f() { !(x && x) }") | 76 | check_assist(apply_demorgan, "fn f() { !x ||$0 !x }", "fn f() { !(x && x) }") |
77 | } | 77 | } |
78 | 78 | ||
79 | #[test] | 79 | #[test] |
80 | fn demorgan_removes_inequality() { | 80 | fn demorgan_removes_inequality() { |
81 | check_assist(apply_demorgan, "fn f() { x != x ||<|> !x }", "fn f() { !(x == x && x) }") | 81 | check_assist(apply_demorgan, "fn f() { x != x ||$0 !x }", "fn f() { !(x == x && x) }") |
82 | } | 82 | } |
83 | 83 | ||
84 | #[test] | 84 | #[test] |
85 | fn demorgan_general_case() { | 85 | fn demorgan_general_case() { |
86 | check_assist(apply_demorgan, "fn f() { x ||<|> x }", "fn f() { !(!x && !x) }") | 86 | check_assist(apply_demorgan, "fn f() { x ||$0 x }", "fn f() { !(!x && !x) }") |
87 | } | 87 | } |
88 | 88 | ||
89 | #[test] | 89 | #[test] |
90 | fn demorgan_doesnt_apply_with_cursor_not_on_op() { | 90 | fn demorgan_doesnt_apply_with_cursor_not_on_op() { |
91 | check_assist_not_applicable(apply_demorgan, "fn f() { <|> !x || !x }") | 91 | check_assist_not_applicable(apply_demorgan, "fn f() { $0 !x || !x }") |
92 | } | 92 | } |
93 | } | 93 | } |
diff --git a/crates/assists/src/handlers/auto_import.rs b/crates/assists/src/handlers/auto_import.rs index bd5bba646..55620f0f3 100644 --- a/crates/assists/src/handlers/auto_import.rs +++ b/crates/assists/src/handlers/auto_import.rs | |||
@@ -70,7 +70,7 @@ use crate::{ | |||
70 | // | 70 | // |
71 | // ``` | 71 | // ``` |
72 | // fn main() { | 72 | // fn main() { |
73 | // let map = HashMap<|>::new(); | 73 | // let map = HashMap$0::new(); |
74 | // } | 74 | // } |
75 | // # pub mod std { pub mod collections { pub struct HashMap { } } } | 75 | // # pub mod std { pub mod collections { pub struct HashMap { } } } |
76 | // ``` | 76 | // ``` |
@@ -151,7 +151,7 @@ mod tests { | |||
151 | 151 | ||
152 | use std::fmt; | 152 | use std::fmt; |
153 | 153 | ||
154 | <|>Formatter | 154 | $0Formatter |
155 | ", | 155 | ", |
156 | r" | 156 | r" |
157 | mod std { | 157 | mod std { |
@@ -172,7 +172,7 @@ mod tests { | |||
172 | check_assist( | 172 | check_assist( |
173 | auto_import, | 173 | auto_import, |
174 | r" | 174 | r" |
175 | <|>PubStruct | 175 | $0PubStruct |
176 | 176 | ||
177 | pub mod PubMod { | 177 | pub mod PubMod { |
178 | pub struct PubStruct; | 178 | pub struct PubStruct; |
@@ -198,7 +198,7 @@ mod tests { | |||
198 | macro_rules! foo { | 198 | macro_rules! foo { |
199 | ($i:ident) => { fn foo(a: $i) {} } | 199 | ($i:ident) => { fn foo(a: $i) {} } |
200 | } | 200 | } |
201 | foo!(Pub<|>Struct); | 201 | foo!(Pub$0Struct); |
202 | 202 | ||
203 | pub mod PubMod { | 203 | pub mod PubMod { |
204 | pub struct PubStruct; | 204 | pub struct PubStruct; |
@@ -227,7 +227,7 @@ mod tests { | |||
227 | use PubMod::PubStruct1; | 227 | use PubMod::PubStruct1; |
228 | 228 | ||
229 | struct Test { | 229 | struct Test { |
230 | test: Pub<|>Struct2<u8>, | 230 | test: Pub$0Struct2<u8>, |
231 | } | 231 | } |
232 | 232 | ||
233 | pub mod PubMod { | 233 | pub mod PubMod { |
@@ -259,7 +259,7 @@ mod tests { | |||
259 | check_assist( | 259 | check_assist( |
260 | auto_import, | 260 | auto_import, |
261 | r" | 261 | r" |
262 | PubSt<|>ruct | 262 | PubSt$0ruct |
263 | 263 | ||
264 | pub mod PubMod1 { | 264 | pub mod PubMod1 { |
265 | pub struct PubStruct; | 265 | pub struct PubStruct; |
@@ -296,7 +296,7 @@ mod tests { | |||
296 | r" | 296 | r" |
297 | use PubMod::PubStruct; | 297 | use PubMod::PubStruct; |
298 | 298 | ||
299 | PubStruct<|> | 299 | PubStruct$0 |
300 | 300 | ||
301 | pub mod PubMod { | 301 | pub mod PubMod { |
302 | pub struct PubStruct; | 302 | pub struct PubStruct; |
@@ -310,7 +310,7 @@ mod tests { | |||
310 | check_assist_not_applicable( | 310 | check_assist_not_applicable( |
311 | auto_import, | 311 | auto_import, |
312 | r" | 312 | r" |
313 | PrivateStruct<|> | 313 | PrivateStruct$0 |
314 | 314 | ||
315 | pub mod PubMod { | 315 | pub mod PubMod { |
316 | struct PrivateStruct; | 316 | struct PrivateStruct; |
@@ -324,7 +324,7 @@ mod tests { | |||
324 | check_assist_not_applicable( | 324 | check_assist_not_applicable( |
325 | auto_import, | 325 | auto_import, |
326 | " | 326 | " |
327 | PubStruct<|>", | 327 | PubStruct$0", |
328 | ); | 328 | ); |
329 | } | 329 | } |
330 | 330 | ||
@@ -333,7 +333,7 @@ mod tests { | |||
333 | check_assist_not_applicable( | 333 | check_assist_not_applicable( |
334 | auto_import, | 334 | auto_import, |
335 | r" | 335 | r" |
336 | use PubStruct<|>; | 336 | use PubStruct$0; |
337 | 337 | ||
338 | pub mod PubMod { | 338 | pub mod PubMod { |
339 | pub struct PubStruct; | 339 | pub struct PubStruct; |
@@ -346,7 +346,7 @@ mod tests { | |||
346 | check_assist( | 346 | check_assist( |
347 | auto_import, | 347 | auto_import, |
348 | r" | 348 | r" |
349 | test_function<|> | 349 | test_function$0 |
350 | 350 | ||
351 | pub mod PubMod { | 351 | pub mod PubMod { |
352 | pub fn test_function() {}; | 352 | pub fn test_function() {}; |
@@ -377,7 +377,7 @@ macro_rules! foo { | |||
377 | 377 | ||
378 | //- /main.rs crate:main deps:crate_with_macro | 378 | //- /main.rs crate:main deps:crate_with_macro |
379 | fn main() { | 379 | fn main() { |
380 | foo<|> | 380 | foo$0 |
381 | } | 381 | } |
382 | ", | 382 | ", |
383 | r"use crate_with_macro::foo; | 383 | r"use crate_with_macro::foo; |
@@ -395,7 +395,7 @@ fn main() { | |||
395 | auto_import, | 395 | auto_import, |
396 | r" | 396 | r" |
397 | struct AssistInfo { | 397 | struct AssistInfo { |
398 | group_label: Option<<|>GroupLabel>, | 398 | group_label: Option<$0GroupLabel>, |
399 | } | 399 | } |
400 | 400 | ||
401 | mod m { pub struct GroupLabel; } | 401 | mod m { pub struct GroupLabel; } |
@@ -419,7 +419,7 @@ fn main() { | |||
419 | 419 | ||
420 | use mod1::mod2; | 420 | use mod1::mod2; |
421 | fn main() { | 421 | fn main() { |
422 | mod2::mod3::TestStruct<|> | 422 | mod2::mod3::TestStruct$0 |
423 | } | 423 | } |
424 | ", | 424 | ", |
425 | ); | 425 | ); |
@@ -436,7 +436,7 @@ fn main() { | |||
436 | 436 | ||
437 | use test_mod::test_function; | 437 | use test_mod::test_function; |
438 | fn main() { | 438 | fn main() { |
439 | test_function<|> | 439 | test_function$0 |
440 | } | 440 | } |
441 | ", | 441 | ", |
442 | ); | 442 | ); |
@@ -455,7 +455,7 @@ fn main() { | |||
455 | } | 455 | } |
456 | 456 | ||
457 | fn main() { | 457 | fn main() { |
458 | TestStruct::test_function<|> | 458 | TestStruct::test_function$0 |
459 | } | 459 | } |
460 | ", | 460 | ", |
461 | r" | 461 | r" |
@@ -488,7 +488,7 @@ fn main() { | |||
488 | } | 488 | } |
489 | 489 | ||
490 | fn main() { | 490 | fn main() { |
491 | TestStruct::TEST_CONST<|> | 491 | TestStruct::TEST_CONST$0 |
492 | } | 492 | } |
493 | ", | 493 | ", |
494 | r" | 494 | r" |
@@ -524,7 +524,7 @@ fn main() { | |||
524 | } | 524 | } |
525 | 525 | ||
526 | fn main() { | 526 | fn main() { |
527 | test_mod::TestStruct::test_function<|> | 527 | test_mod::TestStruct::test_function$0 |
528 | } | 528 | } |
529 | ", | 529 | ", |
530 | r" | 530 | r" |
@@ -573,7 +573,7 @@ fn main() { | |||
573 | 573 | ||
574 | use test_mod::TestTrait2; | 574 | use test_mod::TestTrait2; |
575 | fn main() { | 575 | fn main() { |
576 | test_mod::TestEnum::test_function<|>; | 576 | test_mod::TestEnum::test_function$0; |
577 | } | 577 | } |
578 | ", | 578 | ", |
579 | ) | 579 | ) |
@@ -595,7 +595,7 @@ fn main() { | |||
595 | } | 595 | } |
596 | 596 | ||
597 | fn main() { | 597 | fn main() { |
598 | test_mod::TestStruct::TEST_CONST<|> | 598 | test_mod::TestStruct::TEST_CONST$0 |
599 | } | 599 | } |
600 | ", | 600 | ", |
601 | r" | 601 | r" |
@@ -644,7 +644,7 @@ fn main() { | |||
644 | 644 | ||
645 | use test_mod::TestTrait2; | 645 | use test_mod::TestTrait2; |
646 | fn main() { | 646 | fn main() { |
647 | test_mod::TestEnum::TEST_CONST<|>; | 647 | test_mod::TestEnum::TEST_CONST$0; |
648 | } | 648 | } |
649 | ", | 649 | ", |
650 | ) | 650 | ) |
@@ -667,7 +667,7 @@ fn main() { | |||
667 | 667 | ||
668 | fn main() { | 668 | fn main() { |
669 | let test_struct = test_mod::TestStruct {}; | 669 | let test_struct = test_mod::TestStruct {}; |
670 | test_struct.test_meth<|>od() | 670 | test_struct.test_meth$0od() |
671 | } | 671 | } |
672 | ", | 672 | ", |
673 | r" | 673 | r" |
@@ -699,7 +699,7 @@ fn main() { | |||
699 | //- /main.rs crate:main deps:dep | 699 | //- /main.rs crate:main deps:dep |
700 | fn main() { | 700 | fn main() { |
701 | let test_struct = dep::test_mod::TestStruct {}; | 701 | let test_struct = dep::test_mod::TestStruct {}; |
702 | test_struct.test_meth<|>od() | 702 | test_struct.test_meth$0od() |
703 | } | 703 | } |
704 | //- /dep.rs crate:dep | 704 | //- /dep.rs crate:dep |
705 | pub mod test_mod { | 705 | pub mod test_mod { |
@@ -730,7 +730,7 @@ fn main() { | |||
730 | r" | 730 | r" |
731 | //- /main.rs crate:main deps:dep | 731 | //- /main.rs crate:main deps:dep |
732 | fn main() { | 732 | fn main() { |
733 | dep::test_mod::TestStruct::test_func<|>tion | 733 | dep::test_mod::TestStruct::test_func$0tion |
734 | } | 734 | } |
735 | //- /dep.rs crate:dep | 735 | //- /dep.rs crate:dep |
736 | pub mod test_mod { | 736 | pub mod test_mod { |
@@ -760,7 +760,7 @@ fn main() { | |||
760 | r" | 760 | r" |
761 | //- /main.rs crate:main deps:dep | 761 | //- /main.rs crate:main deps:dep |
762 | fn main() { | 762 | fn main() { |
763 | dep::test_mod::TestStruct::CONST<|> | 763 | dep::test_mod::TestStruct::CONST$0 |
764 | } | 764 | } |
765 | //- /dep.rs crate:dep | 765 | //- /dep.rs crate:dep |
766 | pub mod test_mod { | 766 | pub mod test_mod { |
@@ -791,7 +791,7 @@ fn main() { | |||
791 | //- /main.rs crate:main deps:dep | 791 | //- /main.rs crate:main deps:dep |
792 | fn main() { | 792 | fn main() { |
793 | let test_struct = dep::test_mod::TestStruct {}; | 793 | let test_struct = dep::test_mod::TestStruct {}; |
794 | test_struct.test_func<|>tion() | 794 | test_struct.test_func$0tion() |
795 | } | 795 | } |
796 | //- /dep.rs crate:dep | 796 | //- /dep.rs crate:dep |
797 | pub mod test_mod { | 797 | pub mod test_mod { |
@@ -815,7 +815,7 @@ fn main() { | |||
815 | //- /main.rs crate:main deps:dep | 815 | //- /main.rs crate:main deps:dep |
816 | fn main() { | 816 | fn main() { |
817 | let test_struct = dep::test_mod::TestStruct {}; | 817 | let test_struct = dep::test_mod::TestStruct {}; |
818 | test_struct.test_meth<|>od() | 818 | test_struct.test_meth$0od() |
819 | } | 819 | } |
820 | //- /dep.rs crate:dep | 820 | //- /dep.rs crate:dep |
821 | pub mod test_mod { | 821 | pub mod test_mod { |
@@ -858,7 +858,7 @@ fn main() { | |||
858 | use test_mod::TestTrait2; | 858 | use test_mod::TestTrait2; |
859 | fn main() { | 859 | fn main() { |
860 | let one = test_mod::TestEnum::One; | 860 | let one = test_mod::TestEnum::One; |
861 | one.test<|>_method(); | 861 | one.test$0_method(); |
862 | } | 862 | } |
863 | ", | 863 | ", |
864 | ) | 864 | ) |
@@ -874,7 +874,7 @@ pub struct Struct; | |||
874 | 874 | ||
875 | //- /main.rs crate:main deps:dep | 875 | //- /main.rs crate:main deps:dep |
876 | fn main() { | 876 | fn main() { |
877 | Struct<|> | 877 | Struct$0 |
878 | } | 878 | } |
879 | ", | 879 | ", |
880 | r"use dep::Struct; | 880 | r"use dep::Struct; |
@@ -902,7 +902,7 @@ pub fn panic_fmt() {} | |||
902 | //- /main.rs crate:main deps:dep | 902 | //- /main.rs crate:main deps:dep |
903 | struct S; | 903 | struct S; |
904 | 904 | ||
905 | impl f<|>mt::Display for S {} | 905 | impl f$0mt::Display for S {} |
906 | ", | 906 | ", |
907 | r"use dep::fmt; | 907 | r"use dep::fmt; |
908 | 908 | ||
@@ -930,7 +930,7 @@ mac!(); | |||
930 | 930 | ||
931 | //- /main.rs crate:main deps:dep | 931 | //- /main.rs crate:main deps:dep |
932 | fn main() { | 932 | fn main() { |
933 | Cheese<|>; | 933 | Cheese$0; |
934 | } | 934 | } |
935 | ", | 935 | ", |
936 | r"use dep::Cheese; | 936 | r"use dep::Cheese; |
@@ -954,7 +954,7 @@ pub struct fmt; | |||
954 | 954 | ||
955 | //- /main.rs crate:main deps:dep | 955 | //- /main.rs crate:main deps:dep |
956 | fn main() { | 956 | fn main() { |
957 | FMT<|>; | 957 | FMT$0; |
958 | } | 958 | } |
959 | ", | 959 | ", |
960 | r"use dep::FMT; | 960 | r"use dep::FMT; |
diff --git a/crates/assists/src/handlers/change_visibility.rs b/crates/assists/src/handlers/change_visibility.rs index 22d7c95d9..ac8c44124 100644 --- a/crates/assists/src/handlers/change_visibility.rs +++ b/crates/assists/src/handlers/change_visibility.rs | |||
@@ -13,7 +13,7 @@ use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists}; | |||
13 | // Adds or changes existing visibility specifier. | 13 | // Adds or changes existing visibility specifier. |
14 | // | 14 | // |
15 | // ``` | 15 | // ``` |
16 | // <|>fn frobnicate() {} | 16 | // $0fn frobnicate() {} |
17 | // ``` | 17 | // ``` |
18 | // -> | 18 | // -> |
19 | // ``` | 19 | // ``` |
@@ -118,23 +118,23 @@ mod tests { | |||
118 | 118 | ||
119 | #[test] | 119 | #[test] |
120 | fn change_visibility_adds_pub_crate_to_items() { | 120 | fn change_visibility_adds_pub_crate_to_items() { |
121 | check_assist(change_visibility, "<|>fn foo() {}", "pub(crate) fn foo() {}"); | 121 | check_assist(change_visibility, "$0fn foo() {}", "pub(crate) fn foo() {}"); |
122 | check_assist(change_visibility, "f<|>n foo() {}", "pub(crate) fn foo() {}"); | 122 | check_assist(change_visibility, "f$0n foo() {}", "pub(crate) fn foo() {}"); |
123 | check_assist(change_visibility, "<|>struct Foo {}", "pub(crate) struct Foo {}"); | 123 | check_assist(change_visibility, "$0struct Foo {}", "pub(crate) struct Foo {}"); |
124 | check_assist(change_visibility, "<|>mod foo {}", "pub(crate) mod foo {}"); | 124 | check_assist(change_visibility, "$0mod foo {}", "pub(crate) mod foo {}"); |
125 | check_assist(change_visibility, "<|>trait Foo {}", "pub(crate) trait Foo {}"); | 125 | check_assist(change_visibility, "$0trait Foo {}", "pub(crate) trait Foo {}"); |
126 | check_assist(change_visibility, "m<|>od {}", "pub(crate) mod {}"); | 126 | check_assist(change_visibility, "m$0od {}", "pub(crate) mod {}"); |
127 | check_assist(change_visibility, "unsafe f<|>n foo() {}", "pub(crate) unsafe fn foo() {}"); | 127 | check_assist(change_visibility, "unsafe f$0n foo() {}", "pub(crate) unsafe fn foo() {}"); |
128 | } | 128 | } |
129 | 129 | ||
130 | #[test] | 130 | #[test] |
131 | fn change_visibility_works_with_struct_fields() { | 131 | fn change_visibility_works_with_struct_fields() { |
132 | check_assist( | 132 | check_assist( |
133 | change_visibility, | 133 | change_visibility, |
134 | r"struct S { <|>field: u32 }", | 134 | r"struct S { $0field: u32 }", |
135 | r"struct S { pub(crate) field: u32 }", | 135 | r"struct S { pub(crate) field: u32 }", |
136 | ); | 136 | ); |
137 | check_assist(change_visibility, r"struct S ( <|>u32 )", r"struct S ( pub(crate) u32 )"); | 137 | check_assist(change_visibility, r"struct S ( $0u32 )", r"struct S ( pub(crate) u32 )"); |
138 | } | 138 | } |
139 | 139 | ||
140 | #[test] | 140 | #[test] |
@@ -142,33 +142,33 @@ mod tests { | |||
142 | mark::check!(change_visibility_field_false_positive); | 142 | mark::check!(change_visibility_field_false_positive); |
143 | check_assist_not_applicable( | 143 | check_assist_not_applicable( |
144 | change_visibility, | 144 | change_visibility, |
145 | r"struct S { field: [(); { let <|>x = ();}] }", | 145 | r"struct S { field: [(); { let $0x = ();}] }", |
146 | ) | 146 | ) |
147 | } | 147 | } |
148 | 148 | ||
149 | #[test] | 149 | #[test] |
150 | fn change_visibility_pub_to_pub_crate() { | 150 | fn change_visibility_pub_to_pub_crate() { |
151 | check_assist(change_visibility, "<|>pub fn foo() {}", "pub(crate) fn foo() {}") | 151 | check_assist(change_visibility, "$0pub fn foo() {}", "pub(crate) fn foo() {}") |
152 | } | 152 | } |
153 | 153 | ||
154 | #[test] | 154 | #[test] |
155 | fn change_visibility_pub_crate_to_pub() { | 155 | fn change_visibility_pub_crate_to_pub() { |
156 | check_assist(change_visibility, "<|>pub(crate) fn foo() {}", "pub fn foo() {}") | 156 | check_assist(change_visibility, "$0pub(crate) fn foo() {}", "pub fn foo() {}") |
157 | } | 157 | } |
158 | 158 | ||
159 | #[test] | 159 | #[test] |
160 | fn change_visibility_const() { | 160 | fn change_visibility_const() { |
161 | check_assist(change_visibility, "<|>const FOO = 3u8;", "pub(crate) const FOO = 3u8;"); | 161 | check_assist(change_visibility, "$0const FOO = 3u8;", "pub(crate) const FOO = 3u8;"); |
162 | } | 162 | } |
163 | 163 | ||
164 | #[test] | 164 | #[test] |
165 | fn change_visibility_static() { | 165 | fn change_visibility_static() { |
166 | check_assist(change_visibility, "<|>static FOO = 3u8;", "pub(crate) static FOO = 3u8;"); | 166 | check_assist(change_visibility, "$0static FOO = 3u8;", "pub(crate) static FOO = 3u8;"); |
167 | } | 167 | } |
168 | 168 | ||
169 | #[test] | 169 | #[test] |
170 | fn change_visibility_type_alias() { | 170 | fn change_visibility_type_alias() { |
171 | check_assist(change_visibility, "<|>type T = ();", "pub(crate) type T = ();"); | 171 | check_assist(change_visibility, "$0type T = ();", "pub(crate) type T = ();"); |
172 | } | 172 | } |
173 | 173 | ||
174 | #[test] | 174 | #[test] |
@@ -181,7 +181,7 @@ mod tests { | |||
181 | // comments | 181 | // comments |
182 | 182 | ||
183 | #[derive(Debug)] | 183 | #[derive(Debug)] |
184 | <|>struct Foo; | 184 | $0struct Foo; |
185 | ", | 185 | ", |
186 | r" | 186 | r" |
187 | /// docs | 187 | /// docs |
@@ -199,14 +199,14 @@ mod tests { | |||
199 | check_assist_not_applicable( | 199 | check_assist_not_applicable( |
200 | change_visibility, | 200 | change_visibility, |
201 | r"mod foo { pub enum Foo {Foo1} } | 201 | r"mod foo { pub enum Foo {Foo1} } |
202 | fn main() { foo::Foo::Foo1<|> } ", | 202 | fn main() { foo::Foo::Foo1$0 } ", |
203 | ); | 203 | ); |
204 | } | 204 | } |
205 | 205 | ||
206 | #[test] | 206 | #[test] |
207 | fn change_visibility_target() { | 207 | fn change_visibility_target() { |
208 | check_assist_target(change_visibility, "<|>fn foo() {}", "fn"); | 208 | check_assist_target(change_visibility, "$0fn foo() {}", "fn"); |
209 | check_assist_target(change_visibility, "pub(crate)<|> fn foo() {}", "pub(crate)"); | 209 | check_assist_target(change_visibility, "pub(crate)$0 fn foo() {}", "pub(crate)"); |
210 | check_assist_target(change_visibility, "struct S { <|>field: u32 }", "field"); | 210 | check_assist_target(change_visibility, "struct S { $0field: u32 }", "field"); |
211 | } | 211 | } |
212 | } | 212 | } |
diff --git a/crates/assists/src/handlers/convert_integer_literal.rs b/crates/assists/src/handlers/convert_integer_literal.rs index 667115382..a8a819cfc 100644 --- a/crates/assists/src/handlers/convert_integer_literal.rs +++ b/crates/assists/src/handlers/convert_integer_literal.rs | |||
@@ -7,7 +7,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel}; | |||
7 | // Converts the base of integer literals to other bases. | 7 | // Converts the base of integer literals to other bases. |
8 | // | 8 | // |
9 | // ``` | 9 | // ``` |
10 | // const _: i32 = 10<|>; | 10 | // const _: i32 = 10$0; |
11 | // ``` | 11 | // ``` |
12 | // -> | 12 | // -> |
13 | // ``` | 13 | // ``` |
@@ -65,47 +65,47 @@ mod tests { | |||
65 | 65 | ||
66 | #[test] | 66 | #[test] |
67 | fn binary_target() { | 67 | fn binary_target() { |
68 | check_assist_target(convert_integer_literal, "const _: i32 = 0b1010<|>;", "0b1010"); | 68 | check_assist_target(convert_integer_literal, "const _: i32 = 0b1010$0;", "0b1010"); |
69 | } | 69 | } |
70 | 70 | ||
71 | #[test] | 71 | #[test] |
72 | fn octal_target() { | 72 | fn octal_target() { |
73 | check_assist_target(convert_integer_literal, "const _: i32 = 0o12<|>;", "0o12"); | 73 | check_assist_target(convert_integer_literal, "const _: i32 = 0o12$0;", "0o12"); |
74 | } | 74 | } |
75 | 75 | ||
76 | #[test] | 76 | #[test] |
77 | fn decimal_target() { | 77 | fn decimal_target() { |
78 | check_assist_target(convert_integer_literal, "const _: i32 = 10<|>;", "10"); | 78 | check_assist_target(convert_integer_literal, "const _: i32 = 10$0;", "10"); |
79 | } | 79 | } |
80 | 80 | ||
81 | #[test] | 81 | #[test] |
82 | fn hexadecimal_target() { | 82 | fn hexadecimal_target() { |
83 | check_assist_target(convert_integer_literal, "const _: i32 = 0xA<|>;", "0xA"); | 83 | check_assist_target(convert_integer_literal, "const _: i32 = 0xA$0;", "0xA"); |
84 | } | 84 | } |
85 | 85 | ||
86 | #[test] | 86 | #[test] |
87 | fn binary_target_with_underscores() { | 87 | fn binary_target_with_underscores() { |
88 | check_assist_target(convert_integer_literal, "const _: i32 = 0b10_10<|>;", "0b10_10"); | 88 | check_assist_target(convert_integer_literal, "const _: i32 = 0b10_10$0;", "0b10_10"); |
89 | } | 89 | } |
90 | 90 | ||
91 | #[test] | 91 | #[test] |
92 | fn octal_target_with_underscores() { | 92 | fn octal_target_with_underscores() { |
93 | check_assist_target(convert_integer_literal, "const _: i32 = 0o1_2<|>;", "0o1_2"); | 93 | check_assist_target(convert_integer_literal, "const _: i32 = 0o1_2$0;", "0o1_2"); |
94 | } | 94 | } |
95 | 95 | ||
96 | #[test] | 96 | #[test] |
97 | fn decimal_target_with_underscores() { | 97 | fn decimal_target_with_underscores() { |
98 | check_assist_target(convert_integer_literal, "const _: i32 = 1_0<|>;", "1_0"); | 98 | check_assist_target(convert_integer_literal, "const _: i32 = 1_0$0;", "1_0"); |
99 | } | 99 | } |
100 | 100 | ||
101 | #[test] | 101 | #[test] |
102 | fn hexadecimal_target_with_underscores() { | 102 | fn hexadecimal_target_with_underscores() { |
103 | check_assist_target(convert_integer_literal, "const _: i32 = 0x_A<|>;", "0x_A"); | 103 | check_assist_target(convert_integer_literal, "const _: i32 = 0x_A$0;", "0x_A"); |
104 | } | 104 | } |
105 | 105 | ||
106 | #[test] | 106 | #[test] |
107 | fn convert_decimal_integer() { | 107 | fn convert_decimal_integer() { |
108 | let before = "const _: i32 = 1000<|>;"; | 108 | let before = "const _: i32 = 1000$0;"; |
109 | 109 | ||
110 | check_assist_by_label( | 110 | check_assist_by_label( |
111 | convert_integer_literal, | 111 | convert_integer_literal, |
@@ -131,7 +131,7 @@ mod tests { | |||
131 | 131 | ||
132 | #[test] | 132 | #[test] |
133 | fn convert_hexadecimal_integer() { | 133 | fn convert_hexadecimal_integer() { |
134 | let before = "const _: i32 = 0xFF<|>;"; | 134 | let before = "const _: i32 = 0xFF$0;"; |
135 | 135 | ||
136 | check_assist_by_label( | 136 | check_assist_by_label( |
137 | convert_integer_literal, | 137 | convert_integer_literal, |
@@ -157,7 +157,7 @@ mod tests { | |||
157 | 157 | ||
158 | #[test] | 158 | #[test] |
159 | fn convert_binary_integer() { | 159 | fn convert_binary_integer() { |
160 | let before = "const _: i32 = 0b11111111<|>;"; | 160 | let before = "const _: i32 = 0b11111111$0;"; |
161 | 161 | ||
162 | check_assist_by_label( | 162 | check_assist_by_label( |
163 | convert_integer_literal, | 163 | convert_integer_literal, |
@@ -183,7 +183,7 @@ mod tests { | |||
183 | 183 | ||
184 | #[test] | 184 | #[test] |
185 | fn convert_octal_integer() { | 185 | fn convert_octal_integer() { |
186 | let before = "const _: i32 = 0o377<|>;"; | 186 | let before = "const _: i32 = 0o377$0;"; |
187 | 187 | ||
188 | check_assist_by_label( | 188 | check_assist_by_label( |
189 | convert_integer_literal, | 189 | convert_integer_literal, |
@@ -209,7 +209,7 @@ mod tests { | |||
209 | 209 | ||
210 | #[test] | 210 | #[test] |
211 | fn convert_integer_with_underscores() { | 211 | fn convert_integer_with_underscores() { |
212 | let before = "const _: i32 = 1_00_0<|>;"; | 212 | let before = "const _: i32 = 1_00_0$0;"; |
213 | 213 | ||
214 | check_assist_by_label( | 214 | check_assist_by_label( |
215 | convert_integer_literal, | 215 | convert_integer_literal, |
@@ -235,7 +235,7 @@ mod tests { | |||
235 | 235 | ||
236 | #[test] | 236 | #[test] |
237 | fn convert_integer_with_suffix() { | 237 | fn convert_integer_with_suffix() { |
238 | let before = "const _: i32 = 1000i32<|>;"; | 238 | let before = "const _: i32 = 1000i32$0;"; |
239 | 239 | ||
240 | check_assist_by_label( | 240 | check_assist_by_label( |
241 | convert_integer_literal, | 241 | convert_integer_literal, |
@@ -262,7 +262,7 @@ mod tests { | |||
262 | #[test] | 262 | #[test] |
263 | fn convert_overflowing_literal() { | 263 | fn convert_overflowing_literal() { |
264 | let before = "const _: i32 = | 264 | let before = "const _: i32 = |
265 | 111111111111111111111111111111111111111111111111111111111111111111111111<|>;"; | 265 | 111111111111111111111111111111111111111111111111111111111111111111111111$0;"; |
266 | check_assist_not_applicable(convert_integer_literal, before); | 266 | check_assist_not_applicable(convert_integer_literal, before); |
267 | } | 267 | } |
268 | } | 268 | } |
diff --git a/crates/assists/src/handlers/early_return.rs b/crates/assists/src/handlers/early_return.rs index 2c48f32bf..8bbbb7ed5 100644 --- a/crates/assists/src/handlers/early_return.rs +++ b/crates/assists/src/handlers/early_return.rs | |||
@@ -24,7 +24,7 @@ use crate::{ | |||
24 | // | 24 | // |
25 | // ``` | 25 | // ``` |
26 | // fn main() { | 26 | // fn main() { |
27 | // <|>if cond { | 27 | // $0if cond { |
28 | // foo(); | 28 | // foo(); |
29 | // bar(); | 29 | // bar(); |
30 | // } | 30 | // } |
@@ -200,7 +200,7 @@ mod tests { | |||
200 | r#" | 200 | r#" |
201 | fn main() { | 201 | fn main() { |
202 | bar(); | 202 | bar(); |
203 | if<|> true { | 203 | if$0 true { |
204 | foo(); | 204 | foo(); |
205 | 205 | ||
206 | //comment | 206 | //comment |
@@ -230,7 +230,7 @@ mod tests { | |||
230 | r#" | 230 | r#" |
231 | fn main(n: Option<String>) { | 231 | fn main(n: Option<String>) { |
232 | bar(); | 232 | bar(); |
233 | if<|> let Some(n) = n { | 233 | if$0 let Some(n) = n { |
234 | foo(n); | 234 | foo(n); |
235 | 235 | ||
236 | //comment | 236 | //comment |
@@ -260,7 +260,7 @@ mod tests { | |||
260 | convert_to_guarded_return, | 260 | convert_to_guarded_return, |
261 | r#" | 261 | r#" |
262 | fn main() { | 262 | fn main() { |
263 | if<|> let Ok(x) = Err(92) { | 263 | if$0 let Ok(x) = Err(92) { |
264 | foo(x); | 264 | foo(x); |
265 | } | 265 | } |
266 | } | 266 | } |
@@ -284,7 +284,7 @@ mod tests { | |||
284 | r#" | 284 | r#" |
285 | fn main(n: Option<String>) { | 285 | fn main(n: Option<String>) { |
286 | bar(); | 286 | bar(); |
287 | if<|> let Ok(n) = n { | 287 | if$0 let Ok(n) = n { |
288 | foo(n); | 288 | foo(n); |
289 | 289 | ||
290 | //comment | 290 | //comment |
@@ -315,7 +315,7 @@ mod tests { | |||
315 | r#" | 315 | r#" |
316 | fn main() { | 316 | fn main() { |
317 | while true { | 317 | while true { |
318 | if<|> true { | 318 | if$0 true { |
319 | foo(); | 319 | foo(); |
320 | bar(); | 320 | bar(); |
321 | } | 321 | } |
@@ -343,7 +343,7 @@ mod tests { | |||
343 | r#" | 343 | r#" |
344 | fn main() { | 344 | fn main() { |
345 | while true { | 345 | while true { |
346 | if<|> let Some(n) = n { | 346 | if$0 let Some(n) = n { |
347 | foo(n); | 347 | foo(n); |
348 | bar(); | 348 | bar(); |
349 | } | 349 | } |
@@ -372,7 +372,7 @@ mod tests { | |||
372 | r#" | 372 | r#" |
373 | fn main() { | 373 | fn main() { |
374 | loop { | 374 | loop { |
375 | if<|> true { | 375 | if$0 true { |
376 | foo(); | 376 | foo(); |
377 | bar(); | 377 | bar(); |
378 | } | 378 | } |
@@ -400,7 +400,7 @@ mod tests { | |||
400 | r#" | 400 | r#" |
401 | fn main() { | 401 | fn main() { |
402 | loop { | 402 | loop { |
403 | if<|> let Some(n) = n { | 403 | if$0 let Some(n) = n { |
404 | foo(n); | 404 | foo(n); |
405 | bar(); | 405 | bar(); |
406 | } | 406 | } |
@@ -428,7 +428,7 @@ mod tests { | |||
428 | convert_to_guarded_return, | 428 | convert_to_guarded_return, |
429 | r#" | 429 | r#" |
430 | fn main() { | 430 | fn main() { |
431 | if<|> true { | 431 | if$0 true { |
432 | return; | 432 | return; |
433 | } | 433 | } |
434 | } | 434 | } |
@@ -443,7 +443,7 @@ mod tests { | |||
443 | r#" | 443 | r#" |
444 | fn main() { | 444 | fn main() { |
445 | loop { | 445 | loop { |
446 | if<|> true { | 446 | if$0 true { |
447 | continue; | 447 | continue; |
448 | } | 448 | } |
449 | } | 449 | } |
@@ -458,7 +458,7 @@ mod tests { | |||
458 | convert_to_guarded_return, | 458 | convert_to_guarded_return, |
459 | r#" | 459 | r#" |
460 | fn main() { | 460 | fn main() { |
461 | if<|> true { | 461 | if$0 true { |
462 | return | 462 | return |
463 | } | 463 | } |
464 | } | 464 | } |
@@ -472,7 +472,7 @@ mod tests { | |||
472 | convert_to_guarded_return, | 472 | convert_to_guarded_return, |
473 | r#" | 473 | r#" |
474 | fn main() { | 474 | fn main() { |
475 | if<|> true { | 475 | if$0 true { |
476 | foo(); | 476 | foo(); |
477 | } else { | 477 | } else { |
478 | bar() | 478 | bar() |
@@ -488,7 +488,7 @@ mod tests { | |||
488 | convert_to_guarded_return, | 488 | convert_to_guarded_return, |
489 | r#" | 489 | r#" |
490 | fn main() { | 490 | fn main() { |
491 | if<|> true { | 491 | if$0 true { |
492 | foo(); | 492 | foo(); |
493 | } | 493 | } |
494 | bar(); | 494 | bar(); |
@@ -504,7 +504,7 @@ mod tests { | |||
504 | r#" | 504 | r#" |
505 | fn main() { | 505 | fn main() { |
506 | if false { | 506 | if false { |
507 | if<|> true { | 507 | if$0 true { |
508 | foo(); | 508 | foo(); |
509 | } | 509 | } |
510 | } | 510 | } |
diff --git a/crates/assists/src/handlers/expand_glob_import.rs b/crates/assists/src/handlers/expand_glob_import.rs index f51a9a4ad..5fe617ba4 100644 --- a/crates/assists/src/handlers/expand_glob_import.rs +++ b/crates/assists/src/handlers/expand_glob_import.rs | |||
@@ -25,7 +25,7 @@ use crate::{ | |||
25 | // pub struct Baz; | 25 | // pub struct Baz; |
26 | // } | 26 | // } |
27 | // | 27 | // |
28 | // use foo::*<|>; | 28 | // use foo::*$0; |
29 | // | 29 | // |
30 | // fn qux(bar: Bar, baz: Baz) {} | 30 | // fn qux(bar: Bar, baz: Baz) {} |
31 | // ``` | 31 | // ``` |
@@ -201,7 +201,7 @@ fn is_mod_visible_from(ctx: &AssistContext, module: Module, from: Module) -> boo | |||
201 | // } | 201 | // } |
202 | // | 202 | // |
203 | // ↓ --------------- | 203 | // ↓ --------------- |
204 | // use foo::*<|>; | 204 | // use foo::*$0; |
205 | // use baz::Baz; | 205 | // use baz::Baz; |
206 | // ↑ --------------- | 206 | // ↑ --------------- |
207 | fn find_imported_defs(ctx: &AssistContext, star: SyntaxToken) -> Option<Vec<Def>> { | 207 | fn find_imported_defs(ctx: &AssistContext, star: SyntaxToken) -> Option<Vec<Def>> { |
@@ -303,7 +303,7 @@ mod foo { | |||
303 | pub fn f() {} | 303 | pub fn f() {} |
304 | } | 304 | } |
305 | 305 | ||
306 | use foo::*<|>; | 306 | use foo::*$0; |
307 | 307 | ||
308 | fn qux(bar: Bar, baz: Baz) { | 308 | fn qux(bar: Bar, baz: Baz) { |
309 | f(); | 309 | f(); |
@@ -340,7 +340,7 @@ mod foo { | |||
340 | pub fn f() {} | 340 | pub fn f() {} |
341 | } | 341 | } |
342 | 342 | ||
343 | use foo::{*<|>, f}; | 343 | use foo::{*$0, f}; |
344 | 344 | ||
345 | fn qux(bar: Bar, baz: Baz) { | 345 | fn qux(bar: Bar, baz: Baz) { |
346 | f(); | 346 | f(); |
@@ -378,7 +378,7 @@ mod foo { | |||
378 | } | 378 | } |
379 | 379 | ||
380 | use foo::Bar; | 380 | use foo::Bar; |
381 | use foo::{*<|>, f}; | 381 | use foo::{*$0, f}; |
382 | 382 | ||
383 | fn qux(bar: Bar, baz: Baz) { | 383 | fn qux(bar: Bar, baz: Baz) { |
384 | f(); | 384 | f(); |
@@ -422,7 +422,7 @@ mod foo { | |||
422 | } | 422 | } |
423 | } | 423 | } |
424 | 424 | ||
425 | use foo::{bar::{*<|>, f}, baz::*}; | 425 | use foo::{bar::{*$0, f}, baz::*}; |
426 | 426 | ||
427 | fn qux(bar: Bar, baz: Baz) { | 427 | fn qux(bar: Bar, baz: Baz) { |
428 | f(); | 428 | f(); |
@@ -470,7 +470,7 @@ mod foo { | |||
470 | } | 470 | } |
471 | } | 471 | } |
472 | 472 | ||
473 | use foo::{bar::{Bar, Baz, f}, baz::*<|>}; | 473 | use foo::{bar::{Bar, Baz, f}, baz::*$0}; |
474 | 474 | ||
475 | fn qux(bar: Bar, baz: Baz) { | 475 | fn qux(bar: Bar, baz: Baz) { |
476 | f(); | 476 | f(); |
@@ -529,7 +529,7 @@ mod foo { | |||
529 | 529 | ||
530 | use foo::{ | 530 | use foo::{ |
531 | bar::{*, f}, | 531 | bar::{*, f}, |
532 | baz::{g, qux::*<|>} | 532 | baz::{g, qux::*$0} |
533 | }; | 533 | }; |
534 | 534 | ||
535 | fn qux(bar: Bar, baz: Baz) { | 535 | fn qux(bar: Bar, baz: Baz) { |
@@ -605,7 +605,7 @@ mod foo { | |||
605 | 605 | ||
606 | use foo::{ | 606 | use foo::{ |
607 | bar::{*, f}, | 607 | bar::{*, f}, |
608 | baz::{g, qux::{h, q::*<|>}} | 608 | baz::{g, qux::{h, q::*$0}} |
609 | }; | 609 | }; |
610 | 610 | ||
611 | fn qux(bar: Bar, baz: Baz) { | 611 | fn qux(bar: Bar, baz: Baz) { |
@@ -681,7 +681,7 @@ mod foo { | |||
681 | 681 | ||
682 | use foo::{ | 682 | use foo::{ |
683 | bar::{*, f}, | 683 | bar::{*, f}, |
684 | baz::{g, qux::{q::j, *<|>}} | 684 | baz::{g, qux::{q::j, *$0}} |
685 | }; | 685 | }; |
686 | 686 | ||
687 | fn qux(bar: Bar, baz: Baz) { | 687 | fn qux(bar: Bar, baz: Baz) { |
@@ -747,7 +747,7 @@ fn qux(bar: Bar, baz: Baz) { | |||
747 | // pub fn baz() {} | 747 | // pub fn baz() {} |
748 | 748 | ||
749 | // //- /main.rs crate:main deps:foo | 749 | // //- /main.rs crate:main deps:foo |
750 | // use foo::*<|>; | 750 | // use foo::*$0; |
751 | 751 | ||
752 | // fn main() { | 752 | // fn main() { |
753 | // bar!(); | 753 | // bar!(); |
@@ -777,7 +777,7 @@ pub trait Tr { | |||
777 | impl Tr for () {} | 777 | impl Tr for () {} |
778 | 778 | ||
779 | //- /main.rs crate:main deps:foo | 779 | //- /main.rs crate:main deps:foo |
780 | use foo::*<|>; | 780 | use foo::*$0; |
781 | 781 | ||
782 | fn main() { | 782 | fn main() { |
783 | ().method(); | 783 | ().method(); |
@@ -807,7 +807,7 @@ pub trait Tr2 { | |||
807 | impl Tr2 for () {} | 807 | impl Tr2 for () {} |
808 | 808 | ||
809 | //- /main.rs crate:main deps:foo | 809 | //- /main.rs crate:main deps:foo |
810 | use foo::*<|>; | 810 | use foo::*$0; |
811 | 811 | ||
812 | fn main() { | 812 | fn main() { |
813 | ().method(); | 813 | ().method(); |
@@ -834,7 +834,7 @@ mod foo { | |||
834 | } | 834 | } |
835 | } | 835 | } |
836 | 836 | ||
837 | use foo::bar::*<|>; | 837 | use foo::bar::*$0; |
838 | 838 | ||
839 | fn baz(bar: Bar) {} | 839 | fn baz(bar: Bar) {} |
840 | ", | 840 | ", |
@@ -851,7 +851,7 @@ mod foo { | |||
851 | } | 851 | } |
852 | } | 852 | } |
853 | 853 | ||
854 | use foo::bar::baz::*<|>; | 854 | use foo::bar::baz::*$0; |
855 | 855 | ||
856 | fn qux(baz: Baz) {} | 856 | fn qux(baz: Baz) {} |
857 | ", | 857 | ", |
@@ -869,7 +869,7 @@ fn qux(baz: Baz) {} | |||
869 | pub struct Qux; | 869 | pub struct Qux; |
870 | } | 870 | } |
871 | 871 | ||
872 | use foo::Bar<|>; | 872 | use foo::Bar$0; |
873 | 873 | ||
874 | fn qux(bar: Bar, baz: Baz) {} | 874 | fn qux(bar: Bar, baz: Baz) {} |
875 | ", | 875 | ", |
@@ -885,7 +885,7 @@ mod foo { | |||
885 | pub struct Bar; | 885 | pub struct Bar; |
886 | } | 886 | } |
887 | 887 | ||
888 | use foo::{*<|>}; | 888 | use foo::{*$0}; |
889 | 889 | ||
890 | struct Baz { | 890 | struct Baz { |
891 | bar: Bar | 891 | bar: Bar |
diff --git a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs index 6f35a061c..e3ef04932 100644 --- a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs | |||
@@ -2,12 +2,16 @@ use std::iter; | |||
2 | 2 | ||
3 | use either::Either; | 3 | use either::Either; |
4 | use hir::{AsName, Module, ModuleDef, Name, Variant}; | 4 | use hir::{AsName, Module, ModuleDef, Name, Variant}; |
5 | use ide_db::helpers::{ | 5 | use ide_db::{ |
6 | insert_use::{insert_use, ImportScope}, | 6 | defs::Definition, |
7 | mod_path_to_ast, | 7 | helpers::{ |
8 | insert_use::{insert_use, ImportScope}, | ||
9 | mod_path_to_ast, | ||
10 | }, | ||
11 | search::FileReference, | ||
12 | RootDatabase, | ||
8 | }; | 13 | }; |
9 | use ide_db::{defs::Definition, search::Reference, RootDatabase}; | 14 | use rustc_hash::FxHashSet; |
10 | use rustc_hash::{FxHashMap, FxHashSet}; | ||
11 | use syntax::{ | 15 | use syntax::{ |
12 | algo::{find_node_at_offset, SyntaxRewriter}, | 16 | algo::{find_node_at_offset, SyntaxRewriter}, |
13 | ast::{self, edit::IndentLevel, make, AstNode, NameOwner, VisibilityOwner}, | 17 | ast::{self, edit::IndentLevel, make, AstNode, NameOwner, VisibilityOwner}, |
@@ -21,7 +25,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
21 | // Extracts a struct from enum variant. | 25 | // Extracts a struct from enum variant. |
22 | // | 26 | // |
23 | // ``` | 27 | // ``` |
24 | // enum A { <|>One(u32, u32) } | 28 | // enum A { $0One(u32, u32) } |
25 | // ``` | 29 | // ``` |
26 | // -> | 30 | // -> |
27 | // ``` | 31 | // ``` |
@@ -58,29 +62,29 @@ pub(crate) fn extract_struct_from_enum_variant( | |||
58 | let mut visited_modules_set = FxHashSet::default(); | 62 | let mut visited_modules_set = FxHashSet::default(); |
59 | let current_module = enum_hir.module(ctx.db()); | 63 | let current_module = enum_hir.module(ctx.db()); |
60 | visited_modules_set.insert(current_module); | 64 | visited_modules_set.insert(current_module); |
61 | let mut rewriters = FxHashMap::default(); | 65 | let mut def_rewriter = None; |
62 | for reference in usages { | 66 | for (file_id, references) in usages { |
63 | let rewriter = rewriters | 67 | let mut rewriter = SyntaxRewriter::default(); |
64 | .entry(reference.file_range.file_id) | 68 | let source_file = ctx.sema.parse(file_id); |
65 | .or_insert_with(SyntaxRewriter::default); | 69 | for reference in references { |
66 | let source_file = ctx.sema.parse(reference.file_range.file_id); | 70 | update_reference( |
67 | update_reference( | 71 | ctx, |
68 | ctx, | 72 | &mut rewriter, |
69 | rewriter, | 73 | reference, |
70 | reference, | 74 | &source_file, |
71 | &source_file, | 75 | &enum_module_def, |
72 | &enum_module_def, | 76 | &variant_hir_name, |
73 | &variant_hir_name, | 77 | &mut visited_modules_set, |
74 | &mut visited_modules_set, | 78 | ); |
75 | ); | 79 | } |
76 | } | 80 | if file_id == ctx.frange.file_id { |
77 | let mut rewriter = | 81 | def_rewriter = Some(rewriter); |
78 | rewriters.remove(&ctx.frange.file_id).unwrap_or_else(SyntaxRewriter::default); | 82 | continue; |
79 | for (file_id, rewriter) in rewriters { | 83 | } |
80 | builder.edit_file(file_id); | 84 | builder.edit_file(file_id); |
81 | builder.rewrite(rewriter); | 85 | builder.rewrite(rewriter); |
82 | } | 86 | } |
83 | builder.edit_file(ctx.frange.file_id); | 87 | let mut rewriter = def_rewriter.unwrap_or_default(); |
84 | update_variant(&mut rewriter, &variant); | 88 | update_variant(&mut rewriter, &variant); |
85 | extract_struct_def( | 89 | extract_struct_def( |
86 | &mut rewriter, | 90 | &mut rewriter, |
@@ -90,6 +94,7 @@ pub(crate) fn extract_struct_from_enum_variant( | |||
90 | &variant.parent_enum().syntax().clone().into(), | 94 | &variant.parent_enum().syntax().clone().into(), |
91 | enum_ast.visibility(), | 95 | enum_ast.visibility(), |
92 | ); | 96 | ); |
97 | builder.edit_file(ctx.frange.file_id); | ||
93 | builder.rewrite(rewriter); | 98 | builder.rewrite(rewriter); |
94 | }, | 99 | }, |
95 | ) | 100 | ) |
@@ -205,13 +210,13 @@ fn update_variant(rewriter: &mut SyntaxRewriter, variant: &ast::Variant) -> Opti | |||
205 | fn update_reference( | 210 | fn update_reference( |
206 | ctx: &AssistContext, | 211 | ctx: &AssistContext, |
207 | rewriter: &mut SyntaxRewriter, | 212 | rewriter: &mut SyntaxRewriter, |
208 | reference: Reference, | 213 | reference: FileReference, |
209 | source_file: &SourceFile, | 214 | source_file: &SourceFile, |
210 | enum_module_def: &ModuleDef, | 215 | enum_module_def: &ModuleDef, |
211 | variant_hir_name: &Name, | 216 | variant_hir_name: &Name, |
212 | visited_modules_set: &mut FxHashSet<Module>, | 217 | visited_modules_set: &mut FxHashSet<Module>, |
213 | ) -> Option<()> { | 218 | ) -> Option<()> { |
214 | let offset = reference.file_range.range.start(); | 219 | let offset = reference.range.start(); |
215 | let (segment, expr) = if let Some(path_expr) = | 220 | let (segment, expr) = if let Some(path_expr) = |
216 | find_node_at_offset::<ast::PathExpr>(source_file.syntax(), offset) | 221 | find_node_at_offset::<ast::PathExpr>(source_file.syntax(), offset) |
217 | { | 222 | { |
@@ -251,7 +256,7 @@ mod tests { | |||
251 | fn test_extract_struct_several_fields_tuple() { | 256 | fn test_extract_struct_several_fields_tuple() { |
252 | check_assist( | 257 | check_assist( |
253 | extract_struct_from_enum_variant, | 258 | extract_struct_from_enum_variant, |
254 | "enum A { <|>One(u32, u32) }", | 259 | "enum A { $0One(u32, u32) }", |
255 | r#"struct One(pub u32, pub u32); | 260 | r#"struct One(pub u32, pub u32); |
256 | 261 | ||
257 | enum A { One(One) }"#, | 262 | enum A { One(One) }"#, |
@@ -262,7 +267,7 @@ enum A { One(One) }"#, | |||
262 | fn test_extract_struct_several_fields_named() { | 267 | fn test_extract_struct_several_fields_named() { |
263 | check_assist( | 268 | check_assist( |
264 | extract_struct_from_enum_variant, | 269 | extract_struct_from_enum_variant, |
265 | "enum A { <|>One { foo: u32, bar: u32 } }", | 270 | "enum A { $0One { foo: u32, bar: u32 } }", |
266 | r#"struct One{ pub foo: u32, pub bar: u32 } | 271 | r#"struct One{ pub foo: u32, pub bar: u32 } |
267 | 272 | ||
268 | enum A { One(One) }"#, | 273 | enum A { One(One) }"#, |
@@ -273,7 +278,7 @@ enum A { One(One) }"#, | |||
273 | fn test_extract_struct_one_field_named() { | 278 | fn test_extract_struct_one_field_named() { |
274 | check_assist( | 279 | check_assist( |
275 | extract_struct_from_enum_variant, | 280 | extract_struct_from_enum_variant, |
276 | "enum A { <|>One { foo: u32 } }", | 281 | "enum A { $0One { foo: u32 } }", |
277 | r#"struct One{ pub foo: u32 } | 282 | r#"struct One{ pub foo: u32 } |
278 | 283 | ||
279 | enum A { One(One) }"#, | 284 | enum A { One(One) }"#, |
@@ -285,7 +290,7 @@ enum A { One(One) }"#, | |||
285 | check_assist( | 290 | check_assist( |
286 | extract_struct_from_enum_variant, | 291 | extract_struct_from_enum_variant, |
287 | r#"const One: () = (); | 292 | r#"const One: () = (); |
288 | enum A { <|>One(u32, u32) }"#, | 293 | enum A { $0One(u32, u32) }"#, |
289 | r#"const One: () = (); | 294 | r#"const One: () = (); |
290 | struct One(pub u32, pub u32); | 295 | struct One(pub u32, pub u32); |
291 | 296 | ||
@@ -297,7 +302,7 @@ enum A { One(One) }"#, | |||
297 | fn test_extract_struct_pub_visibility() { | 302 | fn test_extract_struct_pub_visibility() { |
298 | check_assist( | 303 | check_assist( |
299 | extract_struct_from_enum_variant, | 304 | extract_struct_from_enum_variant, |
300 | "pub enum A { <|>One(u32, u32) }", | 305 | "pub enum A { $0One(u32, u32) }", |
301 | r#"pub struct One(pub u32, pub u32); | 306 | r#"pub struct One(pub u32, pub u32); |
302 | 307 | ||
303 | pub enum A { One(One) }"#, | 308 | pub enum A { One(One) }"#, |
@@ -319,7 +324,7 @@ pub enum A { One(One) }"#, | |||
319 | } | 324 | } |
320 | 325 | ||
321 | pub enum MyEnum { | 326 | pub enum MyEnum { |
322 | <|>MyField(u8, u8), | 327 | $0MyField(u8, u8), |
323 | } | 328 | } |
324 | } | 329 | } |
325 | } | 330 | } |
@@ -361,7 +366,7 @@ fn another_fn() { | |||
361 | extract_struct_from_enum_variant, | 366 | extract_struct_from_enum_variant, |
362 | r#" | 367 | r#" |
363 | enum E { | 368 | enum E { |
364 | <|>V { i: i32, j: i32 } | 369 | $0V { i: i32, j: i32 } |
365 | } | 370 | } |
366 | 371 | ||
367 | fn f() { | 372 | fn f() { |
@@ -389,7 +394,7 @@ fn f() { | |||
389 | r#" | 394 | r#" |
390 | //- /main.rs | 395 | //- /main.rs |
391 | enum E { | 396 | enum E { |
392 | <|>V(i32, i32) | 397 | $0V(i32, i32) |
393 | } | 398 | } |
394 | mod foo; | 399 | mod foo; |
395 | 400 | ||
@@ -424,7 +429,7 @@ fn f() { | |||
424 | r#" | 429 | r#" |
425 | //- /main.rs | 430 | //- /main.rs |
426 | enum E { | 431 | enum E { |
427 | <|>V { i: i32, j: i32 } | 432 | $0V { i: i32, j: i32 } |
428 | } | 433 | } |
429 | mod foo; | 434 | mod foo; |
430 | 435 | ||
@@ -457,7 +462,7 @@ fn f() { | |||
457 | check_assist( | 462 | check_assist( |
458 | extract_struct_from_enum_variant, | 463 | extract_struct_from_enum_variant, |
459 | r#" | 464 | r#" |
460 | enum A { <|>One { a: u32, b: u32 } } | 465 | enum A { $0One { a: u32, b: u32 } } |
461 | 466 | ||
462 | struct B(A); | 467 | struct B(A); |
463 | 468 | ||
@@ -487,29 +492,29 @@ fn foo() { | |||
487 | 492 | ||
488 | #[test] | 493 | #[test] |
489 | fn test_extract_enum_not_applicable_for_element_with_no_fields() { | 494 | fn test_extract_enum_not_applicable_for_element_with_no_fields() { |
490 | check_not_applicable("enum A { <|>One }"); | 495 | check_not_applicable("enum A { $0One }"); |
491 | } | 496 | } |
492 | 497 | ||
493 | #[test] | 498 | #[test] |
494 | fn test_extract_enum_not_applicable_if_struct_exists() { | 499 | fn test_extract_enum_not_applicable_if_struct_exists() { |
495 | check_not_applicable( | 500 | check_not_applicable( |
496 | r#"struct One; | 501 | r#"struct One; |
497 | enum A { <|>One(u8, u32) }"#, | 502 | enum A { $0One(u8, u32) }"#, |
498 | ); | 503 | ); |
499 | } | 504 | } |
500 | 505 | ||
501 | #[test] | 506 | #[test] |
502 | fn test_extract_not_applicable_one_field() { | 507 | fn test_extract_not_applicable_one_field() { |
503 | check_not_applicable(r"enum A { <|>One(u32) }"); | 508 | check_not_applicable(r"enum A { $0One(u32) }"); |
504 | } | 509 | } |
505 | 510 | ||
506 | #[test] | 511 | #[test] |
507 | fn test_extract_not_applicable_no_field_tuple() { | 512 | fn test_extract_not_applicable_no_field_tuple() { |
508 | check_not_applicable(r"enum A { <|>None() }"); | 513 | check_not_applicable(r"enum A { $0None() }"); |
509 | } | 514 | } |
510 | 515 | ||
511 | #[test] | 516 | #[test] |
512 | fn test_extract_not_applicable_no_field_named() { | 517 | fn test_extract_not_applicable_no_field_named() { |
513 | check_not_applicable(r"enum A { <|>None {} }"); | 518 | check_not_applicable(r"enum A { $0None {} }"); |
514 | } | 519 | } |
515 | } | 520 | } |
diff --git a/crates/assists/src/handlers/extract_variable.rs b/crates/assists/src/handlers/extract_variable.rs index 291809205..98f3dc6ca 100644 --- a/crates/assists/src/handlers/extract_variable.rs +++ b/crates/assists/src/handlers/extract_variable.rs | |||
@@ -16,7 +16,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
16 | // | 16 | // |
17 | // ``` | 17 | // ``` |
18 | // fn main() { | 18 | // fn main() { |
19 | // <|>(1 + 2)<|> * 4; | 19 | // $0(1 + 2)$0 * 4; |
20 | // } | 20 | // } |
21 | // ``` | 21 | // ``` |
22 | // -> | 22 | // -> |
@@ -187,7 +187,7 @@ mod tests { | |||
187 | extract_variable, | 187 | extract_variable, |
188 | r#" | 188 | r#" |
189 | fn foo() { | 189 | fn foo() { |
190 | foo(<|>1 + 1<|>); | 190 | foo($01 + 1$0); |
191 | }"#, | 191 | }"#, |
192 | r#" | 192 | r#" |
193 | fn foo() { | 193 | fn foo() { |
@@ -200,7 +200,7 @@ fn foo() { | |||
200 | #[test] | 200 | #[test] |
201 | fn extract_var_in_comment_is_not_applicable() { | 201 | fn extract_var_in_comment_is_not_applicable() { |
202 | mark::check!(extract_var_in_comment_is_not_applicable); | 202 | mark::check!(extract_var_in_comment_is_not_applicable); |
203 | check_assist_not_applicable(extract_variable, "fn main() { 1 + /* <|>comment<|> */ 1; }"); | 203 | check_assist_not_applicable(extract_variable, "fn main() { 1 + /* $0comment$0 */ 1; }"); |
204 | } | 204 | } |
205 | 205 | ||
206 | #[test] | 206 | #[test] |
@@ -210,7 +210,7 @@ fn foo() { | |||
210 | extract_variable, | 210 | extract_variable, |
211 | r#" | 211 | r#" |
212 | fn foo() { | 212 | fn foo() { |
213 | <|>1 + 1<|>; | 213 | $01 + 1$0; |
214 | }"#, | 214 | }"#, |
215 | r#" | 215 | r#" |
216 | fn foo() { | 216 | fn foo() { |
@@ -221,7 +221,7 @@ fn foo() { | |||
221 | extract_variable, | 221 | extract_variable, |
222 | " | 222 | " |
223 | fn foo() { | 223 | fn foo() { |
224 | <|>{ let x = 0; x }<|> | 224 | $0{ let x = 0; x }$0 |
225 | something_else(); | 225 | something_else(); |
226 | }", | 226 | }", |
227 | " | 227 | " |
@@ -238,7 +238,7 @@ fn foo() { | |||
238 | extract_variable, | 238 | extract_variable, |
239 | " | 239 | " |
240 | fn foo() { | 240 | fn foo() { |
241 | <|>1<|> + 1; | 241 | $01$0 + 1; |
242 | }", | 242 | }", |
243 | " | 243 | " |
244 | fn foo() { | 244 | fn foo() { |
@@ -255,7 +255,7 @@ fn foo() { | |||
255 | extract_variable, | 255 | extract_variable, |
256 | r#" | 256 | r#" |
257 | fn foo() { | 257 | fn foo() { |
258 | bar(<|>1 + 1<|>) | 258 | bar($01 + 1$0) |
259 | } | 259 | } |
260 | "#, | 260 | "#, |
261 | r#" | 261 | r#" |
@@ -269,7 +269,7 @@ fn foo() { | |||
269 | extract_variable, | 269 | extract_variable, |
270 | r#" | 270 | r#" |
271 | fn foo() { | 271 | fn foo() { |
272 | <|>bar(1 + 1)<|> | 272 | $0bar(1 + 1)$0 |
273 | } | 273 | } |
274 | "#, | 274 | "#, |
275 | r#" | 275 | r#" |
@@ -289,7 +289,7 @@ fn foo() { | |||
289 | fn main() { | 289 | fn main() { |
290 | let x = true; | 290 | let x = true; |
291 | let tuple = match x { | 291 | let tuple = match x { |
292 | true => (<|>2 + 2<|>, true) | 292 | true => ($02 + 2$0, true) |
293 | _ => (0, false) | 293 | _ => (0, false) |
294 | }; | 294 | }; |
295 | } | 295 | } |
@@ -316,7 +316,7 @@ fn main() { | |||
316 | let tuple = match x { | 316 | let tuple = match x { |
317 | true => { | 317 | true => { |
318 | let y = 1; | 318 | let y = 1; |
319 | (<|>2 + y<|>, true) | 319 | ($02 + y$0, true) |
320 | } | 320 | } |
321 | _ => (0, false) | 321 | _ => (0, false) |
322 | }; | 322 | }; |
@@ -344,7 +344,7 @@ fn main() { | |||
344 | extract_variable, | 344 | extract_variable, |
345 | " | 345 | " |
346 | fn main() { | 346 | fn main() { |
347 | let lambda = |x: u32| <|>x * 2<|>; | 347 | let lambda = |x: u32| $0x * 2$0; |
348 | } | 348 | } |
349 | ", | 349 | ", |
350 | " | 350 | " |
@@ -361,7 +361,7 @@ fn main() { | |||
361 | extract_variable, | 361 | extract_variable, |
362 | " | 362 | " |
363 | fn main() { | 363 | fn main() { |
364 | let lambda = |x: u32| { <|>x * 2<|> }; | 364 | let lambda = |x: u32| { $0x * 2$0 }; |
365 | } | 365 | } |
366 | ", | 366 | ", |
367 | " | 367 | " |
@@ -378,7 +378,7 @@ fn main() { | |||
378 | extract_variable, | 378 | extract_variable, |
379 | " | 379 | " |
380 | fn main() { | 380 | fn main() { |
381 | let o = <|>Some(true)<|>; | 381 | let o = $0Some(true)$0; |
382 | } | 382 | } |
383 | ", | 383 | ", |
384 | " | 384 | " |
@@ -396,7 +396,7 @@ fn main() { | |||
396 | extract_variable, | 396 | extract_variable, |
397 | " | 397 | " |
398 | fn main() { | 398 | fn main() { |
399 | let v = <|>bar.foo()<|>; | 399 | let v = $0bar.foo()$0; |
400 | } | 400 | } |
401 | ", | 401 | ", |
402 | " | 402 | " |
@@ -414,7 +414,7 @@ fn main() { | |||
414 | extract_variable, | 414 | extract_variable, |
415 | " | 415 | " |
416 | fn foo() -> u32 { | 416 | fn foo() -> u32 { |
417 | <|>return 2 + 2<|>; | 417 | $0return 2 + 2$0; |
418 | } | 418 | } |
419 | ", | 419 | ", |
420 | " | 420 | " |
@@ -434,7 +434,7 @@ fn foo() -> u32 { | |||
434 | fn foo() -> u32 { | 434 | fn foo() -> u32 { |
435 | 435 | ||
436 | 436 | ||
437 | <|>return 2 + 2<|>; | 437 | $0return 2 + 2$0; |
438 | } | 438 | } |
439 | ", | 439 | ", |
440 | " | 440 | " |
@@ -452,7 +452,7 @@ fn foo() -> u32 { | |||
452 | " | 452 | " |
453 | fn foo() -> u32 { | 453 | fn foo() -> u32 { |
454 | 454 | ||
455 | <|>return 2 + 2<|>; | 455 | $0return 2 + 2$0; |
456 | } | 456 | } |
457 | ", | 457 | ", |
458 | " | 458 | " |
@@ -473,7 +473,7 @@ fn foo() -> u32 { | |||
473 | // bar | 473 | // bar |
474 | 474 | ||
475 | 475 | ||
476 | <|>return 2 + 2<|>; | 476 | $0return 2 + 2$0; |
477 | } | 477 | } |
478 | ", | 478 | ", |
479 | " | 479 | " |
@@ -497,7 +497,7 @@ fn foo() -> u32 { | |||
497 | " | 497 | " |
498 | fn main() { | 498 | fn main() { |
499 | let result = loop { | 499 | let result = loop { |
500 | <|>break 2 + 2<|>; | 500 | $0break 2 + 2$0; |
501 | }; | 501 | }; |
502 | } | 502 | } |
503 | ", | 503 | ", |
@@ -518,7 +518,7 @@ fn main() { | |||
518 | extract_variable, | 518 | extract_variable, |
519 | " | 519 | " |
520 | fn main() { | 520 | fn main() { |
521 | let v = <|>0f32 as u32<|>; | 521 | let v = $00f32 as u32$0; |
522 | } | 522 | } |
523 | ", | 523 | ", |
524 | " | 524 | " |
@@ -540,7 +540,7 @@ struct S { | |||
540 | } | 540 | } |
541 | 541 | ||
542 | fn main() { | 542 | fn main() { |
543 | S { foo: <|>1 + 1<|> } | 543 | S { foo: $01 + 1$0 } |
544 | } | 544 | } |
545 | "#, | 545 | "#, |
546 | r#" | 546 | r#" |
@@ -558,18 +558,18 @@ fn main() { | |||
558 | 558 | ||
559 | #[test] | 559 | #[test] |
560 | fn test_extract_var_for_return_not_applicable() { | 560 | fn test_extract_var_for_return_not_applicable() { |
561 | check_assist_not_applicable(extract_variable, "fn foo() { <|>return<|>; } "); | 561 | check_assist_not_applicable(extract_variable, "fn foo() { $0return$0; } "); |
562 | } | 562 | } |
563 | 563 | ||
564 | #[test] | 564 | #[test] |
565 | fn test_extract_var_for_break_not_applicable() { | 565 | fn test_extract_var_for_break_not_applicable() { |
566 | check_assist_not_applicable(extract_variable, "fn main() { loop { <|>break<|>; }; }"); | 566 | check_assist_not_applicable(extract_variable, "fn main() { loop { $0break$0; }; }"); |
567 | } | 567 | } |
568 | 568 | ||
569 | // FIXME: This is not quite correct, but good enough(tm) for the sorting heuristic | 569 | // FIXME: This is not quite correct, but good enough(tm) for the sorting heuristic |
570 | #[test] | 570 | #[test] |
571 | fn extract_var_target() { | 571 | fn extract_var_target() { |
572 | check_assist_target(extract_variable, "fn foo() -> u32 { <|>return 2 + 2<|>; }", "2 + 2"); | 572 | check_assist_target(extract_variable, "fn foo() -> u32 { $0return 2 + 2$0; }", "2 + 2"); |
573 | 573 | ||
574 | check_assist_target( | 574 | check_assist_target( |
575 | extract_variable, | 575 | extract_variable, |
@@ -577,7 +577,7 @@ fn main() { | |||
577 | fn main() { | 577 | fn main() { |
578 | let x = true; | 578 | let x = true; |
579 | let tuple = match x { | 579 | let tuple = match x { |
580 | true => (<|>2 + 2<|>, true) | 580 | true => ($02 + 2$0, true) |
581 | _ => (0, false) | 581 | _ => (0, false) |
582 | }; | 582 | }; |
583 | } | 583 | } |
diff --git a/crates/assists/src/handlers/fill_match_arms.rs b/crates/assists/src/handlers/fill_match_arms.rs index f9a62b9fa..da47187e4 100644 --- a/crates/assists/src/handlers/fill_match_arms.rs +++ b/crates/assists/src/handlers/fill_match_arms.rs | |||
@@ -21,7 +21,7 @@ use crate::{ | |||
21 | // | 21 | // |
22 | // fn handle(action: Action) { | 22 | // fn handle(action: Action) { |
23 | // match action { | 23 | // match action { |
24 | // <|> | 24 | // $0 |
25 | // } | 25 | // } |
26 | // } | 26 | // } |
27 | // ``` | 27 | // ``` |
@@ -231,7 +231,7 @@ mod tests { | |||
231 | Cs(i32, Option<i32>), | 231 | Cs(i32, Option<i32>), |
232 | } | 232 | } |
233 | fn main() { | 233 | fn main() { |
234 | match A::As<|> { | 234 | match A::As$0 { |
235 | A::As, | 235 | A::As, |
236 | A::Bs{x,y:Some(_)} => {} | 236 | A::Bs{x,y:Some(_)} => {} |
237 | A::Cs(_, Some(_)) => {} | 237 | A::Cs(_, Some(_)) => {} |
@@ -249,7 +249,7 @@ mod tests { | |||
249 | fill_match_arms, | 249 | fill_match_arms, |
250 | r#" | 250 | r#" |
251 | fn main() { | 251 | fn main() { |
252 | match (0, false)<|> { | 252 | match (0, false)$0 { |
253 | } | 253 | } |
254 | } | 254 | } |
255 | "#, | 255 | "#, |
@@ -267,7 +267,7 @@ mod tests { | |||
267 | Cs(i32, Option<i32>), | 267 | Cs(i32, Option<i32>), |
268 | } | 268 | } |
269 | fn main() { | 269 | fn main() { |
270 | match A::As<|> { | 270 | match A::As$0 { |
271 | A::Bs { x, y: Some(_) } => {} | 271 | A::Bs { x, y: Some(_) } => {} |
272 | A::Cs(_, Some(_)) => {} | 272 | A::Cs(_, Some(_)) => {} |
273 | } | 273 | } |
@@ -297,7 +297,7 @@ mod tests { | |||
297 | r#" | 297 | r#" |
298 | enum A { As, Bs, Cs(Option<i32>) } | 298 | enum A { As, Bs, Cs(Option<i32>) } |
299 | fn main() { | 299 | fn main() { |
300 | match A::As<|> { | 300 | match A::As$0 { |
301 | A::Cs(_) | A::Bs => {} | 301 | A::Cs(_) | A::Bs => {} |
302 | } | 302 | } |
303 | } | 303 | } |
@@ -322,7 +322,7 @@ fn main() { | |||
322 | enum A { As, Bs, Cs, Ds(String), Es(B) } | 322 | enum A { As, Bs, Cs, Ds(String), Es(B) } |
323 | enum B { Xs, Ys } | 323 | enum B { Xs, Ys } |
324 | fn main() { | 324 | fn main() { |
325 | match A::As<|> { | 325 | match A::As$0 { |
326 | A::Bs if 0 < 1 => {} | 326 | A::Bs if 0 < 1 => {} |
327 | A::Ds(_value) => { let x = 1; } | 327 | A::Ds(_value) => { let x = 1; } |
328 | A::Es(B::Xs) => (), | 328 | A::Es(B::Xs) => (), |
@@ -352,7 +352,7 @@ fn main() { | |||
352 | r#" | 352 | r#" |
353 | enum A { As, Bs, Cs(Option<i32>) } | 353 | enum A { As, Bs, Cs(Option<i32>) } |
354 | fn main() { | 354 | fn main() { |
355 | match A::As<|> { | 355 | match A::As$0 { |
356 | A::As(_) => {} | 356 | A::As(_) => {} |
357 | a @ A::Bs(_) => {} | 357 | a @ A::Bs(_) => {} |
358 | } | 358 | } |
@@ -380,7 +380,7 @@ enum A { As, Bs, Cs(String), Ds(String, String), Es { x: usize, y: usize } } | |||
380 | 380 | ||
381 | fn main() { | 381 | fn main() { |
382 | let a = A::As; | 382 | let a = A::As; |
383 | match a<|> {} | 383 | match a$0 {} |
384 | } | 384 | } |
385 | "#, | 385 | "#, |
386 | r#" | 386 | r#" |
@@ -411,7 +411,7 @@ fn main() { | |||
411 | fn main() { | 411 | fn main() { |
412 | let a = A::One; | 412 | let a = A::One; |
413 | let b = B::One; | 413 | let b = B::One; |
414 | match (a<|>, b) {} | 414 | match (a$0, b) {} |
415 | } | 415 | } |
416 | "#, | 416 | "#, |
417 | r#" | 417 | r#" |
@@ -443,7 +443,7 @@ fn main() { | |||
443 | fn main() { | 443 | fn main() { |
444 | let a = A::One; | 444 | let a = A::One; |
445 | let b = B::One; | 445 | let b = B::One; |
446 | match (&a<|>, &b) {} | 446 | match (&a$0, &b) {} |
447 | } | 447 | } |
448 | "#, | 448 | "#, |
449 | r#" | 449 | r#" |
@@ -475,7 +475,7 @@ fn main() { | |||
475 | fn main() { | 475 | fn main() { |
476 | let a = A::One; | 476 | let a = A::One; |
477 | let b = B::One; | 477 | let b = B::One; |
478 | match (a<|>, b) { | 478 | match (a$0, b) { |
479 | (A::Two, B::One) => {} | 479 | (A::Two, B::One) => {} |
480 | } | 480 | } |
481 | } | 481 | } |
@@ -494,7 +494,7 @@ fn main() { | |||
494 | fn main() { | 494 | fn main() { |
495 | let a = A::One; | 495 | let a = A::One; |
496 | let b = B::One; | 496 | let b = B::One; |
497 | match (a<|>, b) { | 497 | match (a$0, b) { |
498 | (A::Two, B::One) => {} | 498 | (A::Two, B::One) => {} |
499 | (A::One, B::One) => {} | 499 | (A::One, B::One) => {} |
500 | (A::One, B::Two) => {} | 500 | (A::One, B::Two) => {} |
@@ -517,7 +517,7 @@ fn main() { | |||
517 | 517 | ||
518 | fn main() { | 518 | fn main() { |
519 | let a = A::One; | 519 | let a = A::One; |
520 | match (a<|>, ) { | 520 | match (a$0, ) { |
521 | } | 521 | } |
522 | } | 522 | } |
523 | "#, | 523 | "#, |
@@ -532,7 +532,7 @@ fn main() { | |||
532 | enum A { As } | 532 | enum A { As } |
533 | 533 | ||
534 | fn foo(a: &A) { | 534 | fn foo(a: &A) { |
535 | match a<|> { | 535 | match a$0 { |
536 | } | 536 | } |
537 | } | 537 | } |
538 | "#, | 538 | "#, |
@@ -555,7 +555,7 @@ fn main() { | |||
555 | } | 555 | } |
556 | 556 | ||
557 | fn foo(a: &mut A) { | 557 | fn foo(a: &mut A) { |
558 | match a<|> { | 558 | match a$0 { |
559 | } | 559 | } |
560 | } | 560 | } |
561 | "#, | 561 | "#, |
@@ -581,7 +581,7 @@ fn main() { | |||
581 | enum E { X, Y } | 581 | enum E { X, Y } |
582 | 582 | ||
583 | fn main() { | 583 | fn main() { |
584 | match E::X<|> {} | 584 | match E::X$0 {} |
585 | } | 585 | } |
586 | "#, | 586 | "#, |
587 | "match E::X {}", | 587 | "match E::X {}", |
@@ -597,7 +597,7 @@ fn main() { | |||
597 | 597 | ||
598 | fn main() { | 598 | fn main() { |
599 | match E::X { | 599 | match E::X { |
600 | <|>_ => {} | 600 | $0_ => {} |
601 | } | 601 | } |
602 | } | 602 | } |
603 | "#, | 603 | "#, |
@@ -624,7 +624,7 @@ fn main() { | |||
624 | 624 | ||
625 | fn main() { | 625 | fn main() { |
626 | match X { | 626 | match X { |
627 | <|> | 627 | $0 |
628 | } | 628 | } |
629 | } | 629 | } |
630 | "#, | 630 | "#, |
@@ -650,7 +650,7 @@ fn main() { | |||
650 | enum A { One, Two } | 650 | enum A { One, Two } |
651 | fn foo(a: A) { | 651 | fn foo(a: A) { |
652 | match a { | 652 | match a { |
653 | // foo bar baz<|> | 653 | // foo bar baz$0 |
654 | A::One => {} | 654 | A::One => {} |
655 | // This is where the rest should be | 655 | // This is where the rest should be |
656 | } | 656 | } |
@@ -678,7 +678,7 @@ fn main() { | |||
678 | enum A { One, Two } | 678 | enum A { One, Two } |
679 | fn foo(a: A) { | 679 | fn foo(a: A) { |
680 | match a { | 680 | match a { |
681 | // foo bar baz<|> | 681 | // foo bar baz$0 |
682 | } | 682 | } |
683 | } | 683 | } |
684 | "#, | 684 | "#, |
@@ -702,7 +702,7 @@ fn main() { | |||
702 | r#" | 702 | r#" |
703 | enum A { One, Two, } | 703 | enum A { One, Two, } |
704 | fn foo(a: A) { | 704 | fn foo(a: A) { |
705 | match a<|> { | 705 | match a$0 { |
706 | _ => (), | 706 | _ => (), |
707 | } | 707 | } |
708 | } | 708 | } |
@@ -724,7 +724,7 @@ fn main() { | |||
724 | mark::check!(option_order); | 724 | mark::check!(option_order); |
725 | let before = r#" | 725 | let before = r#" |
726 | fn foo(opt: Option<i32>) { | 726 | fn foo(opt: Option<i32>) { |
727 | match opt<|> { | 727 | match opt$0 { |
728 | } | 728 | } |
729 | } | 729 | } |
730 | "#; | 730 | "#; |
diff --git a/crates/assists/src/handlers/fix_visibility.rs b/crates/assists/src/handlers/fix_visibility.rs index de1e8f0bf..6c7824e55 100644 --- a/crates/assists/src/handlers/fix_visibility.rs +++ b/crates/assists/src/handlers/fix_visibility.rs | |||
@@ -18,7 +18,7 @@ use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists}; | |||
18 | // fn frobnicate() {} | 18 | // fn frobnicate() {} |
19 | // } | 19 | // } |
20 | // fn main() { | 20 | // fn main() { |
21 | // m::frobnicate<|>() {} | 21 | // m::frobnicate$0() {} |
22 | // } | 22 | // } |
23 | // ``` | 23 | // ``` |
24 | // -> | 24 | // -> |
@@ -97,7 +97,6 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> | |||
97 | let parent_name = parent.name(ctx.db()); | 97 | let parent_name = parent.name(ctx.db()); |
98 | let target_module = parent.module(ctx.db()); | 98 | let target_module = parent.module(ctx.db()); |
99 | 99 | ||
100 | #[allow(deprecated)] | ||
101 | let in_file_source = record_field_def.source(ctx.db())?; | 100 | let in_file_source = record_field_def.source(ctx.db())?; |
102 | let (offset, current_visibility, target) = match in_file_source.value { | 101 | let (offset, current_visibility, target) = match in_file_source.value { |
103 | hir::FieldSource::Named(it) => { | 102 | hir::FieldSource::Named(it) => { |
@@ -219,14 +218,14 @@ mod tests { | |||
219 | check_assist( | 218 | check_assist( |
220 | fix_visibility, | 219 | fix_visibility, |
221 | r"mod foo { fn foo() {} } | 220 | r"mod foo { fn foo() {} } |
222 | fn main() { foo::foo<|>() } ", | 221 | fn main() { foo::foo$0() } ", |
223 | r"mod foo { $0pub(crate) fn foo() {} } | 222 | r"mod foo { $0pub(crate) fn foo() {} } |
224 | fn main() { foo::foo() } ", | 223 | fn main() { foo::foo() } ", |
225 | ); | 224 | ); |
226 | check_assist_not_applicable( | 225 | check_assist_not_applicable( |
227 | fix_visibility, | 226 | fix_visibility, |
228 | r"mod foo { pub fn foo() {} } | 227 | r"mod foo { pub fn foo() {} } |
229 | fn main() { foo::foo<|>() } ", | 228 | fn main() { foo::foo$0() } ", |
230 | ) | 229 | ) |
231 | } | 230 | } |
232 | 231 | ||
@@ -235,38 +234,38 @@ mod tests { | |||
235 | check_assist( | 234 | check_assist( |
236 | fix_visibility, | 235 | fix_visibility, |
237 | r"mod foo { struct Foo; } | 236 | r"mod foo { struct Foo; } |
238 | fn main() { foo::Foo<|> } ", | 237 | fn main() { foo::Foo$0 } ", |
239 | r"mod foo { $0pub(crate) struct Foo; } | 238 | r"mod foo { $0pub(crate) struct Foo; } |
240 | fn main() { foo::Foo } ", | 239 | fn main() { foo::Foo } ", |
241 | ); | 240 | ); |
242 | check_assist_not_applicable( | 241 | check_assist_not_applicable( |
243 | fix_visibility, | 242 | fix_visibility, |
244 | r"mod foo { pub struct Foo; } | 243 | r"mod foo { pub struct Foo; } |
245 | fn main() { foo::Foo<|> } ", | 244 | fn main() { foo::Foo$0 } ", |
246 | ); | 245 | ); |
247 | check_assist( | 246 | check_assist( |
248 | fix_visibility, | 247 | fix_visibility, |
249 | r"mod foo { enum Foo; } | 248 | r"mod foo { enum Foo; } |
250 | fn main() { foo::Foo<|> } ", | 249 | fn main() { foo::Foo$0 } ", |
251 | r"mod foo { $0pub(crate) enum Foo; } | 250 | r"mod foo { $0pub(crate) enum Foo; } |
252 | fn main() { foo::Foo } ", | 251 | fn main() { foo::Foo } ", |
253 | ); | 252 | ); |
254 | check_assist_not_applicable( | 253 | check_assist_not_applicable( |
255 | fix_visibility, | 254 | fix_visibility, |
256 | r"mod foo { pub enum Foo; } | 255 | r"mod foo { pub enum Foo; } |
257 | fn main() { foo::Foo<|> } ", | 256 | fn main() { foo::Foo$0 } ", |
258 | ); | 257 | ); |
259 | check_assist( | 258 | check_assist( |
260 | fix_visibility, | 259 | fix_visibility, |
261 | r"mod foo { union Foo; } | 260 | r"mod foo { union Foo; } |
262 | fn main() { foo::Foo<|> } ", | 261 | fn main() { foo::Foo$0 } ", |
263 | r"mod foo { $0pub(crate) union Foo; } | 262 | r"mod foo { $0pub(crate) union Foo; } |
264 | fn main() { foo::Foo } ", | 263 | fn main() { foo::Foo } ", |
265 | ); | 264 | ); |
266 | check_assist_not_applicable( | 265 | check_assist_not_applicable( |
267 | fix_visibility, | 266 | fix_visibility, |
268 | r"mod foo { pub union Foo; } | 267 | r"mod foo { pub union Foo; } |
269 | fn main() { foo::Foo<|> } ", | 268 | fn main() { foo::Foo$0 } ", |
270 | ); | 269 | ); |
271 | } | 270 | } |
272 | 271 | ||
@@ -277,7 +276,7 @@ mod tests { | |||
277 | r" | 276 | r" |
278 | //- /main.rs | 277 | //- /main.rs |
279 | mod foo; | 278 | mod foo; |
280 | fn main() { foo::Foo<|> } | 279 | fn main() { foo::Foo$0 } |
281 | 280 | ||
282 | //- /foo.rs | 281 | //- /foo.rs |
283 | struct Foo; | 282 | struct Foo; |
@@ -292,7 +291,7 @@ struct Foo; | |||
292 | check_assist( | 291 | check_assist( |
293 | fix_visibility, | 292 | fix_visibility, |
294 | r"mod foo { pub struct Foo { bar: (), } } | 293 | r"mod foo { pub struct Foo { bar: (), } } |
295 | fn main() { foo::Foo { <|>bar: () }; } ", | 294 | fn main() { foo::Foo { $0bar: () }; } ", |
296 | r"mod foo { pub struct Foo { $0pub(crate) bar: (), } } | 295 | r"mod foo { pub struct Foo { $0pub(crate) bar: (), } } |
297 | fn main() { foo::Foo { bar: () }; } ", | 296 | fn main() { foo::Foo { bar: () }; } ", |
298 | ); | 297 | ); |
@@ -301,7 +300,7 @@ struct Foo; | |||
301 | r" | 300 | r" |
302 | //- /lib.rs | 301 | //- /lib.rs |
303 | mod foo; | 302 | mod foo; |
304 | fn main() { foo::Foo { <|>bar: () }; } | 303 | fn main() { foo::Foo { $0bar: () }; } |
305 | //- /foo.rs | 304 | //- /foo.rs |
306 | pub struct Foo { bar: () } | 305 | pub struct Foo { bar: () } |
307 | ", | 306 | ", |
@@ -311,14 +310,14 @@ pub struct Foo { bar: () } | |||
311 | check_assist_not_applicable( | 310 | check_assist_not_applicable( |
312 | fix_visibility, | 311 | fix_visibility, |
313 | r"mod foo { pub struct Foo { pub bar: (), } } | 312 | r"mod foo { pub struct Foo { pub bar: (), } } |
314 | fn main() { foo::Foo { <|>bar: () }; } ", | 313 | fn main() { foo::Foo { $0bar: () }; } ", |
315 | ); | 314 | ); |
316 | check_assist_not_applicable( | 315 | check_assist_not_applicable( |
317 | fix_visibility, | 316 | fix_visibility, |
318 | r" | 317 | r" |
319 | //- /lib.rs | 318 | //- /lib.rs |
320 | mod foo; | 319 | mod foo; |
321 | fn main() { foo::Foo { <|>bar: () }; } | 320 | fn main() { foo::Foo { $0bar: () }; } |
322 | //- /foo.rs | 321 | //- /foo.rs |
323 | pub struct Foo { pub bar: () } | 322 | pub struct Foo { pub bar: () } |
324 | ", | 323 | ", |
@@ -332,14 +331,14 @@ pub struct Foo { pub bar: () } | |||
332 | check_assist_not_applicable( | 331 | check_assist_not_applicable( |
333 | fix_visibility, | 332 | fix_visibility, |
334 | r"mod foo { pub enum Foo { Bar { bar: () } } } | 333 | r"mod foo { pub enum Foo { Bar { bar: () } } } |
335 | fn main() { foo::Foo::Bar { <|>bar: () }; } ", | 334 | fn main() { foo::Foo::Bar { $0bar: () }; } ", |
336 | ); | 335 | ); |
337 | check_assist_not_applicable( | 336 | check_assist_not_applicable( |
338 | fix_visibility, | 337 | fix_visibility, |
339 | r" | 338 | r" |
340 | //- /lib.rs | 339 | //- /lib.rs |
341 | mod foo; | 340 | mod foo; |
342 | fn main() { foo::Foo::Bar { <|>bar: () }; } | 341 | fn main() { foo::Foo::Bar { $0bar: () }; } |
343 | //- /foo.rs | 342 | //- /foo.rs |
344 | pub enum Foo { Bar { bar: () } } | 343 | pub enum Foo { Bar { bar: () } } |
345 | ", | 344 | ", |
@@ -347,14 +346,14 @@ pub enum Foo { Bar { bar: () } } | |||
347 | check_assist_not_applicable( | 346 | check_assist_not_applicable( |
348 | fix_visibility, | 347 | fix_visibility, |
349 | r"mod foo { pub struct Foo { pub bar: (), } } | 348 | r"mod foo { pub struct Foo { pub bar: (), } } |
350 | fn main() { foo::Foo { <|>bar: () }; } ", | 349 | fn main() { foo::Foo { $0bar: () }; } ", |
351 | ); | 350 | ); |
352 | check_assist_not_applicable( | 351 | check_assist_not_applicable( |
353 | fix_visibility, | 352 | fix_visibility, |
354 | r" | 353 | r" |
355 | //- /lib.rs | 354 | //- /lib.rs |
356 | mod foo; | 355 | mod foo; |
357 | fn main() { foo::Foo { <|>bar: () }; } | 356 | fn main() { foo::Foo { $0bar: () }; } |
358 | //- /foo.rs | 357 | //- /foo.rs |
359 | pub struct Foo { pub bar: () } | 358 | pub struct Foo { pub bar: () } |
360 | ", | 359 | ", |
@@ -368,7 +367,7 @@ pub struct Foo { pub bar: () } | |||
368 | check_assist( | 367 | check_assist( |
369 | fix_visibility, | 368 | fix_visibility, |
370 | r"mod foo { pub union Foo { bar: (), } } | 369 | r"mod foo { pub union Foo { bar: (), } } |
371 | fn main() { foo::Foo { <|>bar: () }; } ", | 370 | fn main() { foo::Foo { $0bar: () }; } ", |
372 | r"mod foo { pub union Foo { $0pub(crate) bar: (), } } | 371 | r"mod foo { pub union Foo { $0pub(crate) bar: (), } } |
373 | fn main() { foo::Foo { bar: () }; } ", | 372 | fn main() { foo::Foo { bar: () }; } ", |
374 | ); | 373 | ); |
@@ -377,7 +376,7 @@ pub struct Foo { pub bar: () } | |||
377 | r" | 376 | r" |
378 | //- /lib.rs | 377 | //- /lib.rs |
379 | mod foo; | 378 | mod foo; |
380 | fn main() { foo::Foo { <|>bar: () }; } | 379 | fn main() { foo::Foo { $0bar: () }; } |
381 | //- /foo.rs | 380 | //- /foo.rs |
382 | pub union Foo { bar: () } | 381 | pub union Foo { bar: () } |
383 | ", | 382 | ", |
@@ -387,14 +386,14 @@ pub union Foo { bar: () } | |||
387 | check_assist_not_applicable( | 386 | check_assist_not_applicable( |
388 | fix_visibility, | 387 | fix_visibility, |
389 | r"mod foo { pub union Foo { pub bar: (), } } | 388 | r"mod foo { pub union Foo { pub bar: (), } } |
390 | fn main() { foo::Foo { <|>bar: () }; } ", | 389 | fn main() { foo::Foo { $0bar: () }; } ", |
391 | ); | 390 | ); |
392 | check_assist_not_applicable( | 391 | check_assist_not_applicable( |
393 | fix_visibility, | 392 | fix_visibility, |
394 | r" | 393 | r" |
395 | //- /lib.rs | 394 | //- /lib.rs |
396 | mod foo; | 395 | mod foo; |
397 | fn main() { foo::Foo { <|>bar: () }; } | 396 | fn main() { foo::Foo { $0bar: () }; } |
398 | //- /foo.rs | 397 | //- /foo.rs |
399 | pub union Foo { pub bar: () } | 398 | pub union Foo { pub bar: () } |
400 | ", | 399 | ", |
@@ -406,14 +405,14 @@ pub union Foo { pub bar: () } | |||
406 | check_assist( | 405 | check_assist( |
407 | fix_visibility, | 406 | fix_visibility, |
408 | r"mod foo { const FOO: () = (); } | 407 | r"mod foo { const FOO: () = (); } |
409 | fn main() { foo::FOO<|> } ", | 408 | fn main() { foo::FOO$0 } ", |
410 | r"mod foo { $0pub(crate) const FOO: () = (); } | 409 | r"mod foo { $0pub(crate) const FOO: () = (); } |
411 | fn main() { foo::FOO } ", | 410 | fn main() { foo::FOO } ", |
412 | ); | 411 | ); |
413 | check_assist_not_applicable( | 412 | check_assist_not_applicable( |
414 | fix_visibility, | 413 | fix_visibility, |
415 | r"mod foo { pub const FOO: () = (); } | 414 | r"mod foo { pub const FOO: () = (); } |
416 | fn main() { foo::FOO<|> } ", | 415 | fn main() { foo::FOO$0 } ", |
417 | ); | 416 | ); |
418 | } | 417 | } |
419 | 418 | ||
@@ -422,14 +421,14 @@ pub union Foo { pub bar: () } | |||
422 | check_assist( | 421 | check_assist( |
423 | fix_visibility, | 422 | fix_visibility, |
424 | r"mod foo { static FOO: () = (); } | 423 | r"mod foo { static FOO: () = (); } |
425 | fn main() { foo::FOO<|> } ", | 424 | fn main() { foo::FOO$0 } ", |
426 | r"mod foo { $0pub(crate) static FOO: () = (); } | 425 | r"mod foo { $0pub(crate) static FOO: () = (); } |
427 | fn main() { foo::FOO } ", | 426 | fn main() { foo::FOO } ", |
428 | ); | 427 | ); |
429 | check_assist_not_applicable( | 428 | check_assist_not_applicable( |
430 | fix_visibility, | 429 | fix_visibility, |
431 | r"mod foo { pub static FOO: () = (); } | 430 | r"mod foo { pub static FOO: () = (); } |
432 | fn main() { foo::FOO<|> } ", | 431 | fn main() { foo::FOO$0 } ", |
433 | ); | 432 | ); |
434 | } | 433 | } |
435 | 434 | ||
@@ -438,14 +437,14 @@ pub union Foo { pub bar: () } | |||
438 | check_assist( | 437 | check_assist( |
439 | fix_visibility, | 438 | fix_visibility, |
440 | r"mod foo { trait Foo { fn foo(&self) {} } } | 439 | r"mod foo { trait Foo { fn foo(&self) {} } } |
441 | fn main() { let x: &dyn foo::<|>Foo; } ", | 440 | fn main() { let x: &dyn foo::$0Foo; } ", |
442 | r"mod foo { $0pub(crate) trait Foo { fn foo(&self) {} } } | 441 | r"mod foo { $0pub(crate) trait Foo { fn foo(&self) {} } } |
443 | fn main() { let x: &dyn foo::Foo; } ", | 442 | fn main() { let x: &dyn foo::Foo; } ", |
444 | ); | 443 | ); |
445 | check_assist_not_applicable( | 444 | check_assist_not_applicable( |
446 | fix_visibility, | 445 | fix_visibility, |
447 | r"mod foo { pub trait Foo { fn foo(&self) {} } } | 446 | r"mod foo { pub trait Foo { fn foo(&self) {} } } |
448 | fn main() { let x: &dyn foo::Foo<|>; } ", | 447 | fn main() { let x: &dyn foo::Foo$0; } ", |
449 | ); | 448 | ); |
450 | } | 449 | } |
451 | 450 | ||
@@ -454,14 +453,14 @@ pub union Foo { pub bar: () } | |||
454 | check_assist( | 453 | check_assist( |
455 | fix_visibility, | 454 | fix_visibility, |
456 | r"mod foo { type Foo = (); } | 455 | r"mod foo { type Foo = (); } |
457 | fn main() { let x: foo::Foo<|>; } ", | 456 | fn main() { let x: foo::Foo$0; } ", |
458 | r"mod foo { $0pub(crate) type Foo = (); } | 457 | r"mod foo { $0pub(crate) type Foo = (); } |
459 | fn main() { let x: foo::Foo; } ", | 458 | fn main() { let x: foo::Foo; } ", |
460 | ); | 459 | ); |
461 | check_assist_not_applicable( | 460 | check_assist_not_applicable( |
462 | fix_visibility, | 461 | fix_visibility, |
463 | r"mod foo { pub type Foo = (); } | 462 | r"mod foo { pub type Foo = (); } |
464 | fn main() { let x: foo::Foo<|>; } ", | 463 | fn main() { let x: foo::Foo$0; } ", |
465 | ); | 464 | ); |
466 | } | 465 | } |
467 | 466 | ||
@@ -470,7 +469,7 @@ pub union Foo { pub bar: () } | |||
470 | check_assist( | 469 | check_assist( |
471 | fix_visibility, | 470 | fix_visibility, |
472 | r"mod foo { mod bar { fn bar() {} } } | 471 | r"mod foo { mod bar { fn bar() {} } } |
473 | fn main() { foo::bar<|>::bar(); } ", | 472 | fn main() { foo::bar$0::bar(); } ", |
474 | r"mod foo { $0pub(crate) mod bar { fn bar() {} } } | 473 | r"mod foo { $0pub(crate) mod bar { fn bar() {} } } |
475 | fn main() { foo::bar::bar(); } ", | 474 | fn main() { foo::bar::bar(); } ", |
476 | ); | 475 | ); |
@@ -480,7 +479,7 @@ pub union Foo { pub bar: () } | |||
480 | r" | 479 | r" |
481 | //- /main.rs | 480 | //- /main.rs |
482 | mod foo; | 481 | mod foo; |
483 | fn main() { foo::bar<|>::baz(); } | 482 | fn main() { foo::bar$0::baz(); } |
484 | 483 | ||
485 | //- /foo.rs | 484 | //- /foo.rs |
486 | mod bar { | 485 | mod bar { |
@@ -496,7 +495,7 @@ mod bar { | |||
496 | check_assist_not_applicable( | 495 | check_assist_not_applicable( |
497 | fix_visibility, | 496 | fix_visibility, |
498 | r"mod foo { pub mod bar { pub fn bar() {} } } | 497 | r"mod foo { pub mod bar { pub fn bar() {} } } |
499 | fn main() { foo::bar<|>::bar(); } ", | 498 | fn main() { foo::bar$0::bar(); } ", |
500 | ); | 499 | ); |
501 | } | 500 | } |
502 | 501 | ||
@@ -507,7 +506,7 @@ mod bar { | |||
507 | r" | 506 | r" |
508 | //- /main.rs | 507 | //- /main.rs |
509 | mod foo; | 508 | mod foo; |
510 | fn main() { foo::bar<|>::baz(); } | 509 | fn main() { foo::bar$0::baz(); } |
511 | 510 | ||
512 | //- /foo.rs | 511 | //- /foo.rs |
513 | mod bar; | 512 | mod bar; |
@@ -526,7 +525,7 @@ pub fn baz() {} | |||
526 | r" | 525 | r" |
527 | //- /main.rs | 526 | //- /main.rs |
528 | mod foo; | 527 | mod foo; |
529 | fn main() { foo::bar<|>>::baz(); } | 528 | fn main() { foo::bar$0>::baz(); } |
530 | 529 | ||
531 | //- /foo.rs | 530 | //- /foo.rs |
532 | mod bar { | 531 | mod bar { |
@@ -546,7 +545,7 @@ mod bar { | |||
546 | fix_visibility, | 545 | fix_visibility, |
547 | r" | 546 | r" |
548 | //- /main.rs crate:a deps:foo | 547 | //- /main.rs crate:a deps:foo |
549 | foo::Bar<|> | 548 | foo::Bar$0 |
550 | //- /lib.rs crate:foo | 549 | //- /lib.rs crate:foo |
551 | struct Bar; | 550 | struct Bar; |
552 | ", | 551 | ", |
@@ -561,7 +560,7 @@ struct Bar; | |||
561 | fix_visibility, | 560 | fix_visibility, |
562 | r" | 561 | r" |
563 | //- /main.rs crate:a deps:foo | 562 | //- /main.rs crate:a deps:foo |
564 | foo::Bar<|> | 563 | foo::Bar$0 |
565 | //- /lib.rs crate:foo | 564 | //- /lib.rs crate:foo |
566 | pub(crate) struct Bar; | 565 | pub(crate) struct Bar; |
567 | ", | 566 | ", |
@@ -573,7 +572,7 @@ pub(crate) struct Bar; | |||
573 | r" | 572 | r" |
574 | //- /main.rs crate:a deps:foo | 573 | //- /main.rs crate:a deps:foo |
575 | fn main() { | 574 | fn main() { |
576 | foo::Foo { <|>bar: () }; | 575 | foo::Foo { $0bar: () }; |
577 | } | 576 | } |
578 | //- /lib.rs crate:foo | 577 | //- /lib.rs crate:foo |
579 | pub struct Foo { pub(crate) bar: () } | 578 | pub struct Foo { pub(crate) bar: () } |
@@ -594,7 +593,7 @@ pub struct Foo { pub(crate) bar: () } | |||
594 | use bar::Baz; | 593 | use bar::Baz; |
595 | mod bar { pub(super) struct Baz; } | 594 | mod bar { pub(super) struct Baz; } |
596 | } | 595 | } |
597 | foo::Baz<|> | 596 | foo::Baz$0 |
598 | ", | 597 | ", |
599 | r" | 598 | r" |
600 | mod foo { | 599 | mod foo { |
diff --git a/crates/assists/src/handlers/flip_binexpr.rs b/crates/assists/src/handlers/flip_binexpr.rs index 404f06133..209e5d43c 100644 --- a/crates/assists/src/handlers/flip_binexpr.rs +++ b/crates/assists/src/handlers/flip_binexpr.rs | |||
@@ -8,7 +8,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
8 | // | 8 | // |
9 | // ``` | 9 | // ``` |
10 | // fn main() { | 10 | // fn main() { |
11 | // let _ = 90 +<|> 2; | 11 | // let _ = 90 +$0 2; |
12 | // } | 12 | // } |
13 | // ``` | 13 | // ``` |
14 | // -> | 14 | // -> |
@@ -77,42 +77,34 @@ mod tests { | |||
77 | 77 | ||
78 | #[test] | 78 | #[test] |
79 | fn flip_binexpr_target_is_the_op() { | 79 | fn flip_binexpr_target_is_the_op() { |
80 | check_assist_target(flip_binexpr, "fn f() { let res = 1 ==<|> 2; }", "==") | 80 | check_assist_target(flip_binexpr, "fn f() { let res = 1 ==$0 2; }", "==") |
81 | } | 81 | } |
82 | 82 | ||
83 | #[test] | 83 | #[test] |
84 | fn flip_binexpr_not_applicable_for_assignment() { | 84 | fn flip_binexpr_not_applicable_for_assignment() { |
85 | check_assist_not_applicable(flip_binexpr, "fn f() { let mut _x = 1; _x +=<|> 2 }") | 85 | check_assist_not_applicable(flip_binexpr, "fn f() { let mut _x = 1; _x +=$0 2 }") |
86 | } | 86 | } |
87 | 87 | ||
88 | #[test] | 88 | #[test] |
89 | fn flip_binexpr_works_for_eq() { | 89 | fn flip_binexpr_works_for_eq() { |
90 | check_assist( | 90 | check_assist(flip_binexpr, "fn f() { let res = 1 ==$0 2; }", "fn f() { let res = 2 == 1; }") |
91 | flip_binexpr, | ||
92 | "fn f() { let res = 1 ==<|> 2; }", | ||
93 | "fn f() { let res = 2 == 1; }", | ||
94 | ) | ||
95 | } | 91 | } |
96 | 92 | ||
97 | #[test] | 93 | #[test] |
98 | fn flip_binexpr_works_for_gt() { | 94 | fn flip_binexpr_works_for_gt() { |
99 | check_assist(flip_binexpr, "fn f() { let res = 1 ><|> 2; }", "fn f() { let res = 2 < 1; }") | 95 | check_assist(flip_binexpr, "fn f() { let res = 1 >$0 2; }", "fn f() { let res = 2 < 1; }") |
100 | } | 96 | } |
101 | 97 | ||
102 | #[test] | 98 | #[test] |
103 | fn flip_binexpr_works_for_lteq() { | 99 | fn flip_binexpr_works_for_lteq() { |
104 | check_assist( | 100 | check_assist(flip_binexpr, "fn f() { let res = 1 <=$0 2; }", "fn f() { let res = 2 >= 1; }") |
105 | flip_binexpr, | ||
106 | "fn f() { let res = 1 <=<|> 2; }", | ||
107 | "fn f() { let res = 2 >= 1; }", | ||
108 | ) | ||
109 | } | 101 | } |
110 | 102 | ||
111 | #[test] | 103 | #[test] |
112 | fn flip_binexpr_works_for_complex_expr() { | 104 | fn flip_binexpr_works_for_complex_expr() { |
113 | check_assist( | 105 | check_assist( |
114 | flip_binexpr, | 106 | flip_binexpr, |
115 | "fn f() { let res = (1 + 1) ==<|> (2 + 2); }", | 107 | "fn f() { let res = (1 + 1) ==$0 (2 + 2); }", |
116 | "fn f() { let res = (2 + 2) == (1 + 1); }", | 108 | "fn f() { let res = (2 + 2) == (1 + 1); }", |
117 | ) | 109 | ) |
118 | } | 110 | } |
@@ -125,7 +117,7 @@ mod tests { | |||
125 | fn dyn_eq(&self, other: &dyn Diagnostic) -> bool { | 117 | fn dyn_eq(&self, other: &dyn Diagnostic) -> bool { |
126 | match other.downcast_ref::<Self>() { | 118 | match other.downcast_ref::<Self>() { |
127 | None => false, | 119 | None => false, |
128 | Some(it) => it ==<|> self, | 120 | Some(it) => it ==$0 self, |
129 | } | 121 | } |
130 | } | 122 | } |
131 | "#, | 123 | "#, |
diff --git a/crates/assists/src/handlers/flip_comma.rs b/crates/assists/src/handlers/flip_comma.rs index 64b4b1a76..18cf64a34 100644 --- a/crates/assists/src/handlers/flip_comma.rs +++ b/crates/assists/src/handlers/flip_comma.rs | |||
@@ -8,7 +8,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
8 | // | 8 | // |
9 | // ``` | 9 | // ``` |
10 | // fn main() { | 10 | // fn main() { |
11 | // ((1, 2),<|> (3, 4)); | 11 | // ((1, 2),$0 (3, 4)); |
12 | // } | 12 | // } |
13 | // ``` | 13 | // ``` |
14 | // -> | 14 | // -> |
@@ -49,14 +49,14 @@ mod tests { | |||
49 | fn flip_comma_works_for_function_parameters() { | 49 | fn flip_comma_works_for_function_parameters() { |
50 | check_assist( | 50 | check_assist( |
51 | flip_comma, | 51 | flip_comma, |
52 | "fn foo(x: i32,<|> y: Result<(), ()>) {}", | 52 | r#"fn foo(x: i32,$0 y: Result<(), ()>) {}"#, |
53 | "fn foo(y: Result<(), ()>, x: i32) {}", | 53 | r#"fn foo(y: Result<(), ()>, x: i32) {}"#, |
54 | ) | 54 | ) |
55 | } | 55 | } |
56 | 56 | ||
57 | #[test] | 57 | #[test] |
58 | fn flip_comma_target() { | 58 | fn flip_comma_target() { |
59 | check_assist_target(flip_comma, "fn foo(x: i32,<|> y: Result<(), ()>) {}", ",") | 59 | check_assist_target(flip_comma, r#"fn foo(x: i32,$0 y: Result<(), ()>) {}"#, ",") |
60 | } | 60 | } |
61 | 61 | ||
62 | #[test] | 62 | #[test] |
@@ -68,7 +68,7 @@ mod tests { | |||
68 | check_assist_target( | 68 | check_assist_target( |
69 | flip_comma, | 69 | flip_comma, |
70 | "pub enum Test { \ | 70 | "pub enum Test { \ |
71 | A,<|> \ | 71 | A,$0 \ |
72 | }", | 72 | }", |
73 | ",", | 73 | ",", |
74 | ); | 74 | ); |
@@ -76,7 +76,7 @@ mod tests { | |||
76 | check_assist_target( | 76 | check_assist_target( |
77 | flip_comma, | 77 | flip_comma, |
78 | "pub struct Test { \ | 78 | "pub struct Test { \ |
79 | foo: usize,<|> \ | 79 | foo: usize,$0 \ |
80 | }", | 80 | }", |
81 | ",", | 81 | ",", |
82 | ); | 82 | ); |
diff --git a/crates/assists/src/handlers/flip_trait_bound.rs b/crates/assists/src/handlers/flip_trait_bound.rs index 92ee42181..d419d263e 100644 --- a/crates/assists/src/handlers/flip_trait_bound.rs +++ b/crates/assists/src/handlers/flip_trait_bound.rs | |||
@@ -11,7 +11,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
11 | // Flips two trait bounds. | 11 | // Flips two trait bounds. |
12 | // | 12 | // |
13 | // ``` | 13 | // ``` |
14 | // fn foo<T: Clone +<|> Copy>() { } | 14 | // fn foo<T: Clone +$0 Copy>() { } |
15 | // ``` | 15 | // ``` |
16 | // -> | 16 | // -> |
17 | // ``` | 17 | // ``` |
@@ -52,19 +52,19 @@ mod tests { | |||
52 | 52 | ||
53 | #[test] | 53 | #[test] |
54 | fn flip_trait_bound_assist_available() { | 54 | fn flip_trait_bound_assist_available() { |
55 | check_assist_target(flip_trait_bound, "struct S<T> where T: A <|>+ B + C { }", "+") | 55 | check_assist_target(flip_trait_bound, "struct S<T> where T: A $0+ B + C { }", "+") |
56 | } | 56 | } |
57 | 57 | ||
58 | #[test] | 58 | #[test] |
59 | fn flip_trait_bound_not_applicable_for_single_trait_bound() { | 59 | fn flip_trait_bound_not_applicable_for_single_trait_bound() { |
60 | check_assist_not_applicable(flip_trait_bound, "struct S<T> where T: <|>A { }") | 60 | check_assist_not_applicable(flip_trait_bound, "struct S<T> where T: $0A { }") |
61 | } | 61 | } |
62 | 62 | ||
63 | #[test] | 63 | #[test] |
64 | fn flip_trait_bound_works_for_struct() { | 64 | fn flip_trait_bound_works_for_struct() { |
65 | check_assist( | 65 | check_assist( |
66 | flip_trait_bound, | 66 | flip_trait_bound, |
67 | "struct S<T> where T: A <|>+ B { }", | 67 | "struct S<T> where T: A $0+ B { }", |
68 | "struct S<T> where T: B + A { }", | 68 | "struct S<T> where T: B + A { }", |
69 | ) | 69 | ) |
70 | } | 70 | } |
@@ -73,21 +73,21 @@ mod tests { | |||
73 | fn flip_trait_bound_works_for_trait_impl() { | 73 | fn flip_trait_bound_works_for_trait_impl() { |
74 | check_assist( | 74 | check_assist( |
75 | flip_trait_bound, | 75 | flip_trait_bound, |
76 | "impl X for S<T> where T: A +<|> B { }", | 76 | "impl X for S<T> where T: A +$0 B { }", |
77 | "impl X for S<T> where T: B + A { }", | 77 | "impl X for S<T> where T: B + A { }", |
78 | ) | 78 | ) |
79 | } | 79 | } |
80 | 80 | ||
81 | #[test] | 81 | #[test] |
82 | fn flip_trait_bound_works_for_fn() { | 82 | fn flip_trait_bound_works_for_fn() { |
83 | check_assist(flip_trait_bound, "fn f<T: A <|>+ B>(t: T) { }", "fn f<T: B + A>(t: T) { }") | 83 | check_assist(flip_trait_bound, "fn f<T: A $0+ B>(t: T) { }", "fn f<T: B + A>(t: T) { }") |
84 | } | 84 | } |
85 | 85 | ||
86 | #[test] | 86 | #[test] |
87 | fn flip_trait_bound_works_for_fn_where_clause() { | 87 | fn flip_trait_bound_works_for_fn_where_clause() { |
88 | check_assist( | 88 | check_assist( |
89 | flip_trait_bound, | 89 | flip_trait_bound, |
90 | "fn f<T>(t: T) where T: A +<|> B { }", | 90 | "fn f<T>(t: T) where T: A +$0 B { }", |
91 | "fn f<T>(t: T) where T: B + A { }", | 91 | "fn f<T>(t: T) where T: B + A { }", |
92 | ) | 92 | ) |
93 | } | 93 | } |
@@ -96,7 +96,7 @@ mod tests { | |||
96 | fn flip_trait_bound_works_for_lifetime() { | 96 | fn flip_trait_bound_works_for_lifetime() { |
97 | check_assist( | 97 | check_assist( |
98 | flip_trait_bound, | 98 | flip_trait_bound, |
99 | "fn f<T>(t: T) where T: A <|>+ 'static { }", | 99 | "fn f<T>(t: T) where T: A $0+ 'static { }", |
100 | "fn f<T>(t: T) where T: 'static + A { }", | 100 | "fn f<T>(t: T) where T: 'static + A { }", |
101 | ) | 101 | ) |
102 | } | 102 | } |
@@ -105,7 +105,7 @@ mod tests { | |||
105 | fn flip_trait_bound_works_for_complex_bounds() { | 105 | fn flip_trait_bound_works_for_complex_bounds() { |
106 | check_assist( | 106 | check_assist( |
107 | flip_trait_bound, | 107 | flip_trait_bound, |
108 | "struct S<T> where T: A<T> <|>+ b_mod::B<T> + C<T> { }", | 108 | "struct S<T> where T: A<T> $0+ b_mod::B<T> + C<T> { }", |
109 | "struct S<T> where T: b_mod::B<T> + A<T> + C<T> { }", | 109 | "struct S<T> where T: b_mod::B<T> + A<T> + C<T> { }", |
110 | ) | 110 | ) |
111 | } | 111 | } |
@@ -114,7 +114,7 @@ mod tests { | |||
114 | fn flip_trait_bound_works_for_long_bounds() { | 114 | fn flip_trait_bound_works_for_long_bounds() { |
115 | check_assist( | 115 | check_assist( |
116 | flip_trait_bound, | 116 | flip_trait_bound, |
117 | "struct S<T> where T: A + B + C + D + E + F +<|> G + H + I + J { }", | 117 | "struct S<T> where T: A + B + C + D + E + F +$0 G + H + I + J { }", |
118 | "struct S<T> where T: A + B + C + D + E + G + F + H + I + J { }", | 118 | "struct S<T> where T: A + B + C + D + E + G + F + H + I + J { }", |
119 | ) | 119 | ) |
120 | } | 120 | } |
diff --git a/crates/assists/src/handlers/generate_default_from_enum_variant.rs b/crates/assists/src/handlers/generate_default_from_enum_variant.rs index bcea46735..6a2ab9596 100644 --- a/crates/assists/src/handlers/generate_default_from_enum_variant.rs +++ b/crates/assists/src/handlers/generate_default_from_enum_variant.rs | |||
@@ -12,7 +12,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
12 | // ``` | 12 | // ``` |
13 | // enum Version { | 13 | // enum Version { |
14 | // Undefined, | 14 | // Undefined, |
15 | // Minor<|>, | 15 | // Minor$0, |
16 | // Major, | 16 | // Major, |
17 | // } | 17 | // } |
18 | // ``` | 18 | // ``` |
@@ -108,7 +108,7 @@ mod tests { | |||
108 | r#" | 108 | r#" |
109 | enum Variant { | 109 | enum Variant { |
110 | Undefined, | 110 | Undefined, |
111 | Minor<|>, | 111 | Minor$0, |
112 | Major, | 112 | Major, |
113 | }"#, | 113 | }"#, |
114 | r#"enum Variant { | 114 | r#"enum Variant { |
@@ -132,7 +132,7 @@ impl Default for Variant { | |||
132 | r#" | 132 | r#" |
133 | enum Variant { | 133 | enum Variant { |
134 | Undefined, | 134 | Undefined, |
135 | Minor<|>, | 135 | Minor$0, |
136 | Major, | 136 | Major, |
137 | } | 137 | } |
138 | 138 | ||
@@ -151,7 +151,7 @@ impl Default for Variant { | |||
151 | r#" | 151 | r#" |
152 | enum Variant { | 152 | enum Variant { |
153 | Undefined, | 153 | Undefined, |
154 | Minor(u32)<|>, | 154 | Minor(u32)$0, |
155 | Major, | 155 | Major, |
156 | }"#, | 156 | }"#, |
157 | ); | 157 | ); |
@@ -161,7 +161,7 @@ enum Variant { | |||
161 | fn test_generate_default_from_variant_with_one_variant() { | 161 | fn test_generate_default_from_variant_with_one_variant() { |
162 | check_assist( | 162 | check_assist( |
163 | generate_default_from_enum_variant, | 163 | generate_default_from_enum_variant, |
164 | r#"enum Variant { Undefi<|>ned }"#, | 164 | r#"enum Variant { Undefi$0ned }"#, |
165 | r#" | 165 | r#" |
166 | enum Variant { Undefined } | 166 | enum Variant { Undefined } |
167 | 167 | ||
diff --git a/crates/assists/src/handlers/generate_derive.rs b/crates/assists/src/handlers/generate_derive.rs index 314504e15..f876b7684 100644 --- a/crates/assists/src/handlers/generate_derive.rs +++ b/crates/assists/src/handlers/generate_derive.rs | |||
@@ -13,7 +13,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
13 | // ``` | 13 | // ``` |
14 | // struct Point { | 14 | // struct Point { |
15 | // x: u32, | 15 | // x: u32, |
16 | // y: u32,<|> | 16 | // y: u32,$0 |
17 | // } | 17 | // } |
18 | // ``` | 18 | // ``` |
19 | // -> | 19 | // -> |
@@ -76,12 +76,12 @@ mod tests { | |||
76 | fn add_derive_new() { | 76 | fn add_derive_new() { |
77 | check_assist( | 77 | check_assist( |
78 | generate_derive, | 78 | generate_derive, |
79 | "struct Foo { a: i32, <|>}", | 79 | "struct Foo { a: i32, $0}", |
80 | "#[derive($0)]\nstruct Foo { a: i32, }", | 80 | "#[derive($0)]\nstruct Foo { a: i32, }", |
81 | ); | 81 | ); |
82 | check_assist( | 82 | check_assist( |
83 | generate_derive, | 83 | generate_derive, |
84 | "struct Foo { <|> a: i32, }", | 84 | "struct Foo { $0 a: i32, }", |
85 | "#[derive($0)]\nstruct Foo { a: i32, }", | 85 | "#[derive($0)]\nstruct Foo { a: i32, }", |
86 | ); | 86 | ); |
87 | } | 87 | } |
@@ -90,7 +90,7 @@ mod tests { | |||
90 | fn add_derive_existing() { | 90 | fn add_derive_existing() { |
91 | check_assist( | 91 | check_assist( |
92 | generate_derive, | 92 | generate_derive, |
93 | "#[derive(Clone)]\nstruct Foo { a: i32<|>, }", | 93 | "#[derive(Clone)]\nstruct Foo { a: i32$0, }", |
94 | "#[derive(Clone$0)]\nstruct Foo { a: i32, }", | 94 | "#[derive(Clone$0)]\nstruct Foo { a: i32, }", |
95 | ); | 95 | ); |
96 | } | 96 | } |
@@ -102,7 +102,7 @@ mod tests { | |||
102 | " | 102 | " |
103 | /// `Foo` is a pretty important struct. | 103 | /// `Foo` is a pretty important struct. |
104 | /// It does stuff. | 104 | /// It does stuff. |
105 | struct Foo { a: i32<|>, } | 105 | struct Foo { a: i32$0, } |
106 | ", | 106 | ", |
107 | " | 107 | " |
108 | /// `Foo` is a pretty important struct. | 108 | /// `Foo` is a pretty important struct. |
@@ -121,7 +121,7 @@ struct Foo { a: i32, } | |||
121 | struct SomeThingIrrelevant; | 121 | struct SomeThingIrrelevant; |
122 | /// `Foo` is a pretty important struct. | 122 | /// `Foo` is a pretty important struct. |
123 | /// It does stuff. | 123 | /// It does stuff. |
124 | struct Foo { a: i32<|>, } | 124 | struct Foo { a: i32$0, } |
125 | struct EvenMoreIrrelevant; | 125 | struct EvenMoreIrrelevant; |
126 | ", | 126 | ", |
127 | "/// `Foo` is a pretty important struct. | 127 | "/// `Foo` is a pretty important struct. |
diff --git a/crates/assists/src/handlers/generate_from_impl_for_enum.rs b/crates/assists/src/handlers/generate_from_impl_for_enum.rs index 3c374e5d9..d9af6ab11 100644 --- a/crates/assists/src/handlers/generate_from_impl_for_enum.rs +++ b/crates/assists/src/handlers/generate_from_impl_for_enum.rs | |||
@@ -10,7 +10,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
10 | // Adds a From impl for an enum variant with one tuple field. | 10 | // Adds a From impl for an enum variant with one tuple field. |
11 | // | 11 | // |
12 | // ``` | 12 | // ``` |
13 | // enum A { <|>One(u32) } | 13 | // enum A { $0One(u32) } |
14 | // ``` | 14 | // ``` |
15 | // -> | 15 | // -> |
16 | // ``` | 16 | // ``` |
@@ -101,7 +101,7 @@ mod tests { | |||
101 | fn test_generate_from_impl_for_enum() { | 101 | fn test_generate_from_impl_for_enum() { |
102 | check_assist( | 102 | check_assist( |
103 | generate_from_impl_for_enum, | 103 | generate_from_impl_for_enum, |
104 | "enum A { <|>One(u32) }", | 104 | "enum A { $0One(u32) }", |
105 | r#"enum A { One(u32) } | 105 | r#"enum A { One(u32) } |
106 | 106 | ||
107 | impl From<u32> for A { | 107 | impl From<u32> for A { |
@@ -116,7 +116,7 @@ impl From<u32> for A { | |||
116 | fn test_generate_from_impl_for_enum_complicated_path() { | 116 | fn test_generate_from_impl_for_enum_complicated_path() { |
117 | check_assist( | 117 | check_assist( |
118 | generate_from_impl_for_enum, | 118 | generate_from_impl_for_enum, |
119 | r#"enum A { <|>One(foo::bar::baz::Boo) }"#, | 119 | r#"enum A { $0One(foo::bar::baz::Boo) }"#, |
120 | r#"enum A { One(foo::bar::baz::Boo) } | 120 | r#"enum A { One(foo::bar::baz::Boo) } |
121 | 121 | ||
122 | impl From<foo::bar::baz::Boo> for A { | 122 | impl From<foo::bar::baz::Boo> for A { |
@@ -135,17 +135,17 @@ impl From<foo::bar::baz::Boo> for A { | |||
135 | 135 | ||
136 | #[test] | 136 | #[test] |
137 | fn test_add_from_impl_no_element() { | 137 | fn test_add_from_impl_no_element() { |
138 | check_not_applicable("enum A { <|>One }"); | 138 | check_not_applicable("enum A { $0One }"); |
139 | } | 139 | } |
140 | 140 | ||
141 | #[test] | 141 | #[test] |
142 | fn test_add_from_impl_more_than_one_element_in_tuple() { | 142 | fn test_add_from_impl_more_than_one_element_in_tuple() { |
143 | check_not_applicable("enum A { <|>One(u32, String) }"); | 143 | check_not_applicable("enum A { $0One(u32, String) }"); |
144 | } | 144 | } |
145 | 145 | ||
146 | #[test] | 146 | #[test] |
147 | fn test_add_from_impl_struct_variant() { | 147 | fn test_add_from_impl_struct_variant() { |
148 | check_not_applicable("enum A { <|>One { x: u32 } }"); | 148 | check_not_applicable("enum A { $0One { x: u32 } }"); |
149 | } | 149 | } |
150 | 150 | ||
151 | #[test] | 151 | #[test] |
@@ -153,7 +153,7 @@ impl From<foo::bar::baz::Boo> for A { | |||
153 | mark::check!(test_add_from_impl_already_exists); | 153 | mark::check!(test_add_from_impl_already_exists); |
154 | check_not_applicable( | 154 | check_not_applicable( |
155 | r#" | 155 | r#" |
156 | enum A { <|>One(u32), } | 156 | enum A { $0One(u32), } |
157 | 157 | ||
158 | impl From<u32> for A { | 158 | impl From<u32> for A { |
159 | fn from(v: u32) -> Self { | 159 | fn from(v: u32) -> Self { |
@@ -168,7 +168,7 @@ impl From<u32> for A { | |||
168 | fn test_add_from_impl_different_variant_impl_exists() { | 168 | fn test_add_from_impl_different_variant_impl_exists() { |
169 | check_assist( | 169 | check_assist( |
170 | generate_from_impl_for_enum, | 170 | generate_from_impl_for_enum, |
171 | r#"enum A { <|>One(u32), Two(String), } | 171 | r#"enum A { $0One(u32), Two(String), } |
172 | 172 | ||
173 | impl From<String> for A { | 173 | impl From<String> for A { |
174 | fn from(v: String) -> Self { | 174 | fn from(v: String) -> Self { |
diff --git a/crates/assists/src/handlers/generate_function.rs b/crates/assists/src/handlers/generate_function.rs index f4cf155b6..06ac85f67 100644 --- a/crates/assists/src/handlers/generate_function.rs +++ b/crates/assists/src/handlers/generate_function.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use hir::HirDisplay; | 1 | use hir::HirDisplay; |
2 | use ide_db::base_db::FileId; | 2 | use ide_db::{base_db::FileId, helpers::SnippetCap}; |
3 | use rustc_hash::{FxHashMap, FxHashSet}; | 3 | use rustc_hash::{FxHashMap, FxHashSet}; |
4 | use syntax::{ | 4 | use syntax::{ |
5 | ast::{ | 5 | ast::{ |
@@ -11,7 +11,6 @@ use syntax::{ | |||
11 | }; | 11 | }; |
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{ |
14 | assist_config::SnippetCap, | ||
15 | utils::{render_snippet, Cursor}, | 14 | utils::{render_snippet, Cursor}, |
16 | AssistContext, AssistId, AssistKind, Assists, | 15 | AssistContext, AssistId, AssistKind, Assists, |
17 | }; | 16 | }; |
@@ -24,7 +23,7 @@ use crate::{ | |||
24 | // struct Baz; | 23 | // struct Baz; |
25 | // fn baz() -> Baz { Baz } | 24 | // fn baz() -> Baz { Baz } |
26 | // fn foo() { | 25 | // fn foo() { |
27 | // bar<|>("", baz()); | 26 | // bar$0("", baz()); |
28 | // } | 27 | // } |
29 | // | 28 | // |
30 | // ``` | 29 | // ``` |
@@ -343,7 +342,7 @@ mod tests { | |||
343 | generate_function, | 342 | generate_function, |
344 | r" | 343 | r" |
345 | fn foo() { | 344 | fn foo() { |
346 | bar<|>(); | 345 | bar$0(); |
347 | } | 346 | } |
348 | ", | 347 | ", |
349 | r" | 348 | r" |
@@ -367,7 +366,7 @@ fn bar() ${0:-> ()} { | |||
367 | r" | 366 | r" |
368 | impl Foo { | 367 | impl Foo { |
369 | fn foo() { | 368 | fn foo() { |
370 | bar<|>(); | 369 | bar$0(); |
371 | } | 370 | } |
372 | } | 371 | } |
373 | ", | 372 | ", |
@@ -392,7 +391,7 @@ fn bar() ${0:-> ()} { | |||
392 | generate_function, | 391 | generate_function, |
393 | r" | 392 | r" |
394 | fn foo1() { | 393 | fn foo1() { |
395 | bar<|>(); | 394 | bar$0(); |
396 | } | 395 | } |
397 | 396 | ||
398 | fn foo2() {} | 397 | fn foo2() {} |
@@ -418,7 +417,7 @@ fn foo2() {} | |||
418 | r" | 417 | r" |
419 | mod baz { | 418 | mod baz { |
420 | fn foo() { | 419 | fn foo() { |
421 | bar<|>(); | 420 | bar$0(); |
422 | } | 421 | } |
423 | } | 422 | } |
424 | ", | 423 | ", |
@@ -444,7 +443,7 @@ mod baz { | |||
444 | struct Baz; | 443 | struct Baz; |
445 | fn baz() -> Baz { todo!() } | 444 | fn baz() -> Baz { todo!() } |
446 | fn foo() { | 445 | fn foo() { |
447 | bar<|>(baz()); | 446 | bar$0(baz()); |
448 | } | 447 | } |
449 | ", | 448 | ", |
450 | r" | 449 | r" |
@@ -469,7 +468,7 @@ fn bar(baz: Baz) ${0:-> ()} { | |||
469 | struct Baz; | 468 | struct Baz; |
470 | impl Baz { | 469 | impl Baz { |
471 | fn foo(&self) -> Baz { | 470 | fn foo(&self) -> Baz { |
472 | ba<|>r(self.baz()) | 471 | ba$0r(self.baz()) |
473 | } | 472 | } |
474 | fn baz(&self) -> Baz { | 473 | fn baz(&self) -> Baz { |
475 | Baz | 474 | Baz |
@@ -500,7 +499,7 @@ fn bar(baz: Baz) ${0:-> ()} { | |||
500 | generate_function, | 499 | generate_function, |
501 | r#" | 500 | r#" |
502 | fn foo() { | 501 | fn foo() { |
503 | <|>bar("bar") | 502 | $0bar("bar") |
504 | } | 503 | } |
505 | "#, | 504 | "#, |
506 | r#" | 505 | r#" |
@@ -521,7 +520,7 @@ fn bar(arg: &str) ${0:-> ()} { | |||
521 | generate_function, | 520 | generate_function, |
522 | r#" | 521 | r#" |
523 | fn foo() { | 522 | fn foo() { |
524 | <|>bar('x') | 523 | $0bar('x') |
525 | } | 524 | } |
526 | "#, | 525 | "#, |
527 | r#" | 526 | r#" |
@@ -542,7 +541,7 @@ fn bar(arg: char) ${0:-> ()} { | |||
542 | generate_function, | 541 | generate_function, |
543 | r" | 542 | r" |
544 | fn foo() { | 543 | fn foo() { |
545 | <|>bar(42) | 544 | $0bar(42) |
546 | } | 545 | } |
547 | ", | 546 | ", |
548 | r" | 547 | r" |
@@ -563,7 +562,7 @@ fn bar(arg: i32) ${0:-> ()} { | |||
563 | generate_function, | 562 | generate_function, |
564 | r" | 563 | r" |
565 | fn foo() { | 564 | fn foo() { |
566 | <|>bar(42 as u8) | 565 | $0bar(42 as u8) |
567 | } | 566 | } |
568 | ", | 567 | ", |
569 | r" | 568 | r" |
@@ -587,7 +586,7 @@ fn bar(arg: u8) ${0:-> ()} { | |||
587 | r" | 586 | r" |
588 | fn foo() { | 587 | fn foo() { |
589 | let x = 42; | 588 | let x = 42; |
590 | bar<|>(x as u8) | 589 | bar$0(x as u8) |
591 | } | 590 | } |
592 | ", | 591 | ", |
593 | r" | 592 | r" |
@@ -610,7 +609,7 @@ fn bar(x: u8) ${0:-> ()} { | |||
610 | r" | 609 | r" |
611 | fn foo() { | 610 | fn foo() { |
612 | let worble = (); | 611 | let worble = (); |
613 | <|>bar(worble) | 612 | $0bar(worble) |
614 | } | 613 | } |
615 | ", | 614 | ", |
616 | r" | 615 | r" |
@@ -636,7 +635,7 @@ fn foo() -> impl Foo { | |||
636 | todo!() | 635 | todo!() |
637 | } | 636 | } |
638 | fn baz() { | 637 | fn baz() { |
639 | <|>bar(foo()) | 638 | $0bar(foo()) |
640 | } | 639 | } |
641 | ", | 640 | ", |
642 | r" | 641 | r" |
@@ -664,7 +663,7 @@ struct Baz; | |||
664 | fn baz() -> Baz { todo!() } | 663 | fn baz() -> Baz { todo!() } |
665 | 664 | ||
666 | fn foo() { | 665 | fn foo() { |
667 | bar<|>(&baz()) | 666 | bar$0(&baz()) |
668 | } | 667 | } |
669 | ", | 668 | ", |
670 | r" | 669 | r" |
@@ -692,7 +691,7 @@ mod Baz { | |||
692 | pub fn baz() -> Bof { Bof } | 691 | pub fn baz() -> Bof { Bof } |
693 | } | 692 | } |
694 | fn foo() { | 693 | fn foo() { |
695 | <|>bar(Baz::baz()) | 694 | $0bar(Baz::baz()) |
696 | } | 695 | } |
697 | ", | 696 | ", |
698 | r" | 697 | r" |
@@ -719,7 +718,7 @@ fn bar(baz: Baz::Bof) ${0:-> ()} { | |||
719 | generate_function, | 718 | generate_function, |
720 | r" | 719 | r" |
721 | fn foo<T>(t: T) { | 720 | fn foo<T>(t: T) { |
722 | <|>bar(t) | 721 | $0bar(t) |
723 | } | 722 | } |
724 | ", | 723 | ", |
725 | r" | 724 | r" |
@@ -746,7 +745,7 @@ impl Baz { | |||
746 | fn new() -> Self { Baz } | 745 | fn new() -> Self { Baz } |
747 | } | 746 | } |
748 | fn foo() { | 747 | fn foo() { |
749 | <|>bar(Baz::new); | 748 | $0bar(Baz::new); |
750 | } | 749 | } |
751 | ", | 750 | ", |
752 | r" | 751 | r" |
@@ -774,7 +773,7 @@ fn bar(arg: fn() -> Baz) ${0:-> ()} { | |||
774 | r" | 773 | r" |
775 | fn foo() { | 774 | fn foo() { |
776 | let closure = |x: i64| x - 1; | 775 | let closure = |x: i64| x - 1; |
777 | <|>bar(closure) | 776 | $0bar(closure) |
778 | } | 777 | } |
779 | ", | 778 | ", |
780 | r" | 779 | r" |
@@ -796,7 +795,7 @@ fn bar(closure: impl Fn(i64) -> i64) ${0:-> ()} { | |||
796 | generate_function, | 795 | generate_function, |
797 | r" | 796 | r" |
798 | fn foo() { | 797 | fn foo() { |
799 | <|>bar(baz) | 798 | $0bar(baz) |
800 | } | 799 | } |
801 | ", | 800 | ", |
802 | r" | 801 | r" |
@@ -819,7 +818,7 @@ fn bar(baz: ()) ${0:-> ()} { | |||
819 | struct Baz; | 818 | struct Baz; |
820 | fn baz() -> Baz { Baz } | 819 | fn baz() -> Baz { Baz } |
821 | fn foo() { | 820 | fn foo() { |
822 | <|>bar(baz(), baz()) | 821 | $0bar(baz(), baz()) |
823 | } | 822 | } |
824 | ", | 823 | ", |
825 | r" | 824 | r" |
@@ -844,7 +843,7 @@ fn bar(baz_1: Baz, baz_2: Baz) ${0:-> ()} { | |||
844 | struct Baz; | 843 | struct Baz; |
845 | fn baz() -> Baz { Baz } | 844 | fn baz() -> Baz { Baz } |
846 | fn foo() { | 845 | fn foo() { |
847 | <|>bar(baz(), baz(), "foo", "bar") | 846 | $0bar(baz(), baz(), "foo", "bar") |
848 | } | 847 | } |
849 | "#, | 848 | "#, |
850 | r#" | 849 | r#" |
@@ -869,7 +868,7 @@ fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) ${0:-> ()} { | |||
869 | mod bar {} | 868 | mod bar {} |
870 | 869 | ||
871 | fn foo() { | 870 | fn foo() { |
872 | bar::my_fn<|>() | 871 | bar::my_fn$0() |
873 | } | 872 | } |
874 | ", | 873 | ", |
875 | r" | 874 | r" |
@@ -900,7 +899,7 @@ mod foo { | |||
900 | fn bar() { | 899 | fn bar() { |
901 | use foo::Foo; | 900 | use foo::Foo; |
902 | let foo = Foo; | 901 | let foo = Foo; |
903 | baz<|>(foo) | 902 | baz$0(foo) |
904 | } | 903 | } |
905 | ", | 904 | ", |
906 | " | 905 | " |
@@ -930,7 +929,7 @@ mod bar { | |||
930 | } | 929 | } |
931 | 930 | ||
932 | fn foo() { | 931 | fn foo() { |
933 | bar::my_fn<|>() | 932 | bar::my_fn$0() |
934 | } | 933 | } |
935 | ", | 934 | ", |
936 | r" | 935 | r" |
@@ -959,7 +958,7 @@ mod bar { | |||
959 | } | 958 | } |
960 | 959 | ||
961 | fn foo() { | 960 | fn foo() { |
962 | bar::baz::my_fn<|>() | 961 | bar::baz::my_fn$0() |
963 | } | 962 | } |
964 | ", | 963 | ", |
965 | r" | 964 | r" |
@@ -987,7 +986,7 @@ fn foo() { | |||
987 | mod foo; | 986 | mod foo; |
988 | 987 | ||
989 | fn main() { | 988 | fn main() { |
990 | foo::bar<|>() | 989 | foo::bar$0() |
991 | } | 990 | } |
992 | //- /foo.rs | 991 | //- /foo.rs |
993 | ", | 992 | ", |
@@ -1006,7 +1005,7 @@ pub(crate) fn bar() ${0:-> ()} { | |||
1006 | generate_function, | 1005 | generate_function, |
1007 | r" | 1006 | r" |
1008 | fn foo() { | 1007 | fn foo() { |
1009 | bar<|>(); | 1008 | bar$0(); |
1010 | } | 1009 | } |
1011 | 1010 | ||
1012 | fn bar() {} | 1011 | fn bar() {} |
@@ -1023,7 +1022,7 @@ fn bar() {} | |||
1023 | generate_function, | 1022 | generate_function, |
1024 | r" | 1023 | r" |
1025 | fn foo() { | 1024 | fn foo() { |
1026 | bar(b<|>az); | 1025 | bar(b$0az); |
1027 | } | 1026 | } |
1028 | 1027 | ||
1029 | fn bar(baz: ()) {} | 1028 | fn bar(baz: ()) {} |
@@ -1040,7 +1039,7 @@ fn bar(baz: ()) {} | |||
1040 | struct Foo; | 1039 | struct Foo; |
1041 | impl Foo { | 1040 | impl Foo { |
1042 | fn foo(&self) { | 1041 | fn foo(&self) { |
1043 | self.bar()<|>; | 1042 | self.bar()$0; |
1044 | } | 1043 | } |
1045 | } | 1044 | } |
1046 | ", | 1045 | ", |
diff --git a/crates/assists/src/handlers/generate_impl.rs b/crates/assists/src/handlers/generate_impl.rs index 960af5ab3..9af45192b 100644 --- a/crates/assists/src/handlers/generate_impl.rs +++ b/crates/assists/src/handlers/generate_impl.rs | |||
@@ -10,7 +10,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
10 | // | 10 | // |
11 | // ``` | 11 | // ``` |
12 | // struct Ctx<T: Clone> { | 12 | // struct Ctx<T: Clone> { |
13 | // data: T,<|> | 13 | // data: T,$0 |
14 | // } | 14 | // } |
15 | // ``` | 15 | // ``` |
16 | // -> | 16 | // -> |
@@ -87,24 +87,24 @@ mod tests { | |||
87 | fn test_add_impl() { | 87 | fn test_add_impl() { |
88 | check_assist( | 88 | check_assist( |
89 | generate_impl, | 89 | generate_impl, |
90 | "struct Foo {<|>}\n", | 90 | "struct Foo {$0}\n", |
91 | "struct Foo {}\n\nimpl Foo {\n $0\n}\n", | 91 | "struct Foo {}\n\nimpl Foo {\n $0\n}\n", |
92 | ); | 92 | ); |
93 | check_assist( | 93 | check_assist( |
94 | generate_impl, | 94 | generate_impl, |
95 | "struct Foo<T: Clone> {<|>}", | 95 | "struct Foo<T: Clone> {$0}", |
96 | "struct Foo<T: Clone> {}\n\nimpl<T: Clone> Foo<T> {\n $0\n}", | 96 | "struct Foo<T: Clone> {}\n\nimpl<T: Clone> Foo<T> {\n $0\n}", |
97 | ); | 97 | ); |
98 | check_assist( | 98 | check_assist( |
99 | generate_impl, | 99 | generate_impl, |
100 | "struct Foo<'a, T: Foo<'a>> {<|>}", | 100 | "struct Foo<'a, T: Foo<'a>> {$0}", |
101 | "struct Foo<'a, T: Foo<'a>> {}\n\nimpl<'a, T: Foo<'a>> Foo<'a, T> {\n $0\n}", | 101 | "struct Foo<'a, T: Foo<'a>> {}\n\nimpl<'a, T: Foo<'a>> Foo<'a, T> {\n $0\n}", |
102 | ); | 102 | ); |
103 | check_assist( | 103 | check_assist( |
104 | generate_impl, | 104 | generate_impl, |
105 | r#" | 105 | r#" |
106 | #[cfg(feature = "foo")] | 106 | #[cfg(feature = "foo")] |
107 | struct Foo<'a, T: Foo<'a>> {<|>}"#, | 107 | struct Foo<'a, T: Foo<'a>> {$0}"#, |
108 | r#" | 108 | r#" |
109 | #[cfg(feature = "foo")] | 109 | #[cfg(feature = "foo")] |
110 | struct Foo<'a, T: Foo<'a>> {} | 110 | struct Foo<'a, T: Foo<'a>> {} |
@@ -119,7 +119,7 @@ mod tests { | |||
119 | generate_impl, | 119 | generate_impl, |
120 | r#" | 120 | r#" |
121 | #[cfg(not(feature = "foo"))] | 121 | #[cfg(not(feature = "foo"))] |
122 | struct Foo<'a, T: Foo<'a>> {<|>}"#, | 122 | struct Foo<'a, T: Foo<'a>> {$0}"#, |
123 | r#" | 123 | r#" |
124 | #[cfg(not(feature = "foo"))] | 124 | #[cfg(not(feature = "foo"))] |
125 | struct Foo<'a, T: Foo<'a>> {} | 125 | struct Foo<'a, T: Foo<'a>> {} |
@@ -138,7 +138,7 @@ mod tests { | |||
138 | " | 138 | " |
139 | struct SomeThingIrrelevant; | 139 | struct SomeThingIrrelevant; |
140 | /// Has a lifetime parameter | 140 | /// Has a lifetime parameter |
141 | struct Foo<'a, T: Foo<'a>> {<|>} | 141 | struct Foo<'a, T: Foo<'a>> {$0} |
142 | struct EvenMoreIrrelevant; | 142 | struct EvenMoreIrrelevant; |
143 | ", | 143 | ", |
144 | "/// Has a lifetime parameter | 144 | "/// Has a lifetime parameter |
diff --git a/crates/assists/src/handlers/generate_new.rs b/crates/assists/src/handlers/generate_new.rs index c5fec4e0a..5c52b2bc8 100644 --- a/crates/assists/src/handlers/generate_new.rs +++ b/crates/assists/src/handlers/generate_new.rs | |||
@@ -14,7 +14,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
14 | // | 14 | // |
15 | // ``` | 15 | // ``` |
16 | // struct Ctx<T: Clone> { | 16 | // struct Ctx<T: Clone> { |
17 | // data: T,<|> | 17 | // data: T,$0 |
18 | // } | 18 | // } |
19 | // ``` | 19 | // ``` |
20 | // -> | 20 | // -> |
@@ -182,7 +182,7 @@ mod tests { | |||
182 | // Check output of generation | 182 | // Check output of generation |
183 | check_assist( | 183 | check_assist( |
184 | generate_new, | 184 | generate_new, |
185 | "struct Foo {<|>}", | 185 | "struct Foo {$0}", |
186 | "struct Foo {} | 186 | "struct Foo {} |
187 | 187 | ||
188 | impl Foo { | 188 | impl Foo { |
@@ -192,7 +192,7 @@ impl Foo { | |||
192 | ); | 192 | ); |
193 | check_assist( | 193 | check_assist( |
194 | generate_new, | 194 | generate_new, |
195 | "struct Foo<T: Clone> {<|>}", | 195 | "struct Foo<T: Clone> {$0}", |
196 | "struct Foo<T: Clone> {} | 196 | "struct Foo<T: Clone> {} |
197 | 197 | ||
198 | impl<T: Clone> Foo<T> { | 198 | impl<T: Clone> Foo<T> { |
@@ -202,7 +202,7 @@ impl<T: Clone> Foo<T> { | |||
202 | ); | 202 | ); |
203 | check_assist( | 203 | check_assist( |
204 | generate_new, | 204 | generate_new, |
205 | "struct Foo<'a, T: Foo<'a>> {<|>}", | 205 | "struct Foo<'a, T: Foo<'a>> {$0}", |
206 | "struct Foo<'a, T: Foo<'a>> {} | 206 | "struct Foo<'a, T: Foo<'a>> {} |
207 | 207 | ||
208 | impl<'a, T: Foo<'a>> Foo<'a, T> { | 208 | impl<'a, T: Foo<'a>> Foo<'a, T> { |
@@ -212,7 +212,7 @@ impl<'a, T: Foo<'a>> Foo<'a, T> { | |||
212 | ); | 212 | ); |
213 | check_assist( | 213 | check_assist( |
214 | generate_new, | 214 | generate_new, |
215 | "struct Foo { baz: String <|>}", | 215 | "struct Foo { baz: String $0}", |
216 | "struct Foo { baz: String } | 216 | "struct Foo { baz: String } |
217 | 217 | ||
218 | impl Foo { | 218 | impl Foo { |
@@ -222,7 +222,7 @@ impl Foo { | |||
222 | ); | 222 | ); |
223 | check_assist( | 223 | check_assist( |
224 | generate_new, | 224 | generate_new, |
225 | "struct Foo { baz: String, qux: Vec<i32> <|>}", | 225 | "struct Foo { baz: String, qux: Vec<i32> $0}", |
226 | "struct Foo { baz: String, qux: Vec<i32> } | 226 | "struct Foo { baz: String, qux: Vec<i32> } |
227 | 227 | ||
228 | impl Foo { | 228 | impl Foo { |
@@ -234,7 +234,7 @@ impl Foo { | |||
234 | // Check that visibility modifiers don't get brought in for fields | 234 | // Check that visibility modifiers don't get brought in for fields |
235 | check_assist( | 235 | check_assist( |
236 | generate_new, | 236 | generate_new, |
237 | "struct Foo { pub baz: String, pub qux: Vec<i32> <|>}", | 237 | "struct Foo { pub baz: String, pub qux: Vec<i32> $0}", |
238 | "struct Foo { pub baz: String, pub qux: Vec<i32> } | 238 | "struct Foo { pub baz: String, pub qux: Vec<i32> } |
239 | 239 | ||
240 | impl Foo { | 240 | impl Foo { |
@@ -246,7 +246,7 @@ impl Foo { | |||
246 | // Check that it reuses existing impls | 246 | // Check that it reuses existing impls |
247 | check_assist( | 247 | check_assist( |
248 | generate_new, | 248 | generate_new, |
249 | "struct Foo {<|>} | 249 | "struct Foo {$0} |
250 | 250 | ||
251 | impl Foo {} | 251 | impl Foo {} |
252 | ", | 252 | ", |
@@ -259,7 +259,7 @@ impl Foo { | |||
259 | ); | 259 | ); |
260 | check_assist( | 260 | check_assist( |
261 | generate_new, | 261 | generate_new, |
262 | "struct Foo {<|>} | 262 | "struct Foo {$0} |
263 | 263 | ||
264 | impl Foo { | 264 | impl Foo { |
265 | fn qux(&self) {} | 265 | fn qux(&self) {} |
@@ -277,7 +277,7 @@ impl Foo { | |||
277 | 277 | ||
278 | check_assist( | 278 | check_assist( |
279 | generate_new, | 279 | generate_new, |
280 | "struct Foo {<|>} | 280 | "struct Foo {$0} |
281 | 281 | ||
282 | impl Foo { | 282 | impl Foo { |
283 | fn qux(&self) {} | 283 | fn qux(&self) {} |
@@ -302,7 +302,7 @@ impl Foo { | |||
302 | // Check visibility of new fn based on struct | 302 | // Check visibility of new fn based on struct |
303 | check_assist( | 303 | check_assist( |
304 | generate_new, | 304 | generate_new, |
305 | "pub struct Foo {<|>}", | 305 | "pub struct Foo {$0}", |
306 | "pub struct Foo {} | 306 | "pub struct Foo {} |
307 | 307 | ||
308 | impl Foo { | 308 | impl Foo { |
@@ -312,7 +312,7 @@ impl Foo { | |||
312 | ); | 312 | ); |
313 | check_assist( | 313 | check_assist( |
314 | generate_new, | 314 | generate_new, |
315 | "pub(crate) struct Foo {<|>}", | 315 | "pub(crate) struct Foo {$0}", |
316 | "pub(crate) struct Foo {} | 316 | "pub(crate) struct Foo {} |
317 | 317 | ||
318 | impl Foo { | 318 | impl Foo { |
@@ -327,7 +327,7 @@ impl Foo { | |||
327 | check_assist_not_applicable( | 327 | check_assist_not_applicable( |
328 | generate_new, | 328 | generate_new, |
329 | " | 329 | " |
330 | struct Foo {<|>} | 330 | struct Foo {$0} |
331 | 331 | ||
332 | impl Foo { | 332 | impl Foo { |
333 | fn new() -> Self { | 333 | fn new() -> Self { |
@@ -339,7 +339,7 @@ impl Foo { | |||
339 | check_assist_not_applicable( | 339 | check_assist_not_applicable( |
340 | generate_new, | 340 | generate_new, |
341 | " | 341 | " |
342 | struct Foo {<|>} | 342 | struct Foo {$0} |
343 | 343 | ||
344 | impl Foo { | 344 | impl Foo { |
345 | fn New() -> Self { | 345 | fn New() -> Self { |
@@ -356,7 +356,7 @@ impl Foo { | |||
356 | " | 356 | " |
357 | struct SomeThingIrrelevant; | 357 | struct SomeThingIrrelevant; |
358 | /// Has a lifetime parameter | 358 | /// Has a lifetime parameter |
359 | struct Foo<'a, T: Foo<'a>> {<|>} | 359 | struct Foo<'a, T: Foo<'a>> {$0} |
360 | struct EvenMoreIrrelevant; | 360 | struct EvenMoreIrrelevant; |
361 | ", | 361 | ", |
362 | "/// Has a lifetime parameter | 362 | "/// Has a lifetime parameter |
@@ -381,7 +381,7 @@ impl<N: AstNode> AstId<N> { | |||
381 | } | 381 | } |
382 | 382 | ||
383 | pub struct Source<T> { | 383 | pub struct Source<T> { |
384 | pub file_id: HirFileId,<|> | 384 | pub file_id: HirFileId,$0 |
385 | pub ast: T, | 385 | pub ast: T, |
386 | } | 386 | } |
387 | 387 | ||
diff --git a/crates/assists/src/handlers/infer_function_return_type.rs b/crates/assists/src/handlers/infer_function_return_type.rs index f499cdfdc..5279af1f3 100644 --- a/crates/assists/src/handlers/infer_function_return_type.rs +++ b/crates/assists/src/handlers/infer_function_return_type.rs | |||
@@ -10,7 +10,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
10 | // type specified. This assists is useable in a functions or closures tail expression or return type position. | 10 | // type specified. This assists is useable in a functions or closures tail expression or return type position. |
11 | // | 11 | // |
12 | // ``` | 12 | // ``` |
13 | // fn foo() { 4<|>2i32 } | 13 | // fn foo() { 4$02i32 } |
14 | // ``` | 14 | // ``` |
15 | // -> | 15 | // -> |
16 | // ``` | 16 | // ``` |
@@ -131,7 +131,7 @@ mod tests { | |||
131 | mark::check!(existing_infer_ret_type); | 131 | mark::check!(existing_infer_ret_type); |
132 | check_assist( | 132 | check_assist( |
133 | infer_function_return_type, | 133 | infer_function_return_type, |
134 | r#"fn foo() -> <|>_ { | 134 | r#"fn foo() -> $0_ { |
135 | 45 | 135 | 45 |
136 | }"#, | 136 | }"#, |
137 | r#"fn foo() -> i32 { | 137 | r#"fn foo() -> i32 { |
@@ -146,7 +146,7 @@ mod tests { | |||
146 | check_assist( | 146 | check_assist( |
147 | infer_function_return_type, | 147 | infer_function_return_type, |
148 | r#"fn foo() { | 148 | r#"fn foo() { |
149 | || -> _ {<|>45}; | 149 | || -> _ {$045}; |
150 | }"#, | 150 | }"#, |
151 | r#"fn foo() { | 151 | r#"fn foo() { |
152 | || -> i32 {45}; | 152 | || -> i32 {45}; |
@@ -159,7 +159,7 @@ mod tests { | |||
159 | mark::check!(cursor_in_ret_position); | 159 | mark::check!(cursor_in_ret_position); |
160 | check_assist( | 160 | check_assist( |
161 | infer_function_return_type, | 161 | infer_function_return_type, |
162 | r#"fn foo() <|>{ | 162 | r#"fn foo() $0{ |
163 | 45 | 163 | 45 |
164 | }"#, | 164 | }"#, |
165 | r#"fn foo() -> i32 { | 165 | r#"fn foo() -> i32 { |
@@ -174,7 +174,7 @@ mod tests { | |||
174 | check_assist( | 174 | check_assist( |
175 | infer_function_return_type, | 175 | infer_function_return_type, |
176 | r#"fn foo() { | 176 | r#"fn foo() { |
177 | || <|>45 | 177 | || $045 |
178 | }"#, | 178 | }"#, |
179 | r#"fn foo() { | 179 | r#"fn foo() { |
180 | || -> i32 {45} | 180 | || -> i32 {45} |
@@ -188,7 +188,7 @@ mod tests { | |||
188 | check_assist( | 188 | check_assist( |
189 | infer_function_return_type, | 189 | infer_function_return_type, |
190 | r#"fn foo() { | 190 | r#"fn foo() { |
191 | 45<|> | 191 | 45$0 |
192 | }"#, | 192 | }"#, |
193 | r#"fn foo() -> i32 { | 193 | r#"fn foo() -> i32 { |
194 | 45 | 194 | 45 |
@@ -202,7 +202,7 @@ mod tests { | |||
202 | infer_function_return_type, | 202 | infer_function_return_type, |
203 | r#"fn foo() { | 203 | r#"fn foo() { |
204 | if true { | 204 | if true { |
205 | 3<|> | 205 | 3$0 |
206 | } else { | 206 | } else { |
207 | 5 | 207 | 5 |
208 | } | 208 | } |
@@ -223,7 +223,7 @@ mod tests { | |||
223 | check_assist_not_applicable( | 223 | check_assist_not_applicable( |
224 | infer_function_return_type, | 224 | infer_function_return_type, |
225 | r#"fn foo() -> i32 { | 225 | r#"fn foo() -> i32 { |
226 | ( 45<|> + 32 ) * 123 | 226 | ( 45$0 + 32 ) * 123 |
227 | }"#, | 227 | }"#, |
228 | ); | 228 | ); |
229 | } | 229 | } |
@@ -233,7 +233,7 @@ mod tests { | |||
233 | check_assist_not_applicable( | 233 | check_assist_not_applicable( |
234 | infer_function_return_type, | 234 | infer_function_return_type, |
235 | r#"fn foo() { | 235 | r#"fn foo() { |
236 | let x = <|>3; | 236 | let x = $03; |
237 | ( 45 + 32 ) * 123 | 237 | ( 45 + 32 ) * 123 |
238 | }"#, | 238 | }"#, |
239 | ); | 239 | ); |
@@ -244,7 +244,7 @@ mod tests { | |||
244 | check_assist_not_applicable( | 244 | check_assist_not_applicable( |
245 | infer_function_return_type, | 245 | infer_function_return_type, |
246 | r#"fn foo() { | 246 | r#"fn foo() { |
247 | (<|>) | 247 | ($0) |
248 | }"#, | 248 | }"#, |
249 | ); | 249 | ); |
250 | } | 250 | } |
@@ -256,7 +256,7 @@ mod tests { | |||
256 | infer_function_return_type, | 256 | infer_function_return_type, |
257 | r#"fn foo() { | 257 | r#"fn foo() { |
258 | |x: i32| { | 258 | |x: i32| { |
259 | x<|> | 259 | x$0 |
260 | }; | 260 | }; |
261 | }"#, | 261 | }"#, |
262 | r#"fn foo() { | 262 | r#"fn foo() { |
@@ -272,7 +272,7 @@ mod tests { | |||
272 | check_assist( | 272 | check_assist( |
273 | infer_function_return_type, | 273 | infer_function_return_type, |
274 | r#"fn foo() { | 274 | r#"fn foo() { |
275 | |x: i32| { x<|> }; | 275 | |x: i32| { x$0 }; |
276 | }"#, | 276 | }"#, |
277 | r#"fn foo() { | 277 | r#"fn foo() { |
278 | |x: i32| -> i32 { x }; | 278 | |x: i32| -> i32 { x }; |
@@ -286,7 +286,7 @@ mod tests { | |||
286 | check_assist( | 286 | check_assist( |
287 | infer_function_return_type, | 287 | infer_function_return_type, |
288 | r#"fn foo() { | 288 | r#"fn foo() { |
289 | |x: i32| x<|>; | 289 | |x: i32| x$0; |
290 | }"#, | 290 | }"#, |
291 | r#"fn foo() { | 291 | r#"fn foo() { |
292 | |x: i32| -> i32 {x}; | 292 | |x: i32| -> i32 {x}; |
@@ -301,7 +301,7 @@ mod tests { | |||
301 | r#"fn foo() { | 301 | r#"fn foo() { |
302 | || { | 302 | || { |
303 | if true { | 303 | if true { |
304 | 3<|> | 304 | 3$0 |
305 | } else { | 305 | } else { |
306 | 5 | 306 | 5 |
307 | } | 307 | } |
@@ -325,7 +325,7 @@ mod tests { | |||
325 | check_assist_not_applicable( | 325 | check_assist_not_applicable( |
326 | infer_function_return_type, | 326 | infer_function_return_type, |
327 | r#"fn foo() { | 327 | r#"fn foo() { |
328 | || -> i32 { 3<|> } | 328 | || -> i32 { 3$0 } |
329 | }"#, | 329 | }"#, |
330 | ); | 330 | ); |
331 | } | 331 | } |
@@ -336,7 +336,7 @@ mod tests { | |||
336 | infer_function_return_type, | 336 | infer_function_return_type, |
337 | r#"fn foo() { | 337 | r#"fn foo() { |
338 | || -> i32 { | 338 | || -> i32 { |
339 | let x = 3<|>; | 339 | let x = 3$0; |
340 | 6 | 340 | 6 |
341 | } | 341 | } |
342 | }"#, | 342 | }"#, |
diff --git a/crates/assists/src/handlers/inline_function.rs b/crates/assists/src/handlers/inline_function.rs index 6e351bdcd..6ec99b09b 100644 --- a/crates/assists/src/handlers/inline_function.rs +++ b/crates/assists/src/handlers/inline_function.rs | |||
@@ -18,7 +18,7 @@ use crate::{ | |||
18 | // ``` | 18 | // ``` |
19 | // fn add(a: u32, b: u32) -> u32 { a + b } | 19 | // fn add(a: u32, b: u32) -> u32 { a + b } |
20 | // fn main() { | 20 | // fn main() { |
21 | // let x = add<|>(1, 2); | 21 | // let x = add$0(1, 2); |
22 | // } | 22 | // } |
23 | // ``` | 23 | // ``` |
24 | // -> | 24 | // -> |
@@ -104,7 +104,7 @@ mod tests { | |||
104 | r#" | 104 | r#" |
105 | fn foo() { println!("Hello, World!"); } | 105 | fn foo() { println!("Hello, World!"); } |
106 | fn main() { | 106 | fn main() { |
107 | fo<|>o(); | 107 | fo$0o(); |
108 | } | 108 | } |
109 | "#, | 109 | "#, |
110 | r#" | 110 | r#" |
@@ -125,7 +125,7 @@ fn main() { | |||
125 | r#" | 125 | r#" |
126 | fn foo(name: String) { println!("Hello, {}!", name); } | 126 | fn foo(name: String) { println!("Hello, {}!", name); } |
127 | fn main() { | 127 | fn main() { |
128 | foo<|>(String::from("Michael")); | 128 | foo$0(String::from("Michael")); |
129 | } | 129 | } |
130 | "#, | 130 | "#, |
131 | r#" | 131 | r#" |
@@ -148,7 +148,7 @@ fn main() { | |||
148 | struct Foo; | 148 | struct Foo; |
149 | impl Foo { fn bar(&self) {} } | 149 | impl Foo { fn bar(&self) {} } |
150 | 150 | ||
151 | fn main() { Foo.bar<|>(); } | 151 | fn main() { Foo.bar$0(); } |
152 | ", | 152 | ", |
153 | ); | 153 | ); |
154 | } | 154 | } |
@@ -160,7 +160,7 @@ fn main() { Foo.bar<|>(); } | |||
160 | inline_function, | 160 | inline_function, |
161 | r#" | 161 | r#" |
162 | fn add(a: u32, b: u32) -> u32 { a + b } | 162 | fn add(a: u32, b: u32) -> u32 { a + b } |
163 | fn main() { let x = add<|>(42); } | 163 | fn main() { let x = add$0(42); } |
164 | "#, | 164 | "#, |
165 | ); | 165 | ); |
166 | } | 166 | } |
@@ -177,7 +177,7 @@ fn foo(a: u32, b: u32) -> u32 { | |||
177 | } | 177 | } |
178 | 178 | ||
179 | fn main() { | 179 | fn main() { |
180 | let x = foo<|>(1, 2); | 180 | let x = foo$0(1, 2); |
181 | } | 181 | } |
182 | "#, | 182 | "#, |
183 | r#" | 183 | r#" |
diff --git a/crates/assists/src/handlers/inline_local_variable.rs b/crates/assists/src/handlers/inline_local_variable.rs index 587eb5feb..dc798daaa 100644 --- a/crates/assists/src/handlers/inline_local_variable.rs +++ b/crates/assists/src/handlers/inline_local_variable.rs | |||
@@ -1,4 +1,7 @@ | |||
1 | use ide_db::{defs::Definition, search::ReferenceKind}; | 1 | use ide_db::{ |
2 | defs::Definition, | ||
3 | search::{FileReference, ReferenceKind}, | ||
4 | }; | ||
2 | use syntax::{ | 5 | use syntax::{ |
3 | ast::{self, AstNode, AstToken}, | 6 | ast::{self, AstNode, AstToken}, |
4 | TextRange, | 7 | TextRange, |
@@ -16,7 +19,7 @@ use crate::{ | |||
16 | // | 19 | // |
17 | // ``` | 20 | // ``` |
18 | // fn main() { | 21 | // fn main() { |
19 | // let x<|> = 1 + 2; | 22 | // let x$0 = 1 + 2; |
20 | // x * 4; | 23 | // x * 4; |
21 | // } | 24 | // } |
22 | // ``` | 25 | // ``` |
@@ -44,8 +47,8 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> O | |||
44 | 47 | ||
45 | let def = ctx.sema.to_def(&bind_pat)?; | 48 | let def = ctx.sema.to_def(&bind_pat)?; |
46 | let def = Definition::Local(def); | 49 | let def = Definition::Local(def); |
47 | let refs = def.usages(&ctx.sema).all(); | 50 | let usages = def.usages(&ctx.sema).all(); |
48 | if refs.is_empty() { | 51 | if usages.is_empty() { |
49 | mark::hit!(test_not_applicable_if_variable_unused); | 52 | mark::hit!(test_not_applicable_if_variable_unused); |
50 | return None; | 53 | return None; |
51 | }; | 54 | }; |
@@ -63,48 +66,45 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> O | |||
63 | let_stmt.syntax().text_range() | 66 | let_stmt.syntax().text_range() |
64 | }; | 67 | }; |
65 | 68 | ||
66 | let mut wrap_in_parens = vec![true; refs.len()]; | 69 | let wrap_in_parens = usages |
67 | 70 | .references | |
68 | for (i, desc) in refs.iter().enumerate() { | 71 | .values() |
69 | let usage_node = ctx | 72 | .flatten() |
70 | .covering_node_for_range(desc.file_range.range) | 73 | .map(|&FileReference { range, .. }| { |
71 | .ancestors() | 74 | let usage_node = |
72 | .find_map(ast::PathExpr::cast)?; | 75 | ctx.covering_node_for_range(range).ancestors().find_map(ast::PathExpr::cast)?; |
73 | let usage_parent_option = usage_node.syntax().parent().and_then(ast::Expr::cast); | 76 | let usage_parent_option = usage_node.syntax().parent().and_then(ast::Expr::cast); |
74 | let usage_parent = match usage_parent_option { | 77 | let usage_parent = match usage_parent_option { |
75 | Some(u) => u, | 78 | Some(u) => u, |
76 | None => { | 79 | None => return Ok(false), |
77 | wrap_in_parens[i] = false; | 80 | }; |
78 | continue; | 81 | |
79 | } | 82 | Ok(!matches!((&initializer_expr, usage_parent), |
80 | }; | 83 | (ast::Expr::CallExpr(_), _) |
81 | 84 | | (ast::Expr::IndexExpr(_), _) | |
82 | wrap_in_parens[i] = match (&initializer_expr, usage_parent) { | 85 | | (ast::Expr::MethodCallExpr(_), _) |
83 | (ast::Expr::CallExpr(_), _) | 86 | | (ast::Expr::FieldExpr(_), _) |
84 | | (ast::Expr::IndexExpr(_), _) | 87 | | (ast::Expr::TryExpr(_), _) |
85 | | (ast::Expr::MethodCallExpr(_), _) | 88 | | (ast::Expr::RefExpr(_), _) |
86 | | (ast::Expr::FieldExpr(_), _) | 89 | | (ast::Expr::Literal(_), _) |
87 | | (ast::Expr::TryExpr(_), _) | 90 | | (ast::Expr::TupleExpr(_), _) |
88 | | (ast::Expr::RefExpr(_), _) | 91 | | (ast::Expr::ArrayExpr(_), _) |
89 | | (ast::Expr::Literal(_), _) | 92 | | (ast::Expr::ParenExpr(_), _) |
90 | | (ast::Expr::TupleExpr(_), _) | 93 | | (ast::Expr::PathExpr(_), _) |
91 | | (ast::Expr::ArrayExpr(_), _) | 94 | | (ast::Expr::BlockExpr(_), _) |
92 | | (ast::Expr::ParenExpr(_), _) | 95 | | (ast::Expr::EffectExpr(_), _) |
93 | | (ast::Expr::PathExpr(_), _) | 96 | | (_, ast::Expr::CallExpr(_)) |
94 | | (ast::Expr::BlockExpr(_), _) | 97 | | (_, ast::Expr::TupleExpr(_)) |
95 | | (ast::Expr::EffectExpr(_), _) | 98 | | (_, ast::Expr::ArrayExpr(_)) |
96 | | (_, ast::Expr::CallExpr(_)) | 99 | | (_, ast::Expr::ParenExpr(_)) |
97 | | (_, ast::Expr::TupleExpr(_)) | 100 | | (_, ast::Expr::ForExpr(_)) |
98 | | (_, ast::Expr::ArrayExpr(_)) | 101 | | (_, ast::Expr::WhileExpr(_)) |
99 | | (_, ast::Expr::ParenExpr(_)) | 102 | | (_, ast::Expr::BreakExpr(_)) |
100 | | (_, ast::Expr::ForExpr(_)) | 103 | | (_, ast::Expr::ReturnExpr(_)) |
101 | | (_, ast::Expr::WhileExpr(_)) | 104 | | (_, ast::Expr::MatchExpr(_)) |
102 | | (_, ast::Expr::BreakExpr(_)) | 105 | )) |
103 | | (_, ast::Expr::ReturnExpr(_)) | 106 | }) |
104 | | (_, ast::Expr::MatchExpr(_)) => false, | 107 | .collect::<Result<Vec<_>, _>>()?; |
105 | _ => true, | ||
106 | }; | ||
107 | } | ||
108 | 108 | ||
109 | let init_str = initializer_expr.syntax().text().to_string(); | 109 | let init_str = initializer_expr.syntax().text().to_string(); |
110 | let init_in_paren = format!("({})", &init_str); | 110 | let init_in_paren = format!("({})", &init_str); |
@@ -116,15 +116,16 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> O | |||
116 | target, | 116 | target, |
117 | move |builder| { | 117 | move |builder| { |
118 | builder.delete(delete_range); | 118 | builder.delete(delete_range); |
119 | for (desc, should_wrap) in refs.iter().zip(wrap_in_parens) { | 119 | for (reference, should_wrap) in usages.references.values().flatten().zip(wrap_in_parens) |
120 | { | ||
120 | let replacement = | 121 | let replacement = |
121 | if should_wrap { init_in_paren.clone() } else { init_str.clone() }; | 122 | if should_wrap { init_in_paren.clone() } else { init_str.clone() }; |
122 | match desc.kind { | 123 | match reference.kind { |
123 | ReferenceKind::FieldShorthandForLocal => { | 124 | ReferenceKind::FieldShorthandForLocal => { |
124 | mark::hit!(inline_field_shorthand); | 125 | mark::hit!(inline_field_shorthand); |
125 | builder.insert(desc.file_range.range.end(), format!(": {}", replacement)) | 126 | builder.insert(reference.range.end(), format!(": {}", replacement)) |
126 | } | 127 | } |
127 | _ => builder.replace(desc.file_range.range, replacement), | 128 | _ => builder.replace(reference.range, replacement), |
128 | } | 129 | } |
129 | } | 130 | } |
130 | }, | 131 | }, |
@@ -146,7 +147,7 @@ mod tests { | |||
146 | r" | 147 | r" |
147 | fn bar(a: usize) {} | 148 | fn bar(a: usize) {} |
148 | fn foo() { | 149 | fn foo() { |
149 | let a<|> = 1; | 150 | let a$0 = 1; |
150 | a + 1; | 151 | a + 1; |
151 | if a > 10 { | 152 | if a > 10 { |
152 | } | 153 | } |
@@ -180,7 +181,7 @@ fn foo() { | |||
180 | r" | 181 | r" |
181 | fn bar(a: usize) {} | 182 | fn bar(a: usize) {} |
182 | fn foo() { | 183 | fn foo() { |
183 | let a<|> = 1 + 1; | 184 | let a$0 = 1 + 1; |
184 | a + 1; | 185 | a + 1; |
185 | if a > 10 { | 186 | if a > 10 { |
186 | } | 187 | } |
@@ -214,7 +215,7 @@ fn foo() { | |||
214 | r" | 215 | r" |
215 | fn bar(a: usize) {} | 216 | fn bar(a: usize) {} |
216 | fn foo() { | 217 | fn foo() { |
217 | let a<|> = bar(1); | 218 | let a$0 = bar(1); |
218 | a + 1; | 219 | a + 1; |
219 | if a > 10 { | 220 | if a > 10 { |
220 | } | 221 | } |
@@ -248,7 +249,7 @@ fn foo() { | |||
248 | r" | 249 | r" |
249 | fn bar(a: usize): usize { a } | 250 | fn bar(a: usize): usize { a } |
250 | fn foo() { | 251 | fn foo() { |
251 | let a<|> = bar(1) as u64; | 252 | let a$0 = bar(1) as u64; |
252 | a + 1; | 253 | a + 1; |
253 | if a > 10 { | 254 | if a > 10 { |
254 | } | 255 | } |
@@ -281,7 +282,7 @@ fn foo() { | |||
281 | inline_local_variable, | 282 | inline_local_variable, |
282 | r" | 283 | r" |
283 | fn foo() { | 284 | fn foo() { |
284 | let a<|> = { 10 + 1 }; | 285 | let a$0 = { 10 + 1 }; |
285 | a + 1; | 286 | a + 1; |
286 | if a > 10 { | 287 | if a > 10 { |
287 | } | 288 | } |
@@ -313,7 +314,7 @@ fn foo() { | |||
313 | inline_local_variable, | 314 | inline_local_variable, |
314 | r" | 315 | r" |
315 | fn foo() { | 316 | fn foo() { |
316 | let a<|> = ( 10 + 1 ); | 317 | let a$0 = ( 10 + 1 ); |
317 | a + 1; | 318 | a + 1; |
318 | if a > 10 { | 319 | if a > 10 { |
319 | } | 320 | } |
@@ -346,7 +347,7 @@ fn foo() { | |||
346 | inline_local_variable, | 347 | inline_local_variable, |
347 | r" | 348 | r" |
348 | fn foo() { | 349 | fn foo() { |
349 | let mut a<|> = 1 + 1; | 350 | let mut a$0 = 1 + 1; |
350 | a + 1; | 351 | a + 1; |
351 | }", | 352 | }", |
352 | ); | 353 | ); |
@@ -358,7 +359,7 @@ fn foo() { | |||
358 | inline_local_variable, | 359 | inline_local_variable, |
359 | r" | 360 | r" |
360 | fn foo() { | 361 | fn foo() { |
361 | let a<|> = bar(10 + 1); | 362 | let a$0 = bar(10 + 1); |
362 | let b = a * 10; | 363 | let b = a * 10; |
363 | let c = a as usize; | 364 | let c = a as usize; |
364 | }", | 365 | }", |
@@ -377,7 +378,7 @@ fn foo() { | |||
377 | r" | 378 | r" |
378 | fn foo() { | 379 | fn foo() { |
379 | let x = vec![1, 2, 3]; | 380 | let x = vec![1, 2, 3]; |
380 | let a<|> = x[0]; | 381 | let a$0 = x[0]; |
381 | let b = a * 10; | 382 | let b = a * 10; |
382 | let c = a as usize; | 383 | let c = a as usize; |
383 | }", | 384 | }", |
@@ -397,7 +398,7 @@ fn foo() { | |||
397 | r" | 398 | r" |
398 | fn foo() { | 399 | fn foo() { |
399 | let bar = vec![1]; | 400 | let bar = vec![1]; |
400 | let a<|> = bar.len(); | 401 | let a$0 = bar.len(); |
401 | let b = a * 10; | 402 | let b = a * 10; |
402 | let c = a as usize; | 403 | let c = a as usize; |
403 | }", | 404 | }", |
@@ -421,7 +422,7 @@ struct Bar { | |||
421 | 422 | ||
422 | fn foo() { | 423 | fn foo() { |
423 | let bar = Bar { foo: 1 }; | 424 | let bar = Bar { foo: 1 }; |
424 | let a<|> = bar.foo; | 425 | let a$0 = bar.foo; |
425 | let b = a * 10; | 426 | let b = a * 10; |
426 | let c = a as usize; | 427 | let c = a as usize; |
427 | }", | 428 | }", |
@@ -445,7 +446,7 @@ fn foo() { | |||
445 | r" | 446 | r" |
446 | fn foo() -> Option<usize> { | 447 | fn foo() -> Option<usize> { |
447 | let bar = Some(1); | 448 | let bar = Some(1); |
448 | let a<|> = bar?; | 449 | let a$0 = bar?; |
449 | let b = a * 10; | 450 | let b = a * 10; |
450 | let c = a as usize; | 451 | let c = a as usize; |
451 | None | 452 | None |
@@ -467,7 +468,7 @@ fn foo() -> Option<usize> { | |||
467 | r" | 468 | r" |
468 | fn foo() { | 469 | fn foo() { |
469 | let bar = 10; | 470 | let bar = 10; |
470 | let a<|> = &bar; | 471 | let a$0 = &bar; |
471 | let b = a * 10; | 472 | let b = a * 10; |
472 | }", | 473 | }", |
473 | r" | 474 | r" |
@@ -484,7 +485,7 @@ fn foo() { | |||
484 | inline_local_variable, | 485 | inline_local_variable, |
485 | r" | 486 | r" |
486 | fn foo() { | 487 | fn foo() { |
487 | let a<|> = (10, 20); | 488 | let a$0 = (10, 20); |
488 | let b = a[0]; | 489 | let b = a[0]; |
489 | }", | 490 | }", |
490 | r" | 491 | r" |
@@ -500,7 +501,7 @@ fn foo() { | |||
500 | inline_local_variable, | 501 | inline_local_variable, |
501 | r" | 502 | r" |
502 | fn foo() { | 503 | fn foo() { |
503 | let a<|> = [1, 2, 3]; | 504 | let a$0 = [1, 2, 3]; |
504 | let b = a.len(); | 505 | let b = a.len(); |
505 | }", | 506 | }", |
506 | r" | 507 | r" |
@@ -516,7 +517,7 @@ fn foo() { | |||
516 | inline_local_variable, | 517 | inline_local_variable, |
517 | r" | 518 | r" |
518 | fn foo() { | 519 | fn foo() { |
519 | let a<|> = (10 + 20); | 520 | let a$0 = (10 + 20); |
520 | let b = a * 10; | 521 | let b = a * 10; |
521 | let c = a as usize; | 522 | let c = a as usize; |
522 | }", | 523 | }", |
@@ -535,7 +536,7 @@ fn foo() { | |||
535 | r" | 536 | r" |
536 | fn foo() { | 537 | fn foo() { |
537 | let d = 10; | 538 | let d = 10; |
538 | let a<|> = d; | 539 | let a$0 = d; |
539 | let b = a * 10; | 540 | let b = a * 10; |
540 | let c = a as usize; | 541 | let c = a as usize; |
541 | }", | 542 | }", |
@@ -554,7 +555,7 @@ fn foo() { | |||
554 | inline_local_variable, | 555 | inline_local_variable, |
555 | r" | 556 | r" |
556 | fn foo() { | 557 | fn foo() { |
557 | let a<|> = { 10 }; | 558 | let a$0 = { 10 }; |
558 | let b = a * 10; | 559 | let b = a * 10; |
559 | let c = a as usize; | 560 | let c = a as usize; |
560 | }", | 561 | }", |
@@ -572,7 +573,7 @@ fn foo() { | |||
572 | inline_local_variable, | 573 | inline_local_variable, |
573 | r" | 574 | r" |
574 | fn foo() { | 575 | fn foo() { |
575 | let a<|> = 10 + 20; | 576 | let a$0 = 10 + 20; |
576 | let b = a * 10; | 577 | let b = a * 10; |
577 | let c = (a, 20); | 578 | let c = (a, 20); |
578 | let d = [a, 10]; | 579 | let d = [a, 10]; |
@@ -594,7 +595,7 @@ fn foo() { | |||
594 | inline_local_variable, | 595 | inline_local_variable, |
595 | r" | 596 | r" |
596 | fn foo() { | 597 | fn foo() { |
597 | let a<|> = vec![10, 20]; | 598 | let a$0 = vec![10, 20]; |
598 | for i in a {} | 599 | for i in a {} |
599 | }", | 600 | }", |
600 | r" | 601 | r" |
@@ -610,7 +611,7 @@ fn foo() { | |||
610 | inline_local_variable, | 611 | inline_local_variable, |
611 | r" | 612 | r" |
612 | fn foo() { | 613 | fn foo() { |
613 | let a<|> = 1 > 0; | 614 | let a$0 = 1 > 0; |
614 | while a {} | 615 | while a {} |
615 | }", | 616 | }", |
616 | r" | 617 | r" |
@@ -626,7 +627,7 @@ fn foo() { | |||
626 | inline_local_variable, | 627 | inline_local_variable, |
627 | r" | 628 | r" |
628 | fn foo() { | 629 | fn foo() { |
629 | let a<|> = 1 + 1; | 630 | let a$0 = 1 + 1; |
630 | loop { | 631 | loop { |
631 | break a; | 632 | break a; |
632 | } | 633 | } |
@@ -646,7 +647,7 @@ fn foo() { | |||
646 | inline_local_variable, | 647 | inline_local_variable, |
647 | r" | 648 | r" |
648 | fn foo() { | 649 | fn foo() { |
649 | let a<|> = 1 > 0; | 650 | let a$0 = 1 > 0; |
650 | return a; | 651 | return a; |
651 | }", | 652 | }", |
652 | r" | 653 | r" |
@@ -662,7 +663,7 @@ fn foo() { | |||
662 | inline_local_variable, | 663 | inline_local_variable, |
663 | r" | 664 | r" |
664 | fn foo() { | 665 | fn foo() { |
665 | let a<|> = 1 > 0; | 666 | let a$0 = 1 > 0; |
666 | match a {} | 667 | match a {} |
667 | }", | 668 | }", |
668 | r" | 669 | r" |
@@ -680,7 +681,7 @@ fn foo() { | |||
680 | r" | 681 | r" |
681 | struct S { foo: i32} | 682 | struct S { foo: i32} |
682 | fn main() { | 683 | fn main() { |
683 | let <|>foo = 92; | 684 | let $0foo = 92; |
684 | S { foo } | 685 | S { foo } |
685 | } | 686 | } |
686 | ", | 687 | ", |
@@ -700,7 +701,7 @@ fn main() { | |||
700 | inline_local_variable, | 701 | inline_local_variable, |
701 | r" | 702 | r" |
702 | fn foo() { | 703 | fn foo() { |
703 | let <|>a = 0; | 704 | let $0a = 0; |
704 | } | 705 | } |
705 | ", | 706 | ", |
706 | ) | 707 | ) |
@@ -713,7 +714,7 @@ fn foo() { | |||
713 | inline_local_variable, | 714 | inline_local_variable, |
714 | r" | 715 | r" |
715 | fn main() { | 716 | fn main() { |
716 | let x = <|>1 + 2; | 717 | let x = $01 + 2; |
717 | x * 4; | 718 | x * 4; |
718 | } | 719 | } |
719 | ", | 720 | ", |
diff --git a/crates/assists/src/handlers/introduce_named_lifetime.rs b/crates/assists/src/handlers/introduce_named_lifetime.rs index ab8fe3ea9..3f5f44d69 100644 --- a/crates/assists/src/handlers/introduce_named_lifetime.rs +++ b/crates/assists/src/handlers/introduce_named_lifetime.rs | |||
@@ -14,7 +14,7 @@ static ASSIST_LABEL: &str = "Introduce named lifetime"; | |||
14 | // Change an anonymous lifetime to a named lifetime. | 14 | // Change an anonymous lifetime to a named lifetime. |
15 | // | 15 | // |
16 | // ``` | 16 | // ``` |
17 | // impl Cursor<'_<|>> { | 17 | // impl Cursor<'_$0> { |
18 | // fn node(self) -> &SyntaxNode { | 18 | // fn node(self) -> &SyntaxNode { |
19 | // match self { | 19 | // match self { |
20 | // Cursor::Replace(node) | Cursor::Before(node) => node, | 20 | // Cursor::Replace(node) | Cursor::Before(node) => node, |
@@ -33,7 +33,7 @@ static ASSIST_LABEL: &str = "Introduce named lifetime"; | |||
33 | // } | 33 | // } |
34 | // ``` | 34 | // ``` |
35 | // FIXME: How can we handle renaming any one of multiple anonymous lifetimes? | 35 | // FIXME: How can we handle renaming any one of multiple anonymous lifetimes? |
36 | // FIXME: should also add support for the case fun(f: &Foo) -> &<|>Foo | 36 | // FIXME: should also add support for the case fun(f: &Foo) -> &$0Foo |
37 | pub(crate) fn introduce_named_lifetime(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 37 | pub(crate) fn introduce_named_lifetime(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
38 | let lifetime = | 38 | let lifetime = |
39 | ctx.find_node_at_offset::<ast::Lifetime>().filter(|lifetime| lifetime.text() == "'_")?; | 39 | ctx.find_node_at_offset::<ast::Lifetime>().filter(|lifetime| lifetime.text() == "'_")?; |
@@ -150,7 +150,7 @@ mod tests { | |||
150 | fn test_example_case() { | 150 | fn test_example_case() { |
151 | check_assist( | 151 | check_assist( |
152 | introduce_named_lifetime, | 152 | introduce_named_lifetime, |
153 | r#"impl Cursor<'_<|>> { | 153 | r#"impl Cursor<'_$0> { |
154 | fn node(self) -> &SyntaxNode { | 154 | fn node(self) -> &SyntaxNode { |
155 | match self { | 155 | match self { |
156 | Cursor::Replace(node) | Cursor::Before(node) => node, | 156 | Cursor::Replace(node) | Cursor::Before(node) => node, |
@@ -171,7 +171,7 @@ mod tests { | |||
171 | fn test_example_case_simplified() { | 171 | fn test_example_case_simplified() { |
172 | check_assist( | 172 | check_assist( |
173 | introduce_named_lifetime, | 173 | introduce_named_lifetime, |
174 | r#"impl Cursor<'_<|>> {"#, | 174 | r#"impl Cursor<'_$0> {"#, |
175 | r#"impl<'a> Cursor<'a> {"#, | 175 | r#"impl<'a> Cursor<'a> {"#, |
176 | ); | 176 | ); |
177 | } | 177 | } |
@@ -180,7 +180,7 @@ mod tests { | |||
180 | fn test_example_case_cursor_after_tick() { | 180 | fn test_example_case_cursor_after_tick() { |
181 | check_assist( | 181 | check_assist( |
182 | introduce_named_lifetime, | 182 | introduce_named_lifetime, |
183 | r#"impl Cursor<'<|>_> {"#, | 183 | r#"impl Cursor<'$0_> {"#, |
184 | r#"impl<'a> Cursor<'a> {"#, | 184 | r#"impl<'a> Cursor<'a> {"#, |
185 | ); | 185 | ); |
186 | } | 186 | } |
@@ -189,7 +189,7 @@ mod tests { | |||
189 | fn test_impl_with_other_type_param() { | 189 | fn test_impl_with_other_type_param() { |
190 | check_assist( | 190 | check_assist( |
191 | introduce_named_lifetime, | 191 | introduce_named_lifetime, |
192 | "impl<I> fmt::Display for SepByBuilder<'_<|>, I> | 192 | "impl<I> fmt::Display for SepByBuilder<'_$0, I> |
193 | where | 193 | where |
194 | I: Iterator, | 194 | I: Iterator, |
195 | I::Item: fmt::Display, | 195 | I::Item: fmt::Display, |
@@ -206,28 +206,28 @@ mod tests { | |||
206 | fn test_example_case_cursor_before_tick() { | 206 | fn test_example_case_cursor_before_tick() { |
207 | check_assist( | 207 | check_assist( |
208 | introduce_named_lifetime, | 208 | introduce_named_lifetime, |
209 | r#"impl Cursor<<|>'_> {"#, | 209 | r#"impl Cursor<$0'_> {"#, |
210 | r#"impl<'a> Cursor<'a> {"#, | 210 | r#"impl<'a> Cursor<'a> {"#, |
211 | ); | 211 | ); |
212 | } | 212 | } |
213 | 213 | ||
214 | #[test] | 214 | #[test] |
215 | fn test_not_applicable_cursor_position() { | 215 | fn test_not_applicable_cursor_position() { |
216 | check_assist_not_applicable(introduce_named_lifetime, r#"impl Cursor<'_><|> {"#); | 216 | check_assist_not_applicable(introduce_named_lifetime, r#"impl Cursor<'_>$0 {"#); |
217 | check_assist_not_applicable(introduce_named_lifetime, r#"impl Cursor<|><'_> {"#); | 217 | check_assist_not_applicable(introduce_named_lifetime, r#"impl Cursor$0<'_> {"#); |
218 | } | 218 | } |
219 | 219 | ||
220 | #[test] | 220 | #[test] |
221 | fn test_not_applicable_lifetime_already_name() { | 221 | fn test_not_applicable_lifetime_already_name() { |
222 | check_assist_not_applicable(introduce_named_lifetime, r#"impl Cursor<'a<|>> {"#); | 222 | check_assist_not_applicable(introduce_named_lifetime, r#"impl Cursor<'a$0> {"#); |
223 | check_assist_not_applicable(introduce_named_lifetime, r#"fn my_fun<'a>() -> X<'a<|>>"#); | 223 | check_assist_not_applicable(introduce_named_lifetime, r#"fn my_fun<'a>() -> X<'a$0>"#); |
224 | } | 224 | } |
225 | 225 | ||
226 | #[test] | 226 | #[test] |
227 | fn test_with_type_parameter() { | 227 | fn test_with_type_parameter() { |
228 | check_assist( | 228 | check_assist( |
229 | introduce_named_lifetime, | 229 | introduce_named_lifetime, |
230 | r#"impl<T> Cursor<T, '_<|>>"#, | 230 | r#"impl<T> Cursor<T, '_$0>"#, |
231 | r#"impl<T, 'a> Cursor<T, 'a>"#, | 231 | r#"impl<T, 'a> Cursor<T, 'a>"#, |
232 | ); | 232 | ); |
233 | } | 233 | } |
@@ -236,7 +236,7 @@ mod tests { | |||
236 | fn test_with_existing_lifetime_name_conflict() { | 236 | fn test_with_existing_lifetime_name_conflict() { |
237 | check_assist( | 237 | check_assist( |
238 | introduce_named_lifetime, | 238 | introduce_named_lifetime, |
239 | r#"impl<'a, 'b> Cursor<'a, 'b, '_<|>>"#, | 239 | r#"impl<'a, 'b> Cursor<'a, 'b, '_$0>"#, |
240 | r#"impl<'a, 'b, 'c> Cursor<'a, 'b, 'c>"#, | 240 | r#"impl<'a, 'b, 'c> Cursor<'a, 'b, 'c>"#, |
241 | ); | 241 | ); |
242 | } | 242 | } |
@@ -245,7 +245,7 @@ mod tests { | |||
245 | fn test_function_return_value_anon_lifetime_param() { | 245 | fn test_function_return_value_anon_lifetime_param() { |
246 | check_assist( | 246 | check_assist( |
247 | introduce_named_lifetime, | 247 | introduce_named_lifetime, |
248 | r#"fn my_fun() -> X<'_<|>>"#, | 248 | r#"fn my_fun() -> X<'_$0>"#, |
249 | r#"fn my_fun<'a>() -> X<'a>"#, | 249 | r#"fn my_fun<'a>() -> X<'a>"#, |
250 | ); | 250 | ); |
251 | } | 251 | } |
@@ -254,7 +254,7 @@ mod tests { | |||
254 | fn test_function_return_value_anon_reference_lifetime() { | 254 | fn test_function_return_value_anon_reference_lifetime() { |
255 | check_assist( | 255 | check_assist( |
256 | introduce_named_lifetime, | 256 | introduce_named_lifetime, |
257 | r#"fn my_fun() -> &'_<|> X"#, | 257 | r#"fn my_fun() -> &'_$0 X"#, |
258 | r#"fn my_fun<'a>() -> &'a X"#, | 258 | r#"fn my_fun<'a>() -> &'a X"#, |
259 | ); | 259 | ); |
260 | } | 260 | } |
@@ -263,7 +263,7 @@ mod tests { | |||
263 | fn test_function_param_anon_lifetime() { | 263 | fn test_function_param_anon_lifetime() { |
264 | check_assist( | 264 | check_assist( |
265 | introduce_named_lifetime, | 265 | introduce_named_lifetime, |
266 | r#"fn my_fun(x: X<'_<|>>)"#, | 266 | r#"fn my_fun(x: X<'_$0>)"#, |
267 | r#"fn my_fun<'a>(x: X<'a>)"#, | 267 | r#"fn my_fun<'a>(x: X<'a>)"#, |
268 | ); | 268 | ); |
269 | } | 269 | } |
@@ -272,7 +272,7 @@ mod tests { | |||
272 | fn test_function_add_lifetime_to_params() { | 272 | fn test_function_add_lifetime_to_params() { |
273 | check_assist( | 273 | check_assist( |
274 | introduce_named_lifetime, | 274 | introduce_named_lifetime, |
275 | r#"fn my_fun(f: &Foo) -> X<'_<|>>"#, | 275 | r#"fn my_fun(f: &Foo) -> X<'_$0>"#, |
276 | r#"fn my_fun<'a>(f: &'a Foo) -> X<'a>"#, | 276 | r#"fn my_fun<'a>(f: &'a Foo) -> X<'a>"#, |
277 | ); | 277 | ); |
278 | } | 278 | } |
@@ -281,7 +281,7 @@ mod tests { | |||
281 | fn test_function_add_lifetime_to_params_in_presence_of_other_lifetime() { | 281 | fn test_function_add_lifetime_to_params_in_presence_of_other_lifetime() { |
282 | check_assist( | 282 | check_assist( |
283 | introduce_named_lifetime, | 283 | introduce_named_lifetime, |
284 | r#"fn my_fun<'other>(f: &Foo, b: &'other Bar) -> X<'_<|>>"#, | 284 | r#"fn my_fun<'other>(f: &Foo, b: &'other Bar) -> X<'_$0>"#, |
285 | r#"fn my_fun<'other, 'a>(f: &'a Foo, b: &'other Bar) -> X<'a>"#, | 285 | r#"fn my_fun<'other, 'a>(f: &'a Foo, b: &'other Bar) -> X<'a>"#, |
286 | ); | 286 | ); |
287 | } | 287 | } |
@@ -291,7 +291,7 @@ mod tests { | |||
291 | // this is not permitted under lifetime elision rules | 291 | // this is not permitted under lifetime elision rules |
292 | check_assist_not_applicable( | 292 | check_assist_not_applicable( |
293 | introduce_named_lifetime, | 293 | introduce_named_lifetime, |
294 | r#"fn my_fun(f: &Foo, b: &Bar) -> X<'_<|>>"#, | 294 | r#"fn my_fun(f: &Foo, b: &Bar) -> X<'_$0>"#, |
295 | ); | 295 | ); |
296 | } | 296 | } |
297 | 297 | ||
@@ -299,7 +299,7 @@ mod tests { | |||
299 | fn test_function_add_lifetime_to_self_ref_param() { | 299 | fn test_function_add_lifetime_to_self_ref_param() { |
300 | check_assist( | 300 | check_assist( |
301 | introduce_named_lifetime, | 301 | introduce_named_lifetime, |
302 | r#"fn my_fun<'other>(&self, f: &Foo, b: &'other Bar) -> X<'_<|>>"#, | 302 | r#"fn my_fun<'other>(&self, f: &Foo, b: &'other Bar) -> X<'_$0>"#, |
303 | r#"fn my_fun<'other, 'a>(&'a self, f: &Foo, b: &'other Bar) -> X<'a>"#, | 303 | r#"fn my_fun<'other, 'a>(&'a self, f: &Foo, b: &'other Bar) -> X<'a>"#, |
304 | ); | 304 | ); |
305 | } | 305 | } |
@@ -308,7 +308,7 @@ mod tests { | |||
308 | fn test_function_add_lifetime_to_param_with_non_ref_self() { | 308 | fn test_function_add_lifetime_to_param_with_non_ref_self() { |
309 | check_assist( | 309 | check_assist( |
310 | introduce_named_lifetime, | 310 | introduce_named_lifetime, |
311 | r#"fn my_fun<'other>(self, f: &Foo, b: &'other Bar) -> X<'_<|>>"#, | 311 | r#"fn my_fun<'other>(self, f: &Foo, b: &'other Bar) -> X<'_$0>"#, |
312 | r#"fn my_fun<'other, 'a>(self, f: &'a Foo, b: &'other Bar) -> X<'a>"#, | 312 | r#"fn my_fun<'other, 'a>(self, f: &'a Foo, b: &'other Bar) -> X<'a>"#, |
313 | ); | 313 | ); |
314 | } | 314 | } |
diff --git a/crates/assists/src/handlers/invert_if.rs b/crates/assists/src/handlers/invert_if.rs index f9c33b3f7..5b69dafd4 100644 --- a/crates/assists/src/handlers/invert_if.rs +++ b/crates/assists/src/handlers/invert_if.rs | |||
@@ -18,7 +18,7 @@ use crate::{ | |||
18 | // | 18 | // |
19 | // ``` | 19 | // ``` |
20 | // fn main() { | 20 | // fn main() { |
21 | // if<|> !y { A } else { B } | 21 | // if$0 !y { A } else { B } |
22 | // } | 22 | // } |
23 | // ``` | 23 | // ``` |
24 | // -> | 24 | // -> |
@@ -72,7 +72,7 @@ mod tests { | |||
72 | fn invert_if_composite_condition() { | 72 | fn invert_if_composite_condition() { |
73 | check_assist( | 73 | check_assist( |
74 | invert_if, | 74 | invert_if, |
75 | "fn f() { i<|>f x == 3 || x == 4 || x == 5 { 1 } else { 3 * 2 } }", | 75 | "fn f() { i$0f x == 3 || x == 4 || x == 5 { 1 } else { 3 * 2 } }", |
76 | "fn f() { if !(x == 3 || x == 4 || x == 5) { 3 * 2 } else { 1 } }", | 76 | "fn f() { if !(x == 3 || x == 4 || x == 5) { 3 * 2 } else { 1 } }", |
77 | ) | 77 | ) |
78 | } | 78 | } |
@@ -81,7 +81,7 @@ mod tests { | |||
81 | fn invert_if_remove_not_parentheses() { | 81 | fn invert_if_remove_not_parentheses() { |
82 | check_assist( | 82 | check_assist( |
83 | invert_if, | 83 | invert_if, |
84 | "fn f() { i<|>f !(x == 3 || x == 4 || x == 5) { 3 * 2 } else { 1 } }", | 84 | "fn f() { i$0f !(x == 3 || x == 4 || x == 5) { 3 * 2 } else { 1 } }", |
85 | "fn f() { if x == 3 || x == 4 || x == 5 { 1 } else { 3 * 2 } }", | 85 | "fn f() { if x == 3 || x == 4 || x == 5 { 1 } else { 3 * 2 } }", |
86 | ) | 86 | ) |
87 | } | 87 | } |
@@ -90,7 +90,7 @@ mod tests { | |||
90 | fn invert_if_remove_inequality() { | 90 | fn invert_if_remove_inequality() { |
91 | check_assist( | 91 | check_assist( |
92 | invert_if, | 92 | invert_if, |
93 | "fn f() { i<|>f x != 3 { 1 } else { 3 + 2 } }", | 93 | "fn f() { i$0f x != 3 { 1 } else { 3 + 2 } }", |
94 | "fn f() { if x == 3 { 3 + 2 } else { 1 } }", | 94 | "fn f() { if x == 3 { 3 + 2 } else { 1 } }", |
95 | ) | 95 | ) |
96 | } | 96 | } |
@@ -99,7 +99,7 @@ mod tests { | |||
99 | fn invert_if_remove_not() { | 99 | fn invert_if_remove_not() { |
100 | check_assist( | 100 | check_assist( |
101 | invert_if, | 101 | invert_if, |
102 | "fn f() { <|>if !cond { 3 * 2 } else { 1 } }", | 102 | "fn f() { $0if !cond { 3 * 2 } else { 1 } }", |
103 | "fn f() { if cond { 1 } else { 3 * 2 } }", | 103 | "fn f() { if cond { 1 } else { 3 * 2 } }", |
104 | ) | 104 | ) |
105 | } | 105 | } |
@@ -108,21 +108,21 @@ mod tests { | |||
108 | fn invert_if_general_case() { | 108 | fn invert_if_general_case() { |
109 | check_assist( | 109 | check_assist( |
110 | invert_if, | 110 | invert_if, |
111 | "fn f() { i<|>f cond { 3 * 2 } else { 1 } }", | 111 | "fn f() { i$0f cond { 3 * 2 } else { 1 } }", |
112 | "fn f() { if !cond { 1 } else { 3 * 2 } }", | 112 | "fn f() { if !cond { 1 } else { 3 * 2 } }", |
113 | ) | 113 | ) |
114 | } | 114 | } |
115 | 115 | ||
116 | #[test] | 116 | #[test] |
117 | fn invert_if_doesnt_apply_with_cursor_not_on_if() { | 117 | fn invert_if_doesnt_apply_with_cursor_not_on_if() { |
118 | check_assist_not_applicable(invert_if, "fn f() { if !<|>cond { 3 * 2 } else { 1 } }") | 118 | check_assist_not_applicable(invert_if, "fn f() { if !$0cond { 3 * 2 } else { 1 } }") |
119 | } | 119 | } |
120 | 120 | ||
121 | #[test] | 121 | #[test] |
122 | fn invert_if_doesnt_apply_with_if_let() { | 122 | fn invert_if_doesnt_apply_with_if_let() { |
123 | check_assist_not_applicable( | 123 | check_assist_not_applicable( |
124 | invert_if, | 124 | invert_if, |
125 | "fn f() { i<|>f let Some(_) = Some(1) { 1 } else { 0 } }", | 125 | "fn f() { i$0f let Some(_) = Some(1) { 1 } else { 0 } }", |
126 | ) | 126 | ) |
127 | } | 127 | } |
128 | 128 | ||
@@ -130,7 +130,7 @@ mod tests { | |||
130 | fn invert_if_option_case() { | 130 | fn invert_if_option_case() { |
131 | check_assist( | 131 | check_assist( |
132 | invert_if, | 132 | invert_if, |
133 | "fn f() { if<|> doc_style.is_some() { Class::DocComment } else { Class::Comment } }", | 133 | "fn f() { if$0 doc_style.is_some() { Class::DocComment } else { Class::Comment } }", |
134 | "fn f() { if doc_style.is_none() { Class::Comment } else { Class::DocComment } }", | 134 | "fn f() { if doc_style.is_none() { Class::Comment } else { Class::DocComment } }", |
135 | ) | 135 | ) |
136 | } | 136 | } |
@@ -139,7 +139,7 @@ mod tests { | |||
139 | fn invert_if_result_case() { | 139 | fn invert_if_result_case() { |
140 | check_assist( | 140 | check_assist( |
141 | invert_if, | 141 | invert_if, |
142 | "fn f() { i<|>f doc_style.is_err() { Class::Err } else { Class::Ok } }", | 142 | "fn f() { i$0f doc_style.is_err() { Class::Err } else { Class::Ok } }", |
143 | "fn f() { if doc_style.is_ok() { Class::Ok } else { Class::Err } }", | 143 | "fn f() { if doc_style.is_ok() { Class::Ok } else { Class::Err } }", |
144 | ) | 144 | ) |
145 | } | 145 | } |
diff --git a/crates/assists/src/handlers/merge_imports.rs b/crates/assists/src/handlers/merge_imports.rs index 2f0dc7831..7bd7e1e36 100644 --- a/crates/assists/src/handlers/merge_imports.rs +++ b/crates/assists/src/handlers/merge_imports.rs | |||
@@ -15,7 +15,7 @@ use crate::{ | |||
15 | // Merges two imports with a common prefix. | 15 | // Merges two imports with a common prefix. |
16 | // | 16 | // |
17 | // ``` | 17 | // ``` |
18 | // use std::<|>fmt::Formatter; | 18 | // use std::$0fmt::Formatter; |
19 | // use std::io; | 19 | // use std::io; |
20 | // ``` | 20 | // ``` |
21 | // -> | 21 | // -> |
@@ -75,7 +75,7 @@ mod tests { | |||
75 | check_assist( | 75 | check_assist( |
76 | merge_imports, | 76 | merge_imports, |
77 | r" | 77 | r" |
78 | use std::fmt<|>::{Display, Debug}; | 78 | use std::fmt$0::{Display, Debug}; |
79 | use std::fmt::{Display, Debug}; | 79 | use std::fmt::{Display, Debug}; |
80 | ", | 80 | ", |
81 | r" | 81 | r" |
@@ -89,7 +89,7 @@ use std::fmt::{Debug, Display}; | |||
89 | check_assist( | 89 | check_assist( |
90 | merge_imports, | 90 | merge_imports, |
91 | r" | 91 | r" |
92 | use std::fmt<|>::Debug; | 92 | use std::fmt$0::Debug; |
93 | use std::fmt::Display; | 93 | use std::fmt::Display; |
94 | ", | 94 | ", |
95 | r" | 95 | r" |
@@ -104,7 +104,7 @@ use std::fmt::{Debug, Display}; | |||
104 | merge_imports, | 104 | merge_imports, |
105 | r" | 105 | r" |
106 | use std::fmt::Debug; | 106 | use std::fmt::Debug; |
107 | use std::fmt<|>::Display; | 107 | use std::fmt$0::Display; |
108 | ", | 108 | ", |
109 | r" | 109 | r" |
110 | use std::fmt::{Debug, Display}; | 110 | use std::fmt::{Debug, Display}; |
@@ -117,7 +117,7 @@ use std::fmt::{Debug, Display}; | |||
117 | check_assist( | 117 | check_assist( |
118 | merge_imports, | 118 | merge_imports, |
119 | r" | 119 | r" |
120 | use std::fmt<|>; | 120 | use std::fmt$0; |
121 | use std::fmt::Display; | 121 | use std::fmt::Display; |
122 | ", | 122 | ", |
123 | r" | 123 | r" |
@@ -131,7 +131,7 @@ use std::fmt::{self, Display}; | |||
131 | check_assist( | 131 | check_assist( |
132 | merge_imports, | 132 | merge_imports, |
133 | r" | 133 | r" |
134 | use std::{fmt, <|>fmt::Display}; | 134 | use std::{fmt, $0fmt::Display}; |
135 | ", | 135 | ", |
136 | r" | 136 | r" |
137 | use std::{fmt::{self, Display}}; | 137 | use std::{fmt::{self, Display}}; |
@@ -144,7 +144,7 @@ use std::{fmt::{self, Display}}; | |||
144 | check_assist_not_applicable( | 144 | check_assist_not_applicable( |
145 | merge_imports, | 145 | merge_imports, |
146 | r" | 146 | r" |
147 | pub use std::fmt<|>::Debug; | 147 | pub use std::fmt$0::Debug; |
148 | use std::fmt::Display; | 148 | use std::fmt::Display; |
149 | ", | 149 | ", |
150 | ); | 150 | ); |
@@ -155,7 +155,7 @@ use std::fmt::Display; | |||
155 | check_assist_not_applicable( | 155 | check_assist_not_applicable( |
156 | merge_imports, | 156 | merge_imports, |
157 | r" | 157 | r" |
158 | use std::fmt<|>::Debug; | 158 | use std::fmt$0::Debug; |
159 | pub use std::fmt::Display; | 159 | pub use std::fmt::Display; |
160 | ", | 160 | ", |
161 | ); | 161 | ); |
@@ -166,7 +166,7 @@ pub use std::fmt::Display; | |||
166 | check_assist_not_applicable( | 166 | check_assist_not_applicable( |
167 | merge_imports, | 167 | merge_imports, |
168 | r" | 168 | r" |
169 | pub(crate) use std::fmt<|>::Debug; | 169 | pub(crate) use std::fmt$0::Debug; |
170 | pub use std::fmt::Display; | 170 | pub use std::fmt::Display; |
171 | ", | 171 | ", |
172 | ); | 172 | ); |
@@ -177,7 +177,7 @@ pub use std::fmt::Display; | |||
177 | check_assist_not_applicable( | 177 | check_assist_not_applicable( |
178 | merge_imports, | 178 | merge_imports, |
179 | r" | 179 | r" |
180 | pub use std::fmt<|>::Debug; | 180 | pub use std::fmt$0::Debug; |
181 | pub(crate) use std::fmt::Display; | 181 | pub(crate) use std::fmt::Display; |
182 | ", | 182 | ", |
183 | ); | 183 | ); |
@@ -188,7 +188,7 @@ pub(crate) use std::fmt::Display; | |||
188 | check_assist( | 188 | check_assist( |
189 | merge_imports, | 189 | merge_imports, |
190 | r" | 190 | r" |
191 | pub use std::fmt<|>::Debug; | 191 | pub use std::fmt$0::Debug; |
192 | pub use std::fmt::Display; | 192 | pub use std::fmt::Display; |
193 | ", | 193 | ", |
194 | r" | 194 | r" |
@@ -202,7 +202,7 @@ pub use std::fmt::{Debug, Display}; | |||
202 | check_assist( | 202 | check_assist( |
203 | merge_imports, | 203 | merge_imports, |
204 | r" | 204 | r" |
205 | pub(crate) use std::fmt<|>::Debug; | 205 | pub(crate) use std::fmt$0::Debug; |
206 | pub(crate) use std::fmt::Display; | 206 | pub(crate) use std::fmt::Display; |
207 | ", | 207 | ", |
208 | r" | 208 | r" |
@@ -216,7 +216,7 @@ pub(crate) use std::fmt::{Debug, Display}; | |||
216 | check_assist( | 216 | check_assist( |
217 | merge_imports, | 217 | merge_imports, |
218 | r" | 218 | r" |
219 | use std::{fmt<|>::Debug, fmt::Display}; | 219 | use std::{fmt$0::Debug, fmt::Display}; |
220 | ", | 220 | ", |
221 | r" | 221 | r" |
222 | use std::{fmt::{Debug, Display}}; | 222 | use std::{fmt::{Debug, Display}}; |
@@ -229,7 +229,7 @@ use std::{fmt::{Debug, Display}}; | |||
229 | check_assist( | 229 | check_assist( |
230 | merge_imports, | 230 | merge_imports, |
231 | r" | 231 | r" |
232 | use std::{fmt::Debug, fmt<|>::Display}; | 232 | use std::{fmt::Debug, fmt$0::Display}; |
233 | ", | 233 | ", |
234 | r" | 234 | r" |
235 | use std::{fmt::{Debug, Display}}; | 235 | use std::{fmt::{Debug, Display}}; |
@@ -242,7 +242,7 @@ use std::{fmt::{Debug, Display}}; | |||
242 | check_assist( | 242 | check_assist( |
243 | merge_imports, | 243 | merge_imports, |
244 | r" | 244 | r" |
245 | use std<|>::cell::*; | 245 | use std$0::cell::*; |
246 | use std::str; | 246 | use std::str; |
247 | ", | 247 | ", |
248 | r" | 248 | r" |
@@ -256,7 +256,7 @@ use std::{cell::*, str}; | |||
256 | check_assist( | 256 | check_assist( |
257 | merge_imports, | 257 | merge_imports, |
258 | r" | 258 | r" |
259 | use std<|>::cell::*; | 259 | use std$0::cell::*; |
260 | use std::str::*; | 260 | use std::str::*; |
261 | ", | 261 | ", |
262 | r" | 262 | r" |
@@ -270,7 +270,7 @@ use std::{cell::*, str::*}; | |||
270 | check_assist( | 270 | check_assist( |
271 | merge_imports, | 271 | merge_imports, |
272 | r" | 272 | r" |
273 | use foo<|>::bar; | 273 | use foo$0::bar; |
274 | use foo::baz; | 274 | use foo::baz; |
275 | 275 | ||
276 | /// Doc comment | 276 | /// Doc comment |
@@ -289,7 +289,7 @@ use foo::{bar, baz}; | |||
289 | merge_imports, | 289 | merge_imports, |
290 | r" | 290 | r" |
291 | use { | 291 | use { |
292 | foo<|>::bar, | 292 | foo$0::bar, |
293 | foo::baz, | 293 | foo::baz, |
294 | }; | 294 | }; |
295 | ", | 295 | ", |
@@ -304,7 +304,7 @@ use { | |||
304 | r" | 304 | r" |
305 | use { | 305 | use { |
306 | foo::baz, | 306 | foo::baz, |
307 | foo<|>::bar, | 307 | foo$0::bar, |
308 | }; | 308 | }; |
309 | ", | 309 | ", |
310 | r" | 310 | r" |
@@ -321,7 +321,7 @@ use { | |||
321 | merge_imports, | 321 | merge_imports, |
322 | r" | 322 | r" |
323 | use foo::bar::baz; | 323 | use foo::bar::baz; |
324 | use foo::<|>{ | 324 | use foo::$0{ |
325 | FooBar, | 325 | FooBar, |
326 | }; | 326 | }; |
327 | ", | 327 | ", |
@@ -336,7 +336,7 @@ use foo::{FooBar, bar::baz}; | |||
336 | check_assist_not_applicable( | 336 | check_assist_not_applicable( |
337 | merge_imports, | 337 | merge_imports, |
338 | r" | 338 | r" |
339 | use std::<|> | 339 | use std::$0 |
340 | fn main() {}", | 340 | fn main() {}", |
341 | ); | 341 | ); |
342 | } | 342 | } |
diff --git a/crates/assists/src/handlers/merge_match_arms.rs b/crates/assists/src/handlers/merge_match_arms.rs index c347eb40e..9bf076cb9 100644 --- a/crates/assists/src/handlers/merge_match_arms.rs +++ b/crates/assists/src/handlers/merge_match_arms.rs | |||
@@ -17,7 +17,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists, TextRange}; | |||
17 | // | 17 | // |
18 | // fn handle(action: Action) { | 18 | // fn handle(action: Action) { |
19 | // match action { | 19 | // match action { |
20 | // <|>Action::Move(..) => foo(), | 20 | // $0Action::Move(..) => foo(), |
21 | // Action::Stop => foo(), | 21 | // Action::Stop => foo(), |
22 | // } | 22 | // } |
23 | // } | 23 | // } |
@@ -106,7 +106,7 @@ mod tests { | |||
106 | fn main() { | 106 | fn main() { |
107 | let x = X::A; | 107 | let x = X::A; |
108 | let y = match x { | 108 | let y = match x { |
109 | X::A => { 1i32<|> } | 109 | X::A => { 1i32$0 } |
110 | X::B => { 1i32 } | 110 | X::B => { 1i32 } |
111 | X::C => { 2i32 } | 111 | X::C => { 2i32 } |
112 | } | 112 | } |
@@ -138,7 +138,7 @@ mod tests { | |||
138 | fn main() { | 138 | fn main() { |
139 | let x = X::A; | 139 | let x = X::A; |
140 | let y = match x { | 140 | let y = match x { |
141 | X::A | X::B => {<|> 1i32 }, | 141 | X::A | X::B => {$0 1i32 }, |
142 | X::C | X::D => { 1i32 }, | 142 | X::C | X::D => { 1i32 }, |
143 | X::E => { 2i32 }, | 143 | X::E => { 2i32 }, |
144 | } | 144 | } |
@@ -171,7 +171,7 @@ mod tests { | |||
171 | let x = X::A; | 171 | let x = X::A; |
172 | let y = match x { | 172 | let y = match x { |
173 | X::A => { 1i32 }, | 173 | X::A => { 1i32 }, |
174 | X::B => { 2i<|>32 }, | 174 | X::B => { 2i$032 }, |
175 | _ => { 2i32 } | 175 | _ => { 2i32 } |
176 | } | 176 | } |
177 | } | 177 | } |
@@ -200,7 +200,7 @@ mod tests { | |||
200 | 200 | ||
201 | fn main() { | 201 | fn main() { |
202 | match X::A { | 202 | match X::A { |
203 | X::A<|> => 92, | 203 | X::A$0 => 92, |
204 | X::B => 92, | 204 | X::B => 92, |
205 | X::C => 92, | 205 | X::C => 92, |
206 | X::D => 62, | 206 | X::D => 62, |
@@ -237,7 +237,7 @@ mod tests { | |||
237 | fn main() { | 237 | fn main() { |
238 | let x = X::A; | 238 | let x = X::A; |
239 | let y = match x { | 239 | let y = match x { |
240 | X::A(a) if a > 5 => { <|>1i32 }, | 240 | X::A(a) if a > 5 => { $01i32 }, |
241 | X::B => { 1i32 }, | 241 | X::B => { 1i32 }, |
242 | X::C => { 2i32 } | 242 | X::C => { 2i32 } |
243 | } | 243 | } |
diff --git a/crates/assists/src/handlers/move_bounds.rs b/crates/assists/src/handlers/move_bounds.rs index e2e461520..cf260c6f8 100644 --- a/crates/assists/src/handlers/move_bounds.rs +++ b/crates/assists/src/handlers/move_bounds.rs | |||
@@ -12,7 +12,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
12 | // Moves inline type bounds to a where clause. | 12 | // Moves inline type bounds to a where clause. |
13 | // | 13 | // |
14 | // ``` | 14 | // ``` |
15 | // fn apply<T, U, <|>F: FnOnce(T) -> U>(f: F, x: T) -> U { | 15 | // fn apply<T, U, $0F: FnOnce(T) -> U>(f: F, x: T) -> U { |
16 | // f(x) | 16 | // f(x) |
17 | // } | 17 | // } |
18 | // ``` | 18 | // ``` |
@@ -103,7 +103,7 @@ mod tests { | |||
103 | check_assist( | 103 | check_assist( |
104 | move_bounds_to_where_clause, | 104 | move_bounds_to_where_clause, |
105 | r#" | 105 | r#" |
106 | fn foo<T: u32, <|>F: FnOnce(T) -> T>() {} | 106 | fn foo<T: u32, $0F: FnOnce(T) -> T>() {} |
107 | "#, | 107 | "#, |
108 | r#" | 108 | r#" |
109 | fn foo<T, F>() where T: u32, F: FnOnce(T) -> T {} | 109 | fn foo<T, F>() where T: u32, F: FnOnce(T) -> T {} |
@@ -116,7 +116,7 @@ mod tests { | |||
116 | check_assist( | 116 | check_assist( |
117 | move_bounds_to_where_clause, | 117 | move_bounds_to_where_clause, |
118 | r#" | 118 | r#" |
119 | impl<U: u32, <|>T> A<U, T> {} | 119 | impl<U: u32, $0T> A<U, T> {} |
120 | "#, | 120 | "#, |
121 | r#" | 121 | r#" |
122 | impl<U, T> A<U, T> where U: u32 {} | 122 | impl<U, T> A<U, T> where U: u32 {} |
@@ -129,7 +129,7 @@ mod tests { | |||
129 | check_assist( | 129 | check_assist( |
130 | move_bounds_to_where_clause, | 130 | move_bounds_to_where_clause, |
131 | r#" | 131 | r#" |
132 | struct A<<|>T: Iterator<Item = u32>> {} | 132 | struct A<$0T: Iterator<Item = u32>> {} |
133 | "#, | 133 | "#, |
134 | r#" | 134 | r#" |
135 | struct A<T> where T: Iterator<Item = u32> {} | 135 | struct A<T> where T: Iterator<Item = u32> {} |
@@ -142,7 +142,7 @@ mod tests { | |||
142 | check_assist( | 142 | check_assist( |
143 | move_bounds_to_where_clause, | 143 | move_bounds_to_where_clause, |
144 | r#" | 144 | r#" |
145 | struct Pair<<|>T: u32>(T, T); | 145 | struct Pair<$0T: u32>(T, T); |
146 | "#, | 146 | "#, |
147 | r#" | 147 | r#" |
148 | struct Pair<T>(T, T) where T: u32; | 148 | struct Pair<T>(T, T) where T: u32; |
diff --git a/crates/assists/src/handlers/move_guard.rs b/crates/assists/src/handlers/move_guard.rs index 4318ca6dc..3f22302a9 100644 --- a/crates/assists/src/handlers/move_guard.rs +++ b/crates/assists/src/handlers/move_guard.rs | |||
@@ -14,7 +14,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
14 | // | 14 | // |
15 | // fn handle(action: Action) { | 15 | // fn handle(action: Action) { |
16 | // match action { | 16 | // match action { |
17 | // Action::Move { distance } <|>if distance > 10 => foo(), | 17 | // Action::Move { distance } $0if distance > 10 => foo(), |
18 | // _ => (), | 18 | // _ => (), |
19 | // } | 19 | // } |
20 | // } | 20 | // } |
@@ -74,7 +74,7 @@ pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext) -> | |||
74 | // | 74 | // |
75 | // fn handle(action: Action) { | 75 | // fn handle(action: Action) { |
76 | // match action { | 76 | // match action { |
77 | // Action::Move { distance } => <|>if distance > 10 { foo() }, | 77 | // Action::Move { distance } => $0if distance > 10 { foo() }, |
78 | // _ => (), | 78 | // _ => (), |
79 | // } | 79 | // } |
80 | // } | 80 | // } |
@@ -158,7 +158,7 @@ mod tests { | |||
158 | r#" | 158 | r#" |
159 | fn main() { | 159 | fn main() { |
160 | match 92 { | 160 | match 92 { |
161 | x <|>if x > 10 => false, | 161 | x $0if x > 10 => false, |
162 | _ => true | 162 | _ => true |
163 | } | 163 | } |
164 | } | 164 | } |
@@ -174,7 +174,7 @@ fn main() { | |||
174 | r#" | 174 | r#" |
175 | fn main() { | 175 | fn main() { |
176 | match 92 { | 176 | match 92 { |
177 | x <|>if x > 10 => false, | 177 | x $0if x > 10 => false, |
178 | _ => true | 178 | _ => true |
179 | } | 179 | } |
180 | } | 180 | } |
@@ -199,7 +199,7 @@ fn main() { | |||
199 | r#" | 199 | r#" |
200 | fn main() { | 200 | fn main() { |
201 | match 92 { | 201 | match 92 { |
202 | <|>x @ 4 | x @ 5 if x > 5 => true, | 202 | $0x @ 4 | x @ 5 if x > 5 => true, |
203 | _ => false | 203 | _ => false |
204 | } | 204 | } |
205 | } | 205 | } |
@@ -224,7 +224,7 @@ fn main() { | |||
224 | r#" | 224 | r#" |
225 | fn main() { | 225 | fn main() { |
226 | match 92 { | 226 | match 92 { |
227 | x => if x > 10 { <|>false }, | 227 | x => if x > 10 { $0false }, |
228 | _ => true | 228 | _ => true |
229 | } | 229 | } |
230 | } | 230 | } |
@@ -248,7 +248,7 @@ fn main() { | |||
248 | fn main() { | 248 | fn main() { |
249 | match 92 { | 249 | match 92 { |
250 | x => { | 250 | x => { |
251 | <|>if x > 10 { | 251 | $0if x > 10 { |
252 | false | 252 | false |
253 | } | 253 | } |
254 | }, | 254 | }, |
@@ -274,7 +274,7 @@ fn main() { | |||
274 | r#" | 274 | r#" |
275 | fn main() { | 275 | fn main() { |
276 | match 92 { | 276 | match 92 { |
277 | x => if let 62 = x { <|>false }, | 277 | x => if let 62 = x { $0false }, |
278 | _ => true | 278 | _ => true |
279 | } | 279 | } |
280 | } | 280 | } |
@@ -289,7 +289,7 @@ fn main() { | |||
289 | r#" | 289 | r#" |
290 | fn main() { | 290 | fn main() { |
291 | match 92 { | 291 | match 92 { |
292 | x => if x > 10 { <|> }, | 292 | x => if x > 10 { $0 }, |
293 | _ => true | 293 | _ => true |
294 | } | 294 | } |
295 | } | 295 | } |
@@ -313,7 +313,7 @@ fn main() { | |||
313 | fn main() { | 313 | fn main() { |
314 | match 92 { | 314 | match 92 { |
315 | x => if x > 10 { | 315 | x => if x > 10 { |
316 | 92;<|> | 316 | 92;$0 |
317 | false | 317 | false |
318 | }, | 318 | }, |
319 | _ => true | 319 | _ => true |
@@ -343,7 +343,7 @@ fn main() { | |||
343 | match 92 { | 343 | match 92 { |
344 | x => { | 344 | x => { |
345 | if x > 10 { | 345 | if x > 10 { |
346 | 92;<|> | 346 | 92;$0 |
347 | false | 347 | false |
348 | } | 348 | } |
349 | } | 349 | } |
diff --git a/crates/assists/src/handlers/extract_module_to_file.rs b/crates/assists/src/handlers/move_module_to_file.rs index 50bf67ef7..9d8579f47 100644 --- a/crates/assists/src/handlers/extract_module_to_file.rs +++ b/crates/assists/src/handlers/move_module_to_file.rs | |||
@@ -2,17 +2,18 @@ use ast::edit::IndentLevel; | |||
2 | use ide_db::base_db::AnchoredPathBuf; | 2 | use ide_db::base_db::AnchoredPathBuf; |
3 | use syntax::{ | 3 | use syntax::{ |
4 | ast::{self, edit::AstNodeEdit, NameOwner}, | 4 | ast::{self, edit::AstNodeEdit, NameOwner}, |
5 | AstNode, | 5 | AstNode, TextRange, |
6 | }; | 6 | }; |
7 | use test_utils::mark; | ||
7 | 8 | ||
8 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 9 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
9 | 10 | ||
10 | // Assist: extract_module_to_file | 11 | // Assist: move_module_to_file |
11 | // | 12 | // |
12 | // This assist extract module to file. | 13 | // Moves inline module's contents to a separate file. |
13 | // | 14 | // |
14 | // ``` | 15 | // ``` |
15 | // mod foo {<|> | 16 | // mod $0foo { |
16 | // fn t() {} | 17 | // fn t() {} |
17 | // } | 18 | // } |
18 | // ``` | 19 | // ``` |
@@ -20,19 +21,24 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
20 | // ``` | 21 | // ``` |
21 | // mod foo; | 22 | // mod foo; |
22 | // ``` | 23 | // ``` |
23 | pub(crate) fn extract_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 24 | pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
24 | let module_ast = ctx.find_node_at_offset::<ast::Module>()?; | 25 | let module_ast = ctx.find_node_at_offset::<ast::Module>()?; |
26 | let module_items = module_ast.item_list()?; | ||
27 | |||
28 | let l_curly_offset = module_items.syntax().text_range().start(); | ||
29 | if l_curly_offset <= ctx.offset() { | ||
30 | mark::hit!(available_before_curly); | ||
31 | return None; | ||
32 | } | ||
33 | let target = TextRange::new(module_ast.syntax().text_range().start(), l_curly_offset); | ||
34 | |||
25 | let module_name = module_ast.name()?; | 35 | let module_name = module_ast.name()?; |
26 | 36 | ||
27 | let module_def = ctx.sema.to_def(&module_ast)?; | 37 | let module_def = ctx.sema.to_def(&module_ast)?; |
28 | let parent_module = module_def.parent(ctx.db())?; | 38 | let parent_module = module_def.parent(ctx.db())?; |
29 | 39 | ||
30 | let module_items = module_ast.item_list()?; | ||
31 | let target = module_ast.syntax().text_range(); | ||
32 | let anchor_file_id = ctx.frange.file_id; | ||
33 | |||
34 | acc.add( | 40 | acc.add( |
35 | AssistId("extract_module_to_file", AssistKind::RefactorExtract), | 41 | AssistId("move_module_to_file", AssistKind::RefactorExtract), |
36 | "Extract module to file", | 42 | "Extract module to file", |
37 | target, | 43 | target, |
38 | |builder| { | 44 | |builder| { |
@@ -53,9 +59,9 @@ pub(crate) fn extract_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> | |||
53 | items | 59 | items |
54 | }; | 60 | }; |
55 | 61 | ||
56 | builder.replace(target, format!("mod {};", module_name)); | 62 | builder.replace(module_ast.syntax().text_range(), format!("mod {};", module_name)); |
57 | 63 | ||
58 | let dst = AnchoredPathBuf { anchor: anchor_file_id, path }; | 64 | let dst = AnchoredPathBuf { anchor: ctx.frange.file_id, path }; |
59 | builder.create_file(dst, contents); | 65 | builder.create_file(dst, contents); |
60 | }, | 66 | }, |
61 | ) | 67 | ) |
@@ -63,16 +69,16 @@ pub(crate) fn extract_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> | |||
63 | 69 | ||
64 | #[cfg(test)] | 70 | #[cfg(test)] |
65 | mod tests { | 71 | mod tests { |
66 | use crate::tests::check_assist; | 72 | use crate::tests::{check_assist, check_assist_not_applicable}; |
67 | 73 | ||
68 | use super::*; | 74 | use super::*; |
69 | 75 | ||
70 | #[test] | 76 | #[test] |
71 | fn extract_from_root() { | 77 | fn extract_from_root() { |
72 | check_assist( | 78 | check_assist( |
73 | extract_module_to_file, | 79 | move_module_to_file, |
74 | r#" | 80 | r#" |
75 | mod tests {<|> | 81 | mod $0tests { |
76 | #[test] fn t() {} | 82 | #[test] fn t() {} |
77 | } | 83 | } |
78 | "#, | 84 | "#, |
@@ -88,12 +94,12 @@ mod tests; | |||
88 | #[test] | 94 | #[test] |
89 | fn extract_from_submodule() { | 95 | fn extract_from_submodule() { |
90 | check_assist( | 96 | check_assist( |
91 | extract_module_to_file, | 97 | move_module_to_file, |
92 | r#" | 98 | r#" |
93 | //- /main.rs | 99 | //- /main.rs |
94 | mod submod; | 100 | mod submod; |
95 | //- /submod.rs | 101 | //- /submod.rs |
96 | mod inner<|> { | 102 | $0mod inner { |
97 | fn f() {} | 103 | fn f() {} |
98 | } | 104 | } |
99 | fn g() {} | 105 | fn g() {} |
@@ -111,12 +117,12 @@ fn f() {} | |||
111 | #[test] | 117 | #[test] |
112 | fn extract_from_mod_rs() { | 118 | fn extract_from_mod_rs() { |
113 | check_assist( | 119 | check_assist( |
114 | extract_module_to_file, | 120 | move_module_to_file, |
115 | r#" | 121 | r#" |
116 | //- /main.rs | 122 | //- /main.rs |
117 | mod submodule; | 123 | mod submodule; |
118 | //- /submodule/mod.rs | 124 | //- /submodule/mod.rs |
119 | mod inner<|> { | 125 | mod inner$0 { |
120 | fn f() {} | 126 | fn f() {} |
121 | } | 127 | } |
122 | fn g() {} | 128 | fn g() {} |
@@ -130,4 +136,10 @@ fn f() {} | |||
130 | "#, | 136 | "#, |
131 | ); | 137 | ); |
132 | } | 138 | } |
139 | |||
140 | #[test] | ||
141 | fn available_before_curly() { | ||
142 | mark::check!(available_before_curly); | ||
143 | check_assist_not_applicable(move_module_to_file, r#"mod m { $0 }"#); | ||
144 | } | ||
133 | } | 145 | } |
diff --git a/crates/assists/src/handlers/pull_assignment_up.rs b/crates/assists/src/handlers/pull_assignment_up.rs index 63b662fad..13e1cb754 100644 --- a/crates/assists/src/handlers/pull_assignment_up.rs +++ b/crates/assists/src/handlers/pull_assignment_up.rs | |||
@@ -18,7 +18,7 @@ use crate::{ | |||
18 | // let mut foo = 6; | 18 | // let mut foo = 6; |
19 | // | 19 | // |
20 | // if true { | 20 | // if true { |
21 | // <|>foo = 5; | 21 | // $0foo = 5; |
22 | // } else { | 22 | // } else { |
23 | // foo = 4; | 23 | // foo = 4; |
24 | // } | 24 | // } |
@@ -175,7 +175,7 @@ fn foo() { | |||
175 | let mut a = 1; | 175 | let mut a = 1; |
176 | 176 | ||
177 | if true { | 177 | if true { |
178 | <|>a = 2; | 178 | $0a = 2; |
179 | } else { | 179 | } else { |
180 | a = 3; | 180 | a = 3; |
181 | } | 181 | } |
@@ -203,7 +203,7 @@ fn foo() { | |||
203 | 203 | ||
204 | match 1 { | 204 | match 1 { |
205 | 1 => { | 205 | 1 => { |
206 | <|>a = 2; | 206 | $0a = 2; |
207 | }, | 207 | }, |
208 | 2 => { | 208 | 2 => { |
209 | a = 3; | 209 | a = 3; |
@@ -241,7 +241,7 @@ fn foo() { | |||
241 | let mut a = 1; | 241 | let mut a = 1; |
242 | 242 | ||
243 | if true { | 243 | if true { |
244 | <|>a = 2; | 244 | $0a = 2; |
245 | b = a; | 245 | b = a; |
246 | } else { | 246 | } else { |
247 | a = 3; | 247 | a = 3; |
@@ -260,7 +260,7 @@ fn foo() { | |||
260 | let mut a = 1; | 260 | let mut a = 1; |
261 | 261 | ||
262 | if true { | 262 | if true { |
263 | <|>a = 2; | 263 | $0a = 2; |
264 | } else if false { | 264 | } else if false { |
265 | a = 3; | 265 | a = 3; |
266 | } else { | 266 | } else { |
@@ -292,7 +292,7 @@ fn foo() { | |||
292 | 292 | ||
293 | if true { | 293 | if true { |
294 | let b = 2; | 294 | let b = 2; |
295 | <|>a = 2; | 295 | $0a = 2; |
296 | } else { | 296 | } else { |
297 | let b = 3; | 297 | let b = 3; |
298 | a = 3; | 298 | a = 3; |
@@ -322,7 +322,7 @@ fn foo() { | |||
322 | let mut a = 1; | 322 | let mut a = 1; |
323 | 323 | ||
324 | let b = if true { | 324 | let b = if true { |
325 | <|>a = 2 | 325 | $0a = 2 |
326 | } else { | 326 | } else { |
327 | a = 3 | 327 | a = 3 |
328 | }; | 328 | }; |
@@ -339,7 +339,7 @@ fn foo() { | |||
339 | let mut a = 1; | 339 | let mut a = 1; |
340 | 340 | ||
341 | if true { | 341 | if true { |
342 | <|>a = 2; | 342 | $0a = 2; |
343 | } else {} | 343 | } else {} |
344 | }"#, | 344 | }"#, |
345 | ) | 345 | ) |
@@ -355,7 +355,7 @@ fn foo() { | |||
355 | 355 | ||
356 | match 1 { | 356 | match 1 { |
357 | 1 => { | 357 | 1 => { |
358 | <|>a = 2; | 358 | $0a = 2; |
359 | }, | 359 | }, |
360 | 2 => { | 360 | 2 => { |
361 | a = 3; | 361 | a = 3; |
@@ -378,7 +378,7 @@ fn foo() { | |||
378 | let mut a = A(1); | 378 | let mut a = A(1); |
379 | 379 | ||
380 | if true { | 380 | if true { |
381 | <|>a.0 = 2; | 381 | $0a.0 = 2; |
382 | } else { | 382 | } else { |
383 | a.0 = 3; | 383 | a.0 = 3; |
384 | } | 384 | } |
diff --git a/crates/assists/src/handlers/qualify_path.rs b/crates/assists/src/handlers/qualify_path.rs index 98cb09214..f7fbf37f4 100644 --- a/crates/assists/src/handlers/qualify_path.rs +++ b/crates/assists/src/handlers/qualify_path.rs | |||
@@ -22,7 +22,7 @@ use crate::{ | |||
22 | // | 22 | // |
23 | // ``` | 23 | // ``` |
24 | // fn main() { | 24 | // fn main() { |
25 | // let map = HashMap<|>::new(); | 25 | // let map = HashMap$0::new(); |
26 | // } | 26 | // } |
27 | // # pub mod std { pub mod collections { pub struct HashMap { } } } | 27 | // # pub mod std { pub mod collections { pub struct HashMap { } } } |
28 | // ``` | 28 | // ``` |
@@ -221,7 +221,7 @@ mod tests { | |||
221 | 221 | ||
222 | use std::fmt; | 222 | use std::fmt; |
223 | 223 | ||
224 | <|>Formatter | 224 | $0Formatter |
225 | ", | 225 | ", |
226 | r" | 226 | r" |
227 | mod std { | 227 | mod std { |
@@ -242,7 +242,7 @@ mod tests { | |||
242 | check_assist( | 242 | check_assist( |
243 | qualify_path, | 243 | qualify_path, |
244 | r" | 244 | r" |
245 | <|>PubStruct | 245 | $0PubStruct |
246 | 246 | ||
247 | pub mod PubMod { | 247 | pub mod PubMod { |
248 | pub struct PubStruct; | 248 | pub struct PubStruct; |
@@ -266,7 +266,7 @@ mod tests { | |||
266 | macro_rules! foo { | 266 | macro_rules! foo { |
267 | ($i:ident) => { fn foo(a: $i) {} } | 267 | ($i:ident) => { fn foo(a: $i) {} } |
268 | } | 268 | } |
269 | foo!(Pub<|>Struct); | 269 | foo!(Pub$0Struct); |
270 | 270 | ||
271 | pub mod PubMod { | 271 | pub mod PubMod { |
272 | pub struct PubStruct; | 272 | pub struct PubStruct; |
@@ -290,7 +290,7 @@ mod tests { | |||
290 | check_assist( | 290 | check_assist( |
291 | qualify_path, | 291 | qualify_path, |
292 | r" | 292 | r" |
293 | PubSt<|>ruct | 293 | PubSt$0ruct |
294 | 294 | ||
295 | pub mod PubMod1 { | 295 | pub mod PubMod1 { |
296 | pub struct PubStruct; | 296 | pub struct PubStruct; |
@@ -325,7 +325,7 @@ mod tests { | |||
325 | r" | 325 | r" |
326 | use PubMod::PubStruct; | 326 | use PubMod::PubStruct; |
327 | 327 | ||
328 | PubStruct<|> | 328 | PubStruct$0 |
329 | 329 | ||
330 | pub mod PubMod { | 330 | pub mod PubMod { |
331 | pub struct PubStruct; | 331 | pub struct PubStruct; |
@@ -339,7 +339,7 @@ mod tests { | |||
339 | check_assist_not_applicable( | 339 | check_assist_not_applicable( |
340 | qualify_path, | 340 | qualify_path, |
341 | r" | 341 | r" |
342 | PrivateStruct<|> | 342 | PrivateStruct$0 |
343 | 343 | ||
344 | pub mod PubMod { | 344 | pub mod PubMod { |
345 | struct PrivateStruct; | 345 | struct PrivateStruct; |
@@ -353,7 +353,7 @@ mod tests { | |||
353 | check_assist_not_applicable( | 353 | check_assist_not_applicable( |
354 | qualify_path, | 354 | qualify_path, |
355 | " | 355 | " |
356 | PubStruct<|>", | 356 | PubStruct$0", |
357 | ); | 357 | ); |
358 | } | 358 | } |
359 | 359 | ||
@@ -362,7 +362,7 @@ mod tests { | |||
362 | check_assist_not_applicable( | 362 | check_assist_not_applicable( |
363 | qualify_path, | 363 | qualify_path, |
364 | r" | 364 | r" |
365 | use PubStruct<|>; | 365 | use PubStruct$0; |
366 | 366 | ||
367 | pub mod PubMod { | 367 | pub mod PubMod { |
368 | pub struct PubStruct; | 368 | pub struct PubStruct; |
@@ -375,7 +375,7 @@ mod tests { | |||
375 | check_assist( | 375 | check_assist( |
376 | qualify_path, | 376 | qualify_path, |
377 | r" | 377 | r" |
378 | test_function<|> | 378 | test_function$0 |
379 | 379 | ||
380 | pub mod PubMod { | 380 | pub mod PubMod { |
381 | pub fn test_function() {}; | 381 | pub fn test_function() {}; |
@@ -404,7 +404,7 @@ macro_rules! foo { | |||
404 | 404 | ||
405 | //- /main.rs crate:main deps:crate_with_macro | 405 | //- /main.rs crate:main deps:crate_with_macro |
406 | fn main() { | 406 | fn main() { |
407 | foo<|> | 407 | foo$0 |
408 | } | 408 | } |
409 | ", | 409 | ", |
410 | r" | 410 | r" |
@@ -421,7 +421,7 @@ fn main() { | |||
421 | qualify_path, | 421 | qualify_path, |
422 | r" | 422 | r" |
423 | struct AssistInfo { | 423 | struct AssistInfo { |
424 | group_label: Option<<|>GroupLabel>, | 424 | group_label: Option<$0GroupLabel>, |
425 | } | 425 | } |
426 | 426 | ||
427 | mod m { pub struct GroupLabel; } | 427 | mod m { pub struct GroupLabel; } |
@@ -445,7 +445,7 @@ fn main() { | |||
445 | 445 | ||
446 | use mod1::mod2; | 446 | use mod1::mod2; |
447 | fn main() { | 447 | fn main() { |
448 | mod2::mod3::TestStruct<|> | 448 | mod2::mod3::TestStruct$0 |
449 | } | 449 | } |
450 | ", | 450 | ", |
451 | ); | 451 | ); |
@@ -462,7 +462,7 @@ fn main() { | |||
462 | 462 | ||
463 | use test_mod::test_function; | 463 | use test_mod::test_function; |
464 | fn main() { | 464 | fn main() { |
465 | test_function<|> | 465 | test_function$0 |
466 | } | 466 | } |
467 | ", | 467 | ", |
468 | ); | 468 | ); |
@@ -481,7 +481,7 @@ fn main() { | |||
481 | } | 481 | } |
482 | 482 | ||
483 | fn main() { | 483 | fn main() { |
484 | TestStruct::test_function<|> | 484 | TestStruct::test_function$0 |
485 | } | 485 | } |
486 | ", | 486 | ", |
487 | r" | 487 | r" |
@@ -513,7 +513,7 @@ fn main() { | |||
513 | } | 513 | } |
514 | 514 | ||
515 | fn main() { | 515 | fn main() { |
516 | TestStruct::TEST_CONST<|> | 516 | TestStruct::TEST_CONST$0 |
517 | } | 517 | } |
518 | ", | 518 | ", |
519 | r" | 519 | r" |
@@ -547,7 +547,7 @@ fn main() { | |||
547 | } | 547 | } |
548 | 548 | ||
549 | fn main() { | 549 | fn main() { |
550 | test_mod::TestStruct::test_function<|> | 550 | test_mod::TestStruct::test_function$0 |
551 | } | 551 | } |
552 | ", | 552 | ", |
553 | r" | 553 | r" |
@@ -594,7 +594,7 @@ fn main() { | |||
594 | 594 | ||
595 | use test_mod::TestTrait2; | 595 | use test_mod::TestTrait2; |
596 | fn main() { | 596 | fn main() { |
597 | test_mod::TestEnum::test_function<|>; | 597 | test_mod::TestEnum::test_function$0; |
598 | } | 598 | } |
599 | ", | 599 | ", |
600 | ) | 600 | ) |
@@ -617,7 +617,7 @@ fn main() { | |||
617 | } | 617 | } |
618 | 618 | ||
619 | fn main() { | 619 | fn main() { |
620 | test_mod::TestStruct::TEST_CONST<|> | 620 | test_mod::TestStruct::TEST_CONST$0 |
621 | } | 621 | } |
622 | ", | 622 | ", |
623 | r" | 623 | r" |
@@ -664,7 +664,7 @@ fn main() { | |||
664 | 664 | ||
665 | use test_mod::TestTrait2; | 665 | use test_mod::TestTrait2; |
666 | fn main() { | 666 | fn main() { |
667 | test_mod::TestEnum::TEST_CONST<|>; | 667 | test_mod::TestEnum::TEST_CONST$0; |
668 | } | 668 | } |
669 | ", | 669 | ", |
670 | ) | 670 | ) |
@@ -688,7 +688,7 @@ fn main() { | |||
688 | 688 | ||
689 | fn main() { | 689 | fn main() { |
690 | let test_struct = test_mod::TestStruct {}; | 690 | let test_struct = test_mod::TestStruct {}; |
691 | test_struct.test_meth<|>od() | 691 | test_struct.test_meth$0od() |
692 | } | 692 | } |
693 | ", | 693 | ", |
694 | r" | 694 | r" |
@@ -727,7 +727,7 @@ fn main() { | |||
727 | 727 | ||
728 | fn main() { | 728 | fn main() { |
729 | let test_struct = test_mod::TestStruct {}; | 729 | let test_struct = test_mod::TestStruct {}; |
730 | test_struct.test_meth<|>od(42) | 730 | test_struct.test_meth$0od(42) |
731 | } | 731 | } |
732 | ", | 732 | ", |
733 | r" | 733 | r" |
@@ -766,7 +766,7 @@ fn main() { | |||
766 | 766 | ||
767 | fn main() { | 767 | fn main() { |
768 | let test_struct = test_mod::TestStruct {}; | 768 | let test_struct = test_mod::TestStruct {}; |
769 | test_struct.test_meth<|>od() | 769 | test_struct.test_meth$0od() |
770 | } | 770 | } |
771 | ", | 771 | ", |
772 | r" | 772 | r" |
@@ -796,7 +796,7 @@ fn main() { | |||
796 | //- /main.rs crate:main deps:dep | 796 | //- /main.rs crate:main deps:dep |
797 | fn main() { | 797 | fn main() { |
798 | let test_struct = dep::test_mod::TestStruct {}; | 798 | let test_struct = dep::test_mod::TestStruct {}; |
799 | test_struct.test_meth<|>od() | 799 | test_struct.test_meth$0od() |
800 | } | 800 | } |
801 | //- /dep.rs crate:dep | 801 | //- /dep.rs crate:dep |
802 | pub mod test_mod { | 802 | pub mod test_mod { |
@@ -825,7 +825,7 @@ fn main() { | |||
825 | r" | 825 | r" |
826 | //- /main.rs crate:main deps:dep | 826 | //- /main.rs crate:main deps:dep |
827 | fn main() { | 827 | fn main() { |
828 | dep::test_mod::TestStruct::test_func<|>tion | 828 | dep::test_mod::TestStruct::test_func$0tion |
829 | } | 829 | } |
830 | //- /dep.rs crate:dep | 830 | //- /dep.rs crate:dep |
831 | pub mod test_mod { | 831 | pub mod test_mod { |
@@ -853,7 +853,7 @@ fn main() { | |||
853 | r" | 853 | r" |
854 | //- /main.rs crate:main deps:dep | 854 | //- /main.rs crate:main deps:dep |
855 | fn main() { | 855 | fn main() { |
856 | dep::test_mod::TestStruct::CONST<|> | 856 | dep::test_mod::TestStruct::CONST$0 |
857 | } | 857 | } |
858 | //- /dep.rs crate:dep | 858 | //- /dep.rs crate:dep |
859 | pub mod test_mod { | 859 | pub mod test_mod { |
@@ -882,7 +882,7 @@ fn main() { | |||
882 | //- /main.rs crate:main deps:dep | 882 | //- /main.rs crate:main deps:dep |
883 | fn main() { | 883 | fn main() { |
884 | let test_struct = dep::test_mod::TestStruct {}; | 884 | let test_struct = dep::test_mod::TestStruct {}; |
885 | test_struct.test_func<|>tion() | 885 | test_struct.test_func$0tion() |
886 | } | 886 | } |
887 | //- /dep.rs crate:dep | 887 | //- /dep.rs crate:dep |
888 | pub mod test_mod { | 888 | pub mod test_mod { |
@@ -906,7 +906,7 @@ fn main() { | |||
906 | //- /main.rs crate:main deps:dep | 906 | //- /main.rs crate:main deps:dep |
907 | fn main() { | 907 | fn main() { |
908 | let test_struct = dep::test_mod::TestStruct {}; | 908 | let test_struct = dep::test_mod::TestStruct {}; |
909 | test_struct.test_meth<|>od() | 909 | test_struct.test_meth$0od() |
910 | } | 910 | } |
911 | //- /dep.rs crate:dep | 911 | //- /dep.rs crate:dep |
912 | pub mod test_mod { | 912 | pub mod test_mod { |
@@ -949,7 +949,7 @@ fn main() { | |||
949 | use test_mod::TestTrait2; | 949 | use test_mod::TestTrait2; |
950 | fn main() { | 950 | fn main() { |
951 | let one = test_mod::TestEnum::One; | 951 | let one = test_mod::TestEnum::One; |
952 | one.test<|>_method(); | 952 | one.test$0_method(); |
953 | } | 953 | } |
954 | ", | 954 | ", |
955 | ) | 955 | ) |
@@ -965,7 +965,7 @@ pub struct Struct; | |||
965 | 965 | ||
966 | //- /main.rs crate:main deps:dep | 966 | //- /main.rs crate:main deps:dep |
967 | fn main() { | 967 | fn main() { |
968 | Struct<|> | 968 | Struct$0 |
969 | } | 969 | } |
970 | ", | 970 | ", |
971 | r" | 971 | r" |
@@ -992,7 +992,7 @@ pub fn panic_fmt() {} | |||
992 | //- /main.rs crate:main deps:dep | 992 | //- /main.rs crate:main deps:dep |
993 | struct S; | 993 | struct S; |
994 | 994 | ||
995 | impl f<|>mt::Display for S {} | 995 | impl f$0mt::Display for S {} |
996 | ", | 996 | ", |
997 | r" | 997 | r" |
998 | struct S; | 998 | struct S; |
@@ -1019,7 +1019,7 @@ mac!(); | |||
1019 | 1019 | ||
1020 | //- /main.rs crate:main deps:dep | 1020 | //- /main.rs crate:main deps:dep |
1021 | fn main() { | 1021 | fn main() { |
1022 | Cheese<|>; | 1022 | Cheese$0; |
1023 | } | 1023 | } |
1024 | ", | 1024 | ", |
1025 | r" | 1025 | r" |
@@ -1042,7 +1042,7 @@ pub struct fmt; | |||
1042 | 1042 | ||
1043 | //- /main.rs crate:main deps:dep | 1043 | //- /main.rs crate:main deps:dep |
1044 | fn main() { | 1044 | fn main() { |
1045 | FMT<|>; | 1045 | FMT$0; |
1046 | } | 1046 | } |
1047 | ", | 1047 | ", |
1048 | r" | 1048 | r" |
@@ -1062,7 +1062,7 @@ fn main() { | |||
1062 | pub mod generic { pub struct Thing<'a, T>(&'a T); } | 1062 | pub mod generic { pub struct Thing<'a, T>(&'a T); } |
1063 | 1063 | ||
1064 | //- /main.rs crate:main deps:dep | 1064 | //- /main.rs crate:main deps:dep |
1065 | fn foo() -> Thin<|>g<'static, ()> {} | 1065 | fn foo() -> Thin$0g<'static, ()> {} |
1066 | 1066 | ||
1067 | fn main() {} | 1067 | fn main() {} |
1068 | ", | 1068 | ", |
@@ -1083,7 +1083,7 @@ fn main() {} | |||
1083 | pub mod generic { pub struct Thing<'a, T>(&'a T); } | 1083 | pub mod generic { pub struct Thing<'a, T>(&'a T); } |
1084 | 1084 | ||
1085 | //- /main.rs crate:main deps:dep | 1085 | //- /main.rs crate:main deps:dep |
1086 | fn foo() -> Thin<|>g::<'static, ()> {} | 1086 | fn foo() -> Thin$0g::<'static, ()> {} |
1087 | 1087 | ||
1088 | fn main() {} | 1088 | fn main() {} |
1089 | ", | 1089 | ", |
@@ -1108,7 +1108,7 @@ fn main() {} | |||
1108 | } | 1108 | } |
1109 | 1109 | ||
1110 | fn main() { | 1110 | fn main() { |
1111 | TestStruct::<()>::TEST_CONST<|> | 1111 | TestStruct::<()>::TEST_CONST$0 |
1112 | } | 1112 | } |
1113 | ", | 1113 | ", |
1114 | r" | 1114 | r" |
@@ -1142,7 +1142,7 @@ fn main() {} | |||
1142 | } | 1142 | } |
1143 | 1143 | ||
1144 | fn main() { | 1144 | fn main() { |
1145 | test_mod::TestStruct::<()>::TEST_CONST<|> | 1145 | test_mod::TestStruct::<()>::TEST_CONST$0 |
1146 | } | 1146 | } |
1147 | ", | 1147 | ", |
1148 | r" | 1148 | r" |
@@ -1180,7 +1180,7 @@ fn main() {} | |||
1180 | 1180 | ||
1181 | fn main() { | 1181 | fn main() { |
1182 | let test_struct = test_mod::TestStruct {}; | 1182 | let test_struct = test_mod::TestStruct {}; |
1183 | test_struct.test_meth<|>od::<()>() | 1183 | test_struct.test_meth$0od::<()>() |
1184 | } | 1184 | } |
1185 | ", | 1185 | ", |
1186 | r" | 1186 | r" |
diff --git a/crates/assists/src/handlers/raw_string.rs b/crates/assists/src/handlers/raw_string.rs index 4c759cc25..be963f162 100644 --- a/crates/assists/src/handlers/raw_string.rs +++ b/crates/assists/src/handlers/raw_string.rs | |||
@@ -11,7 +11,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
11 | // | 11 | // |
12 | // ``` | 12 | // ``` |
13 | // fn main() { | 13 | // fn main() { |
14 | // "Hello,<|> World!"; | 14 | // "Hello,$0 World!"; |
15 | // } | 15 | // } |
16 | // ``` | 16 | // ``` |
17 | // -> | 17 | // -> |
@@ -53,7 +53,7 @@ pub(crate) fn make_raw_string(acc: &mut Assists, ctx: &AssistContext) -> Option< | |||
53 | // | 53 | // |
54 | // ``` | 54 | // ``` |
55 | // fn main() { | 55 | // fn main() { |
56 | // r#"Hello,<|> "World!""#; | 56 | // r#"Hello,$0 "World!""#; |
57 | // } | 57 | // } |
58 | // ``` | 58 | // ``` |
59 | // -> | 59 | // -> |
@@ -95,7 +95,7 @@ pub(crate) fn make_usual_string(acc: &mut Assists, ctx: &AssistContext) -> Optio | |||
95 | // | 95 | // |
96 | // ``` | 96 | // ``` |
97 | // fn main() { | 97 | // fn main() { |
98 | // r#"Hello,<|> World!"#; | 98 | // r#"Hello,$0 World!"#; |
99 | // } | 99 | // } |
100 | // ``` | 100 | // ``` |
101 | // -> | 101 | // -> |
@@ -123,7 +123,7 @@ pub(crate) fn add_hash(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | |||
123 | // | 123 | // |
124 | // ``` | 124 | // ``` |
125 | // fn main() { | 125 | // fn main() { |
126 | // r#"Hello,<|> World!"#; | 126 | // r#"Hello,$0 World!"#; |
127 | // } | 127 | // } |
128 | // ``` | 128 | // ``` |
129 | // -> | 129 | // -> |
@@ -194,7 +194,7 @@ mod tests { | |||
194 | make_raw_string, | 194 | make_raw_string, |
195 | r#" | 195 | r#" |
196 | fn f() { | 196 | fn f() { |
197 | let s = <|>"random\nstring"; | 197 | let s = $0"random\nstring"; |
198 | } | 198 | } |
199 | "#, | 199 | "#, |
200 | r#""random\nstring""#, | 200 | r#""random\nstring""#, |
@@ -207,7 +207,7 @@ mod tests { | |||
207 | make_raw_string, | 207 | make_raw_string, |
208 | r#" | 208 | r#" |
209 | fn f() { | 209 | fn f() { |
210 | let s = <|>"random\nstring"; | 210 | let s = $0"random\nstring"; |
211 | } | 211 | } |
212 | "#, | 212 | "#, |
213 | r##" | 213 | r##" |
@@ -225,7 +225,7 @@ string"#; | |||
225 | make_raw_string, | 225 | make_raw_string, |
226 | r#" | 226 | r#" |
227 | fn f() { | 227 | fn f() { |
228 | format!(<|>"x = {}", 92) | 228 | format!($0"x = {}", 92) |
229 | } | 229 | } |
230 | "#, | 230 | "#, |
231 | r##" | 231 | r##" |
@@ -242,7 +242,7 @@ string"#; | |||
242 | make_raw_string, | 242 | make_raw_string, |
243 | r###" | 243 | r###" |
244 | fn f() { | 244 | fn f() { |
245 | let s = <|>"#random##\nstring"; | 245 | let s = $0"#random##\nstring"; |
246 | } | 246 | } |
247 | "###, | 247 | "###, |
248 | r####" | 248 | r####" |
@@ -260,7 +260,7 @@ string"#; | |||
260 | make_raw_string, | 260 | make_raw_string, |
261 | r###" | 261 | r###" |
262 | fn f() { | 262 | fn f() { |
263 | let s = <|>"#random\"##\nstring"; | 263 | let s = $0"#random\"##\nstring"; |
264 | } | 264 | } |
265 | "###, | 265 | "###, |
266 | r####" | 266 | r####" |
@@ -278,7 +278,7 @@ string"###; | |||
278 | make_raw_string, | 278 | make_raw_string, |
279 | r#" | 279 | r#" |
280 | fn f() { | 280 | fn f() { |
281 | let s = <|>"random string"; | 281 | let s = $0"random string"; |
282 | } | 282 | } |
283 | "#, | 283 | "#, |
284 | r##" | 284 | r##" |
@@ -295,7 +295,7 @@ string"###; | |||
295 | make_raw_string, | 295 | make_raw_string, |
296 | r#" | 296 | r#" |
297 | fn f() { | 297 | fn f() { |
298 | let s = "foo<|> | 298 | let s = "foo$0 |
299 | } | 299 | } |
300 | "#, | 300 | "#, |
301 | ) | 301 | ) |
@@ -307,7 +307,7 @@ string"###; | |||
307 | make_usual_string, | 307 | make_usual_string, |
308 | r#" | 308 | r#" |
309 | fn main() { | 309 | fn main() { |
310 | let s = r#"bar<|> | 310 | let s = r#"bar$0 |
311 | } | 311 | } |
312 | "#, | 312 | "#, |
313 | ) | 313 | ) |
@@ -319,7 +319,7 @@ string"###; | |||
319 | add_hash, | 319 | add_hash, |
320 | r#" | 320 | r#" |
321 | fn f() { | 321 | fn f() { |
322 | let s = <|>r"random string"; | 322 | let s = $0r"random string"; |
323 | } | 323 | } |
324 | "#, | 324 | "#, |
325 | r#"r"random string""#, | 325 | r#"r"random string""#, |
@@ -332,7 +332,7 @@ string"###; | |||
332 | add_hash, | 332 | add_hash, |
333 | r#" | 333 | r#" |
334 | fn f() { | 334 | fn f() { |
335 | let s = <|>r"random string"; | 335 | let s = $0r"random string"; |
336 | } | 336 | } |
337 | "#, | 337 | "#, |
338 | r##" | 338 | r##" |
@@ -349,7 +349,7 @@ string"###; | |||
349 | add_hash, | 349 | add_hash, |
350 | r##" | 350 | r##" |
351 | fn f() { | 351 | fn f() { |
352 | let s = <|>r#"random"string"#; | 352 | let s = $0r#"random"string"#; |
353 | } | 353 | } |
354 | "##, | 354 | "##, |
355 | r###" | 355 | r###" |
@@ -366,7 +366,7 @@ string"###; | |||
366 | add_hash, | 366 | add_hash, |
367 | r#" | 367 | r#" |
368 | fn f() { | 368 | fn f() { |
369 | let s = <|>"random string"; | 369 | let s = $0"random string"; |
370 | } | 370 | } |
371 | "#, | 371 | "#, |
372 | ); | 372 | ); |
@@ -378,7 +378,7 @@ string"###; | |||
378 | remove_hash, | 378 | remove_hash, |
379 | r##" | 379 | r##" |
380 | fn f() { | 380 | fn f() { |
381 | let s = <|>r#"random string"#; | 381 | let s = $0r#"random string"#; |
382 | } | 382 | } |
383 | "##, | 383 | "##, |
384 | r##"r#"random string"#"##, | 384 | r##"r#"random string"#"##, |
@@ -389,7 +389,7 @@ string"###; | |||
389 | fn remove_hash_works() { | 389 | fn remove_hash_works() { |
390 | check_assist( | 390 | check_assist( |
391 | remove_hash, | 391 | remove_hash, |
392 | r##"fn f() { let s = <|>r#"random string"#; }"##, | 392 | r##"fn f() { let s = $0r#"random string"#; }"##, |
393 | r#"fn f() { let s = r"random string"; }"#, | 393 | r#"fn f() { let s = r"random string"; }"#, |
394 | ) | 394 | ) |
395 | } | 395 | } |
@@ -401,7 +401,7 @@ string"###; | |||
401 | remove_hash, | 401 | remove_hash, |
402 | r##" | 402 | r##" |
403 | fn f() { | 403 | fn f() { |
404 | let s = <|>r#"random"str"ing"#; | 404 | let s = $0r#"random"str"ing"#; |
405 | } | 405 | } |
406 | "##, | 406 | "##, |
407 | ) | 407 | ) |
@@ -413,7 +413,7 @@ string"###; | |||
413 | remove_hash, | 413 | remove_hash, |
414 | r###" | 414 | r###" |
415 | fn f() { | 415 | fn f() { |
416 | let s = <|>r##"random string"##; | 416 | let s = $0r##"random string"##; |
417 | } | 417 | } |
418 | "###, | 418 | "###, |
419 | r##" | 419 | r##" |
@@ -426,12 +426,12 @@ string"###; | |||
426 | 426 | ||
427 | #[test] | 427 | #[test] |
428 | fn remove_hash_doesnt_work() { | 428 | fn remove_hash_doesnt_work() { |
429 | check_assist_not_applicable(remove_hash, r#"fn f() { let s = <|>"random string"; }"#); | 429 | check_assist_not_applicable(remove_hash, r#"fn f() { let s = $0"random string"; }"#); |
430 | } | 430 | } |
431 | 431 | ||
432 | #[test] | 432 | #[test] |
433 | fn remove_hash_no_hash_doesnt_work() { | 433 | fn remove_hash_no_hash_doesnt_work() { |
434 | check_assist_not_applicable(remove_hash, r#"fn f() { let s = <|>r"random string"; }"#); | 434 | check_assist_not_applicable(remove_hash, r#"fn f() { let s = $0r"random string"; }"#); |
435 | } | 435 | } |
436 | 436 | ||
437 | #[test] | 437 | #[test] |
@@ -440,7 +440,7 @@ string"###; | |||
440 | make_usual_string, | 440 | make_usual_string, |
441 | r##" | 441 | r##" |
442 | fn f() { | 442 | fn f() { |
443 | let s = <|>r#"random string"#; | 443 | let s = $0r#"random string"#; |
444 | } | 444 | } |
445 | "##, | 445 | "##, |
446 | r##"r#"random string"#"##, | 446 | r##"r#"random string"#"##, |
@@ -453,7 +453,7 @@ string"###; | |||
453 | make_usual_string, | 453 | make_usual_string, |
454 | r##" | 454 | r##" |
455 | fn f() { | 455 | fn f() { |
456 | let s = <|>r#"random string"#; | 456 | let s = $0r#"random string"#; |
457 | } | 457 | } |
458 | "##, | 458 | "##, |
459 | r#" | 459 | r#" |
@@ -470,7 +470,7 @@ string"###; | |||
470 | make_usual_string, | 470 | make_usual_string, |
471 | r##" | 471 | r##" |
472 | fn f() { | 472 | fn f() { |
473 | let s = <|>r#"random"str"ing"#; | 473 | let s = $0r#"random"str"ing"#; |
474 | } | 474 | } |
475 | "##, | 475 | "##, |
476 | r#" | 476 | r#" |
@@ -487,7 +487,7 @@ string"###; | |||
487 | make_usual_string, | 487 | make_usual_string, |
488 | r###" | 488 | r###" |
489 | fn f() { | 489 | fn f() { |
490 | let s = <|>r##"random string"##; | 490 | let s = $0r##"random string"##; |
491 | } | 491 | } |
492 | "###, | 492 | "###, |
493 | r##" | 493 | r##" |
@@ -504,7 +504,7 @@ string"###; | |||
504 | make_usual_string, | 504 | make_usual_string, |
505 | r#" | 505 | r#" |
506 | fn f() { | 506 | fn f() { |
507 | let s = <|>"random string"; | 507 | let s = $0"random string"; |
508 | } | 508 | } |
509 | "#, | 509 | "#, |
510 | ); | 510 | ); |
diff --git a/crates/assists/src/handlers/remove_dbg.rs b/crates/assists/src/handlers/remove_dbg.rs index eae6367c1..6114091f2 100644 --- a/crates/assists/src/handlers/remove_dbg.rs +++ b/crates/assists/src/handlers/remove_dbg.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use syntax::{ | 1 | use syntax::{ |
2 | ast::{self, AstNode}, | 2 | ast::{self, AstNode}, |
3 | match_ast, SyntaxElement, SyntaxKind, TextRange, TextSize, T, | 3 | match_ast, SyntaxElement, TextRange, TextSize, T, |
4 | }; | 4 | }; |
5 | 5 | ||
6 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 6 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
@@ -11,7 +11,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
11 | // | 11 | // |
12 | // ``` | 12 | // ``` |
13 | // fn main() { | 13 | // fn main() { |
14 | // <|>dbg!(92); | 14 | // $0dbg!(92); |
15 | // } | 15 | // } |
16 | // ``` | 16 | // ``` |
17 | // -> | 17 | // -> |
@@ -136,14 +136,14 @@ fn needs_parentheses_around_macro_contents(macro_contents: Vec<SyntaxElement>) - | |||
136 | symbol_kind => { | 136 | symbol_kind => { |
137 | let symbol_not_in_bracket = unpaired_brackets_in_contents.is_empty(); | 137 | let symbol_not_in_bracket = unpaired_brackets_in_contents.is_empty(); |
138 | if symbol_not_in_bracket | 138 | if symbol_not_in_bracket |
139 | && symbol_kind != SyntaxKind::COLON // paths | 139 | && symbol_kind != T![:] // paths |
140 | && (symbol_kind != SyntaxKind::DOT // field/method access | 140 | && (symbol_kind != T![.] // field/method access |
141 | || macro_contents // range expressions consist of two SyntaxKind::Dot in macro invocations | 141 | || macro_contents // range expressions consist of two SyntaxKind::Dot in macro invocations |
142 | .peek() | 142 | .peek() |
143 | .map(|element| element.kind() == SyntaxKind::DOT) | 143 | .map(|element| element.kind() == T![.]) |
144 | .unwrap_or(false)) | 144 | .unwrap_or(false)) |
145 | && symbol_kind != SyntaxKind::QUESTION // try operator | 145 | && symbol_kind != T![?] // try operator |
146 | && (symbol_kind.is_punct() || symbol_kind == SyntaxKind::AS_KW) | 146 | && (symbol_kind.is_punct() || symbol_kind == T![as]) |
147 | { | 147 | { |
148 | return true; | 148 | return true; |
149 | } | 149 | } |
@@ -161,19 +161,19 @@ mod tests { | |||
161 | 161 | ||
162 | #[test] | 162 | #[test] |
163 | fn test_remove_dbg() { | 163 | fn test_remove_dbg() { |
164 | check_assist(remove_dbg, "<|>dbg!(1 + 1)", "1 + 1"); | 164 | check_assist(remove_dbg, "$0dbg!(1 + 1)", "1 + 1"); |
165 | 165 | ||
166 | check_assist(remove_dbg, "dbg!<|>((1 + 1))", "(1 + 1)"); | 166 | check_assist(remove_dbg, "dbg!$0((1 + 1))", "(1 + 1)"); |
167 | 167 | ||
168 | check_assist(remove_dbg, "dbg!(1 <|>+ 1)", "1 + 1"); | 168 | check_assist(remove_dbg, "dbg!(1 $0+ 1)", "1 + 1"); |
169 | 169 | ||
170 | check_assist(remove_dbg, "let _ = <|>dbg!(1 + 1)", "let _ = 1 + 1"); | 170 | check_assist(remove_dbg, "let _ = $0dbg!(1 + 1)", "let _ = 1 + 1"); |
171 | 171 | ||
172 | check_assist( | 172 | check_assist( |
173 | remove_dbg, | 173 | remove_dbg, |
174 | " | 174 | " |
175 | fn foo(n: usize) { | 175 | fn foo(n: usize) { |
176 | if let Some(_) = dbg!(n.<|>checked_sub(4)) { | 176 | if let Some(_) = dbg!(n.$0checked_sub(4)) { |
177 | // ... | 177 | // ... |
178 | } | 178 | } |
179 | } | 179 | } |
@@ -187,20 +187,20 @@ fn foo(n: usize) { | |||
187 | ", | 187 | ", |
188 | ); | 188 | ); |
189 | 189 | ||
190 | check_assist(remove_dbg, "<|>dbg!(Foo::foo_test()).bar()", "Foo::foo_test().bar()"); | 190 | check_assist(remove_dbg, "$0dbg!(Foo::foo_test()).bar()", "Foo::foo_test().bar()"); |
191 | } | 191 | } |
192 | 192 | ||
193 | #[test] | 193 | #[test] |
194 | fn test_remove_dbg_with_brackets_and_braces() { | 194 | fn test_remove_dbg_with_brackets_and_braces() { |
195 | check_assist(remove_dbg, "dbg![<|>1 + 1]", "1 + 1"); | 195 | check_assist(remove_dbg, "dbg![$01 + 1]", "1 + 1"); |
196 | check_assist(remove_dbg, "dbg!{<|>1 + 1}", "1 + 1"); | 196 | check_assist(remove_dbg, "dbg!{$01 + 1}", "1 + 1"); |
197 | } | 197 | } |
198 | 198 | ||
199 | #[test] | 199 | #[test] |
200 | fn test_remove_dbg_not_applicable() { | 200 | fn test_remove_dbg_not_applicable() { |
201 | check_assist_not_applicable(remove_dbg, "<|>vec![1, 2, 3]"); | 201 | check_assist_not_applicable(remove_dbg, "$0vec![1, 2, 3]"); |
202 | check_assist_not_applicable(remove_dbg, "<|>dbg(5, 6, 7)"); | 202 | check_assist_not_applicable(remove_dbg, "$0dbg(5, 6, 7)"); |
203 | check_assist_not_applicable(remove_dbg, "<|>dbg!(5, 6, 7"); | 203 | check_assist_not_applicable(remove_dbg, "$0dbg!(5, 6, 7"); |
204 | } | 204 | } |
205 | 205 | ||
206 | #[test] | 206 | #[test] |
@@ -209,7 +209,7 @@ fn foo(n: usize) { | |||
209 | remove_dbg, | 209 | remove_dbg, |
210 | " | 210 | " |
211 | fn foo(n: usize) { | 211 | fn foo(n: usize) { |
212 | if let Some(_) = dbg!(n.<|>checked_sub(4)) { | 212 | if let Some(_) = dbg!(n.$0checked_sub(4)) { |
213 | // ... | 213 | // ... |
214 | } | 214 | } |
215 | } | 215 | } |
@@ -226,7 +226,7 @@ fn foo(n: usize) { | |||
226 | // the ast::MacroCall to include the semicolon at the end | 226 | // the ast::MacroCall to include the semicolon at the end |
227 | check_assist( | 227 | check_assist( |
228 | remove_dbg, | 228 | remove_dbg, |
229 | r#"let res = <|>dbg!(1 * 20); // needless comment"#, | 229 | r#"let res = $0dbg!(1 * 20); // needless comment"#, |
230 | r#"let res = 1 * 20; // needless comment"#, | 230 | r#"let res = 1 * 20; // needless comment"#, |
231 | ); | 231 | ); |
232 | } | 232 | } |
@@ -238,7 +238,7 @@ fn foo(n: usize) { | |||
238 | " | 238 | " |
239 | fn main() { | 239 | fn main() { |
240 | let mut a = 1; | 240 | let mut a = 1; |
241 | while dbg!<|>(a) < 10000 { | 241 | while dbg!$0(a) < 10000 { |
242 | a += 1; | 242 | a += 1; |
243 | } | 243 | } |
244 | } | 244 | } |
@@ -258,31 +258,31 @@ fn main() { | |||
258 | fn test_remove_dbg_keep_expression() { | 258 | fn test_remove_dbg_keep_expression() { |
259 | check_assist( | 259 | check_assist( |
260 | remove_dbg, | 260 | remove_dbg, |
261 | r#"let res = <|>dbg!(a + b).foo();"#, | 261 | r#"let res = $0dbg!(a + b).foo();"#, |
262 | r#"let res = (a + b).foo();"#, | 262 | r#"let res = (a + b).foo();"#, |
263 | ); | 263 | ); |
264 | 264 | ||
265 | check_assist(remove_dbg, r#"let res = <|>dbg!(2 + 2) * 5"#, r#"let res = (2 + 2) * 5"#); | 265 | check_assist(remove_dbg, r#"let res = $0dbg!(2 + 2) * 5"#, r#"let res = (2 + 2) * 5"#); |
266 | check_assist(remove_dbg, r#"let res = <|>dbg![2 + 2] * 5"#, r#"let res = (2 + 2) * 5"#); | 266 | check_assist(remove_dbg, r#"let res = $0dbg![2 + 2] * 5"#, r#"let res = (2 + 2) * 5"#); |
267 | } | 267 | } |
268 | 268 | ||
269 | #[test] | 269 | #[test] |
270 | fn test_remove_dbg_method_chaining() { | 270 | fn test_remove_dbg_method_chaining() { |
271 | check_assist( | 271 | check_assist( |
272 | remove_dbg, | 272 | remove_dbg, |
273 | r#"let res = <|>dbg!(foo().bar()).baz();"#, | 273 | r#"let res = $0dbg!(foo().bar()).baz();"#, |
274 | r#"let res = foo().bar().baz();"#, | 274 | r#"let res = foo().bar().baz();"#, |
275 | ); | 275 | ); |
276 | check_assist( | 276 | check_assist( |
277 | remove_dbg, | 277 | remove_dbg, |
278 | r#"let res = <|>dbg!(foo.bar()).baz();"#, | 278 | r#"let res = $0dbg!(foo.bar()).baz();"#, |
279 | r#"let res = foo.bar().baz();"#, | 279 | r#"let res = foo.bar().baz();"#, |
280 | ); | 280 | ); |
281 | } | 281 | } |
282 | 282 | ||
283 | #[test] | 283 | #[test] |
284 | fn test_remove_dbg_field_chaining() { | 284 | fn test_remove_dbg_field_chaining() { |
285 | check_assist(remove_dbg, r#"let res = <|>dbg!(foo.bar).baz;"#, r#"let res = foo.bar.baz;"#); | 285 | check_assist(remove_dbg, r#"let res = $0dbg!(foo.bar).baz;"#, r#"let res = foo.bar.baz;"#); |
286 | } | 286 | } |
287 | 287 | ||
288 | #[test] | 288 | #[test] |
@@ -295,7 +295,7 @@ fn square(x: u32) -> u32 { | |||
295 | } | 295 | } |
296 | 296 | ||
297 | fn main() { | 297 | fn main() { |
298 | let x = square(dbg<|>!(5 + 10)); | 298 | let x = square(dbg$0!(5 + 10)); |
299 | println!("{}", x); | 299 | println!("{}", x); |
300 | }"#, | 300 | }"#, |
301 | "dbg!(5 + 10)", | 301 | "dbg!(5 + 10)", |
@@ -309,7 +309,7 @@ fn square(x: u32) -> u32 { | |||
309 | } | 309 | } |
310 | 310 | ||
311 | fn main() { | 311 | fn main() { |
312 | let x = square(dbg<|>!(5 + 10)); | 312 | let x = square(dbg$0!(5 + 10)); |
313 | println!("{}", x); | 313 | println!("{}", x); |
314 | }"#, | 314 | }"#, |
315 | r#" | 315 | r#" |
@@ -328,7 +328,7 @@ fn main() { | |||
328 | fn test_remove_dbg_try_expr() { | 328 | fn test_remove_dbg_try_expr() { |
329 | check_assist( | 329 | check_assist( |
330 | remove_dbg, | 330 | remove_dbg, |
331 | r#"let res = <|>dbg!(result?).foo();"#, | 331 | r#"let res = $0dbg!(result?).foo();"#, |
332 | r#"let res = result?.foo();"#, | 332 | r#"let res = result?.foo();"#, |
333 | ); | 333 | ); |
334 | } | 334 | } |
@@ -337,7 +337,7 @@ fn main() { | |||
337 | fn test_remove_dbg_await_expr() { | 337 | fn test_remove_dbg_await_expr() { |
338 | check_assist( | 338 | check_assist( |
339 | remove_dbg, | 339 | remove_dbg, |
340 | r#"let res = <|>dbg!(fut.await).foo();"#, | 340 | r#"let res = $0dbg!(fut.await).foo();"#, |
341 | r#"let res = fut.await.foo();"#, | 341 | r#"let res = fut.await.foo();"#, |
342 | ); | 342 | ); |
343 | } | 343 | } |
@@ -346,7 +346,7 @@ fn main() { | |||
346 | fn test_remove_dbg_as_cast() { | 346 | fn test_remove_dbg_as_cast() { |
347 | check_assist( | 347 | check_assist( |
348 | remove_dbg, | 348 | remove_dbg, |
349 | r#"let res = <|>dbg!(3 as usize).foo();"#, | 349 | r#"let res = $0dbg!(3 as usize).foo();"#, |
350 | r#"let res = (3 as usize).foo();"#, | 350 | r#"let res = (3 as usize).foo();"#, |
351 | ); | 351 | ); |
352 | } | 352 | } |
@@ -355,12 +355,12 @@ fn main() { | |||
355 | fn test_remove_dbg_index_expr() { | 355 | fn test_remove_dbg_index_expr() { |
356 | check_assist( | 356 | check_assist( |
357 | remove_dbg, | 357 | remove_dbg, |
358 | r#"let res = <|>dbg!(array[3]).foo();"#, | 358 | r#"let res = $0dbg!(array[3]).foo();"#, |
359 | r#"let res = array[3].foo();"#, | 359 | r#"let res = array[3].foo();"#, |
360 | ); | 360 | ); |
361 | check_assist( | 361 | check_assist( |
362 | remove_dbg, | 362 | remove_dbg, |
363 | r#"let res = <|>dbg!(tuple.3).foo();"#, | 363 | r#"let res = $0dbg!(tuple.3).foo();"#, |
364 | r#"let res = tuple.3.foo();"#, | 364 | r#"let res = tuple.3.foo();"#, |
365 | ); | 365 | ); |
366 | } | 366 | } |
@@ -369,12 +369,12 @@ fn main() { | |||
369 | fn test_remove_dbg_range_expr() { | 369 | fn test_remove_dbg_range_expr() { |
370 | check_assist( | 370 | check_assist( |
371 | remove_dbg, | 371 | remove_dbg, |
372 | r#"let res = <|>dbg!(foo..bar).foo();"#, | 372 | r#"let res = $0dbg!(foo..bar).foo();"#, |
373 | r#"let res = (foo..bar).foo();"#, | 373 | r#"let res = (foo..bar).foo();"#, |
374 | ); | 374 | ); |
375 | check_assist( | 375 | check_assist( |
376 | remove_dbg, | 376 | remove_dbg, |
377 | r#"let res = <|>dbg!(foo..=bar).foo();"#, | 377 | r#"let res = $0dbg!(foo..=bar).foo();"#, |
378 | r#"let res = (foo..=bar).foo();"#, | 378 | r#"let res = (foo..=bar).foo();"#, |
379 | ); | 379 | ); |
380 | } | 380 | } |
@@ -384,7 +384,7 @@ fn main() { | |||
384 | check_assist( | 384 | check_assist( |
385 | remove_dbg, | 385 | remove_dbg, |
386 | r#"fn foo() { | 386 | r#"fn foo() { |
387 | if <|>dbg!(x || y) {} | 387 | if $0dbg!(x || y) {} |
388 | }"#, | 388 | }"#, |
389 | r#"fn foo() { | 389 | r#"fn foo() { |
390 | if x || y {} | 390 | if x || y {} |
@@ -393,7 +393,7 @@ fn main() { | |||
393 | check_assist( | 393 | check_assist( |
394 | remove_dbg, | 394 | remove_dbg, |
395 | r#"fn foo() { | 395 | r#"fn foo() { |
396 | while let foo = <|>dbg!(&x) {} | 396 | while let foo = $0dbg!(&x) {} |
397 | }"#, | 397 | }"#, |
398 | r#"fn foo() { | 398 | r#"fn foo() { |
399 | while let foo = &x {} | 399 | while let foo = &x {} |
@@ -402,7 +402,7 @@ fn main() { | |||
402 | check_assist( | 402 | check_assist( |
403 | remove_dbg, | 403 | remove_dbg, |
404 | r#"fn foo() { | 404 | r#"fn foo() { |
405 | if let foo = <|>dbg!(&x) {} | 405 | if let foo = $0dbg!(&x) {} |
406 | }"#, | 406 | }"#, |
407 | r#"fn foo() { | 407 | r#"fn foo() { |
408 | if let foo = &x {} | 408 | if let foo = &x {} |
@@ -411,7 +411,7 @@ fn main() { | |||
411 | check_assist( | 411 | check_assist( |
412 | remove_dbg, | 412 | remove_dbg, |
413 | r#"fn foo() { | 413 | r#"fn foo() { |
414 | match <|>dbg!(&x) {} | 414 | match $0dbg!(&x) {} |
415 | }"#, | 415 | }"#, |
416 | r#"fn foo() { | 416 | r#"fn foo() { |
417 | match &x {} | 417 | match &x {} |
diff --git a/crates/assists/src/handlers/remove_mut.rs b/crates/assists/src/handlers/remove_mut.rs index 575b271f7..30d36dacd 100644 --- a/crates/assists/src/handlers/remove_mut.rs +++ b/crates/assists/src/handlers/remove_mut.rs | |||
@@ -8,7 +8,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
8 | // | 8 | // |
9 | // ``` | 9 | // ``` |
10 | // impl Walrus { | 10 | // impl Walrus { |
11 | // fn feed(&mut<|> self, amount: u32) {} | 11 | // fn feed(&mut$0 self, amount: u32) {} |
12 | // } | 12 | // } |
13 | // ``` | 13 | // ``` |
14 | // -> | 14 | // -> |
diff --git a/crates/assists/src/handlers/remove_unused_param.rs b/crates/assists/src/handlers/remove_unused_param.rs index f72dd49ed..c961680e2 100644 --- a/crates/assists/src/handlers/remove_unused_param.rs +++ b/crates/assists/src/handlers/remove_unused_param.rs | |||
@@ -1,8 +1,8 @@ | |||
1 | use ide_db::{defs::Definition, search::Reference}; | 1 | use ide_db::{base_db::FileId, defs::Definition, search::FileReference}; |
2 | use syntax::{ | 2 | use syntax::{ |
3 | algo::find_node_at_range, | 3 | algo::find_node_at_range, |
4 | ast::{self, ArgListOwner}, | 4 | ast::{self, ArgListOwner}, |
5 | AstNode, SyntaxKind, SyntaxNode, TextRange, T, | 5 | AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange, T, |
6 | }; | 6 | }; |
7 | use test_utils::mark; | 7 | use test_utils::mark; |
8 | use SyntaxKind::WHITESPACE; | 8 | use SyntaxKind::WHITESPACE; |
@@ -16,7 +16,7 @@ use crate::{ | |||
16 | // Removes unused function parameter. | 16 | // Removes unused function parameter. |
17 | // | 17 | // |
18 | // ``` | 18 | // ``` |
19 | // fn frobnicate(x: i32<|>) {} | 19 | // fn frobnicate(x: i32$0) {} |
20 | // | 20 | // |
21 | // fn main() { | 21 | // fn main() { |
22 | // frobnicate(92); | 22 | // frobnicate(92); |
@@ -58,32 +58,41 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Opt | |||
58 | param.syntax().text_range(), | 58 | param.syntax().text_range(), |
59 | |builder| { | 59 | |builder| { |
60 | builder.delete(range_to_remove(param.syntax())); | 60 | builder.delete(range_to_remove(param.syntax())); |
61 | for usage in fn_def.usages(&ctx.sema).all() { | 61 | for (file_id, references) in fn_def.usages(&ctx.sema).all() { |
62 | process_usage(ctx, builder, usage, param_position); | 62 | process_usages(ctx, builder, file_id, references, param_position); |
63 | } | 63 | } |
64 | }, | 64 | }, |
65 | ) | 65 | ) |
66 | } | 66 | } |
67 | 67 | ||
68 | fn process_usage( | 68 | fn process_usages( |
69 | ctx: &AssistContext, | 69 | ctx: &AssistContext, |
70 | builder: &mut AssistBuilder, | 70 | builder: &mut AssistBuilder, |
71 | usage: Reference, | 71 | file_id: FileId, |
72 | references: Vec<FileReference>, | ||
72 | arg_to_remove: usize, | 73 | arg_to_remove: usize, |
73 | ) -> Option<()> { | 74 | ) { |
74 | let source_file = ctx.sema.parse(usage.file_range.file_id); | 75 | let source_file = ctx.sema.parse(file_id); |
75 | let call_expr: ast::CallExpr = | 76 | builder.edit_file(file_id); |
76 | find_node_at_range(source_file.syntax(), usage.file_range.range)?; | 77 | for usage in references { |
78 | if let Some(text_range) = process_usage(&source_file, usage, arg_to_remove) { | ||
79 | builder.delete(text_range); | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | |||
84 | fn process_usage( | ||
85 | source_file: &SourceFile, | ||
86 | FileReference { range, .. }: FileReference, | ||
87 | arg_to_remove: usize, | ||
88 | ) -> Option<TextRange> { | ||
89 | let call_expr: ast::CallExpr = find_node_at_range(source_file.syntax(), range)?; | ||
77 | let call_expr_range = call_expr.expr()?.syntax().text_range(); | 90 | let call_expr_range = call_expr.expr()?.syntax().text_range(); |
78 | if !call_expr_range.contains_range(usage.file_range.range) { | 91 | if !call_expr_range.contains_range(range) { |
79 | return None; | 92 | return None; |
80 | } | 93 | } |
81 | let arg = call_expr.arg_list()?.args().nth(arg_to_remove)?; | 94 | let arg = call_expr.arg_list()?.args().nth(arg_to_remove)?; |
82 | 95 | Some(range_to_remove(arg.syntax())) | |
83 | builder.edit_file(usage.file_range.file_id); | ||
84 | builder.delete(range_to_remove(arg.syntax())); | ||
85 | |||
86 | Some(()) | ||
87 | } | 96 | } |
88 | 97 | ||
89 | fn range_to_remove(node: &SyntaxNode) -> TextRange { | 98 | fn range_to_remove(node: &SyntaxNode) -> TextRange { |
@@ -123,7 +132,7 @@ mod tests { | |||
123 | remove_unused_param, | 132 | remove_unused_param, |
124 | r#" | 133 | r#" |
125 | fn a() { foo(9, 2) } | 134 | fn a() { foo(9, 2) } |
126 | fn foo(x: i32, <|>y: i32) { x; } | 135 | fn foo(x: i32, $0y: i32) { x; } |
127 | fn b() { foo(9, 2,) } | 136 | fn b() { foo(9, 2,) } |
128 | "#, | 137 | "#, |
129 | r#" | 138 | r#" |
@@ -139,7 +148,7 @@ fn b() { foo(9, ) } | |||
139 | check_assist( | 148 | check_assist( |
140 | remove_unused_param, | 149 | remove_unused_param, |
141 | r#" | 150 | r#" |
142 | fn foo(<|>x: i32, y: i32) { y; } | 151 | fn foo($0x: i32, y: i32) { y; } |
143 | fn a() { foo(1, 2) } | 152 | fn a() { foo(1, 2) } |
144 | fn b() { foo(1, 2,) } | 153 | fn b() { foo(1, 2,) } |
145 | "#, | 154 | "#, |
@@ -156,7 +165,7 @@ fn b() { foo(2,) } | |||
156 | check_assist( | 165 | check_assist( |
157 | remove_unused_param, | 166 | remove_unused_param, |
158 | r#" | 167 | r#" |
159 | fn foo(<|>x: i32) { 0; } | 168 | fn foo($0x: i32) { 0; } |
160 | fn a() { foo(1) } | 169 | fn a() { foo(1) } |
161 | fn b() { foo(1, ) } | 170 | fn b() { foo(1, ) } |
162 | "#, | 171 | "#, |
@@ -173,7 +182,7 @@ fn b() { foo( ) } | |||
173 | check_assist( | 182 | check_assist( |
174 | remove_unused_param, | 183 | remove_unused_param, |
175 | r#" | 184 | r#" |
176 | fn foo(x: i32, <|>y: i32, z: i32) { x; } | 185 | fn foo(x: i32, $0y: i32, z: i32) { x; } |
177 | fn a() { foo(1, 2, 3) } | 186 | fn a() { foo(1, 2, 3) } |
178 | fn b() { foo(1, 2, 3,) } | 187 | fn b() { foo(1, 2, 3,) } |
179 | "#, | 188 | "#, |
@@ -190,7 +199,7 @@ fn b() { foo(1, 3,) } | |||
190 | check_assist( | 199 | check_assist( |
191 | remove_unused_param, | 200 | remove_unused_param, |
192 | r#" | 201 | r#" |
193 | mod bar { pub fn foo(x: i32, <|>y: i32) { x; } } | 202 | mod bar { pub fn foo(x: i32, $0y: i32) { x; } } |
194 | fn b() { bar::foo(9, 2) } | 203 | fn b() { bar::foo(9, 2) } |
195 | "#, | 204 | "#, |
196 | r#" | 205 | r#" |
@@ -205,7 +214,7 @@ fn b() { bar::foo(9) } | |||
205 | check_assist( | 214 | check_assist( |
206 | remove_unused_param, | 215 | remove_unused_param, |
207 | r#" | 216 | r#" |
208 | pub fn foo<T>(x: T, <|>y: i32) { x; } | 217 | pub fn foo<T>(x: T, $0y: i32) { x; } |
209 | fn b() { foo::<i32>(9, 2) } | 218 | fn b() { foo::<i32>(9, 2) } |
210 | "#, | 219 | "#, |
211 | r#" | 220 | r#" |
@@ -220,7 +229,7 @@ fn b() { foo::<i32>(9) } | |||
220 | check_assist( | 229 | check_assist( |
221 | remove_unused_param, | 230 | remove_unused_param, |
222 | r#" | 231 | r#" |
223 | pub fn foo<T>(x: i32, <|>y: T) { x; } | 232 | pub fn foo<T>(x: i32, $0y: T) { x; } |
224 | fn b() { foo::<i32>(9, 2) } | 233 | fn b() { foo::<i32>(9, 2) } |
225 | fn b2() { foo(9, 2) } | 234 | fn b2() { foo(9, 2) } |
226 | "#, | 235 | "#, |
@@ -238,7 +247,7 @@ fn b2() { foo(9) } | |||
238 | check_assist_not_applicable( | 247 | check_assist_not_applicable( |
239 | remove_unused_param, | 248 | remove_unused_param, |
240 | r#" | 249 | r#" |
241 | fn foo(x: i32, <|>y: i32) { y; } | 250 | fn foo(x: i32, $0y: i32) { y; } |
242 | fn main() { foo(9, 2) } | 251 | fn main() { foo(9, 2) } |
243 | "#, | 252 | "#, |
244 | ); | 253 | ); |
@@ -250,7 +259,7 @@ fn main() { foo(9, 2) } | |||
250 | remove_unused_param, | 259 | remove_unused_param, |
251 | r#" | 260 | r#" |
252 | //- /main.rs | 261 | //- /main.rs |
253 | fn foo(x: i32, <|>y: i32) { x; } | 262 | fn foo(x: i32, $0y: i32) { x; } |
254 | 263 | ||
255 | mod foo; | 264 | mod foo; |
256 | 265 | ||
diff --git a/crates/assists/src/handlers/reorder_fields.rs b/crates/assists/src/handlers/reorder_fields.rs index fe5574242..fba7d6ddb 100644 --- a/crates/assists/src/handlers/reorder_fields.rs +++ b/crates/assists/src/handlers/reorder_fields.rs | |||
@@ -15,7 +15,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
15 | // | 15 | // |
16 | // ``` | 16 | // ``` |
17 | // struct Foo {foo: i32, bar: i32}; | 17 | // struct Foo {foo: i32, bar: i32}; |
18 | // const test: Foo = <|>Foo {bar: 0, foo: 1} | 18 | // const test: Foo = $0Foo {bar: 0, foo: 1} |
19 | // ``` | 19 | // ``` |
20 | // -> | 20 | // -> |
21 | // ``` | 21 | // ``` |
@@ -126,7 +126,7 @@ struct Foo { | |||
126 | bar: i32, | 126 | bar: i32, |
127 | } | 127 | } |
128 | 128 | ||
129 | const test: Foo = <|>Foo { foo: 0, bar: 0 }; | 129 | const test: Foo = $0Foo { foo: 0, bar: 0 }; |
130 | "#, | 130 | "#, |
131 | ) | 131 | ) |
132 | } | 132 | } |
@@ -137,7 +137,7 @@ const test: Foo = <|>Foo { foo: 0, bar: 0 }; | |||
137 | reorder_fields, | 137 | reorder_fields, |
138 | r#" | 138 | r#" |
139 | struct Foo {}; | 139 | struct Foo {}; |
140 | const test: Foo = <|>Foo {} | 140 | const test: Foo = $0Foo {} |
141 | "#, | 141 | "#, |
142 | ) | 142 | ) |
143 | } | 143 | } |
@@ -148,7 +148,7 @@ const test: Foo = <|>Foo {} | |||
148 | reorder_fields, | 148 | reorder_fields, |
149 | r#" | 149 | r#" |
150 | struct Foo {foo: i32, bar: i32}; | 150 | struct Foo {foo: i32, bar: i32}; |
151 | const test: Foo = <|>Foo {bar: 0, foo: 1} | 151 | const test: Foo = $0Foo {bar: 0, foo: 1} |
152 | "#, | 152 | "#, |
153 | r#" | 153 | r#" |
154 | struct Foo {foo: i32, bar: i32}; | 154 | struct Foo {foo: i32, bar: i32}; |
@@ -166,7 +166,7 @@ struct Foo { foo: i64, bar: i64, baz: i64 } | |||
166 | 166 | ||
167 | fn f(f: Foo) -> { | 167 | fn f(f: Foo) -> { |
168 | match f { | 168 | match f { |
169 | <|>Foo { baz: 0, ref mut bar, .. } => (), | 169 | $0Foo { baz: 0, ref mut bar, .. } => (), |
170 | _ => () | 170 | _ => () |
171 | } | 171 | } |
172 | } | 172 | } |
@@ -197,7 +197,7 @@ struct Foo { | |||
197 | impl Foo { | 197 | impl Foo { |
198 | fn new() -> Foo { | 198 | fn new() -> Foo { |
199 | let foo = String::new(); | 199 | let foo = String::new(); |
200 | <|>Foo { | 200 | $0Foo { |
201 | bar: foo.clone(), | 201 | bar: foo.clone(), |
202 | extra: "Extra field", | 202 | extra: "Extra field", |
203 | foo, | 203 | foo, |
diff --git a/crates/assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/assists/src/handlers/replace_derive_with_manual_impl.rs index cb7a5c104..bd4c1c806 100644 --- a/crates/assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/crates/assists/src/handlers/replace_derive_with_manual_impl.rs | |||
@@ -22,7 +22,7 @@ use crate::{ | |||
22 | // | 22 | // |
23 | // ``` | 23 | // ``` |
24 | // # trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; } | 24 | // # trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; } |
25 | // #[derive(Deb<|>ug, Display)] | 25 | // #[derive(Deb$0ug, Display)] |
26 | // struct S; | 26 | // struct S; |
27 | // ``` | 27 | // ``` |
28 | // -> | 28 | // -> |
@@ -219,7 +219,7 @@ mod fmt { | |||
219 | } | 219 | } |
220 | } | 220 | } |
221 | 221 | ||
222 | #[derive(Debu<|>g)] | 222 | #[derive(Debu$0g)] |
223 | struct Foo { | 223 | struct Foo { |
224 | bar: String, | 224 | bar: String, |
225 | } | 225 | } |
@@ -261,7 +261,7 @@ mod foo { | |||
261 | } | 261 | } |
262 | } | 262 | } |
263 | 263 | ||
264 | #[derive(<|>Bar)] | 264 | #[derive($0Bar)] |
265 | struct Foo { | 265 | struct Foo { |
266 | bar: String, | 266 | bar: String, |
267 | } | 267 | } |
@@ -300,7 +300,7 @@ impl foo::Bar for Foo { | |||
300 | check_assist( | 300 | check_assist( |
301 | replace_derive_with_manual_impl, | 301 | replace_derive_with_manual_impl, |
302 | " | 302 | " |
303 | #[derive(Debu<|>g)] | 303 | #[derive(Debu$0g)] |
304 | struct Foo { | 304 | struct Foo { |
305 | bar: String, | 305 | bar: String, |
306 | } | 306 | } |
@@ -322,7 +322,7 @@ impl Debug for Foo { | |||
322 | check_assist( | 322 | check_assist( |
323 | replace_derive_with_manual_impl, | 323 | replace_derive_with_manual_impl, |
324 | " | 324 | " |
325 | #[derive(Debug<|>)] | 325 | #[derive(Debug$0)] |
326 | pub struct Foo { | 326 | pub struct Foo { |
327 | bar: String, | 327 | bar: String, |
328 | } | 328 | } |
@@ -344,7 +344,7 @@ impl Debug for Foo { | |||
344 | check_assist( | 344 | check_assist( |
345 | replace_derive_with_manual_impl, | 345 | replace_derive_with_manual_impl, |
346 | " | 346 | " |
347 | #[derive(Display, Debug<|>, Serialize)] | 347 | #[derive(Display, Debug$0, Serialize)] |
348 | struct Foo {} | 348 | struct Foo {} |
349 | ", | 349 | ", |
350 | " | 350 | " |
@@ -363,7 +363,7 @@ impl Debug for Foo { | |||
363 | check_assist_not_applicable( | 363 | check_assist_not_applicable( |
364 | replace_derive_with_manual_impl, | 364 | replace_derive_with_manual_impl, |
365 | " | 365 | " |
366 | #[derive(<|>)] | 366 | #[derive($0)] |
367 | struct Foo {} | 367 | struct Foo {} |
368 | ", | 368 | ", |
369 | ) | 369 | ) |
@@ -374,7 +374,7 @@ struct Foo {} | |||
374 | check_assist_not_applicable( | 374 | check_assist_not_applicable( |
375 | replace_derive_with_manual_impl, | 375 | replace_derive_with_manual_impl, |
376 | " | 376 | " |
377 | #[derive<|>(Debug)] | 377 | #[derive$0(Debug)] |
378 | struct Foo {} | 378 | struct Foo {} |
379 | ", | 379 | ", |
380 | ); | 380 | ); |
@@ -382,7 +382,7 @@ struct Foo {} | |||
382 | check_assist_not_applicable( | 382 | check_assist_not_applicable( |
383 | replace_derive_with_manual_impl, | 383 | replace_derive_with_manual_impl, |
384 | " | 384 | " |
385 | #[derive(Debug)<|>] | 385 | #[derive(Debug)$0] |
386 | struct Foo {} | 386 | struct Foo {} |
387 | ", | 387 | ", |
388 | ) | 388 | ) |
@@ -393,7 +393,7 @@ struct Foo {} | |||
393 | check_assist_not_applicable( | 393 | check_assist_not_applicable( |
394 | replace_derive_with_manual_impl, | 394 | replace_derive_with_manual_impl, |
395 | " | 395 | " |
396 | #[allow(non_camel_<|>case_types)] | 396 | #[allow(non_camel_$0case_types)] |
397 | struct Foo {} | 397 | struct Foo {} |
398 | ", | 398 | ", |
399 | ) | 399 | ) |
diff --git a/crates/assists/src/handlers/replace_if_let_with_match.rs b/crates/assists/src/handlers/replace_if_let_with_match.rs index b67219222..aee3397ab 100644 --- a/crates/assists/src/handlers/replace_if_let_with_match.rs +++ b/crates/assists/src/handlers/replace_if_let_with_match.rs | |||
@@ -20,7 +20,7 @@ use crate::{utils::unwrap_trivial_block, AssistContext, AssistId, AssistKind, As | |||
20 | // enum Action { Move { distance: u32 }, Stop } | 20 | // enum Action { Move { distance: u32 }, Stop } |
21 | // | 21 | // |
22 | // fn handle(action: Action) { | 22 | // fn handle(action: Action) { |
23 | // <|>if let Action::Move { distance } = action { | 23 | // $0if let Action::Move { distance } = action { |
24 | // foo(distance) | 24 | // foo(distance) |
25 | // } else { | 25 | // } else { |
26 | // bar() | 26 | // bar() |
@@ -89,7 +89,7 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext) | |||
89 | // enum Action { Move { distance: u32 }, Stop } | 89 | // enum Action { Move { distance: u32 }, Stop } |
90 | // | 90 | // |
91 | // fn handle(action: Action) { | 91 | // fn handle(action: Action) { |
92 | // <|>match action { | 92 | // $0match action { |
93 | // Action::Move { distance } => foo(distance), | 93 | // Action::Move { distance } => foo(distance), |
94 | // _ => bar(), | 94 | // _ => bar(), |
95 | // } | 95 | // } |
@@ -179,7 +179,7 @@ mod tests { | |||
179 | r#" | 179 | r#" |
180 | impl VariantData { | 180 | impl VariantData { |
181 | pub fn is_struct(&self) -> bool { | 181 | pub fn is_struct(&self) -> bool { |
182 | if <|>let VariantData::Struct(..) = *self { | 182 | if $0let VariantData::Struct(..) = *self { |
183 | true | 183 | true |
184 | } else { | 184 | } else { |
185 | false | 185 | false |
@@ -204,7 +204,7 @@ impl VariantData { | |||
204 | replace_if_let_with_match, | 204 | replace_if_let_with_match, |
205 | r#" | 205 | r#" |
206 | fn foo() { | 206 | fn foo() { |
207 | if <|>let VariantData::Struct(..) = a { | 207 | if $0let VariantData::Struct(..) = a { |
208 | bar( | 208 | bar( |
209 | 123 | 209 | 123 |
210 | ) | 210 | ) |
@@ -233,7 +233,7 @@ fn foo() { | |||
233 | r#" | 233 | r#" |
234 | impl VariantData { | 234 | impl VariantData { |
235 | pub fn is_struct(&self) -> bool { | 235 | pub fn is_struct(&self) -> bool { |
236 | if <|>let VariantData::Struct(..) = *self { | 236 | if $0let VariantData::Struct(..) = *self { |
237 | true | 237 | true |
238 | } else { | 238 | } else { |
239 | false | 239 | false |
@@ -257,7 +257,7 @@ enum Option<T> { Some(T), None } | |||
257 | use Option::*; | 257 | use Option::*; |
258 | 258 | ||
259 | fn foo(x: Option<i32>) { | 259 | fn foo(x: Option<i32>) { |
260 | <|>if let Some(x) = x { | 260 | $0if let Some(x) = x { |
261 | println!("{}", x) | 261 | println!("{}", x) |
262 | } else { | 262 | } else { |
263 | println!("none") | 263 | println!("none") |
@@ -287,7 +287,7 @@ enum Result<T, E> { Ok(T), Err(E) } | |||
287 | use Result::*; | 287 | use Result::*; |
288 | 288 | ||
289 | fn foo(x: Result<i32, ()>) { | 289 | fn foo(x: Result<i32, ()>) { |
290 | <|>if let Ok(x) = x { | 290 | $0if let Ok(x) = x { |
291 | println!("{}", x) | 291 | println!("{}", x) |
292 | } else { | 292 | } else { |
293 | println!("none") | 293 | println!("none") |
@@ -315,7 +315,7 @@ fn foo(x: Result<i32, ()>) { | |||
315 | r#" | 315 | r#" |
316 | fn main() { | 316 | fn main() { |
317 | if true { | 317 | if true { |
318 | <|>if let Ok(rel_path) = path.strip_prefix(root_path) { | 318 | $0if let Ok(rel_path) = path.strip_prefix(root_path) { |
319 | let rel_path = RelativePathBuf::from_path(rel_path).ok()?; | 319 | let rel_path = RelativePathBuf::from_path(rel_path).ok()?; |
320 | Some((*id, rel_path)) | 320 | Some((*id, rel_path)) |
321 | } else { | 321 | } else { |
@@ -347,7 +347,7 @@ fn main() { | |||
347 | r#" | 347 | r#" |
348 | impl VariantData { | 348 | impl VariantData { |
349 | pub fn is_struct(&self) -> bool { | 349 | pub fn is_struct(&self) -> bool { |
350 | <|>match *self { | 350 | $0match *self { |
351 | VariantData::Struct(..) => true, | 351 | VariantData::Struct(..) => true, |
352 | _ => false, | 352 | _ => false, |
353 | } | 353 | } |
@@ -372,7 +372,7 @@ impl VariantData { | |||
372 | replace_match_with_if_let, | 372 | replace_match_with_if_let, |
373 | r#" | 373 | r#" |
374 | fn foo() { | 374 | fn foo() { |
375 | <|>match a { | 375 | $0match a { |
376 | VariantData::Struct(..) => { | 376 | VariantData::Struct(..) => { |
377 | bar( | 377 | bar( |
378 | 123 | 378 | 123 |
@@ -401,7 +401,7 @@ fn foo() { | |||
401 | r#" | 401 | r#" |
402 | impl VariantData { | 402 | impl VariantData { |
403 | pub fn is_struct(&self) -> bool { | 403 | pub fn is_struct(&self) -> bool { |
404 | <|>match *self { | 404 | $0match *self { |
405 | VariantData::Struct(..) => true, | 405 | VariantData::Struct(..) => true, |
406 | _ => false, | 406 | _ => false, |
407 | } | 407 | } |
@@ -423,7 +423,7 @@ enum Option<T> { Some(T), None } | |||
423 | use Option::*; | 423 | use Option::*; |
424 | 424 | ||
425 | fn foo(x: Option<i32>) { | 425 | fn foo(x: Option<i32>) { |
426 | <|>match x { | 426 | $0match x { |
427 | Some(x) => println!("{}", x), | 427 | Some(x) => println!("{}", x), |
428 | None => println!("none"), | 428 | None => println!("none"), |
429 | } | 429 | } |
@@ -453,7 +453,7 @@ enum Result<T, E> { Ok(T), Err(E) } | |||
453 | use Result::*; | 453 | use Result::*; |
454 | 454 | ||
455 | fn foo(x: Result<i32, ()>) { | 455 | fn foo(x: Result<i32, ()>) { |
456 | <|>match x { | 456 | $0match x { |
457 | Ok(x) => println!("{}", x), | 457 | Ok(x) => println!("{}", x), |
458 | Err(_) => println!("none"), | 458 | Err(_) => println!("none"), |
459 | } | 459 | } |
@@ -481,7 +481,7 @@ fn foo(x: Result<i32, ()>) { | |||
481 | r#" | 481 | r#" |
482 | fn main() { | 482 | fn main() { |
483 | if true { | 483 | if true { |
484 | <|>match path.strip_prefix(root_path) { | 484 | $0match path.strip_prefix(root_path) { |
485 | Ok(rel_path) => { | 485 | Ok(rel_path) => { |
486 | let rel_path = RelativePathBuf::from_path(rel_path).ok()?; | 486 | let rel_path = RelativePathBuf::from_path(rel_path).ok()?; |
487 | Some((*id, rel_path)) | 487 | Some((*id, rel_path)) |
@@ -512,7 +512,7 @@ fn main() { | |||
512 | replace_match_with_if_let, | 512 | replace_match_with_if_let, |
513 | r#" | 513 | r#" |
514 | fn main() { | 514 | fn main() { |
515 | <|>match path.strip_prefix(root_path) { | 515 | $0match path.strip_prefix(root_path) { |
516 | Ok(rel_path) => println!("{}", rel_path), | 516 | Ok(rel_path) => println!("{}", rel_path), |
517 | _ => (), | 517 | _ => (), |
518 | } | 518 | } |
diff --git a/crates/assists/src/handlers/replace_impl_trait_with_generic.rs b/crates/assists/src/handlers/replace_impl_trait_with_generic.rs index 6738bc134..ff25b61ea 100644 --- a/crates/assists/src/handlers/replace_impl_trait_with_generic.rs +++ b/crates/assists/src/handlers/replace_impl_trait_with_generic.rs | |||
@@ -7,7 +7,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
7 | // Replaces `impl Trait` function argument with the named generic. | 7 | // Replaces `impl Trait` function argument with the named generic. |
8 | // | 8 | // |
9 | // ``` | 9 | // ``` |
10 | // fn foo(bar: <|>impl Bar) {} | 10 | // fn foo(bar: $0impl Bar) {} |
11 | // ``` | 11 | // ``` |
12 | // -> | 12 | // -> |
13 | // ``` | 13 | // ``` |
@@ -56,7 +56,7 @@ mod tests { | |||
56 | check_assist( | 56 | check_assist( |
57 | replace_impl_trait_with_generic, | 57 | replace_impl_trait_with_generic, |
58 | r#" | 58 | r#" |
59 | fn foo<G>(bar: <|>impl Bar) {} | 59 | fn foo<G>(bar: $0impl Bar) {} |
60 | "#, | 60 | "#, |
61 | r#" | 61 | r#" |
62 | fn foo<G, B: Bar>(bar: B) {} | 62 | fn foo<G, B: Bar>(bar: B) {} |
@@ -69,7 +69,7 @@ mod tests { | |||
69 | check_assist( | 69 | check_assist( |
70 | replace_impl_trait_with_generic, | 70 | replace_impl_trait_with_generic, |
71 | r#" | 71 | r#" |
72 | fn foo(bar: <|>impl Bar) {} | 72 | fn foo(bar: $0impl Bar) {} |
73 | "#, | 73 | "#, |
74 | r#" | 74 | r#" |
75 | fn foo<B: Bar>(bar: B) {} | 75 | fn foo<B: Bar>(bar: B) {} |
@@ -82,7 +82,7 @@ mod tests { | |||
82 | check_assist( | 82 | check_assist( |
83 | replace_impl_trait_with_generic, | 83 | replace_impl_trait_with_generic, |
84 | r#" | 84 | r#" |
85 | fn foo<G>(foo: impl Foo, bar: <|>impl Bar) {} | 85 | fn foo<G>(foo: impl Foo, bar: $0impl Bar) {} |
86 | "#, | 86 | "#, |
87 | r#" | 87 | r#" |
88 | fn foo<G, B: Bar>(foo: impl Foo, bar: B) {} | 88 | fn foo<G, B: Bar>(foo: impl Foo, bar: B) {} |
@@ -95,7 +95,7 @@ mod tests { | |||
95 | check_assist( | 95 | check_assist( |
96 | replace_impl_trait_with_generic, | 96 | replace_impl_trait_with_generic, |
97 | r#" | 97 | r#" |
98 | fn foo<>(bar: <|>impl Bar) {} | 98 | fn foo<>(bar: $0impl Bar) {} |
99 | "#, | 99 | "#, |
100 | r#" | 100 | r#" |
101 | fn foo<B: Bar>(bar: B) {} | 101 | fn foo<B: Bar>(bar: B) {} |
@@ -109,7 +109,7 @@ mod tests { | |||
109 | replace_impl_trait_with_generic, | 109 | replace_impl_trait_with_generic, |
110 | r#" | 110 | r#" |
111 | fn foo< | 111 | fn foo< |
112 | >(bar: <|>impl Bar) {} | 112 | >(bar: $0impl Bar) {} |
113 | "#, | 113 | "#, |
114 | r#" | 114 | r#" |
115 | fn foo<B: Bar | 115 | fn foo<B: Bar |
@@ -124,7 +124,7 @@ mod tests { | |||
124 | check_assist( | 124 | check_assist( |
125 | replace_impl_trait_with_generic, | 125 | replace_impl_trait_with_generic, |
126 | r#" | 126 | r#" |
127 | fn foo<B>(bar: <|>impl Bar) {} | 127 | fn foo<B>(bar: $0impl Bar) {} |
128 | "#, | 128 | "#, |
129 | r#" | 129 | r#" |
130 | fn foo<B, C: Bar>(bar: C) {} | 130 | fn foo<B, C: Bar>(bar: C) {} |
@@ -141,7 +141,7 @@ mod tests { | |||
141 | G: Foo, | 141 | G: Foo, |
142 | F, | 142 | F, |
143 | H, | 143 | H, |
144 | >(bar: <|>impl Bar) {} | 144 | >(bar: $0impl Bar) {} |
145 | "#, | 145 | "#, |
146 | r#" | 146 | r#" |
147 | fn foo< | 147 | fn foo< |
@@ -158,7 +158,7 @@ mod tests { | |||
158 | check_assist( | 158 | check_assist( |
159 | replace_impl_trait_with_generic, | 159 | replace_impl_trait_with_generic, |
160 | r#" | 160 | r#" |
161 | fn foo(bar: <|>impl Foo + Bar) {} | 161 | fn foo(bar: $0impl Foo + Bar) {} |
162 | "#, | 162 | "#, |
163 | r#" | 163 | r#" |
164 | fn foo<F: Foo + Bar>(bar: F) {} | 164 | fn foo<F: Foo + Bar>(bar: F) {} |
diff --git a/crates/assists/src/handlers/replace_let_with_if_let.rs b/crates/assists/src/handlers/replace_let_with_if_let.rs index 5970e283c..5a27ada6b 100644 --- a/crates/assists/src/handlers/replace_let_with_if_let.rs +++ b/crates/assists/src/handlers/replace_let_with_if_let.rs | |||
@@ -20,7 +20,7 @@ use ide_db::ty_filter::TryEnum; | |||
20 | // # enum Option<T> { Some(T), None } | 20 | // # enum Option<T> { Some(T), None } |
21 | // | 21 | // |
22 | // fn main(action: Action) { | 22 | // fn main(action: Action) { |
23 | // <|>let x = compute(); | 23 | // $0let x = compute(); |
24 | // } | 24 | // } |
25 | // | 25 | // |
26 | // fn compute() -> Option<i32> { None } | 26 | // fn compute() -> Option<i32> { None } |
@@ -85,7 +85,7 @@ mod tests { | |||
85 | enum E<T> { X(T), Y(T) } | 85 | enum E<T> { X(T), Y(T) } |
86 | 86 | ||
87 | fn main() { | 87 | fn main() { |
88 | <|>let x = E::X(92); | 88 | $0let x = E::X(92); |
89 | } | 89 | } |
90 | ", | 90 | ", |
91 | r" | 91 | r" |
diff --git a/crates/assists/src/handlers/replace_qualified_name_with_use.rs b/crates/assists/src/handlers/replace_qualified_name_with_use.rs index 8193e45a8..f3bc6cf39 100644 --- a/crates/assists/src/handlers/replace_qualified_name_with_use.rs +++ b/crates/assists/src/handlers/replace_qualified_name_with_use.rs | |||
@@ -9,7 +9,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
9 | // Adds a use statement for a given fully-qualified name. | 9 | // Adds a use statement for a given fully-qualified name. |
10 | // | 10 | // |
11 | // ``` | 11 | // ``` |
12 | // fn process(map: std::collections::<|>HashMap<String, String>) {} | 12 | // fn process(map: std::collections::$0HashMap<String, String>) {} |
13 | // ``` | 13 | // ``` |
14 | // -> | 14 | // -> |
15 | // ``` | 15 | // ``` |
@@ -127,7 +127,7 @@ mod tests { | |||
127 | r"use std::fs; | 127 | r"use std::fs; |
128 | 128 | ||
129 | fn main() { | 129 | fn main() { |
130 | std::f<|>s::Path | 130 | std::f$0s::Path |
131 | }", | 131 | }", |
132 | r"use std::fs; | 132 | r"use std::fs; |
133 | 133 | ||
@@ -142,7 +142,7 @@ fn main() { | |||
142 | check_assist( | 142 | check_assist( |
143 | replace_qualified_name_with_use, | 143 | replace_qualified_name_with_use, |
144 | r" | 144 | r" |
145 | std::fmt::Debug<|> | 145 | std::fmt::Debug$0 |
146 | ", | 146 | ", |
147 | r" | 147 | r" |
148 | use std::fmt::Debug; | 148 | use std::fmt::Debug; |
@@ -156,7 +156,7 @@ Debug | |||
156 | check_assist( | 156 | check_assist( |
157 | replace_qualified_name_with_use, | 157 | replace_qualified_name_with_use, |
158 | r" | 158 | r" |
159 | std::fmt::Debug<|> | 159 | std::fmt::Debug$0 |
160 | 160 | ||
161 | fn main() { | 161 | fn main() { |
162 | } | 162 | } |
@@ -180,7 +180,7 @@ fn main() { | |||
180 | fn main() { | 180 | fn main() { |
181 | } | 181 | } |
182 | 182 | ||
183 | std::fmt::Debug<|> | 183 | std::fmt::Debug$0 |
184 | ", | 184 | ", |
185 | r" | 185 | r" |
186 | use std::fmt::Debug; | 186 | use std::fmt::Debug; |
@@ -198,7 +198,7 @@ Debug | |||
198 | check_assist( | 198 | check_assist( |
199 | replace_qualified_name_with_use, | 199 | replace_qualified_name_with_use, |
200 | r" | 200 | r" |
201 | std::fmt<|>::Debug | 201 | std::fmt$0::Debug |
202 | ", | 202 | ", |
203 | r" | 203 | r" |
204 | use std::fmt; | 204 | use std::fmt; |
@@ -215,7 +215,7 @@ fmt::Debug | |||
215 | r" | 215 | r" |
216 | use stdx; | 216 | use stdx; |
217 | 217 | ||
218 | impl std::fmt::Debug<|> for Foo { | 218 | impl std::fmt::Debug$0 for Foo { |
219 | } | 219 | } |
220 | ", | 220 | ", |
221 | r" | 221 | r" |
@@ -234,7 +234,7 @@ impl Debug for Foo { | |||
234 | check_assist( | 234 | check_assist( |
235 | replace_qualified_name_with_use, | 235 | replace_qualified_name_with_use, |
236 | r" | 236 | r" |
237 | impl std::fmt::Debug<|> for Foo { | 237 | impl std::fmt::Debug$0 for Foo { |
238 | } | 238 | } |
239 | ", | 239 | ", |
240 | r" | 240 | r" |
@@ -251,7 +251,7 @@ impl Debug for Foo { | |||
251 | check_assist( | 251 | check_assist( |
252 | replace_qualified_name_with_use, | 252 | replace_qualified_name_with_use, |
253 | r" | 253 | r" |
254 | impl std::fmt::Debug<|> for Foo { | 254 | impl std::fmt::Debug$0 for Foo { |
255 | } | 255 | } |
256 | ", | 256 | ", |
257 | r" | 257 | r" |
@@ -270,7 +270,7 @@ impl Debug for Foo { | |||
270 | r" | 270 | r" |
271 | use std::fmt; | 271 | use std::fmt; |
272 | 272 | ||
273 | impl std::io<|> for Foo { | 273 | impl std::io$0 for Foo { |
274 | } | 274 | } |
275 | ", | 275 | ", |
276 | r" | 276 | r" |
@@ -289,7 +289,7 @@ impl io for Foo { | |||
289 | r" | 289 | r" |
290 | use std::fmt; | 290 | use std::fmt; |
291 | 291 | ||
292 | impl std::fmt::Debug<|> for Foo { | 292 | impl std::fmt::Debug$0 for Foo { |
293 | } | 293 | } |
294 | ", | 294 | ", |
295 | r" | 295 | r" |
@@ -308,7 +308,7 @@ impl Debug for Foo { | |||
308 | r" | 308 | r" |
309 | use std::fmt::Debug; | 309 | use std::fmt::Debug; |
310 | 310 | ||
311 | impl std::fmt<|> for Foo { | 311 | impl std::fmt$0 for Foo { |
312 | } | 312 | } |
313 | ", | 313 | ", |
314 | r" | 314 | r" |
@@ -327,7 +327,7 @@ impl fmt for Foo { | |||
327 | r" | 327 | r" |
328 | use std::fmt::{Debug, nested::{Display}}; | 328 | use std::fmt::{Debug, nested::{Display}}; |
329 | 329 | ||
330 | impl std::fmt::nested<|> for Foo { | 330 | impl std::fmt::nested$0 for Foo { |
331 | } | 331 | } |
332 | ", | 332 | ", |
333 | r" | 333 | r" |
@@ -346,7 +346,7 @@ impl nested for Foo { | |||
346 | r" | 346 | r" |
347 | use std::fmt::{Debug, nested::{self, Display}}; | 347 | use std::fmt::{Debug, nested::{self, Display}}; |
348 | 348 | ||
349 | impl std::fmt::nested<|> for Foo { | 349 | impl std::fmt::nested$0 for Foo { |
350 | } | 350 | } |
351 | ", | 351 | ", |
352 | r" | 352 | r" |
@@ -365,7 +365,7 @@ impl nested for Foo { | |||
365 | r" | 365 | r" |
366 | use std::fmt::{Debug, nested::{Display}}; | 366 | use std::fmt::{Debug, nested::{Display}}; |
367 | 367 | ||
368 | impl std::fmt::nested::Debug<|> for Foo { | 368 | impl std::fmt::nested::Debug$0 for Foo { |
369 | } | 369 | } |
370 | ", | 370 | ", |
371 | r" | 371 | r" |
@@ -384,7 +384,7 @@ impl Debug for Foo { | |||
384 | r" | 384 | r" |
385 | use std::fmt::Debug; | 385 | use std::fmt::Debug; |
386 | 386 | ||
387 | impl std::fmt::nested::Display<|> for Foo { | 387 | impl std::fmt::nested::Display$0 for Foo { |
388 | } | 388 | } |
389 | ", | 389 | ", |
390 | r" | 390 | r" |
@@ -403,7 +403,7 @@ impl Display for Foo { | |||
403 | r" | 403 | r" |
404 | use std::fmt::nested::Debug; | 404 | use std::fmt::nested::Debug; |
405 | 405 | ||
406 | impl std::fmt::Display<|> for Foo { | 406 | impl std::fmt::Display$0 for Foo { |
407 | } | 407 | } |
408 | ", | 408 | ", |
409 | r" | 409 | r" |
@@ -425,7 +425,7 @@ use crate::{ | |||
425 | AssocItem, | 425 | AssocItem, |
426 | }; | 426 | }; |
427 | 427 | ||
428 | fn foo() { crate::ty::lower<|>::trait_env() } | 428 | fn foo() { crate::ty::lower$0::trait_env() } |
429 | ", | 429 | ", |
430 | r" | 430 | r" |
431 | use crate::{AssocItem, ty::{Substs, Ty, lower}}; | 431 | use crate::{AssocItem, ty::{Substs, Ty, lower}}; |
@@ -442,7 +442,7 @@ fn foo() { lower::trait_env() } | |||
442 | r" | 442 | r" |
443 | use std::fmt as foo; | 443 | use std::fmt as foo; |
444 | 444 | ||
445 | impl foo::Debug<|> for Foo { | 445 | impl foo::Debug$0 for Foo { |
446 | } | 446 | } |
447 | ", | 447 | ", |
448 | r" | 448 | r" |
@@ -462,7 +462,7 @@ impl Debug for Foo { | |||
462 | check_assist_not_applicable( | 462 | check_assist_not_applicable( |
463 | replace_qualified_name_with_use, | 463 | replace_qualified_name_with_use, |
464 | r" | 464 | r" |
465 | impl foo<|> for Foo { | 465 | impl foo$0 for Foo { |
466 | } | 466 | } |
467 | ", | 467 | ", |
468 | ); | 468 | ); |
@@ -473,7 +473,7 @@ impl foo<|> for Foo { | |||
473 | check_assist_not_applicable( | 473 | check_assist_not_applicable( |
474 | replace_qualified_name_with_use, | 474 | replace_qualified_name_with_use, |
475 | r" | 475 | r" |
476 | use std::fmt<|>; | 476 | use std::fmt$0; |
477 | ", | 477 | ", |
478 | ); | 478 | ); |
479 | } | 479 | } |
@@ -485,7 +485,7 @@ use std::fmt<|>; | |||
485 | r" | 485 | r" |
486 | mod foo { | 486 | mod foo { |
487 | mod bar { | 487 | mod bar { |
488 | std::fmt::Debug<|> | 488 | std::fmt::Debug$0 |
489 | } | 489 | } |
490 | } | 490 | } |
491 | ", | 491 | ", |
@@ -509,7 +509,7 @@ mod foo { | |||
509 | #![allow(dead_code)] | 509 | #![allow(dead_code)] |
510 | 510 | ||
511 | fn main() { | 511 | fn main() { |
512 | std::fmt::Debug<|> | 512 | std::fmt::Debug$0 |
513 | } | 513 | } |
514 | ", | 514 | ", |
515 | r" | 515 | r" |
@@ -530,7 +530,7 @@ fn main() { | |||
530 | replace_qualified_name_with_use, | 530 | replace_qualified_name_with_use, |
531 | r" | 531 | r" |
532 | fn main() { | 532 | fn main() { |
533 | std::fmt::Debug<|>; | 533 | std::fmt::Debug$0; |
534 | let x: std::fmt::Debug = std::fmt::Debug; | 534 | let x: std::fmt::Debug = std::fmt::Debug; |
535 | } | 535 | } |
536 | ", | 536 | ", |
@@ -552,7 +552,7 @@ fn main() { | |||
552 | r" | 552 | r" |
553 | mod m { | 553 | mod m { |
554 | fn f() { | 554 | fn f() { |
555 | std::fmt::Debug<|>; | 555 | std::fmt::Debug$0; |
556 | let x: std::fmt::Debug = std::fmt::Debug; | 556 | let x: std::fmt::Debug = std::fmt::Debug; |
557 | } | 557 | } |
558 | fn g() { | 558 | fn g() { |
@@ -590,7 +590,7 @@ fn f() { | |||
590 | replace_qualified_name_with_use, | 590 | replace_qualified_name_with_use, |
591 | r" | 591 | r" |
592 | fn main() { | 592 | fn main() { |
593 | std::fmt::Debug<|>; | 593 | std::fmt::Debug$0; |
594 | } | 594 | } |
595 | 595 | ||
596 | mod sub { | 596 | mod sub { |
@@ -623,7 +623,7 @@ mod sub { | |||
623 | use std::fmt::Display; | 623 | use std::fmt::Display; |
624 | 624 | ||
625 | fn main() { | 625 | fn main() { |
626 | std::fmt<|>; | 626 | std::fmt$0; |
627 | } | 627 | } |
628 | ", | 628 | ", |
629 | r" | 629 | r" |
@@ -643,7 +643,7 @@ fn main() { | |||
643 | r" | 643 | r" |
644 | pub use std::fmt; | 644 | pub use std::fmt; |
645 | 645 | ||
646 | impl std::io<|> for Foo { | 646 | impl std::io$0 for Foo { |
647 | } | 647 | } |
648 | ", | 648 | ", |
649 | r" | 649 | r" |
@@ -663,7 +663,7 @@ impl io for Foo { | |||
663 | r" | 663 | r" |
664 | pub(crate) use std::fmt; | 664 | pub(crate) use std::fmt; |
665 | 665 | ||
666 | impl std::io<|> for Foo { | 666 | impl std::io$0 for Foo { |
667 | } | 667 | } |
668 | ", | 668 | ", |
669 | r" | 669 | r" |
diff --git a/crates/assists/src/handlers/replace_string_with_char.rs b/crates/assists/src/handlers/replace_string_with_char.rs index b4b898846..317318c24 100644 --- a/crates/assists/src/handlers/replace_string_with_char.rs +++ b/crates/assists/src/handlers/replace_string_with_char.rs | |||
@@ -8,7 +8,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
8 | // | 8 | // |
9 | // ``` | 9 | // ``` |
10 | // fn main() { | 10 | // fn main() { |
11 | // find("{<|>"); | 11 | // find("{$0"); |
12 | // } | 12 | // } |
13 | // ``` | 13 | // ``` |
14 | // -> | 14 | // -> |
@@ -48,7 +48,7 @@ mod tests { | |||
48 | replace_string_with_char, | 48 | replace_string_with_char, |
49 | r#" | 49 | r#" |
50 | fn f() { | 50 | fn f() { |
51 | let s = "<|>c"; | 51 | let s = "$0c"; |
52 | } | 52 | } |
53 | "#, | 53 | "#, |
54 | r#""c""#, | 54 | r#""c""#, |
@@ -61,7 +61,7 @@ mod tests { | |||
61 | replace_string_with_char, | 61 | replace_string_with_char, |
62 | r#" | 62 | r#" |
63 | fn f() { | 63 | fn f() { |
64 | let s = "<|>c"; | 64 | let s = "$0c"; |
65 | } | 65 | } |
66 | "#, | 66 | "#, |
67 | r##" | 67 | r##" |
@@ -78,7 +78,7 @@ mod tests { | |||
78 | replace_string_with_char, | 78 | replace_string_with_char, |
79 | r#" | 79 | r#" |
80 | fn f() { | 80 | fn f() { |
81 | let s = "<|>😀"; | 81 | let s = "$0😀"; |
82 | } | 82 | } |
83 | "#, | 83 | "#, |
84 | r##" | 84 | r##" |
@@ -95,7 +95,7 @@ mod tests { | |||
95 | replace_string_with_char, | 95 | replace_string_with_char, |
96 | r#" | 96 | r#" |
97 | fn f() { | 97 | fn f() { |
98 | let s = "<|>test"; | 98 | let s = "$0test"; |
99 | } | 99 | } |
100 | "#, | 100 | "#, |
101 | ) | 101 | ) |
@@ -107,7 +107,7 @@ mod tests { | |||
107 | replace_string_with_char, | 107 | replace_string_with_char, |
108 | r#" | 108 | r#" |
109 | fn f() { | 109 | fn f() { |
110 | format!(<|>"x", 92) | 110 | format!($0"x", 92) |
111 | } | 111 | } |
112 | "#, | 112 | "#, |
113 | r##" | 113 | r##" |
@@ -124,7 +124,7 @@ mod tests { | |||
124 | replace_string_with_char, | 124 | replace_string_with_char, |
125 | r#" | 125 | r#" |
126 | fn f() { | 126 | fn f() { |
127 | find(<|>"x"); | 127 | find($0"x"); |
128 | } | 128 | } |
129 | "#, | 129 | "#, |
130 | r##" | 130 | r##" |
diff --git a/crates/assists/src/handlers/replace_unwrap_with_match.rs b/crates/assists/src/handlers/replace_unwrap_with_match.rs index f547066f0..a986a6ae8 100644 --- a/crates/assists/src/handlers/replace_unwrap_with_match.rs +++ b/crates/assists/src/handlers/replace_unwrap_with_match.rs | |||
@@ -23,7 +23,7 @@ use ide_db::ty_filter::TryEnum; | |||
23 | // enum Result<T, E> { Ok(T), Err(E) } | 23 | // enum Result<T, E> { Ok(T), Err(E) } |
24 | // fn main() { | 24 | // fn main() { |
25 | // let x: Result<i32, i32> = Result::Ok(92); | 25 | // let x: Result<i32, i32> = Result::Ok(92); |
26 | // let y = x.<|>unwrap(); | 26 | // let y = x.$0unwrap(); |
27 | // } | 27 | // } |
28 | // ``` | 28 | // ``` |
29 | // -> | 29 | // -> |
@@ -101,7 +101,7 @@ enum Result<T, E> { Ok(T), Err(E) } | |||
101 | fn i<T>(a: T) -> T { a } | 101 | fn i<T>(a: T) -> T { a } |
102 | fn main() { | 102 | fn main() { |
103 | let x: Result<i32, i32> = Result::Ok(92); | 103 | let x: Result<i32, i32> = Result::Ok(92); |
104 | let y = i(x).<|>unwrap(); | 104 | let y = i(x).$0unwrap(); |
105 | } | 105 | } |
106 | ", | 106 | ", |
107 | r" | 107 | r" |
@@ -127,7 +127,7 @@ enum Option<T> { Some(T), None } | |||
127 | fn i<T>(a: T) -> T { a } | 127 | fn i<T>(a: T) -> T { a } |
128 | fn main() { | 128 | fn main() { |
129 | let x = Option::Some(92); | 129 | let x = Option::Some(92); |
130 | let y = i(x).<|>unwrap(); | 130 | let y = i(x).$0unwrap(); |
131 | } | 131 | } |
132 | ", | 132 | ", |
133 | r" | 133 | r" |
@@ -153,7 +153,7 @@ enum Result<T, E> { Ok(T), Err(E) } | |||
153 | fn i<T>(a: T) -> T { a } | 153 | fn i<T>(a: T) -> T { a } |
154 | fn main() { | 154 | fn main() { |
155 | let x: Result<i32, i32> = Result::Ok(92); | 155 | let x: Result<i32, i32> = Result::Ok(92); |
156 | let y = i(x).<|>unwrap().count_zeroes(); | 156 | let y = i(x).$0unwrap().count_zeroes(); |
157 | } | 157 | } |
158 | ", | 158 | ", |
159 | r" | 159 | r" |
@@ -179,7 +179,7 @@ enum Option<T> { Some(T), None } | |||
179 | fn i<T>(a: T) -> T { a } | 179 | fn i<T>(a: T) -> T { a } |
180 | fn main() { | 180 | fn main() { |
181 | let x = Option::Some(92); | 181 | let x = Option::Some(92); |
182 | let y = i(x).<|>unwrap(); | 182 | let y = i(x).$0unwrap(); |
183 | } | 183 | } |
184 | ", | 184 | ", |
185 | r"i(x).unwrap()", | 185 | r"i(x).unwrap()", |
diff --git a/crates/assists/src/handlers/split_import.rs b/crates/assists/src/handlers/split_import.rs index ef1f6b8a1..9319a4267 100644 --- a/crates/assists/src/handlers/split_import.rs +++ b/crates/assists/src/handlers/split_import.rs | |||
@@ -9,7 +9,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
9 | // Wraps the tail of import into braces. | 9 | // Wraps the tail of import into braces. |
10 | // | 10 | // |
11 | // ``` | 11 | // ``` |
12 | // use std::<|>collections::HashMap; | 12 | // use std::$0collections::HashMap; |
13 | // ``` | 13 | // ``` |
14 | // -> | 14 | // -> |
15 | // ``` | 15 | // ``` |
@@ -43,7 +43,7 @@ mod tests { | |||
43 | fn test_split_import() { | 43 | fn test_split_import() { |
44 | check_assist( | 44 | check_assist( |
45 | split_import, | 45 | split_import, |
46 | "use crate::<|>db::RootDatabase;", | 46 | "use crate::$0db::RootDatabase;", |
47 | "use crate::{db::RootDatabase};", | 47 | "use crate::{db::RootDatabase};", |
48 | ) | 48 | ) |
49 | } | 49 | } |
@@ -52,19 +52,19 @@ mod tests { | |||
52 | fn split_import_works_with_trees() { | 52 | fn split_import_works_with_trees() { |
53 | check_assist( | 53 | check_assist( |
54 | split_import, | 54 | split_import, |
55 | "use crate:<|>:db::{RootDatabase, FileSymbol}", | 55 | "use crate:$0:db::{RootDatabase, FileSymbol}", |
56 | "use crate::{db::{RootDatabase, FileSymbol}}", | 56 | "use crate::{db::{RootDatabase, FileSymbol}}", |
57 | ) | 57 | ) |
58 | } | 58 | } |
59 | 59 | ||
60 | #[test] | 60 | #[test] |
61 | fn split_import_target() { | 61 | fn split_import_target() { |
62 | check_assist_target(split_import, "use crate::<|>db::{RootDatabase, FileSymbol}", "::"); | 62 | check_assist_target(split_import, "use crate::$0db::{RootDatabase, FileSymbol}", "::"); |
63 | } | 63 | } |
64 | 64 | ||
65 | #[test] | 65 | #[test] |
66 | fn issue4044() { | 66 | fn issue4044() { |
67 | check_assist_not_applicable(split_import, "use crate::<|>:::self;") | 67 | check_assist_not_applicable(split_import, "use crate::$0:::self;") |
68 | } | 68 | } |
69 | 69 | ||
70 | #[test] | 70 | #[test] |
@@ -72,7 +72,7 @@ mod tests { | |||
72 | check_assist_not_applicable( | 72 | check_assist_not_applicable( |
73 | split_import, | 73 | split_import, |
74 | r" | 74 | r" |
75 | use std::<|> | 75 | use std::$0 |
76 | fn main() {}", | 76 | fn main() {}", |
77 | ); | 77 | ); |
78 | } | 78 | } |
diff --git a/crates/assists/src/handlers/toggle_ignore.rs b/crates/assists/src/handlers/toggle_ignore.rs index 14b420421..33e12a7d0 100644 --- a/crates/assists/src/handlers/toggle_ignore.rs +++ b/crates/assists/src/handlers/toggle_ignore.rs | |||
@@ -10,7 +10,7 @@ use crate::{utils::test_related_attribute, AssistContext, AssistId, AssistKind, | |||
10 | // Adds `#[ignore]` attribute to the test. | 10 | // Adds `#[ignore]` attribute to the test. |
11 | // | 11 | // |
12 | // ``` | 12 | // ``` |
13 | // <|>#[test] | 13 | // $0#[test] |
14 | // fn arithmetics { | 14 | // fn arithmetics { |
15 | // assert_eq!(2 + 2, 5); | 15 | // assert_eq!(2 + 2, 5); |
16 | // } | 16 | // } |
@@ -69,7 +69,7 @@ mod tests { | |||
69 | check_assist( | 69 | check_assist( |
70 | toggle_ignore, | 70 | toggle_ignore, |
71 | r#" | 71 | r#" |
72 | #[test<|>] | 72 | #[test$0] |
73 | fn test() {} | 73 | fn test() {} |
74 | "#, | 74 | "#, |
75 | r#" | 75 | r#" |
@@ -85,7 +85,7 @@ mod tests { | |||
85 | check_assist( | 85 | check_assist( |
86 | toggle_ignore, | 86 | toggle_ignore, |
87 | r#" | 87 | r#" |
88 | #[test<|>] | 88 | #[test$0] |
89 | #[ignore] | 89 | #[ignore] |
90 | fn test() {} | 90 | fn test() {} |
91 | "#, | 91 | "#, |
diff --git a/crates/assists/src/handlers/unwrap_block.rs b/crates/assists/src/handlers/unwrap_block.rs index 676db7137..ed6f6177d 100644 --- a/crates/assists/src/handlers/unwrap_block.rs +++ b/crates/assists/src/handlers/unwrap_block.rs | |||
@@ -14,7 +14,7 @@ use crate::{utils::unwrap_trivial_block, AssistContext, AssistId, AssistKind, As | |||
14 | // | 14 | // |
15 | // ``` | 15 | // ``` |
16 | // fn foo() { | 16 | // fn foo() { |
17 | // if true {<|> | 17 | // if true {$0 |
18 | // println!("foo"); | 18 | // println!("foo"); |
19 | // } | 19 | // } |
20 | // } | 20 | // } |
@@ -124,7 +124,7 @@ mod tests { | |||
124 | unwrap_block, | 124 | unwrap_block, |
125 | r#" | 125 | r#" |
126 | fn main() { | 126 | fn main() { |
127 | <|>{ | 127 | $0{ |
128 | 92 | 128 | 92 |
129 | } | 129 | } |
130 | } | 130 | } |
@@ -143,7 +143,7 @@ fn main() { | |||
143 | unwrap_block, | 143 | unwrap_block, |
144 | r#" | 144 | r#" |
145 | fn main() { | 145 | fn main() { |
146 | <|>{ | 146 | $0{ |
147 | 92; | 147 | 92; |
148 | } | 148 | } |
149 | () | 149 | () |
@@ -161,7 +161,7 @@ fn main() { | |||
161 | unwrap_block, | 161 | unwrap_block, |
162 | r#" | 162 | r#" |
163 | fn main() { | 163 | fn main() { |
164 | <|>{ | 164 | $0{ |
165 | 92 | 165 | 92 |
166 | } | 166 | } |
167 | () | 167 | () |
@@ -183,7 +183,7 @@ fn main() { | |||
183 | r#" | 183 | r#" |
184 | fn main() { | 184 | fn main() { |
185 | bar(); | 185 | bar(); |
186 | if true {<|> | 186 | if true {$0 |
187 | foo(); | 187 | foo(); |
188 | 188 | ||
189 | //comment | 189 | //comment |
@@ -217,7 +217,7 @@ fn main() { | |||
217 | 217 | ||
218 | //comment | 218 | //comment |
219 | bar(); | 219 | bar(); |
220 | } else {<|> | 220 | } else {$0 |
221 | println!("bar"); | 221 | println!("bar"); |
222 | } | 222 | } |
223 | } | 223 | } |
@@ -249,7 +249,7 @@ fn main() { | |||
249 | 249 | ||
250 | //comment | 250 | //comment |
251 | //bar(); | 251 | //bar(); |
252 | } else if false {<|> | 252 | } else if false {$0 |
253 | println!("bar"); | 253 | println!("bar"); |
254 | } else { | 254 | } else { |
255 | println!("foo"); | 255 | println!("foo"); |
@@ -285,7 +285,7 @@ fn main() { | |||
285 | //bar(); | 285 | //bar(); |
286 | } else if false { | 286 | } else if false { |
287 | println!("bar"); | 287 | println!("bar"); |
288 | } else if true {<|> | 288 | } else if true {$0 |
289 | println!("foo"); | 289 | println!("foo"); |
290 | } | 290 | } |
291 | } | 291 | } |
@@ -323,7 +323,7 @@ fn main() { | |||
323 | println!("bar"); | 323 | println!("bar"); |
324 | } else if true { | 324 | } else if true { |
325 | println!("foo"); | 325 | println!("foo"); |
326 | } else {<|> | 326 | } else {$0 |
327 | println!("else"); | 327 | println!("else"); |
328 | } | 328 | } |
329 | } | 329 | } |
@@ -361,7 +361,7 @@ fn main() { | |||
361 | //bar(); | 361 | //bar(); |
362 | } else if false { | 362 | } else if false { |
363 | println!("bar"); | 363 | println!("bar"); |
364 | } else if true {<|> | 364 | } else if true {$0 |
365 | println!("foo"); | 365 | println!("foo"); |
366 | } else { | 366 | } else { |
367 | println!("else"); | 367 | println!("else"); |
@@ -391,7 +391,7 @@ fn main() { | |||
391 | unwrap_block, | 391 | unwrap_block, |
392 | r#" | 392 | r#" |
393 | fn main() { | 393 | fn main() { |
394 | bar();<|> | 394 | bar();$0 |
395 | if true { | 395 | if true { |
396 | foo(); | 396 | foo(); |
397 | 397 | ||
@@ -411,7 +411,7 @@ fn main() { | |||
411 | unwrap_block, | 411 | unwrap_block, |
412 | r#" | 412 | r#" |
413 | fn main() { | 413 | fn main() { |
414 | for i in 0..5 {<|> | 414 | for i in 0..5 {$0 |
415 | if true { | 415 | if true { |
416 | foo(); | 416 | foo(); |
417 | 417 | ||
@@ -445,7 +445,7 @@ fn main() { | |||
445 | r#" | 445 | r#" |
446 | fn main() { | 446 | fn main() { |
447 | for i in 0..5 { | 447 | for i in 0..5 { |
448 | if true {<|> | 448 | if true {$0 |
449 | foo(); | 449 | foo(); |
450 | 450 | ||
451 | //comment | 451 | //comment |
@@ -475,7 +475,7 @@ fn main() { | |||
475 | unwrap_block, | 475 | unwrap_block, |
476 | r#" | 476 | r#" |
477 | fn main() { | 477 | fn main() { |
478 | loop {<|> | 478 | loop {$0 |
479 | if true { | 479 | if true { |
480 | foo(); | 480 | foo(); |
481 | 481 | ||
@@ -508,7 +508,7 @@ fn main() { | |||
508 | unwrap_block, | 508 | unwrap_block, |
509 | r#" | 509 | r#" |
510 | fn main() { | 510 | fn main() { |
511 | while true {<|> | 511 | while true {$0 |
512 | if true { | 512 | if true { |
513 | foo(); | 513 | foo(); |
514 | 514 | ||
@@ -542,7 +542,7 @@ fn main() { | |||
542 | r#" | 542 | r#" |
543 | fn main() { | 543 | fn main() { |
544 | match rel_path { | 544 | match rel_path { |
545 | Ok(rel_path) => {<|> | 545 | Ok(rel_path) => {$0 |
546 | let rel_path = RelativePathBuf::from_path(rel_path).ok()?; | 546 | let rel_path = RelativePathBuf::from_path(rel_path).ok()?; |
547 | Some((*id, rel_path)) | 547 | Some((*id, rel_path)) |
548 | } | 548 | } |
@@ -567,7 +567,7 @@ fn main() { | |||
567 | fn main() { | 567 | fn main() { |
568 | while true { | 568 | while true { |
569 | if true { | 569 | if true { |
570 | foo();<|> | 570 | foo();$0 |
571 | 571 | ||
572 | //comment | 572 | //comment |
573 | bar(); | 573 | bar(); |
diff --git a/crates/assists/src/handlers/wrap_return_type_in_result.rs b/crates/assists/src/handlers/wrap_return_type_in_result.rs index 358b61046..fec16fc49 100644 --- a/crates/assists/src/handlers/wrap_return_type_in_result.rs +++ b/crates/assists/src/handlers/wrap_return_type_in_result.rs | |||
@@ -13,7 +13,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
13 | // Wrap the function's return type into Result. | 13 | // Wrap the function's return type into Result. |
14 | // | 14 | // |
15 | // ``` | 15 | // ``` |
16 | // fn foo() -> i32<|> { 42i32 } | 16 | // fn foo() -> i32$0 { 42i32 } |
17 | // ``` | 17 | // ``` |
18 | // -> | 18 | // -> |
19 | // ``` | 19 | // ``` |
@@ -282,7 +282,7 @@ mod tests { | |||
282 | check_assist( | 282 | check_assist( |
283 | wrap_return_type_in_result, | 283 | wrap_return_type_in_result, |
284 | r#" | 284 | r#" |
285 | fn foo() -> i3<|>2 { | 285 | fn foo() -> i3$02 { |
286 | let test = "test"; | 286 | let test = "test"; |
287 | return 42i32; | 287 | return 42i32; |
288 | } | 288 | } |
@@ -302,7 +302,7 @@ fn foo() -> Result<i32, ${0:_}> { | |||
302 | wrap_return_type_in_result, | 302 | wrap_return_type_in_result, |
303 | r#" | 303 | r#" |
304 | fn foo() { | 304 | fn foo() { |
305 | || -> i32<|> { | 305 | || -> i32$0 { |
306 | let test = "test"; | 306 | let test = "test"; |
307 | return 42i32; | 307 | return 42i32; |
308 | }; | 308 | }; |
@@ -325,7 +325,7 @@ fn foo() { | |||
325 | wrap_return_type_in_result, | 325 | wrap_return_type_in_result, |
326 | r#" | 326 | r#" |
327 | fn foo() -> i32 { | 327 | fn foo() -> i32 { |
328 | let test = "test";<|> | 328 | let test = "test";$0 |
329 | return 42i32; | 329 | return 42i32; |
330 | } | 330 | } |
331 | "#, | 331 | "#, |
@@ -339,7 +339,7 @@ fn foo() -> i32 { | |||
339 | r#" | 339 | r#" |
340 | fn foo() { | 340 | fn foo() { |
341 | || -> i32 { | 341 | || -> i32 { |
342 | let test = "test";<|> | 342 | let test = "test";$0 |
343 | return 42i32; | 343 | return 42i32; |
344 | }; | 344 | }; |
345 | } | 345 | } |
@@ -349,7 +349,7 @@ fn foo() { | |||
349 | 349 | ||
350 | #[test] | 350 | #[test] |
351 | fn wrap_return_type_in_result_closure_non_block() { | 351 | fn wrap_return_type_in_result_closure_non_block() { |
352 | check_assist_not_applicable(wrap_return_type_in_result, r#"fn foo() { || -> i<|>32 3; }"#); | 352 | check_assist_not_applicable(wrap_return_type_in_result, r#"fn foo() { || -> i$032 3; }"#); |
353 | } | 353 | } |
354 | 354 | ||
355 | #[test] | 355 | #[test] |
@@ -357,7 +357,7 @@ fn foo() { | |||
357 | check_assist_not_applicable( | 357 | check_assist_not_applicable( |
358 | wrap_return_type_in_result, | 358 | wrap_return_type_in_result, |
359 | r#" | 359 | r#" |
360 | fn foo() -> std::result::Result<i32<|>, String> { | 360 | fn foo() -> std::result::Result<i32$0, String> { |
361 | let test = "test"; | 361 | let test = "test"; |
362 | return 42i32; | 362 | return 42i32; |
363 | } | 363 | } |
@@ -371,7 +371,7 @@ fn foo() -> std::result::Result<i32<|>, String> { | |||
371 | check_assist_not_applicable( | 371 | check_assist_not_applicable( |
372 | wrap_return_type_in_result, | 372 | wrap_return_type_in_result, |
373 | r#" | 373 | r#" |
374 | fn foo() -> Result<i32<|>, String> { | 374 | fn foo() -> Result<i32$0, String> { |
375 | let test = "test"; | 375 | let test = "test"; |
376 | return 42i32; | 376 | return 42i32; |
377 | } | 377 | } |
@@ -385,7 +385,7 @@ fn foo() -> Result<i32<|>, String> { | |||
385 | wrap_return_type_in_result, | 385 | wrap_return_type_in_result, |
386 | r#" | 386 | r#" |
387 | fn foo() { | 387 | fn foo() { |
388 | || -> Result<i32<|>, String> { | 388 | || -> Result<i32$0, String> { |
389 | let test = "test"; | 389 | let test = "test"; |
390 | return 42i32; | 390 | return 42i32; |
391 | }; | 391 | }; |
@@ -399,7 +399,7 @@ fn foo() { | |||
399 | check_assist( | 399 | check_assist( |
400 | wrap_return_type_in_result, | 400 | wrap_return_type_in_result, |
401 | r#" | 401 | r#" |
402 | fn foo() -> <|>i32 { | 402 | fn foo() -> $0i32 { |
403 | let test = "test"; | 403 | let test = "test"; |
404 | return 42i32; | 404 | return 42i32; |
405 | } | 405 | } |
@@ -418,7 +418,7 @@ fn foo() -> Result<i32, ${0:_}> { | |||
418 | check_assist( | 418 | check_assist( |
419 | wrap_return_type_in_result, | 419 | wrap_return_type_in_result, |
420 | r#" | 420 | r#" |
421 | fn foo() -><|> i32 { | 421 | fn foo() ->$0 i32 { |
422 | let test = "test"; | 422 | let test = "test"; |
423 | 42i32 | 423 | 42i32 |
424 | } | 424 | } |
@@ -438,7 +438,7 @@ fn foo() -> Result<i32, ${0:_}> { | |||
438 | wrap_return_type_in_result, | 438 | wrap_return_type_in_result, |
439 | r#" | 439 | r#" |
440 | fn foo() { | 440 | fn foo() { |
441 | || -><|> i32 { | 441 | || ->$0 i32 { |
442 | let test = "test"; | 442 | let test = "test"; |
443 | 42i32 | 443 | 42i32 |
444 | }; | 444 | }; |
@@ -459,7 +459,7 @@ fn foo() { | |||
459 | fn wrap_return_type_in_result_simple_with_tail_only() { | 459 | fn wrap_return_type_in_result_simple_with_tail_only() { |
460 | check_assist( | 460 | check_assist( |
461 | wrap_return_type_in_result, | 461 | wrap_return_type_in_result, |
462 | r#"fn foo() -> i32<|> { 42i32 }"#, | 462 | r#"fn foo() -> i32$0 { 42i32 }"#, |
463 | r#"fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }"#, | 463 | r#"fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }"#, |
464 | ); | 464 | ); |
465 | } | 465 | } |
@@ -469,7 +469,7 @@ fn foo() { | |||
469 | check_assist( | 469 | check_assist( |
470 | wrap_return_type_in_result, | 470 | wrap_return_type_in_result, |
471 | r#" | 471 | r#" |
472 | fn foo() -> i32<|> { | 472 | fn foo() -> i32$0 { |
473 | if true { | 473 | if true { |
474 | 42i32 | 474 | 42i32 |
475 | } else { | 475 | } else { |
@@ -495,7 +495,7 @@ fn foo() -> Result<i32, ${0:_}> { | |||
495 | wrap_return_type_in_result, | 495 | wrap_return_type_in_result, |
496 | r#" | 496 | r#" |
497 | fn foo() { | 497 | fn foo() { |
498 | || -> i32<|> { | 498 | || -> i32$0 { |
499 | if true { | 499 | if true { |
500 | 42i32 | 500 | 42i32 |
501 | } else { | 501 | } else { |
@@ -523,7 +523,7 @@ fn foo() { | |||
523 | check_assist( | 523 | check_assist( |
524 | wrap_return_type_in_result, | 524 | wrap_return_type_in_result, |
525 | r#" | 525 | r#" |
526 | fn foo() -> i32<|> { | 526 | fn foo() -> i32$0 { |
527 | if true { | 527 | if true { |
528 | if false { | 528 | if false { |
529 | 1 | 529 | 1 |
@@ -556,7 +556,7 @@ fn foo() -> Result<i32, ${0:_}> { | |||
556 | check_assist( | 556 | check_assist( |
557 | wrap_return_type_in_result, | 557 | wrap_return_type_in_result, |
558 | r#" | 558 | r#" |
559 | async fn foo() -> i<|>32 { | 559 | async fn foo() -> i$032 { |
560 | if true { | 560 | if true { |
561 | if false { | 561 | if false { |
562 | 1.await | 562 | 1.await |
@@ -588,7 +588,7 @@ async fn foo() -> Result<i32, ${0:_}> { | |||
588 | fn wrap_return_type_in_result_simple_with_array() { | 588 | fn wrap_return_type_in_result_simple_with_array() { |
589 | check_assist( | 589 | check_assist( |
590 | wrap_return_type_in_result, | 590 | wrap_return_type_in_result, |
591 | r#"fn foo() -> [i32;<|> 3] { [1, 2, 3] }"#, | 591 | r#"fn foo() -> [i32;$0 3] { [1, 2, 3] }"#, |
592 | r#"fn foo() -> Result<[i32; 3], ${0:_}> { Ok([1, 2, 3]) }"#, | 592 | r#"fn foo() -> Result<[i32; 3], ${0:_}> { Ok([1, 2, 3]) }"#, |
593 | ); | 593 | ); |
594 | } | 594 | } |
@@ -598,7 +598,7 @@ async fn foo() -> Result<i32, ${0:_}> { | |||
598 | check_assist( | 598 | check_assist( |
599 | wrap_return_type_in_result, | 599 | wrap_return_type_in_result, |
600 | r#" | 600 | r#" |
601 | fn foo() -<|>> i32 { | 601 | fn foo() -$0> i32 { |
602 | if true { | 602 | if true { |
603 | if false { | 603 | if false { |
604 | 1 as i32 | 604 | 1 as i32 |
@@ -631,7 +631,7 @@ fn foo() -> Result<i32, ${0:_}> { | |||
631 | check_assist( | 631 | check_assist( |
632 | wrap_return_type_in_result, | 632 | wrap_return_type_in_result, |
633 | r#" | 633 | r#" |
634 | fn foo() -> i32<|> { | 634 | fn foo() -> i32$0 { |
635 | let my_var = 5; | 635 | let my_var = 5; |
636 | match my_var { | 636 | match my_var { |
637 | 5 => 42i32, | 637 | 5 => 42i32, |
@@ -656,7 +656,7 @@ fn foo() -> Result<i32, ${0:_}> { | |||
656 | check_assist( | 656 | check_assist( |
657 | wrap_return_type_in_result, | 657 | wrap_return_type_in_result, |
658 | r#" | 658 | r#" |
659 | fn foo() -> i32<|> { | 659 | fn foo() -> i32$0 { |
660 | let my_var = 5; | 660 | let my_var = 5; |
661 | loop { | 661 | loop { |
662 | println!("test"); | 662 | println!("test"); |
@@ -683,7 +683,7 @@ fn foo() -> Result<i32, ${0:_}> { | |||
683 | check_assist( | 683 | check_assist( |
684 | wrap_return_type_in_result, | 684 | wrap_return_type_in_result, |
685 | r#" | 685 | r#" |
686 | fn foo() -> i32<|> { | 686 | fn foo() -> i32$0 { |
687 | let my_var = let x = loop { | 687 | let my_var = let x = loop { |
688 | break 1; | 688 | break 1; |
689 | }; | 689 | }; |
@@ -706,7 +706,7 @@ fn foo() -> Result<i32, ${0:_}> { | |||
706 | check_assist( | 706 | check_assist( |
707 | wrap_return_type_in_result, | 707 | wrap_return_type_in_result, |
708 | r#" | 708 | r#" |
709 | fn foo() -> i32<|> { | 709 | fn foo() -> i32$0 { |
710 | let my_var = 5; | 710 | let my_var = 5; |
711 | let res = match my_var { | 711 | let res = match my_var { |
712 | 5 => 42i32, | 712 | 5 => 42i32, |
@@ -730,7 +730,7 @@ fn foo() -> Result<i32, ${0:_}> { | |||
730 | check_assist( | 730 | check_assist( |
731 | wrap_return_type_in_result, | 731 | wrap_return_type_in_result, |
732 | r#" | 732 | r#" |
733 | fn foo() -> i32<|> { | 733 | fn foo() -> i32$0 { |
734 | let my_var = 5; | 734 | let my_var = 5; |
735 | let res = if my_var == 5 { | 735 | let res = if my_var == 5 { |
736 | 42i32 | 736 | 42i32 |
@@ -759,7 +759,7 @@ fn foo() -> Result<i32, ${0:_}> { | |||
759 | check_assist( | 759 | check_assist( |
760 | wrap_return_type_in_result, | 760 | wrap_return_type_in_result, |
761 | r#" | 761 | r#" |
762 | fn foo() -> i32<|> { | 762 | fn foo() -> i32$0 { |
763 | let my_var = 5; | 763 | let my_var = 5; |
764 | match my_var { | 764 | match my_var { |
765 | 5 => { | 765 | 5 => { |
@@ -808,7 +808,7 @@ fn foo() -> Result<i32, ${0:_}> { | |||
808 | check_assist( | 808 | check_assist( |
809 | wrap_return_type_in_result, | 809 | wrap_return_type_in_result, |
810 | r#" | 810 | r#" |
811 | fn foo() -> i<|>32 { | 811 | fn foo() -> i$032 { |
812 | let test = "test"; | 812 | let test = "test"; |
813 | if test == "test" { | 813 | if test == "test" { |
814 | return 24i32; | 814 | return 24i32; |
@@ -833,7 +833,7 @@ fn foo() -> Result<i32, ${0:_}> { | |||
833 | check_assist( | 833 | check_assist( |
834 | wrap_return_type_in_result, | 834 | wrap_return_type_in_result, |
835 | r#" | 835 | r#" |
836 | fn foo(the_field: u32) -><|> u32 { | 836 | fn foo(the_field: u32) ->$0 u32 { |
837 | let true_closure = || { return true; }; | 837 | let true_closure = || { return true; }; |
838 | if the_field < 5 { | 838 | if the_field < 5 { |
839 | let mut i = 0; | 839 | let mut i = 0; |
@@ -865,7 +865,7 @@ fn foo(the_field: u32) -> Result<u32, ${0:_}> { | |||
865 | check_assist( | 865 | check_assist( |
866 | wrap_return_type_in_result, | 866 | wrap_return_type_in_result, |
867 | r#" | 867 | r#" |
868 | fn foo(the_field: u32) -> u32<|> { | 868 | fn foo(the_field: u32) -> u32$0 { |
869 | let true_closure = || { | 869 | let true_closure = || { |
870 | return true; | 870 | return true; |
871 | }; | 871 | }; |
@@ -912,7 +912,7 @@ fn foo(the_field: u32) -> Result<u32, ${0:_}> { | |||
912 | check_assist( | 912 | check_assist( |
913 | wrap_return_type_in_result, | 913 | wrap_return_type_in_result, |
914 | r#" | 914 | r#" |
915 | fn foo() -> i32<|> { | 915 | fn foo() -> i32$0 { |
916 | let test = "test"; | 916 | let test = "test"; |
917 | if test == "test" { | 917 | if test == "test" { |
918 | return 24i32; | 918 | return 24i32; |
@@ -946,7 +946,7 @@ fn foo() -> Result<i32, ${0:_}> { | |||
946 | check_assist( | 946 | check_assist( |
947 | wrap_return_type_in_result, | 947 | wrap_return_type_in_result, |
948 | r#" | 948 | r#" |
949 | fn foo() -> i32<|> { | 949 | fn foo() -> i32$0 { |
950 | let test = "test"; | 950 | let test = "test"; |
951 | if test == "test" { | 951 | if test == "test" { |
952 | return 24i32; | 952 | return 24i32; |
@@ -984,7 +984,7 @@ fn foo() -> Result<i32, ${0:_}> { | |||
984 | check_assist( | 984 | check_assist( |
985 | wrap_return_type_in_result, | 985 | wrap_return_type_in_result, |
986 | r#" | 986 | r#" |
987 | fn foo() -> i3<|>2 { | 987 | fn foo() -> i3$02 { |
988 | let test = "test"; | 988 | let test = "test"; |
989 | let other = 5; | 989 | let other = 5; |
990 | if test == "test" { | 990 | if test == "test" { |
@@ -1030,7 +1030,7 @@ fn foo() -> Result<i32, ${0:_}> { | |||
1030 | check_assist( | 1030 | check_assist( |
1031 | wrap_return_type_in_result, | 1031 | wrap_return_type_in_result, |
1032 | r#" | 1032 | r#" |
1033 | fn foo(the_field: u32) -> u32<|> { | 1033 | fn foo(the_field: u32) -> u32$0 { |
1034 | if the_field < 5 { | 1034 | if the_field < 5 { |
1035 | let mut i = 0; | 1035 | let mut i = 0; |
1036 | loop { | 1036 | loop { |
@@ -1070,7 +1070,7 @@ fn foo(the_field: u32) -> Result<u32, ${0:_}> { | |||
1070 | check_assist( | 1070 | check_assist( |
1071 | wrap_return_type_in_result, | 1071 | wrap_return_type_in_result, |
1072 | r#" | 1072 | r#" |
1073 | fn foo(the_field: u32) -> u3<|>2 { | 1073 | fn foo(the_field: u32) -> u3$02 { |
1074 | if the_field < 5 { | 1074 | if the_field < 5 { |
1075 | let mut i = 0; | 1075 | let mut i = 0; |
1076 | match i { | 1076 | match i { |
@@ -1098,7 +1098,7 @@ fn foo(the_field: u32) -> Result<u32, ${0:_}> { | |||
1098 | check_assist( | 1098 | check_assist( |
1099 | wrap_return_type_in_result, | 1099 | wrap_return_type_in_result, |
1100 | r#" | 1100 | r#" |
1101 | fn foo(the_field: u32) -> u32<|> { | 1101 | fn foo(the_field: u32) -> u32$0 { |
1102 | if the_field < 5 { | 1102 | if the_field < 5 { |
1103 | let mut i = 0; | 1103 | let mut i = 0; |
1104 | if i == 5 { | 1104 | if i == 5 { |
@@ -1128,7 +1128,7 @@ fn foo(the_field: u32) -> Result<u32, ${0:_}> { | |||
1128 | check_assist( | 1128 | check_assist( |
1129 | wrap_return_type_in_result, | 1129 | wrap_return_type_in_result, |
1130 | r#" | 1130 | r#" |
1131 | fn foo(the_field: u32) -> <|>u32 { | 1131 | fn foo(the_field: u32) -> $0u32 { |
1132 | if the_field < 5 { | 1132 | if the_field < 5 { |
1133 | let mut i = 0; | 1133 | let mut i = 0; |
1134 | if i == 5 { | 1134 | if i == 5 { |
diff --git a/crates/assists/src/lib.rs b/crates/assists/src/lib.rs index 9c2a95735..90009c55a 100644 --- a/crates/assists/src/lib.rs +++ b/crates/assists/src/lib.rs | |||
@@ -24,7 +24,7 @@ use syntax::TextRange; | |||
24 | 24 | ||
25 | pub(crate) use crate::assist_context::{AssistContext, Assists}; | 25 | pub(crate) use crate::assist_context::{AssistContext, Assists}; |
26 | 26 | ||
27 | pub use assist_config::AssistConfig; | 27 | pub use assist_config::{AssistConfig, InsertUseConfig}; |
28 | 28 | ||
29 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 29 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
30 | pub enum AssistKind { | 30 | pub enum AssistKind { |
@@ -116,7 +116,6 @@ mod handlers { | |||
116 | mod convert_integer_literal; | 116 | mod convert_integer_literal; |
117 | mod early_return; | 117 | mod early_return; |
118 | mod expand_glob_import; | 118 | mod expand_glob_import; |
119 | mod extract_module_to_file; | ||
120 | mod extract_struct_from_enum_variant; | 119 | mod extract_struct_from_enum_variant; |
121 | mod extract_variable; | 120 | mod extract_variable; |
122 | mod fill_match_arms; | 121 | mod fill_match_arms; |
@@ -139,6 +138,7 @@ mod handlers { | |||
139 | mod merge_match_arms; | 138 | mod merge_match_arms; |
140 | mod move_bounds; | 139 | mod move_bounds; |
141 | mod move_guard; | 140 | mod move_guard; |
141 | mod move_module_to_file; | ||
142 | mod pull_assignment_up; | 142 | mod pull_assignment_up; |
143 | mod qualify_path; | 143 | mod qualify_path; |
144 | mod raw_string; | 144 | mod raw_string; |
@@ -169,7 +169,7 @@ mod handlers { | |||
169 | convert_integer_literal::convert_integer_literal, | 169 | convert_integer_literal::convert_integer_literal, |
170 | early_return::convert_to_guarded_return, | 170 | early_return::convert_to_guarded_return, |
171 | expand_glob_import::expand_glob_import, | 171 | expand_glob_import::expand_glob_import, |
172 | extract_module_to_file::extract_module_to_file, | 172 | move_module_to_file::move_module_to_file, |
173 | extract_struct_from_enum_variant::extract_struct_from_enum_variant, | 173 | extract_struct_from_enum_variant::extract_struct_from_enum_variant, |
174 | extract_variable::extract_variable, | 174 | extract_variable::extract_variable, |
175 | fill_match_arms::fill_match_arms, | 175 | fill_match_arms::fill_match_arms, |
diff --git a/crates/assists/src/tests.rs b/crates/assists/src/tests.rs index 21e448fb8..fef29a0b8 100644 --- a/crates/assists/src/tests.rs +++ b/crates/assists/src/tests.rs | |||
@@ -1,15 +1,29 @@ | |||
1 | mod generated; | 1 | mod generated; |
2 | 2 | ||
3 | use hir::Semantics; | 3 | use hir::Semantics; |
4 | use ide_db::base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}; | 4 | use ide_db::{ |
5 | use ide_db::source_change::FileSystemEdit; | 5 | base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}, |
6 | use ide_db::RootDatabase; | 6 | helpers::{insert_use::MergeBehavior, SnippetCap}, |
7 | source_change::FileSystemEdit, | ||
8 | RootDatabase, | ||
9 | }; | ||
7 | use syntax::TextRange; | 10 | use syntax::TextRange; |
8 | use test_utils::{assert_eq_text, extract_offset, extract_range}; | 11 | use test_utils::{assert_eq_text, extract_offset, extract_range}; |
9 | 12 | ||
10 | use crate::{handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind, Assists}; | 13 | use crate::{ |
14 | handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind, Assists, InsertUseConfig, | ||
15 | }; | ||
11 | use stdx::{format_to, trim_indent}; | 16 | use stdx::{format_to, trim_indent}; |
12 | 17 | ||
18 | pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig { | ||
19 | snippet_cap: SnippetCap::new(true), | ||
20 | allowed: None, | ||
21 | insert_use: InsertUseConfig { | ||
22 | merge: Some(MergeBehavior::Full), | ||
23 | prefix_kind: hir::PrefixKind::Plain, | ||
24 | }, | ||
25 | }; | ||
26 | |||
13 | pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { | 27 | pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { |
14 | RootDatabase::with_single_file(text) | 28 | RootDatabase::with_single_file(text) |
15 | } | 29 | } |
@@ -48,14 +62,14 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) { | |||
48 | let before = db.file_text(file_id).to_string(); | 62 | let before = db.file_text(file_id).to_string(); |
49 | let frange = FileRange { file_id, range: selection.into() }; | 63 | let frange = FileRange { file_id, range: selection.into() }; |
50 | 64 | ||
51 | let assist = Assist::get(&db, &AssistConfig::default(), true, frange) | 65 | let assist = Assist::get(&db, &TEST_CONFIG, true, frange) |
52 | .into_iter() | 66 | .into_iter() |
53 | .find(|assist| assist.id.0 == assist_id) | 67 | .find(|assist| assist.id.0 == assist_id) |
54 | .unwrap_or_else(|| { | 68 | .unwrap_or_else(|| { |
55 | panic!( | 69 | panic!( |
56 | "\n\nAssist is not applicable: {}\nAvailable assists: {}", | 70 | "\n\nAssist is not applicable: {}\nAvailable assists: {}", |
57 | assist_id, | 71 | assist_id, |
58 | Assist::get(&db, &AssistConfig::default(), false, frange) | 72 | Assist::get(&db, &TEST_CONFIG, false, frange) |
59 | .into_iter() | 73 | .into_iter() |
60 | .map(|assist| assist.id.0) | 74 | .map(|assist| assist.id.0) |
61 | .collect::<Vec<_>>() | 75 | .collect::<Vec<_>>() |
@@ -89,7 +103,7 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label: | |||
89 | let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() }; | 103 | let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() }; |
90 | 104 | ||
91 | let sema = Semantics::new(&db); | 105 | let sema = Semantics::new(&db); |
92 | let config = AssistConfig::default(); | 106 | let config = TEST_CONFIG; |
93 | let ctx = AssistContext::new(sema, &config, frange); | 107 | let ctx = AssistContext::new(sema, &config, frange); |
94 | let mut acc = Assists::new(&ctx, true); | 108 | let mut acc = Assists::new(&ctx, true); |
95 | handler(&mut acc, &ctx); | 109 | handler(&mut acc, &ctx); |
@@ -152,11 +166,11 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label: | |||
152 | 166 | ||
153 | #[test] | 167 | #[test] |
154 | fn assist_order_field_struct() { | 168 | fn assist_order_field_struct() { |
155 | let before = "struct Foo { <|>bar: u32 }"; | 169 | let before = "struct Foo { $0bar: u32 }"; |
156 | let (before_cursor_pos, before) = extract_offset(before); | 170 | let (before_cursor_pos, before) = extract_offset(before); |
157 | let (db, file_id) = with_single_file(&before); | 171 | let (db, file_id) = with_single_file(&before); |
158 | let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) }; | 172 | let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) }; |
159 | let assists = Assist::get(&db, &AssistConfig::default(), false, frange); | 173 | let assists = Assist::get(&db, &TEST_CONFIG, false, frange); |
160 | let mut assists = assists.iter(); | 174 | let mut assists = assists.iter(); |
161 | 175 | ||
162 | assert_eq!(assists.next().expect("expected assist").label, "Change visibility to pub(crate)"); | 176 | assert_eq!(assists.next().expect("expected assist").label, "Change visibility to pub(crate)"); |
@@ -167,7 +181,7 @@ fn assist_order_field_struct() { | |||
167 | fn assist_order_if_expr() { | 181 | fn assist_order_if_expr() { |
168 | let before = " | 182 | let before = " |
169 | pub fn test_some_range(a: int) -> bool { | 183 | pub fn test_some_range(a: int) -> bool { |
170 | if let 2..6 = <|>5<|> { | 184 | if let 2..6 = $05$0 { |
171 | true | 185 | true |
172 | } else { | 186 | } else { |
173 | false | 187 | false |
@@ -176,7 +190,7 @@ fn assist_order_if_expr() { | |||
176 | let (range, before) = extract_range(before); | 190 | let (range, before) = extract_range(before); |
177 | let (db, file_id) = with_single_file(&before); | 191 | let (db, file_id) = with_single_file(&before); |
178 | let frange = FileRange { file_id, range }; | 192 | let frange = FileRange { file_id, range }; |
179 | let assists = Assist::get(&db, &AssistConfig::default(), false, frange); | 193 | let assists = Assist::get(&db, &TEST_CONFIG, false, frange); |
180 | let mut assists = assists.iter(); | 194 | let mut assists = assists.iter(); |
181 | 195 | ||
182 | assert_eq!(assists.next().expect("expected assist").label, "Extract into variable"); | 196 | assert_eq!(assists.next().expect("expected assist").label, "Extract into variable"); |
@@ -187,7 +201,7 @@ fn assist_order_if_expr() { | |||
187 | fn assist_filter_works() { | 201 | fn assist_filter_works() { |
188 | let before = " | 202 | let before = " |
189 | pub fn test_some_range(a: int) -> bool { | 203 | pub fn test_some_range(a: int) -> bool { |
190 | if let 2..6 = <|>5<|> { | 204 | if let 2..6 = $05$0 { |
191 | true | 205 | true |
192 | } else { | 206 | } else { |
193 | false | 207 | false |
@@ -198,7 +212,7 @@ fn assist_filter_works() { | |||
198 | let frange = FileRange { file_id, range }; | 212 | let frange = FileRange { file_id, range }; |
199 | 213 | ||
200 | { | 214 | { |
201 | let mut cfg = AssistConfig::default(); | 215 | let mut cfg = TEST_CONFIG; |
202 | cfg.allowed = Some(vec![AssistKind::Refactor]); | 216 | cfg.allowed = Some(vec![AssistKind::Refactor]); |
203 | 217 | ||
204 | let assists = Assist::get(&db, &cfg, false, frange); | 218 | let assists = Assist::get(&db, &cfg, false, frange); |
@@ -209,7 +223,7 @@ fn assist_filter_works() { | |||
209 | } | 223 | } |
210 | 224 | ||
211 | { | 225 | { |
212 | let mut cfg = AssistConfig::default(); | 226 | let mut cfg = TEST_CONFIG; |
213 | cfg.allowed = Some(vec![AssistKind::RefactorExtract]); | 227 | cfg.allowed = Some(vec![AssistKind::RefactorExtract]); |
214 | let assists = Assist::get(&db, &cfg, false, frange); | 228 | let assists = Assist::get(&db, &cfg, false, frange); |
215 | assert_eq!(assists.len(), 1); | 229 | assert_eq!(assists.len(), 1); |
@@ -219,7 +233,7 @@ fn assist_filter_works() { | |||
219 | } | 233 | } |
220 | 234 | ||
221 | { | 235 | { |
222 | let mut cfg = AssistConfig::default(); | 236 | let mut cfg = TEST_CONFIG; |
223 | cfg.allowed = Some(vec![AssistKind::QuickFix]); | 237 | cfg.allowed = Some(vec![AssistKind::QuickFix]); |
224 | let assists = Assist::get(&db, &cfg, false, frange); | 238 | let assists = Assist::get(&db, &cfg, false, frange); |
225 | assert!(assists.is_empty(), "All asserts but quickfixes should be filtered out"); | 239 | assert!(assists.is_empty(), "All asserts but quickfixes should be filtered out"); |
diff --git a/crates/assists/src/tests/generated.rs b/crates/assists/src/tests/generated.rs index b15352cf3..e28837b53 100644 --- a/crates/assists/src/tests/generated.rs +++ b/crates/assists/src/tests/generated.rs | |||
@@ -8,7 +8,7 @@ fn doctest_add_explicit_type() { | |||
8 | "add_explicit_type", | 8 | "add_explicit_type", |
9 | r#####" | 9 | r#####" |
10 | fn main() { | 10 | fn main() { |
11 | let x<|> = 92; | 11 | let x$0 = 92; |
12 | } | 12 | } |
13 | "#####, | 13 | "#####, |
14 | r#####" | 14 | r#####" |
@@ -25,7 +25,7 @@ fn doctest_add_hash() { | |||
25 | "add_hash", | 25 | "add_hash", |
26 | r#####" | 26 | r#####" |
27 | fn main() { | 27 | fn main() { |
28 | r#"Hello,<|> World!"#; | 28 | r#"Hello,$0 World!"#; |
29 | } | 29 | } |
30 | "#####, | 30 | "#####, |
31 | r#####" | 31 | r#####" |
@@ -49,7 +49,7 @@ trait Trait { | |||
49 | 49 | ||
50 | impl Trait for () { | 50 | impl Trait for () { |
51 | type X = (); | 51 | type X = (); |
52 | fn foo(&self) {}<|> | 52 | fn foo(&self) {}$0 |
53 | 53 | ||
54 | } | 54 | } |
55 | "#####, | 55 | "#####, |
@@ -81,7 +81,7 @@ trait Trait<T> { | |||
81 | fn bar(&self) {} | 81 | fn bar(&self) {} |
82 | } | 82 | } |
83 | 83 | ||
84 | impl Trait<u32> for () {<|> | 84 | impl Trait<u32> for () {$0 |
85 | 85 | ||
86 | } | 86 | } |
87 | "#####, | 87 | "#####, |
@@ -110,7 +110,7 @@ fn doctest_add_turbo_fish() { | |||
110 | r#####" | 110 | r#####" |
111 | fn make<T>() -> T { todo!() } | 111 | fn make<T>() -> T { todo!() } |
112 | fn main() { | 112 | fn main() { |
113 | let x = make<|>(); | 113 | let x = make$0(); |
114 | } | 114 | } |
115 | "#####, | 115 | "#####, |
116 | r#####" | 116 | r#####" |
@@ -128,7 +128,7 @@ fn doctest_apply_demorgan() { | |||
128 | "apply_demorgan", | 128 | "apply_demorgan", |
129 | r#####" | 129 | r#####" |
130 | fn main() { | 130 | fn main() { |
131 | if x != 4 ||<|> !y {} | 131 | if x != 4 ||$0 !y {} |
132 | } | 132 | } |
133 | "#####, | 133 | "#####, |
134 | r#####" | 134 | r#####" |
@@ -145,7 +145,7 @@ fn doctest_auto_import() { | |||
145 | "auto_import", | 145 | "auto_import", |
146 | r#####" | 146 | r#####" |
147 | fn main() { | 147 | fn main() { |
148 | let map = HashMap<|>::new(); | 148 | let map = HashMap$0::new(); |
149 | } | 149 | } |
150 | pub mod std { pub mod collections { pub struct HashMap { } } } | 150 | pub mod std { pub mod collections { pub struct HashMap { } } } |
151 | "#####, | 151 | "#####, |
@@ -165,7 +165,7 @@ fn doctest_change_visibility() { | |||
165 | check_doc_test( | 165 | check_doc_test( |
166 | "change_visibility", | 166 | "change_visibility", |
167 | r#####" | 167 | r#####" |
168 | <|>fn frobnicate() {} | 168 | $0fn frobnicate() {} |
169 | "#####, | 169 | "#####, |
170 | r#####" | 170 | r#####" |
171 | pub(crate) fn frobnicate() {} | 171 | pub(crate) fn frobnicate() {} |
@@ -178,7 +178,7 @@ fn doctest_convert_integer_literal() { | |||
178 | check_doc_test( | 178 | check_doc_test( |
179 | "convert_integer_literal", | 179 | "convert_integer_literal", |
180 | r#####" | 180 | r#####" |
181 | const _: i32 = 10<|>; | 181 | const _: i32 = 10$0; |
182 | "#####, | 182 | "#####, |
183 | r#####" | 183 | r#####" |
184 | const _: i32 = 0b1010; | 184 | const _: i32 = 0b1010; |
@@ -192,7 +192,7 @@ fn doctest_convert_to_guarded_return() { | |||
192 | "convert_to_guarded_return", | 192 | "convert_to_guarded_return", |
193 | r#####" | 193 | r#####" |
194 | fn main() { | 194 | fn main() { |
195 | <|>if cond { | 195 | $0if cond { |
196 | foo(); | 196 | foo(); |
197 | bar(); | 197 | bar(); |
198 | } | 198 | } |
@@ -220,7 +220,7 @@ mod foo { | |||
220 | pub struct Baz; | 220 | pub struct Baz; |
221 | } | 221 | } |
222 | 222 | ||
223 | use foo::*<|>; | 223 | use foo::*$0; |
224 | 224 | ||
225 | fn qux(bar: Bar, baz: Baz) {} | 225 | fn qux(bar: Bar, baz: Baz) {} |
226 | "#####, | 226 | "#####, |
@@ -238,26 +238,11 @@ fn qux(bar: Bar, baz: Baz) {} | |||
238 | } | 238 | } |
239 | 239 | ||
240 | #[test] | 240 | #[test] |
241 | fn doctest_extract_module_to_file() { | ||
242 | check_doc_test( | ||
243 | "extract_module_to_file", | ||
244 | r#####" | ||
245 | mod foo {<|> | ||
246 | fn t() {} | ||
247 | } | ||
248 | "#####, | ||
249 | r#####" | ||
250 | mod foo; | ||
251 | "#####, | ||
252 | ) | ||
253 | } | ||
254 | |||
255 | #[test] | ||
256 | fn doctest_extract_struct_from_enum_variant() { | 241 | fn doctest_extract_struct_from_enum_variant() { |
257 | check_doc_test( | 242 | check_doc_test( |
258 | "extract_struct_from_enum_variant", | 243 | "extract_struct_from_enum_variant", |
259 | r#####" | 244 | r#####" |
260 | enum A { <|>One(u32, u32) } | 245 | enum A { $0One(u32, u32) } |
261 | "#####, | 246 | "#####, |
262 | r#####" | 247 | r#####" |
263 | struct One(pub u32, pub u32); | 248 | struct One(pub u32, pub u32); |
@@ -273,7 +258,7 @@ fn doctest_extract_variable() { | |||
273 | "extract_variable", | 258 | "extract_variable", |
274 | r#####" | 259 | r#####" |
275 | fn main() { | 260 | fn main() { |
276 | <|>(1 + 2)<|> * 4; | 261 | $0(1 + 2)$0 * 4; |
277 | } | 262 | } |
278 | "#####, | 263 | "#####, |
279 | r#####" | 264 | r#####" |
@@ -294,7 +279,7 @@ enum Action { Move { distance: u32 }, Stop } | |||
294 | 279 | ||
295 | fn handle(action: Action) { | 280 | fn handle(action: Action) { |
296 | match action { | 281 | match action { |
297 | <|> | 282 | $0 |
298 | } | 283 | } |
299 | } | 284 | } |
300 | "#####, | 285 | "#####, |
@@ -320,7 +305,7 @@ mod m { | |||
320 | fn frobnicate() {} | 305 | fn frobnicate() {} |
321 | } | 306 | } |
322 | fn main() { | 307 | fn main() { |
323 | m::frobnicate<|>() {} | 308 | m::frobnicate$0() {} |
324 | } | 309 | } |
325 | "#####, | 310 | "#####, |
326 | r#####" | 311 | r#####" |
@@ -340,7 +325,7 @@ fn doctest_flip_binexpr() { | |||
340 | "flip_binexpr", | 325 | "flip_binexpr", |
341 | r#####" | 326 | r#####" |
342 | fn main() { | 327 | fn main() { |
343 | let _ = 90 +<|> 2; | 328 | let _ = 90 +$0 2; |
344 | } | 329 | } |
345 | "#####, | 330 | "#####, |
346 | r#####" | 331 | r#####" |
@@ -357,7 +342,7 @@ fn doctest_flip_comma() { | |||
357 | "flip_comma", | 342 | "flip_comma", |
358 | r#####" | 343 | r#####" |
359 | fn main() { | 344 | fn main() { |
360 | ((1, 2),<|> (3, 4)); | 345 | ((1, 2),$0 (3, 4)); |
361 | } | 346 | } |
362 | "#####, | 347 | "#####, |
363 | r#####" | 348 | r#####" |
@@ -373,7 +358,7 @@ fn doctest_flip_trait_bound() { | |||
373 | check_doc_test( | 358 | check_doc_test( |
374 | "flip_trait_bound", | 359 | "flip_trait_bound", |
375 | r#####" | 360 | r#####" |
376 | fn foo<T: Clone +<|> Copy>() { } | 361 | fn foo<T: Clone +$0 Copy>() { } |
377 | "#####, | 362 | "#####, |
378 | r#####" | 363 | r#####" |
379 | fn foo<T: Copy + Clone>() { } | 364 | fn foo<T: Copy + Clone>() { } |
@@ -388,7 +373,7 @@ fn doctest_generate_default_from_enum_variant() { | |||
388 | r#####" | 373 | r#####" |
389 | enum Version { | 374 | enum Version { |
390 | Undefined, | 375 | Undefined, |
391 | Minor<|>, | 376 | Minor$0, |
392 | Major, | 377 | Major, |
393 | } | 378 | } |
394 | "#####, | 379 | "#####, |
@@ -415,7 +400,7 @@ fn doctest_generate_derive() { | |||
415 | r#####" | 400 | r#####" |
416 | struct Point { | 401 | struct Point { |
417 | x: u32, | 402 | x: u32, |
418 | y: u32,<|> | 403 | y: u32,$0 |
419 | } | 404 | } |
420 | "#####, | 405 | "#####, |
421 | r#####" | 406 | r#####" |
@@ -433,7 +418,7 @@ fn doctest_generate_from_impl_for_enum() { | |||
433 | check_doc_test( | 418 | check_doc_test( |
434 | "generate_from_impl_for_enum", | 419 | "generate_from_impl_for_enum", |
435 | r#####" | 420 | r#####" |
436 | enum A { <|>One(u32) } | 421 | enum A { $0One(u32) } |
437 | "#####, | 422 | "#####, |
438 | r#####" | 423 | r#####" |
439 | enum A { One(u32) } | 424 | enum A { One(u32) } |
@@ -455,7 +440,7 @@ fn doctest_generate_function() { | |||
455 | struct Baz; | 440 | struct Baz; |
456 | fn baz() -> Baz { Baz } | 441 | fn baz() -> Baz { Baz } |
457 | fn foo() { | 442 | fn foo() { |
458 | bar<|>("", baz()); | 443 | bar$0("", baz()); |
459 | } | 444 | } |
460 | 445 | ||
461 | "#####, | 446 | "#####, |
@@ -480,7 +465,7 @@ fn doctest_generate_impl() { | |||
480 | "generate_impl", | 465 | "generate_impl", |
481 | r#####" | 466 | r#####" |
482 | struct Ctx<T: Clone> { | 467 | struct Ctx<T: Clone> { |
483 | data: T,<|> | 468 | data: T,$0 |
484 | } | 469 | } |
485 | "#####, | 470 | "#####, |
486 | r#####" | 471 | r#####" |
@@ -501,7 +486,7 @@ fn doctest_generate_new() { | |||
501 | "generate_new", | 486 | "generate_new", |
502 | r#####" | 487 | r#####" |
503 | struct Ctx<T: Clone> { | 488 | struct Ctx<T: Clone> { |
504 | data: T,<|> | 489 | data: T,$0 |
505 | } | 490 | } |
506 | "#####, | 491 | "#####, |
507 | r#####" | 492 | r#####" |
@@ -522,7 +507,7 @@ fn doctest_infer_function_return_type() { | |||
522 | check_doc_test( | 507 | check_doc_test( |
523 | "infer_function_return_type", | 508 | "infer_function_return_type", |
524 | r#####" | 509 | r#####" |
525 | fn foo() { 4<|>2i32 } | 510 | fn foo() { 4$02i32 } |
526 | "#####, | 511 | "#####, |
527 | r#####" | 512 | r#####" |
528 | fn foo() -> i32 { 42i32 } | 513 | fn foo() -> i32 { 42i32 } |
@@ -537,7 +522,7 @@ fn doctest_inline_function() { | |||
537 | r#####" | 522 | r#####" |
538 | fn add(a: u32, b: u32) -> u32 { a + b } | 523 | fn add(a: u32, b: u32) -> u32 { a + b } |
539 | fn main() { | 524 | fn main() { |
540 | let x = add<|>(1, 2); | 525 | let x = add$0(1, 2); |
541 | } | 526 | } |
542 | "#####, | 527 | "#####, |
543 | r#####" | 528 | r#####" |
@@ -559,7 +544,7 @@ fn doctest_inline_local_variable() { | |||
559 | "inline_local_variable", | 544 | "inline_local_variable", |
560 | r#####" | 545 | r#####" |
561 | fn main() { | 546 | fn main() { |
562 | let x<|> = 1 + 2; | 547 | let x$0 = 1 + 2; |
563 | x * 4; | 548 | x * 4; |
564 | } | 549 | } |
565 | "#####, | 550 | "#####, |
@@ -576,7 +561,7 @@ fn doctest_introduce_named_lifetime() { | |||
576 | check_doc_test( | 561 | check_doc_test( |
577 | "introduce_named_lifetime", | 562 | "introduce_named_lifetime", |
578 | r#####" | 563 | r#####" |
579 | impl Cursor<'_<|>> { | 564 | impl Cursor<'_$0> { |
580 | fn node(self) -> &SyntaxNode { | 565 | fn node(self) -> &SyntaxNode { |
581 | match self { | 566 | match self { |
582 | Cursor::Replace(node) | Cursor::Before(node) => node, | 567 | Cursor::Replace(node) | Cursor::Before(node) => node, |
@@ -602,7 +587,7 @@ fn doctest_invert_if() { | |||
602 | "invert_if", | 587 | "invert_if", |
603 | r#####" | 588 | r#####" |
604 | fn main() { | 589 | fn main() { |
605 | if<|> !y { A } else { B } | 590 | if$0 !y { A } else { B } |
606 | } | 591 | } |
607 | "#####, | 592 | "#####, |
608 | r#####" | 593 | r#####" |
@@ -619,7 +604,7 @@ fn doctest_make_raw_string() { | |||
619 | "make_raw_string", | 604 | "make_raw_string", |
620 | r#####" | 605 | r#####" |
621 | fn main() { | 606 | fn main() { |
622 | "Hello,<|> World!"; | 607 | "Hello,$0 World!"; |
623 | } | 608 | } |
624 | "#####, | 609 | "#####, |
625 | r#####" | 610 | r#####" |
@@ -636,7 +621,7 @@ fn doctest_make_usual_string() { | |||
636 | "make_usual_string", | 621 | "make_usual_string", |
637 | r#####" | 622 | r#####" |
638 | fn main() { | 623 | fn main() { |
639 | r#"Hello,<|> "World!""#; | 624 | r#"Hello,$0 "World!""#; |
640 | } | 625 | } |
641 | "#####, | 626 | "#####, |
642 | r#####" | 627 | r#####" |
@@ -652,7 +637,7 @@ fn doctest_merge_imports() { | |||
652 | check_doc_test( | 637 | check_doc_test( |
653 | "merge_imports", | 638 | "merge_imports", |
654 | r#####" | 639 | r#####" |
655 | use std::<|>fmt::Formatter; | 640 | use std::$0fmt::Formatter; |
656 | use std::io; | 641 | use std::io; |
657 | "#####, | 642 | "#####, |
658 | r#####" | 643 | r#####" |
@@ -670,7 +655,7 @@ enum Action { Move { distance: u32 }, Stop } | |||
670 | 655 | ||
671 | fn handle(action: Action) { | 656 | fn handle(action: Action) { |
672 | match action { | 657 | match action { |
673 | <|>Action::Move(..) => foo(), | 658 | $0Action::Move(..) => foo(), |
674 | Action::Stop => foo(), | 659 | Action::Stop => foo(), |
675 | } | 660 | } |
676 | } | 661 | } |
@@ -696,7 +681,7 @@ enum Action { Move { distance: u32 }, Stop } | |||
696 | 681 | ||
697 | fn handle(action: Action) { | 682 | fn handle(action: Action) { |
698 | match action { | 683 | match action { |
699 | Action::Move { distance } => <|>if distance > 10 { foo() }, | 684 | Action::Move { distance } => $0if distance > 10 { foo() }, |
700 | _ => (), | 685 | _ => (), |
701 | } | 686 | } |
702 | } | 687 | } |
@@ -719,7 +704,7 @@ fn doctest_move_bounds_to_where_clause() { | |||
719 | check_doc_test( | 704 | check_doc_test( |
720 | "move_bounds_to_where_clause", | 705 | "move_bounds_to_where_clause", |
721 | r#####" | 706 | r#####" |
722 | fn apply<T, U, <|>F: FnOnce(T) -> U>(f: F, x: T) -> U { | 707 | fn apply<T, U, $0F: FnOnce(T) -> U>(f: F, x: T) -> U { |
723 | f(x) | 708 | f(x) |
724 | } | 709 | } |
725 | "#####, | 710 | "#####, |
@@ -740,7 +725,7 @@ enum Action { Move { distance: u32 }, Stop } | |||
740 | 725 | ||
741 | fn handle(action: Action) { | 726 | fn handle(action: Action) { |
742 | match action { | 727 | match action { |
743 | Action::Move { distance } <|>if distance > 10 => foo(), | 728 | Action::Move { distance } $0if distance > 10 => foo(), |
744 | _ => (), | 729 | _ => (), |
745 | } | 730 | } |
746 | } | 731 | } |
@@ -761,6 +746,21 @@ fn handle(action: Action) { | |||
761 | } | 746 | } |
762 | 747 | ||
763 | #[test] | 748 | #[test] |
749 | fn doctest_move_module_to_file() { | ||
750 | check_doc_test( | ||
751 | "move_module_to_file", | ||
752 | r#####" | ||
753 | mod $0foo { | ||
754 | fn t() {} | ||
755 | } | ||
756 | "#####, | ||
757 | r#####" | ||
758 | mod foo; | ||
759 | "#####, | ||
760 | ) | ||
761 | } | ||
762 | |||
763 | #[test] | ||
764 | fn doctest_pull_assignment_up() { | 764 | fn doctest_pull_assignment_up() { |
765 | check_doc_test( | 765 | check_doc_test( |
766 | "pull_assignment_up", | 766 | "pull_assignment_up", |
@@ -769,7 +769,7 @@ fn main() { | |||
769 | let mut foo = 6; | 769 | let mut foo = 6; |
770 | 770 | ||
771 | if true { | 771 | if true { |
772 | <|>foo = 5; | 772 | $0foo = 5; |
773 | } else { | 773 | } else { |
774 | foo = 4; | 774 | foo = 4; |
775 | } | 775 | } |
@@ -795,7 +795,7 @@ fn doctest_qualify_path() { | |||
795 | "qualify_path", | 795 | "qualify_path", |
796 | r#####" | 796 | r#####" |
797 | fn main() { | 797 | fn main() { |
798 | let map = HashMap<|>::new(); | 798 | let map = HashMap$0::new(); |
799 | } | 799 | } |
800 | pub mod std { pub mod collections { pub struct HashMap { } } } | 800 | pub mod std { pub mod collections { pub struct HashMap { } } } |
801 | "#####, | 801 | "#####, |
@@ -814,7 +814,7 @@ fn doctest_remove_dbg() { | |||
814 | "remove_dbg", | 814 | "remove_dbg", |
815 | r#####" | 815 | r#####" |
816 | fn main() { | 816 | fn main() { |
817 | <|>dbg!(92); | 817 | $0dbg!(92); |
818 | } | 818 | } |
819 | "#####, | 819 | "#####, |
820 | r#####" | 820 | r#####" |
@@ -831,7 +831,7 @@ fn doctest_remove_hash() { | |||
831 | "remove_hash", | 831 | "remove_hash", |
832 | r#####" | 832 | r#####" |
833 | fn main() { | 833 | fn main() { |
834 | r#"Hello,<|> World!"#; | 834 | r#"Hello,$0 World!"#; |
835 | } | 835 | } |
836 | "#####, | 836 | "#####, |
837 | r#####" | 837 | r#####" |
@@ -848,7 +848,7 @@ fn doctest_remove_mut() { | |||
848 | "remove_mut", | 848 | "remove_mut", |
849 | r#####" | 849 | r#####" |
850 | impl Walrus { | 850 | impl Walrus { |
851 | fn feed(&mut<|> self, amount: u32) {} | 851 | fn feed(&mut$0 self, amount: u32) {} |
852 | } | 852 | } |
853 | "#####, | 853 | "#####, |
854 | r#####" | 854 | r#####" |
@@ -864,7 +864,7 @@ fn doctest_remove_unused_param() { | |||
864 | check_doc_test( | 864 | check_doc_test( |
865 | "remove_unused_param", | 865 | "remove_unused_param", |
866 | r#####" | 866 | r#####" |
867 | fn frobnicate(x: i32<|>) {} | 867 | fn frobnicate(x: i32$0) {} |
868 | 868 | ||
869 | fn main() { | 869 | fn main() { |
870 | frobnicate(92); | 870 | frobnicate(92); |
@@ -886,7 +886,7 @@ fn doctest_reorder_fields() { | |||
886 | "reorder_fields", | 886 | "reorder_fields", |
887 | r#####" | 887 | r#####" |
888 | struct Foo {foo: i32, bar: i32}; | 888 | struct Foo {foo: i32, bar: i32}; |
889 | const test: Foo = <|>Foo {bar: 0, foo: 1} | 889 | const test: Foo = $0Foo {bar: 0, foo: 1} |
890 | "#####, | 890 | "#####, |
891 | r#####" | 891 | r#####" |
892 | struct Foo {foo: i32, bar: i32}; | 892 | struct Foo {foo: i32, bar: i32}; |
@@ -901,7 +901,7 @@ fn doctest_replace_derive_with_manual_impl() { | |||
901 | "replace_derive_with_manual_impl", | 901 | "replace_derive_with_manual_impl", |
902 | r#####" | 902 | r#####" |
903 | trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; } | 903 | trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; } |
904 | #[derive(Deb<|>ug, Display)] | 904 | #[derive(Deb$0ug, Display)] |
905 | struct S; | 905 | struct S; |
906 | "#####, | 906 | "#####, |
907 | r#####" | 907 | r#####" |
@@ -926,7 +926,7 @@ fn doctest_replace_if_let_with_match() { | |||
926 | enum Action { Move { distance: u32 }, Stop } | 926 | enum Action { Move { distance: u32 }, Stop } |
927 | 927 | ||
928 | fn handle(action: Action) { | 928 | fn handle(action: Action) { |
929 | <|>if let Action::Move { distance } = action { | 929 | $0if let Action::Move { distance } = action { |
930 | foo(distance) | 930 | foo(distance) |
931 | } else { | 931 | } else { |
932 | bar() | 932 | bar() |
@@ -951,7 +951,7 @@ fn doctest_replace_impl_trait_with_generic() { | |||
951 | check_doc_test( | 951 | check_doc_test( |
952 | "replace_impl_trait_with_generic", | 952 | "replace_impl_trait_with_generic", |
953 | r#####" | 953 | r#####" |
954 | fn foo(bar: <|>impl Bar) {} | 954 | fn foo(bar: $0impl Bar) {} |
955 | "#####, | 955 | "#####, |
956 | r#####" | 956 | r#####" |
957 | fn foo<B: Bar>(bar: B) {} | 957 | fn foo<B: Bar>(bar: B) {} |
@@ -967,7 +967,7 @@ fn doctest_replace_let_with_if_let() { | |||
967 | enum Option<T> { Some(T), None } | 967 | enum Option<T> { Some(T), None } |
968 | 968 | ||
969 | fn main(action: Action) { | 969 | fn main(action: Action) { |
970 | <|>let x = compute(); | 970 | $0let x = compute(); |
971 | } | 971 | } |
972 | 972 | ||
973 | fn compute() -> Option<i32> { None } | 973 | fn compute() -> Option<i32> { None } |
@@ -993,7 +993,7 @@ fn doctest_replace_match_with_if_let() { | |||
993 | enum Action { Move { distance: u32 }, Stop } | 993 | enum Action { Move { distance: u32 }, Stop } |
994 | 994 | ||
995 | fn handle(action: Action) { | 995 | fn handle(action: Action) { |
996 | <|>match action { | 996 | $0match action { |
997 | Action::Move { distance } => foo(distance), | 997 | Action::Move { distance } => foo(distance), |
998 | _ => bar(), | 998 | _ => bar(), |
999 | } | 999 | } |
@@ -1018,7 +1018,7 @@ fn doctest_replace_qualified_name_with_use() { | |||
1018 | check_doc_test( | 1018 | check_doc_test( |
1019 | "replace_qualified_name_with_use", | 1019 | "replace_qualified_name_with_use", |
1020 | r#####" | 1020 | r#####" |
1021 | fn process(map: std::collections::<|>HashMap<String, String>) {} | 1021 | fn process(map: std::collections::$0HashMap<String, String>) {} |
1022 | "#####, | 1022 | "#####, |
1023 | r#####" | 1023 | r#####" |
1024 | use std::collections::HashMap; | 1024 | use std::collections::HashMap; |
@@ -1034,7 +1034,7 @@ fn doctest_replace_string_with_char() { | |||
1034 | "replace_string_with_char", | 1034 | "replace_string_with_char", |
1035 | r#####" | 1035 | r#####" |
1036 | fn main() { | 1036 | fn main() { |
1037 | find("{<|>"); | 1037 | find("{$0"); |
1038 | } | 1038 | } |
1039 | "#####, | 1039 | "#####, |
1040 | r#####" | 1040 | r#####" |
@@ -1053,7 +1053,7 @@ fn doctest_replace_unwrap_with_match() { | |||
1053 | enum Result<T, E> { Ok(T), Err(E) } | 1053 | enum Result<T, E> { Ok(T), Err(E) } |
1054 | fn main() { | 1054 | fn main() { |
1055 | let x: Result<i32, i32> = Result::Ok(92); | 1055 | let x: Result<i32, i32> = Result::Ok(92); |
1056 | let y = x.<|>unwrap(); | 1056 | let y = x.$0unwrap(); |
1057 | } | 1057 | } |
1058 | "#####, | 1058 | "#####, |
1059 | r#####" | 1059 | r#####" |
@@ -1074,7 +1074,7 @@ fn doctest_split_import() { | |||
1074 | check_doc_test( | 1074 | check_doc_test( |
1075 | "split_import", | 1075 | "split_import", |
1076 | r#####" | 1076 | r#####" |
1077 | use std::<|>collections::HashMap; | 1077 | use std::$0collections::HashMap; |
1078 | "#####, | 1078 | "#####, |
1079 | r#####" | 1079 | r#####" |
1080 | use std::{collections::HashMap}; | 1080 | use std::{collections::HashMap}; |
@@ -1087,7 +1087,7 @@ fn doctest_toggle_ignore() { | |||
1087 | check_doc_test( | 1087 | check_doc_test( |
1088 | "toggle_ignore", | 1088 | "toggle_ignore", |
1089 | r#####" | 1089 | r#####" |
1090 | <|>#[test] | 1090 | $0#[test] |
1091 | fn arithmetics { | 1091 | fn arithmetics { |
1092 | assert_eq!(2 + 2, 5); | 1092 | assert_eq!(2 + 2, 5); |
1093 | } | 1093 | } |
@@ -1108,7 +1108,7 @@ fn doctest_unwrap_block() { | |||
1108 | "unwrap_block", | 1108 | "unwrap_block", |
1109 | r#####" | 1109 | r#####" |
1110 | fn foo() { | 1110 | fn foo() { |
1111 | if true {<|> | 1111 | if true {$0 |
1112 | println!("foo"); | 1112 | println!("foo"); |
1113 | } | 1113 | } |
1114 | } | 1114 | } |
@@ -1126,7 +1126,7 @@ fn doctest_wrap_return_type_in_result() { | |||
1126 | check_doc_test( | 1126 | check_doc_test( |
1127 | "wrap_return_type_in_result", | 1127 | "wrap_return_type_in_result", |
1128 | r#####" | 1128 | r#####" |
1129 | fn foo() -> i32<|> { 42i32 } | 1129 | fn foo() -> i32$0 { 42i32 } |
1130 | "#####, | 1130 | "#####, |
1131 | r#####" | 1131 | r#####" |
1132 | fn foo() -> Result<i32, ${0:_}> { Ok(42i32) } | 1132 | fn foo() -> Result<i32, ${0:_}> { Ok(42i32) } |
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs index 8212cd129..9ea96eb73 100644 --- a/crates/assists/src/utils.rs +++ b/crates/assists/src/utils.rs | |||
@@ -4,7 +4,7 @@ pub(crate) mod import_assets; | |||
4 | use std::ops; | 4 | use std::ops; |
5 | 5 | ||
6 | use hir::HasSource; | 6 | use hir::HasSource; |
7 | use ide_db::RootDatabase; | 7 | use ide_db::{helpers::SnippetCap, RootDatabase}; |
8 | use itertools::Itertools; | 8 | use itertools::Itertools; |
9 | use syntax::{ | 9 | use syntax::{ |
10 | ast::edit::AstNodeEdit, | 10 | ast::edit::AstNodeEdit, |
@@ -16,10 +16,7 @@ use syntax::{ | |||
16 | SyntaxNode, TextSize, T, | 16 | SyntaxNode, TextSize, T, |
17 | }; | 17 | }; |
18 | 18 | ||
19 | use crate::{ | 19 | use crate::ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}; |
20 | assist_config::SnippetCap, | ||
21 | ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, | ||
22 | }; | ||
23 | 20 | ||
24 | pub(crate) fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr { | 21 | pub(crate) fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr { |
25 | extract_trivial_expression(&block) | 22 | extract_trivial_expression(&block) |
diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs index 66e6443cb..98acd61b1 100644 --- a/crates/base_db/src/fixture.rs +++ b/crates/base_db/src/fixture.rs | |||
@@ -61,7 +61,9 @@ use std::{str::FromStr, sync::Arc}; | |||
61 | 61 | ||
62 | use cfg::CfgOptions; | 62 | use cfg::CfgOptions; |
63 | use rustc_hash::FxHashMap; | 63 | use rustc_hash::FxHashMap; |
64 | use test_utils::{extract_range_or_offset, Fixture, RangeOrOffset, CURSOR_MARKER}; | 64 | use test_utils::{ |
65 | extract_range_or_offset, Fixture, RangeOrOffset, CURSOR_MARKER, ESCAPED_CURSOR_MARKER, | ||
66 | }; | ||
65 | use vfs::{file_set::FileSet, VfsPath}; | 67 | use vfs::{file_set::FileSet, VfsPath}; |
66 | 68 | ||
67 | use crate::{ | 69 | use crate::{ |
@@ -142,10 +144,14 @@ impl ChangeFixture { | |||
142 | 144 | ||
143 | for entry in fixture { | 145 | for entry in fixture { |
144 | let text = if entry.text.contains(CURSOR_MARKER) { | 146 | let text = if entry.text.contains(CURSOR_MARKER) { |
145 | let (range_or_offset, text) = extract_range_or_offset(&entry.text); | 147 | if entry.text.contains(ESCAPED_CURSOR_MARKER) { |
146 | assert!(file_position.is_none()); | 148 | entry.text.replace(ESCAPED_CURSOR_MARKER, CURSOR_MARKER) |
147 | file_position = Some((file_id, range_or_offset)); | 149 | } else { |
148 | text.to_string() | 150 | let (range_or_offset, text) = extract_range_or_offset(&entry.text); |
151 | assert!(file_position.is_none()); | ||
152 | file_position = Some((file_id, range_or_offset)); | ||
153 | text.to_string() | ||
154 | } | ||
149 | } else { | 155 | } else { |
150 | entry.text.clone() | 156 | entry.text.clone() |
151 | }; | 157 | }; |
diff --git a/crates/completion/src/completions/attribute.rs b/crates/completion/src/completions/attribute.rs index 8695eed39..e5522980d 100644 --- a/crates/completion/src/completions/attribute.rs +++ b/crates/completion/src/completions/attribute.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | 5 | ||
6 | use itertools::Itertools; | 6 | use itertools::Itertools; |
7 | use rustc_hash::FxHashSet; | 7 | use rustc_hash::FxHashSet; |
8 | use syntax::{ast, AstNode, SyntaxKind}; | 8 | use syntax::{ast, AstNode, T}; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | context::CompletionContext, | 11 | context::CompletionContext, |
@@ -21,19 +21,16 @@ pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) | |||
21 | 21 | ||
22 | let attribute = ctx.attribute_under_caret.as_ref()?; | 22 | let attribute = ctx.attribute_under_caret.as_ref()?; |
23 | match (attribute.path(), attribute.token_tree()) { | 23 | match (attribute.path(), attribute.token_tree()) { |
24 | (Some(path), Some(token_tree)) if path.to_string() == "derive" => { | 24 | (Some(path), Some(token_tree)) => { |
25 | complete_derive(acc, ctx, token_tree) | 25 | let path = path.syntax().text(); |
26 | } | 26 | if path == "derive" { |
27 | (Some(path), Some(token_tree)) if path.to_string() == "feature" => { | 27 | complete_derive(acc, ctx, token_tree) |
28 | complete_lint(acc, ctx, token_tree, FEATURES); | 28 | } else if path == "feature" { |
29 | } | 29 | complete_lint(acc, ctx, token_tree, FEATURES) |
30 | (Some(path), Some(token_tree)) | 30 | } else if path == "allow" || path == "warn" || path == "deny" || path == "forbid" { |
31 | if ["allow", "warn", "deny", "forbid"] | 31 | complete_lint(acc, ctx, token_tree.clone(), DEFAULT_LINT_COMPLETIONS); |
32 | .iter() | 32 | complete_lint(acc, ctx, token_tree, CLIPPY_LINTS); |
33 | .any(|lint_level| lint_level == &path.to_string()) => | 33 | } |
34 | { | ||
35 | complete_lint(acc, ctx, token_tree.clone(), DEFAULT_LINT_COMPLETIONS); | ||
36 | complete_lint(acc, ctx, token_tree, CLIPPY_LINTS); | ||
37 | } | 34 | } |
38 | (_, Some(_token_tree)) => {} | 35 | (_, Some(_token_tree)) => {} |
39 | _ => complete_attribute_start(acc, ctx, attribute), | 36 | _ => complete_attribute_start(acc, ctx, attribute), |
@@ -54,11 +51,8 @@ fn complete_attribute_start(acc: &mut Completions, ctx: &CompletionContext, attr | |||
54 | item = item.lookup_by(lookup); | 51 | item = item.lookup_by(lookup); |
55 | } | 52 | } |
56 | 53 | ||
57 | match (attr_completion.snippet, ctx.config.snippet_cap) { | 54 | if let Some((snippet, cap)) = attr_completion.snippet.zip(ctx.config.snippet_cap) { |
58 | (Some(snippet), Some(cap)) => { | 55 | item = item.insert_snippet(cap, snippet); |
59 | item = item.insert_snippet(cap, snippet); | ||
60 | } | ||
61 | _ => {} | ||
62 | } | 56 | } |
63 | 57 | ||
64 | if attribute.kind() == ast::AttrKind::Inner || !attr_completion.prefer_inner { | 58 | if attribute.kind() == ast::AttrKind::Inner || !attr_completion.prefer_inner { |
@@ -98,7 +92,7 @@ const ATTRIBUTES: &[AttrCompletion] = &[ | |||
98 | attr(r#"crate_name = """#, Some("crate_name"), Some(r#"crate_name = "${0:crate_name}""#)) | 92 | attr(r#"crate_name = """#, Some("crate_name"), Some(r#"crate_name = "${0:crate_name}""#)) |
99 | .prefer_inner(), | 93 | .prefer_inner(), |
100 | attr("deny(…)", Some("deny"), Some("deny(${0:lint})")), | 94 | attr("deny(…)", Some("deny"), Some("deny(${0:lint})")), |
101 | attr(r#"deprecated = "…""#, Some("deprecated"), Some(r#"deprecated = "${0:reason}""#)), | 95 | attr(r#"deprecated"#, Some("deprecated"), Some(r#"deprecated"#)), |
102 | attr("derive(…)", Some("derive"), Some(r#"derive(${0:Debug})"#)), | 96 | attr("derive(…)", Some("derive"), Some(r#"derive(${0:Debug})"#)), |
103 | attr( | 97 | attr( |
104 | r#"export_name = "…""#, | 98 | r#"export_name = "…""#, |
@@ -121,7 +115,7 @@ const ATTRIBUTES: &[AttrCompletion] = &[ | |||
121 | ), | 115 | ), |
122 | attr("macro_export", None, None), | 116 | attr("macro_export", None, None), |
123 | attr("macro_use", None, None), | 117 | attr("macro_use", None, None), |
124 | attr(r#"must_use = "…""#, Some("must_use"), Some(r#"must_use = "${0:reason}""#)), | 118 | attr(r#"must_use"#, Some("must_use"), Some(r#"must_use"#)), |
125 | attr("no_link", None, None).prefer_inner(), | 119 | attr("no_link", None, None).prefer_inner(), |
126 | attr("no_implicit_prelude", None, None).prefer_inner(), | 120 | attr("no_implicit_prelude", None, None).prefer_inner(), |
127 | attr("no_main", None, None).prefer_inner(), | 121 | attr("no_main", None, None).prefer_inner(), |
@@ -136,11 +130,7 @@ const ATTRIBUTES: &[AttrCompletion] = &[ | |||
136 | attr("recursion_limit = …", Some("recursion_limit"), Some("recursion_limit = ${0:128}")) | 130 | attr("recursion_limit = …", Some("recursion_limit"), Some("recursion_limit = ${0:128}")) |
137 | .prefer_inner(), | 131 | .prefer_inner(), |
138 | attr("repr(…)", Some("repr"), Some("repr(${0:C})")), | 132 | attr("repr(…)", Some("repr"), Some("repr(${0:C})")), |
139 | attr( | 133 | attr("should_panic", Some("should_panic"), Some(r#"should_panic"#)), |
140 | "should_panic(…)", | ||
141 | Some("should_panic"), | ||
142 | Some(r#"should_panic(expected = "${0:reason}")"#), | ||
143 | ), | ||
144 | attr( | 134 | attr( |
145 | r#"target_feature = "…""#, | 135 | r#"target_feature = "…""#, |
146 | Some("target_feature"), | 136 | Some("target_feature"), |
@@ -215,8 +205,7 @@ fn complete_lint( | |||
215 | fn parse_comma_sep_input(derive_input: ast::TokenTree) -> Result<FxHashSet<String>, ()> { | 205 | fn parse_comma_sep_input(derive_input: ast::TokenTree) -> Result<FxHashSet<String>, ()> { |
216 | match (derive_input.left_delimiter_token(), derive_input.right_delimiter_token()) { | 206 | match (derive_input.left_delimiter_token(), derive_input.right_delimiter_token()) { |
217 | (Some(left_paren), Some(right_paren)) | 207 | (Some(left_paren), Some(right_paren)) |
218 | if left_paren.kind() == SyntaxKind::L_PAREN | 208 | if left_paren.kind() == T!['('] && right_paren.kind() == T![')'] => |
219 | && right_paren.kind() == SyntaxKind::R_PAREN => | ||
220 | { | 209 | { |
221 | let mut input_derives = FxHashSet::default(); | 210 | let mut input_derives = FxHashSet::default(); |
222 | let mut current_derive = String::new(); | 211 | let mut current_derive = String::new(); |
@@ -228,7 +217,7 @@ fn parse_comma_sep_input(derive_input: ast::TokenTree) -> Result<FxHashSet<Strin | |||
228 | .skip(1) | 217 | .skip(1) |
229 | .take_while(|token| token != &right_paren) | 218 | .take_while(|token| token != &right_paren) |
230 | { | 219 | { |
231 | if SyntaxKind::COMMA == token.kind() { | 220 | if T![,] == token.kind() { |
232 | if !current_derive.is_empty() { | 221 | if !current_derive.is_empty() { |
233 | input_derives.insert(current_derive); | 222 | input_derives.insert(current_derive); |
234 | current_derive = String::new(); | 223 | current_derive = String::new(); |
@@ -417,7 +406,7 @@ mod tests { | |||
417 | fn empty_derive_completion() { | 406 | fn empty_derive_completion() { |
418 | check( | 407 | check( |
419 | r#" | 408 | r#" |
420 | #[derive(<|>)] | 409 | #[derive($0)] |
421 | struct Test {} | 410 | struct Test {} |
422 | "#, | 411 | "#, |
423 | expect![[r#" | 412 | expect![[r#" |
@@ -438,7 +427,7 @@ struct Test {} | |||
438 | fn no_completion_for_incorrect_derive() { | 427 | fn no_completion_for_incorrect_derive() { |
439 | check( | 428 | check( |
440 | r#" | 429 | r#" |
441 | #[derive{<|>)] | 430 | #[derive{$0)] |
442 | struct Test {} | 431 | struct Test {} |
443 | "#, | 432 | "#, |
444 | expect![[r#""#]], | 433 | expect![[r#""#]], |
@@ -449,7 +438,7 @@ struct Test {} | |||
449 | fn derive_with_input_completion() { | 438 | fn derive_with_input_completion() { |
450 | check( | 439 | check( |
451 | r#" | 440 | r#" |
452 | #[derive(serde::Serialize, PartialEq, <|>)] | 441 | #[derive(serde::Serialize, PartialEq, $0)] |
453 | struct Test {} | 442 | struct Test {} |
454 | "#, | 443 | "#, |
455 | expect![[r#" | 444 | expect![[r#" |
@@ -468,7 +457,7 @@ struct Test {} | |||
468 | #[test] | 457 | #[test] |
469 | fn test_attribute_completion() { | 458 | fn test_attribute_completion() { |
470 | check( | 459 | check( |
471 | r#"#[<|>]"#, | 460 | r#"#[$0]"#, |
472 | expect![[r#" | 461 | expect![[r#" |
473 | at allow(…) | 462 | at allow(…) |
474 | at automatically_derived | 463 | at automatically_derived |
@@ -476,7 +465,7 @@ struct Test {} | |||
476 | at cfg(…) | 465 | at cfg(…) |
477 | at cold | 466 | at cold |
478 | at deny(…) | 467 | at deny(…) |
479 | at deprecated = "…" | 468 | at deprecated |
480 | at derive(…) | 469 | at derive(…) |
481 | at export_name = "…" | 470 | at export_name = "…" |
482 | at doc = "…" | 471 | at doc = "…" |
@@ -488,7 +477,7 @@ struct Test {} | |||
488 | at link_section = "…" | 477 | at link_section = "…" |
489 | at macro_export | 478 | at macro_export |
490 | at macro_use | 479 | at macro_use |
491 | at must_use = "…" | 480 | at must_use |
492 | at no_mangle | 481 | at no_mangle |
493 | at non_exhaustive | 482 | at non_exhaustive |
494 | at path = "…" | 483 | at path = "…" |
@@ -496,7 +485,7 @@ struct Test {} | |||
496 | at proc_macro_attribute | 485 | at proc_macro_attribute |
497 | at proc_macro_derive(…) | 486 | at proc_macro_derive(…) |
498 | at repr(…) | 487 | at repr(…) |
499 | at should_panic(…) | 488 | at should_panic |
500 | at target_feature = "…" | 489 | at target_feature = "…" |
501 | at test | 490 | at test |
502 | at track_caller | 491 | at track_caller |
@@ -508,13 +497,13 @@ struct Test {} | |||
508 | 497 | ||
509 | #[test] | 498 | #[test] |
510 | fn test_attribute_completion_inside_nested_attr() { | 499 | fn test_attribute_completion_inside_nested_attr() { |
511 | check(r#"#[cfg(<|>)]"#, expect![[]]) | 500 | check(r#"#[cfg($0)]"#, expect![[]]) |
512 | } | 501 | } |
513 | 502 | ||
514 | #[test] | 503 | #[test] |
515 | fn test_inner_attribute_completion() { | 504 | fn test_inner_attribute_completion() { |
516 | check( | 505 | check( |
517 | r"#![<|>]", | 506 | r"#![$0]", |
518 | expect![[r#" | 507 | expect![[r#" |
519 | at allow(…) | 508 | at allow(…) |
520 | at automatically_derived | 509 | at automatically_derived |
@@ -523,7 +512,7 @@ struct Test {} | |||
523 | at cold | 512 | at cold |
524 | at crate_name = "" | 513 | at crate_name = "" |
525 | at deny(…) | 514 | at deny(…) |
526 | at deprecated = "…" | 515 | at deprecated |
527 | at derive(…) | 516 | at derive(…) |
528 | at export_name = "…" | 517 | at export_name = "…" |
529 | at doc = "…" | 518 | at doc = "…" |
@@ -537,7 +526,7 @@ struct Test {} | |||
537 | at link_section = "…" | 526 | at link_section = "…" |
538 | at macro_export | 527 | at macro_export |
539 | at macro_use | 528 | at macro_use |
540 | at must_use = "…" | 529 | at must_use |
541 | at no_link | 530 | at no_link |
542 | at no_implicit_prelude | 531 | at no_implicit_prelude |
543 | at no_main | 532 | at no_main |
@@ -551,7 +540,7 @@ struct Test {} | |||
551 | at proc_macro_derive(…) | 540 | at proc_macro_derive(…) |
552 | at recursion_limit = … | 541 | at recursion_limit = … |
553 | at repr(…) | 542 | at repr(…) |
554 | at should_panic(…) | 543 | at should_panic |
555 | at target_feature = "…" | 544 | at target_feature = "…" |
556 | at test | 545 | at test |
557 | at track_caller | 546 | at track_caller |
diff --git a/crates/completion/src/completions/dot.rs b/crates/completion/src/completions/dot.rs index 551ef1771..d04eef65a 100644 --- a/crates/completion/src/completions/dot.rs +++ b/crates/completion/src/completions/dot.rs | |||
@@ -79,7 +79,7 @@ struct S { foo: u32 } | |||
79 | impl S { | 79 | impl S { |
80 | fn bar(&self) {} | 80 | fn bar(&self) {} |
81 | } | 81 | } |
82 | fn foo(s: S) { s.<|> } | 82 | fn foo(s: S) { s.$0 } |
83 | "#, | 83 | "#, |
84 | expect![[r#" | 84 | expect![[r#" |
85 | fd foo u32 | 85 | fd foo u32 |
@@ -94,7 +94,7 @@ fn foo(s: S) { s.<|> } | |||
94 | r#" | 94 | r#" |
95 | struct S { the_field: (u32,) } | 95 | struct S { the_field: (u32,) } |
96 | impl S { | 96 | impl S { |
97 | fn foo(self) { self.<|> } | 97 | fn foo(self) { self.$0 } |
98 | } | 98 | } |
99 | "#, | 99 | "#, |
100 | expect![[r#" | 100 | expect![[r#" |
@@ -110,7 +110,7 @@ impl S { | |||
110 | r#" | 110 | r#" |
111 | struct A { the_field: (u32, i32) } | 111 | struct A { the_field: (u32, i32) } |
112 | impl A { | 112 | impl A { |
113 | fn foo(&self) { self.<|> } | 113 | fn foo(&self) { self.$0 } |
114 | } | 114 | } |
115 | "#, | 115 | "#, |
116 | expect![[r#" | 116 | expect![[r#" |
@@ -126,7 +126,7 @@ impl A { | |||
126 | check( | 126 | check( |
127 | r#" | 127 | r#" |
128 | struct A { the_field: u32 } | 128 | struct A { the_field: u32 } |
129 | fn foo(a: A) { a.<|>() } | 129 | fn foo(a: A) { a.$0() } |
130 | "#, | 130 | "#, |
131 | expect![[""]], | 131 | expect![[""]], |
132 | ); | 132 | ); |
@@ -144,7 +144,7 @@ mod inner { | |||
144 | pub(crate) super_field: u32, | 144 | pub(crate) super_field: u32, |
145 | } | 145 | } |
146 | } | 146 | } |
147 | fn foo(a: inner::A) { a.<|> } | 147 | fn foo(a: inner::A) { a.$0 } |
148 | "#, | 148 | "#, |
149 | expect![[r#" | 149 | expect![[r#" |
150 | fd pub_field u32 | 150 | fd pub_field u32 |
@@ -162,7 +162,7 @@ mod m { | |||
162 | pub(crate) fn the_method(&self) {} | 162 | pub(crate) fn the_method(&self) {} |
163 | } | 163 | } |
164 | } | 164 | } |
165 | fn foo(a: A) { a.<|> } | 165 | fn foo(a: A) { a.$0 } |
166 | "#, | 166 | "#, |
167 | expect![[r#" | 167 | expect![[r#" |
168 | me the_method() pub(crate) fn the_method(&self) | 168 | me the_method() pub(crate) fn the_method(&self) |
@@ -175,7 +175,7 @@ fn foo(a: A) { a.<|> } | |||
175 | check( | 175 | check( |
176 | r#" | 176 | r#" |
177 | union U { field: u8, other: u16 } | 177 | union U { field: u8, other: u16 } |
178 | fn foo(u: U) { u.<|> } | 178 | fn foo(u: U) { u.$0 } |
179 | "#, | 179 | "#, |
180 | expect![[r#" | 180 | expect![[r#" |
181 | fd field u8 | 181 | fd field u8 |
@@ -195,7 +195,7 @@ impl A<u32> { | |||
195 | impl A<i32> { | 195 | impl A<i32> { |
196 | fn the_other_method(&self) {} | 196 | fn the_other_method(&self) {} |
197 | } | 197 | } |
198 | fn foo(a: A<u32>) { a.<|> } | 198 | fn foo(a: A<u32>) { a.$0 } |
199 | "#, | 199 | "#, |
200 | expect![[r#" | 200 | expect![[r#" |
201 | me the_method() fn the_method(&self) | 201 | me the_method() fn the_method(&self) |
@@ -210,7 +210,7 @@ fn foo(a: A<u32>) { a.<|> } | |||
210 | struct A {} | 210 | struct A {} |
211 | trait Trait { fn the_method(&self); } | 211 | trait Trait { fn the_method(&self); } |
212 | impl Trait for A {} | 212 | impl Trait for A {} |
213 | fn foo(a: A) { a.<|> } | 213 | fn foo(a: A) { a.$0 } |
214 | "#, | 214 | "#, |
215 | expect![[r#" | 215 | expect![[r#" |
216 | me the_method() fn the_method(&self) | 216 | me the_method() fn the_method(&self) |
@@ -225,7 +225,7 @@ fn foo(a: A) { a.<|> } | |||
225 | struct A {} | 225 | struct A {} |
226 | trait Trait { fn the_method(&self); } | 226 | trait Trait { fn the_method(&self); } |
227 | impl<T> Trait for T {} | 227 | impl<T> Trait for T {} |
228 | fn foo(a: &A) { a.<|> } | 228 | fn foo(a: &A) { a.$0 } |
229 | ", | 229 | ", |
230 | expect![[r#" | 230 | expect![[r#" |
231 | me the_method() fn the_method(&self) | 231 | me the_method() fn the_method(&self) |
@@ -243,7 +243,7 @@ mod m { | |||
243 | } | 243 | } |
244 | use m::Trait; | 244 | use m::Trait; |
245 | impl Trait for A {} | 245 | impl Trait for A {} |
246 | fn foo(a: A) { a.<|> } | 246 | fn foo(a: A) { a.$0 } |
247 | ", | 247 | ", |
248 | expect![[r#" | 248 | expect![[r#" |
249 | me the_method() fn the_method(&self) | 249 | me the_method() fn the_method(&self) |
@@ -260,7 +260,7 @@ impl A { | |||
260 | fn the_method() {} | 260 | fn the_method() {} |
261 | } | 261 | } |
262 | fn foo(a: A) { | 262 | fn foo(a: A) { |
263 | a.<|> | 263 | a.$0 |
264 | } | 264 | } |
265 | "#, | 265 | "#, |
266 | expect![[""]], | 266 | expect![[""]], |
@@ -273,7 +273,7 @@ fn foo(a: A) { | |||
273 | r#" | 273 | r#" |
274 | fn foo() { | 274 | fn foo() { |
275 | let b = (0, 3.14); | 275 | let b = (0, 3.14); |
276 | b.<|> | 276 | b.$0 |
277 | } | 277 | } |
278 | "#, | 278 | "#, |
279 | expect![[r#" | 279 | expect![[r#" |
@@ -295,7 +295,7 @@ struct T(S); | |||
295 | impl T { | 295 | impl T { |
296 | fn foo(&self) { | 296 | fn foo(&self) { |
297 | // FIXME: This doesn't work without the trailing `a` as `0.` is a float | 297 | // FIXME: This doesn't work without the trailing `a` as `0.` is a float |
298 | self.0.a<|> | 298 | self.0.a$0 |
299 | } | 299 | } |
300 | } | 300 | } |
301 | "#, | 301 | "#, |
@@ -311,7 +311,7 @@ impl T { | |||
311 | r#" | 311 | r#" |
312 | struct A { the_field: u32 } | 312 | struct A { the_field: u32 } |
313 | const X: u32 = { | 313 | const X: u32 = { |
314 | A { the_field: 92 }.<|> | 314 | A { the_field: 92 }.$0 |
315 | }; | 315 | }; |
316 | "#, | 316 | "#, |
317 | expect![[r#" | 317 | expect![[r#" |
@@ -327,7 +327,7 @@ const X: u32 = { | |||
327 | macro_rules! m { ($e:expr) => { $e } } | 327 | macro_rules! m { ($e:expr) => { $e } } |
328 | struct A { the_field: u32 } | 328 | struct A { the_field: u32 } |
329 | fn foo(a: A) { | 329 | fn foo(a: A) { |
330 | m!(a.x<|>) | 330 | m!(a.x$0) |
331 | } | 331 | } |
332 | "#, | 332 | "#, |
333 | expect![[r#" | 333 | expect![[r#" |
@@ -344,7 +344,7 @@ fn foo(a: A) { | |||
344 | macro_rules! m { ($e:expr) => { $e } } | 344 | macro_rules! m { ($e:expr) => { $e } } |
345 | struct A { the_field: u32 } | 345 | struct A { the_field: u32 } |
346 | fn foo(a: A) { | 346 | fn foo(a: A) { |
347 | m!(a.<|>) | 347 | m!(a.$0) |
348 | } | 348 | } |
349 | "#, | 349 | "#, |
350 | expect![[r#" | 350 | expect![[r#" |
@@ -360,7 +360,7 @@ fn foo(a: A) { | |||
360 | macro_rules! m { ($e:expr) => { $e } } | 360 | macro_rules! m { ($e:expr) => { $e } } |
361 | struct A { the_field: u32 } | 361 | struct A { the_field: u32 } |
362 | fn foo(a: A) { | 362 | fn foo(a: A) { |
363 | m!(m!(m!(a.x<|>))) | 363 | m!(m!(m!(a.x$0))) |
364 | } | 364 | } |
365 | "#, | 365 | "#, |
366 | expect![[r#" | 366 | expect![[r#" |
@@ -373,20 +373,20 @@ fn foo(a: A) { | |||
373 | fn macro_expansion_resilient() { | 373 | fn macro_expansion_resilient() { |
374 | check( | 374 | check( |
375 | r#" | 375 | r#" |
376 | macro_rules! dbg { | 376 | macro_rules! d { |
377 | () => {}; | 377 | () => {}; |
378 | ($val:expr) => { | 378 | ($val:expr) => { |
379 | match $val { tmp => { tmp } } | 379 | match $val { tmp => { tmp } } |
380 | }; | 380 | }; |
381 | // Trailing comma with single argument is ignored | 381 | // Trailing comma with single argument is ignored |
382 | ($val:expr,) => { $crate::dbg!($val) }; | 382 | ($val:expr,) => { $crate::d!($val) }; |
383 | ($($val:expr),+ $(,)?) => { | 383 | ($($val:expr),+ $(,)?) => { |
384 | ($($crate::dbg!($val)),+,) | 384 | ($($crate::d!($val)),+,) |
385 | }; | 385 | }; |
386 | } | 386 | } |
387 | struct A { the_field: u32 } | 387 | struct A { the_field: u32 } |
388 | fn foo(a: A) { | 388 | fn foo(a: A) { |
389 | dbg!(a.<|>) | 389 | d!(a.$0) |
390 | } | 390 | } |
391 | "#, | 391 | "#, |
392 | expect![[r#" | 392 | expect![[r#" |
@@ -405,7 +405,7 @@ impl<T> HashSet<T> { | |||
405 | } | 405 | } |
406 | fn foo() { | 406 | fn foo() { |
407 | let s: HashSet<_>; | 407 | let s: HashSet<_>; |
408 | s.<|> | 408 | s.$0 |
409 | } | 409 | } |
410 | "#, | 410 | "#, |
411 | expect![[r#" | 411 | expect![[r#" |
@@ -421,7 +421,7 @@ fn foo() { | |||
421 | struct S; | 421 | struct S; |
422 | impl S { fn foo(&self) {} } | 422 | impl S { fn foo(&self) {} } |
423 | macro_rules! make_s { () => { S }; } | 423 | macro_rules! make_s { () => { S }; } |
424 | fn main() { make_s!().f<|>; } | 424 | fn main() { make_s!().f$0; } |
425 | "#, | 425 | "#, |
426 | expect![[r#" | 426 | expect![[r#" |
427 | me foo() fn foo(&self) | 427 | me foo() fn foo(&self) |
diff --git a/crates/completion/src/completions/fn_param.rs b/crates/completion/src/completions/fn_param.rs index e777a53c1..5505c3559 100644 --- a/crates/completion/src/completions/fn_param.rs +++ b/crates/completion/src/completions/fn_param.rs | |||
@@ -81,7 +81,7 @@ mod tests { | |||
81 | r#" | 81 | r#" |
82 | fn foo(file_id: FileId) {} | 82 | fn foo(file_id: FileId) {} |
83 | fn bar(file_id: FileId) {} | 83 | fn bar(file_id: FileId) {} |
84 | fn baz(file<|>) {} | 84 | fn baz(file$0) {} |
85 | "#, | 85 | "#, |
86 | expect![[r#" | 86 | expect![[r#" |
87 | bn file_id: FileId | 87 | bn file_id: FileId |
@@ -94,7 +94,7 @@ fn baz(file<|>) {} | |||
94 | check( | 94 | check( |
95 | r#" | 95 | r#" |
96 | fn foo(file_id: FileId) {} | 96 | fn foo(file_id: FileId) {} |
97 | fn baz(file<|>, x: i32) {} | 97 | fn baz(file$0, x: i32) {} |
98 | "#, | 98 | "#, |
99 | expect![[r#" | 99 | expect![[r#" |
100 | bn file_id: FileId | 100 | bn file_id: FileId |
@@ -110,7 +110,7 @@ pub(crate) trait SourceRoot { | |||
110 | pub fn contains(&self, file_id: FileId) -> bool; | 110 | pub fn contains(&self, file_id: FileId) -> bool; |
111 | pub fn module_map(&self) -> &ModuleMap; | 111 | pub fn module_map(&self) -> &ModuleMap; |
112 | pub fn lines(&self, file_id: FileId) -> &LineIndex; | 112 | pub fn lines(&self, file_id: FileId) -> &LineIndex; |
113 | pub fn syntax(&self, file<|>) | 113 | pub fn syntax(&self, file$0) |
114 | } | 114 | } |
115 | "#, | 115 | "#, |
116 | expect![[r#" | 116 | expect![[r#" |
@@ -124,7 +124,7 @@ pub(crate) trait SourceRoot { | |||
124 | check( | 124 | check( |
125 | r#" | 125 | r#" |
126 | fn outer(text: String) { | 126 | fn outer(text: String) { |
127 | fn inner(<|>) | 127 | fn inner($0) |
128 | } | 128 | } |
129 | "#, | 129 | "#, |
130 | expect![[r#" | 130 | expect![[r#" |
diff --git a/crates/completion/src/completions/keyword.rs b/crates/completion/src/completions/keyword.rs index 1859dec70..425a688ff 100644 --- a/crates/completion/src/completions/keyword.rs +++ b/crates/completion/src/completions/keyword.rs | |||
@@ -193,7 +193,7 @@ mod tests { | |||
193 | #[test] | 193 | #[test] |
194 | fn test_keywords_in_use_stmt() { | 194 | fn test_keywords_in_use_stmt() { |
195 | check( | 195 | check( |
196 | r"use <|>", | 196 | r"use $0", |
197 | expect![[r#" | 197 | expect![[r#" |
198 | kw crate:: | 198 | kw crate:: |
199 | kw self | 199 | kw self |
@@ -202,7 +202,7 @@ mod tests { | |||
202 | ); | 202 | ); |
203 | 203 | ||
204 | check( | 204 | check( |
205 | r"use a::<|>", | 205 | r"use a::$0", |
206 | expect![[r#" | 206 | expect![[r#" |
207 | kw self | 207 | kw self |
208 | kw super:: | 208 | kw super:: |
@@ -210,7 +210,7 @@ mod tests { | |||
210 | ); | 210 | ); |
211 | 211 | ||
212 | check( | 212 | check( |
213 | r"use a::{b, <|>}", | 213 | r"use a::{b, $0}", |
214 | expect![[r#" | 214 | expect![[r#" |
215 | kw self | 215 | kw self |
216 | kw super:: | 216 | kw super:: |
@@ -221,7 +221,7 @@ mod tests { | |||
221 | #[test] | 221 | #[test] |
222 | fn test_keywords_at_source_file_level() { | 222 | fn test_keywords_at_source_file_level() { |
223 | check( | 223 | check( |
224 | r"m<|>", | 224 | r"m$0", |
225 | expect![[r#" | 225 | expect![[r#" |
226 | kw fn | 226 | kw fn |
227 | kw use | 227 | kw use |
@@ -245,7 +245,7 @@ mod tests { | |||
245 | #[test] | 245 | #[test] |
246 | fn test_keywords_in_function() { | 246 | fn test_keywords_in_function() { |
247 | check( | 247 | check( |
248 | r"fn quux() { <|> }", | 248 | r"fn quux() { $0 }", |
249 | expect![[r#" | 249 | expect![[r#" |
250 | kw fn | 250 | kw fn |
251 | kw use | 251 | kw use |
@@ -271,7 +271,7 @@ mod tests { | |||
271 | #[test] | 271 | #[test] |
272 | fn test_keywords_inside_block() { | 272 | fn test_keywords_inside_block() { |
273 | check( | 273 | check( |
274 | r"fn quux() { if true { <|> } }", | 274 | r"fn quux() { if true { $0 } }", |
275 | expect![[r#" | 275 | expect![[r#" |
276 | kw fn | 276 | kw fn |
277 | kw use | 277 | kw use |
@@ -297,7 +297,7 @@ mod tests { | |||
297 | #[test] | 297 | #[test] |
298 | fn test_keywords_after_if() { | 298 | fn test_keywords_after_if() { |
299 | check( | 299 | check( |
300 | r#"fn quux() { if true { () } <|> }"#, | 300 | r#"fn quux() { if true { () } $0 }"#, |
301 | expect![[r#" | 301 | expect![[r#" |
302 | kw fn | 302 | kw fn |
303 | kw use | 303 | kw use |
@@ -322,7 +322,7 @@ mod tests { | |||
322 | ); | 322 | ); |
323 | check_edit( | 323 | check_edit( |
324 | "else", | 324 | "else", |
325 | r#"fn quux() { if true { () } <|> }"#, | 325 | r#"fn quux() { if true { () } $0 }"#, |
326 | r#"fn quux() { if true { () } else {$0} }"#, | 326 | r#"fn quux() { if true { () } else {$0} }"#, |
327 | ); | 327 | ); |
328 | } | 328 | } |
@@ -332,7 +332,7 @@ mod tests { | |||
332 | check( | 332 | check( |
333 | r#" | 333 | r#" |
334 | fn quux() -> i32 { | 334 | fn quux() -> i32 { |
335 | match () { () => <|> } | 335 | match () { () => $0 } |
336 | } | 336 | } |
337 | "#, | 337 | "#, |
338 | expect![[r#" | 338 | expect![[r#" |
@@ -350,7 +350,7 @@ fn quux() -> i32 { | |||
350 | #[test] | 350 | #[test] |
351 | fn test_keywords_in_trait_def() { | 351 | fn test_keywords_in_trait_def() { |
352 | check( | 352 | check( |
353 | r"trait My { <|> }", | 353 | r"trait My { $0 }", |
354 | expect![[r#" | 354 | expect![[r#" |
355 | kw fn | 355 | kw fn |
356 | kw const | 356 | kw const |
@@ -363,7 +363,7 @@ fn quux() -> i32 { | |||
363 | #[test] | 363 | #[test] |
364 | fn test_keywords_in_impl_def() { | 364 | fn test_keywords_in_impl_def() { |
365 | check( | 365 | check( |
366 | r"impl My { <|> }", | 366 | r"impl My { $0 }", |
367 | expect![[r#" | 367 | expect![[r#" |
368 | kw fn | 368 | kw fn |
369 | kw const | 369 | kw const |
@@ -378,7 +378,7 @@ fn quux() -> i32 { | |||
378 | #[test] | 378 | #[test] |
379 | fn test_keywords_in_loop() { | 379 | fn test_keywords_in_loop() { |
380 | check( | 380 | check( |
381 | r"fn my() { loop { <|> } }", | 381 | r"fn my() { loop { $0 } }", |
382 | expect![[r#" | 382 | expect![[r#" |
383 | kw fn | 383 | kw fn |
384 | kw use | 384 | kw use |
@@ -406,7 +406,7 @@ fn quux() -> i32 { | |||
406 | #[test] | 406 | #[test] |
407 | fn test_keywords_after_unsafe_in_item_list() { | 407 | fn test_keywords_after_unsafe_in_item_list() { |
408 | check( | 408 | check( |
409 | r"unsafe <|>", | 409 | r"unsafe $0", |
410 | expect![[r#" | 410 | expect![[r#" |
411 | kw fn | 411 | kw fn |
412 | kw trait | 412 | kw trait |
@@ -418,7 +418,7 @@ fn quux() -> i32 { | |||
418 | #[test] | 418 | #[test] |
419 | fn test_keywords_after_unsafe_in_block_expr() { | 419 | fn test_keywords_after_unsafe_in_block_expr() { |
420 | check( | 420 | check( |
421 | r"fn my_fn() { unsafe <|> }", | 421 | r"fn my_fn() { unsafe $0 }", |
422 | expect![[r#" | 422 | expect![[r#" |
423 | kw fn | 423 | kw fn |
424 | kw trait | 424 | kw trait |
@@ -430,19 +430,19 @@ fn quux() -> i32 { | |||
430 | #[test] | 430 | #[test] |
431 | fn test_mut_in_ref_and_in_fn_parameters_list() { | 431 | fn test_mut_in_ref_and_in_fn_parameters_list() { |
432 | check( | 432 | check( |
433 | r"fn my_fn(&<|>) {}", | 433 | r"fn my_fn(&$0) {}", |
434 | expect![[r#" | 434 | expect![[r#" |
435 | kw mut | 435 | kw mut |
436 | "#]], | 436 | "#]], |
437 | ); | 437 | ); |
438 | check( | 438 | check( |
439 | r"fn my_fn(<|>) {}", | 439 | r"fn my_fn($0) {}", |
440 | expect![[r#" | 440 | expect![[r#" |
441 | kw mut | 441 | kw mut |
442 | "#]], | 442 | "#]], |
443 | ); | 443 | ); |
444 | check( | 444 | check( |
445 | r"fn my_fn() { let &<|> }", | 445 | r"fn my_fn() { let &$0 }", |
446 | expect![[r#" | 446 | expect![[r#" |
447 | kw mut | 447 | kw mut |
448 | "#]], | 448 | "#]], |
@@ -452,13 +452,13 @@ fn quux() -> i32 { | |||
452 | #[test] | 452 | #[test] |
453 | fn test_where_keyword() { | 453 | fn test_where_keyword() { |
454 | check( | 454 | check( |
455 | r"trait A <|>", | 455 | r"trait A $0", |
456 | expect![[r#" | 456 | expect![[r#" |
457 | kw where | 457 | kw where |
458 | "#]], | 458 | "#]], |
459 | ); | 459 | ); |
460 | check( | 460 | check( |
461 | r"impl A <|>", | 461 | r"impl A $0", |
462 | expect![[r#" | 462 | expect![[r#" |
463 | kw where | 463 | kw where |
464 | "#]], | 464 | "#]], |
@@ -471,7 +471,7 @@ fn quux() -> i32 { | |||
471 | check( | 471 | check( |
472 | r#" | 472 | r#" |
473 | fn test() { | 473 | fn test() { |
474 | let x = 2; // A comment<|> | 474 | let x = 2; // A comment$0 |
475 | } | 475 | } |
476 | "#, | 476 | "#, |
477 | expect![[""]], | 477 | expect![[""]], |
@@ -479,7 +479,7 @@ fn test() { | |||
479 | check( | 479 | check( |
480 | r#" | 480 | r#" |
481 | /* | 481 | /* |
482 | Some multi-line comment<|> | 482 | Some multi-line comment$0 |
483 | */ | 483 | */ |
484 | "#, | 484 | "#, |
485 | expect![[""]], | 485 | expect![[""]], |
@@ -487,7 +487,7 @@ Some multi-line comment<|> | |||
487 | check( | 487 | check( |
488 | r#" | 488 | r#" |
489 | /// Some doc comment | 489 | /// Some doc comment |
490 | /// let test<|> = 1 | 490 | /// let test$0 = 1 |
491 | "#, | 491 | "#, |
492 | expect![[""]], | 492 | expect![[""]], |
493 | ); | 493 | ); |
@@ -501,7 +501,7 @@ Some multi-line comment<|> | |||
501 | use std::future::*; | 501 | use std::future::*; |
502 | struct A {} | 502 | struct A {} |
503 | impl Future for A {} | 503 | impl Future for A {} |
504 | fn foo(a: A) { a.<|> } | 504 | fn foo(a: A) { a.$0 } |
505 | 505 | ||
506 | //- /std/lib.rs crate:std | 506 | //- /std/lib.rs crate:std |
507 | pub mod future { | 507 | pub mod future { |
@@ -520,7 +520,7 @@ pub mod future { | |||
520 | use std::future::*; | 520 | use std::future::*; |
521 | fn foo() { | 521 | fn foo() { |
522 | let a = async {}; | 522 | let a = async {}; |
523 | a.<|> | 523 | a.$0 |
524 | } | 524 | } |
525 | 525 | ||
526 | //- /std/lib.rs crate:std | 526 | //- /std/lib.rs crate:std |
@@ -540,7 +540,7 @@ pub mod future { | |||
540 | #[test] | 540 | #[test] |
541 | fn after_let() { | 541 | fn after_let() { |
542 | check( | 542 | check( |
543 | r#"fn main() { let _ = <|> }"#, | 543 | r#"fn main() { let _ = $0 }"#, |
544 | expect![[r#" | 544 | expect![[r#" |
545 | kw match | 545 | kw match |
546 | kw while | 546 | kw while |
@@ -557,7 +557,7 @@ pub mod future { | |||
557 | check( | 557 | check( |
558 | r#" | 558 | r#" |
559 | struct Foo { | 559 | struct Foo { |
560 | <|> | 560 | $0 |
561 | pub f: i32, | 561 | pub f: i32, |
562 | } | 562 | } |
563 | "#, | 563 | "#, |
@@ -578,7 +578,7 @@ struct Foo { | |||
578 | } | 578 | } |
579 | fn foo() { | 579 | fn foo() { |
580 | Foo { | 580 | Foo { |
581 | <|> | 581 | $0 |
582 | } | 582 | } |
583 | } | 583 | } |
584 | "#, | 584 | "#, |
@@ -595,7 +595,7 @@ struct Foo { | |||
595 | } | 595 | } |
596 | fn foo() { | 596 | fn foo() { |
597 | Foo { | 597 | Foo { |
598 | f: <|> | 598 | f: $0 |
599 | } | 599 | } |
600 | } | 600 | } |
601 | "#, | 601 | "#, |
diff --git a/crates/completion/src/completions/macro_in_item_position.rs b/crates/completion/src/completions/macro_in_item_position.rs index 82884a181..2be299ac2 100644 --- a/crates/completion/src/completions/macro_in_item_position.rs +++ b/crates/completion/src/completions/macro_in_item_position.rs | |||
@@ -31,7 +31,7 @@ mod tests { | |||
31 | macro_rules! foo { () => {} } | 31 | macro_rules! foo { () => {} } |
32 | fn foo() {} | 32 | fn foo() {} |
33 | 33 | ||
34 | <|> | 34 | $0 |
35 | "#, | 35 | "#, |
36 | expect![[r#" | 36 | expect![[r#" |
37 | ma foo!(…) macro_rules! foo | 37 | ma foo!(…) macro_rules! foo |
diff --git a/crates/completion/src/completions/mod_.rs b/crates/completion/src/completions/mod_.rs index f77864b77..00e951ca9 100644 --- a/crates/completion/src/completions/mod_.rs +++ b/crates/completion/src/completions/mod_.rs | |||
@@ -1,5 +1,7 @@ | |||
1 | //! Completes mod declarations. | 1 | //! Completes mod declarations. |
2 | 2 | ||
3 | use std::iter; | ||
4 | |||
3 | use hir::{Module, ModuleSource}; | 5 | use hir::{Module, ModuleSource}; |
4 | use ide_db::base_db::{SourceDatabaseExt, VfsPath}; | 6 | use ide_db::base_db::{SourceDatabaseExt, VfsPath}; |
5 | use ide_db::RootDatabase; | 7 | use ide_db::RootDatabase; |
@@ -9,12 +11,11 @@ use crate::{CompletionItem, CompletionItemKind}; | |||
9 | 11 | ||
10 | use crate::{context::CompletionContext, item::CompletionKind, Completions}; | 12 | use crate::{context::CompletionContext, item::CompletionKind, Completions}; |
11 | 13 | ||
12 | /// Complete mod declaration, i.e. `mod <|> ;` | 14 | /// Complete mod declaration, i.e. `mod $0 ;` |
13 | pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { | 15 | pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { |
14 | let mod_under_caret = match &ctx.mod_declaration_under_caret { | 16 | let mod_under_caret = match &ctx.mod_declaration_under_caret { |
15 | Some(mod_under_caret) if mod_under_caret.item_list().is_some() => return None, | 17 | Some(mod_under_caret) if mod_under_caret.item_list().is_none() => mod_under_caret, |
16 | Some(mod_under_caret) => mod_under_caret, | 18 | _ => return None, |
17 | None => return None, | ||
18 | }; | 19 | }; |
19 | 20 | ||
20 | let _p = profile::span("completion::complete_mod"); | 21 | let _p = profile::span("completion::complete_mod"); |
@@ -49,9 +50,13 @@ pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Op | |||
49 | .filter_map(|submodule_file| { | 50 | .filter_map(|submodule_file| { |
50 | let submodule_path = source_root.path_for_file(&submodule_file)?; | 51 | let submodule_path = source_root.path_for_file(&submodule_file)?; |
51 | let directory_with_submodule = submodule_path.parent()?; | 52 | let directory_with_submodule = submodule_path.parent()?; |
52 | match submodule_path.name_and_extension()? { | 53 | let (name, ext) = submodule_path.name_and_extension()?; |
53 | ("lib", Some("rs")) | ("main", Some("rs")) => None, | 54 | if ext != Some("rs") { |
54 | ("mod", Some("rs")) => { | 55 | return None; |
56 | } | ||
57 | match name { | ||
58 | "lib" | "main" => None, | ||
59 | "mod" => { | ||
55 | if directory_with_submodule.parent()? == directory_to_look_for_submodules { | 60 | if directory_with_submodule.parent()? == directory_to_look_for_submodules { |
56 | match directory_with_submodule.name_and_extension()? { | 61 | match directory_with_submodule.name_and_extension()? { |
57 | (directory_name, None) => Some(directory_name.to_owned()), | 62 | (directory_name, None) => Some(directory_name.to_owned()), |
@@ -61,9 +66,7 @@ pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Op | |||
61 | None | 66 | None |
62 | } | 67 | } |
63 | } | 68 | } |
64 | (file_name, Some("rs")) | 69 | file_name if directory_with_submodule == directory_to_look_for_submodules => { |
65 | if directory_with_submodule == directory_to_look_for_submodules => | ||
66 | { | ||
67 | Some(file_name.to_owned()) | 70 | Some(file_name.to_owned()) |
68 | } | 71 | } |
69 | _ => None, | 72 | _ => None, |
@@ -73,7 +76,7 @@ pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Op | |||
73 | .for_each(|submodule_name| { | 76 | .for_each(|submodule_name| { |
74 | let mut label = submodule_name; | 77 | let mut label = submodule_name; |
75 | if mod_under_caret.semicolon_token().is_none() { | 78 | if mod_under_caret.semicolon_token().is_none() { |
76 | label.push(';') | 79 | label.push(';'); |
77 | } | 80 | } |
78 | CompletionItem::new(CompletionKind::Magic, ctx.source_range(), &label) | 81 | CompletionItem::new(CompletionKind::Magic, ctx.source_range(), &label) |
79 | .kind(CompletionItemKind::Module) | 82 | .kind(CompletionItemKind::Module) |
@@ -89,11 +92,13 @@ fn directory_to_look_for_submodules( | |||
89 | module_file_path: &VfsPath, | 92 | module_file_path: &VfsPath, |
90 | ) -> Option<VfsPath> { | 93 | ) -> Option<VfsPath> { |
91 | let directory_with_module_path = module_file_path.parent()?; | 94 | let directory_with_module_path = module_file_path.parent()?; |
92 | let base_directory = match module_file_path.name_and_extension()? { | 95 | let (name, ext) = module_file_path.name_and_extension()?; |
93 | ("mod", Some("rs")) | ("lib", Some("rs")) | ("main", Some("rs")) => { | 96 | if ext != Some("rs") { |
94 | Some(directory_with_module_path) | 97 | return None; |
95 | } | 98 | } |
96 | (regular_rust_file_name, Some("rs")) => { | 99 | let base_directory = match name { |
100 | "mod" | "lib" | "main" => Some(directory_with_module_path), | ||
101 | regular_rust_file_name => { | ||
97 | if matches!( | 102 | if matches!( |
98 | ( | 103 | ( |
99 | directory_with_module_path | 104 | directory_with_module_path |
@@ -110,37 +115,25 @@ fn directory_to_look_for_submodules( | |||
110 | directory_with_module_path.join(regular_rust_file_name) | 115 | directory_with_module_path.join(regular_rust_file_name) |
111 | } | 116 | } |
112 | } | 117 | } |
113 | _ => None, | ||
114 | }?; | 118 | }?; |
115 | 119 | ||
116 | let mut resulting_path = base_directory; | 120 | module_chain_to_containing_module_file(module, db) |
117 | for module in module_chain_to_containing_module_file(module, db) { | 121 | .into_iter() |
118 | if let Some(name) = module.name(db) { | 122 | .filter_map(|module| module.name(db)) |
119 | resulting_path = resulting_path.join(&name.to_string())?; | 123 | .try_fold(base_directory, |path, name| path.join(&name.to_string())) |
120 | } | ||
121 | } | ||
122 | |||
123 | Some(resulting_path) | ||
124 | } | 124 | } |
125 | 125 | ||
126 | fn module_chain_to_containing_module_file( | 126 | fn module_chain_to_containing_module_file( |
127 | current_module: Module, | 127 | current_module: Module, |
128 | db: &RootDatabase, | 128 | db: &RootDatabase, |
129 | ) -> Vec<Module> { | 129 | ) -> Vec<Module> { |
130 | let mut path = Vec::new(); | 130 | let mut path = |
131 | 131 | iter::successors(Some(current_module), |current_module| current_module.parent(db)) | |
132 | let mut current_module = Some(current_module); | 132 | .take_while(|current_module| { |
133 | while let Some(ModuleSource::Module(_)) = | 133 | matches!(current_module.definition_source(db).value, ModuleSource::Module(_)) |
134 | current_module.map(|module| module.definition_source(db).value) | 134 | }) |
135 | { | 135 | .collect::<Vec<_>>(); |
136 | if let Some(module) = current_module { | 136 | path.reverse(); |
137 | path.insert(0, module); | ||
138 | current_module = module.parent(db); | ||
139 | } else { | ||
140 | current_module = None; | ||
141 | } | ||
142 | } | ||
143 | |||
144 | path | 137 | path |
145 | } | 138 | } |
146 | 139 | ||
@@ -159,7 +152,7 @@ mod tests { | |||
159 | check( | 152 | check( |
160 | r#" | 153 | r#" |
161 | //- /lib.rs | 154 | //- /lib.rs |
162 | mod <|> | 155 | mod $0 |
163 | //- /foo.rs | 156 | //- /foo.rs |
164 | fn foo() {} | 157 | fn foo() {} |
165 | //- /foo/ignored_foo.rs | 158 | //- /foo/ignored_foo.rs |
@@ -181,7 +174,7 @@ mod tests { | |||
181 | check( | 174 | check( |
182 | r#" | 175 | r#" |
183 | //- /lib.rs | 176 | //- /lib.rs |
184 | mod <|> { | 177 | mod $0 { |
185 | 178 | ||
186 | } | 179 | } |
187 | //- /foo.rs | 180 | //- /foo.rs |
@@ -196,7 +189,7 @@ mod tests { | |||
196 | check( | 189 | check( |
197 | r#" | 190 | r#" |
198 | //- /main.rs | 191 | //- /main.rs |
199 | mod <|> | 192 | mod $0 |
200 | //- /foo.rs | 193 | //- /foo.rs |
201 | fn foo() {} | 194 | fn foo() {} |
202 | //- /foo/ignored_foo.rs | 195 | //- /foo/ignored_foo.rs |
@@ -219,7 +212,7 @@ mod tests { | |||
219 | r#" | 212 | r#" |
220 | //- /main.rs | 213 | //- /main.rs |
221 | mod tests { | 214 | mod tests { |
222 | mod <|>; | 215 | mod $0; |
223 | } | 216 | } |
224 | //- /tests/foo.rs | 217 | //- /tests/foo.rs |
225 | fn foo() {} | 218 | fn foo() {} |
@@ -237,7 +230,7 @@ mod tests { | |||
237 | //- /lib.rs | 230 | //- /lib.rs |
238 | mod foo; | 231 | mod foo; |
239 | //- /foo.rs | 232 | //- /foo.rs |
240 | mod <|>; | 233 | mod $0; |
241 | //- /foo/bar.rs | 234 | //- /foo/bar.rs |
242 | fn bar() {} | 235 | fn bar() {} |
243 | //- /foo/bar/ignored_bar.rs | 236 | //- /foo/bar/ignored_bar.rs |
@@ -262,7 +255,7 @@ mod tests { | |||
262 | mod foo; | 255 | mod foo; |
263 | //- /foo.rs | 256 | //- /foo.rs |
264 | mod bar { | 257 | mod bar { |
265 | mod <|> | 258 | mod $0 |
266 | } | 259 | } |
267 | //- /foo/bar/baz.rs | 260 | //- /foo/bar/baz.rs |
268 | fn baz() {} | 261 | fn baz() {} |
@@ -288,7 +281,7 @@ mod tests { | |||
288 | // //- /src/bin.rs | 281 | // //- /src/bin.rs |
289 | // fn main() {} | 282 | // fn main() {} |
290 | // //- /src/bin/foo.rs | 283 | // //- /src/bin/foo.rs |
291 | // mod <|> | 284 | // mod $0 |
292 | // //- /src/bin/bar.rs | 285 | // //- /src/bin/bar.rs |
293 | // fn bar() {} | 286 | // fn bar() {} |
294 | // //- /src/bin/bar/bar_ignored.rs | 287 | // //- /src/bin/bar/bar_ignored.rs |
@@ -307,7 +300,7 @@ mod tests { | |||
307 | //- /src/bin.rs crate:main | 300 | //- /src/bin.rs crate:main |
308 | fn main() {} | 301 | fn main() {} |
309 | //- /src/bin/foo.rs | 302 | //- /src/bin/foo.rs |
310 | mod <|> | 303 | mod $0 |
311 | //- /src/bin/bar.rs | 304 | //- /src/bin/bar.rs |
312 | mod foo; | 305 | mod foo; |
313 | fn bar() {} | 306 | fn bar() {} |
diff --git a/crates/completion/src/completions/pattern.rs b/crates/completion/src/completions/pattern.rs index eee31098d..595160ff5 100644 --- a/crates/completion/src/completions/pattern.rs +++ b/crates/completion/src/completions/pattern.rs | |||
@@ -71,7 +71,7 @@ static FOO: E = E::X; | |||
71 | struct Bar { f: u32 } | 71 | struct Bar { f: u32 } |
72 | 72 | ||
73 | fn foo() { | 73 | fn foo() { |
74 | match E::X { <|> } | 74 | match E::X { $0 } |
75 | } | 75 | } |
76 | "#, | 76 | "#, |
77 | expect![[r#" | 77 | expect![[r#" |
@@ -92,7 +92,7 @@ macro_rules! m { ($e:expr) => { $e } } | |||
92 | enum E { X } | 92 | enum E { X } |
93 | 93 | ||
94 | fn foo() { | 94 | fn foo() { |
95 | m!(match E::X { <|> }) | 95 | m!(match E::X { $0 }) |
96 | } | 96 | } |
97 | "#, | 97 | "#, |
98 | expect![[r#" | 98 | expect![[r#" |
@@ -115,7 +115,7 @@ static FOO: E = E::X; | |||
115 | struct Bar { f: u32 } | 115 | struct Bar { f: u32 } |
116 | 116 | ||
117 | fn foo() { | 117 | fn foo() { |
118 | let <|> | 118 | let $0 |
119 | } | 119 | } |
120 | "#, | 120 | "#, |
121 | expect![[r#" | 121 | expect![[r#" |
@@ -133,7 +133,7 @@ enum E { X } | |||
133 | static FOO: E = E::X; | 133 | static FOO: E = E::X; |
134 | struct Bar { f: u32 } | 134 | struct Bar { f: u32 } |
135 | 135 | ||
136 | fn foo(<|>) { | 136 | fn foo($0) { |
137 | } | 137 | } |
138 | "#, | 138 | "#, |
139 | expect![[r#" | 139 | expect![[r#" |
@@ -149,7 +149,7 @@ fn foo(<|>) { | |||
149 | struct Bar { f: u32 } | 149 | struct Bar { f: u32 } |
150 | 150 | ||
151 | fn foo() { | 151 | fn foo() { |
152 | let <|> | 152 | let $0 |
153 | } | 153 | } |
154 | "#, | 154 | "#, |
155 | expect![[r#" | 155 | expect![[r#" |
@@ -165,7 +165,7 @@ fn foo() { | |||
165 | struct Foo { bar: String, baz: String } | 165 | struct Foo { bar: String, baz: String } |
166 | struct Bar(String, String); | 166 | struct Bar(String, String); |
167 | struct Baz; | 167 | struct Baz; |
168 | fn outer(<|>) {} | 168 | fn outer($0) {} |
169 | "#, | 169 | "#, |
170 | expect![[r#" | 170 | expect![[r#" |
171 | bn Foo Foo { bar$1, baz$2 }: Foo$0 | 171 | bn Foo Foo { bar$1, baz$2 }: Foo$0 |
@@ -182,7 +182,7 @@ struct Foo { bar: String, baz: String } | |||
182 | struct Bar(String, String); | 182 | struct Bar(String, String); |
183 | struct Baz; | 183 | struct Baz; |
184 | fn outer() { | 184 | fn outer() { |
185 | let <|> | 185 | let $0 |
186 | } | 186 | } |
187 | "#, | 187 | "#, |
188 | expect![[r#" | 188 | expect![[r#" |
@@ -201,7 +201,7 @@ struct Bar(String, String); | |||
201 | struct Baz; | 201 | struct Baz; |
202 | fn outer() { | 202 | fn outer() { |
203 | match () { | 203 | match () { |
204 | <|> | 204 | $0 |
205 | } | 205 | } |
206 | } | 206 | } |
207 | "#, | 207 | "#, |
@@ -225,7 +225,7 @@ use foo::*; | |||
225 | 225 | ||
226 | fn outer() { | 226 | fn outer() { |
227 | match () { | 227 | match () { |
228 | <|> | 228 | $0 |
229 | } | 229 | } |
230 | } | 230 | } |
231 | "#, | 231 | "#, |
@@ -244,7 +244,7 @@ fn outer() { | |||
244 | struct Foo(i32); | 244 | struct Foo(i32); |
245 | fn main() { | 245 | fn main() { |
246 | match Foo(92) { | 246 | match Foo(92) { |
247 | <|>(92) => (), | 247 | $0(92) => (), |
248 | } | 248 | } |
249 | } | 249 | } |
250 | "#, | 250 | "#, |
diff --git a/crates/completion/src/completions/postfix.rs b/crates/completion/src/completions/postfix.rs index 3883d6d21..9c34ed0b6 100644 --- a/crates/completion/src/completions/postfix.rs +++ b/crates/completion/src/completions/postfix.rs | |||
@@ -1,8 +1,8 @@ | |||
1 | //! Postfix completions, like `Ok(10).ifl<|>` => `if let Ok() = Ok(10) { <|> }`. | 1 | //! Postfix completions, like `Ok(10).ifl$0` => `if let Ok() = Ok(10) { $0 }`. |
2 | 2 | ||
3 | mod format_like; | 3 | mod format_like; |
4 | 4 | ||
5 | use ide_db::ty_filter::TryEnum; | 5 | use ide_db::{helpers::SnippetCap, ty_filter::TryEnum}; |
6 | use syntax::{ | 6 | use syntax::{ |
7 | ast::{self, AstNode, AstToken}, | 7 | ast::{self, AstNode, AstToken}, |
8 | SyntaxKind::{BLOCK_EXPR, EXPR_STMT}, | 8 | SyntaxKind::{BLOCK_EXPR, EXPR_STMT}, |
@@ -10,9 +10,8 @@ use syntax::{ | |||
10 | }; | 10 | }; |
11 | use text_edit::TextEdit; | 11 | use text_edit::TextEdit; |
12 | 12 | ||
13 | use self::format_like::add_format_like_completions; | ||
14 | use crate::{ | 13 | use crate::{ |
15 | config::SnippetCap, | 14 | completions::postfix::format_like::add_format_like_completions, |
16 | context::CompletionContext, | 15 | context::CompletionContext, |
17 | item::{Builder, CompletionKind}, | 16 | item::{Builder, CompletionKind}, |
18 | CompletionItem, CompletionItemKind, Completions, | 17 | CompletionItem, CompletionItemKind, Completions, |
@@ -36,11 +35,14 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
36 | None => return, | 35 | None => return, |
37 | }; | 36 | }; |
38 | 37 | ||
38 | let ref_removed_ty = | ||
39 | std::iter::successors(Some(receiver_ty.clone()), |ty| ty.remove_ref()).last().unwrap(); | ||
40 | |||
39 | let cap = match ctx.config.snippet_cap { | 41 | let cap = match ctx.config.snippet_cap { |
40 | Some(it) => it, | 42 | Some(it) => it, |
41 | None => return, | 43 | None => return, |
42 | }; | 44 | }; |
43 | let try_enum = TryEnum::from_ty(&ctx.sema, &receiver_ty); | 45 | let try_enum = TryEnum::from_ty(&ctx.sema, &ref_removed_ty); |
44 | if let Some(try_enum) = &try_enum { | 46 | if let Some(try_enum) = &try_enum { |
45 | match try_enum { | 47 | match try_enum { |
46 | TryEnum::Result => { | 48 | TryEnum::Result => { |
@@ -311,7 +313,7 @@ mod tests { | |||
311 | r#" | 313 | r#" |
312 | fn main() { | 314 | fn main() { |
313 | let bar = true; | 315 | let bar = true; |
314 | bar.<|> | 316 | bar.$0 |
315 | } | 317 | } |
316 | "#, | 318 | "#, |
317 | expect![[r#" | 319 | expect![[r#" |
@@ -343,7 +345,7 @@ fn foo(elt: bool) -> bool { | |||
343 | 345 | ||
344 | fn main() { | 346 | fn main() { |
345 | let bar = true; | 347 | let bar = true; |
346 | foo(bar.<|>) | 348 | foo(bar.$0) |
347 | } | 349 | } |
348 | "#, | 350 | "#, |
349 | expect![[r#" | 351 | expect![[r#" |
@@ -369,7 +371,7 @@ fn main() { | |||
369 | r#" | 371 | r#" |
370 | fn main() { | 372 | fn main() { |
371 | let bar: u8 = 12; | 373 | let bar: u8 = 12; |
372 | bar.<|> | 374 | bar.$0 |
373 | } | 375 | } |
374 | "#, | 376 | "#, |
375 | expect![[r#" | 377 | expect![[r#" |
@@ -393,7 +395,7 @@ fn main() { | |||
393 | check( | 395 | check( |
394 | r#" | 396 | r#" |
395 | fn main() { | 397 | fn main() { |
396 | baz.l<|> | 398 | baz.l$0 |
397 | res | 399 | res |
398 | } | 400 | } |
399 | "#, | 401 | "#, |
@@ -425,7 +427,7 @@ enum Option<T> { Some(T), None } | |||
425 | 427 | ||
426 | fn main() { | 428 | fn main() { |
427 | let bar = Option::Some(true); | 429 | let bar = Option::Some(true); |
428 | bar.<|> | 430 | bar.$0 |
429 | } | 431 | } |
430 | "#, | 432 | "#, |
431 | r#" | 433 | r#" |
@@ -450,7 +452,7 @@ enum Result<T, E> { Ok(T), Err(E) } | |||
450 | 452 | ||
451 | fn main() { | 453 | fn main() { |
452 | let bar = Result::Ok(true); | 454 | let bar = Result::Ok(true); |
453 | bar.<|> | 455 | bar.$0 |
454 | } | 456 | } |
455 | "#, | 457 | "#, |
456 | r#" | 458 | r#" |
@@ -469,7 +471,7 @@ fn main() { | |||
469 | 471 | ||
470 | #[test] | 472 | #[test] |
471 | fn postfix_completion_works_for_ambiguous_float_literal() { | 473 | fn postfix_completion_works_for_ambiguous_float_literal() { |
472 | check_edit("refm", r#"fn main() { 42.<|> }"#, r#"fn main() { &mut 42 }"#) | 474 | check_edit("refm", r#"fn main() { 42.$0 }"#, r#"fn main() { &mut 42 }"#) |
473 | } | 475 | } |
474 | 476 | ||
475 | #[test] | 477 | #[test] |
@@ -480,7 +482,7 @@ fn main() { | |||
480 | macro_rules! m { ($e:expr) => { $e } } | 482 | macro_rules! m { ($e:expr) => { $e } } |
481 | fn main() { | 483 | fn main() { |
482 | let bar: u8 = 12; | 484 | let bar: u8 = 12; |
483 | m!(bar.d<|>) | 485 | m!(bar.d$0) |
484 | } | 486 | } |
485 | "#, | 487 | "#, |
486 | r#" | 488 | r#" |
@@ -495,55 +497,68 @@ fn main() { | |||
495 | 497 | ||
496 | #[test] | 498 | #[test] |
497 | fn postfix_completion_for_references() { | 499 | fn postfix_completion_for_references() { |
498 | check_edit("dbg", r#"fn main() { &&42.<|> }"#, r#"fn main() { dbg!(&&42) }"#); | 500 | check_edit("dbg", r#"fn main() { &&42.$0 }"#, r#"fn main() { dbg!(&&42) }"#); |
499 | check_edit("refm", r#"fn main() { &&42.<|> }"#, r#"fn main() { &&&mut 42 }"#); | 501 | check_edit("refm", r#"fn main() { &&42.$0 }"#, r#"fn main() { &&&mut 42 }"#); |
502 | check_edit( | ||
503 | "ifl", | ||
504 | r#" | ||
505 | enum Option<T> { Some(T), None } | ||
506 | |||
507 | fn main() { | ||
508 | let bar = &Option::Some(true); | ||
509 | bar.$0 | ||
510 | } | ||
511 | "#, | ||
512 | r#" | ||
513 | enum Option<T> { Some(T), None } | ||
514 | |||
515 | fn main() { | ||
516 | let bar = &Option::Some(true); | ||
517 | if let Some($1) = bar { | ||
518 | $0 | ||
519 | } | ||
520 | } | ||
521 | "#, | ||
522 | ) | ||
500 | } | 523 | } |
501 | 524 | ||
502 | #[test] | 525 | #[test] |
503 | fn postfix_completion_for_format_like_strings() { | 526 | fn postfix_completion_for_format_like_strings() { |
504 | check_edit( | 527 | check_edit( |
505 | "format", | 528 | "format", |
506 | r#"fn main() { "{some_var:?}".<|> }"#, | 529 | r#"fn main() { "{some_var:?}".$0 }"#, |
507 | r#"fn main() { format!("{:?}", some_var) }"#, | 530 | r#"fn main() { format!("{:?}", some_var) }"#, |
508 | ); | 531 | ); |
509 | check_edit( | 532 | check_edit( |
510 | "panic", | 533 | "panic", |
511 | r#"fn main() { "Panic with {a}".<|> }"#, | 534 | r#"fn main() { "Panic with {a}".$0 }"#, |
512 | r#"fn main() { panic!("Panic with {}", a) }"#, | 535 | r#"fn main() { panic!("Panic with {}", a) }"#, |
513 | ); | 536 | ); |
514 | check_edit( | 537 | check_edit( |
515 | "println", | 538 | "println", |
516 | r#"fn main() { "{ 2+2 } { SomeStruct { val: 1, other: 32 } :?}".<|> }"#, | 539 | r#"fn main() { "{ 2+2 } { SomeStruct { val: 1, other: 32 } :?}".$0 }"#, |
517 | r#"fn main() { println!("{} {:?}", 2+2, SomeStruct { val: 1, other: 32 }) }"#, | 540 | r#"fn main() { println!("{} {:?}", 2+2, SomeStruct { val: 1, other: 32 }) }"#, |
518 | ); | 541 | ); |
519 | check_edit( | 542 | check_edit( |
520 | "loge", | 543 | "loge", |
521 | r#"fn main() { "{2+2}".<|> }"#, | 544 | r#"fn main() { "{2+2}".$0 }"#, |
522 | r#"fn main() { log::error!("{}", 2+2) }"#, | 545 | r#"fn main() { log::error!("{}", 2+2) }"#, |
523 | ); | 546 | ); |
524 | check_edit( | 547 | check_edit( |
525 | "logt", | 548 | "logt", |
526 | r#"fn main() { "{2+2}".<|> }"#, | 549 | r#"fn main() { "{2+2}".$0 }"#, |
527 | r#"fn main() { log::trace!("{}", 2+2) }"#, | 550 | r#"fn main() { log::trace!("{}", 2+2) }"#, |
528 | ); | 551 | ); |
529 | check_edit( | 552 | check_edit( |
530 | "logd", | 553 | "logd", |
531 | r#"fn main() { "{2+2}".<|> }"#, | 554 | r#"fn main() { "{2+2}".$0 }"#, |
532 | r#"fn main() { log::debug!("{}", 2+2) }"#, | 555 | r#"fn main() { log::debug!("{}", 2+2) }"#, |
533 | ); | 556 | ); |
534 | check_edit( | 557 | check_edit("logi", r#"fn main() { "{2+2}".$0 }"#, r#"fn main() { log::info!("{}", 2+2) }"#); |
535 | "logi", | 558 | check_edit("logw", r#"fn main() { "{2+2}".$0 }"#, r#"fn main() { log::warn!("{}", 2+2) }"#); |
536 | r#"fn main() { "{2+2}".<|> }"#, | ||
537 | r#"fn main() { log::info!("{}", 2+2) }"#, | ||
538 | ); | ||
539 | check_edit( | ||
540 | "logw", | ||
541 | r#"fn main() { "{2+2}".<|> }"#, | ||
542 | r#"fn main() { log::warn!("{}", 2+2) }"#, | ||
543 | ); | ||
544 | check_edit( | 559 | check_edit( |
545 | "loge", | 560 | "loge", |
546 | r#"fn main() { "{2+2}".<|> }"#, | 561 | r#"fn main() { "{2+2}".$0 }"#, |
547 | r#"fn main() { log::error!("{}", 2+2) }"#, | 562 | r#"fn main() { log::error!("{}", 2+2) }"#, |
548 | ); | 563 | ); |
549 | } | 564 | } |
diff --git a/crates/completion/src/completions/postfix/format_like.rs b/crates/completion/src/completions/postfix/format_like.rs index def4b13fb..3afc63021 100644 --- a/crates/completion/src/completions/postfix/format_like.rs +++ b/crates/completion/src/completions/postfix/format_like.rs | |||
@@ -14,12 +14,11 @@ | |||
14 | // + `logw` -> `log::warn!(...)` | 14 | // + `logw` -> `log::warn!(...)` |
15 | // + `loge` -> `log::error!(...)` | 15 | // + `loge` -> `log::error!(...)` |
16 | 16 | ||
17 | use crate::{ | 17 | use ide_db::helpers::SnippetCap; |
18 | completions::postfix::postfix_snippet, config::SnippetCap, context::CompletionContext, | ||
19 | Completions, | ||
20 | }; | ||
21 | use syntax::ast::{self, AstToken}; | 18 | use syntax::ast::{self, AstToken}; |
22 | 19 | ||
20 | use crate::{completions::postfix::postfix_snippet, context::CompletionContext, Completions}; | ||
21 | |||
23 | /// Mapping ("postfix completion item" => "macro to use") | 22 | /// Mapping ("postfix completion item" => "macro to use") |
24 | static KINDS: &[(&str, &str)] = &[ | 23 | static KINDS: &[(&str, &str)] = &[ |
25 | ("format", "format!"), | 24 | ("format", "format!"), |
diff --git a/crates/completion/src/completions/qualified_path.rs b/crates/completion/src/completions/qualified_path.rs index 882c4dcbc..fa9e6e810 100644 --- a/crates/completion/src/completions/qualified_path.rs +++ b/crates/completion/src/completions/qualified_path.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! Completion of paths, i.e. `some::prefix::<|>`. | 1 | //! Completion of paths, i.e. `some::prefix::$0`. |
2 | 2 | ||
3 | use hir::{Adt, HasVisibility, PathResolution, ScopeDef}; | 3 | use hir::{Adt, HasVisibility, PathResolution, ScopeDef}; |
4 | use rustc_hash::FxHashSet; | 4 | use rustc_hash::FxHashSet; |
@@ -38,7 +38,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
38 | if let ScopeDef::Unknown = def { | 38 | if let ScopeDef::Unknown = def { |
39 | if let Some(name_ref) = ctx.name_ref_syntax.as_ref() { | 39 | if let Some(name_ref) = ctx.name_ref_syntax.as_ref() { |
40 | if name_ref.syntax().text() == name.to_string().as_str() { | 40 | if name_ref.syntax().text() == name.to_string().as_str() { |
41 | // for `use self::foo<|>`, don't suggest `foo` as a completion | 41 | // for `use self::foo$0`, don't suggest `foo` as a completion |
42 | mark::hit!(dont_complete_current_use); | 42 | mark::hit!(dont_complete_current_use); |
43 | continue; | 43 | continue; |
44 | } | 44 | } |
@@ -173,7 +173,7 @@ mod tests { | |||
173 | #[test] | 173 | #[test] |
174 | fn dont_complete_current_use() { | 174 | fn dont_complete_current_use() { |
175 | mark::check!(dont_complete_current_use); | 175 | mark::check!(dont_complete_current_use); |
176 | check(r#"use self::foo<|>;"#, expect![[""]]); | 176 | check(r#"use self::foo$0;"#, expect![[""]]); |
177 | } | 177 | } |
178 | 178 | ||
179 | #[test] | 179 | #[test] |
@@ -181,7 +181,7 @@ mod tests { | |||
181 | check( | 181 | check( |
182 | r#" | 182 | r#" |
183 | mod foo { pub struct S; } | 183 | mod foo { pub struct S; } |
184 | use self::{foo::*, bar<|>}; | 184 | use self::{foo::*, bar$0}; |
185 | "#, | 185 | "#, |
186 | expect![[r#" | 186 | expect![[r#" |
187 | st S | 187 | st S |
@@ -192,18 +192,18 @@ use self::{foo::*, bar<|>}; | |||
192 | 192 | ||
193 | #[test] | 193 | #[test] |
194 | fn dont_complete_primitive_in_use() { | 194 | fn dont_complete_primitive_in_use() { |
195 | check_builtin(r#"use self::<|>;"#, expect![[""]]); | 195 | check_builtin(r#"use self::$0;"#, expect![[""]]); |
196 | } | 196 | } |
197 | 197 | ||
198 | #[test] | 198 | #[test] |
199 | fn dont_complete_primitive_in_module_scope() { | 199 | fn dont_complete_primitive_in_module_scope() { |
200 | check_builtin(r#"fn foo() { self::<|> }"#, expect![[""]]); | 200 | check_builtin(r#"fn foo() { self::$0 }"#, expect![[""]]); |
201 | } | 201 | } |
202 | 202 | ||
203 | #[test] | 203 | #[test] |
204 | fn completes_primitives() { | 204 | fn completes_primitives() { |
205 | check_builtin( | 205 | check_builtin( |
206 | r#"fn main() { let _: <|> = 92; }"#, | 206 | r#"fn main() { let _: $0 = 92; }"#, |
207 | expect![[r#" | 207 | expect![[r#" |
208 | bt u32 | 208 | bt u32 |
209 | bt bool | 209 | bt bool |
@@ -230,7 +230,7 @@ use self::{foo::*, bar<|>}; | |||
230 | fn completes_mod_with_same_name_as_function() { | 230 | fn completes_mod_with_same_name_as_function() { |
231 | check( | 231 | check( |
232 | r#" | 232 | r#" |
233 | use self::my::<|>; | 233 | use self::my::$0; |
234 | 234 | ||
235 | mod my { pub struct Bar; } | 235 | mod my { pub struct Bar; } |
236 | fn my() {} | 236 | fn my() {} |
@@ -245,7 +245,7 @@ fn my() {} | |||
245 | fn filters_visibility() { | 245 | fn filters_visibility() { |
246 | check( | 246 | check( |
247 | r#" | 247 | r#" |
248 | use self::my::<|>; | 248 | use self::my::$0; |
249 | 249 | ||
250 | mod my { | 250 | mod my { |
251 | struct Bar; | 251 | struct Bar; |
@@ -264,7 +264,7 @@ mod my { | |||
264 | fn completes_use_item_starting_with_self() { | 264 | fn completes_use_item_starting_with_self() { |
265 | check( | 265 | check( |
266 | r#" | 266 | r#" |
267 | use self::m::<|>; | 267 | use self::m::$0; |
268 | 268 | ||
269 | mod m { pub struct Bar; } | 269 | mod m { pub struct Bar; } |
270 | "#, | 270 | "#, |
@@ -282,7 +282,7 @@ mod m { pub struct Bar; } | |||
282 | mod foo; | 282 | mod foo; |
283 | struct Spam; | 283 | struct Spam; |
284 | //- /foo.rs | 284 | //- /foo.rs |
285 | use crate::Sp<|> | 285 | use crate::Sp$0 |
286 | "#, | 286 | "#, |
287 | expect![[r#" | 287 | expect![[r#" |
288 | md foo | 288 | md foo |
@@ -299,7 +299,7 @@ use crate::Sp<|> | |||
299 | mod foo; | 299 | mod foo; |
300 | struct Spam; | 300 | struct Spam; |
301 | //- /foo.rs | 301 | //- /foo.rs |
302 | use crate::{Sp<|>}; | 302 | use crate::{Sp$0}; |
303 | "#, | 303 | "#, |
304 | expect![[r#" | 304 | expect![[r#" |
305 | md foo | 305 | md foo |
@@ -320,7 +320,7 @@ pub mod bar { | |||
320 | } | 320 | } |
321 | } | 321 | } |
322 | //- /foo.rs | 322 | //- /foo.rs |
323 | use crate::{bar::{baz::Sp<|>}}; | 323 | use crate::{bar::{baz::Sp$0}}; |
324 | "#, | 324 | "#, |
325 | expect![[r#" | 325 | expect![[r#" |
326 | st Spam | 326 | st Spam |
@@ -333,7 +333,7 @@ use crate::{bar::{baz::Sp<|>}}; | |||
333 | check( | 333 | check( |
334 | r#" | 334 | r#" |
335 | enum E { Foo, Bar(i32) } | 335 | enum E { Foo, Bar(i32) } |
336 | fn foo() { let _ = E::<|> } | 336 | fn foo() { let _ = E::$0 } |
337 | "#, | 337 | "#, |
338 | expect![[r#" | 338 | expect![[r#" |
339 | ev Foo () | 339 | ev Foo () |
@@ -356,7 +356,7 @@ impl S { | |||
356 | type T = i32; | 356 | type T = i32; |
357 | } | 357 | } |
358 | 358 | ||
359 | fn foo() { let _ = S::<|> } | 359 | fn foo() { let _ = S::$0 } |
360 | "#, | 360 | "#, |
361 | expect![[r#" | 361 | expect![[r#" |
362 | fn a() fn a() | 362 | fn a() fn a() |
@@ -384,7 +384,7 @@ mod m { | |||
384 | } | 384 | } |
385 | } | 385 | } |
386 | 386 | ||
387 | fn foo() { let _ = S::<|> } | 387 | fn foo() { let _ = S::$0 } |
388 | "#, | 388 | "#, |
389 | expect![[r#" | 389 | expect![[r#" |
390 | fn public_method() pub(crate) fn public_method() | 390 | fn public_method() pub(crate) fn public_method() |
@@ -401,7 +401,7 @@ fn foo() { let _ = S::<|> } | |||
401 | enum E {}; | 401 | enum E {}; |
402 | impl E { fn m() { } } | 402 | impl E { fn m() { } } |
403 | 403 | ||
404 | fn foo() { let _ = E::<|> } | 404 | fn foo() { let _ = E::$0 } |
405 | "#, | 405 | "#, |
406 | expect![[r#" | 406 | expect![[r#" |
407 | fn m() fn m() | 407 | fn m() fn m() |
@@ -416,7 +416,7 @@ fn foo() { let _ = E::<|> } | |||
416 | union U {}; | 416 | union U {}; |
417 | impl U { fn m() { } } | 417 | impl U { fn m() { } } |
418 | 418 | ||
419 | fn foo() { let _ = U::<|> } | 419 | fn foo() { let _ = U::$0 } |
420 | "#, | 420 | "#, |
421 | expect![[r#" | 421 | expect![[r#" |
422 | fn m() fn m() | 422 | fn m() fn m() |
@@ -429,7 +429,7 @@ fn foo() { let _ = U::<|> } | |||
429 | check( | 429 | check( |
430 | r#" | 430 | r#" |
431 | //- /main.rs crate:main deps:foo | 431 | //- /main.rs crate:main deps:foo |
432 | use foo::<|>; | 432 | use foo::$0; |
433 | 433 | ||
434 | //- /foo/lib.rs crate:foo | 434 | //- /foo/lib.rs crate:foo |
435 | pub mod bar { pub struct S; } | 435 | pub mod bar { pub struct S; } |
@@ -446,7 +446,7 @@ pub mod bar { pub struct S; } | |||
446 | r#" | 446 | r#" |
447 | trait Trait { fn m(); } | 447 | trait Trait { fn m(); } |
448 | 448 | ||
449 | fn foo() { let _ = Trait::<|> } | 449 | fn foo() { let _ = Trait::$0 } |
450 | "#, | 450 | "#, |
451 | expect![[r#" | 451 | expect![[r#" |
452 | fn m() fn m() | 452 | fn m() fn m() |
@@ -463,7 +463,7 @@ trait Trait { fn m(); } | |||
463 | struct S; | 463 | struct S; |
464 | impl Trait for S {} | 464 | impl Trait for S {} |
465 | 465 | ||
466 | fn foo() { let _ = S::<|> } | 466 | fn foo() { let _ = S::$0 } |
467 | "#, | 467 | "#, |
468 | expect![[r#" | 468 | expect![[r#" |
469 | fn m() fn m() | 469 | fn m() fn m() |
@@ -480,7 +480,7 @@ trait Trait { fn m(); } | |||
480 | struct S; | 480 | struct S; |
481 | impl Trait for S {} | 481 | impl Trait for S {} |
482 | 482 | ||
483 | fn foo() { let _ = <S as Trait>::<|> } | 483 | fn foo() { let _ = <S as Trait>::$0 } |
484 | "#, | 484 | "#, |
485 | expect![[r#" | 485 | expect![[r#" |
486 | fn m() fn m() | 486 | fn m() fn m() |
@@ -506,7 +506,7 @@ trait Sub: Super { | |||
506 | fn submethod(&self) {} | 506 | fn submethod(&self) {} |
507 | } | 507 | } |
508 | 508 | ||
509 | fn foo<T: Sub>() { T::<|> } | 509 | fn foo<T: Sub>() { T::$0 } |
510 | "#, | 510 | "#, |
511 | expect![[r#" | 511 | expect![[r#" |
512 | ta SubTy type SubTy; | 512 | ta SubTy type SubTy; |
@@ -544,7 +544,7 @@ impl<T> Super for Wrap<T> {} | |||
544 | impl<T> Sub for Wrap<T> { | 544 | impl<T> Sub for Wrap<T> { |
545 | fn subfunc() { | 545 | fn subfunc() { |
546 | // Should be able to assume `Self: Sub + Super` | 546 | // Should be able to assume `Self: Sub + Super` |
547 | Self::<|> | 547 | Self::$0 |
548 | } | 548 | } |
549 | } | 549 | } |
550 | "#, | 550 | "#, |
@@ -570,7 +570,7 @@ impl S { fn foo() {} } | |||
570 | type T = S; | 570 | type T = S; |
571 | impl T { fn bar() {} } | 571 | impl T { fn bar() {} } |
572 | 572 | ||
573 | fn main() { T::<|>; } | 573 | fn main() { T::$0; } |
574 | "#, | 574 | "#, |
575 | expect![[r#" | 575 | expect![[r#" |
576 | fn foo() fn foo() | 576 | fn foo() fn foo() |
@@ -586,7 +586,7 @@ fn main() { T::<|>; } | |||
586 | #[macro_export] | 586 | #[macro_export] |
587 | macro_rules! foo { () => {} } | 587 | macro_rules! foo { () => {} } |
588 | 588 | ||
589 | fn main() { let _ = crate::<|> } | 589 | fn main() { let _ = crate::$0 } |
590 | "#, | 590 | "#, |
591 | expect![[r##" | 591 | expect![[r##" |
592 | fn main() fn main() | 592 | fn main() fn main() |
@@ -604,7 +604,7 @@ mod a { | |||
604 | const A: usize = 0; | 604 | const A: usize = 0; |
605 | mod b { | 605 | mod b { |
606 | const B: usize = 0; | 606 | const B: usize = 0; |
607 | mod c { use super::super::<|> } | 607 | mod c { use super::super::$0 } |
608 | } | 608 | } |
609 | } | 609 | } |
610 | "#, | 610 | "#, |
@@ -619,7 +619,7 @@ mod a { | |||
619 | fn completes_reexported_items_under_correct_name() { | 619 | fn completes_reexported_items_under_correct_name() { |
620 | check( | 620 | check( |
621 | r#" | 621 | r#" |
622 | fn foo() { self::m::<|> } | 622 | fn foo() { self::m::$0 } |
623 | 623 | ||
624 | mod m { | 624 | mod m { |
625 | pub use super::p::wrong_fn as right_fn; | 625 | pub use super::p::wrong_fn as right_fn; |
@@ -642,7 +642,7 @@ mod p { | |||
642 | check_edit( | 642 | check_edit( |
643 | "RightType", | 643 | "RightType", |
644 | r#" | 644 | r#" |
645 | fn foo() { self::m::<|> } | 645 | fn foo() { self::m::$0 } |
646 | 646 | ||
647 | mod m { | 647 | mod m { |
648 | pub use super::p::wrong_fn as right_fn; | 648 | pub use super::p::wrong_fn as right_fn; |
@@ -677,7 +677,7 @@ mod p { | |||
677 | check( | 677 | check( |
678 | r#" | 678 | r#" |
679 | macro_rules! m { ($e:expr) => { $e } } | 679 | macro_rules! m { ($e:expr) => { $e } } |
680 | fn main() { m!(self::f<|>); } | 680 | fn main() { m!(self::f$0); } |
681 | fn foo() {} | 681 | fn foo() {} |
682 | "#, | 682 | "#, |
683 | expect![[r#" | 683 | expect![[r#" |
@@ -691,7 +691,7 @@ fn foo() {} | |||
691 | fn function_mod_share_name() { | 691 | fn function_mod_share_name() { |
692 | check( | 692 | check( |
693 | r#" | 693 | r#" |
694 | fn foo() { self::m::<|> } | 694 | fn foo() { self::m::$0 } |
695 | 695 | ||
696 | mod m { | 696 | mod m { |
697 | pub mod z {} | 697 | pub mod z {} |
@@ -716,7 +716,7 @@ impl<K, V> HashMap<K, V, RandomState> { | |||
716 | pub fn new() -> HashMap<K, V, RandomState> { } | 716 | pub fn new() -> HashMap<K, V, RandomState> { } |
717 | } | 717 | } |
718 | fn foo() { | 718 | fn foo() { |
719 | HashMap::<|> | 719 | HashMap::$0 |
720 | } | 720 | } |
721 | "#, | 721 | "#, |
722 | expect![[r#" | 722 | expect![[r#" |
@@ -730,7 +730,7 @@ fn foo() { | |||
730 | check( | 730 | check( |
731 | r#" | 731 | r#" |
732 | mod foo { pub struct Foo; } | 732 | mod foo { pub struct Foo; } |
733 | #[foo::<|>] | 733 | #[foo::$0] |
734 | fn f() {} | 734 | fn f() {} |
735 | "#, | 735 | "#, |
736 | expect![[""]], | 736 | expect![[""]], |
@@ -749,7 +749,7 @@ fn foo( | |||
749 | } | 749 | } |
750 | 750 | ||
751 | fn main() { | 751 | fn main() { |
752 | fo<|> | 752 | fo$0 |
753 | } | 753 | } |
754 | "#, | 754 | "#, |
755 | expect![[r#" | 755 | expect![[r#" |
@@ -770,7 +770,7 @@ enum Foo { | |||
770 | 770 | ||
771 | impl Foo { | 771 | impl Foo { |
772 | fn foo(self) { | 772 | fn foo(self) { |
773 | Self::<|> | 773 | Self::$0 |
774 | } | 774 | } |
775 | } | 775 | } |
776 | "#, | 776 | "#, |
diff --git a/crates/completion/src/completions/record.rs b/crates/completion/src/completions/record.rs index e58b9a274..bb6354ded 100644 --- a/crates/completion/src/completions/record.rs +++ b/crates/completion/src/completions/record.rs | |||
@@ -99,7 +99,7 @@ impl core::default::Default for S { | |||
99 | fn process(f: S) { | 99 | fn process(f: S) { |
100 | let other = S { | 100 | let other = S { |
101 | foo: 5, | 101 | foo: 5, |
102 | .<|> | 102 | .$0 |
103 | }; | 103 | }; |
104 | } | 104 | } |
105 | "#; | 105 | "#; |
@@ -139,7 +139,7 @@ impl core::default::Default for S { | |||
139 | fn process(f: S) { | 139 | fn process(f: S) { |
140 | let other = S { | 140 | let other = S { |
141 | foo: 5, | 141 | foo: 5, |
142 | .<|> | 142 | .$0 |
143 | }; | 143 | }; |
144 | } | 144 | } |
145 | "#, | 145 | "#, |
@@ -173,7 +173,7 @@ struct S { foo: u32, bar: usize } | |||
173 | fn process(f: S) { | 173 | fn process(f: S) { |
174 | let other = S { | 174 | let other = S { |
175 | foo: 5, | 175 | foo: 5, |
176 | .<|> | 176 | .$0 |
177 | }; | 177 | }; |
178 | } | 178 | } |
179 | "#; | 179 | "#; |
@@ -201,7 +201,7 @@ struct S { foo: u32 } | |||
201 | 201 | ||
202 | fn process(f: S) { | 202 | fn process(f: S) { |
203 | match f { | 203 | match f { |
204 | S { f<|>: 92 } => (), | 204 | S { f$0: 92 } => (), |
205 | } | 205 | } |
206 | } | 206 | } |
207 | "#, | 207 | "#, |
@@ -219,7 +219,7 @@ enum E { S { foo: u32, bar: () } } | |||
219 | 219 | ||
220 | fn process(e: E) { | 220 | fn process(e: E) { |
221 | match e { | 221 | match e { |
222 | E::S { <|> } => (), | 222 | E::S { $0 } => (), |
223 | } | 223 | } |
224 | } | 224 | } |
225 | "#, | 225 | "#, |
@@ -239,7 +239,7 @@ struct S { foo: u32 } | |||
239 | 239 | ||
240 | fn process(f: S) { | 240 | fn process(f: S) { |
241 | m!(match f { | 241 | m!(match f { |
242 | S { f<|>: 92 } => (), | 242 | S { f$0: 92 } => (), |
243 | }) | 243 | }) |
244 | } | 244 | } |
245 | ", | 245 | ", |
@@ -263,7 +263,7 @@ fn main() { | |||
263 | foo1: 1, foo2: 2, | 263 | foo1: 1, foo2: 2, |
264 | bar: 3, baz: 4, | 264 | bar: 3, baz: 4, |
265 | }; | 265 | }; |
266 | if let S { foo1, foo2: a, <|> } = s {} | 266 | if let S { foo1, foo2: a, $0 } = s {} |
267 | } | 267 | } |
268 | "#, | 268 | "#, |
269 | expect![[r#" | 269 | expect![[r#" |
@@ -279,7 +279,7 @@ fn main() { | |||
279 | r#" | 279 | r#" |
280 | struct A { the_field: u32 } | 280 | struct A { the_field: u32 } |
281 | fn foo() { | 281 | fn foo() { |
282 | A { the<|> } | 282 | A { the$0 } |
283 | } | 283 | } |
284 | "#, | 284 | "#, |
285 | expect![[r#" | 285 | expect![[r#" |
@@ -294,7 +294,7 @@ fn foo() { | |||
294 | r#" | 294 | r#" |
295 | enum E { A { a: u32 } } | 295 | enum E { A { a: u32 } } |
296 | fn foo() { | 296 | fn foo() { |
297 | let _ = E::A { <|> } | 297 | let _ = E::A { $0 } |
298 | } | 298 | } |
299 | "#, | 299 | "#, |
300 | expect![[r#" | 300 | expect![[r#" |
@@ -311,7 +311,7 @@ struct A { a: u32 } | |||
311 | struct B { b: u32 } | 311 | struct B { b: u32 } |
312 | 312 | ||
313 | fn foo() { | 313 | fn foo() { |
314 | let _: A = B { <|> } | 314 | let _: A = B { $0 } |
315 | } | 315 | } |
316 | "#, | 316 | "#, |
317 | expect![[r#" | 317 | expect![[r#" |
@@ -327,7 +327,7 @@ fn foo() { | |||
327 | struct A<T> { a: T } | 327 | struct A<T> { a: T } |
328 | 328 | ||
329 | fn foo() { | 329 | fn foo() { |
330 | let _: A<u32> = A { <|> } | 330 | let _: A<u32> = A { $0 } |
331 | } | 331 | } |
332 | "#, | 332 | "#, |
333 | expect![[r#" | 333 | expect![[r#" |
@@ -343,7 +343,7 @@ fn foo() { | |||
343 | macro_rules! m { ($e:expr) => { $e } } | 343 | macro_rules! m { ($e:expr) => { $e } } |
344 | struct A { the_field: u32 } | 344 | struct A { the_field: u32 } |
345 | fn foo() { | 345 | fn foo() { |
346 | m!(A { the<|> }) | 346 | m!(A { the$0 }) |
347 | } | 347 | } |
348 | "#, | 348 | "#, |
349 | expect![[r#" | 349 | expect![[r#" |
@@ -363,7 +363,7 @@ struct S { | |||
363 | 363 | ||
364 | fn main() { | 364 | fn main() { |
365 | let foo1 = 1; | 365 | let foo1 = 1; |
366 | let s = S { foo1, foo2: 5, <|> } | 366 | let s = S { foo1, foo2: 5, $0 } |
367 | } | 367 | } |
368 | "#, | 368 | "#, |
369 | expect![[r#" | 369 | expect![[r#" |
@@ -381,7 +381,7 @@ struct S { foo1: u32, foo2: u32 } | |||
381 | 381 | ||
382 | fn main() { | 382 | fn main() { |
383 | let foo1 = 1; | 383 | let foo1 = 1; |
384 | let s = S { foo1, <|> .. loop {} } | 384 | let s = S { foo1, $0 .. loop {} } |
385 | } | 385 | } |
386 | "#, | 386 | "#, |
387 | expect![[r#" | 387 | expect![[r#" |
diff --git a/crates/completion/src/completions/snippet.rs b/crates/completion/src/completions/snippet.rs index 842590130..df17a15c5 100644 --- a/crates/completion/src/completions/snippet.rs +++ b/crates/completion/src/completions/snippet.rs | |||
@@ -1,8 +1,10 @@ | |||
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; | ||
4 | |||
3 | use crate::{ | 5 | use crate::{ |
4 | config::SnippetCap, item::Builder, CompletionContext, CompletionItem, CompletionItemKind, | 6 | item::Builder, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, |
5 | CompletionKind, Completions, | 7 | Completions, |
6 | }; | 8 | }; |
7 | 9 | ||
8 | fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str) -> Builder { | 10 | fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str) -> Builder { |
@@ -81,7 +83,7 @@ mod tests { | |||
81 | #[test] | 83 | #[test] |
82 | fn completes_snippets_in_expressions() { | 84 | fn completes_snippets_in_expressions() { |
83 | check( | 85 | check( |
84 | r#"fn foo(x: i32) { <|> }"#, | 86 | r#"fn foo(x: i32) { $0 }"#, |
85 | expect![[r#" | 87 | expect![[r#" |
86 | sn pd | 88 | sn pd |
87 | sn ppd | 89 | sn ppd |
@@ -91,8 +93,8 @@ mod tests { | |||
91 | 93 | ||
92 | #[test] | 94 | #[test] |
93 | fn should_not_complete_snippets_in_path() { | 95 | fn should_not_complete_snippets_in_path() { |
94 | check(r#"fn foo(x: i32) { ::foo<|> }"#, expect![[""]]); | 96 | check(r#"fn foo(x: i32) { ::foo$0 }"#, expect![[""]]); |
95 | check(r#"fn foo(x: i32) { ::<|> }"#, expect![[""]]); | 97 | check(r#"fn foo(x: i32) { ::$0 }"#, expect![[""]]); |
96 | } | 98 | } |
97 | 99 | ||
98 | #[test] | 100 | #[test] |
@@ -101,7 +103,7 @@ mod tests { | |||
101 | r#" | 103 | r#" |
102 | #[cfg(test)] | 104 | #[cfg(test)] |
103 | mod tests { | 105 | mod tests { |
104 | <|> | 106 | $0 |
105 | } | 107 | } |
106 | "#, | 108 | "#, |
107 | expect![[r#" | 109 | expect![[r#" |
diff --git a/crates/completion/src/completions/trait_impl.rs b/crates/completion/src/completions/trait_impl.rs index 54bb897e9..135ae49dc 100644 --- a/crates/completion/src/completions/trait_impl.rs +++ b/crates/completion/src/completions/trait_impl.rs | |||
@@ -15,7 +15,7 @@ | |||
15 | //! } | 15 | //! } |
16 | //! | 16 | //! |
17 | //! impl SomeTrait for () { | 17 | //! impl SomeTrait for () { |
18 | //! fn f<|> | 18 | //! fn f$0 |
19 | //! } | 19 | //! } |
20 | //! ``` | 20 | //! ``` |
21 | //! | 21 | //! |
@@ -27,7 +27,7 @@ | |||
27 | //! # } | 27 | //! # } |
28 | //! | 28 | //! |
29 | //! impl SomeTrait for () { | 29 | //! impl SomeTrait for () { |
30 | //! fn foo() {}<|> | 30 | //! fn foo() {}$0 |
31 | //! } | 31 | //! } |
32 | //! ``` | 32 | //! ``` |
33 | 33 | ||
@@ -82,7 +82,7 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext | |||
82 | 82 | ||
83 | fn completion_match(ctx: &CompletionContext) -> Option<(ImplCompletionKind, SyntaxNode, Impl)> { | 83 | fn completion_match(ctx: &CompletionContext) -> Option<(ImplCompletionKind, SyntaxNode, Impl)> { |
84 | let mut token = ctx.token.clone(); | 84 | let mut token = ctx.token.clone(); |
85 | // For keywork without name like `impl .. { fn <|> }`, the current position is inside | 85 | // For keywork without name like `impl .. { fn $0 }`, the current position is inside |
86 | // the whitespace token, which is outside `FN` syntax node. | 86 | // the whitespace token, which is outside `FN` syntax node. |
87 | // We need to follow the previous token in this case. | 87 | // We need to follow the previous token in this case. |
88 | if token.kind() == SyntaxKind::WHITESPACE { | 88 | if token.kind() == SyntaxKind::WHITESPACE { |
@@ -90,20 +90,20 @@ fn completion_match(ctx: &CompletionContext) -> Option<(ImplCompletionKind, Synt | |||
90 | } | 90 | } |
91 | 91 | ||
92 | let impl_item_offset = match token.kind() { | 92 | let impl_item_offset = match token.kind() { |
93 | // `impl .. { const <|> }` | 93 | // `impl .. { const $0 }` |
94 | // ERROR 0 | 94 | // ERROR 0 |
95 | // CONST_KW <- * | 95 | // CONST_KW <- * |
96 | SyntaxKind::CONST_KW => 0, | 96 | T![const] => 0, |
97 | // `impl .. { fn/type <|> }` | 97 | // `impl .. { fn/type $0 }` |
98 | // FN/TYPE_ALIAS 0 | 98 | // FN/TYPE_ALIAS 0 |
99 | // FN_KW <- * | 99 | // FN_KW <- * |
100 | SyntaxKind::FN_KW | SyntaxKind::TYPE_KW => 0, | 100 | T![fn] | T![type] => 0, |
101 | // `impl .. { fn/type/const foo<|> }` | 101 | // `impl .. { fn/type/const foo$0 }` |
102 | // FN/TYPE_ALIAS/CONST 1 | 102 | // FN/TYPE_ALIAS/CONST 1 |
103 | // NAME 0 | 103 | // NAME 0 |
104 | // IDENT <- * | 104 | // IDENT <- * |
105 | SyntaxKind::IDENT if token.parent().kind() == SyntaxKind::NAME => 1, | 105 | SyntaxKind::IDENT if token.parent().kind() == SyntaxKind::NAME => 1, |
106 | // `impl .. { foo<|> }` | 106 | // `impl .. { foo$0 }` |
107 | // MACRO_CALL 3 | 107 | // MACRO_CALL 3 |
108 | // PATH 2 | 108 | // PATH 2 |
109 | // PATH_SEGMENT 1 | 109 | // PATH_SEGMENT 1 |
@@ -120,8 +120,8 @@ fn completion_match(ctx: &CompletionContext) -> Option<(ImplCompletionKind, Synt | |||
120 | // <item> | 120 | // <item> |
121 | let impl_def = ast::Impl::cast(impl_item.parent()?.parent()?)?; | 121 | let impl_def = ast::Impl::cast(impl_item.parent()?.parent()?)?; |
122 | let kind = match impl_item.kind() { | 122 | let kind = match impl_item.kind() { |
123 | // `impl ... { const <|> fn/type/const }` | 123 | // `impl ... { const $0 fn/type/const }` |
124 | _ if token.kind() == SyntaxKind::CONST_KW => ImplCompletionKind::Const, | 124 | _ if token.kind() == T![const] => ImplCompletionKind::Const, |
125 | SyntaxKind::CONST | SyntaxKind::ERROR => ImplCompletionKind::Const, | 125 | SyntaxKind::CONST | SyntaxKind::ERROR => ImplCompletionKind::Const, |
126 | SyntaxKind::TYPE_ALIAS => ImplCompletionKind::TypeAlias, | 126 | SyntaxKind::TYPE_ALIAS => ImplCompletionKind::TypeAlias, |
127 | SyntaxKind::FN => ImplCompletionKind::Fn, | 127 | SyntaxKind::FN => ImplCompletionKind::Fn, |
@@ -267,7 +267,7 @@ trait Test { | |||
267 | struct T; | 267 | struct T; |
268 | 268 | ||
269 | impl Test for T { | 269 | impl Test for T { |
270 | t<|> | 270 | t$0 |
271 | } | 271 | } |
272 | "#, | 272 | "#, |
273 | expect![[" | 273 | expect![[" |
@@ -287,7 +287,7 @@ struct T; | |||
287 | 287 | ||
288 | impl Test for T { | 288 | impl Test for T { |
289 | fn test() { | 289 | fn test() { |
290 | t<|> | 290 | t$0 |
291 | } | 291 | } |
292 | } | 292 | } |
293 | ", | 293 | ", |
@@ -301,7 +301,7 @@ struct T; | |||
301 | 301 | ||
302 | impl Test for T { | 302 | impl Test for T { |
303 | fn test() { | 303 | fn test() { |
304 | fn t<|> | 304 | fn t$0 |
305 | } | 305 | } |
306 | } | 306 | } |
307 | ", | 307 | ", |
@@ -315,7 +315,7 @@ struct T; | |||
315 | 315 | ||
316 | impl Test for T { | 316 | impl Test for T { |
317 | fn test() { | 317 | fn test() { |
318 | fn <|> | 318 | fn $0 |
319 | } | 319 | } |
320 | } | 320 | } |
321 | ", | 321 | ", |
@@ -330,7 +330,7 @@ struct T; | |||
330 | 330 | ||
331 | impl Test for T { | 331 | impl Test for T { |
332 | fn test() { | 332 | fn test() { |
333 | foo.<|> | 333 | foo.$0 |
334 | } | 334 | } |
335 | } | 335 | } |
336 | ", | 336 | ", |
@@ -343,7 +343,7 @@ trait Test { fn test(_: i32); fn test2(); } | |||
343 | struct T; | 343 | struct T; |
344 | 344 | ||
345 | impl Test for T { | 345 | impl Test for T { |
346 | fn test(t<|>) | 346 | fn test(t$0) |
347 | } | 347 | } |
348 | ", | 348 | ", |
349 | expect![[""]], | 349 | expect![[""]], |
@@ -355,7 +355,7 @@ trait Test { fn test(_: fn()); fn test2(); } | |||
355 | struct T; | 355 | struct T; |
356 | 356 | ||
357 | impl Test for T { | 357 | impl Test for T { |
358 | fn test(f: fn <|>) | 358 | fn test(f: fn $0) |
359 | } | 359 | } |
360 | ", | 360 | ", |
361 | expect![[""]], | 361 | expect![[""]], |
@@ -370,7 +370,7 @@ trait Test { const TEST: fn(); const TEST2: u32; type Test; fn test(); } | |||
370 | struct T; | 370 | struct T; |
371 | 371 | ||
372 | impl Test for T { | 372 | impl Test for T { |
373 | const TEST: fn <|> | 373 | const TEST: fn $0 |
374 | } | 374 | } |
375 | ", | 375 | ", |
376 | expect![[""]], | 376 | expect![[""]], |
@@ -382,7 +382,7 @@ trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); } | |||
382 | struct T; | 382 | struct T; |
383 | 383 | ||
384 | impl Test for T { | 384 | impl Test for T { |
385 | const TEST: T<|> | 385 | const TEST: T$0 |
386 | } | 386 | } |
387 | ", | 387 | ", |
388 | expect![[""]], | 388 | expect![[""]], |
@@ -394,7 +394,7 @@ trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); } | |||
394 | struct T; | 394 | struct T; |
395 | 395 | ||
396 | impl Test for T { | 396 | impl Test for T { |
397 | const TEST: u32 = f<|> | 397 | const TEST: u32 = f$0 |
398 | } | 398 | } |
399 | ", | 399 | ", |
400 | expect![[""]], | 400 | expect![[""]], |
@@ -407,7 +407,7 @@ struct T; | |||
407 | 407 | ||
408 | impl Test for T { | 408 | impl Test for T { |
409 | const TEST: u32 = { | 409 | const TEST: u32 = { |
410 | t<|> | 410 | t$0 |
411 | }; | 411 | }; |
412 | } | 412 | } |
413 | ", | 413 | ", |
@@ -421,7 +421,7 @@ struct T; | |||
421 | 421 | ||
422 | impl Test for T { | 422 | impl Test for T { |
423 | const TEST: u32 = { | 423 | const TEST: u32 = { |
424 | fn <|> | 424 | fn $0 |
425 | }; | 425 | }; |
426 | } | 426 | } |
427 | ", | 427 | ", |
@@ -435,7 +435,7 @@ struct T; | |||
435 | 435 | ||
436 | impl Test for T { | 436 | impl Test for T { |
437 | const TEST: u32 = { | 437 | const TEST: u32 = { |
438 | fn t<|> | 438 | fn t$0 |
439 | }; | 439 | }; |
440 | } | 440 | } |
441 | ", | 441 | ", |
@@ -451,7 +451,7 @@ trait Test { type Test; type Test2; fn test(); } | |||
451 | struct T; | 451 | struct T; |
452 | 452 | ||
453 | impl Test for T { | 453 | impl Test for T { |
454 | type Test = T<|>; | 454 | type Test = T$0; |
455 | } | 455 | } |
456 | ", | 456 | ", |
457 | expect![[""]], | 457 | expect![[""]], |
@@ -463,7 +463,7 @@ trait Test { type Test; type Test2; fn test(); } | |||
463 | struct T; | 463 | struct T; |
464 | 464 | ||
465 | impl Test for T { | 465 | impl Test for T { |
466 | type Test = fn <|>; | 466 | type Test = fn $0; |
467 | } | 467 | } |
468 | ", | 468 | ", |
469 | expect![[""]], | 469 | expect![[""]], |
@@ -481,7 +481,7 @@ trait Test { | |||
481 | struct T; | 481 | struct T; |
482 | 482 | ||
483 | impl Test for T { | 483 | impl Test for T { |
484 | t<|> | 484 | t$0 |
485 | } | 485 | } |
486 | "#, | 486 | "#, |
487 | r#" | 487 | r#" |
@@ -510,7 +510,7 @@ trait Test { | |||
510 | struct T; | 510 | struct T; |
511 | 511 | ||
512 | impl Test for T { | 512 | impl Test for T { |
513 | fn t<|> | 513 | fn t$0 |
514 | } | 514 | } |
515 | "#, | 515 | "#, |
516 | r#" | 516 | r#" |
@@ -540,7 +540,7 @@ struct T; | |||
540 | 540 | ||
541 | impl Test for T { | 541 | impl Test for T { |
542 | fn foo() {} | 542 | fn foo() {} |
543 | fn f<|> | 543 | fn f$0 |
544 | } | 544 | } |
545 | "#, | 545 | "#, |
546 | expect![[r#" | 546 | expect![[r#" |
@@ -560,7 +560,7 @@ trait Test { | |||
560 | struct T; | 560 | struct T; |
561 | 561 | ||
562 | impl Test for T { | 562 | impl Test for T { |
563 | fn f<|> | 563 | fn f$0 |
564 | } | 564 | } |
565 | "#, | 565 | "#, |
566 | r#" | 566 | r#" |
@@ -585,7 +585,7 @@ trait Test { | |||
585 | struct T; | 585 | struct T; |
586 | 586 | ||
587 | impl Test for T { | 587 | impl Test for T { |
588 | fn f<|> | 588 | fn f$0 |
589 | } | 589 | } |
590 | "#, | 590 | "#, |
591 | r#" | 591 | r#" |
@@ -614,7 +614,7 @@ trait Test { | |||
614 | } | 614 | } |
615 | 615 | ||
616 | impl Test for () { | 616 | impl Test for () { |
617 | type S<|> | 617 | type S$0 |
618 | } | 618 | } |
619 | "#, | 619 | "#, |
620 | " | 620 | " |
@@ -639,7 +639,7 @@ trait Test { | |||
639 | } | 639 | } |
640 | 640 | ||
641 | impl Test for () { | 641 | impl Test for () { |
642 | const S<|> | 642 | const S$0 |
643 | } | 643 | } |
644 | "#, | 644 | "#, |
645 | " | 645 | " |
@@ -661,7 +661,7 @@ trait Test { | |||
661 | } | 661 | } |
662 | 662 | ||
663 | impl Test for () { | 663 | impl Test for () { |
664 | const S<|> | 664 | const S$0 |
665 | } | 665 | } |
666 | "#, | 666 | "#, |
667 | " | 667 | " |
@@ -724,7 +724,7 @@ impl Test for T {{ | |||
724 | // Enumerate some possible next siblings. | 724 | // Enumerate some possible next siblings. |
725 | for next_sibling in &[ | 725 | for next_sibling in &[ |
726 | "", | 726 | "", |
727 | "fn other_fn() {}", // `const <|> fn` -> `const fn` | 727 | "fn other_fn() {}", // `const $0 fn` -> `const fn` |
728 | "type OtherType = i32;", | 728 | "type OtherType = i32;", |
729 | "const OTHER_CONST: i32 = 0;", | 729 | "const OTHER_CONST: i32 = 0;", |
730 | "async fn other_fn() {}", | 730 | "async fn other_fn() {}", |
@@ -733,9 +733,9 @@ impl Test for T {{ | |||
733 | "default type OtherType = i32;", | 733 | "default type OtherType = i32;", |
734 | "default const OTHER_CONST: i32 = 0;", | 734 | "default const OTHER_CONST: i32 = 0;", |
735 | ] { | 735 | ] { |
736 | test("bar", "fn <|>", "fn bar() {\n $0\n}", next_sibling); | 736 | test("bar", "fn $0", "fn bar() {\n $0\n}", next_sibling); |
737 | test("Foo", "type <|>", "type Foo = ", next_sibling); | 737 | test("Foo", "type $0", "type Foo = ", next_sibling); |
738 | test("CONST", "const <|>", "const CONST: u16 = ", next_sibling); | 738 | test("CONST", "const $0", "const CONST: u16 = ", next_sibling); |
739 | } | 739 | } |
740 | } | 740 | } |
741 | } | 741 | } |
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs index 2f41a3f96..12cdb869d 100644 --- a/crates/completion/src/completions/unqualified_path.rs +++ b/crates/completion/src/completions/unqualified_path.rs | |||
@@ -46,7 +46,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC | |||
46 | acc.add_resolution(ctx, name.to_string(), &res) | 46 | acc.add_resolution(ctx, name.to_string(), &res) |
47 | }); | 47 | }); |
48 | 48 | ||
49 | if ctx.config.enable_autoimport_completions && ctx.config.resolve_additional_edits_lazily() { | 49 | if ctx.config.enable_autoimport_completions { |
50 | fuzzy_completion(acc, ctx); | 50 | fuzzy_completion(acc, ctx); |
51 | } | 51 | } |
52 | } | 52 | } |
@@ -85,7 +85,7 @@ fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &T | |||
85 | // | 85 | // |
86 | // ``` | 86 | // ``` |
87 | // fn main() { | 87 | // fn main() { |
88 | // pda<|> | 88 | // pda$0 |
89 | // } | 89 | // } |
90 | // # pub mod std { pub mod marker { pub struct PhantomData { } } } | 90 | // # pub mod std { pub mod marker { pub struct PhantomData { } } } |
91 | // ``` | 91 | // ``` |
@@ -192,12 +192,14 @@ mod tests { | |||
192 | use test_utils::mark; | 192 | use test_utils::mark; |
193 | 193 | ||
194 | use crate::{ | 194 | use crate::{ |
195 | test_utils::{check_edit, check_edit_with_config, completion_list_with_config}, | 195 | test_utils::{ |
196 | check_edit, check_edit_with_config, completion_list_with_config, TEST_CONFIG, | ||
197 | }, | ||
196 | CompletionConfig, CompletionKind, | 198 | CompletionConfig, CompletionKind, |
197 | }; | 199 | }; |
198 | 200 | ||
199 | fn check(ra_fixture: &str, expect: Expect) { | 201 | fn check(ra_fixture: &str, expect: Expect) { |
200 | check_with_config(CompletionConfig::default(), ra_fixture, expect); | 202 | check_with_config(TEST_CONFIG, ra_fixture, expect); |
201 | } | 203 | } |
202 | 204 | ||
203 | fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) { | 205 | fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) { |
@@ -205,20 +207,12 @@ mod tests { | |||
205 | expect.assert_eq(&actual) | 207 | expect.assert_eq(&actual) |
206 | } | 208 | } |
207 | 209 | ||
208 | fn fuzzy_completion_config() -> CompletionConfig { | ||
209 | let mut completion_config = CompletionConfig::default(); | ||
210 | completion_config | ||
211 | .active_resolve_capabilities | ||
212 | .insert(crate::CompletionResolveCapability::AdditionalTextEdits); | ||
213 | completion_config | ||
214 | } | ||
215 | |||
216 | #[test] | 210 | #[test] |
217 | fn self_fulfilling_completion() { | 211 | fn self_fulfilling_completion() { |
218 | mark::check!(self_fulfilling_completion); | 212 | mark::check!(self_fulfilling_completion); |
219 | check( | 213 | check( |
220 | r#" | 214 | r#" |
221 | use foo<|> | 215 | use foo$0 |
222 | use std::collections; | 216 | use std::collections; |
223 | "#, | 217 | "#, |
224 | expect![[r#" | 218 | expect![[r#" |
@@ -235,7 +229,7 @@ enum Enum { A, B } | |||
235 | fn quux(x: Option<Enum>) { | 229 | fn quux(x: Option<Enum>) { |
236 | match x { | 230 | match x { |
237 | None => (), | 231 | None => (), |
238 | Some(en<|> @ Enum::A) => (), | 232 | Some(en$0 @ Enum::A) => (), |
239 | } | 233 | } |
240 | } | 234 | } |
241 | "#, | 235 | "#, |
@@ -251,7 +245,7 @@ enum Enum { A, B } | |||
251 | fn quux(x: Option<Enum>) { | 245 | fn quux(x: Option<Enum>) { |
252 | match x { | 246 | match x { |
253 | None => (), | 247 | None => (), |
254 | Some(ref en<|>) => (), | 248 | Some(ref en$0) => (), |
255 | } | 249 | } |
256 | } | 250 | } |
257 | "#, | 251 | "#, |
@@ -267,7 +261,7 @@ enum Enum { A, B } | |||
267 | fn quux(x: Option<Enum>) { | 261 | fn quux(x: Option<Enum>) { |
268 | match x { | 262 | match x { |
269 | None => (), | 263 | None => (), |
270 | Some(En<|>) => (), | 264 | Some(En$0) => (), |
271 | } | 265 | } |
272 | } | 266 | } |
273 | "#, | 267 | "#, |
@@ -283,7 +277,7 @@ fn quux(x: Option<Enum>) { | |||
283 | r#" | 277 | r#" |
284 | fn quux(x: i32) { | 278 | fn quux(x: i32) { |
285 | let y = 92; | 279 | let y = 92; |
286 | 1 + <|>; | 280 | 1 + $0; |
287 | let z = (); | 281 | let z = (); |
288 | } | 282 | } |
289 | "#, | 283 | "#, |
@@ -305,7 +299,7 @@ fn quux() { | |||
305 | }; | 299 | }; |
306 | if let Some(a) = bar() { | 300 | if let Some(a) = bar() { |
307 | let b = 62; | 301 | let b = 62; |
308 | 1 + <|> | 302 | 1 + $0 |
309 | } | 303 | } |
310 | } | 304 | } |
311 | "#, | 305 | "#, |
@@ -322,7 +316,7 @@ fn quux() { | |||
322 | check( | 316 | check( |
323 | r#" | 317 | r#" |
324 | fn quux() { | 318 | fn quux() { |
325 | for x in &[1, 2, 3] { <|> } | 319 | for x in &[1, 2, 3] { $0 } |
326 | } | 320 | } |
327 | "#, | 321 | "#, |
328 | expect![[r#" | 322 | expect![[r#" |
@@ -340,7 +334,7 @@ fn quux() { | |||
340 | r#" | 334 | r#" |
341 | fn main() { | 335 | fn main() { |
342 | let wherewolf = 92; | 336 | let wherewolf = 92; |
343 | drop(where<|>) | 337 | drop(where$0) |
344 | } | 338 | } |
345 | "#, | 339 | "#, |
346 | r#" | 340 | r#" |
@@ -355,7 +349,7 @@ fn main() { | |||
355 | #[test] | 349 | #[test] |
356 | fn completes_generic_params() { | 350 | fn completes_generic_params() { |
357 | check( | 351 | check( |
358 | r#"fn quux<T>() { <|> }"#, | 352 | r#"fn quux<T>() { $0 }"#, |
359 | expect![[r#" | 353 | expect![[r#" |
360 | tp T | 354 | tp T |
361 | fn quux() fn quux<T>() | 355 | fn quux() fn quux<T>() |
@@ -366,7 +360,7 @@ fn main() { | |||
366 | #[test] | 360 | #[test] |
367 | fn completes_generic_params_in_struct() { | 361 | fn completes_generic_params_in_struct() { |
368 | check( | 362 | check( |
369 | r#"struct S<T> { x: <|>}"#, | 363 | r#"struct S<T> { x: $0}"#, |
370 | expect![[r#" | 364 | expect![[r#" |
371 | tp Self | 365 | tp Self |
372 | tp T | 366 | tp T |
@@ -378,7 +372,7 @@ fn main() { | |||
378 | #[test] | 372 | #[test] |
379 | fn completes_self_in_enum() { | 373 | fn completes_self_in_enum() { |
380 | check( | 374 | check( |
381 | r#"enum X { Y(<|>) }"#, | 375 | r#"enum X { Y($0) }"#, |
382 | expect![[r#" | 376 | expect![[r#" |
383 | tp Self | 377 | tp Self |
384 | en X | 378 | en X |
@@ -392,7 +386,7 @@ fn main() { | |||
392 | r#" | 386 | r#" |
393 | struct S; | 387 | struct S; |
394 | enum E {} | 388 | enum E {} |
395 | fn quux() { <|> } | 389 | fn quux() { $0 } |
396 | "#, | 390 | "#, |
397 | expect![[r#" | 391 | expect![[r#" |
398 | st S | 392 | st S |
@@ -409,7 +403,7 @@ fn quux() { <|> } | |||
409 | "_alpha", | 403 | "_alpha", |
410 | r#" | 404 | r#" |
411 | fn main() { | 405 | fn main() { |
412 | _<|> | 406 | _$0 |
413 | } | 407 | } |
414 | fn _alpha() {} | 408 | fn _alpha() {} |
415 | "#, | 409 | "#, |
@@ -427,7 +421,7 @@ fn _alpha() {} | |||
427 | check( | 421 | check( |
428 | r#" | 422 | r#" |
429 | //- /lib.rs crate:main deps:other_crate | 423 | //- /lib.rs crate:main deps:other_crate |
430 | use <|>; | 424 | use $0; |
431 | 425 | ||
432 | //- /other_crate/lib.rs crate:other_crate | 426 | //- /other_crate/lib.rs crate:other_crate |
433 | // nothing here | 427 | // nothing here |
@@ -445,7 +439,7 @@ use <|>; | |||
445 | struct Foo; | 439 | struct Foo; |
446 | mod m { | 440 | mod m { |
447 | struct Bar; | 441 | struct Bar; |
448 | fn quux() { <|> } | 442 | fn quux() { $0 } |
449 | } | 443 | } |
450 | "#, | 444 | "#, |
451 | expect![[r#" | 445 | expect![[r#" |
@@ -460,7 +454,7 @@ mod m { | |||
460 | check( | 454 | check( |
461 | r#" | 455 | r#" |
462 | struct Foo; | 456 | struct Foo; |
463 | fn x() -> <|> | 457 | fn x() -> $0 |
464 | "#, | 458 | "#, |
465 | expect![[r#" | 459 | expect![[r#" |
466 | st Foo | 460 | st Foo |
@@ -477,7 +471,7 @@ fn foo() { | |||
477 | let bar = 92; | 471 | let bar = 92; |
478 | { | 472 | { |
479 | let bar = 62; | 473 | let bar = 62; |
480 | drop(<|>) | 474 | drop($0) |
481 | } | 475 | } |
482 | } | 476 | } |
483 | "#, | 477 | "#, |
@@ -493,7 +487,7 @@ fn foo() { | |||
493 | #[test] | 487 | #[test] |
494 | fn completes_self_in_methods() { | 488 | fn completes_self_in_methods() { |
495 | check( | 489 | check( |
496 | r#"impl S { fn foo(&self) { <|> } }"#, | 490 | r#"impl S { fn foo(&self) { $0 } }"#, |
497 | expect![[r#" | 491 | expect![[r#" |
498 | bn self &{unknown} | 492 | bn self &{unknown} |
499 | tp Self | 493 | tp Self |
@@ -506,7 +500,7 @@ fn foo() { | |||
506 | check( | 500 | check( |
507 | r#" | 501 | r#" |
508 | //- /main.rs crate:main deps:std | 502 | //- /main.rs crate:main deps:std |
509 | fn foo() { let x: <|> } | 503 | fn foo() { let x: $0 } |
510 | 504 | ||
511 | //- /std/lib.rs crate:std | 505 | //- /std/lib.rs crate:std |
512 | #[prelude_import] | 506 | #[prelude_import] |
@@ -527,7 +521,7 @@ mod prelude { struct Option; } | |||
527 | check( | 521 | check( |
528 | r#" | 522 | r#" |
529 | //- /main.rs crate:main deps:core,std | 523 | //- /main.rs crate:main deps:core,std |
530 | fn foo() { let x: <|> } | 524 | fn foo() { let x: $0 } |
531 | 525 | ||
532 | //- /core/lib.rs crate:core | 526 | //- /core/lib.rs crate:core |
533 | #[prelude_import] | 527 | #[prelude_import] |
@@ -568,7 +562,7 @@ mod m2 { | |||
568 | macro_rules! baz { () => {} } | 562 | macro_rules! baz { () => {} } |
569 | } | 563 | } |
570 | 564 | ||
571 | fn main() { let v = <|> } | 565 | fn main() { let v = $0 } |
572 | "#, | 566 | "#, |
573 | expect![[r##" | 567 | expect![[r##" |
574 | md m1 | 568 | md m1 |
@@ -587,7 +581,7 @@ fn main() { let v = <|> } | |||
587 | check( | 581 | check( |
588 | r#" | 582 | r#" |
589 | macro_rules! foo { () => {} } | 583 | macro_rules! foo { () => {} } |
590 | fn foo() { <|> } | 584 | fn foo() { $0 } |
591 | "#, | 585 | "#, |
592 | expect![[r#" | 586 | expect![[r#" |
593 | fn foo() fn foo() | 587 | fn foo() fn foo() |
@@ -601,7 +595,7 @@ fn foo() { <|> } | |||
601 | check( | 595 | check( |
602 | r#" | 596 | r#" |
603 | macro_rules! foo { () => {} } | 597 | macro_rules! foo { () => {} } |
604 | fn main() { let x: <|> } | 598 | fn main() { let x: $0 } |
605 | "#, | 599 | "#, |
606 | expect![[r#" | 600 | expect![[r#" |
607 | fn main() fn main() | 601 | fn main() fn main() |
@@ -615,7 +609,7 @@ fn main() { let x: <|> } | |||
615 | check( | 609 | check( |
616 | r#" | 610 | r#" |
617 | macro_rules! foo { () => {} } | 611 | macro_rules! foo { () => {} } |
618 | fn main() { <|> } | 612 | fn main() { $0 } |
619 | "#, | 613 | "#, |
620 | expect![[r#" | 614 | expect![[r#" |
621 | fn main() fn main() | 615 | fn main() fn main() |
@@ -629,7 +623,7 @@ fn main() { <|> } | |||
629 | check( | 623 | check( |
630 | r#" | 624 | r#" |
631 | fn main() { | 625 | fn main() { |
632 | return f<|>; | 626 | return f$0; |
633 | fn frobnicate() {} | 627 | fn frobnicate() {} |
634 | } | 628 | } |
635 | "#, | 629 | "#, |
@@ -647,7 +641,7 @@ fn main() { | |||
647 | macro_rules! m { ($e:expr) => { $e } } | 641 | macro_rules! m { ($e:expr) => { $e } } |
648 | fn quux(x: i32) { | 642 | fn quux(x: i32) { |
649 | let y = 92; | 643 | let y = 92; |
650 | m!(<|>); | 644 | m!($0); |
651 | } | 645 | } |
652 | "#, | 646 | "#, |
653 | expect![[r#" | 647 | expect![[r#" |
@@ -666,7 +660,7 @@ fn quux(x: i32) { | |||
666 | macro_rules! m { ($e:expr) => { $e } } | 660 | macro_rules! m { ($e:expr) => { $e } } |
667 | fn quux(x: i32) { | 661 | fn quux(x: i32) { |
668 | let y = 92; | 662 | let y = 92; |
669 | m!(x<|>); | 663 | m!(x$0); |
670 | } | 664 | } |
671 | ", | 665 | ", |
672 | expect![[r#" | 666 | expect![[r#" |
@@ -685,7 +679,7 @@ fn quux(x: i32) { | |||
685 | macro_rules! m { ($e:expr) => { $e } } | 679 | macro_rules! m { ($e:expr) => { $e } } |
686 | fn quux(x: i32) { | 680 | fn quux(x: i32) { |
687 | let y = 92; | 681 | let y = 92; |
688 | m!(x<|> | 682 | m!(x$0 |
689 | } | 683 | } |
690 | "#, | 684 | "#, |
691 | expect![[r#" | 685 | expect![[r#" |
@@ -703,7 +697,7 @@ fn quux(x: i32) { | |||
703 | r#" | 697 | r#" |
704 | use spam::Quux; | 698 | use spam::Quux; |
705 | 699 | ||
706 | fn main() { <|> } | 700 | fn main() { $0 } |
707 | "#, | 701 | "#, |
708 | expect![[r#" | 702 | expect![[r#" |
709 | fn main() fn main() | 703 | fn main() fn main() |
@@ -720,7 +714,7 @@ enum Foo { Bar, Baz, Quux } | |||
720 | 714 | ||
721 | fn main() { | 715 | fn main() { |
722 | let foo = Foo::Quux; | 716 | let foo = Foo::Quux; |
723 | match foo { Qu<|> } | 717 | match foo { Qu$0 } |
724 | } | 718 | } |
725 | "#, | 719 | "#, |
726 | expect![[r#" | 720 | expect![[r#" |
@@ -740,7 +734,7 @@ enum Foo { Bar, Baz, Quux } | |||
740 | 734 | ||
741 | fn main() { | 735 | fn main() { |
742 | let foo = Foo::Quux; | 736 | let foo = Foo::Quux; |
743 | match &foo { Qu<|> } | 737 | match &foo { Qu$0 } |
744 | } | 738 | } |
745 | "#, | 739 | "#, |
746 | expect![[r#" | 740 | expect![[r#" |
@@ -760,7 +754,7 @@ enum Foo { Bar, Baz, Quux } | |||
760 | 754 | ||
761 | fn main() { | 755 | fn main() { |
762 | let foo = Foo::Quux; | 756 | let foo = Foo::Quux; |
763 | if let Qu<|> = foo { } | 757 | if let Qu$0 = foo { } |
764 | } | 758 | } |
765 | "#, | 759 | "#, |
766 | expect![[r#" | 760 | expect![[r#" |
@@ -777,7 +771,7 @@ fn main() { | |||
777 | check( | 771 | check( |
778 | r#" | 772 | r#" |
779 | enum Foo { Bar, Baz, Quux } | 773 | enum Foo { Bar, Baz, Quux } |
780 | fn main() { let foo: Foo = Q<|> } | 774 | fn main() { let foo: Foo = Q$0 } |
781 | "#, | 775 | "#, |
782 | expect![[r#" | 776 | expect![[r#" |
783 | ev Foo::Bar () | 777 | ev Foo::Bar () |
@@ -794,7 +788,7 @@ fn main() { let foo: Foo = Q<|> } | |||
794 | check( | 788 | check( |
795 | r#" | 789 | r#" |
796 | mod m { pub enum E { V } } | 790 | mod m { pub enum E { V } } |
797 | fn f() -> m::E { V<|> } | 791 | fn f() -> m::E { V$0 } |
798 | "#, | 792 | "#, |
799 | expect![[r#" | 793 | expect![[r#" |
800 | ev m::E::V () | 794 | ev m::E::V () |
@@ -809,7 +803,7 @@ fn f() -> m::E { V<|> } | |||
809 | check( | 803 | check( |
810 | r#" | 804 | r#" |
811 | struct Foo; | 805 | struct Foo; |
812 | #[<|>] | 806 | #[$0] |
813 | fn f() {} | 807 | fn f() {} |
814 | "#, | 808 | "#, |
815 | expect![[""]], | 809 | expect![[""]], |
@@ -823,7 +817,7 @@ fn f() {} | |||
823 | trait MyTrait {} | 817 | trait MyTrait {} |
824 | struct MyStruct {} | 818 | struct MyStruct {} |
825 | 819 | ||
826 | impl My<|> | 820 | impl My$0 |
827 | "#, | 821 | "#, |
828 | expect![[r#" | 822 | expect![[r#" |
829 | tp Self | 823 | tp Self |
@@ -836,7 +830,7 @@ impl My<|> | |||
836 | #[test] | 830 | #[test] |
837 | fn function_fuzzy_completion() { | 831 | fn function_fuzzy_completion() { |
838 | check_edit_with_config( | 832 | check_edit_with_config( |
839 | fuzzy_completion_config(), | 833 | TEST_CONFIG, |
840 | "stdin", | 834 | "stdin", |
841 | r#" | 835 | r#" |
842 | //- /lib.rs crate:dep | 836 | //- /lib.rs crate:dep |
@@ -846,7 +840,7 @@ pub mod io { | |||
846 | 840 | ||
847 | //- /main.rs crate:main deps:dep | 841 | //- /main.rs crate:main deps:dep |
848 | fn main() { | 842 | fn main() { |
849 | stdi<|> | 843 | stdi$0 |
850 | } | 844 | } |
851 | "#, | 845 | "#, |
852 | r#" | 846 | r#" |
@@ -862,7 +856,7 @@ fn main() { | |||
862 | #[test] | 856 | #[test] |
863 | fn macro_fuzzy_completion() { | 857 | fn macro_fuzzy_completion() { |
864 | check_edit_with_config( | 858 | check_edit_with_config( |
865 | fuzzy_completion_config(), | 859 | TEST_CONFIG, |
866 | "macro_with_curlies!", | 860 | "macro_with_curlies!", |
867 | r#" | 861 | r#" |
868 | //- /lib.rs crate:dep | 862 | //- /lib.rs crate:dep |
@@ -874,7 +868,7 @@ macro_rules! macro_with_curlies { | |||
874 | 868 | ||
875 | //- /main.rs crate:main deps:dep | 869 | //- /main.rs crate:main deps:dep |
876 | fn main() { | 870 | fn main() { |
877 | curli<|> | 871 | curli$0 |
878 | } | 872 | } |
879 | "#, | 873 | "#, |
880 | r#" | 874 | r#" |
@@ -890,7 +884,7 @@ fn main() { | |||
890 | #[test] | 884 | #[test] |
891 | fn struct_fuzzy_completion() { | 885 | fn struct_fuzzy_completion() { |
892 | check_edit_with_config( | 886 | check_edit_with_config( |
893 | fuzzy_completion_config(), | 887 | TEST_CONFIG, |
894 | "ThirdStruct", | 888 | "ThirdStruct", |
895 | r#" | 889 | r#" |
896 | //- /lib.rs crate:dep | 890 | //- /lib.rs crate:dep |
@@ -904,7 +898,7 @@ pub mod some_module { | |||
904 | use dep::{FirstStruct, some_module::SecondStruct}; | 898 | use dep::{FirstStruct, some_module::SecondStruct}; |
905 | 899 | ||
906 | fn main() { | 900 | fn main() { |
907 | this<|> | 901 | this$0 |
908 | } | 902 | } |
909 | "#, | 903 | "#, |
910 | r#" | 904 | r#" |
@@ -921,7 +915,7 @@ fn main() { | |||
921 | fn fuzzy_completions_come_in_specific_order() { | 915 | fn fuzzy_completions_come_in_specific_order() { |
922 | mark::check!(certain_fuzzy_order_test); | 916 | mark::check!(certain_fuzzy_order_test); |
923 | check_with_config( | 917 | check_with_config( |
924 | fuzzy_completion_config(), | 918 | TEST_CONFIG, |
925 | r#" | 919 | r#" |
926 | //- /lib.rs crate:dep | 920 | //- /lib.rs crate:dep |
927 | pub struct FirstStruct; | 921 | pub struct FirstStruct; |
@@ -942,7 +936,7 @@ pub mod some_module { | |||
942 | use dep::{FirstStruct, some_module::SecondStruct}; | 936 | use dep::{FirstStruct, some_module::SecondStruct}; |
943 | 937 | ||
944 | fn main() { | 938 | fn main() { |
945 | hir<|> | 939 | hir$0 |
946 | } | 940 | } |
947 | "#, | 941 | "#, |
948 | expect![[r#" | 942 | expect![[r#" |
diff --git a/crates/completion/src/config.rs b/crates/completion/src/config.rs index 30577dc11..b4439b7d1 100644 --- a/crates/completion/src/config.rs +++ b/crates/completion/src/config.rs | |||
@@ -4,8 +4,7 @@ | |||
4 | //! module, and we use to statically check that we only produce snippet | 4 | //! module, and we use to statically check that we only produce snippet |
5 | //! completions if we are allowed to. | 5 | //! completions if we are allowed to. |
6 | 6 | ||
7 | use ide_db::helpers::insert_use::MergeBehavior; | 7 | use ide_db::helpers::{insert_use::MergeBehavior, SnippetCap}; |
8 | use rustc_hash::FxHashSet; | ||
9 | 8 | ||
10 | #[derive(Clone, Debug, PartialEq, Eq)] | 9 | #[derive(Clone, Debug, PartialEq, Eq)] |
11 | pub struct CompletionConfig { | 10 | pub struct CompletionConfig { |
@@ -15,49 +14,4 @@ pub struct CompletionConfig { | |||
15 | pub add_call_argument_snippets: bool, | 14 | pub add_call_argument_snippets: bool, |
16 | pub snippet_cap: Option<SnippetCap>, | 15 | pub snippet_cap: Option<SnippetCap>, |
17 | pub merge: Option<MergeBehavior>, | 16 | pub merge: Option<MergeBehavior>, |
18 | /// A set of capabilities, enabled on the client and supported on the server. | ||
19 | pub active_resolve_capabilities: FxHashSet<CompletionResolveCapability>, | ||
20 | } | ||
21 | |||
22 | /// A resolve capability, supported on the server. | ||
23 | /// If the client registers any completion resolve capabilities, | ||
24 | /// the server is able to render completion items' corresponding fields later, | ||
25 | /// not during an initial completion item request. | ||
26 | /// See https://github.com/rust-analyzer/rust-analyzer/issues/6366 for more details. | ||
27 | #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)] | ||
28 | pub enum CompletionResolveCapability { | ||
29 | Documentation, | ||
30 | Detail, | ||
31 | AdditionalTextEdits, | ||
32 | } | ||
33 | |||
34 | impl CompletionConfig { | ||
35 | pub fn allow_snippets(&mut self, yes: bool) { | ||
36 | self.snippet_cap = if yes { Some(SnippetCap { _private: () }) } else { None } | ||
37 | } | ||
38 | |||
39 | /// Whether the completions' additional edits are calculated when sending an initional completions list | ||
40 | /// or later, in a separate resolve request. | ||
41 | pub fn resolve_additional_edits_lazily(&self) -> bool { | ||
42 | self.active_resolve_capabilities.contains(&CompletionResolveCapability::AdditionalTextEdits) | ||
43 | } | ||
44 | } | ||
45 | |||
46 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||
47 | pub struct SnippetCap { | ||
48 | _private: (), | ||
49 | } | ||
50 | |||
51 | impl Default for CompletionConfig { | ||
52 | fn default() -> Self { | ||
53 | CompletionConfig { | ||
54 | enable_postfix_completions: true, | ||
55 | enable_autoimport_completions: true, | ||
56 | add_call_parenthesis: true, | ||
57 | add_call_argument_snippets: true, | ||
58 | snippet_cap: Some(SnippetCap { _private: () }), | ||
59 | merge: Some(MergeBehavior::Full), | ||
60 | active_resolve_capabilities: FxHashSet::default(), | ||
61 | } | ||
62 | } | ||
63 | } | 17 | } |
diff --git a/crates/completion/src/context.rs b/crates/completion/src/context.rs index f979697ab..ebf28e887 100644 --- a/crates/completion/src/context.rs +++ b/crates/completion/src/context.rs | |||
@@ -63,7 +63,7 @@ pub(crate) struct CompletionContext<'a> { | |||
63 | pub(super) is_expr: bool, | 63 | pub(super) is_expr: bool, |
64 | /// Something is typed at the "top" level, in module or impl/trait. | 64 | /// Something is typed at the "top" level, in module or impl/trait. |
65 | pub(super) is_new_item: bool, | 65 | pub(super) is_new_item: bool, |
66 | /// The receiver if this is a field or method access, i.e. writing something.<|> | 66 | /// The receiver if this is a field or method access, i.e. writing something.$0 |
67 | pub(super) dot_receiver: Option<ast::Expr>, | 67 | pub(super) dot_receiver: Option<ast::Expr>, |
68 | pub(super) dot_receiver_is_ambiguous_float_literal: bool, | 68 | pub(super) dot_receiver_is_ambiguous_float_literal: bool, |
69 | /// If this is a call (method or function) in particular, i.e. the () are already there. | 69 | /// If this is a call (method or function) in particular, i.e. the () are already there. |
@@ -228,9 +228,9 @@ impl<'a> CompletionContext<'a> { | |||
228 | 228 | ||
229 | /// Checks whether completions in that particular case don't make much sense. | 229 | /// Checks whether completions in that particular case don't make much sense. |
230 | /// Examples: | 230 | /// Examples: |
231 | /// - `fn <|>` -- we expect function name, it's unlikely that "hint" will be helpful. | 231 | /// - `fn $0` -- we expect function name, it's unlikely that "hint" will be helpful. |
232 | /// Exception for this case is `impl Trait for Foo`, where we would like to hint trait method names. | 232 | /// Exception for this case is `impl Trait for Foo`, where we would like to hint trait method names. |
233 | /// - `for _ i<|>` -- obviously, it'll be "in" keyword. | 233 | /// - `for _ i$0` -- obviously, it'll be "in" keyword. |
234 | pub(crate) fn no_completion_required(&self) -> bool { | 234 | pub(crate) fn no_completion_required(&self) -> bool { |
235 | (self.fn_is_prev && !self.inside_impl_trait_block) || self.for_is_prev2 | 235 | (self.fn_is_prev && !self.inside_impl_trait_block) || self.for_is_prev2 |
236 | } | 236 | } |
@@ -279,7 +279,7 @@ impl<'a> CompletionContext<'a> { | |||
279 | offset: TextSize, | 279 | offset: TextSize, |
280 | ) { | 280 | ) { |
281 | // FIXME: this is wrong in at least two cases: | 281 | // FIXME: this is wrong in at least two cases: |
282 | // * when there's no token `foo(<|>)` | 282 | // * when there's no token `foo($0)` |
283 | // * when there is a token, but it happens to have type of it's own | 283 | // * when there is a token, but it happens to have type of it's own |
284 | self.expected_type = self | 284 | self.expected_type = self |
285 | .token | 285 | .token |
diff --git a/crates/completion/src/item.rs b/crates/completion/src/item.rs index 65f8353e7..35af354b0 100644 --- a/crates/completion/src/item.rs +++ b/crates/completion/src/item.rs | |||
@@ -5,13 +5,11 @@ use std::fmt; | |||
5 | use hir::{Documentation, ModPath, Mutability}; | 5 | use hir::{Documentation, ModPath, Mutability}; |
6 | use ide_db::helpers::{ | 6 | use ide_db::helpers::{ |
7 | insert_use::{self, ImportScope, MergeBehavior}, | 7 | insert_use::{self, ImportScope, MergeBehavior}, |
8 | mod_path_to_ast, | 8 | mod_path_to_ast, SnippetCap, |
9 | }; | 9 | }; |
10 | use syntax::{algo, TextRange}; | 10 | use syntax::{algo, TextRange}; |
11 | use text_edit::TextEdit; | 11 | use text_edit::TextEdit; |
12 | 12 | ||
13 | use crate::config::SnippetCap; | ||
14 | |||
15 | /// `CompletionItem` describes a single completion variant in the editor pop-up. | 13 | /// `CompletionItem` describes a single completion variant in the editor pop-up. |
16 | /// It is basically a POD with various properties. To construct a | 14 | /// It is basically a POD with various properties. To construct a |
17 | /// `CompletionItem`, use `new` method and the `Builder` struct. | 15 | /// `CompletionItem`, use `new` method and the `Builder` struct. |
@@ -45,7 +43,7 @@ pub struct CompletionItem { | |||
45 | /// Lookup is used to check if completion item indeed can complete current | 43 | /// Lookup is used to check if completion item indeed can complete current |
46 | /// ident. | 44 | /// ident. |
47 | /// | 45 | /// |
48 | /// That is, in `foo.bar<|>` lookup of `abracadabra` will be accepted (it | 46 | /// That is, in `foo.bar$0` lookup of `abracadabra` will be accepted (it |
49 | /// contains `bar` sub sequence), and `quux` will rejected. | 47 | /// contains `bar` sub sequence), and `quux` will rejected. |
50 | lookup: Option<String>, | 48 | lookup: Option<String>, |
51 | 49 | ||
diff --git a/crates/completion/src/lib.rs b/crates/completion/src/lib.rs index c57d05bbe..6cba88a6b 100644 --- a/crates/completion/src/lib.rs +++ b/crates/completion/src/lib.rs | |||
@@ -20,7 +20,7 @@ use text_edit::TextEdit; | |||
20 | use crate::{completions::Completions, context::CompletionContext, item::CompletionKind}; | 20 | use crate::{completions::Completions, context::CompletionContext, item::CompletionKind}; |
21 | 21 | ||
22 | pub use crate::{ | 22 | pub use crate::{ |
23 | config::{CompletionConfig, CompletionResolveCapability}, | 23 | config::CompletionConfig, |
24 | item::{CompletionItem, CompletionItemKind, CompletionScore, ImportEdit, InsertTextFormat}, | 24 | item::{CompletionItem, CompletionItemKind, CompletionScore, ImportEdit, InsertTextFormat}, |
25 | }; | 25 | }; |
26 | 26 | ||
@@ -47,8 +47,8 @@ pub use crate::{ | |||
47 | // - `expr.while` -> `while expr {}` or `while let ... {}` for `Option` or `Result` | 47 | // - `expr.while` -> `while expr {}` or `while let ... {}` for `Option` or `Result` |
48 | // - `expr.ref` -> `&expr` | 48 | // - `expr.ref` -> `&expr` |
49 | // - `expr.refm` -> `&mut expr` | 49 | // - `expr.refm` -> `&mut expr` |
50 | // - `expr.let` -> `let <|> = expr;` | 50 | // - `expr.let` -> `let $0 = expr;` |
51 | // - `expr.letm` -> `let mut <|> = expr;` | 51 | // - `expr.letm` -> `let mut $0 = expr;` |
52 | // - `expr.not` -> `!expr` | 52 | // - `expr.not` -> `!expr` |
53 | // - `expr.dbg` -> `dbg!(expr)` | 53 | // - `expr.dbg` -> `dbg!(expr)` |
54 | // - `expr.dbgr` -> `dbg!(&expr)` | 54 | // - `expr.dbgr` -> `dbg!(&expr)` |
@@ -92,7 +92,7 @@ pub use crate::{ | |||
92 | /// ```no_run | 92 | /// ```no_run |
93 | /// fn f() { | 93 | /// fn f() { |
94 | /// let foo = 92; | 94 | /// let foo = 92; |
95 | /// let _ = bar<|> | 95 | /// let _ = bar$0 |
96 | /// } | 96 | /// } |
97 | /// ``` | 97 | /// ``` |
98 | /// | 98 | /// |
@@ -158,8 +158,7 @@ pub fn resolve_completion_edits( | |||
158 | 158 | ||
159 | #[cfg(test)] | 159 | #[cfg(test)] |
160 | mod tests { | 160 | mod tests { |
161 | use crate::config::CompletionConfig; | 161 | use crate::test_utils::{self, TEST_CONFIG}; |
162 | use crate::test_utils; | ||
163 | 162 | ||
164 | struct DetailAndDocumentation<'a> { | 163 | struct DetailAndDocumentation<'a> { |
165 | detail: &'a str, | 164 | detail: &'a str, |
@@ -168,7 +167,7 @@ mod tests { | |||
168 | 167 | ||
169 | fn check_detail_and_documentation(ra_fixture: &str, expected: DetailAndDocumentation) { | 168 | fn check_detail_and_documentation(ra_fixture: &str, expected: DetailAndDocumentation) { |
170 | let (db, position) = test_utils::position(ra_fixture); | 169 | let (db, position) = test_utils::position(ra_fixture); |
171 | let config = CompletionConfig::default(); | 170 | let config = TEST_CONFIG; |
172 | let completions: Vec<_> = crate::completions(&db, &config, position).unwrap().into(); | 171 | let completions: Vec<_> = crate::completions(&db, &config, position).unwrap().into(); |
173 | for item in completions { | 172 | for item in completions { |
174 | if item.detail() == Some(expected.detail) { | 173 | if item.detail() == Some(expected.detail) { |
@@ -183,7 +182,7 @@ mod tests { | |||
183 | 182 | ||
184 | fn check_no_completion(ra_fixture: &str) { | 183 | fn check_no_completion(ra_fixture: &str) { |
185 | let (db, position) = test_utils::position(ra_fixture); | 184 | let (db, position) = test_utils::position(ra_fixture); |
186 | let config = CompletionConfig::default(); | 185 | let config = TEST_CONFIG; |
187 | 186 | ||
188 | let completions: Option<Vec<String>> = crate::completions(&db, &config, position) | 187 | let completions: Option<Vec<String>> = crate::completions(&db, &config, position) |
189 | .and_then(|completions| { | 188 | .and_then(|completions| { |
@@ -221,7 +220,7 @@ mod tests { | |||
221 | 220 | ||
222 | fn foo() { | 221 | fn foo() { |
223 | let bar = Bar; | 222 | let bar = Bar; |
224 | bar.fo<|>; | 223 | bar.fo$0; |
225 | } | 224 | } |
226 | "#, | 225 | "#, |
227 | DetailAndDocumentation { detail: "fn foo(&self)", documentation: "Do the foo" }, | 226 | DetailAndDocumentation { detail: "fn foo(&self)", documentation: "Do the foo" }, |
@@ -247,7 +246,7 @@ mod tests { | |||
247 | 246 | ||
248 | fn foo() { | 247 | fn foo() { |
249 | let bar = Bar; | 248 | let bar = Bar; |
250 | bar.fo<|>; | 249 | bar.fo$0; |
251 | } | 250 | } |
252 | "#, | 251 | "#, |
253 | DetailAndDocumentation { detail: "fn foo(&self)", documentation: " Do the foo" }, | 252 | DetailAndDocumentation { detail: "fn foo(&self)", documentation: " Do the foo" }, |
@@ -260,7 +259,7 @@ mod tests { | |||
260 | check_no_completion( | 259 | check_no_completion( |
261 | r#" | 260 | r#" |
262 | fn foo() { | 261 | fn foo() { |
263 | for i i<|> | 262 | for i i$0 |
264 | } | 263 | } |
265 | "#, | 264 | "#, |
266 | ); | 265 | ); |
@@ -271,7 +270,7 @@ mod tests { | |||
271 | fn foo() -> &'static str { "foo" } | 270 | fn foo() -> &'static str { "foo" } |
272 | 271 | ||
273 | fn bar() { | 272 | fn bar() { |
274 | for c in fo<|> | 273 | for c in fo$0 |
275 | } | 274 | } |
276 | "#, | 275 | "#, |
277 | DetailAndDocumentation { | 276 | DetailAndDocumentation { |
diff --git a/crates/completion/src/patterns.rs b/crates/completion/src/patterns.rs index b0f35f9bf..f3ce91dd1 100644 --- a/crates/completion/src/patterns.rs +++ b/crates/completion/src/patterns.rs | |||
@@ -5,7 +5,7 @@ use syntax::{ | |||
5 | ast::{self, LoopBodyOwner}, | 5 | ast::{self, LoopBodyOwner}, |
6 | match_ast, AstNode, Direction, NodeOrToken, SyntaxElement, | 6 | match_ast, AstNode, Direction, NodeOrToken, SyntaxElement, |
7 | SyntaxKind::*, | 7 | SyntaxKind::*, |
8 | SyntaxNode, SyntaxToken, | 8 | SyntaxNode, SyntaxToken, T, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | #[cfg(test)] | 11 | #[cfg(test)] |
@@ -20,7 +20,7 @@ pub(crate) fn has_trait_parent(element: SyntaxElement) -> bool { | |||
20 | } | 20 | } |
21 | #[test] | 21 | #[test] |
22 | fn test_has_trait_parent() { | 22 | fn test_has_trait_parent() { |
23 | check_pattern_is_applicable(r"trait A { f<|> }", has_trait_parent); | 23 | check_pattern_is_applicable(r"trait A { f$0 }", has_trait_parent); |
24 | } | 24 | } |
25 | 25 | ||
26 | pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool { | 26 | pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool { |
@@ -32,7 +32,7 @@ pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool { | |||
32 | } | 32 | } |
33 | #[test] | 33 | #[test] |
34 | fn test_has_impl_parent() { | 34 | fn test_has_impl_parent() { |
35 | check_pattern_is_applicable(r"impl A { f<|> }", has_impl_parent); | 35 | check_pattern_is_applicable(r"impl A { f$0 }", has_impl_parent); |
36 | } | 36 | } |
37 | 37 | ||
38 | pub(crate) fn inside_impl_trait_block(element: SyntaxElement) -> bool { | 38 | pub(crate) fn inside_impl_trait_block(element: SyntaxElement) -> bool { |
@@ -47,10 +47,10 @@ pub(crate) fn inside_impl_trait_block(element: SyntaxElement) -> bool { | |||
47 | } | 47 | } |
48 | #[test] | 48 | #[test] |
49 | fn test_inside_impl_trait_block() { | 49 | fn test_inside_impl_trait_block() { |
50 | check_pattern_is_applicable(r"impl Foo for Bar { f<|> }", inside_impl_trait_block); | 50 | check_pattern_is_applicable(r"impl Foo for Bar { f$0 }", inside_impl_trait_block); |
51 | check_pattern_is_applicable(r"impl Foo for Bar { fn f<|> }", inside_impl_trait_block); | 51 | check_pattern_is_applicable(r"impl Foo for Bar { fn f$0 }", inside_impl_trait_block); |
52 | check_pattern_is_not_applicable(r"impl A { f<|> }", inside_impl_trait_block); | 52 | check_pattern_is_not_applicable(r"impl A { f$0 }", inside_impl_trait_block); |
53 | check_pattern_is_not_applicable(r"impl A { fn f<|> }", inside_impl_trait_block); | 53 | check_pattern_is_not_applicable(r"impl A { fn f$0 }", inside_impl_trait_block); |
54 | } | 54 | } |
55 | 55 | ||
56 | pub(crate) fn has_field_list_parent(element: SyntaxElement) -> bool { | 56 | pub(crate) fn has_field_list_parent(element: SyntaxElement) -> bool { |
@@ -58,8 +58,8 @@ pub(crate) fn has_field_list_parent(element: SyntaxElement) -> bool { | |||
58 | } | 58 | } |
59 | #[test] | 59 | #[test] |
60 | fn test_has_field_list_parent() { | 60 | fn test_has_field_list_parent() { |
61 | check_pattern_is_applicable(r"struct Foo { f<|> }", has_field_list_parent); | 61 | check_pattern_is_applicable(r"struct Foo { f$0 }", has_field_list_parent); |
62 | check_pattern_is_applicable(r"struct Foo { f<|> pub f: i32}", has_field_list_parent); | 62 | check_pattern_is_applicable(r"struct Foo { f$0 pub f: i32}", has_field_list_parent); |
63 | } | 63 | } |
64 | 64 | ||
65 | pub(crate) fn has_block_expr_parent(element: SyntaxElement) -> bool { | 65 | pub(crate) fn has_block_expr_parent(element: SyntaxElement) -> bool { |
@@ -67,7 +67,7 @@ pub(crate) fn has_block_expr_parent(element: SyntaxElement) -> bool { | |||
67 | } | 67 | } |
68 | #[test] | 68 | #[test] |
69 | fn test_has_block_expr_parent() { | 69 | fn test_has_block_expr_parent() { |
70 | check_pattern_is_applicable(r"fn my_fn() { let a = 2; f<|> }", has_block_expr_parent); | 70 | check_pattern_is_applicable(r"fn my_fn() { let a = 2; f$0 }", has_block_expr_parent); |
71 | } | 71 | } |
72 | 72 | ||
73 | pub(crate) fn has_bind_pat_parent(element: SyntaxElement) -> bool { | 73 | pub(crate) fn has_bind_pat_parent(element: SyntaxElement) -> bool { |
@@ -75,8 +75,8 @@ pub(crate) fn has_bind_pat_parent(element: SyntaxElement) -> bool { | |||
75 | } | 75 | } |
76 | #[test] | 76 | #[test] |
77 | fn test_has_bind_pat_parent() { | 77 | fn test_has_bind_pat_parent() { |
78 | check_pattern_is_applicable(r"fn my_fn(m<|>) {}", has_bind_pat_parent); | 78 | check_pattern_is_applicable(r"fn my_fn(m$0) {}", has_bind_pat_parent); |
79 | check_pattern_is_applicable(r"fn my_fn() { let m<|> }", has_bind_pat_parent); | 79 | check_pattern_is_applicable(r"fn my_fn() { let m$0 }", has_bind_pat_parent); |
80 | } | 80 | } |
81 | 81 | ||
82 | pub(crate) fn has_ref_parent(element: SyntaxElement) -> bool { | 82 | pub(crate) fn has_ref_parent(element: SyntaxElement) -> bool { |
@@ -86,8 +86,8 @@ pub(crate) fn has_ref_parent(element: SyntaxElement) -> bool { | |||
86 | } | 86 | } |
87 | #[test] | 87 | #[test] |
88 | fn test_has_ref_parent() { | 88 | fn test_has_ref_parent() { |
89 | check_pattern_is_applicable(r"fn my_fn(&m<|>) {}", has_ref_parent); | 89 | check_pattern_is_applicable(r"fn my_fn(&m$0) {}", has_ref_parent); |
90 | check_pattern_is_applicable(r"fn my() { let &m<|> }", has_ref_parent); | 90 | check_pattern_is_applicable(r"fn my() { let &m$0 }", has_ref_parent); |
91 | } | 91 | } |
92 | 92 | ||
93 | pub(crate) fn has_item_list_or_source_file_parent(element: SyntaxElement) -> bool { | 93 | pub(crate) fn has_item_list_or_source_file_parent(element: SyntaxElement) -> bool { |
@@ -99,8 +99,8 @@ pub(crate) fn has_item_list_or_source_file_parent(element: SyntaxElement) -> boo | |||
99 | } | 99 | } |
100 | #[test] | 100 | #[test] |
101 | fn test_has_item_list_or_source_file_parent() { | 101 | fn test_has_item_list_or_source_file_parent() { |
102 | check_pattern_is_applicable(r"i<|>", has_item_list_or_source_file_parent); | 102 | check_pattern_is_applicable(r"i$0", has_item_list_or_source_file_parent); |
103 | check_pattern_is_applicable(r"mod foo { f<|> }", has_item_list_or_source_file_parent); | 103 | check_pattern_is_applicable(r"mod foo { f$0 }", has_item_list_or_source_file_parent); |
104 | } | 104 | } |
105 | 105 | ||
106 | pub(crate) fn is_match_arm(element: SyntaxElement) -> bool { | 106 | pub(crate) fn is_match_arm(element: SyntaxElement) -> bool { |
@@ -112,26 +112,26 @@ pub(crate) fn is_match_arm(element: SyntaxElement) -> bool { | |||
112 | } | 112 | } |
113 | #[test] | 113 | #[test] |
114 | fn test_is_match_arm() { | 114 | fn test_is_match_arm() { |
115 | check_pattern_is_applicable(r"fn my_fn() { match () { () => m<|> } }", is_match_arm); | 115 | check_pattern_is_applicable(r"fn my_fn() { match () { () => m$0 } }", is_match_arm); |
116 | } | 116 | } |
117 | 117 | ||
118 | pub(crate) fn unsafe_is_prev(element: SyntaxElement) -> bool { | 118 | pub(crate) fn unsafe_is_prev(element: SyntaxElement) -> bool { |
119 | element | 119 | element |
120 | .into_token() | 120 | .into_token() |
121 | .and_then(|it| previous_non_trivia_token(it)) | 121 | .and_then(|it| previous_non_trivia_token(it)) |
122 | .filter(|it| it.kind() == UNSAFE_KW) | 122 | .filter(|it| it.kind() == T![unsafe]) |
123 | .is_some() | 123 | .is_some() |
124 | } | 124 | } |
125 | #[test] | 125 | #[test] |
126 | fn test_unsafe_is_prev() { | 126 | fn test_unsafe_is_prev() { |
127 | check_pattern_is_applicable(r"unsafe i<|>", unsafe_is_prev); | 127 | check_pattern_is_applicable(r"unsafe i$0", unsafe_is_prev); |
128 | } | 128 | } |
129 | 129 | ||
130 | pub(crate) fn if_is_prev(element: SyntaxElement) -> bool { | 130 | pub(crate) fn if_is_prev(element: SyntaxElement) -> bool { |
131 | element | 131 | element |
132 | .into_token() | 132 | .into_token() |
133 | .and_then(|it| previous_non_trivia_token(it)) | 133 | .and_then(|it| previous_non_trivia_token(it)) |
134 | .filter(|it| it.kind() == IF_KW) | 134 | .filter(|it| it.kind() == T![if]) |
135 | .is_some() | 135 | .is_some() |
136 | } | 136 | } |
137 | 137 | ||
@@ -139,32 +139,32 @@ pub(crate) fn fn_is_prev(element: SyntaxElement) -> bool { | |||
139 | element | 139 | element |
140 | .into_token() | 140 | .into_token() |
141 | .and_then(|it| previous_non_trivia_token(it)) | 141 | .and_then(|it| previous_non_trivia_token(it)) |
142 | .filter(|it| it.kind() == FN_KW) | 142 | .filter(|it| it.kind() == T![fn]) |
143 | .is_some() | 143 | .is_some() |
144 | } | 144 | } |
145 | #[test] | 145 | #[test] |
146 | fn test_fn_is_prev() { | 146 | fn test_fn_is_prev() { |
147 | check_pattern_is_applicable(r"fn l<|>", fn_is_prev); | 147 | check_pattern_is_applicable(r"fn l$0", fn_is_prev); |
148 | } | 148 | } |
149 | 149 | ||
150 | /// Check if the token previous to the previous one is `for`. | 150 | /// Check if the token previous to the previous one is `for`. |
151 | /// For example, `for _ i<|>` => true. | 151 | /// For example, `for _ i$0` => true. |
152 | pub(crate) fn for_is_prev2(element: SyntaxElement) -> bool { | 152 | pub(crate) fn for_is_prev2(element: SyntaxElement) -> bool { |
153 | element | 153 | element |
154 | .into_token() | 154 | .into_token() |
155 | .and_then(|it| previous_non_trivia_token(it)) | 155 | .and_then(|it| previous_non_trivia_token(it)) |
156 | .and_then(|it| previous_non_trivia_token(it)) | 156 | .and_then(|it| previous_non_trivia_token(it)) |
157 | .filter(|it| it.kind() == FOR_KW) | 157 | .filter(|it| it.kind() == T![for]) |
158 | .is_some() | 158 | .is_some() |
159 | } | 159 | } |
160 | #[test] | 160 | #[test] |
161 | fn test_for_is_prev2() { | 161 | fn test_for_is_prev2() { |
162 | check_pattern_is_applicable(r"for i i<|>", for_is_prev2); | 162 | check_pattern_is_applicable(r"for i i$0", for_is_prev2); |
163 | } | 163 | } |
164 | 164 | ||
165 | #[test] | 165 | #[test] |
166 | fn test_if_is_prev() { | 166 | fn test_if_is_prev() { |
167 | check_pattern_is_applicable(r"if l<|>", if_is_prev); | 167 | check_pattern_is_applicable(r"if l$0", if_is_prev); |
168 | } | 168 | } |
169 | 169 | ||
170 | pub(crate) fn has_trait_as_prev_sibling(element: SyntaxElement) -> bool { | 170 | pub(crate) fn has_trait_as_prev_sibling(element: SyntaxElement) -> bool { |
@@ -172,7 +172,7 @@ pub(crate) fn has_trait_as_prev_sibling(element: SyntaxElement) -> bool { | |||
172 | } | 172 | } |
173 | #[test] | 173 | #[test] |
174 | fn test_has_trait_as_prev_sibling() { | 174 | fn test_has_trait_as_prev_sibling() { |
175 | check_pattern_is_applicable(r"trait A w<|> {}", has_trait_as_prev_sibling); | 175 | check_pattern_is_applicable(r"trait A w$0 {}", has_trait_as_prev_sibling); |
176 | } | 176 | } |
177 | 177 | ||
178 | pub(crate) fn has_impl_as_prev_sibling(element: SyntaxElement) -> bool { | 178 | pub(crate) fn has_impl_as_prev_sibling(element: SyntaxElement) -> bool { |
@@ -180,7 +180,7 @@ pub(crate) fn has_impl_as_prev_sibling(element: SyntaxElement) -> bool { | |||
180 | } | 180 | } |
181 | #[test] | 181 | #[test] |
182 | fn test_has_impl_as_prev_sibling() { | 182 | fn test_has_impl_as_prev_sibling() { |
183 | check_pattern_is_applicable(r"impl A w<|> {}", has_impl_as_prev_sibling); | 183 | check_pattern_is_applicable(r"impl A w$0 {}", has_impl_as_prev_sibling); |
184 | } | 184 | } |
185 | 185 | ||
186 | pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool { | 186 | pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool { |
diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs index ac0b2a513..e93c59f71 100644 --- a/crates/completion/src/render.rs +++ b/crates/completion/src/render.rs | |||
@@ -11,13 +11,13 @@ pub(crate) mod type_alias; | |||
11 | mod builder_ext; | 11 | mod builder_ext; |
12 | 12 | ||
13 | use hir::{Documentation, HasAttrs, HirDisplay, Mutability, ScopeDef, Type}; | 13 | use hir::{Documentation, HasAttrs, HirDisplay, Mutability, ScopeDef, Type}; |
14 | use ide_db::RootDatabase; | 14 | use ide_db::{helpers::SnippetCap, RootDatabase}; |
15 | use syntax::TextRange; | 15 | use syntax::TextRange; |
16 | use test_utils::mark; | 16 | use test_utils::mark; |
17 | 17 | ||
18 | use crate::{ | 18 | use crate::{ |
19 | config::SnippetCap, item::ImportEdit, CompletionContext, CompletionItem, CompletionItemKind, | 19 | item::ImportEdit, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, |
20 | CompletionKind, CompletionScore, | 20 | CompletionScore, |
21 | }; | 21 | }; |
22 | 22 | ||
23 | use crate::render::{enum_variant::render_variant, function::render_fn, macro_::render_macro}; | 23 | use crate::render::{enum_variant::render_variant, function::render_fn, macro_::render_macro}; |
@@ -320,8 +320,8 @@ mod tests { | |||
320 | use test_utils::mark; | 320 | use test_utils::mark; |
321 | 321 | ||
322 | use crate::{ | 322 | use crate::{ |
323 | test_utils::{check_edit, do_completion, get_all_items}, | 323 | test_utils::{check_edit, do_completion, get_all_items, TEST_CONFIG}, |
324 | CompletionConfig, CompletionKind, CompletionScore, | 324 | CompletionKind, CompletionScore, |
325 | }; | 325 | }; |
326 | 326 | ||
327 | fn check(ra_fixture: &str, expect: Expect) { | 327 | fn check(ra_fixture: &str, expect: Expect) { |
@@ -338,7 +338,7 @@ mod tests { | |||
338 | } | 338 | } |
339 | } | 339 | } |
340 | 340 | ||
341 | let mut completions = get_all_items(CompletionConfig::default(), ra_fixture); | 341 | let mut completions = get_all_items(TEST_CONFIG, ra_fixture); |
342 | completions.sort_by_key(|it| (Reverse(it.score()), it.label().to_string())); | 342 | completions.sort_by_key(|it| (Reverse(it.score()), it.label().to_string())); |
343 | let actual = completions | 343 | let actual = completions |
344 | .into_iter() | 344 | .into_iter() |
@@ -358,7 +358,7 @@ mod tests { | |||
358 | r#" | 358 | r#" |
359 | enum Foo { Foo { x: i32, y: i32 } } | 359 | enum Foo { Foo { x: i32, y: i32 } } |
360 | 360 | ||
361 | fn main() { Foo::Fo<|> } | 361 | fn main() { Foo::Fo$0 } |
362 | "#, | 362 | "#, |
363 | expect![[r#" | 363 | expect![[r#" |
364 | [ | 364 | [ |
@@ -381,7 +381,7 @@ fn main() { Foo::Fo<|> } | |||
381 | r#" | 381 | r#" |
382 | enum Foo { Foo (i32, i32) } | 382 | enum Foo { Foo (i32, i32) } |
383 | 383 | ||
384 | fn main() { Foo::Fo<|> } | 384 | fn main() { Foo::Fo$0 } |
385 | "#, | 385 | "#, |
386 | expect![[r#" | 386 | expect![[r#" |
387 | [ | 387 | [ |
@@ -406,7 +406,7 @@ fn main() { Foo::Fo<|> } | |||
406 | r#" | 406 | r#" |
407 | enum Foo { Foo } | 407 | enum Foo { Foo } |
408 | 408 | ||
409 | fn main() { Foo::Fo<|> } | 409 | fn main() { Foo::Fo$0 } |
410 | "#, | 410 | "#, |
411 | expect![[r#" | 411 | expect![[r#" |
412 | [ | 412 | [ |
@@ -430,7 +430,7 @@ fn main() { Foo::Fo<|> } | |||
430 | mod m { | 430 | mod m { |
431 | pub enum Spam { Foo, Bar(i32) } | 431 | pub enum Spam { Foo, Bar(i32) } |
432 | } | 432 | } |
433 | fn main() { let _: m::Spam = S<|> } | 433 | fn main() { let _: m::Spam = S$0 } |
434 | "#, | 434 | "#, |
435 | expect![[r#" | 435 | expect![[r#" |
436 | [ | 436 | [ |
@@ -483,7 +483,7 @@ fn something_deprecated() {} | |||
483 | #[deprecated(since = "1.0.0")] | 483 | #[deprecated(since = "1.0.0")] |
484 | fn something_else_deprecated() {} | 484 | fn something_else_deprecated() {} |
485 | 485 | ||
486 | fn main() { som<|> } | 486 | fn main() { som$0 } |
487 | "#, | 487 | "#, |
488 | expect![[r#" | 488 | expect![[r#" |
489 | [ | 489 | [ |
@@ -523,7 +523,7 @@ fn main() { som<|> } | |||
523 | check( | 523 | check( |
524 | r#" | 524 | r#" |
525 | struct A { #[deprecated] the_field: u32 } | 525 | struct A { #[deprecated] the_field: u32 } |
526 | fn foo() { A { the<|> } } | 526 | fn foo() { A { the$0 } } |
527 | "#, | 527 | "#, |
528 | expect![[r#" | 528 | expect![[r#" |
529 | [ | 529 | [ |
@@ -551,7 +551,7 @@ struct S { | |||
551 | } | 551 | } |
552 | impl S { | 552 | impl S { |
553 | /// Method docs | 553 | /// Method docs |
554 | fn bar(self) { self.<|> } | 554 | fn bar(self) { self.$0 } |
555 | }"#, | 555 | }"#, |
556 | expect![[r#" | 556 | expect![[r#" |
557 | [ | 557 | [ |
@@ -584,7 +584,7 @@ impl S { | |||
584 | 584 | ||
585 | check( | 585 | check( |
586 | r#" | 586 | r#" |
587 | use self::my<|>; | 587 | use self::my$0; |
588 | 588 | ||
589 | /// mod docs | 589 | /// mod docs |
590 | mod my { } | 590 | mod my { } |
@@ -643,7 +643,7 @@ impl S { | |||
643 | #[inline] | 643 | #[inline] |
644 | fn the_method(&self) { } | 644 | fn the_method(&self) { } |
645 | } | 645 | } |
646 | fn foo(s: S) { s.<|> } | 646 | fn foo(s: S) { s.$0 } |
647 | "#, | 647 | "#, |
648 | expect![[r#" | 648 | expect![[r#" |
649 | [ | 649 | [ |
@@ -671,7 +671,7 @@ fn foo(foo: u8, bar: u8) {} | |||
671 | struct ManualVtable { f: fn(u8, u8) } | 671 | struct ManualVtable { f: fn(u8, u8) } |
672 | 672 | ||
673 | fn main() -> ManualVtable { | 673 | fn main() -> ManualVtable { |
674 | ManualVtable { f: f<|> } | 674 | ManualVtable { f: f$0 } |
675 | } | 675 | } |
676 | "#, | 676 | "#, |
677 | r#" | 677 | r#" |
@@ -692,7 +692,7 @@ fn main() -> ManualVtable { | |||
692 | "foo", | 692 | "foo", |
693 | r#" | 693 | r#" |
694 | mod m { pub fn foo() {} } | 694 | mod m { pub fn foo() {} } |
695 | use crate::m::f<|>; | 695 | use crate::m::f$0; |
696 | "#, | 696 | "#, |
697 | r#" | 697 | r#" |
698 | mod m { pub fn foo() {} } | 698 | mod m { pub fn foo() {} } |
@@ -707,7 +707,7 @@ use crate::m::foo; | |||
707 | "foo", | 707 | "foo", |
708 | r#" | 708 | r#" |
709 | fn foo(x: i32) {} | 709 | fn foo(x: i32) {} |
710 | fn main() { f<|>(); } | 710 | fn main() { f$0(); } |
711 | "#, | 711 | "#, |
712 | r#" | 712 | r#" |
713 | fn foo(x: i32) {} | 713 | fn foo(x: i32) {} |
@@ -719,7 +719,7 @@ fn main() { foo(); } | |||
719 | r#" | 719 | r#" |
720 | struct Foo; | 720 | struct Foo; |
721 | impl Foo { fn foo(&self){} } | 721 | impl Foo { fn foo(&self){} } |
722 | fn f(foo: &Foo) { foo.f<|>(); } | 722 | fn f(foo: &Foo) { foo.f$0(); } |
723 | "#, | 723 | "#, |
724 | r#" | 724 | r#" |
725 | struct Foo; | 725 | struct Foo; |
@@ -736,7 +736,7 @@ fn f(foo: &Foo) { foo.foo(); } | |||
736 | "Vec", | 736 | "Vec", |
737 | r#" | 737 | r#" |
738 | struct Vec<T> {} | 738 | struct Vec<T> {} |
739 | fn foo(xs: Ve<|>) | 739 | fn foo(xs: Ve$0) |
740 | "#, | 740 | "#, |
741 | r#" | 741 | r#" |
742 | struct Vec<T> {} | 742 | struct Vec<T> {} |
@@ -747,7 +747,7 @@ fn foo(xs: Vec<$0>) | |||
747 | "Vec", | 747 | "Vec", |
748 | r#" | 748 | r#" |
749 | type Vec<T> = (T,); | 749 | type Vec<T> = (T,); |
750 | fn foo(xs: Ve<|>) | 750 | fn foo(xs: Ve$0) |
751 | "#, | 751 | "#, |
752 | r#" | 752 | r#" |
753 | type Vec<T> = (T,); | 753 | type Vec<T> = (T,); |
@@ -758,7 +758,7 @@ fn foo(xs: Vec<$0>) | |||
758 | "Vec", | 758 | "Vec", |
759 | r#" | 759 | r#" |
760 | struct Vec<T = i128> {} | 760 | struct Vec<T = i128> {} |
761 | fn foo(xs: Ve<|>) | 761 | fn foo(xs: Ve$0) |
762 | "#, | 762 | "#, |
763 | r#" | 763 | r#" |
764 | struct Vec<T = i128> {} | 764 | struct Vec<T = i128> {} |
@@ -769,7 +769,7 @@ fn foo(xs: Vec) | |||
769 | "Vec", | 769 | "Vec", |
770 | r#" | 770 | r#" |
771 | struct Vec<T> {} | 771 | struct Vec<T> {} |
772 | fn foo(xs: Ve<|><i128>) | 772 | fn foo(xs: Ve$0<i128>) |
773 | "#, | 773 | "#, |
774 | r#" | 774 | r#" |
775 | struct Vec<T> {} | 775 | struct Vec<T> {} |
@@ -785,7 +785,7 @@ fn foo(xs: Vec<i128>) | |||
785 | r#" | 785 | r#" |
786 | struct S { foo: i64, bar: u32, baz: u32 } | 786 | struct S { foo: i64, bar: u32, baz: u32 } |
787 | fn test(bar: u32) { } | 787 | fn test(bar: u32) { } |
788 | fn foo(s: S) { test(s.<|>) } | 788 | fn foo(s: S) { test(s.$0) } |
789 | "#, | 789 | "#, |
790 | expect![[r#" | 790 | expect![[r#" |
791 | fd bar [type+name] | 791 | fd bar [type+name] |
@@ -802,7 +802,7 @@ fn foo(s: S) { test(s.<|>) } | |||
802 | r#" | 802 | r#" |
803 | struct A { foo: i64, bar: u32, baz: u32 } | 803 | struct A { foo: i64, bar: u32, baz: u32 } |
804 | struct B { x: (), y: f32, bar: u32 } | 804 | struct B { x: (), y: f32, bar: u32 } |
805 | fn foo(a: A) { B { bar: a.<|> }; } | 805 | fn foo(a: A) { B { bar: a.$0 }; } |
806 | "#, | 806 | "#, |
807 | expect![[r#" | 807 | expect![[r#" |
808 | fd bar [type+name] | 808 | fd bar [type+name] |
@@ -819,7 +819,7 @@ fn foo(a: A) { B { bar: a.<|> }; } | |||
819 | struct A { foo: i64, bar: u32, baz: u32 } | 819 | struct A { foo: i64, bar: u32, baz: u32 } |
820 | struct B { x: (), y: f32, bar: u32 } | 820 | struct B { x: (), y: f32, bar: u32 } |
821 | fn f(foo: i64) { } | 821 | fn f(foo: i64) { } |
822 | fn foo(a: A) { B { bar: f(a.<|>) }; } | 822 | fn foo(a: A) { B { bar: f(a.$0) }; } |
823 | "#, | 823 | "#, |
824 | expect![[r#" | 824 | expect![[r#" |
825 | fd foo [type+name] | 825 | fd foo [type+name] |
@@ -832,7 +832,7 @@ fn foo(a: A) { B { bar: f(a.<|>) }; } | |||
832 | struct A { foo: i64, bar: u32, baz: u32 } | 832 | struct A { foo: i64, bar: u32, baz: u32 } |
833 | struct B { x: (), y: f32, bar: u32 } | 833 | struct B { x: (), y: f32, bar: u32 } |
834 | fn f(foo: i64) { } | 834 | fn f(foo: i64) { } |
835 | fn foo(a: A) { f(B { bar: a.<|> }); } | 835 | fn foo(a: A) { f(B { bar: a.$0 }); } |
836 | "#, | 836 | "#, |
837 | expect![[r#" | 837 | expect![[r#" |
838 | fd bar [type+name] | 838 | fd bar [type+name] |
@@ -847,7 +847,7 @@ fn foo(a: A) { f(B { bar: a.<|> }); } | |||
847 | check_scores( | 847 | check_scores( |
848 | r#" | 848 | r#" |
849 | struct WorldSnapshot { _f: () }; | 849 | struct WorldSnapshot { _f: () }; |
850 | fn go(world: &WorldSnapshot) { go(w<|>) } | 850 | fn go(world: &WorldSnapshot) { go(w$0) } |
851 | "#, | 851 | "#, |
852 | expect![[r#" | 852 | expect![[r#" |
853 | bn world [type+name] | 853 | bn world [type+name] |
@@ -862,7 +862,7 @@ fn go(world: &WorldSnapshot) { go(w<|>) } | |||
862 | check_scores( | 862 | check_scores( |
863 | r#" | 863 | r#" |
864 | struct Foo; | 864 | struct Foo; |
865 | fn f(foo: &Foo) { f(foo, w<|>) } | 865 | fn f(foo: &Foo) { f(foo, w$0) } |
866 | "#, | 866 | "#, |
867 | expect![[r#" | 867 | expect![[r#" |
868 | st Foo [] | 868 | st Foo [] |
diff --git a/crates/completion/src/render/enum_variant.rs b/crates/completion/src/render/enum_variant.rs index 732e139ec..89fb49773 100644 --- a/crates/completion/src/render/enum_variant.rs +++ b/crates/completion/src/render/enum_variant.rs | |||
@@ -115,7 +115,7 @@ mod tests { | |||
115 | enum Option<T> { Some(T), None } | 115 | enum Option<T> { Some(T), None } |
116 | use Option::*; | 116 | use Option::*; |
117 | fn main() -> Option<i32> { | 117 | fn main() -> Option<i32> { |
118 | Som<|> | 118 | Som$0 |
119 | } | 119 | } |
120 | "#, | 120 | "#, |
121 | r#" | 121 | r#" |
diff --git a/crates/completion/src/render/function.rs b/crates/completion/src/render/function.rs index 081be14f4..f5b0ce3e3 100644 --- a/crates/completion/src/render/function.rs +++ b/crates/completion/src/render/function.rs | |||
@@ -113,7 +113,7 @@ mod tests { | |||
113 | use test_utils::mark; | 113 | use test_utils::mark; |
114 | 114 | ||
115 | use crate::{ | 115 | use crate::{ |
116 | test_utils::{check_edit, check_edit_with_config}, | 116 | test_utils::{check_edit, check_edit_with_config, TEST_CONFIG}, |
117 | CompletionConfig, | 117 | CompletionConfig, |
118 | }; | 118 | }; |
119 | 119 | ||
@@ -124,7 +124,7 @@ mod tests { | |||
124 | "no_args", | 124 | "no_args", |
125 | r#" | 125 | r#" |
126 | fn no_args() {} | 126 | fn no_args() {} |
127 | fn main() { no_<|> } | 127 | fn main() { no_$0 } |
128 | "#, | 128 | "#, |
129 | r#" | 129 | r#" |
130 | fn no_args() {} | 130 | fn no_args() {} |
@@ -136,7 +136,7 @@ fn main() { no_args()$0 } | |||
136 | "with_args", | 136 | "with_args", |
137 | r#" | 137 | r#" |
138 | fn with_args(x: i32, y: String) {} | 138 | fn with_args(x: i32, y: String) {} |
139 | fn main() { with_<|> } | 139 | fn main() { with_$0 } |
140 | "#, | 140 | "#, |
141 | r#" | 141 | r#" |
142 | fn with_args(x: i32, y: String) {} | 142 | fn with_args(x: i32, y: String) {} |
@@ -151,7 +151,7 @@ struct S; | |||
151 | impl S { | 151 | impl S { |
152 | fn foo(&self) {} | 152 | fn foo(&self) {} |
153 | } | 153 | } |
154 | fn bar(s: &S) { s.f<|> } | 154 | fn bar(s: &S) { s.f$0 } |
155 | "#, | 155 | "#, |
156 | r#" | 156 | r#" |
157 | struct S; | 157 | struct S; |
@@ -170,7 +170,7 @@ impl S { | |||
170 | fn foo(&self, x: i32) {} | 170 | fn foo(&self, x: i32) {} |
171 | } | 171 | } |
172 | fn bar(s: &S) { | 172 | fn bar(s: &S) { |
173 | s.f<|> | 173 | s.f$0 |
174 | } | 174 | } |
175 | "#, | 175 | "#, |
176 | r#" | 176 | r#" |
@@ -195,7 +195,7 @@ struct S; | |||
195 | impl S { | 195 | impl S { |
196 | fn foo(&self) {} | 196 | fn foo(&self) {} |
197 | } | 197 | } |
198 | fn main() { S::f<|> } | 198 | fn main() { S::f$0 } |
199 | "#, | 199 | "#, |
200 | r#" | 200 | r#" |
201 | struct S; | 201 | struct S; |
@@ -211,11 +211,11 @@ fn main() { S::foo(${1:&self})$0 } | |||
211 | fn suppress_arg_snippets() { | 211 | fn suppress_arg_snippets() { |
212 | mark::check!(suppress_arg_snippets); | 212 | mark::check!(suppress_arg_snippets); |
213 | check_edit_with_config( | 213 | check_edit_with_config( |
214 | CompletionConfig { add_call_argument_snippets: false, ..CompletionConfig::default() }, | 214 | CompletionConfig { add_call_argument_snippets: false, ..TEST_CONFIG }, |
215 | "with_args", | 215 | "with_args", |
216 | r#" | 216 | r#" |
217 | fn with_args(x: i32, y: String) {} | 217 | fn with_args(x: i32, y: String) {} |
218 | fn main() { with_<|> } | 218 | fn main() { with_$0 } |
219 | "#, | 219 | "#, |
220 | r#" | 220 | r#" |
221 | fn with_args(x: i32, y: String) {} | 221 | fn with_args(x: i32, y: String) {} |
@@ -230,7 +230,7 @@ fn main() { with_args($0) } | |||
230 | "foo", | 230 | "foo", |
231 | r#" | 231 | r#" |
232 | fn foo(_foo: i32, ___bar: bool, ho_ge_: String) {} | 232 | fn foo(_foo: i32, ___bar: bool, ho_ge_: String) {} |
233 | fn main() { f<|> } | 233 | fn main() { f$0 } |
234 | "#, | 234 | "#, |
235 | r#" | 235 | r#" |
236 | fn foo(_foo: i32, ___bar: bool, ho_ge_: String) {} | 236 | fn foo(_foo: i32, ___bar: bool, ho_ge_: String) {} |
@@ -248,7 +248,7 @@ struct Foo {} | |||
248 | fn ref_arg(x: &Foo) {} | 248 | fn ref_arg(x: &Foo) {} |
249 | fn main() { | 249 | fn main() { |
250 | let x = Foo {}; | 250 | let x = Foo {}; |
251 | ref_ar<|> | 251 | ref_ar$0 |
252 | } | 252 | } |
253 | "#, | 253 | "#, |
254 | r#" | 254 | r#" |
@@ -271,7 +271,7 @@ struct Foo {} | |||
271 | fn ref_arg(x: &mut Foo) {} | 271 | fn ref_arg(x: &mut Foo) {} |
272 | fn main() { | 272 | fn main() { |
273 | let x = Foo {}; | 273 | let x = Foo {}; |
274 | ref_ar<|> | 274 | ref_ar$0 |
275 | } | 275 | } |
276 | "#, | 276 | "#, |
277 | r#" | 277 | r#" |
@@ -299,7 +299,7 @@ impl Bar { | |||
299 | fn main() { | 299 | fn main() { |
300 | let x = Foo {}; | 300 | let x = Foo {}; |
301 | let y = Bar {}; | 301 | let y = Bar {}; |
302 | y.<|> | 302 | y.$0 |
303 | } | 303 | } |
304 | "#, | 304 | "#, |
305 | r#" | 305 | r#" |
@@ -326,7 +326,7 @@ fn main() { | |||
326 | fn take_mutably(mut x: &i32) {} | 326 | fn take_mutably(mut x: &i32) {} |
327 | 327 | ||
328 | fn main() { | 328 | fn main() { |
329 | take_m<|> | 329 | take_m$0 |
330 | } | 330 | } |
331 | "#, | 331 | "#, |
332 | r#" | 332 | r#" |
diff --git a/crates/completion/src/render/macro_.rs b/crates/completion/src/render/macro_.rs index 6f4f9945c..f893e420a 100644 --- a/crates/completion/src/render/macro_.rs +++ b/crates/completion/src/render/macro_.rs | |||
@@ -135,7 +135,7 @@ mod tests { | |||
135 | "frobnicate!", | 135 | "frobnicate!", |
136 | r#" | 136 | r#" |
137 | //- /main.rs crate:main deps:foo | 137 | //- /main.rs crate:main deps:foo |
138 | use foo::<|>; | 138 | use foo::$0; |
139 | //- /foo/lib.rs crate:foo | 139 | //- /foo/lib.rs crate:foo |
140 | #[macro_export] | 140 | #[macro_export] |
141 | macro_rules! frobnicate { () => () } | 141 | macro_rules! frobnicate { () => () } |
@@ -149,7 +149,7 @@ use foo::frobnicate; | |||
149 | "frobnicate!", | 149 | "frobnicate!", |
150 | r#" | 150 | r#" |
151 | macro_rules! frobnicate { () => () } | 151 | macro_rules! frobnicate { () => () } |
152 | fn main() { frob<|>!(); } | 152 | fn main() { frob$0!(); } |
153 | "#, | 153 | "#, |
154 | r#" | 154 | r#" |
155 | macro_rules! frobnicate { () => () } | 155 | macro_rules! frobnicate { () => () } |
@@ -173,7 +173,7 @@ fn main() { frobnicate!(); } | |||
173 | /// ``` | 173 | /// ``` |
174 | macro_rules! vec { () => {} } | 174 | macro_rules! vec { () => {} } |
175 | 175 | ||
176 | fn fn main() { v<|> } | 176 | fn fn main() { v$0 } |
177 | "#, | 177 | "#, |
178 | r#" | 178 | r#" |
179 | /// Creates a [`Vec`] containing the arguments. | 179 | /// Creates a [`Vec`] containing the arguments. |
@@ -198,7 +198,7 @@ fn fn main() { vec![$0] } | |||
198 | /// Don't call `fooo!()` `fooo!()`, or `_foo![]` `_foo![]`, | 198 | /// Don't call `fooo!()` `fooo!()`, or `_foo![]` `_foo![]`, |
199 | /// call as `let _=foo! { hello world };` | 199 | /// call as `let _=foo! { hello world };` |
200 | macro_rules! foo { () => {} } | 200 | macro_rules! foo { () => {} } |
201 | fn main() { <|> } | 201 | fn main() { $0 } |
202 | "#, | 202 | "#, |
203 | r#" | 203 | r#" |
204 | /// Foo | 204 | /// Foo |
diff --git a/crates/completion/src/render/pattern.rs b/crates/completion/src/render/pattern.rs index a3b6a3cac..61d8a17e5 100644 --- a/crates/completion/src/render/pattern.rs +++ b/crates/completion/src/render/pattern.rs | |||
@@ -1,12 +1,10 @@ | |||
1 | //! Renderer for patterns. | 1 | //! Renderer for patterns. |
2 | 2 | ||
3 | use hir::{db::HirDatabase, HasAttrs, HasVisibility, Name, StructKind}; | 3 | use hir::{db::HirDatabase, HasAttrs, HasVisibility, Name, StructKind}; |
4 | use ide_db::helpers::SnippetCap; | ||
4 | use itertools::Itertools; | 5 | use itertools::Itertools; |
5 | 6 | ||
6 | use crate::{ | 7 | use crate::{item::CompletionKind, render::RenderContext, CompletionItem, CompletionItemKind}; |
7 | config::SnippetCap, item::CompletionKind, render::RenderContext, CompletionItem, | ||
8 | CompletionItemKind, | ||
9 | }; | ||
10 | 8 | ||
11 | fn visible_fields( | 9 | fn visible_fields( |
12 | ctx: &RenderContext<'_>, | 10 | ctx: &RenderContext<'_>, |
diff --git a/crates/completion/src/test_utils.rs b/crates/completion/src/test_utils.rs index eb0c16f52..3f4b9d4ac 100644 --- a/crates/completion/src/test_utils.rs +++ b/crates/completion/src/test_utils.rs | |||
@@ -1,8 +1,11 @@ | |||
1 | //! Runs completion for testing purposes. | 1 | //! Runs completion for testing purposes. |
2 | 2 | ||
3 | use hir::Semantics; | 3 | use hir::Semantics; |
4 | use ide_db::base_db::{fixture::ChangeFixture, FileLoader, FilePosition}; | 4 | use ide_db::{ |
5 | use ide_db::RootDatabase; | 5 | base_db::{fixture::ChangeFixture, FileLoader, FilePosition}, |
6 | helpers::{insert_use::MergeBehavior, SnippetCap}, | ||
7 | RootDatabase, | ||
8 | }; | ||
6 | use itertools::Itertools; | 9 | use itertools::Itertools; |
7 | use stdx::{format_to, trim_indent}; | 10 | use stdx::{format_to, trim_indent}; |
8 | use syntax::{AstNode, NodeOrToken, SyntaxElement}; | 11 | use syntax::{AstNode, NodeOrToken, SyntaxElement}; |
@@ -10,12 +13,21 @@ use test_utils::{assert_eq_text, RangeOrOffset}; | |||
10 | 13 | ||
11 | use crate::{item::CompletionKind, CompletionConfig, CompletionItem}; | 14 | use crate::{item::CompletionKind, CompletionConfig, CompletionItem}; |
12 | 15 | ||
13 | /// Creates analysis from a multi-file fixture, returns positions marked with <|>. | 16 | pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig { |
17 | enable_postfix_completions: true, | ||
18 | enable_autoimport_completions: true, | ||
19 | add_call_parenthesis: true, | ||
20 | add_call_argument_snippets: true, | ||
21 | snippet_cap: SnippetCap::new(true), | ||
22 | merge: Some(MergeBehavior::Full), | ||
23 | }; | ||
24 | |||
25 | /// Creates analysis from a multi-file fixture, returns positions marked with $0. | ||
14 | pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) { | 26 | pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) { |
15 | let change_fixture = ChangeFixture::parse(ra_fixture); | 27 | let change_fixture = ChangeFixture::parse(ra_fixture); |
16 | let mut database = RootDatabase::default(); | 28 | let mut database = RootDatabase::default(); |
17 | database.apply_change(change_fixture.change); | 29 | database.apply_change(change_fixture.change); |
18 | let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker (<|>)"); | 30 | let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker ($0)"); |
19 | let offset = match range_or_offset { | 31 | let offset = match range_or_offset { |
20 | RangeOrOffset::Range(_) => panic!(), | 32 | RangeOrOffset::Range(_) => panic!(), |
21 | RangeOrOffset::Offset(it) => it, | 33 | RangeOrOffset::Offset(it) => it, |
@@ -24,7 +36,7 @@ pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) { | |||
24 | } | 36 | } |
25 | 37 | ||
26 | pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { | 38 | pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { |
27 | do_completion_with_config(CompletionConfig::default(), code, kind) | 39 | do_completion_with_config(TEST_CONFIG, code, kind) |
28 | } | 40 | } |
29 | 41 | ||
30 | pub(crate) fn do_completion_with_config( | 42 | pub(crate) fn do_completion_with_config( |
@@ -39,7 +51,7 @@ pub(crate) fn do_completion_with_config( | |||
39 | } | 51 | } |
40 | 52 | ||
41 | pub(crate) fn completion_list(code: &str, kind: CompletionKind) -> String { | 53 | pub(crate) fn completion_list(code: &str, kind: CompletionKind) -> String { |
42 | completion_list_with_config(CompletionConfig::default(), code, kind) | 54 | completion_list_with_config(TEST_CONFIG, code, kind) |
43 | } | 55 | } |
44 | 56 | ||
45 | pub(crate) fn completion_list_with_config( | 57 | pub(crate) fn completion_list_with_config( |
@@ -76,7 +88,7 @@ fn monospace_width(s: &str) -> usize { | |||
76 | } | 88 | } |
77 | 89 | ||
78 | pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) { | 90 | pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) { |
79 | check_edit_with_config(CompletionConfig::default(), what, ra_fixture_before, ra_fixture_after) | 91 | check_edit_with_config(TEST_CONFIG, what, ra_fixture_before, ra_fixture_after) |
80 | } | 92 | } |
81 | 93 | ||
82 | pub(crate) fn check_edit_with_config( | 94 | pub(crate) fn check_edit_with_config( |
diff --git a/crates/flycheck/Cargo.toml b/crates/flycheck/Cargo.toml index 3d9436d69..1d19c7886 100644 --- a/crates/flycheck/Cargo.toml +++ b/crates/flycheck/Cargo.toml | |||
@@ -12,8 +12,9 @@ doctest = false | |||
12 | [dependencies] | 12 | [dependencies] |
13 | crossbeam-channel = "0.5.0" | 13 | crossbeam-channel = "0.5.0" |
14 | log = "0.4.8" | 14 | log = "0.4.8" |
15 | cargo_metadata = "=0.12.0" | 15 | cargo_metadata = "0.12.2" |
16 | serde_json = "1.0.48" | 16 | serde_json = "1.0.48" |
17 | jod-thread = "0.1.1" | 17 | jod-thread = "0.1.1" |
18 | 18 | ||
19 | toolchain = { path = "../toolchain", version = "0.0.0" } | 19 | toolchain = { path = "../toolchain", version = "0.0.0" } |
20 | stdx = { path = "../stdx", version = "0.0.0" } | ||
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index d982c5f29..4388e8c67 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs | |||
@@ -5,13 +5,13 @@ | |||
5 | use std::{ | 5 | use std::{ |
6 | fmt, | 6 | fmt, |
7 | io::{self, BufReader}, | 7 | io::{self, BufReader}, |
8 | ops, | ||
9 | path::PathBuf, | 8 | path::PathBuf, |
10 | process::{self, Command, Stdio}, | 9 | process::{self, Command, Stdio}, |
11 | time::Duration, | 10 | time::Duration, |
12 | }; | 11 | }; |
13 | 12 | ||
14 | use crossbeam_channel::{never, select, unbounded, Receiver, Sender}; | 13 | use crossbeam_channel::{never, select, unbounded, Receiver, Sender}; |
14 | use stdx::JodChild; | ||
15 | 15 | ||
16 | pub use cargo_metadata::diagnostic::{ | 16 | pub use cargo_metadata::diagnostic::{ |
17 | Applicability, Diagnostic, DiagnosticCode, DiagnosticLevel, DiagnosticSpan, | 17 | Applicability, Diagnostic, DiagnosticCode, DiagnosticLevel, DiagnosticSpan, |
@@ -323,24 +323,3 @@ impl CargoActor { | |||
323 | Ok(read_at_least_one_message) | 323 | Ok(read_at_least_one_message) |
324 | } | 324 | } |
325 | } | 325 | } |
326 | |||
327 | struct JodChild(process::Child); | ||
328 | |||
329 | impl ops::Deref for JodChild { | ||
330 | type Target = process::Child; | ||
331 | fn deref(&self) -> &process::Child { | ||
332 | &self.0 | ||
333 | } | ||
334 | } | ||
335 | |||
336 | impl ops::DerefMut for JodChild { | ||
337 | fn deref_mut(&mut self) -> &mut process::Child { | ||
338 | &mut self.0 | ||
339 | } | ||
340 | } | ||
341 | |||
342 | impl Drop for JodChild { | ||
343 | fn drop(&mut self) { | ||
344 | let _ = self.0.kill(); | ||
345 | } | ||
346 | } | ||
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index cc1938333..6cbf5cecf 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -1263,6 +1263,24 @@ pub enum GenericParam { | |||
1263 | } | 1263 | } |
1264 | impl_from!(TypeParam, LifetimeParam, ConstParam for GenericParam); | 1264 | impl_from!(TypeParam, LifetimeParam, ConstParam for GenericParam); |
1265 | 1265 | ||
1266 | impl GenericParam { | ||
1267 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
1268 | match self { | ||
1269 | GenericParam::TypeParam(it) => it.module(db), | ||
1270 | GenericParam::LifetimeParam(it) => it.module(db), | ||
1271 | GenericParam::ConstParam(it) => it.module(db), | ||
1272 | } | ||
1273 | } | ||
1274 | |||
1275 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
1276 | match self { | ||
1277 | GenericParam::TypeParam(it) => it.name(db), | ||
1278 | GenericParam::LifetimeParam(it) => it.name(db), | ||
1279 | GenericParam::ConstParam(it) => it.name(db), | ||
1280 | } | ||
1281 | } | ||
1282 | } | ||
1283 | |||
1266 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 1284 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
1267 | pub struct TypeParam { | 1285 | pub struct TypeParam { |
1268 | pub(crate) id: TypeParamId, | 1286 | pub(crate) id: TypeParamId, |
diff --git a/crates/hir/src/db.rs b/crates/hir/src/db.rs index d01e1b33d..d5d4cf5b6 100644 --- a/crates/hir/src/db.rs +++ b/crates/hir/src/db.rs | |||
@@ -10,8 +10,8 @@ pub use hir_def::db::{ | |||
10 | TypeAliasDataQuery, UnionDataQuery, | 10 | TypeAliasDataQuery, UnionDataQuery, |
11 | }; | 11 | }; |
12 | pub use hir_expand::db::{ | 12 | pub use hir_expand::db::{ |
13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery, | 13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, HygieneFrameQuery, InternEagerExpansionQuery, |
14 | MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroExpansionQuery, | 14 | InternMacroQuery, MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroExpansionQuery, |
15 | }; | 15 | }; |
16 | pub use hir_ty::db::*; | 16 | pub use hir_ty::db::*; |
17 | 17 | ||
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index b1c924167..447faa04f 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs | |||
@@ -4,6 +4,6 @@ pub use hir_expand::diagnostics::{ | |||
4 | Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder, | 4 | Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder, |
5 | }; | 5 | }; |
6 | pub use hir_ty::diagnostics::{ | 6 | pub use hir_ty::diagnostics::{ |
7 | IncorrectCase, MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, | 7 | IncorrectCase, MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr, |
8 | NoSuchField, RemoveThisSemicolon, | 8 | NoSuchField, RemoveThisSemicolon, |
9 | }; | 9 | }; |
diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs index 3e47a5e9d..c8c5fecd7 100644 --- a/crates/hir/src/from_id.rs +++ b/crates/hir/src/from_id.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! Utility module for converting between hir_def ids and code_model wrappers. | 1 | //! Utility module for converting between hir_def ids and code_model wrappers. |
2 | //! | 2 | //! |
3 | //! It's unclear if we need this long-term, but it's definitelly useful while we | 3 | //! It's unclear if we need this long-term, but it's definitely useful while we |
4 | //! are splitting the hir. | 4 | //! are splitting the hir. |
5 | 5 | ||
6 | use hir_def::{ | 6 | use hir_def::{ |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 6be1eaade..3dc33f248 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -581,7 +581,7 @@ impl ExprCollector<'_> { | |||
581 | match res.value { | 581 | match res.value { |
582 | Some((mark, expansion)) => { | 582 | Some((mark, expansion)) => { |
583 | // FIXME: Statements are too complicated to recover from error for now. | 583 | // FIXME: Statements are too complicated to recover from error for now. |
584 | // It is because we don't have any hygenine for local variable expansion right now. | 584 | // It is because we don't have any hygiene for local variable expansion right now. |
585 | if T::can_cast(syntax::SyntaxKind::MACRO_STMTS) && res.err.is_some() { | 585 | if T::can_cast(syntax::SyntaxKind::MACRO_STMTS) && res.err.is_some() { |
586 | self.expander.exit(self.db, mark); | 586 | self.expander.exit(self.db, mark); |
587 | collector(self, None); | 587 | collector(self, None); |
@@ -959,7 +959,7 @@ impl ExprCollector<'_> { | |||
959 | 959 | ||
960 | fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Vec<PatId>, Option<usize>) { | 960 | fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Vec<PatId>, Option<usize>) { |
961 | // Find the location of the `..`, if there is one. Note that we do not | 961 | // Find the location of the `..`, if there is one. Note that we do not |
962 | // consider the possiblity of there being multiple `..` here. | 962 | // consider the possibility of there being multiple `..` here. |
963 | let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::RestPat(_))); | 963 | let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::RestPat(_))); |
964 | // We want to skip the `..` pattern here, since we account for it above. | 964 | // We want to skip the `..` pattern here, since we account for it above. |
965 | let args = args | 965 | let args = args |
diff --git a/crates/hir_def/src/body/scope.rs b/crates/hir_def/src/body/scope.rs index 9142bc05b..065785da7 100644 --- a/crates/hir_def/src/body/scope.rs +++ b/crates/hir_def/src/body/scope.rs | |||
@@ -194,7 +194,7 @@ mod tests { | |||
194 | let mut buf = String::new(); | 194 | let mut buf = String::new(); |
195 | let off: usize = offset.into(); | 195 | let off: usize = offset.into(); |
196 | buf.push_str(&code[..off]); | 196 | buf.push_str(&code[..off]); |
197 | buf.push_str("<|>marker"); | 197 | buf.push_str("$0marker"); |
198 | buf.push_str(&code[off..]); | 198 | buf.push_str(&code[off..]); |
199 | buf | 199 | buf |
200 | }; | 200 | }; |
@@ -231,7 +231,7 @@ mod tests { | |||
231 | r" | 231 | r" |
232 | fn quux(foo: i32) { | 232 | fn quux(foo: i32) { |
233 | let f = |bar, baz: i32| { | 233 | let f = |bar, baz: i32| { |
234 | <|> | 234 | $0 |
235 | }; | 235 | }; |
236 | }", | 236 | }", |
237 | &["bar", "baz", "foo"], | 237 | &["bar", "baz", "foo"], |
@@ -243,7 +243,7 @@ mod tests { | |||
243 | do_check( | 243 | do_check( |
244 | r" | 244 | r" |
245 | fn quux() { | 245 | fn quux() { |
246 | f(|x| <|> ); | 246 | f(|x| $0 ); |
247 | }", | 247 | }", |
248 | &["x"], | 248 | &["x"], |
249 | ); | 249 | ); |
@@ -254,7 +254,7 @@ mod tests { | |||
254 | do_check( | 254 | do_check( |
255 | r" | 255 | r" |
256 | fn quux() { | 256 | fn quux() { |
257 | z.f(|x| <|> ); | 257 | z.f(|x| $0 ); |
258 | }", | 258 | }", |
259 | &["x"], | 259 | &["x"], |
260 | ); | 260 | ); |
@@ -267,7 +267,7 @@ mod tests { | |||
267 | fn quux() { | 267 | fn quux() { |
268 | loop { | 268 | loop { |
269 | let x = (); | 269 | let x = (); |
270 | <|> | 270 | $0 |
271 | }; | 271 | }; |
272 | }", | 272 | }", |
273 | &["x"], | 273 | &["x"], |
@@ -281,7 +281,7 @@ mod tests { | |||
281 | fn quux() { | 281 | fn quux() { |
282 | match () { | 282 | match () { |
283 | Some(x) => { | 283 | Some(x) => { |
284 | <|> | 284 | $0 |
285 | } | 285 | } |
286 | }; | 286 | }; |
287 | }", | 287 | }", |
@@ -294,7 +294,7 @@ mod tests { | |||
294 | do_check( | 294 | do_check( |
295 | r" | 295 | r" |
296 | fn foo(x: String) { | 296 | fn foo(x: String) { |
297 | let x : &str = &x<|>; | 297 | let x : &str = &x$0; |
298 | }", | 298 | }", |
299 | &["x"], | 299 | &["x"], |
300 | ); | 300 | ); |
@@ -307,7 +307,7 @@ mod tests { | |||
307 | fn foo() { | 307 | fn foo() { |
308 | match Some(()) { | 308 | match Some(()) { |
309 | opt @ Some(unit) => { | 309 | opt @ Some(unit) => { |
310 | <|> | 310 | $0 |
311 | } | 311 | } |
312 | _ => {} | 312 | _ => {} |
313 | } | 313 | } |
@@ -330,7 +330,7 @@ fn foo() { | |||
330 | 330 | ||
331 | fn foo() { | 331 | fn foo() { |
332 | mac!(); | 332 | mac!(); |
333 | <|> | 333 | $0 |
334 | } | 334 | } |
335 | ", | 335 | ", |
336 | &[], | 336 | &[], |
@@ -343,7 +343,7 @@ fn foo() { | |||
343 | r" | 343 | r" |
344 | fn foo() { | 344 | fn foo() { |
345 | trait {} | 345 | trait {} |
346 | <|> | 346 | $0 |
347 | } | 347 | } |
348 | ", | 348 | ", |
349 | &[], | 349 | &[], |
@@ -391,7 +391,7 @@ fn foo(x: i32, y: u32) { | |||
391 | let z = x * 2; | 391 | let z = x * 2; |
392 | } | 392 | } |
393 | { | 393 | { |
394 | let t = x<|> * 3; | 394 | let t = x$0 * 3; |
395 | } | 395 | } |
396 | } | 396 | } |
397 | "#, | 397 | "#, |
@@ -404,7 +404,7 @@ fn foo(x: i32, y: u32) { | |||
404 | do_check_local_name( | 404 | do_check_local_name( |
405 | r#" | 405 | r#" |
406 | fn foo(x: String) { | 406 | fn foo(x: String) { |
407 | let x : &str = &x<|>; | 407 | let x : &str = &x$0; |
408 | } | 408 | } |
409 | "#, | 409 | "#, |
410 | 7, | 410 | 7, |
@@ -417,7 +417,7 @@ fn foo(x: String) { | |||
417 | r" | 417 | r" |
418 | fn foo(x: String) { | 418 | fn foo(x: String) { |
419 | let x : &str = &x; | 419 | let x : &str = &x; |
420 | x<|> | 420 | x$0 |
421 | } | 421 | } |
422 | ", | 422 | ", |
423 | 28, | 423 | 28, |
@@ -430,7 +430,7 @@ fn foo(x: String) { | |||
430 | r" | 430 | r" |
431 | fn foo() { | 431 | fn foo() { |
432 | if let Some(&from) = bar() { | 432 | if let Some(&from) = bar() { |
433 | from<|>; | 433 | from$0; |
434 | } | 434 | } |
435 | } | 435 | } |
436 | ", | 436 | ", |
@@ -446,7 +446,7 @@ fn foo() { | |||
446 | fn test() { | 446 | fn test() { |
447 | let foo: Option<f32> = None; | 447 | let foo: Option<f32> = None; |
448 | while let Option::Some(spam) = foo { | 448 | while let Option::Some(spam) = foo { |
449 | spam<|> | 449 | spam$0 |
450 | } | 450 | } |
451 | } | 451 | } |
452 | "#, | 452 | "#, |
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs index 6a481769d..76f5721e5 100644 --- a/crates/hir_def/src/expr.rs +++ b/crates/hir_def/src/expr.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! This module describes hir-level representation of expressions. | 1 | //! This module describes hir-level representation of expressions. |
2 | //! | 2 | //! |
3 | //! This representaion is: | 3 | //! This representation is: |
4 | //! | 4 | //! |
5 | //! 1. Identity-based. Each expression has an `id`, so we can distinguish | 5 | //! 1. Identity-based. Each expression has an `id`, so we can distinguish |
6 | //! between different `1` in `1 + 1`. | 6 | //! between different `1` in `1 + 1`. |
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index 02613c4c4..4a212d291 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs | |||
@@ -410,7 +410,7 @@ mod tests { | |||
410 | let code = r#" | 410 | let code = r#" |
411 | //- /main.rs | 411 | //- /main.rs |
412 | struct S; | 412 | struct S; |
413 | <|> | 413 | $0 |
414 | "#; | 414 | "#; |
415 | check_found_path(code, "S", "S", "crate::S", "self::S"); | 415 | check_found_path(code, "S", "S", "crate::S", "self::S"); |
416 | } | 416 | } |
@@ -420,7 +420,7 @@ mod tests { | |||
420 | let code = r#" | 420 | let code = r#" |
421 | //- /main.rs | 421 | //- /main.rs |
422 | enum E { A } | 422 | enum E { A } |
423 | <|> | 423 | $0 |
424 | "#; | 424 | "#; |
425 | check_found_path(code, "E::A", "E::A", "E::A", "E::A"); | 425 | check_found_path(code, "E::A", "E::A", "E::A", "E::A"); |
426 | } | 426 | } |
@@ -432,7 +432,7 @@ mod tests { | |||
432 | mod foo { | 432 | mod foo { |
433 | pub struct S; | 433 | pub struct S; |
434 | } | 434 | } |
435 | <|> | 435 | $0 |
436 | "#; | 436 | "#; |
437 | check_found_path(code, "foo::S", "foo::S", "crate::foo::S", "self::foo::S"); | 437 | check_found_path(code, "foo::S", "foo::S", "crate::foo::S", "self::foo::S"); |
438 | } | 438 | } |
@@ -446,7 +446,7 @@ mod tests { | |||
446 | mod bar; | 446 | mod bar; |
447 | struct S; | 447 | struct S; |
448 | //- /foo/bar.rs | 448 | //- /foo/bar.rs |
449 | <|> | 449 | $0 |
450 | "#; | 450 | "#; |
451 | check_found_path(code, "super::S", "super::S", "crate::foo::S", "super::S"); | 451 | check_found_path(code, "super::S", "super::S", "crate::foo::S", "super::S"); |
452 | } | 452 | } |
@@ -457,7 +457,7 @@ mod tests { | |||
457 | //- /main.rs | 457 | //- /main.rs |
458 | mod foo; | 458 | mod foo; |
459 | //- /foo.rs | 459 | //- /foo.rs |
460 | <|> | 460 | $0 |
461 | "#; | 461 | "#; |
462 | check_found_path(code, "self", "self", "crate::foo", "self"); | 462 | check_found_path(code, "self", "self", "crate::foo", "self"); |
463 | } | 463 | } |
@@ -468,7 +468,7 @@ mod tests { | |||
468 | //- /main.rs | 468 | //- /main.rs |
469 | mod foo; | 469 | mod foo; |
470 | //- /foo.rs | 470 | //- /foo.rs |
471 | <|> | 471 | $0 |
472 | "#; | 472 | "#; |
473 | check_found_path(code, "crate", "crate", "crate", "crate"); | 473 | check_found_path(code, "crate", "crate", "crate", "crate"); |
474 | } | 474 | } |
@@ -480,7 +480,7 @@ mod tests { | |||
480 | mod foo; | 480 | mod foo; |
481 | struct S; | 481 | struct S; |
482 | //- /foo.rs | 482 | //- /foo.rs |
483 | <|> | 483 | $0 |
484 | "#; | 484 | "#; |
485 | check_found_path(code, "crate::S", "crate::S", "crate::S", "crate::S"); | 485 | check_found_path(code, "crate::S", "crate::S", "crate::S", "crate::S"); |
486 | } | 486 | } |
@@ -489,7 +489,7 @@ mod tests { | |||
489 | fn different_crate() { | 489 | fn different_crate() { |
490 | let code = r#" | 490 | let code = r#" |
491 | //- /main.rs crate:main deps:std | 491 | //- /main.rs crate:main deps:std |
492 | <|> | 492 | $0 |
493 | //- /std.rs crate:std | 493 | //- /std.rs crate:std |
494 | pub struct S; | 494 | pub struct S; |
495 | "#; | 495 | "#; |
@@ -501,7 +501,7 @@ mod tests { | |||
501 | let code = r#" | 501 | let code = r#" |
502 | //- /main.rs crate:main deps:std | 502 | //- /main.rs crate:main deps:std |
503 | extern crate std as std_renamed; | 503 | extern crate std as std_renamed; |
504 | <|> | 504 | $0 |
505 | //- /std.rs crate:std | 505 | //- /std.rs crate:std |
506 | pub struct S; | 506 | pub struct S; |
507 | "#; | 507 | "#; |
@@ -523,7 +523,7 @@ mod tests { | |||
523 | //- /main.rs crate:main deps:syntax | 523 | //- /main.rs crate:main deps:syntax |
524 | 524 | ||
525 | use syntax::ast; | 525 | use syntax::ast; |
526 | <|> | 526 | $0 |
527 | 527 | ||
528 | //- /lib.rs crate:syntax | 528 | //- /lib.rs crate:syntax |
529 | pub mod ast { | 529 | pub mod ast { |
@@ -543,7 +543,7 @@ mod tests { | |||
543 | let code = r#" | 543 | let code = r#" |
544 | //- /main.rs crate:main deps:syntax | 544 | //- /main.rs crate:main deps:syntax |
545 | 545 | ||
546 | <|> | 546 | $0 |
547 | 547 | ||
548 | //- /lib.rs crate:syntax | 548 | //- /lib.rs crate:syntax |
549 | pub mod ast { | 549 | pub mod ast { |
@@ -569,7 +569,7 @@ mod tests { | |||
569 | mod foo { pub(super) struct S; } | 569 | mod foo { pub(super) struct S; } |
570 | pub(crate) use foo::*; | 570 | pub(crate) use foo::*; |
571 | } | 571 | } |
572 | <|> | 572 | $0 |
573 | "#; | 573 | "#; |
574 | check_found_path(code, "bar::S", "bar::S", "crate::bar::S", "self::bar::S"); | 574 | check_found_path(code, "bar::S", "bar::S", "crate::bar::S", "self::bar::S"); |
575 | } | 575 | } |
@@ -582,7 +582,7 @@ mod tests { | |||
582 | mod foo { pub(super) struct S; } | 582 | mod foo { pub(super) struct S; } |
583 | pub(crate) use foo::S as U; | 583 | pub(crate) use foo::S as U; |
584 | } | 584 | } |
585 | <|> | 585 | $0 |
586 | "#; | 586 | "#; |
587 | check_found_path(code, "bar::U", "bar::U", "crate::bar::U", "self::bar::U"); | 587 | check_found_path(code, "bar::U", "bar::U", "crate::bar::U", "self::bar::U"); |
588 | } | 588 | } |
@@ -591,7 +591,7 @@ mod tests { | |||
591 | fn different_crate_reexport() { | 591 | fn different_crate_reexport() { |
592 | let code = r#" | 592 | let code = r#" |
593 | //- /main.rs crate:main deps:std | 593 | //- /main.rs crate:main deps:std |
594 | <|> | 594 | $0 |
595 | //- /std.rs crate:std deps:core | 595 | //- /std.rs crate:std deps:core |
596 | pub use core::S; | 596 | pub use core::S; |
597 | //- /core.rs crate:core | 597 | //- /core.rs crate:core |
@@ -604,7 +604,7 @@ mod tests { | |||
604 | fn prelude() { | 604 | fn prelude() { |
605 | let code = r#" | 605 | let code = r#" |
606 | //- /main.rs crate:main deps:std | 606 | //- /main.rs crate:main deps:std |
607 | <|> | 607 | $0 |
608 | //- /std.rs crate:std | 608 | //- /std.rs crate:std |
609 | pub mod prelude { pub struct S; } | 609 | pub mod prelude { pub struct S; } |
610 | #[prelude_import] | 610 | #[prelude_import] |
@@ -617,7 +617,7 @@ mod tests { | |||
617 | fn enum_variant_from_prelude() { | 617 | fn enum_variant_from_prelude() { |
618 | let code = r#" | 618 | let code = r#" |
619 | //- /main.rs crate:main deps:std | 619 | //- /main.rs crate:main deps:std |
620 | <|> | 620 | $0 |
621 | //- /std.rs crate:std | 621 | //- /std.rs crate:std |
622 | pub mod prelude { | 622 | pub mod prelude { |
623 | pub enum Option<T> { Some(T), None } | 623 | pub enum Option<T> { Some(T), None } |
@@ -637,7 +637,7 @@ mod tests { | |||
637 | pub mod foo; | 637 | pub mod foo; |
638 | pub mod baz; | 638 | pub mod baz; |
639 | struct S; | 639 | struct S; |
640 | <|> | 640 | $0 |
641 | //- /foo.rs | 641 | //- /foo.rs |
642 | pub mod bar { pub struct S; } | 642 | pub mod bar { pub struct S; } |
643 | //- /baz.rs | 643 | //- /baz.rs |
@@ -654,7 +654,7 @@ mod tests { | |||
654 | pub mod bar { pub struct S; } | 654 | pub mod bar { pub struct S; } |
655 | use bar::S; | 655 | use bar::S; |
656 | //- /foo.rs | 656 | //- /foo.rs |
657 | <|> | 657 | $0 |
658 | "#; | 658 | "#; |
659 | // crate::S would be shorter, but using private imports seems wrong | 659 | // crate::S would be shorter, but using private imports seems wrong |
660 | check_found_path(code, "crate::bar::S", "crate::bar::S", "crate::bar::S", "crate::bar::S"); | 660 | check_found_path(code, "crate::bar::S", "crate::bar::S", "crate::bar::S", "crate::bar::S"); |
@@ -668,7 +668,7 @@ mod tests { | |||
668 | pub mod bar; | 668 | pub mod bar; |
669 | pub mod baz; | 669 | pub mod baz; |
670 | //- /bar.rs | 670 | //- /bar.rs |
671 | <|> | 671 | $0 |
672 | //- /foo.rs | 672 | //- /foo.rs |
673 | pub use super::baz; | 673 | pub use super::baz; |
674 | pub struct S; | 674 | pub struct S; |
@@ -683,7 +683,7 @@ mod tests { | |||
683 | mark::check!(prefer_std_paths); | 683 | mark::check!(prefer_std_paths); |
684 | let code = r#" | 684 | let code = r#" |
685 | //- /main.rs crate:main deps:alloc,std | 685 | //- /main.rs crate:main deps:alloc,std |
686 | <|> | 686 | $0 |
687 | 687 | ||
688 | //- /std.rs crate:std deps:alloc | 688 | //- /std.rs crate:std deps:alloc |
689 | pub mod sync { | 689 | pub mod sync { |
@@ -711,7 +711,7 @@ mod tests { | |||
711 | //- /main.rs crate:main deps:core,std | 711 | //- /main.rs crate:main deps:core,std |
712 | #![no_std] | 712 | #![no_std] |
713 | 713 | ||
714 | <|> | 714 | $0 |
715 | 715 | ||
716 | //- /std.rs crate:std deps:core | 716 | //- /std.rs crate:std deps:core |
717 | 717 | ||
@@ -740,7 +740,7 @@ mod tests { | |||
740 | //- /main.rs crate:main deps:alloc,std | 740 | //- /main.rs crate:main deps:alloc,std |
741 | #![no_std] | 741 | #![no_std] |
742 | 742 | ||
743 | <|> | 743 | $0 |
744 | 744 | ||
745 | //- /std.rs crate:std deps:alloc | 745 | //- /std.rs crate:std deps:alloc |
746 | 746 | ||
@@ -767,7 +767,7 @@ mod tests { | |||
767 | fn prefer_shorter_paths_if_not_alloc() { | 767 | fn prefer_shorter_paths_if_not_alloc() { |
768 | let code = r#" | 768 | let code = r#" |
769 | //- /main.rs crate:main deps:megaalloc,std | 769 | //- /main.rs crate:main deps:megaalloc,std |
770 | <|> | 770 | $0 |
771 | 771 | ||
772 | //- /std.rs crate:std deps:megaalloc | 772 | //- /std.rs crate:std deps:megaalloc |
773 | pub mod sync { | 773 | pub mod sync { |
@@ -790,7 +790,7 @@ mod tests { | |||
790 | fn builtins_are_in_scope() { | 790 | fn builtins_are_in_scope() { |
791 | let code = r#" | 791 | let code = r#" |
792 | //- /main.rs | 792 | //- /main.rs |
793 | <|> | 793 | $0 |
794 | 794 | ||
795 | pub mod primitive { | 795 | pub mod primitive { |
796 | pub use u8; | 796 | pub use u8; |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 77017e4ea..f027fd48d 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -267,7 +267,7 @@ impl DefCollector<'_> { | |||
267 | 267 | ||
268 | // Resolve all indeterminate resolved imports again | 268 | // Resolve all indeterminate resolved imports again |
269 | // As some of the macros will expand newly import shadowing partial resolved imports | 269 | // As some of the macros will expand newly import shadowing partial resolved imports |
270 | // FIXME: We maybe could skip this, if we handle the Indetermine imports in `resolve_imports` | 270 | // FIXME: We maybe could skip this, if we handle the indeterminate imports in `resolve_imports` |
271 | // correctly | 271 | // correctly |
272 | let partial_resolved = self.resolved_imports.iter().filter_map(|directive| { | 272 | let partial_resolved = self.resolved_imports.iter().filter_map(|directive| { |
273 | if let PartialResolvedImport::Indeterminate(_) = directive.status { | 273 | if let PartialResolvedImport::Indeterminate(_) = directive.status { |
@@ -402,7 +402,7 @@ impl DefCollector<'_> { | |||
402 | 402 | ||
403 | /// Define a proc macro | 403 | /// Define a proc macro |
404 | /// | 404 | /// |
405 | /// A proc macro is similar to normal macro scope, but it would not visiable in legacy textual scoped. | 405 | /// A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped. |
406 | /// And unconditionally exported. | 406 | /// And unconditionally exported. |
407 | fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { | 407 | fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { |
408 | self.update( | 408 | self.update( |
@@ -592,7 +592,7 @@ impl DefCollector<'_> { | |||
592 | // XXX: urgh, so this works by accident! Here, we look at | 592 | // XXX: urgh, so this works by accident! Here, we look at |
593 | // the enum data, and, in theory, this might require us to | 593 | // the enum data, and, in theory, this might require us to |
594 | // look back at the crate_def_map, creating a cycle. For | 594 | // look back at the crate_def_map, creating a cycle. For |
595 | // example, `enum E { crate::some_macro!(); }`. Luckely, the | 595 | // example, `enum E { crate::some_macro!(); }`. Luckily, the |
596 | // only kind of macro that is allowed inside enum is a | 596 | // only kind of macro that is allowed inside enum is a |
597 | // `cfg_macro`, and we don't need to run name resolution for | 597 | // `cfg_macro`, and we don't need to run name resolution for |
598 | // it, but this is sheer luck! | 598 | // it, but this is sheer luck! |
@@ -655,7 +655,7 @@ impl DefCollector<'_> { | |||
655 | &mut self, | 655 | &mut self, |
656 | module_id: LocalModuleId, | 656 | module_id: LocalModuleId, |
657 | resolutions: &[(Option<Name>, PerNs)], | 657 | resolutions: &[(Option<Name>, PerNs)], |
658 | // All resolutions are imported with this visibility; the visibilies in | 658 | // All resolutions are imported with this visibility; the visibilities in |
659 | // the `PerNs` values are ignored and overwritten | 659 | // the `PerNs` values are ignored and overwritten |
660 | vis: Visibility, | 660 | vis: Visibility, |
661 | import_type: ImportType, | 661 | import_type: ImportType, |
diff --git a/crates/hir_def/src/nameres/tests/incremental.rs b/crates/hir_def/src/nameres/tests/incremental.rs index 8981fa7c9..509e1bbbc 100644 --- a/crates/hir_def/src/nameres/tests/incremental.rs +++ b/crates/hir_def/src/nameres/tests/incremental.rs | |||
@@ -28,7 +28,7 @@ fn typing_inside_a_function_should_not_invalidate_def_map() { | |||
28 | check_def_map_is_not_recomputed( | 28 | check_def_map_is_not_recomputed( |
29 | r" | 29 | r" |
30 | //- /lib.rs | 30 | //- /lib.rs |
31 | mod foo;<|> | 31 | mod foo;$0 |
32 | 32 | ||
33 | use crate::foo::bar::Baz; | 33 | use crate::foo::bar::Baz; |
34 | 34 | ||
@@ -81,7 +81,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { | |||
81 | pub mod bar; | 81 | pub mod bar; |
82 | 82 | ||
83 | //- /foo/bar.rs | 83 | //- /foo/bar.rs |
84 | <|> | 84 | $0 |
85 | m!(X); | 85 | m!(X); |
86 | ", | 86 | ", |
87 | ); | 87 | ); |
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index e2bf85bbc..3dd7c3cbb 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs | |||
@@ -305,6 +305,7 @@ pub use hir_expand::name as __name; | |||
305 | macro_rules! __known_path { | 305 | macro_rules! __known_path { |
306 | (core::iter::IntoIterator) => {}; | 306 | (core::iter::IntoIterator) => {}; |
307 | (core::result::Result) => {}; | 307 | (core::result::Result) => {}; |
308 | (core::option::Option) => {}; | ||
308 | (core::ops::Range) => {}; | 309 | (core::ops::Range) => {}; |
309 | (core::ops::RangeFrom) => {}; | 310 | (core::ops::RangeFrom) => {}; |
310 | (core::ops::RangeFull) => {}; | 311 | (core::ops::RangeFull) => {}; |
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index 8a01e6eea..9518ac109 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs | |||
@@ -123,7 +123,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
123 | // We follow what it did anyway :) | 123 | // We follow what it did anyway :) |
124 | if segments.len() == 1 && kind == PathKind::Plain { | 124 | if segments.len() == 1 && kind == PathKind::Plain { |
125 | if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) { | 125 | if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) { |
126 | if let Some(crate_id) = hygiene.local_inner_macros() { | 126 | if let Some(crate_id) = hygiene.local_inner_macros(path) { |
127 | kind = PathKind::DollarCrate(crate_id); | 127 | kind = PathKind::DollarCrate(crate_id); |
128 | } | 128 | } |
129 | } | 129 | } |
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index 129f1dbac..e4152a0be 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs | |||
@@ -27,7 +27,7 @@ use crate::{ | |||
27 | 27 | ||
28 | #[derive(Debug, Clone, Default)] | 28 | #[derive(Debug, Clone, Default)] |
29 | pub struct Resolver { | 29 | pub struct Resolver { |
30 | // FIXME: all usages generally call `.rev`, so maybe reverse once in consturciton? | 30 | // FIXME: all usages generally call `.rev`, so maybe reverse once in construction? |
31 | scopes: Vec<Scope>, | 31 | scopes: Vec<Scope>, |
32 | } | 32 | } |
33 | 33 | ||
diff --git a/crates/hir_expand/src/builtin_derive.rs b/crates/hir_expand/src/builtin_derive.rs index ad378762a..eb257579f 100644 --- a/crates/hir_expand/src/builtin_derive.rs +++ b/crates/hir_expand/src/builtin_derive.rs | |||
@@ -277,7 +277,7 @@ mod tests { | |||
277 | let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap(); | 277 | let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap(); |
278 | let fixture = format!( | 278 | let fixture = format!( |
279 | r#"//- /main.rs crate:main deps:core | 279 | r#"//- /main.rs crate:main deps:core |
280 | <|> | 280 | $0 |
281 | {} | 281 | {} |
282 | //- /lib.rs crate:core | 282 | //- /lib.rs crate:core |
283 | // empty | 283 | // empty |
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index 0a0d021e0..c62086390 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -8,9 +8,9 @@ use parser::FragmentKind; | |||
8 | use syntax::{algo::diff, ast::NameOwner, AstNode, GreenNode, Parse, SyntaxKind::*, SyntaxNode}; | 8 | use syntax::{algo::diff, ast::NameOwner, AstNode, GreenNode, Parse, SyntaxKind::*, SyntaxNode}; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallLoc, EagerMacroId, | 11 | ast_id_map::AstIdMap, hygiene::HygieneFrame, BuiltinDeriveExpander, BuiltinFnLikeExpander, |
12 | HirFileId, HirFileIdRepr, LazyMacroId, MacroCallId, MacroCallLoc, MacroDefId, MacroDefKind, | 12 | EagerCallLoc, EagerMacroId, HirFileId, HirFileIdRepr, LazyMacroId, MacroCallId, MacroCallLoc, |
13 | MacroFile, ProcMacroExpander, | 13 | MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | /// Total limit on the number of tokens produced by any macro invocation. | 16 | /// Total limit on the number of tokens produced by any macro invocation. |
@@ -40,7 +40,7 @@ impl TokenExpander { | |||
40 | // FIXME switch these to ExpandResult as well | 40 | // FIXME switch these to ExpandResult as well |
41 | TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), | 41 | TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), |
42 | TokenExpander::ProcMacro(_) => { | 42 | TokenExpander::ProcMacro(_) => { |
43 | // We store the result in salsa db to prevent non-determinisc behavior in | 43 | // We store the result in salsa db to prevent non-deterministic behavior in |
44 | // some proc-macro implementation | 44 | // some proc-macro implementation |
45 | // See #4315 for details | 45 | // See #4315 for details |
46 | db.expand_proc_macro(id.into()).into() | 46 | db.expand_proc_macro(id.into()).into() |
@@ -94,6 +94,8 @@ pub trait AstDatabase: SourceDatabase { | |||
94 | fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId; | 94 | fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId; |
95 | 95 | ||
96 | fn expand_proc_macro(&self, call: MacroCallId) -> Result<tt::Subtree, mbe::ExpandError>; | 96 | fn expand_proc_macro(&self, call: MacroCallId) -> Result<tt::Subtree, mbe::ExpandError>; |
97 | |||
98 | fn hygiene_frame(&self, file_id: HirFileId) -> Arc<HygieneFrame>; | ||
97 | } | 99 | } |
98 | 100 | ||
99 | /// This expands the given macro call, but with different arguments. This is | 101 | /// This expands the given macro call, but with different arguments. This is |
@@ -369,6 +371,10 @@ fn parse_macro_with_arg( | |||
369 | } | 371 | } |
370 | } | 372 | } |
371 | 373 | ||
374 | fn hygiene_frame(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<HygieneFrame> { | ||
375 | Arc::new(HygieneFrame::new(db, file_id)) | ||
376 | } | ||
377 | |||
372 | /// Given a `MacroCallId`, return what `FragmentKind` it belongs to. | 378 | /// Given a `MacroCallId`, return what `FragmentKind` it belongs to. |
373 | /// FIXME: Not completed | 379 | /// FIXME: Not completed |
374 | fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind { | 380 | fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind { |
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs index 7ab0a5e52..8db581b77 100644 --- a/crates/hir_expand/src/hygiene.rs +++ b/crates/hir_expand/src/hygiene.rs | |||
@@ -2,65 +2,209 @@ | |||
2 | //! | 2 | //! |
3 | //! Specifically, `ast` + `Hygiene` allows you to create a `Name`. Note that, at | 3 | //! Specifically, `ast` + `Hygiene` allows you to create a `Name`. Note that, at |
4 | //! this moment, this is horribly incomplete and handles only `$crate`. | 4 | //! this moment, this is horribly incomplete and handles only `$crate`. |
5 | use std::sync::Arc; | ||
6 | |||
5 | use base_db::CrateId; | 7 | use base_db::CrateId; |
6 | use either::Either; | 8 | use either::Either; |
7 | use syntax::ast; | 9 | use mbe::Origin; |
10 | use parser::SyntaxKind; | ||
11 | use syntax::{ast, AstNode, SyntaxNode, TextRange, TextSize}; | ||
8 | 12 | ||
9 | use crate::{ | 13 | use crate::{ |
10 | db::AstDatabase, | 14 | db::{self, AstDatabase}, |
11 | name::{AsName, Name}, | 15 | name::{AsName, Name}, |
12 | HirFileId, HirFileIdRepr, MacroCallId, MacroDefKind, | 16 | HirFileId, HirFileIdRepr, InFile, MacroCallId, MacroCallLoc, MacroDefKind, MacroFile, |
13 | }; | 17 | }; |
14 | 18 | ||
15 | #[derive(Clone, Debug)] | 19 | #[derive(Clone, Debug)] |
16 | pub struct Hygiene { | 20 | pub struct Hygiene { |
17 | // This is what `$crate` expands to | 21 | frames: Option<HygieneFrames>, |
18 | def_crate: Option<CrateId>, | ||
19 | |||
20 | // Indicate this is a local inner macro | ||
21 | local_inner: bool, | ||
22 | } | 22 | } |
23 | 23 | ||
24 | impl Hygiene { | 24 | impl Hygiene { |
25 | pub fn new(db: &dyn AstDatabase, file_id: HirFileId) -> Hygiene { | 25 | pub fn new(db: &dyn AstDatabase, file_id: HirFileId) -> Hygiene { |
26 | let (def_crate, local_inner) = match file_id.0 { | 26 | Hygiene { frames: Some(HygieneFrames::new(db, file_id.clone())) } |
27 | HirFileIdRepr::FileId(_) => (None, false), | ||
28 | HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id { | ||
29 | MacroCallId::LazyMacro(id) => { | ||
30 | let loc = db.lookup_intern_macro(id); | ||
31 | match loc.def.kind { | ||
32 | MacroDefKind::Declarative => (Some(loc.def.krate), loc.def.local_inner), | ||
33 | MacroDefKind::BuiltIn(_) => (Some(loc.def.krate), false), | ||
34 | MacroDefKind::BuiltInDerive(_) => (None, false), | ||
35 | MacroDefKind::BuiltInEager(_) => (None, false), | ||
36 | MacroDefKind::ProcMacro(_) => (None, false), | ||
37 | } | ||
38 | } | ||
39 | MacroCallId::EagerMacro(_id) => (None, false), | ||
40 | }, | ||
41 | }; | ||
42 | Hygiene { def_crate, local_inner } | ||
43 | } | 27 | } |
44 | 28 | ||
45 | pub fn new_unhygienic() -> Hygiene { | 29 | pub fn new_unhygienic() -> Hygiene { |
46 | Hygiene { def_crate: None, local_inner: false } | 30 | Hygiene { frames: None } |
47 | } | 31 | } |
48 | 32 | ||
49 | // FIXME: this should just return name | 33 | // FIXME: this should just return name |
50 | pub fn name_ref_to_name(&self, name_ref: ast::NameRef) -> Either<Name, CrateId> { | 34 | pub fn name_ref_to_name(&self, name_ref: ast::NameRef) -> Either<Name, CrateId> { |
51 | if let Some(def_crate) = self.def_crate { | 35 | if let Some(frames) = &self.frames { |
52 | if name_ref.text() == "$crate" { | 36 | if name_ref.text() == "$crate" { |
53 | return Either::Right(def_crate); | 37 | if let Some(krate) = frames.root_crate(name_ref.syntax()) { |
38 | return Either::Right(krate); | ||
39 | } | ||
54 | } | 40 | } |
55 | } | 41 | } |
42 | |||
56 | Either::Left(name_ref.as_name()) | 43 | Either::Left(name_ref.as_name()) |
57 | } | 44 | } |
58 | 45 | ||
59 | pub fn local_inner_macros(&self) -> Option<CrateId> { | 46 | pub fn local_inner_macros(&self, path: ast::Path) -> Option<CrateId> { |
60 | if self.local_inner { | 47 | let mut token = path.syntax().first_token()?.text_range(); |
61 | self.def_crate | 48 | let frames = self.frames.as_ref()?; |
62 | } else { | 49 | let mut current = frames.0.clone(); |
63 | None | 50 | |
51 | loop { | ||
52 | let (mapped, origin) = current.expansion.as_ref()?.map_ident_up(token)?; | ||
53 | if origin == Origin::Def { | ||
54 | return if current.local_inner { frames.root_crate(path.syntax()) } else { None }; | ||
55 | } | ||
56 | current = current.call_site.as_ref()?.clone(); | ||
57 | token = mapped.value; | ||
58 | } | ||
59 | } | ||
60 | } | ||
61 | |||
62 | #[derive(Clone, Debug)] | ||
63 | struct HygieneFrames(Arc<HygieneFrame>); | ||
64 | |||
65 | #[derive(Clone, Debug, Eq, PartialEq)] | ||
66 | pub struct HygieneFrame { | ||
67 | expansion: Option<HygieneInfo>, | ||
68 | |||
69 | // Indicate this is a local inner macro | ||
70 | local_inner: bool, | ||
71 | krate: Option<CrateId>, | ||
72 | |||
73 | call_site: Option<Arc<HygieneFrame>>, | ||
74 | def_site: Option<Arc<HygieneFrame>>, | ||
75 | } | ||
76 | |||
77 | impl HygieneFrames { | ||
78 | fn new(db: &dyn AstDatabase, file_id: HirFileId) -> Self { | ||
79 | HygieneFrames(Arc::new(HygieneFrame::new(db, file_id))) | ||
80 | } | ||
81 | |||
82 | fn root_crate(&self, node: &SyntaxNode) -> Option<CrateId> { | ||
83 | let mut token = node.first_token()?.text_range(); | ||
84 | let mut result = self.0.krate; | ||
85 | let mut current = self.0.clone(); | ||
86 | |||
87 | while let Some((mapped, origin)) = | ||
88 | current.expansion.as_ref().and_then(|it| it.map_ident_up(token)) | ||
89 | { | ||
90 | result = current.krate; | ||
91 | |||
92 | let site = match origin { | ||
93 | Origin::Def => ¤t.def_site, | ||
94 | Origin::Call => ¤t.call_site, | ||
95 | }; | ||
96 | |||
97 | let site = match site { | ||
98 | None => break, | ||
99 | Some(it) => it, | ||
100 | }; | ||
101 | |||
102 | current = site.clone(); | ||
103 | token = mapped.value; | ||
64 | } | 104 | } |
105 | |||
106 | result | ||
107 | } | ||
108 | } | ||
109 | |||
110 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
111 | struct HygieneInfo { | ||
112 | arg_start: InFile<TextSize>, | ||
113 | /// The `macro_rules!` arguments. | ||
114 | def_start: Option<InFile<TextSize>>, | ||
115 | |||
116 | macro_def: Arc<(db::TokenExpander, mbe::TokenMap)>, | ||
117 | macro_arg: Arc<(tt::Subtree, mbe::TokenMap)>, | ||
118 | exp_map: Arc<mbe::TokenMap>, | ||
119 | } | ||
120 | |||
121 | impl HygieneInfo { | ||
122 | fn map_ident_up(&self, token: TextRange) -> Option<(InFile<TextRange>, Origin)> { | ||
123 | let token_id = self.exp_map.token_by_range(token)?; | ||
124 | |||
125 | let (token_id, origin) = self.macro_def.0.map_id_up(token_id); | ||
126 | let (token_map, tt) = match origin { | ||
127 | mbe::Origin::Call => (&self.macro_arg.1, self.arg_start), | ||
128 | mbe::Origin::Def => ( | ||
129 | &self.macro_def.1, | ||
130 | self.def_start | ||
131 | .as_ref() | ||
132 | .expect("`Origin::Def` used with non-`macro_rules!` macro") | ||
133 | .clone(), | ||
134 | ), | ||
135 | }; | ||
136 | |||
137 | let range = token_map.range_by_token(token_id)?.by_kind(SyntaxKind::IDENT)?; | ||
138 | Some((tt.with_value(range + tt.value), origin)) | ||
139 | } | ||
140 | } | ||
141 | |||
142 | fn make_hygiene_info( | ||
143 | db: &dyn AstDatabase, | ||
144 | macro_file: MacroFile, | ||
145 | loc: &MacroCallLoc, | ||
146 | ) -> Option<HygieneInfo> { | ||
147 | let arg_tt = loc.kind.arg(db)?; | ||
148 | |||
149 | let def_offset = loc.def.ast_id.and_then(|id| { | ||
150 | let def_tt = match id.to_node(db) { | ||
151 | ast::Macro::MacroRules(mac) => mac.token_tree()?.syntax().text_range().start(), | ||
152 | ast::Macro::MacroDef(_) => return None, | ||
153 | }; | ||
154 | Some(InFile::new(id.file_id, def_tt)) | ||
155 | }); | ||
156 | |||
157 | let macro_def = db.macro_def(loc.def)?; | ||
158 | let (_, exp_map) = db.parse_macro_expansion(macro_file).value?; | ||
159 | let macro_arg = db.macro_arg(macro_file.macro_call_id)?; | ||
160 | |||
161 | Some(HygieneInfo { | ||
162 | arg_start: InFile::new(loc.kind.file_id(), arg_tt.text_range().start()), | ||
163 | def_start: def_offset, | ||
164 | macro_arg, | ||
165 | macro_def, | ||
166 | exp_map, | ||
167 | }) | ||
168 | } | ||
169 | |||
170 | impl HygieneFrame { | ||
171 | pub(crate) fn new(db: &dyn AstDatabase, file_id: HirFileId) -> HygieneFrame { | ||
172 | let (info, krate, local_inner) = match file_id.0 { | ||
173 | HirFileIdRepr::FileId(_) => (None, None, false), | ||
174 | HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id { | ||
175 | MacroCallId::EagerMacro(_id) => (None, None, false), | ||
176 | MacroCallId::LazyMacro(id) => { | ||
177 | let loc = db.lookup_intern_macro(id); | ||
178 | let info = make_hygiene_info(db, macro_file, &loc); | ||
179 | match loc.def.kind { | ||
180 | MacroDefKind::Declarative => { | ||
181 | (info, Some(loc.def.krate), loc.def.local_inner) | ||
182 | } | ||
183 | MacroDefKind::BuiltIn(_) => (info, Some(loc.def.krate), false), | ||
184 | MacroDefKind::BuiltInDerive(_) => (info, None, false), | ||
185 | MacroDefKind::BuiltInEager(_) => (info, None, false), | ||
186 | MacroDefKind::ProcMacro(_) => (info, None, false), | ||
187 | } | ||
188 | } | ||
189 | }, | ||
190 | }; | ||
191 | |||
192 | let info = match info { | ||
193 | None => { | ||
194 | return HygieneFrame { | ||
195 | expansion: None, | ||
196 | local_inner, | ||
197 | krate, | ||
198 | call_site: None, | ||
199 | def_site: None, | ||
200 | }; | ||
201 | } | ||
202 | Some(it) => it, | ||
203 | }; | ||
204 | |||
205 | let def_site = info.def_start.map(|it| db.hygiene_frame(it.file_id)); | ||
206 | let call_site = Some(db.hygiene_frame(info.arg_start.file_id)); | ||
207 | |||
208 | HygieneFrame { expansion: Some(info), local_inner, krate, call_site, def_site } | ||
65 | } | 209 | } |
66 | } | 210 | } |
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs index 2f44876a8..95d853b6d 100644 --- a/crates/hir_expand/src/name.rs +++ b/crates/hir_expand/src/name.rs | |||
@@ -164,6 +164,7 @@ pub mod known { | |||
164 | future, | 164 | future, |
165 | result, | 165 | result, |
166 | boxed, | 166 | boxed, |
167 | option, | ||
167 | // Components of known path (type name) | 168 | // Components of known path (type name) |
168 | Iterator, | 169 | Iterator, |
169 | IntoIterator, | 170 | IntoIterator, |
@@ -172,6 +173,7 @@ pub mod known { | |||
172 | Ok, | 173 | Ok, |
173 | Future, | 174 | Future, |
174 | Result, | 175 | Result, |
176 | Option, | ||
175 | Output, | 177 | Output, |
176 | Target, | 178 | Target, |
177 | Box, | 179 | Box, |
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs index 14e18f5a1..c67a289f2 100644 --- a/crates/hir_ty/src/diagnostics.rs +++ b/crates/hir_ty/src/diagnostics.rs | |||
@@ -186,9 +186,10 @@ impl Diagnostic for MissingMatchArms { | |||
186 | } | 186 | } |
187 | } | 187 | } |
188 | 188 | ||
189 | // Diagnostic: missing-ok-in-tail-expr | 189 | // Diagnostic: missing-ok-or-some-in-tail-expr |
190 | // | 190 | // |
191 | // This diagnostic is triggered if block that should return `Result` returns a value not wrapped in `Ok`. | 191 | // This diagnostic is triggered if a block that should return `Result` returns a value not wrapped in `Ok`, |
192 | // or if a block that should return `Option` returns a value not wrapped in `Some`. | ||
192 | // | 193 | // |
193 | // Example: | 194 | // Example: |
194 | // | 195 | // |
@@ -198,17 +199,19 @@ impl Diagnostic for MissingMatchArms { | |||
198 | // } | 199 | // } |
199 | // ``` | 200 | // ``` |
200 | #[derive(Debug)] | 201 | #[derive(Debug)] |
201 | pub struct MissingOkInTailExpr { | 202 | pub struct MissingOkOrSomeInTailExpr { |
202 | pub file: HirFileId, | 203 | pub file: HirFileId, |
203 | pub expr: AstPtr<ast::Expr>, | 204 | pub expr: AstPtr<ast::Expr>, |
205 | // `Some` or `Ok` depending on whether the return type is Result or Option | ||
206 | pub required: String, | ||
204 | } | 207 | } |
205 | 208 | ||
206 | impl Diagnostic for MissingOkInTailExpr { | 209 | impl Diagnostic for MissingOkOrSomeInTailExpr { |
207 | fn code(&self) -> DiagnosticCode { | 210 | fn code(&self) -> DiagnosticCode { |
208 | DiagnosticCode("missing-ok-in-tail-expr") | 211 | DiagnosticCode("missing-ok-or-some-in-tail-expr") |
209 | } | 212 | } |
210 | fn message(&self) -> String { | 213 | fn message(&self) -> String { |
211 | "wrap return expression in Ok".to_string() | 214 | format!("wrap return expression in {}", self.required) |
212 | } | 215 | } |
213 | fn display_source(&self) -> InFile<SyntaxNodePtr> { | 216 | fn display_source(&self) -> InFile<SyntaxNodePtr> { |
214 | InFile { file_id: self.file, value: self.expr.clone().into() } | 217 | InFile { file_id: self.file, value: self.expr.clone().into() } |
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs index b4e453411..107417c27 100644 --- a/crates/hir_ty/src/diagnostics/expr.rs +++ b/crates/hir_ty/src/diagnostics/expr.rs | |||
@@ -11,8 +11,8 @@ use crate::{ | |||
11 | db::HirDatabase, | 11 | db::HirDatabase, |
12 | diagnostics::{ | 12 | diagnostics::{ |
13 | match_check::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness}, | 13 | match_check::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness}, |
14 | MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, MissingPatFields, | 14 | MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr, |
15 | RemoveThisSemicolon, | 15 | MissingPatFields, RemoveThisSemicolon, |
16 | }, | 16 | }, |
17 | utils::variant_data, | 17 | utils::variant_data, |
18 | ApplicationTy, InferenceResult, Ty, TypeCtor, | 18 | ApplicationTy, InferenceResult, Ty, TypeCtor, |
@@ -306,27 +306,40 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
306 | }; | 306 | }; |
307 | 307 | ||
308 | let core_result_path = path![core::result::Result]; | 308 | let core_result_path = path![core::result::Result]; |
309 | let core_option_path = path![core::option::Option]; | ||
309 | 310 | ||
310 | let resolver = self.owner.resolver(db.upcast()); | 311 | let resolver = self.owner.resolver(db.upcast()); |
311 | let core_result_enum = match resolver.resolve_known_enum(db.upcast(), &core_result_path) { | 312 | let core_result_enum = match resolver.resolve_known_enum(db.upcast(), &core_result_path) { |
312 | Some(it) => it, | 313 | Some(it) => it, |
313 | _ => return, | 314 | _ => return, |
314 | }; | 315 | }; |
316 | let core_option_enum = match resolver.resolve_known_enum(db.upcast(), &core_option_path) { | ||
317 | Some(it) => it, | ||
318 | _ => return, | ||
319 | }; | ||
315 | 320 | ||
316 | let core_result_ctor = TypeCtor::Adt(AdtId::EnumId(core_result_enum)); | 321 | let core_result_ctor = TypeCtor::Adt(AdtId::EnumId(core_result_enum)); |
317 | let params = match &mismatch.expected { | 322 | let core_option_ctor = TypeCtor::Adt(AdtId::EnumId(core_option_enum)); |
323 | |||
324 | let (params, required) = match &mismatch.expected { | ||
318 | Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &core_result_ctor => { | 325 | Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &core_result_ctor => { |
319 | parameters | 326 | (parameters, "Ok".to_string()) |
327 | } | ||
328 | Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &core_option_ctor => { | ||
329 | (parameters, "Some".to_string()) | ||
320 | } | 330 | } |
321 | _ => return, | 331 | _ => return, |
322 | }; | 332 | }; |
323 | 333 | ||
324 | if params.len() == 2 && params[0] == mismatch.actual { | 334 | if params.len() > 0 && params[0] == mismatch.actual { |
325 | let (_, source_map) = db.body_with_source_map(self.owner.into()); | 335 | let (_, source_map) = db.body_with_source_map(self.owner.into()); |
326 | 336 | ||
327 | if let Ok(source_ptr) = source_map.expr_syntax(id) { | 337 | if let Ok(source_ptr) = source_map.expr_syntax(id) { |
328 | self.sink | 338 | self.sink.push(MissingOkOrSomeInTailExpr { |
329 | .push(MissingOkInTailExpr { file: source_ptr.file_id, expr: source_ptr.value }); | 339 | file: source_ptr.file_id, |
340 | expr: source_ptr.value, | ||
341 | required, | ||
342 | }); | ||
330 | } | 343 | } |
331 | } | 344 | } |
332 | } | 345 | } |
@@ -366,7 +379,7 @@ pub fn record_literal_missing_fields( | |||
366 | id: ExprId, | 379 | id: ExprId, |
367 | expr: &Expr, | 380 | expr: &Expr, |
368 | ) -> Option<(VariantId, Vec<LocalFieldId>, /*exhaustive*/ bool)> { | 381 | ) -> Option<(VariantId, Vec<LocalFieldId>, /*exhaustive*/ bool)> { |
369 | let (fields, exhausitve) = match expr { | 382 | let (fields, exhaustive) = match expr { |
370 | Expr::RecordLit { path: _, fields, spread } => (fields, spread.is_none()), | 383 | Expr::RecordLit { path: _, fields, spread } => (fields, spread.is_none()), |
371 | _ => return None, | 384 | _ => return None, |
372 | }; | 385 | }; |
@@ -387,7 +400,7 @@ pub fn record_literal_missing_fields( | |||
387 | if missed_fields.is_empty() { | 400 | if missed_fields.is_empty() { |
388 | return None; | 401 | return None; |
389 | } | 402 | } |
390 | Some((variant_def, missed_fields, exhausitve)) | 403 | Some((variant_def, missed_fields, exhaustive)) |
391 | } | 404 | } |
392 | 405 | ||
393 | pub fn record_pattern_missing_fields( | 406 | pub fn record_pattern_missing_fields( |
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index 62c329731..61c47eec8 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs | |||
@@ -14,7 +14,7 @@ | |||
14 | //! The algorithm implemented here is a modified version of the one described in | 14 | //! The algorithm implemented here is a modified version of the one described in |
15 | //! <http://moscova.inria.fr/~maranget/papers/warn/index.html>. | 15 | //! <http://moscova.inria.fr/~maranget/papers/warn/index.html>. |
16 | //! However, to save future implementors from reading the original paper, we | 16 | //! However, to save future implementors from reading the original paper, we |
17 | //! summarise the algorithm here to hopefully save time and be a little clearer | 17 | //! summarize the algorithm here to hopefully save time and be a little clearer |
18 | //! (without being so rigorous). | 18 | //! (without being so rigorous). |
19 | //! | 19 | //! |
20 | //! The core of the algorithm revolves about a "usefulness" check. In particular, we | 20 | //! The core of the algorithm revolves about a "usefulness" check. In particular, we |
@@ -132,7 +132,7 @@ | |||
132 | //! The algorithm is inductive (on the number of columns: i.e., components of tuple patterns). | 132 | //! The algorithm is inductive (on the number of columns: i.e., components of tuple patterns). |
133 | //! That means we're going to check the components from left-to-right, so the algorithm | 133 | //! That means we're going to check the components from left-to-right, so the algorithm |
134 | //! operates principally on the first component of the matrix and new pattern-stack `p`. | 134 | //! operates principally on the first component of the matrix and new pattern-stack `p`. |
135 | //! This algorithm is realised in the `is_useful` function. | 135 | //! This algorithm is realized in the `is_useful` function. |
136 | //! | 136 | //! |
137 | //! Base case (`n = 0`, i.e., an empty tuple pattern): | 137 | //! Base case (`n = 0`, i.e., an empty tuple pattern): |
138 | //! - If `P` already contains an empty pattern (i.e., if the number of patterns `m > 0`), then | 138 | //! - If `P` already contains an empty pattern (i.e., if the number of patterns `m > 0`), then |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 222f61a11..9594cce8b 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -491,16 +491,16 @@ impl Ty { | |||
491 | fn from_hir_path_inner( | 491 | fn from_hir_path_inner( |
492 | ctx: &TyLoweringContext<'_>, | 492 | ctx: &TyLoweringContext<'_>, |
493 | segment: PathSegment<'_>, | 493 | segment: PathSegment<'_>, |
494 | typable: TyDefId, | 494 | typeable: TyDefId, |
495 | infer_args: bool, | 495 | infer_args: bool, |
496 | ) -> Ty { | 496 | ) -> Ty { |
497 | let generic_def = match typable { | 497 | let generic_def = match typeable { |
498 | TyDefId::BuiltinType(_) => None, | 498 | TyDefId::BuiltinType(_) => None, |
499 | TyDefId::AdtId(it) => Some(it.into()), | 499 | TyDefId::AdtId(it) => Some(it.into()), |
500 | TyDefId::TypeAliasId(it) => Some(it.into()), | 500 | TyDefId::TypeAliasId(it) => Some(it.into()), |
501 | }; | 501 | }; |
502 | let substs = substs_from_path_segment(ctx, segment, generic_def, infer_args); | 502 | let substs = substs_from_path_segment(ctx, segment, generic_def, infer_args); |
503 | ctx.db.ty(typable).subst(&substs) | 503 | ctx.db.ty(typeable).subst(&substs) |
504 | } | 504 | } |
505 | 505 | ||
506 | /// Collect generic arguments from a path into a `Substs`. See also | 506 | /// Collect generic arguments from a path into a `Substs`. See also |
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs index 0a400cb70..3b1675f0b 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs | |||
@@ -314,7 +314,7 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() { | |||
314 | " | 314 | " |
315 | //- /lib.rs | 315 | //- /lib.rs |
316 | fn foo() -> i32 { | 316 | fn foo() -> i32 { |
317 | <|>1 + 1 | 317 | $01 + 1 |
318 | } | 318 | } |
319 | ", | 319 | ", |
320 | ); | 320 | ); |
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index 1953da7be..c64f0b5b5 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -371,6 +371,37 @@ expand!(); | |||
371 | } | 371 | } |
372 | 372 | ||
373 | #[test] | 373 | #[test] |
374 | fn infer_macro_with_dollar_crate_in_def_site() { | ||
375 | check_types( | ||
376 | r#" | ||
377 | //- /main.rs crate:main deps:foo | ||
378 | use foo::expand; | ||
379 | |||
380 | macro_rules! list { | ||
381 | ($($tt:tt)*) => { $($tt)* } | ||
382 | } | ||
383 | |||
384 | fn test() { | ||
385 | let r = expand!(); | ||
386 | r; | ||
387 | //^ u128 | ||
388 | } | ||
389 | |||
390 | //- /lib.rs crate:foo | ||
391 | #[macro_export] | ||
392 | macro_rules! expand { | ||
393 | () => { list!($crate::m!()) }; | ||
394 | } | ||
395 | |||
396 | #[macro_export] | ||
397 | macro_rules! m { | ||
398 | () => { 0u128 }; | ||
399 | } | ||
400 | "#, | ||
401 | ); | ||
402 | } | ||
403 | |||
404 | #[test] | ||
374 | fn infer_type_value_non_legacy_macro_use_as() { | 405 | fn infer_type_value_non_legacy_macro_use_as() { |
375 | check_infer( | 406 | check_infer( |
376 | r#" | 407 | r#" |
diff --git a/crates/ide/src/call_hierarchy.rs b/crates/ide/src/call_hierarchy.rs index 3c2d39f5d..e8999a7f3 100644 --- a/crates/ide/src/call_hierarchy.rs +++ b/crates/ide/src/call_hierarchy.rs | |||
@@ -5,7 +5,7 @@ use indexmap::IndexMap; | |||
5 | use hir::Semantics; | 5 | use hir::Semantics; |
6 | use ide_db::call_info::FnCallNode; | 6 | use ide_db::call_info::FnCallNode; |
7 | use ide_db::RootDatabase; | 7 | use ide_db::RootDatabase; |
8 | use syntax::{ast, match_ast, AstNode, TextRange}; | 8 | use syntax::{ast, AstNode, TextRange}; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | display::TryToNav, goto_definition, references, FilePosition, NavigationTarget, RangeInfo, | 11 | display::TryToNav, goto_definition, references, FilePosition, NavigationTarget, RangeInfo, |
@@ -47,28 +47,23 @@ pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Optio | |||
47 | 47 | ||
48 | let mut calls = CallLocations::default(); | 48 | let mut calls = CallLocations::default(); |
49 | 49 | ||
50 | for reference in refs.info.references() { | 50 | for (&file_id, references) in refs.info.references().iter() { |
51 | let file_id = reference.file_range.file_id; | ||
52 | let file = sema.parse(file_id); | 51 | let file = sema.parse(file_id); |
53 | let file = file.syntax(); | 52 | let file = file.syntax(); |
54 | let token = file.token_at_offset(reference.file_range.range.start()).next()?; | 53 | for reference in references { |
55 | let token = sema.descend_into_macros(token); | 54 | let token = file.token_at_offset(reference.range.start()).next()?; |
56 | let syntax = token.parent(); | 55 | let token = sema.descend_into_macros(token); |
57 | 56 | let syntax = token.parent(); | |
58 | // This target is the containing function | 57 | |
59 | if let Some(nav) = syntax.ancestors().find_map(|node| { | 58 | // This target is the containing function |
60 | match_ast! { | 59 | if let Some(nav) = syntax.ancestors().find_map(|node| { |
61 | match node { | 60 | let fn_ = ast::Fn::cast(node)?; |
62 | ast::Fn(it) => { | 61 | let def = sema.to_def(&fn_)?; |
63 | let def = sema.to_def(&it)?; | 62 | def.try_to_nav(sema.db) |
64 | def.try_to_nav(sema.db) | 63 | }) { |
65 | }, | 64 | let relative_range = reference.range; |
66 | _ => None, | 65 | calls.add(&nav, relative_range); |
67 | } | ||
68 | } | 66 | } |
69 | }) { | ||
70 | let relative_range = reference.file_range.range; | ||
71 | calls.add(&nav, relative_range); | ||
72 | } | 67 | } |
73 | } | 68 | } |
74 | 69 | ||
@@ -91,17 +86,12 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio | |||
91 | .filter_map(|node| FnCallNode::with_node_exact(&node)) | 86 | .filter_map(|node| FnCallNode::with_node_exact(&node)) |
92 | .filter_map(|call_node| { | 87 | .filter_map(|call_node| { |
93 | let name_ref = call_node.name_ref()?; | 88 | let name_ref = call_node.name_ref()?; |
94 | 89 | let func_target = match call_node { | |
95 | if let Some(func_target) = match &call_node { | ||
96 | FnCallNode::CallExpr(expr) => { | 90 | FnCallNode::CallExpr(expr) => { |
97 | //FIXME: Type::as_callable is broken | 91 | //FIXME: Type::as_callable is broken |
98 | let callable = sema.type_of_expr(&expr.expr()?)?.as_callable(db)?; | 92 | let callable = sema.type_of_expr(&expr.expr()?)?.as_callable(db)?; |
99 | match callable.kind() { | 93 | match callable.kind() { |
100 | hir::CallableKind::Function(it) => { | 94 | hir::CallableKind::Function(it) => it.try_to_nav(db), |
101 | let fn_def: hir::Function = it.into(); | ||
102 | let nav = fn_def.try_to_nav(db)?; | ||
103 | Some(nav) | ||
104 | } | ||
105 | _ => None, | 95 | _ => None, |
106 | } | 96 | } |
107 | } | 97 | } |
@@ -109,11 +99,8 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio | |||
109 | let function = sema.resolve_method_call(&expr)?; | 99 | let function = sema.resolve_method_call(&expr)?; |
110 | function.try_to_nav(db) | 100 | function.try_to_nav(db) |
111 | } | 101 | } |
112 | } { | 102 | }?; |
113 | Some((func_target, name_ref.syntax().text_range())) | 103 | Some((func_target, name_ref.syntax().text_range())) |
114 | } else { | ||
115 | None | ||
116 | } | ||
117 | }) | 104 | }) |
118 | .for_each(|(nav, range)| calls.add(&nav, range)); | 105 | .for_each(|(nav, range)| calls.add(&nav, range)); |
119 | 106 | ||
@@ -178,7 +165,7 @@ mod tests { | |||
178 | //- /lib.rs | 165 | //- /lib.rs |
179 | fn callee() {} | 166 | fn callee() {} |
180 | fn caller() { | 167 | fn caller() { |
181 | call<|>ee(); | 168 | call$0ee(); |
182 | } | 169 | } |
183 | "#, | 170 | "#, |
184 | "callee Function FileId(0) 0..14 3..9", | 171 | "callee Function FileId(0) 0..14 3..9", |
@@ -192,7 +179,7 @@ fn caller() { | |||
192 | check_hierarchy( | 179 | check_hierarchy( |
193 | r#" | 180 | r#" |
194 | //- /lib.rs | 181 | //- /lib.rs |
195 | fn call<|>ee() {} | 182 | fn call$0ee() {} |
196 | fn caller() { | 183 | fn caller() { |
197 | callee(); | 184 | callee(); |
198 | } | 185 | } |
@@ -210,7 +197,7 @@ fn caller() { | |||
210 | //- /lib.rs | 197 | //- /lib.rs |
211 | fn callee() {} | 198 | fn callee() {} |
212 | fn caller() { | 199 | fn caller() { |
213 | call<|>ee(); | 200 | call$0ee(); |
214 | callee(); | 201 | callee(); |
215 | } | 202 | } |
216 | "#, | 203 | "#, |
@@ -227,7 +214,7 @@ fn caller() { | |||
227 | //- /lib.rs | 214 | //- /lib.rs |
228 | fn callee() {} | 215 | fn callee() {} |
229 | fn caller1() { | 216 | fn caller1() { |
230 | call<|>ee(); | 217 | call$0ee(); |
231 | } | 218 | } |
232 | 219 | ||
233 | fn caller2() { | 220 | fn caller2() { |
@@ -250,7 +237,7 @@ fn caller2() { | |||
250 | //- /lib.rs cfg:test | 237 | //- /lib.rs cfg:test |
251 | fn callee() {} | 238 | fn callee() {} |
252 | fn caller1() { | 239 | fn caller1() { |
253 | call<|>ee(); | 240 | call$0ee(); |
254 | } | 241 | } |
255 | 242 | ||
256 | #[cfg(test)] | 243 | #[cfg(test)] |
@@ -281,7 +268,7 @@ mod foo; | |||
281 | use foo::callee; | 268 | use foo::callee; |
282 | 269 | ||
283 | fn caller() { | 270 | fn caller() { |
284 | call<|>ee(); | 271 | call$0ee(); |
285 | } | 272 | } |
286 | 273 | ||
287 | //- /foo/mod.rs | 274 | //- /foo/mod.rs |
@@ -299,7 +286,7 @@ pub fn callee() {} | |||
299 | r#" | 286 | r#" |
300 | //- /lib.rs | 287 | //- /lib.rs |
301 | fn callee() {} | 288 | fn callee() {} |
302 | fn call<|>er() { | 289 | fn call$0er() { |
303 | callee(); | 290 | callee(); |
304 | callee(); | 291 | callee(); |
305 | } | 292 | } |
@@ -318,7 +305,7 @@ fn call<|>er() { | |||
318 | mod foo; | 305 | mod foo; |
319 | use foo::callee; | 306 | use foo::callee; |
320 | 307 | ||
321 | fn call<|>er() { | 308 | fn call$0er() { |
322 | callee(); | 309 | callee(); |
323 | } | 310 | } |
324 | 311 | ||
@@ -337,7 +324,7 @@ pub fn callee() {} | |||
337 | r#" | 324 | r#" |
338 | //- /lib.rs | 325 | //- /lib.rs |
339 | fn caller1() { | 326 | fn caller1() { |
340 | call<|>er2(); | 327 | call$0er2(); |
341 | } | 328 | } |
342 | 329 | ||
343 | fn caller2() { | 330 | fn caller2() { |
@@ -365,7 +352,7 @@ fn a() { | |||
365 | fn b() {} | 352 | fn b() {} |
366 | 353 | ||
367 | fn main() { | 354 | fn main() { |
368 | a<|>() | 355 | a$0() |
369 | } | 356 | } |
370 | "#, | 357 | "#, |
371 | "a Function FileId(0) 0..18 3..4", | 358 | "a Function FileId(0) 0..18 3..4", |
@@ -376,7 +363,7 @@ fn main() { | |||
376 | check_hierarchy( | 363 | check_hierarchy( |
377 | r#" | 364 | r#" |
378 | fn a() { | 365 | fn a() { |
379 | b<|>() | 366 | b$0() |
380 | } | 367 | } |
381 | 368 | ||
382 | fn b() {} | 369 | fn b() {} |
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs index 79d126ff2..055c0a79c 100644 --- a/crates/ide/src/diagnostics.rs +++ b/crates/ide/src/diagnostics.rs | |||
@@ -125,7 +125,7 @@ pub(crate) fn diagnostics( | |||
125 | .on::<hir::diagnostics::MissingFields, _>(|d| { | 125 | .on::<hir::diagnostics::MissingFields, _>(|d| { |
126 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); | 126 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); |
127 | }) | 127 | }) |
128 | .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| { | 128 | .on::<hir::diagnostics::MissingOkOrSomeInTailExpr, _>(|d| { |
129 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); | 129 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); |
130 | }) | 130 | }) |
131 | .on::<hir::diagnostics::NoSuchField, _>(|d| { | 131 | .on::<hir::diagnostics::NoSuchField, _>(|d| { |
@@ -305,6 +305,40 @@ mod tests { | |||
305 | } | 305 | } |
306 | 306 | ||
307 | #[test] | 307 | #[test] |
308 | fn test_wrap_return_type_option() { | ||
309 | check_fix( | ||
310 | r#" | ||
311 | //- /main.rs crate:main deps:core | ||
312 | use core::option::Option::{self, Some, None}; | ||
313 | |||
314 | fn div(x: i32, y: i32) -> Option<i32> { | ||
315 | if y == 0 { | ||
316 | return None; | ||
317 | } | ||
318 | x / y$0 | ||
319 | } | ||
320 | //- /core/lib.rs crate:core | ||
321 | pub mod result { | ||
322 | pub enum Result<T, E> { Ok(T), Err(E) } | ||
323 | } | ||
324 | pub mod option { | ||
325 | pub enum Option<T> { Some(T), None } | ||
326 | } | ||
327 | "#, | ||
328 | r#" | ||
329 | use core::option::Option::{self, Some, None}; | ||
330 | |||
331 | fn div(x: i32, y: i32) -> Option<i32> { | ||
332 | if y == 0 { | ||
333 | return None; | ||
334 | } | ||
335 | Some(x / y) | ||
336 | } | ||
337 | "#, | ||
338 | ); | ||
339 | } | ||
340 | |||
341 | #[test] | ||
308 | fn test_wrap_return_type() { | 342 | fn test_wrap_return_type() { |
309 | check_fix( | 343 | check_fix( |
310 | r#" | 344 | r#" |
@@ -315,12 +349,15 @@ fn div(x: i32, y: i32) -> Result<i32, ()> { | |||
315 | if y == 0 { | 349 | if y == 0 { |
316 | return Err(()); | 350 | return Err(()); |
317 | } | 351 | } |
318 | x / y<|> | 352 | x / y$0 |
319 | } | 353 | } |
320 | //- /core/lib.rs crate:core | 354 | //- /core/lib.rs crate:core |
321 | pub mod result { | 355 | pub mod result { |
322 | pub enum Result<T, E> { Ok(T), Err(E) } | 356 | pub enum Result<T, E> { Ok(T), Err(E) } |
323 | } | 357 | } |
358 | pub mod option { | ||
359 | pub enum Option<T> { Some(T), None } | ||
360 | } | ||
324 | "#, | 361 | "#, |
325 | r#" | 362 | r#" |
326 | use core::result::Result::{self, Ok, Err}; | 363 | use core::result::Result::{self, Ok, Err}; |
@@ -346,12 +383,15 @@ fn div<T>(x: T) -> Result<T, i32> { | |||
346 | if x == 0 { | 383 | if x == 0 { |
347 | return Err(7); | 384 | return Err(7); |
348 | } | 385 | } |
349 | <|>x | 386 | $0x |
350 | } | 387 | } |
351 | //- /core/lib.rs crate:core | 388 | //- /core/lib.rs crate:core |
352 | pub mod result { | 389 | pub mod result { |
353 | pub enum Result<T, E> { Ok(T), Err(E) } | 390 | pub enum Result<T, E> { Ok(T), Err(E) } |
354 | } | 391 | } |
392 | pub mod option { | ||
393 | pub enum Option<T> { Some(T), None } | ||
394 | } | ||
355 | "#, | 395 | "#, |
356 | r#" | 396 | r#" |
357 | use core::result::Result::{self, Ok, Err}; | 397 | use core::result::Result::{self, Ok, Err}; |
@@ -379,12 +419,15 @@ fn div(x: i32, y: i32) -> MyResult<i32> { | |||
379 | if y == 0 { | 419 | if y == 0 { |
380 | return Err(()); | 420 | return Err(()); |
381 | } | 421 | } |
382 | x <|>/ y | 422 | x $0/ y |
383 | } | 423 | } |
384 | //- /core/lib.rs crate:core | 424 | //- /core/lib.rs crate:core |
385 | pub mod result { | 425 | pub mod result { |
386 | pub enum Result<T, E> { Ok(T), Err(E) } | 426 | pub enum Result<T, E> { Ok(T), Err(E) } |
387 | } | 427 | } |
428 | pub mod option { | ||
429 | pub enum Option<T> { Some(T), None } | ||
430 | } | ||
388 | "#, | 431 | "#, |
389 | r#" | 432 | r#" |
390 | use core::result::Result::{self, Ok, Err}; | 433 | use core::result::Result::{self, Ok, Err}; |
@@ -414,12 +457,15 @@ fn foo() -> Result<(), i32> { 0 } | |||
414 | pub mod result { | 457 | pub mod result { |
415 | pub enum Result<T, E> { Ok(T), Err(E) } | 458 | pub enum Result<T, E> { Ok(T), Err(E) } |
416 | } | 459 | } |
460 | pub mod option { | ||
461 | pub enum Option<T> { Some(T), None } | ||
462 | } | ||
417 | "#, | 463 | "#, |
418 | ); | 464 | ); |
419 | } | 465 | } |
420 | 466 | ||
421 | #[test] | 467 | #[test] |
422 | fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() { | 468 | fn test_wrap_return_type_not_applicable_when_return_type_is_not_result_or_option() { |
423 | check_no_diagnostics( | 469 | check_no_diagnostics( |
424 | r#" | 470 | r#" |
425 | //- /main.rs crate:main deps:core | 471 | //- /main.rs crate:main deps:core |
@@ -433,6 +479,9 @@ fn foo() -> SomeOtherEnum { 0 } | |||
433 | pub mod result { | 479 | pub mod result { |
434 | pub enum Result<T, E> { Ok(T), Err(E) } | 480 | pub enum Result<T, E> { Ok(T), Err(E) } |
435 | } | 481 | } |
482 | pub mod option { | ||
483 | pub enum Option<T> { Some(T), None } | ||
484 | } | ||
436 | "#, | 485 | "#, |
437 | ); | 486 | ); |
438 | } | 487 | } |
@@ -444,7 +493,7 @@ pub mod result { | |||
444 | struct TestStruct { one: i32, two: i64 } | 493 | struct TestStruct { one: i32, two: i64 } |
445 | 494 | ||
446 | fn test_fn() { | 495 | fn test_fn() { |
447 | let s = TestStruct {<|>}; | 496 | let s = TestStruct {$0}; |
448 | } | 497 | } |
449 | "#, | 498 | "#, |
450 | r#" | 499 | r#" |
@@ -464,7 +513,7 @@ fn test_fn() { | |||
464 | struct TestStruct { one: i32 } | 513 | struct TestStruct { one: i32 } |
465 | 514 | ||
466 | impl TestStruct { | 515 | impl TestStruct { |
467 | fn test_fn() { let s = Self {<|>}; } | 516 | fn test_fn() { let s = Self {$0}; } |
468 | } | 517 | } |
469 | "#, | 518 | "#, |
470 | r#" | 519 | r#" |
@@ -487,7 +536,7 @@ enum Expr { | |||
487 | 536 | ||
488 | impl Expr { | 537 | impl Expr { |
489 | fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr { | 538 | fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr { |
490 | Expr::Bin {<|> } | 539 | Expr::Bin {$0 } |
491 | } | 540 | } |
492 | } | 541 | } |
493 | "#, | 542 | "#, |
@@ -512,7 +561,7 @@ impl Expr { | |||
512 | struct TestStruct { one: i32, two: i64 } | 561 | struct TestStruct { one: i32, two: i64 } |
513 | 562 | ||
514 | fn test_fn() { | 563 | fn test_fn() { |
515 | let s = TestStruct{ two: 2<|> }; | 564 | let s = TestStruct{ two: 2$0 }; |
516 | } | 565 | } |
517 | "#, | 566 | "#, |
518 | r" | 567 | r" |
@@ -608,7 +657,7 @@ fn here() {} | |||
608 | macro_rules! id { ($($tt:tt)*) => { $($tt)*}; } | 657 | macro_rules! id { ($($tt:tt)*) => { $($tt)*}; } |
609 | 658 | ||
610 | fn main() { | 659 | fn main() { |
611 | let _x = id![Foo { a: <|>42 }]; | 660 | let _x = id![Foo { a: $042 }]; |
612 | } | 661 | } |
613 | 662 | ||
614 | pub struct Foo { pub a: i32, pub b: i32 } | 663 | pub struct Foo { pub a: i32, pub b: i32 } |
@@ -663,7 +712,7 @@ mod a { | |||
663 | check_fix( | 712 | check_fix( |
664 | r" | 713 | r" |
665 | mod b {} | 714 | mod b {} |
666 | use {<|>b}; | 715 | use {$0b}; |
667 | ", | 716 | ", |
668 | r" | 717 | r" |
669 | mod b {} | 718 | mod b {} |
@@ -673,7 +722,7 @@ mod a { | |||
673 | check_fix( | 722 | check_fix( |
674 | r" | 723 | r" |
675 | mod b {} | 724 | mod b {} |
676 | use {b<|>}; | 725 | use {b$0}; |
677 | ", | 726 | ", |
678 | r" | 727 | r" |
679 | mod b {} | 728 | mod b {} |
@@ -683,7 +732,7 @@ mod a { | |||
683 | check_fix( | 732 | check_fix( |
684 | r" | 733 | r" |
685 | mod a { mod c {} } | 734 | mod a { mod c {} } |
686 | use a::{c<|>}; | 735 | use a::{c$0}; |
687 | ", | 736 | ", |
688 | r" | 737 | r" |
689 | mod a { mod c {} } | 738 | mod a { mod c {} } |
@@ -693,7 +742,7 @@ mod a { | |||
693 | check_fix( | 742 | check_fix( |
694 | r" | 743 | r" |
695 | mod a {} | 744 | mod a {} |
696 | use a::{self<|>}; | 745 | use a::{self$0}; |
697 | ", | 746 | ", |
698 | r" | 747 | r" |
699 | mod a {} | 748 | mod a {} |
@@ -703,7 +752,7 @@ mod a { | |||
703 | check_fix( | 752 | check_fix( |
704 | r" | 753 | r" |
705 | mod a { mod c {} mod d { mod e {} } } | 754 | mod a { mod c {} mod d { mod e {} } } |
706 | use a::{c, d::{e<|>}}; | 755 | use a::{c, d::{e$0}}; |
707 | ", | 756 | ", |
708 | r" | 757 | r" |
709 | mod a { mod c {} mod d { mod e {} } } | 758 | mod a { mod c {} mod d { mod e {} } } |
@@ -717,7 +766,7 @@ mod a { | |||
717 | check_fix( | 766 | check_fix( |
718 | r" | 767 | r" |
719 | fn main() { | 768 | fn main() { |
720 | Foo { bar: 3, baz<|>: false}; | 769 | Foo { bar: 3, baz$0: false}; |
721 | } | 770 | } |
722 | struct Foo { | 771 | struct Foo { |
723 | bar: i32 | 772 | bar: i32 |
@@ -743,7 +792,7 @@ struct Foo { | |||
743 | mod foo; | 792 | mod foo; |
744 | 793 | ||
745 | fn main() { | 794 | fn main() { |
746 | foo::Foo { bar: 3, <|>baz: false}; | 795 | foo::Foo { bar: 3, $0baz: false}; |
747 | } | 796 | } |
748 | //- /foo.rs | 797 | //- /foo.rs |
749 | struct Foo { | 798 | struct Foo { |
@@ -777,7 +826,7 @@ struct Foo { | |||
777 | fn test_rename_incorrect_case() { | 826 | fn test_rename_incorrect_case() { |
778 | check_fix( | 827 | check_fix( |
779 | r#" | 828 | r#" |
780 | pub struct test_struct<|> { one: i32 } | 829 | pub struct test_struct$0 { one: i32 } |
781 | 830 | ||
782 | pub fn some_fn(val: test_struct) -> test_struct { | 831 | pub fn some_fn(val: test_struct) -> test_struct { |
783 | test_struct { one: val.one + 1 } | 832 | test_struct { one: val.one + 1 } |
@@ -794,7 +843,7 @@ pub fn some_fn(val: TestStruct) -> TestStruct { | |||
794 | 843 | ||
795 | check_fix( | 844 | check_fix( |
796 | r#" | 845 | r#" |
797 | pub fn some_fn(NonSnakeCase<|>: u8) -> u8 { | 846 | pub fn some_fn(NonSnakeCase$0: u8) -> u8 { |
798 | NonSnakeCase | 847 | NonSnakeCase |
799 | } | 848 | } |
800 | "#, | 849 | "#, |
@@ -807,7 +856,7 @@ pub fn some_fn(non_snake_case: u8) -> u8 { | |||
807 | 856 | ||
808 | check_fix( | 857 | check_fix( |
809 | r#" | 858 | r#" |
810 | pub fn SomeFn<|>(val: u8) -> u8 { | 859 | pub fn SomeFn$0(val: u8) -> u8 { |
811 | if val != 0 { SomeFn(val - 1) } else { val } | 860 | if val != 0 { SomeFn(val - 1) } else { val } |
812 | } | 861 | } |
813 | "#, | 862 | "#, |
@@ -821,7 +870,7 @@ pub fn some_fn(val: u8) -> u8 { | |||
821 | check_fix( | 870 | check_fix( |
822 | r#" | 871 | r#" |
823 | fn some_fn() { | 872 | fn some_fn() { |
824 | let whatAWeird_Formatting<|> = 10; | 873 | let whatAWeird_Formatting$0 = 10; |
825 | another_func(whatAWeird_Formatting); | 874 | another_func(whatAWeird_Formatting); |
826 | } | 875 | } |
827 | "#, | 876 | "#, |
@@ -839,7 +888,7 @@ fn some_fn() { | |||
839 | check_no_diagnostics( | 888 | check_no_diagnostics( |
840 | r#" | 889 | r#" |
841 | fn foo() { | 890 | fn foo() { |
842 | const ANOTHER_ITEM<|>: &str = "some_item"; | 891 | const ANOTHER_ITEM$0: &str = "some_item"; |
843 | } | 892 | } |
844 | "#, | 893 | "#, |
845 | ); | 894 | ); |
@@ -852,7 +901,7 @@ fn foo() { | |||
852 | pub struct TestStruct; | 901 | pub struct TestStruct; |
853 | 902 | ||
854 | impl TestStruct { | 903 | impl TestStruct { |
855 | pub fn SomeFn<|>() -> TestStruct { | 904 | pub fn SomeFn$0() -> TestStruct { |
856 | TestStruct | 905 | TestStruct |
857 | } | 906 | } |
858 | } | 907 | } |
@@ -871,7 +920,7 @@ impl TestStruct { | |||
871 | 920 | ||
872 | #[test] | 921 | #[test] |
873 | fn test_single_incorrect_case_diagnostic_in_function_name_issue_6970() { | 922 | fn test_single_incorrect_case_diagnostic_in_function_name_issue_6970() { |
874 | let input = r#"fn FOO<|>() {}"#; | 923 | let input = r#"fn FOO$0() {}"#; |
875 | let expected = r#"fn foo() {}"#; | 924 | let expected = r#"fn foo() {}"#; |
876 | 925 | ||
877 | let (analysis, file_position) = fixture::position(input); | 926 | let (analysis, file_position) = fixture::position(input); |
diff --git a/crates/ide/src/diagnostics/field_shorthand.rs b/crates/ide/src/diagnostics/field_shorthand.rs index f41bcd619..16c6ea827 100644 --- a/crates/ide/src/diagnostics/field_shorthand.rs +++ b/crates/ide/src/diagnostics/field_shorthand.rs | |||
@@ -120,7 +120,7 @@ fn main() { A { 0: 0 } } | |||
120 | struct A { a: &'static str } | 120 | struct A { a: &'static str } |
121 | fn main() { | 121 | fn main() { |
122 | let a = "haha"; | 122 | let a = "haha"; |
123 | A { a<|>: a } | 123 | A { a$0: a } |
124 | } | 124 | } |
125 | "#, | 125 | "#, |
126 | r#" | 126 | r#" |
@@ -138,7 +138,7 @@ struct A { a: &'static str, b: &'static str } | |||
138 | fn main() { | 138 | fn main() { |
139 | let a = "haha"; | 139 | let a = "haha"; |
140 | let b = "bb"; | 140 | let b = "bb"; |
141 | A { a<|>: a, b } | 141 | A { a$0: a, b } |
142 | } | 142 | } |
143 | "#, | 143 | "#, |
144 | r#" | 144 | r#" |
@@ -171,7 +171,7 @@ fn f(a: A) { let A { 0: 0 } = a; } | |||
171 | r#" | 171 | r#" |
172 | struct A { a: &'static str } | 172 | struct A { a: &'static str } |
173 | fn f(a: A) { | 173 | fn f(a: A) { |
174 | let A { a<|>: a } = a; | 174 | let A { a$0: a } = a; |
175 | } | 175 | } |
176 | "#, | 176 | "#, |
177 | r#" | 177 | r#" |
@@ -186,7 +186,7 @@ fn f(a: A) { | |||
186 | r#" | 186 | r#" |
187 | struct A { a: &'static str, b: &'static str } | 187 | struct A { a: &'static str, b: &'static str } |
188 | fn f(a: A) { | 188 | fn f(a: A) { |
189 | let A { a<|>: a, b } = a; | 189 | let A { a$0: a, b } = a; |
190 | } | 190 | } |
191 | "#, | 191 | "#, |
192 | r#" | 192 | r#" |
diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs index ec0f840e9..d7ad88ed5 100644 --- a/crates/ide/src/diagnostics/fixes.rs +++ b/crates/ide/src/diagnostics/fixes.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use hir::{ | 3 | use hir::{ |
4 | db::AstDatabase, | 4 | db::AstDatabase, |
5 | diagnostics::{ | 5 | diagnostics::{ |
6 | Diagnostic, IncorrectCase, MissingFields, MissingOkInTailExpr, NoSuchField, | 6 | Diagnostic, IncorrectCase, MissingFields, MissingOkOrSomeInTailExpr, NoSuchField, |
7 | RemoveThisSemicolon, UnresolvedModule, | 7 | RemoveThisSemicolon, UnresolvedModule, |
8 | }, | 8 | }, |
9 | HasSource, HirDisplay, InFile, Semantics, VariantDef, | 9 | HasSource, HirDisplay, InFile, Semantics, VariantDef, |
@@ -94,15 +94,17 @@ impl DiagnosticWithFix for MissingFields { | |||
94 | } | 94 | } |
95 | } | 95 | } |
96 | 96 | ||
97 | impl DiagnosticWithFix for MissingOkInTailExpr { | 97 | impl DiagnosticWithFix for MissingOkOrSomeInTailExpr { |
98 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> { | 98 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> { |
99 | let root = sema.db.parse_or_expand(self.file)?; | 99 | let root = sema.db.parse_or_expand(self.file)?; |
100 | let tail_expr = self.expr.to_node(&root); | 100 | let tail_expr = self.expr.to_node(&root); |
101 | let tail_expr_range = tail_expr.syntax().text_range(); | 101 | let tail_expr_range = tail_expr.syntax().text_range(); |
102 | let edit = TextEdit::replace(tail_expr_range, format!("Ok({})", tail_expr.syntax())); | 102 | let replacement = format!("{}({})", self.required, tail_expr.syntax()); |
103 | let edit = TextEdit::replace(tail_expr_range, replacement); | ||
103 | let source_change = | 104 | let source_change = |
104 | SourceFileEdit { file_id: self.file.original_file(sema.db), edit }.into(); | 105 | SourceFileEdit { file_id: self.file.original_file(sema.db), edit }.into(); |
105 | Some(Fix::new("Wrap with ok", source_change, tail_expr_range)) | 106 | let name = if self.required == "Ok" { "Wrap with Ok" } else { "Wrap with Some" }; |
107 | Some(Fix::new(name, source_change, tail_expr_range)) | ||
106 | } | 108 | } |
107 | } | 109 | } |
108 | 110 | ||
@@ -156,7 +158,6 @@ fn missing_record_expr_field_fix( | |||
156 | let record_fields = match VariantDef::from(def_id) { | 158 | let record_fields = match VariantDef::from(def_id) { |
157 | VariantDef::Struct(s) => { | 159 | VariantDef::Struct(s) => { |
158 | module = s.module(sema.db); | 160 | module = s.module(sema.db); |
159 | #[allow(deprecated)] | ||
160 | let source = s.source(sema.db)?; | 161 | let source = s.source(sema.db)?; |
161 | def_file_id = source.file_id; | 162 | def_file_id = source.file_id; |
162 | let fields = source.value.field_list()?; | 163 | let fields = source.value.field_list()?; |
@@ -164,14 +165,12 @@ fn missing_record_expr_field_fix( | |||
164 | } | 165 | } |
165 | VariantDef::Union(u) => { | 166 | VariantDef::Union(u) => { |
166 | module = u.module(sema.db); | 167 | module = u.module(sema.db); |
167 | #[allow(deprecated)] | ||
168 | let source = u.source(sema.db)?; | 168 | let source = u.source(sema.db)?; |
169 | def_file_id = source.file_id; | 169 | def_file_id = source.file_id; |
170 | source.value.record_field_list()? | 170 | source.value.record_field_list()? |
171 | } | 171 | } |
172 | VariantDef::Variant(e) => { | 172 | VariantDef::Variant(e) => { |
173 | module = e.module(sema.db); | 173 | module = e.module(sema.db); |
174 | #[allow(deprecated)] | ||
175 | let source = e.source(sema.db)?; | 174 | let source = e.source(sema.db)?; |
176 | def_file_id = source.file_id; | 175 | def_file_id = source.file_id; |
177 | let fields = source.value.field_list()?; | 176 | let fields = source.value.field_list()?; |
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs index e24c78301..4eecae697 100644 --- a/crates/ide/src/display/navigation_target.rs +++ b/crates/ide/src/display/navigation_target.rs | |||
@@ -215,10 +215,8 @@ impl TryToNav for Definition { | |||
215 | Definition::ModuleDef(it) => it.try_to_nav(db), | 215 | Definition::ModuleDef(it) => it.try_to_nav(db), |
216 | Definition::SelfType(it) => it.try_to_nav(db), | 216 | Definition::SelfType(it) => it.try_to_nav(db), |
217 | Definition::Local(it) => Some(it.to_nav(db)), | 217 | Definition::Local(it) => Some(it.to_nav(db)), |
218 | Definition::TypeParam(it) => it.try_to_nav(db), | 218 | Definition::GenericParam(it) => it.try_to_nav(db), |
219 | Definition::LifetimeParam(it) => it.try_to_nav(db), | ||
220 | Definition::Label(it) => Some(it.to_nav(db)), | 219 | Definition::Label(it) => Some(it.to_nav(db)), |
221 | Definition::ConstParam(it) => it.try_to_nav(db), | ||
222 | } | 220 | } |
223 | } | 221 | } |
224 | } | 222 | } |
@@ -389,6 +387,16 @@ impl TryToNav for hir::AssocItem { | |||
389 | } | 387 | } |
390 | } | 388 | } |
391 | 389 | ||
390 | impl TryToNav for hir::GenericParam { | ||
391 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { | ||
392 | match self { | ||
393 | hir::GenericParam::TypeParam(it) => it.try_to_nav(db), | ||
394 | hir::GenericParam::ConstParam(it) => it.try_to_nav(db), | ||
395 | hir::GenericParam::LifetimeParam(it) => it.try_to_nav(db), | ||
396 | } | ||
397 | } | ||
398 | } | ||
399 | |||
392 | impl ToNav for hir::Local { | 400 | impl ToNav for hir::Local { |
393 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 401 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { |
394 | let src = self.source(db); | 402 | let src = self.source(db); |
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index 367fac05e..de10406bc 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! Resolves and rewrites links in markdown documentation. | 1 | //! Resolves and rewrites links in markdown documentation. |
2 | 2 | ||
3 | use std::{convert::TryFrom, iter::once}; | 3 | use std::{convert::TryFrom, iter::once, ops::Range}; |
4 | 4 | ||
5 | use itertools::Itertools; | 5 | use itertools::Itertools; |
6 | use pulldown_cmark::{BrokenLink, CowStr, Event, InlineStr, LinkType, Options, Parser, Tag}; | 6 | use pulldown_cmark::{BrokenLink, CowStr, Event, InlineStr, LinkType, Options, Parser, Tag}; |
@@ -39,7 +39,7 @@ pub(crate) fn rewrite_links(db: &RootDatabase, markdown: &str, definition: &Defi | |||
39 | if target.contains("://") { | 39 | if target.contains("://") { |
40 | (target.to_string(), title.to_string()) | 40 | (target.to_string(), title.to_string()) |
41 | } else { | 41 | } else { |
42 | // Two posibilities: | 42 | // Two possibilities: |
43 | // * path-based links: `../../module/struct.MyStruct.html` | 43 | // * path-based links: `../../module/struct.MyStruct.html` |
44 | // * module-based links (AKA intra-doc links): `super::super::module::MyStruct` | 44 | // * module-based links (AKA intra-doc links): `super::super::module::MyStruct` |
45 | if let Some(rewritten) = rewrite_intra_doc_link(db, *definition, target, title) { | 45 | if let Some(rewritten) = rewrite_intra_doc_link(db, *definition, target, title) { |
@@ -61,6 +61,30 @@ pub(crate) fn rewrite_links(db: &RootDatabase, markdown: &str, definition: &Defi | |||
61 | out | 61 | out |
62 | } | 62 | } |
63 | 63 | ||
64 | pub(crate) fn extract_definitions_from_markdown( | ||
65 | markdown: &str, | ||
66 | ) -> Vec<(String, Option<hir::Namespace>, Range<usize>)> { | ||
67 | let mut res = vec![]; | ||
68 | let mut cb = |link: BrokenLink| { | ||
69 | Some(( | ||
70 | /*url*/ link.reference.to_owned().into(), | ||
71 | /*title*/ link.reference.to_owned().into(), | ||
72 | )) | ||
73 | }; | ||
74 | let doc = Parser::new_with_broken_link_callback(markdown, Options::empty(), Some(&mut cb)); | ||
75 | for (event, range) in doc.into_offset_iter() { | ||
76 | match event { | ||
77 | Event::Start(Tag::Link(_link_type, ref target, ref title)) => { | ||
78 | let link = if target.is_empty() { title } else { target }; | ||
79 | let (link, ns) = parse_link(link); | ||
80 | res.push((link.to_string(), ns, range)); | ||
81 | } | ||
82 | _ => {} | ||
83 | } | ||
84 | } | ||
85 | res | ||
86 | } | ||
87 | |||
64 | /// Remove all links in markdown documentation. | 88 | /// Remove all links in markdown documentation. |
65 | pub(crate) fn remove_links(markdown: &str) -> String { | 89 | pub(crate) fn remove_links(markdown: &str) -> String { |
66 | let mut drop_link = false; | 90 | let mut drop_link = false; |
@@ -192,9 +216,7 @@ fn rewrite_intra_doc_link( | |||
192 | Definition::Field(it) => it.resolve_doc_path(db, link, ns), | 216 | Definition::Field(it) => it.resolve_doc_path(db, link, ns), |
193 | Definition::SelfType(_) | 217 | Definition::SelfType(_) |
194 | | Definition::Local(_) | 218 | | Definition::Local(_) |
195 | | Definition::TypeParam(_) | 219 | | Definition::GenericParam(_) |
196 | | Definition::ConstParam(_) | ||
197 | | Definition::LifetimeParam(_) | ||
198 | | Definition::Label(_) => return None, | 220 | | Definition::Label(_) => return None, |
199 | }?; | 221 | }?; |
200 | let krate = resolved.module(db)?.krate(); | 222 | let krate = resolved.module(db)?.krate(); |
@@ -420,7 +442,7 @@ fn get_symbol_fragment(db: &dyn HirDatabase, field_or_assoc: &FieldOrAssocItem) | |||
420 | function.as_assoc_item(db).map(|assoc| assoc.container(db)), | 442 | function.as_assoc_item(db).map(|assoc| assoc.container(db)), |
421 | Some(AssocItemContainer::Trait(..)) | 443 | Some(AssocItemContainer::Trait(..)) |
422 | ); | 444 | ); |
423 | // This distinction may get more complicated when specialisation is available. | 445 | // This distinction may get more complicated when specialization is available. |
424 | // Rustdoc makes this decision based on whether a method 'has defaultness'. | 446 | // Rustdoc makes this decision based on whether a method 'has defaultness'. |
425 | // Currently this is only the case for provided trait methods. | 447 | // Currently this is only the case for provided trait methods. |
426 | if is_trait_method && !function.has_body(db) { | 448 | if is_trait_method && !function.has_body(db) { |
@@ -464,7 +486,7 @@ mod tests { | |||
464 | fn test_doc_url_struct() { | 486 | fn test_doc_url_struct() { |
465 | check( | 487 | check( |
466 | r#" | 488 | r#" |
467 | pub struct Fo<|>o; | 489 | pub struct Fo$0o; |
468 | "#, | 490 | "#, |
469 | expect![[r#"https://docs.rs/test/*/test/struct.Foo.html"#]], | 491 | expect![[r#"https://docs.rs/test/*/test/struct.Foo.html"#]], |
470 | ); | 492 | ); |
@@ -474,7 +496,7 @@ pub struct Fo<|>o; | |||
474 | fn test_doc_url_fn() { | 496 | fn test_doc_url_fn() { |
475 | check( | 497 | check( |
476 | r#" | 498 | r#" |
477 | pub fn fo<|>o() {} | 499 | pub fn fo$0o() {} |
478 | "#, | 500 | "#, |
479 | expect![[r##"https://docs.rs/test/*/test/fn.foo.html#method.foo"##]], | 501 | expect![[r##"https://docs.rs/test/*/test/fn.foo.html#method.foo"##]], |
480 | ); | 502 | ); |
@@ -487,7 +509,7 @@ pub fn fo<|>o() {} | |||
487 | pub struct Foo; | 509 | pub struct Foo; |
488 | 510 | ||
489 | impl Foo { | 511 | impl Foo { |
490 | pub fn met<|>hod() {} | 512 | pub fn met$0hod() {} |
491 | } | 513 | } |
492 | 514 | ||
493 | "#, | 515 | "#, |
@@ -500,7 +522,7 @@ impl Foo { | |||
500 | check( | 522 | check( |
501 | r#" | 523 | r#" |
502 | pub trait Bar { | 524 | pub trait Bar { |
503 | fn met<|>hod() {} | 525 | fn met$0hod() {} |
504 | } | 526 | } |
505 | 527 | ||
506 | "#, | 528 | "#, |
@@ -513,7 +535,7 @@ pub trait Bar { | |||
513 | check( | 535 | check( |
514 | r#" | 536 | r#" |
515 | pub trait Foo { | 537 | pub trait Foo { |
516 | fn met<|>hod(); | 538 | fn met$0hod(); |
517 | } | 539 | } |
518 | 540 | ||
519 | "#, | 541 | "#, |
@@ -526,7 +548,7 @@ pub trait Foo { | |||
526 | check( | 548 | check( |
527 | r#" | 549 | r#" |
528 | pub struct Foo { | 550 | pub struct Foo { |
529 | pub fie<|>ld: () | 551 | pub fie$0ld: () |
530 | } | 552 | } |
531 | 553 | ||
532 | "#, | 554 | "#, |
@@ -539,7 +561,7 @@ pub struct Foo { | |||
539 | check( | 561 | check( |
540 | r#" | 562 | r#" |
541 | pub mod foo { | 563 | pub mod foo { |
542 | pub mod ba<|>r {} | 564 | pub mod ba$0r {} |
543 | } | 565 | } |
544 | "#, | 566 | "#, |
545 | expect![[r#"https://docs.rs/test/*/test/foo/bar/index.html"#]], | 567 | expect![[r#"https://docs.rs/test/*/test/foo/bar/index.html"#]], |
@@ -564,7 +586,7 @@ pub mod wrapper { | |||
564 | } | 586 | } |
565 | 587 | ||
566 | fn foo() { | 588 | fn foo() { |
567 | let bar: wrapper::It<|>em; | 589 | let bar: wrapper::It$0em; |
568 | } | 590 | } |
569 | "#, | 591 | "#, |
570 | expect![[r#"https://docs.rs/test/*/test/wrapper/module/struct.Item.html"#]], | 592 | expect![[r#"https://docs.rs/test/*/test/wrapper/module/struct.Item.html"#]], |
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index 8d75e0f05..ffb3a6f7d 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs | |||
@@ -144,7 +144,7 @@ macro_rules! foo { | |||
144 | macro_rules! baz { | 144 | macro_rules! baz { |
145 | () => { foo!(); } | 145 | () => { foo!(); } |
146 | } | 146 | } |
147 | f<|>oo!(); | 147 | f$0oo!(); |
148 | "#, | 148 | "#, |
149 | expect![[r#" | 149 | expect![[r#" |
150 | foo | 150 | foo |
@@ -165,7 +165,7 @@ macro_rules! foo { | |||
165 | } | 165 | } |
166 | } | 166 | } |
167 | } | 167 | } |
168 | f<|>oo!(); | 168 | f$0oo!(); |
169 | "#, | 169 | "#, |
170 | expect![[r#" | 170 | expect![[r#" |
171 | foo | 171 | foo |
@@ -192,7 +192,7 @@ macro_rules! match_ast { | |||
192 | } | 192 | } |
193 | 193 | ||
194 | fn main() { | 194 | fn main() { |
195 | mat<|>ch_ast! { | 195 | mat$0ch_ast! { |
196 | match container { | 196 | match container { |
197 | ast::TraitDef(it) => {}, | 197 | ast::TraitDef(it) => {}, |
198 | ast::ImplDef(it) => {}, | 198 | ast::ImplDef(it) => {}, |
@@ -226,7 +226,7 @@ macro_rules! match_ast { | |||
226 | 226 | ||
227 | fn main() { | 227 | fn main() { |
228 | let p = f(|it| { | 228 | let p = f(|it| { |
229 | let res = mat<|>ch_ast! { match c {}}; | 229 | let res = mat$0ch_ast! { match c {}}; |
230 | Some(res) | 230 | Some(res) |
231 | })?; | 231 | })?; |
232 | } | 232 | } |
@@ -250,7 +250,7 @@ macro_rules! foo { | |||
250 | } | 250 | } |
251 | 251 | ||
252 | fn main() { | 252 | fn main() { |
253 | let res = fo<|>o!(); | 253 | let res = fo$0o!(); |
254 | } | 254 | } |
255 | "#, | 255 | "#, |
256 | expect![[r#" | 256 | expect![[r#" |
@@ -272,7 +272,7 @@ macro_rules! foo { | |||
272 | } | 272 | } |
273 | 273 | ||
274 | fn main() { | 274 | fn main() { |
275 | let res = fo<|>o!(); | 275 | let res = fo$0o!(); |
276 | } | 276 | } |
277 | "#, | 277 | "#, |
278 | expect![[r#" | 278 | expect![[r#" |
diff --git a/crates/ide/src/extend_selection.rs b/crates/ide/src/extend_selection.rs index 6f3022dfd..56418c960 100644 --- a/crates/ide/src/extend_selection.rs +++ b/crates/ide/src/extend_selection.rs | |||
@@ -334,29 +334,29 @@ mod tests { | |||
334 | 334 | ||
335 | #[test] | 335 | #[test] |
336 | fn test_extend_selection_arith() { | 336 | fn test_extend_selection_arith() { |
337 | do_check(r#"fn foo() { <|>1 + 1 }"#, &["1", "1 + 1", "{ 1 + 1 }"]); | 337 | do_check(r#"fn foo() { $01 + 1 }"#, &["1", "1 + 1", "{ 1 + 1 }"]); |
338 | } | 338 | } |
339 | 339 | ||
340 | #[test] | 340 | #[test] |
341 | fn test_extend_selection_list() { | 341 | fn test_extend_selection_list() { |
342 | do_check(r#"fn foo(<|>x: i32) {}"#, &["x", "x: i32"]); | 342 | do_check(r#"fn foo($0x: i32) {}"#, &["x", "x: i32"]); |
343 | do_check(r#"fn foo(<|>x: i32, y: i32) {}"#, &["x", "x: i32", "x: i32, "]); | 343 | do_check(r#"fn foo($0x: i32, y: i32) {}"#, &["x", "x: i32", "x: i32, "]); |
344 | do_check(r#"fn foo(<|>x: i32,y: i32) {}"#, &["x", "x: i32", "x: i32,", "(x: i32,y: i32)"]); | 344 | do_check(r#"fn foo($0x: i32,y: i32) {}"#, &["x", "x: i32", "x: i32,", "(x: i32,y: i32)"]); |
345 | do_check(r#"fn foo(x: i32, <|>y: i32) {}"#, &["y", "y: i32", ", y: i32"]); | 345 | do_check(r#"fn foo(x: i32, $0y: i32) {}"#, &["y", "y: i32", ", y: i32"]); |
346 | do_check(r#"fn foo(x: i32, <|>y: i32, ) {}"#, &["y", "y: i32", "y: i32, "]); | 346 | do_check(r#"fn foo(x: i32, $0y: i32, ) {}"#, &["y", "y: i32", "y: i32, "]); |
347 | do_check(r#"fn foo(x: i32,<|>y: i32) {}"#, &["y", "y: i32", ",y: i32"]); | 347 | do_check(r#"fn foo(x: i32,$0y: i32) {}"#, &["y", "y: i32", ",y: i32"]); |
348 | 348 | ||
349 | do_check(r#"const FOO: [usize; 2] = [ 22<|> , 33];"#, &["22", "22 , "]); | 349 | do_check(r#"const FOO: [usize; 2] = [ 22$0 , 33];"#, &["22", "22 , "]); |
350 | do_check(r#"const FOO: [usize; 2] = [ 22 , 33<|>];"#, &["33", ", 33"]); | 350 | do_check(r#"const FOO: [usize; 2] = [ 22 , 33$0];"#, &["33", ", 33"]); |
351 | do_check(r#"const FOO: [usize; 2] = [ 22 , 33<|> ,];"#, &["33", "33 ,", "[ 22 , 33 ,]"]); | 351 | do_check(r#"const FOO: [usize; 2] = [ 22 , 33$0 ,];"#, &["33", "33 ,", "[ 22 , 33 ,]"]); |
352 | 352 | ||
353 | do_check(r#"fn main() { (1, 2<|>) }"#, &["2", ", 2", "(1, 2)"]); | 353 | do_check(r#"fn main() { (1, 2$0) }"#, &["2", ", 2", "(1, 2)"]); |
354 | 354 | ||
355 | do_check( | 355 | do_check( |
356 | r#" | 356 | r#" |
357 | const FOO: [usize; 2] = [ | 357 | const FOO: [usize; 2] = [ |
358 | 22, | 358 | 22, |
359 | <|>33, | 359 | $033, |
360 | ]"#, | 360 | ]"#, |
361 | &["33", "33,"], | 361 | &["33", "33,"], |
362 | ); | 362 | ); |
@@ -365,7 +365,7 @@ const FOO: [usize; 2] = [ | |||
365 | r#" | 365 | r#" |
366 | const FOO: [usize; 2] = [ | 366 | const FOO: [usize; 2] = [ |
367 | 22 | 367 | 22 |
368 | , 33<|>, | 368 | , 33$0, |
369 | ]"#, | 369 | ]"#, |
370 | &["33", "33,"], | 370 | &["33", "33,"], |
371 | ); | 371 | ); |
@@ -376,7 +376,7 @@ const FOO: [usize; 2] = [ | |||
376 | do_check( | 376 | do_check( |
377 | r#" | 377 | r#" |
378 | impl S { | 378 | impl S { |
379 | <|> fn foo() { | 379 | $0 fn foo() { |
380 | 380 | ||
381 | } | 381 | } |
382 | }"#, | 382 | }"#, |
@@ -393,7 +393,7 @@ struct A; | |||
393 | /// bla | 393 | /// bla |
394 | /// bla | 394 | /// bla |
395 | struct B { | 395 | struct B { |
396 | <|> | 396 | $0 |
397 | } | 397 | } |
398 | "#, | 398 | "#, |
399 | &["\n \n", "{\n \n}", "/// bla\n/// bla\nstruct B {\n \n}"], | 399 | &["\n \n", "{\n \n}", "/// bla\n/// bla\nstruct B {\n \n}"], |
@@ -407,7 +407,7 @@ struct B { | |||
407 | fn bar(){} | 407 | fn bar(){} |
408 | 408 | ||
409 | // fn foo() { | 409 | // fn foo() { |
410 | // 1 + <|>1 | 410 | // 1 + $01 |
411 | // } | 411 | // } |
412 | 412 | ||
413 | // fn foo(){} | 413 | // fn foo(){} |
@@ -419,7 +419,7 @@ fn bar(){} | |||
419 | r#" | 419 | r#" |
420 | // #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 420 | // #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
421 | // pub enum Direction { | 421 | // pub enum Direction { |
422 | // <|> Next, | 422 | // $0 Next, |
423 | // Prev | 423 | // Prev |
424 | // } | 424 | // } |
425 | "#, | 425 | "#, |
@@ -433,27 +433,27 @@ fn bar(){} | |||
433 | r#" | 433 | r#" |
434 | /* | 434 | /* |
435 | foo | 435 | foo |
436 | _bar1<|>*/ | 436 | _bar1$0*/ |
437 | "#, | 437 | "#, |
438 | &["_bar1", "/*\nfoo\n_bar1*/"], | 438 | &["_bar1", "/*\nfoo\n_bar1*/"], |
439 | ); | 439 | ); |
440 | 440 | ||
441 | do_check(r#"//!<|>foo_2 bar"#, &["foo_2", "//!foo_2 bar"]); | 441 | do_check(r#"//!$0foo_2 bar"#, &["foo_2", "//!foo_2 bar"]); |
442 | 442 | ||
443 | do_check(r#"/<|>/foo bar"#, &["//foo bar"]); | 443 | do_check(r#"/$0/foo bar"#, &["//foo bar"]); |
444 | } | 444 | } |
445 | 445 | ||
446 | #[test] | 446 | #[test] |
447 | fn test_extend_selection_prefer_idents() { | 447 | fn test_extend_selection_prefer_idents() { |
448 | do_check( | 448 | do_check( |
449 | r#" | 449 | r#" |
450 | fn main() { foo<|>+bar;} | 450 | fn main() { foo$0+bar;} |
451 | "#, | 451 | "#, |
452 | &["foo", "foo+bar"], | 452 | &["foo", "foo+bar"], |
453 | ); | 453 | ); |
454 | do_check( | 454 | do_check( |
455 | r#" | 455 | r#" |
456 | fn main() { foo+<|>bar;} | 456 | fn main() { foo+$0bar;} |
457 | "#, | 457 | "#, |
458 | &["bar", "foo+bar"], | 458 | &["bar", "foo+bar"], |
459 | ); | 459 | ); |
@@ -461,18 +461,18 @@ fn main() { foo+<|>bar;} | |||
461 | 461 | ||
462 | #[test] | 462 | #[test] |
463 | fn test_extend_selection_prefer_lifetimes() { | 463 | fn test_extend_selection_prefer_lifetimes() { |
464 | do_check(r#"fn foo<<|>'a>() {}"#, &["'a", "<'a>"]); | 464 | do_check(r#"fn foo<$0'a>() {}"#, &["'a", "<'a>"]); |
465 | do_check(r#"fn foo<'a<|>>() {}"#, &["'a", "<'a>"]); | 465 | do_check(r#"fn foo<'a$0>() {}"#, &["'a", "<'a>"]); |
466 | } | 466 | } |
467 | 467 | ||
468 | #[test] | 468 | #[test] |
469 | fn test_extend_selection_select_first_word() { | 469 | fn test_extend_selection_select_first_word() { |
470 | do_check(r#"// foo bar b<|>az quxx"#, &["baz", "// foo bar baz quxx"]); | 470 | do_check(r#"// foo bar b$0az quxx"#, &["baz", "// foo bar baz quxx"]); |
471 | do_check( | 471 | do_check( |
472 | r#" | 472 | r#" |
473 | impl S { | 473 | impl S { |
474 | fn foo() { | 474 | fn foo() { |
475 | // hel<|>lo world | 475 | // hel$0lo world |
476 | } | 476 | } |
477 | } | 477 | } |
478 | "#, | 478 | "#, |
@@ -486,7 +486,7 @@ fn foo() { | |||
486 | r#" | 486 | r#" |
487 | fn bar(){} | 487 | fn bar(){} |
488 | 488 | ||
489 | " fn f<|>oo() {" | 489 | " fn f$0oo() {" |
490 | "#, | 490 | "#, |
491 | &["foo", "\" fn foo() {\""], | 491 | &["foo", "\" fn foo() {\""], |
492 | ); | 492 | ); |
@@ -499,7 +499,7 @@ fn bar(){} | |||
499 | fn foo<R>() | 499 | fn foo<R>() |
500 | where | 500 | where |
501 | R: req::Request + 'static, | 501 | R: req::Request + 'static, |
502 | R::Params: DeserializeOwned<|> + panic::UnwindSafe + 'static, | 502 | R::Params: DeserializeOwned$0 + panic::UnwindSafe + 'static, |
503 | R::Result: Serialize + 'static, | 503 | R::Result: Serialize + 'static, |
504 | "#, | 504 | "#, |
505 | &[ | 505 | &[ |
@@ -510,26 +510,26 @@ fn foo<R>() | |||
510 | "R::Params: DeserializeOwned + panic::UnwindSafe + 'static,", | 510 | "R::Params: DeserializeOwned + panic::UnwindSafe + 'static,", |
511 | ], | 511 | ], |
512 | ); | 512 | ); |
513 | do_check(r#"fn foo<T>() where T: <|>Copy"#, &["Copy"]); | 513 | do_check(r#"fn foo<T>() where T: $0Copy"#, &["Copy"]); |
514 | do_check(r#"fn foo<T>() where T: <|>Copy + Display"#, &["Copy", "Copy + "]); | 514 | do_check(r#"fn foo<T>() where T: $0Copy + Display"#, &["Copy", "Copy + "]); |
515 | do_check(r#"fn foo<T>() where T: <|>Copy +Display"#, &["Copy", "Copy +"]); | 515 | do_check(r#"fn foo<T>() where T: $0Copy +Display"#, &["Copy", "Copy +"]); |
516 | do_check(r#"fn foo<T>() where T: <|>Copy+Display"#, &["Copy", "Copy+"]); | 516 | do_check(r#"fn foo<T>() where T: $0Copy+Display"#, &["Copy", "Copy+"]); |
517 | do_check(r#"fn foo<T>() where T: Copy + <|>Display"#, &["Display", "+ Display"]); | 517 | do_check(r#"fn foo<T>() where T: Copy + $0Display"#, &["Display", "+ Display"]); |
518 | do_check(r#"fn foo<T>() where T: Copy + <|>Display + Sync"#, &["Display", "Display + "]); | 518 | do_check(r#"fn foo<T>() where T: Copy + $0Display + Sync"#, &["Display", "Display + "]); |
519 | do_check(r#"fn foo<T>() where T: Copy +<|>Display"#, &["Display", "+Display"]); | 519 | do_check(r#"fn foo<T>() where T: Copy +$0Display"#, &["Display", "+Display"]); |
520 | } | 520 | } |
521 | 521 | ||
522 | #[test] | 522 | #[test] |
523 | fn test_extend_trait_bounds_list_inline() { | 523 | fn test_extend_trait_bounds_list_inline() { |
524 | do_check(r#"fn foo<T: <|>Copy>() {}"#, &["Copy"]); | 524 | do_check(r#"fn foo<T: $0Copy>() {}"#, &["Copy"]); |
525 | do_check(r#"fn foo<T: <|>Copy + Display>() {}"#, &["Copy", "Copy + "]); | 525 | do_check(r#"fn foo<T: $0Copy + Display>() {}"#, &["Copy", "Copy + "]); |
526 | do_check(r#"fn foo<T: <|>Copy +Display>() {}"#, &["Copy", "Copy +"]); | 526 | do_check(r#"fn foo<T: $0Copy +Display>() {}"#, &["Copy", "Copy +"]); |
527 | do_check(r#"fn foo<T: <|>Copy+Display>() {}"#, &["Copy", "Copy+"]); | 527 | do_check(r#"fn foo<T: $0Copy+Display>() {}"#, &["Copy", "Copy+"]); |
528 | do_check(r#"fn foo<T: Copy + <|>Display>() {}"#, &["Display", "+ Display"]); | 528 | do_check(r#"fn foo<T: Copy + $0Display>() {}"#, &["Display", "+ Display"]); |
529 | do_check(r#"fn foo<T: Copy + <|>Display + Sync>() {}"#, &["Display", "Display + "]); | 529 | do_check(r#"fn foo<T: Copy + $0Display + Sync>() {}"#, &["Display", "Display + "]); |
530 | do_check(r#"fn foo<T: Copy +<|>Display>() {}"#, &["Display", "+Display"]); | 530 | do_check(r#"fn foo<T: Copy +$0Display>() {}"#, &["Display", "+Display"]); |
531 | do_check( | 531 | do_check( |
532 | r#"fn foo<T: Copy<|> + Display, U: Copy>() {}"#, | 532 | r#"fn foo<T: Copy$0 + Display, U: Copy>() {}"#, |
533 | &[ | 533 | &[ |
534 | "Copy", | 534 | "Copy", |
535 | "Copy + ", | 535 | "Copy + ", |
@@ -544,19 +544,19 @@ fn foo<R>() | |||
544 | #[test] | 544 | #[test] |
545 | fn test_extend_selection_on_tuple_in_type() { | 545 | fn test_extend_selection_on_tuple_in_type() { |
546 | do_check( | 546 | do_check( |
547 | r#"fn main() { let _: (krate, <|>_crate_def_map, module_id) = (); }"#, | 547 | r#"fn main() { let _: (krate, $0_crate_def_map, module_id) = (); }"#, |
548 | &["_crate_def_map", "_crate_def_map, ", "(krate, _crate_def_map, module_id)"], | 548 | &["_crate_def_map", "_crate_def_map, ", "(krate, _crate_def_map, module_id)"], |
549 | ); | 549 | ); |
550 | // white space variations | 550 | // white space variations |
551 | do_check( | 551 | do_check( |
552 | r#"fn main() { let _: (krate,<|>_crate_def_map,module_id) = (); }"#, | 552 | r#"fn main() { let _: (krate,$0_crate_def_map,module_id) = (); }"#, |
553 | &["_crate_def_map", "_crate_def_map,", "(krate,_crate_def_map,module_id)"], | 553 | &["_crate_def_map", "_crate_def_map,", "(krate,_crate_def_map,module_id)"], |
554 | ); | 554 | ); |
555 | do_check( | 555 | do_check( |
556 | r#" | 556 | r#" |
557 | fn main() { let _: ( | 557 | fn main() { let _: ( |
558 | krate, | 558 | krate, |
559 | _crate<|>_def_map, | 559 | _crate$0_def_map, |
560 | module_id | 560 | module_id |
561 | ) = (); }"#, | 561 | ) = (); }"#, |
562 | &[ | 562 | &[ |
@@ -570,19 +570,19 @@ fn main() { let _: ( | |||
570 | #[test] | 570 | #[test] |
571 | fn test_extend_selection_on_tuple_in_rvalue() { | 571 | fn test_extend_selection_on_tuple_in_rvalue() { |
572 | do_check( | 572 | do_check( |
573 | r#"fn main() { let var = (krate, _crate_def_map<|>, module_id); }"#, | 573 | r#"fn main() { let var = (krate, _crate_def_map$0, module_id); }"#, |
574 | &["_crate_def_map", "_crate_def_map, ", "(krate, _crate_def_map, module_id)"], | 574 | &["_crate_def_map", "_crate_def_map, ", "(krate, _crate_def_map, module_id)"], |
575 | ); | 575 | ); |
576 | // white space variations | 576 | // white space variations |
577 | do_check( | 577 | do_check( |
578 | r#"fn main() { let var = (krate,_crate<|>_def_map,module_id); }"#, | 578 | r#"fn main() { let var = (krate,_crate$0_def_map,module_id); }"#, |
579 | &["_crate_def_map", "_crate_def_map,", "(krate,_crate_def_map,module_id)"], | 579 | &["_crate_def_map", "_crate_def_map,", "(krate,_crate_def_map,module_id)"], |
580 | ); | 580 | ); |
581 | do_check( | 581 | do_check( |
582 | r#" | 582 | r#" |
583 | fn main() { let var = ( | 583 | fn main() { let var = ( |
584 | krate, | 584 | krate, |
585 | _crate_def_map<|>, | 585 | _crate_def_map$0, |
586 | module_id | 586 | module_id |
587 | ); }"#, | 587 | ); }"#, |
588 | &[ | 588 | &[ |
@@ -596,19 +596,19 @@ fn main() { let var = ( | |||
596 | #[test] | 596 | #[test] |
597 | fn test_extend_selection_on_tuple_pat() { | 597 | fn test_extend_selection_on_tuple_pat() { |
598 | do_check( | 598 | do_check( |
599 | r#"fn main() { let (krate, _crate_def_map<|>, module_id) = var; }"#, | 599 | r#"fn main() { let (krate, _crate_def_map$0, module_id) = var; }"#, |
600 | &["_crate_def_map", "_crate_def_map, ", "(krate, _crate_def_map, module_id)"], | 600 | &["_crate_def_map", "_crate_def_map, ", "(krate, _crate_def_map, module_id)"], |
601 | ); | 601 | ); |
602 | // white space variations | 602 | // white space variations |
603 | do_check( | 603 | do_check( |
604 | r#"fn main() { let (krate,_crate<|>_def_map,module_id) = var; }"#, | 604 | r#"fn main() { let (krate,_crate$0_def_map,module_id) = var; }"#, |
605 | &["_crate_def_map", "_crate_def_map,", "(krate,_crate_def_map,module_id)"], | 605 | &["_crate_def_map", "_crate_def_map,", "(krate,_crate_def_map,module_id)"], |
606 | ); | 606 | ); |
607 | do_check( | 607 | do_check( |
608 | r#" | 608 | r#" |
609 | fn main() { let ( | 609 | fn main() { let ( |
610 | krate, | 610 | krate, |
611 | _crate_def_map<|>, | 611 | _crate_def_map$0, |
612 | module_id | 612 | module_id |
613 | ) = var; }"#, | 613 | ) = var; }"#, |
614 | &[ | 614 | &[ |
@@ -623,7 +623,7 @@ fn main() { let ( | |||
623 | fn extend_selection_inside_macros() { | 623 | fn extend_selection_inside_macros() { |
624 | do_check( | 624 | do_check( |
625 | r#"macro_rules! foo { ($item:item) => {$item} } | 625 | r#"macro_rules! foo { ($item:item) => {$item} } |
626 | foo!{fn hello(na<|>me:usize){}}"#, | 626 | foo!{fn hello(na$0me:usize){}}"#, |
627 | &[ | 627 | &[ |
628 | "name", | 628 | "name", |
629 | "name:usize", | 629 | "name:usize", |
@@ -640,7 +640,7 @@ fn main() { let ( | |||
640 | do_check( | 640 | do_check( |
641 | r#" macro_rules! foo2 { ($item:item) => {$item} } | 641 | r#" macro_rules! foo2 { ($item:item) => {$item} } |
642 | macro_rules! foo { ($item:item) => {foo2!($item);} } | 642 | macro_rules! foo { ($item:item) => {foo2!($item);} } |
643 | foo!{fn hello(na<|>me:usize){}}"#, | 643 | foo!{fn hello(na$0me:usize){}}"#, |
644 | &[ | 644 | &[ |
645 | "name", | 645 | "name", |
646 | "name:usize", | 646 | "name:usize", |
diff --git a/crates/ide/src/fixture.rs b/crates/ide/src/fixture.rs index eb57f9224..cc8218885 100644 --- a/crates/ide/src/fixture.rs +++ b/crates/ide/src/fixture.rs | |||
@@ -20,12 +20,12 @@ pub(crate) fn files(ra_fixture: &str) -> (Analysis, Vec<FileId>) { | |||
20 | (host.analysis(), change_fixture.files) | 20 | (host.analysis(), change_fixture.files) |
21 | } | 21 | } |
22 | 22 | ||
23 | /// Creates analysis from a multi-file fixture, returns positions marked with <|>. | 23 | /// Creates analysis from a multi-file fixture, returns positions marked with $0. |
24 | pub(crate) fn position(ra_fixture: &str) -> (Analysis, FilePosition) { | 24 | pub(crate) fn position(ra_fixture: &str) -> (Analysis, FilePosition) { |
25 | let mut host = AnalysisHost::default(); | 25 | let mut host = AnalysisHost::default(); |
26 | let change_fixture = ChangeFixture::parse(ra_fixture); | 26 | let change_fixture = ChangeFixture::parse(ra_fixture); |
27 | host.db.apply_change(change_fixture.change); | 27 | host.db.apply_change(change_fixture.change); |
28 | let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker (<|>)"); | 28 | let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker ($0)"); |
29 | let offset = match range_or_offset { | 29 | let offset = match range_or_offset { |
30 | RangeOrOffset::Range(_) => panic!(), | 30 | RangeOrOffset::Range(_) => panic!(), |
31 | RangeOrOffset::Offset(it) => it, | 31 | RangeOrOffset::Offset(it) => it, |
@@ -33,12 +33,12 @@ pub(crate) fn position(ra_fixture: &str) -> (Analysis, FilePosition) { | |||
33 | (host.analysis(), FilePosition { file_id, offset }) | 33 | (host.analysis(), FilePosition { file_id, offset }) |
34 | } | 34 | } |
35 | 35 | ||
36 | /// Creates analysis for a single file, returns range marked with a pair of <|>. | 36 | /// Creates analysis for a single file, returns range marked with a pair of $0. |
37 | pub(crate) fn range(ra_fixture: &str) -> (Analysis, FileRange) { | 37 | pub(crate) fn range(ra_fixture: &str) -> (Analysis, FileRange) { |
38 | let mut host = AnalysisHost::default(); | 38 | let mut host = AnalysisHost::default(); |
39 | let change_fixture = ChangeFixture::parse(ra_fixture); | 39 | let change_fixture = ChangeFixture::parse(ra_fixture); |
40 | host.db.apply_change(change_fixture.change); | 40 | host.db.apply_change(change_fixture.change); |
41 | let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker (<|>)"); | 41 | let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker ($0)"); |
42 | let range = match range_or_offset { | 42 | let range = match range_or_offset { |
43 | RangeOrOffset::Range(it) => it, | 43 | RangeOrOffset::Range(it) => it, |
44 | RangeOrOffset::Offset(_) => panic!(), | 44 | RangeOrOffset::Offset(_) => panic!(), |
@@ -46,12 +46,12 @@ pub(crate) fn range(ra_fixture: &str) -> (Analysis, FileRange) { | |||
46 | (host.analysis(), FileRange { file_id, range }) | 46 | (host.analysis(), FileRange { file_id, range }) |
47 | } | 47 | } |
48 | 48 | ||
49 | /// Creates analysis from a multi-file fixture, returns positions marked with <|>. | 49 | /// Creates analysis from a multi-file fixture, returns positions marked with $0. |
50 | pub(crate) fn annotations(ra_fixture: &str) -> (Analysis, FilePosition, Vec<(FileRange, String)>) { | 50 | pub(crate) fn annotations(ra_fixture: &str) -> (Analysis, FilePosition, Vec<(FileRange, String)>) { |
51 | let mut host = AnalysisHost::default(); | 51 | let mut host = AnalysisHost::default(); |
52 | let change_fixture = ChangeFixture::parse(ra_fixture); | 52 | let change_fixture = ChangeFixture::parse(ra_fixture); |
53 | host.db.apply_change(change_fixture.change); | 53 | host.db.apply_change(change_fixture.change); |
54 | let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker (<|>)"); | 54 | let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker ($0)"); |
55 | let offset = match range_or_offset { | 55 | let offset = match range_or_offset { |
56 | RangeOrOffset::Range(_) => panic!(), | 56 | RangeOrOffset::Range(_) => panic!(), |
57 | RangeOrOffset::Offset(it) => it, | 57 | RangeOrOffset::Offset(it) => it, |
diff --git a/crates/ide/src/fn_references.rs b/crates/ide/src/fn_references.rs index 5cbbe306e..f6e5a522b 100644 --- a/crates/ide/src/fn_references.rs +++ b/crates/ide/src/fn_references.rs | |||
@@ -34,7 +34,7 @@ mod tests { | |||
34 | fn test_find_all_methods() { | 34 | fn test_find_all_methods() { |
35 | let (analysis, pos) = fixture::position( | 35 | let (analysis, pos) = fixture::position( |
36 | r#" | 36 | r#" |
37 | fn private_fn() {<|>} | 37 | fn private_fn() {$0} |
38 | 38 | ||
39 | pub fn pub_fn() {} | 39 | pub fn pub_fn() {} |
40 | 40 | ||
@@ -51,7 +51,7 @@ mod tests { | |||
51 | let (analysis, pos) = fixture::position( | 51 | let (analysis, pos) = fixture::position( |
52 | r#" | 52 | r#" |
53 | trait Foo { | 53 | trait Foo { |
54 | fn bar() {<|>} | 54 | fn bar() {$0} |
55 | fn baz() {} | 55 | fn baz() {} |
56 | } | 56 | } |
57 | "#, | 57 | "#, |
@@ -67,7 +67,7 @@ mod tests { | |||
67 | r#" | 67 | r#" |
68 | //- /lib.rs | 68 | //- /lib.rs |
69 | #[test] | 69 | #[test] |
70 | fn foo() {<|>} | 70 | fn foo() {$0} |
71 | 71 | ||
72 | pub fn pub_fn() {} | 72 | pub fn pub_fn() {} |
73 | 73 | ||
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index 912144f8b..cd4afc804 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs | |||
@@ -1,14 +1,18 @@ | |||
1 | use either::Either; | 1 | use either::Either; |
2 | use hir::Semantics; | 2 | use hir::{HasAttrs, ModuleDef, Semantics}; |
3 | use ide_db::{ | 3 | use ide_db::{ |
4 | base_db::FileId, | 4 | base_db::FileId, |
5 | defs::{NameClass, NameRefClass}, | 5 | defs::{Definition, NameClass, NameRefClass}, |
6 | symbol_index, RootDatabase, | 6 | symbol_index, RootDatabase, |
7 | }; | 7 | }; |
8 | use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; | 8 | use syntax::{ |
9 | ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextSize, TokenAtOffset, T, | ||
10 | }; | ||
9 | 11 | ||
10 | use crate::{ | 12 | use crate::{ |
11 | display::{ToNav, TryToNav}, | 13 | display::{ToNav, TryToNav}, |
14 | doc_links::extract_definitions_from_markdown, | ||
15 | runnables::doc_owner_to_def, | ||
12 | FilePosition, NavigationTarget, RangeInfo, SymbolKind, | 16 | FilePosition, NavigationTarget, RangeInfo, SymbolKind, |
13 | }; | 17 | }; |
14 | 18 | ||
@@ -30,6 +34,10 @@ pub(crate) fn goto_definition( | |||
30 | let original_token = pick_best(file.token_at_offset(position.offset))?; | 34 | let original_token = pick_best(file.token_at_offset(position.offset))?; |
31 | let token = sema.descend_into_macros(original_token.clone()); | 35 | let token = sema.descend_into_macros(original_token.clone()); |
32 | let parent = token.parent(); | 36 | let parent = token.parent(); |
37 | if let Some(comment) = ast::Comment::cast(token.clone()) { | ||
38 | let nav = def_for_doc_comment(&sema, position, &comment)?.try_to_nav(db)?; | ||
39 | return Some(RangeInfo::new(original_token.text_range(), vec![nav])); | ||
40 | } | ||
33 | 41 | ||
34 | let nav_targets = match_ast! { | 42 | let nav_targets = match_ast! { |
35 | match parent { | 43 | match parent { |
@@ -68,11 +76,58 @@ pub(crate) fn goto_definition( | |||
68 | Some(RangeInfo::new(original_token.text_range(), nav_targets)) | 76 | Some(RangeInfo::new(original_token.text_range(), nav_targets)) |
69 | } | 77 | } |
70 | 78 | ||
79 | fn def_for_doc_comment( | ||
80 | sema: &Semantics<RootDatabase>, | ||
81 | position: FilePosition, | ||
82 | doc_comment: &ast::Comment, | ||
83 | ) -> Option<hir::ModuleDef> { | ||
84 | let parent = doc_comment.syntax().parent(); | ||
85 | let (link, ns) = extract_positioned_link_from_comment(position, doc_comment)?; | ||
86 | |||
87 | let def = doc_owner_to_def(sema, parent)?; | ||
88 | match def { | ||
89 | Definition::ModuleDef(def) => match def { | ||
90 | ModuleDef::Module(it) => it.resolve_doc_path(sema.db, &link, ns), | ||
91 | ModuleDef::Function(it) => it.resolve_doc_path(sema.db, &link, ns), | ||
92 | ModuleDef::Adt(it) => it.resolve_doc_path(sema.db, &link, ns), | ||
93 | ModuleDef::Variant(it) => it.resolve_doc_path(sema.db, &link, ns), | ||
94 | ModuleDef::Const(it) => it.resolve_doc_path(sema.db, &link, ns), | ||
95 | ModuleDef::Static(it) => it.resolve_doc_path(sema.db, &link, ns), | ||
96 | ModuleDef::Trait(it) => it.resolve_doc_path(sema.db, &link, ns), | ||
97 | ModuleDef::TypeAlias(it) => it.resolve_doc_path(sema.db, &link, ns), | ||
98 | ModuleDef::BuiltinType(_) => return None, | ||
99 | }, | ||
100 | Definition::Macro(it) => it.resolve_doc_path(sema.db, &link, ns), | ||
101 | Definition::Field(it) => it.resolve_doc_path(sema.db, &link, ns), | ||
102 | Definition::SelfType(_) | ||
103 | | Definition::Local(_) | ||
104 | | Definition::GenericParam(_) | ||
105 | | Definition::Label(_) => return None, | ||
106 | } | ||
107 | } | ||
108 | |||
109 | fn extract_positioned_link_from_comment( | ||
110 | position: FilePosition, | ||
111 | comment: &ast::Comment, | ||
112 | ) -> Option<(String, Option<hir::Namespace>)> { | ||
113 | let comment_range = comment.syntax().text_range(); | ||
114 | let doc_comment = comment.doc_comment()?; | ||
115 | let def_links = extract_definitions_from_markdown(doc_comment); | ||
116 | let (def_link, ns, _) = def_links.iter().min_by_key(|(_, _, def_link_range)| { | ||
117 | let matched_position = comment_range.start() + TextSize::from(def_link_range.start as u32); | ||
118 | match position.offset.checked_sub(matched_position) { | ||
119 | Some(distance) => distance, | ||
120 | None => comment_range.end(), | ||
121 | } | ||
122 | })?; | ||
123 | Some((def_link.to_string(), ns.clone())) | ||
124 | } | ||
125 | |||
71 | fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | 126 | fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { |
72 | return tokens.max_by_key(priority); | 127 | return tokens.max_by_key(priority); |
73 | fn priority(n: &SyntaxToken) -> usize { | 128 | fn priority(n: &SyntaxToken) -> usize { |
74 | match n.kind() { | 129 | match n.kind() { |
75 | IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] => 2, | 130 | IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] | COMMENT => 2, |
76 | kind if kind.is_trivia() => 0, | 131 | kind if kind.is_trivia() => 0, |
77 | _ => 1, | 132 | _ => 1, |
78 | } | 133 | } |
@@ -166,7 +221,7 @@ mod tests { | |||
166 | check( | 221 | check( |
167 | r#" | 222 | r#" |
168 | //- /main.rs crate:main deps:std | 223 | //- /main.rs crate:main deps:std |
169 | extern crate std<|>; | 224 | extern crate std$0; |
170 | //- /std/lib.rs crate:std | 225 | //- /std/lib.rs crate:std |
171 | // empty | 226 | // empty |
172 | //^ file | 227 | //^ file |
@@ -179,7 +234,7 @@ mod tests { | |||
179 | check( | 234 | check( |
180 | r#" | 235 | r#" |
181 | //- /main.rs crate:main deps:std | 236 | //- /main.rs crate:main deps:std |
182 | extern crate std as abc<|>; | 237 | extern crate std as abc$0; |
183 | //- /std/lib.rs crate:std | 238 | //- /std/lib.rs crate:std |
184 | // empty | 239 | // empty |
185 | //^ file | 240 | //^ file |
@@ -193,7 +248,7 @@ mod tests { | |||
193 | r#" | 248 | r#" |
194 | struct Foo; | 249 | struct Foo; |
195 | //^^^ | 250 | //^^^ |
196 | enum E { X(Foo<|>) } | 251 | enum E { X(Foo$0) } |
197 | "#, | 252 | "#, |
198 | ); | 253 | ); |
199 | } | 254 | } |
@@ -204,7 +259,7 @@ enum E { X(Foo<|>) } | |||
204 | r#" | 259 | r#" |
205 | struct Foo; | 260 | struct Foo; |
206 | //^^^ | 261 | //^^^ |
207 | enum E { X(<|>Foo) } | 262 | enum E { X($0Foo) } |
208 | "#, | 263 | "#, |
209 | ); | 264 | ); |
210 | } | 265 | } |
@@ -217,7 +272,7 @@ enum E { X(<|>Foo) } | |||
217 | use a::Foo; | 272 | use a::Foo; |
218 | mod a; | 273 | mod a; |
219 | mod b; | 274 | mod b; |
220 | enum E { X(Foo<|>) } | 275 | enum E { X(Foo$0) } |
221 | 276 | ||
222 | //- /a.rs | 277 | //- /a.rs |
223 | struct Foo; | 278 | struct Foo; |
@@ -233,7 +288,7 @@ struct Foo; | |||
233 | check( | 288 | check( |
234 | r#" | 289 | r#" |
235 | //- /lib.rs | 290 | //- /lib.rs |
236 | mod <|>foo; | 291 | mod $0foo; |
237 | 292 | ||
238 | //- /foo.rs | 293 | //- /foo.rs |
239 | // empty | 294 | // empty |
@@ -244,7 +299,7 @@ mod <|>foo; | |||
244 | check( | 299 | check( |
245 | r#" | 300 | r#" |
246 | //- /lib.rs | 301 | //- /lib.rs |
247 | mod <|>foo; | 302 | mod $0foo; |
248 | 303 | ||
249 | //- /foo/mod.rs | 304 | //- /foo/mod.rs |
250 | // empty | 305 | // empty |
@@ -260,7 +315,7 @@ mod <|>foo; | |||
260 | macro_rules! foo { () => { () } } | 315 | macro_rules! foo { () => { () } } |
261 | //^^^ | 316 | //^^^ |
262 | fn bar() { | 317 | fn bar() { |
263 | <|>foo!(); | 318 | $0foo!(); |
264 | } | 319 | } |
265 | "#, | 320 | "#, |
266 | ); | 321 | ); |
@@ -273,7 +328,7 @@ fn bar() { | |||
273 | //- /lib.rs | 328 | //- /lib.rs |
274 | use foo::foo; | 329 | use foo::foo; |
275 | fn bar() { | 330 | fn bar() { |
276 | <|>foo!(); | 331 | $0foo!(); |
277 | } | 332 | } |
278 | 333 | ||
279 | //- /foo/lib.rs | 334 | //- /foo/lib.rs |
@@ -289,7 +344,7 @@ macro_rules! foo { () => { () } } | |||
289 | check( | 344 | check( |
290 | r#" | 345 | r#" |
291 | //- /lib.rs | 346 | //- /lib.rs |
292 | use foo::foo<|>; | 347 | use foo::foo$0; |
293 | 348 | ||
294 | //- /foo/lib.rs | 349 | //- /foo/lib.rs |
295 | #[macro_export] | 350 | #[macro_export] |
@@ -312,7 +367,7 @@ define_fn!(foo); | |||
312 | //^^^ | 367 | //^^^ |
313 | 368 | ||
314 | fn bar() { | 369 | fn bar() { |
315 | <|>foo(); | 370 | $0foo(); |
316 | } | 371 | } |
317 | "#, | 372 | "#, |
318 | ); | 373 | ); |
@@ -331,7 +386,7 @@ macro_rules! define_fn { | |||
331 | //^^^^^^^^^^^^^ | 386 | //^^^^^^^^^^^^^ |
332 | 387 | ||
333 | fn bar() { | 388 | fn bar() { |
334 | <|>foo(); | 389 | $0foo(); |
335 | } | 390 | } |
336 | "#, | 391 | "#, |
337 | ); | 392 | ); |
@@ -347,7 +402,7 @@ macro_rules! foo {() => {0}} | |||
347 | 402 | ||
348 | fn bar() { | 403 | fn bar() { |
349 | match (0,1) { | 404 | match (0,1) { |
350 | (<|>foo!(), _) => {} | 405 | ($0foo!(), _) => {} |
351 | } | 406 | } |
352 | } | 407 | } |
353 | "#, | 408 | "#, |
@@ -363,7 +418,7 @@ macro_rules! foo {() => {0}} | |||
363 | //^^^ | 418 | //^^^ |
364 | fn bar() { | 419 | fn bar() { |
365 | match 0 { | 420 | match 0 { |
366 | <|>foo!() => {} | 421 | $0foo!() => {} |
367 | } | 422 | } |
368 | } | 423 | } |
369 | "#, | 424 | "#, |
@@ -375,7 +430,7 @@ fn bar() { | |||
375 | check( | 430 | check( |
376 | r#" | 431 | r#" |
377 | //- /lib.rs crate:main deps:foo | 432 | //- /lib.rs crate:main deps:foo |
378 | use foo as bar<|>; | 433 | use foo as bar$0; |
379 | 434 | ||
380 | //- /foo/lib.rs crate:foo | 435 | //- /foo/lib.rs crate:foo |
381 | // empty | 436 | // empty |
@@ -389,7 +444,7 @@ use foo as bar<|>; | |||
389 | check( | 444 | check( |
390 | r#" | 445 | r#" |
391 | //- /lib.rs crate:main deps:foo | 446 | //- /lib.rs crate:main deps:foo |
392 | use foo::foo as bar<|>; | 447 | use foo::foo as bar$0; |
393 | 448 | ||
394 | //- /foo/lib.rs crate:foo | 449 | //- /foo/lib.rs crate:foo |
395 | #[macro_export] | 450 | #[macro_export] |
@@ -410,7 +465,7 @@ impl Foo { | |||
410 | } | 465 | } |
411 | 466 | ||
412 | fn bar(foo: &Foo) { | 467 | fn bar(foo: &Foo) { |
413 | foo.frobnicate<|>(); | 468 | foo.frobnicate$0(); |
414 | } | 469 | } |
415 | "#, | 470 | "#, |
416 | ); | 471 | ); |
@@ -425,7 +480,7 @@ struct Foo { | |||
425 | } //^^^^ | 480 | } //^^^^ |
426 | 481 | ||
427 | fn bar(foo: &Foo) { | 482 | fn bar(foo: &Foo) { |
428 | foo.spam<|>; | 483 | foo.spam$0; |
429 | } | 484 | } |
430 | "#, | 485 | "#, |
431 | ); | 486 | ); |
@@ -442,7 +497,7 @@ struct Foo { | |||
442 | 497 | ||
443 | fn bar() -> Foo { | 498 | fn bar() -> Foo { |
444 | Foo { | 499 | Foo { |
445 | spam<|>: 0, | 500 | spam$0: 0, |
446 | } | 501 | } |
447 | } | 502 | } |
448 | "#, | 503 | "#, |
@@ -459,7 +514,7 @@ struct Foo { | |||
459 | } //^^^^ | 514 | } //^^^^ |
460 | 515 | ||
461 | fn bar(foo: Foo) -> Foo { | 516 | fn bar(foo: Foo) -> Foo { |
462 | let Foo { spam<|>: _, } = foo | 517 | let Foo { spam$0: _, } = foo |
463 | } | 518 | } |
464 | "#, | 519 | "#, |
465 | ); | 520 | ); |
@@ -474,7 +529,7 @@ struct Foo { spam: u32 } | |||
474 | //^^^^ | 529 | //^^^^ |
475 | 530 | ||
476 | fn bar() -> Foo { | 531 | fn bar() -> Foo { |
477 | Foo { spam<|>: m!() } | 532 | Foo { spam$0: m!() } |
478 | } | 533 | } |
479 | ", | 534 | ", |
480 | ); | 535 | ); |
@@ -489,7 +544,7 @@ struct Foo(u32); | |||
489 | 544 | ||
490 | fn bar() { | 545 | fn bar() { |
491 | let foo = Foo(0); | 546 | let foo = Foo(0); |
492 | foo.<|>0; | 547 | foo.$00; |
493 | } | 548 | } |
494 | "#, | 549 | "#, |
495 | ); | 550 | ); |
@@ -505,7 +560,7 @@ impl Foo { | |||
505 | } //^^^^^^^^^^ | 560 | } //^^^^^^^^^^ |
506 | 561 | ||
507 | fn bar(foo: &Foo) { | 562 | fn bar(foo: &Foo) { |
508 | Foo::frobnicate<|>(); | 563 | Foo::frobnicate$0(); |
509 | } | 564 | } |
510 | "#, | 565 | "#, |
511 | ); | 566 | ); |
@@ -520,7 +575,7 @@ trait Foo { | |||
520 | } //^^^^^^^^^^ | 575 | } //^^^^^^^^^^ |
521 | 576 | ||
522 | fn bar() { | 577 | fn bar() { |
523 | Foo::frobnicate<|>(); | 578 | Foo::frobnicate$0(); |
524 | } | 579 | } |
525 | "#, | 580 | "#, |
526 | ); | 581 | ); |
@@ -537,7 +592,7 @@ trait Trait { | |||
537 | impl Trait for Foo {} | 592 | impl Trait for Foo {} |
538 | 593 | ||
539 | fn bar() { | 594 | fn bar() { |
540 | Foo::frobnicate<|>(); | 595 | Foo::frobnicate$0(); |
541 | } | 596 | } |
542 | "#, | 597 | "#, |
543 | ); | 598 | ); |
@@ -551,7 +606,7 @@ struct Foo; | |||
551 | impl Foo { | 606 | impl Foo { |
552 | //^^^ | 607 | //^^^ |
553 | pub fn new() -> Self { | 608 | pub fn new() -> Self { |
554 | Self<|> {} | 609 | Self$0 {} |
555 | } | 610 | } |
556 | } | 611 | } |
557 | "#, | 612 | "#, |
@@ -561,7 +616,7 @@ impl Foo { | |||
561 | struct Foo; | 616 | struct Foo; |
562 | impl Foo { | 617 | impl Foo { |
563 | //^^^ | 618 | //^^^ |
564 | pub fn new() -> Self<|> { | 619 | pub fn new() -> Self$0 { |
565 | Self {} | 620 | Self {} |
566 | } | 621 | } |
567 | } | 622 | } |
@@ -573,7 +628,7 @@ impl Foo { | |||
573 | enum Foo { A } | 628 | enum Foo { A } |
574 | impl Foo { | 629 | impl Foo { |
575 | //^^^ | 630 | //^^^ |
576 | pub fn new() -> Self<|> { | 631 | pub fn new() -> Self$0 { |
577 | Foo::A | 632 | Foo::A |
578 | } | 633 | } |
579 | } | 634 | } |
@@ -585,7 +640,7 @@ impl Foo { | |||
585 | enum Foo { A } | 640 | enum Foo { A } |
586 | impl Foo { | 641 | impl Foo { |
587 | //^^^ | 642 | //^^^ |
588 | pub fn thing(a: &Self<|>) { | 643 | pub fn thing(a: &Self$0) { |
589 | } | 644 | } |
590 | } | 645 | } |
591 | "#, | 646 | "#, |
@@ -603,7 +658,7 @@ trait Make { | |||
603 | impl Make for Foo { | 658 | impl Make for Foo { |
604 | //^^^ | 659 | //^^^ |
605 | fn new() -> Self { | 660 | fn new() -> Self { |
606 | Self<|> {} | 661 | Self$0 {} |
607 | } | 662 | } |
608 | } | 663 | } |
609 | "#, | 664 | "#, |
@@ -617,7 +672,7 @@ trait Make { | |||
617 | } | 672 | } |
618 | impl Make for Foo { | 673 | impl Make for Foo { |
619 | //^^^ | 674 | //^^^ |
620 | fn new() -> Self<|> { | 675 | fn new() -> Self$0 { |
621 | Self {} | 676 | Self {} |
622 | } | 677 | } |
623 | } | 678 | } |
@@ -629,7 +684,7 @@ impl Make for Foo { | |||
629 | fn goto_def_when_used_on_definition_name_itself() { | 684 | fn goto_def_when_used_on_definition_name_itself() { |
630 | check( | 685 | check( |
631 | r#" | 686 | r#" |
632 | struct Foo<|> { value: u32 } | 687 | struct Foo$0 { value: u32 } |
633 | //^^^ | 688 | //^^^ |
634 | "#, | 689 | "#, |
635 | ); | 690 | ); |
@@ -637,21 +692,21 @@ struct Foo<|> { value: u32 } | |||
637 | check( | 692 | check( |
638 | r#" | 693 | r#" |
639 | struct Foo { | 694 | struct Foo { |
640 | field<|>: string, | 695 | field$0: string, |
641 | } //^^^^^ | 696 | } //^^^^^ |
642 | "#, | 697 | "#, |
643 | ); | 698 | ); |
644 | 699 | ||
645 | check( | 700 | check( |
646 | r#" | 701 | r#" |
647 | fn foo_test<|>() { } | 702 | fn foo_test$0() { } |
648 | //^^^^^^^^ | 703 | //^^^^^^^^ |
649 | "#, | 704 | "#, |
650 | ); | 705 | ); |
651 | 706 | ||
652 | check( | 707 | check( |
653 | r#" | 708 | r#" |
654 | enum Foo<|> { Variant } | 709 | enum Foo$0 { Variant } |
655 | //^^^ | 710 | //^^^ |
656 | "#, | 711 | "#, |
657 | ); | 712 | ); |
@@ -660,7 +715,7 @@ enum Foo<|> { Variant } | |||
660 | r#" | 715 | r#" |
661 | enum Foo { | 716 | enum Foo { |
662 | Variant1, | 717 | Variant1, |
663 | Variant2<|>, | 718 | Variant2$0, |
664 | //^^^^^^^^ | 719 | //^^^^^^^^ |
665 | Variant3, | 720 | Variant3, |
666 | } | 721 | } |
@@ -669,35 +724,35 @@ enum Foo { | |||
669 | 724 | ||
670 | check( | 725 | check( |
671 | r#" | 726 | r#" |
672 | static INNER<|>: &str = ""; | 727 | static INNER$0: &str = ""; |
673 | //^^^^^ | 728 | //^^^^^ |
674 | "#, | 729 | "#, |
675 | ); | 730 | ); |
676 | 731 | ||
677 | check( | 732 | check( |
678 | r#" | 733 | r#" |
679 | const INNER<|>: &str = ""; | 734 | const INNER$0: &str = ""; |
680 | //^^^^^ | 735 | //^^^^^ |
681 | "#, | 736 | "#, |
682 | ); | 737 | ); |
683 | 738 | ||
684 | check( | 739 | check( |
685 | r#" | 740 | r#" |
686 | type Thing<|> = Option<()>; | 741 | type Thing$0 = Option<()>; |
687 | //^^^^^ | 742 | //^^^^^ |
688 | "#, | 743 | "#, |
689 | ); | 744 | ); |
690 | 745 | ||
691 | check( | 746 | check( |
692 | r#" | 747 | r#" |
693 | trait Foo<|> { } | 748 | trait Foo$0 { } |
694 | //^^^ | 749 | //^^^ |
695 | "#, | 750 | "#, |
696 | ); | 751 | ); |
697 | 752 | ||
698 | check( | 753 | check( |
699 | r#" | 754 | r#" |
700 | mod bar<|> { } | 755 | mod bar$0 { } |
701 | //^^^ | 756 | //^^^ |
702 | "#, | 757 | "#, |
703 | ); | 758 | ); |
@@ -714,7 +769,7 @@ fn foo() {} | |||
714 | //^^^ | 769 | //^^^ |
715 | id! { | 770 | id! { |
716 | fn bar() { | 771 | fn bar() { |
717 | fo<|>o(); | 772 | fo$0o(); |
718 | } | 773 | } |
719 | } | 774 | } |
720 | mod confuse_index { fn foo(); } | 775 | mod confuse_index { fn foo(); } |
@@ -743,7 +798,7 @@ pub mod __export { | |||
743 | fn foo() -> i8 {} | 798 | fn foo() -> i8 {} |
744 | //^^^ | 799 | //^^^ |
745 | fn test() { | 800 | fn test() { |
746 | format!("{}", fo<|>o()) | 801 | format!("{}", fo$0o()) |
747 | } | 802 | } |
748 | "#, | 803 | "#, |
749 | ); | 804 | ); |
@@ -761,7 +816,7 @@ macro_rules! include {} | |||
761 | //^^^^^^^^^^^^^^^^^^^ | 816 | //^^^^^^^^^^^^^^^^^^^ |
762 | 817 | ||
763 | fn f() { | 818 | fn f() { |
764 | foo<|>(); | 819 | foo$0(); |
765 | } | 820 | } |
766 | 821 | ||
767 | mod confuse_index { | 822 | mod confuse_index { |
@@ -778,7 +833,7 @@ fn foo() {} | |||
778 | fn goto_for_type_param() { | 833 | fn goto_for_type_param() { |
779 | check( | 834 | check( |
780 | r#" | 835 | r#" |
781 | struct Foo<T: Clone> { t: <|>T } | 836 | struct Foo<T: Clone> { t: $0T } |
782 | //^ | 837 | //^ |
783 | "#, | 838 | "#, |
784 | ); | 839 | ); |
@@ -796,7 +851,7 @@ fn foo() { | |||
796 | let x = 1; | 851 | let x = 1; |
797 | //^ | 852 | //^ |
798 | id!({ | 853 | id!({ |
799 | let y = <|>x; | 854 | let y = $0x; |
800 | let z = y; | 855 | let z = y; |
801 | }); | 856 | }); |
802 | } | 857 | } |
@@ -814,7 +869,7 @@ fn foo() { | |||
814 | id!({ | 869 | id!({ |
815 | let y = x; | 870 | let y = x; |
816 | //^ | 871 | //^ |
817 | let z = <|>y; | 872 | let z = $0y; |
818 | }); | 873 | }); |
819 | } | 874 | } |
820 | "#, | 875 | "#, |
@@ -829,7 +884,7 @@ fn main() { | |||
829 | fn foo() { | 884 | fn foo() { |
830 | let x = 92; | 885 | let x = 92; |
831 | //^ | 886 | //^ |
832 | <|>x; | 887 | $0x; |
833 | } | 888 | } |
834 | } | 889 | } |
835 | "#, | 890 | "#, |
@@ -843,7 +898,7 @@ fn main() { | |||
843 | fn bar() { | 898 | fn bar() { |
844 | macro_rules! foo { () => { () } } | 899 | macro_rules! foo { () => { () } } |
845 | //^^^ | 900 | //^^^ |
846 | <|>foo!(); | 901 | $0foo!(); |
847 | } | 902 | } |
848 | "#, | 903 | "#, |
849 | ); | 904 | ); |
@@ -857,7 +912,7 @@ struct Foo { x: i32 } | |||
857 | fn main() { | 912 | fn main() { |
858 | let x = 92; | 913 | let x = 92; |
859 | //^ | 914 | //^ |
860 | Foo { x<|> }; | 915 | Foo { x$0 }; |
861 | } | 916 | } |
862 | "#, | 917 | "#, |
863 | ) | 918 | ) |
@@ -872,7 +927,7 @@ enum Foo { | |||
872 | } //^ | 927 | } //^ |
873 | fn baz(foo: Foo) { | 928 | fn baz(foo: Foo) { |
874 | match foo { | 929 | match foo { |
875 | Foo::Bar { x<|> } => x | 930 | Foo::Bar { x$0 } => x |
876 | }; | 931 | }; |
877 | } | 932 | } |
878 | "#, | 933 | "#, |
@@ -887,7 +942,7 @@ enum Foo { Bar } | |||
887 | //^^^ | 942 | //^^^ |
888 | impl Foo { | 943 | impl Foo { |
889 | fn baz(self) { | 944 | fn baz(self) { |
890 | match self { Self::Bar<|> => {} } | 945 | match self { Self::Bar$0 => {} } |
891 | } | 946 | } |
892 | } | 947 | } |
893 | "#, | 948 | "#, |
@@ -902,7 +957,7 @@ enum Foo { Bar { val: i32 } } | |||
902 | //^^^ | 957 | //^^^ |
903 | impl Foo { | 958 | impl Foo { |
904 | fn baz(self) -> i32 { | 959 | fn baz(self) -> i32 { |
905 | match self { Self::Bar<|> { val } => {} } | 960 | match self { Self::Bar$0 { val } => {} } |
906 | } | 961 | } |
907 | } | 962 | } |
908 | "#, | 963 | "#, |
@@ -916,7 +971,7 @@ impl Foo { | |||
916 | enum Foo { Bar } | 971 | enum Foo { Bar } |
917 | //^^^ | 972 | //^^^ |
918 | impl Foo { | 973 | impl Foo { |
919 | fn baz(self) { Self::Bar<|>; } | 974 | fn baz(self) { Self::Bar$0; } |
920 | } | 975 | } |
921 | "#, | 976 | "#, |
922 | ); | 977 | ); |
@@ -929,7 +984,7 @@ impl Foo { | |||
929 | enum Foo { Bar { val: i32 } } | 984 | enum Foo { Bar { val: i32 } } |
930 | //^^^ | 985 | //^^^ |
931 | impl Foo { | 986 | impl Foo { |
932 | fn baz(self) { Self::Bar<|> {val: 4}; } | 987 | fn baz(self) { Self::Bar$0 {val: 4}; } |
933 | } | 988 | } |
934 | "#, | 989 | "#, |
935 | ); | 990 | ); |
@@ -939,7 +994,7 @@ impl Foo { | |||
939 | fn goto_def_for_type_alias_generic_parameter() { | 994 | fn goto_def_for_type_alias_generic_parameter() { |
940 | check( | 995 | check( |
941 | r#" | 996 | r#" |
942 | type Alias<T> = T<|>; | 997 | type Alias<T> = T$0; |
943 | //^ | 998 | //^ |
944 | "#, | 999 | "#, |
945 | ) | 1000 | ) |
@@ -950,7 +1005,7 @@ type Alias<T> = T<|>; | |||
950 | check( | 1005 | check( |
951 | r#" | 1006 | r#" |
952 | //- /lib.rs | 1007 | //- /lib.rs |
953 | foo::module<|>::mac!(); | 1008 | foo::module$0::mac!(); |
954 | 1009 | ||
955 | //- /foo/lib.rs | 1010 | //- /foo/lib.rs |
956 | pub mod module { | 1011 | pub mod module { |
@@ -972,7 +1027,7 @@ trait Iterator { | |||
972 | //^^^^ | 1027 | //^^^^ |
973 | } | 1028 | } |
974 | 1029 | ||
975 | fn f() -> impl Iterator<Item<|> = u8> {} | 1030 | fn f() -> impl Iterator<Item$0 = u8> {} |
976 | "#, | 1031 | "#, |
977 | ); | 1032 | ); |
978 | } | 1033 | } |
@@ -987,7 +1042,7 @@ trait Iterator { | |||
987 | type B; | 1042 | type B; |
988 | } | 1043 | } |
989 | 1044 | ||
990 | fn f() -> impl Iterator<A<|> = u8, B = ()> {} | 1045 | fn f() -> impl Iterator<A$0 = u8, B = ()> {} |
991 | "#, | 1046 | "#, |
992 | ); | 1047 | ); |
993 | check( | 1048 | check( |
@@ -998,7 +1053,7 @@ trait Iterator { | |||
998 | //^ | 1053 | //^ |
999 | } | 1054 | } |
1000 | 1055 | ||
1001 | fn f() -> impl Iterator<A = u8, B<|> = ()> {} | 1056 | fn f() -> impl Iterator<A = u8, B$0 = ()> {} |
1002 | "#, | 1057 | "#, |
1003 | ); | 1058 | ); |
1004 | } | 1059 | } |
@@ -1012,7 +1067,7 @@ trait Iterator { | |||
1012 | //^^^^ | 1067 | //^^^^ |
1013 | } | 1068 | } |
1014 | 1069 | ||
1015 | fn g() -> <() as Iterator<Item<|> = ()>>::Item {} | 1070 | fn g() -> <() as Iterator<Item$0 = ()>>::Item {} |
1016 | "#, | 1071 | "#, |
1017 | ); | 1072 | ); |
1018 | } | 1073 | } |
@@ -1027,7 +1082,7 @@ trait Iterator { | |||
1027 | type B; | 1082 | type B; |
1028 | } | 1083 | } |
1029 | 1084 | ||
1030 | fn g() -> <() as Iterator<A<|> = (), B = u8>>::B {} | 1085 | fn g() -> <() as Iterator<A$0 = (), B = u8>>::B {} |
1031 | "#, | 1086 | "#, |
1032 | ); | 1087 | ); |
1033 | check( | 1088 | check( |
@@ -1038,7 +1093,7 @@ trait Iterator { | |||
1038 | //^ | 1093 | //^ |
1039 | } | 1094 | } |
1040 | 1095 | ||
1041 | fn g() -> <() as Iterator<A = (), B<|> = u8>>::A {} | 1096 | fn g() -> <() as Iterator<A = (), B$0 = u8>>::A {} |
1042 | "#, | 1097 | "#, |
1043 | ); | 1098 | ); |
1044 | } | 1099 | } |
@@ -1052,7 +1107,7 @@ struct Foo {} | |||
1052 | impl Foo { | 1107 | impl Foo { |
1053 | fn bar(self: &Foo) { | 1108 | fn bar(self: &Foo) { |
1054 | //^^^^ | 1109 | //^^^^ |
1055 | let foo = sel<|>f; | 1110 | let foo = sel$0f; |
1056 | } | 1111 | } |
1057 | }"#, | 1112 | }"#, |
1058 | ) | 1113 | ) |
@@ -1065,7 +1120,7 @@ impl Foo { | |||
1065 | struct Foo {} | 1120 | struct Foo {} |
1066 | 1121 | ||
1067 | impl Foo { | 1122 | impl Foo { |
1068 | fn bar(&self<|>) { | 1123 | fn bar(&self$0) { |
1069 | //^^^^ | 1124 | //^^^^ |
1070 | } | 1125 | } |
1071 | }"#, | 1126 | }"#, |
@@ -1076,7 +1131,7 @@ impl Foo { | |||
1076 | fn goto_lifetime_param_on_decl() { | 1131 | fn goto_lifetime_param_on_decl() { |
1077 | check( | 1132 | check( |
1078 | r#" | 1133 | r#" |
1079 | fn foo<'foobar<|>>(_: &'foobar ()) { | 1134 | fn foo<'foobar$0>(_: &'foobar ()) { |
1080 | //^^^^^^^ | 1135 | //^^^^^^^ |
1081 | }"#, | 1136 | }"#, |
1082 | ) | 1137 | ) |
@@ -1086,7 +1141,7 @@ fn foo<'foobar<|>>(_: &'foobar ()) { | |||
1086 | fn goto_lifetime_param_decl() { | 1141 | fn goto_lifetime_param_decl() { |
1087 | check( | 1142 | check( |
1088 | r#" | 1143 | r#" |
1089 | fn foo<'foobar>(_: &'foobar<|> ()) { | 1144 | fn foo<'foobar>(_: &'foobar$0 ()) { |
1090 | //^^^^^^^ | 1145 | //^^^^^^^ |
1091 | }"#, | 1146 | }"#, |
1092 | ) | 1147 | ) |
@@ -1097,7 +1152,7 @@ fn foo<'foobar>(_: &'foobar<|> ()) { | |||
1097 | check( | 1152 | check( |
1098 | r#" | 1153 | r#" |
1099 | fn foo<'foobar>(_: &'foobar ()) { | 1154 | fn foo<'foobar>(_: &'foobar ()) { |
1100 | fn foo<'foobar>(_: &'foobar<|> ()) {} | 1155 | fn foo<'foobar>(_: &'foobar$0 ()) {} |
1101 | //^^^^^^^ | 1156 | //^^^^^^^ |
1102 | }"#, | 1157 | }"#, |
1103 | ) | 1158 | ) |
@@ -1108,13 +1163,13 @@ fn foo<'foobar>(_: &'foobar ()) { | |||
1108 | fn goto_lifetime_hrtb() { | 1163 | fn goto_lifetime_hrtb() { |
1109 | check( | 1164 | check( |
1110 | r#"trait Foo<T> {} | 1165 | r#"trait Foo<T> {} |
1111 | fn foo<T>() where for<'a> T: Foo<&'a<|> (u8, u16)>, {} | 1166 | fn foo<T>() where for<'a> T: Foo<&'a$0 (u8, u16)>, {} |
1112 | //^^ | 1167 | //^^ |
1113 | "#, | 1168 | "#, |
1114 | ); | 1169 | ); |
1115 | check( | 1170 | check( |
1116 | r#"trait Foo<T> {} | 1171 | r#"trait Foo<T> {} |
1117 | fn foo<T>() where for<'a<|>> T: Foo<&'a (u8, u16)>, {} | 1172 | fn foo<T>() where for<'a$0> T: Foo<&'a (u8, u16)>, {} |
1118 | //^^ | 1173 | //^^ |
1119 | "#, | 1174 | "#, |
1120 | ); | 1175 | ); |
@@ -1125,7 +1180,7 @@ fn foo<T>() where for<'a<|>> T: Foo<&'a (u8, u16)>, {} | |||
1125 | fn goto_lifetime_hrtb_for_type() { | 1180 | fn goto_lifetime_hrtb_for_type() { |
1126 | check( | 1181 | check( |
1127 | r#"trait Foo<T> {} | 1182 | r#"trait Foo<T> {} |
1128 | fn foo<T>() where T: for<'a> Foo<&'a<|> (u8, u16)>, {} | 1183 | fn foo<T>() where T: for<'a> Foo<&'a$0 (u8, u16)>, {} |
1129 | //^^ | 1184 | //^^ |
1130 | "#, | 1185 | "#, |
1131 | ); | 1186 | ); |
@@ -1139,10 +1194,40 @@ fn foo<'foo>(_: &'foo ()) { | |||
1139 | 'foo: { | 1194 | 'foo: { |
1140 | //^^^^ | 1195 | //^^^^ |
1141 | 'bar: loop { | 1196 | 'bar: loop { |
1142 | break 'foo<|>; | 1197 | break 'foo$0; |
1143 | } | 1198 | } |
1144 | } | 1199 | } |
1145 | }"#, | 1200 | }"#, |
1146 | ) | 1201 | ) |
1147 | } | 1202 | } |
1203 | |||
1204 | #[test] | ||
1205 | fn goto_def_for_intra_doc_link_same_file() { | ||
1206 | check( | ||
1207 | r#" | ||
1208 | /// Blah, [`bar`](bar) .. [`foo`](foo)$0 has [`bar`](bar) | ||
1209 | pub fn bar() { } | ||
1210 | |||
1211 | /// You might want to see [`std::fs::read()`] too. | ||
1212 | pub fn foo() { } | ||
1213 | //^^^ | ||
1214 | |||
1215 | }"#, | ||
1216 | ) | ||
1217 | } | ||
1218 | |||
1219 | #[test] | ||
1220 | fn goto_def_for_intra_doc_link_inner() { | ||
1221 | check( | ||
1222 | r#" | ||
1223 | //- /main.rs | ||
1224 | mod m; | ||
1225 | struct S; | ||
1226 | //^ | ||
1227 | |||
1228 | //- /m.rs | ||
1229 | //! [`super::S$0`] | ||
1230 | "#, | ||
1231 | ) | ||
1232 | } | ||
1148 | } | 1233 | } |
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs index da9378a97..761a98b2c 100644 --- a/crates/ide/src/goto_implementation.rs +++ b/crates/ide/src/goto_implementation.rs | |||
@@ -107,7 +107,7 @@ mod tests { | |||
107 | fn goto_implementation_works() { | 107 | fn goto_implementation_works() { |
108 | check( | 108 | check( |
109 | r#" | 109 | r#" |
110 | struct Foo<|>; | 110 | struct Foo$0; |
111 | impl Foo {} | 111 | impl Foo {} |
112 | //^^^ | 112 | //^^^ |
113 | "#, | 113 | "#, |
@@ -118,7 +118,7 @@ impl Foo {} | |||
118 | fn goto_implementation_works_multiple_blocks() { | 118 | fn goto_implementation_works_multiple_blocks() { |
119 | check( | 119 | check( |
120 | r#" | 120 | r#" |
121 | struct Foo<|>; | 121 | struct Foo$0; |
122 | impl Foo {} | 122 | impl Foo {} |
123 | //^^^ | 123 | //^^^ |
124 | impl Foo {} | 124 | impl Foo {} |
@@ -131,7 +131,7 @@ impl Foo {} | |||
131 | fn goto_implementation_works_multiple_mods() { | 131 | fn goto_implementation_works_multiple_mods() { |
132 | check( | 132 | check( |
133 | r#" | 133 | r#" |
134 | struct Foo<|>; | 134 | struct Foo$0; |
135 | mod a { | 135 | mod a { |
136 | impl super::Foo {} | 136 | impl super::Foo {} |
137 | //^^^^^^^^^^ | 137 | //^^^^^^^^^^ |
@@ -149,7 +149,7 @@ mod b { | |||
149 | check( | 149 | check( |
150 | r#" | 150 | r#" |
151 | //- /lib.rs | 151 | //- /lib.rs |
152 | struct Foo<|>; | 152 | struct Foo$0; |
153 | mod a; | 153 | mod a; |
154 | mod b; | 154 | mod b; |
155 | //- /a.rs | 155 | //- /a.rs |
@@ -166,7 +166,7 @@ impl crate::Foo {} | |||
166 | fn goto_implementation_for_trait() { | 166 | fn goto_implementation_for_trait() { |
167 | check( | 167 | check( |
168 | r#" | 168 | r#" |
169 | trait T<|> {} | 169 | trait T$0 {} |
170 | struct Foo; | 170 | struct Foo; |
171 | impl T for Foo {} | 171 | impl T for Foo {} |
172 | //^^^ | 172 | //^^^ |
@@ -179,7 +179,7 @@ impl T for Foo {} | |||
179 | check( | 179 | check( |
180 | r#" | 180 | r#" |
181 | //- /lib.rs | 181 | //- /lib.rs |
182 | trait T<|> {}; | 182 | trait T$0 {}; |
183 | struct Foo; | 183 | struct Foo; |
184 | mod a; | 184 | mod a; |
185 | mod b; | 185 | mod b; |
@@ -199,7 +199,7 @@ impl crate::T for crate::Foo {} | |||
199 | r#" | 199 | r#" |
200 | //- /lib.rs | 200 | //- /lib.rs |
201 | trait T {} | 201 | trait T {} |
202 | struct Foo<|>; | 202 | struct Foo$0; |
203 | impl Foo {} | 203 | impl Foo {} |
204 | //^^^ | 204 | //^^^ |
205 | impl T for Foo {} | 205 | impl T for Foo {} |
@@ -216,7 +216,7 @@ impl T for &Foo {} | |||
216 | r#" | 216 | r#" |
217 | #[derive(Copy)] | 217 | #[derive(Copy)] |
218 | //^^^^^^^^^^^^^^^ | 218 | //^^^^^^^^^^^^^^^ |
219 | struct Foo<|>; | 219 | struct Foo$0; |
220 | 220 | ||
221 | mod marker { | 221 | mod marker { |
222 | trait Copy {} | 222 | trait Copy {} |
diff --git a/crates/ide/src/goto_type_definition.rs b/crates/ide/src/goto_type_definition.rs index 7e84e06be..369a59820 100644 --- a/crates/ide/src/goto_type_definition.rs +++ b/crates/ide/src/goto_type_definition.rs | |||
@@ -76,7 +76,7 @@ mod tests { | |||
76 | struct Foo; | 76 | struct Foo; |
77 | //^^^ | 77 | //^^^ |
78 | fn foo() { | 78 | fn foo() { |
79 | let f: Foo; f<|> | 79 | let f: Foo; f$0 |
80 | } | 80 | } |
81 | "#, | 81 | "#, |
82 | ); | 82 | ); |
@@ -89,7 +89,7 @@ fn foo() { | |||
89 | struct Foo; | 89 | struct Foo; |
90 | //^^^ | 90 | //^^^ |
91 | fn foo() { | 91 | fn foo() { |
92 | let f: &Foo; f<|> | 92 | let f: &Foo; f$0 |
93 | } | 93 | } |
94 | "#, | 94 | "#, |
95 | ); | 95 | ); |
@@ -103,7 +103,7 @@ macro_rules! id { ($($tt:tt)*) => { $($tt)* } } | |||
103 | struct Foo {} | 103 | struct Foo {} |
104 | //^^^ | 104 | //^^^ |
105 | id! { | 105 | id! { |
106 | fn bar() { let f<|> = Foo {}; } | 106 | fn bar() { let f$0 = Foo {}; } |
107 | } | 107 | } |
108 | "#, | 108 | "#, |
109 | ); | 109 | ); |
@@ -115,7 +115,7 @@ id! { | |||
115 | r#" | 115 | r#" |
116 | struct Foo; | 116 | struct Foo; |
117 | //^^^ | 117 | //^^^ |
118 | fn foo(<|>f: Foo) {} | 118 | fn foo($0f: Foo) {} |
119 | "#, | 119 | "#, |
120 | ); | 120 | ); |
121 | } | 121 | } |
@@ -129,7 +129,7 @@ struct Foo; | |||
129 | struct Bar(Foo); | 129 | struct Bar(Foo); |
130 | fn foo() { | 130 | fn foo() { |
131 | let bar = Bar(Foo); | 131 | let bar = Bar(Foo); |
132 | bar.<|>0; | 132 | bar.$00; |
133 | } | 133 | } |
134 | "#, | 134 | "#, |
135 | ); | 135 | ); |
@@ -142,7 +142,7 @@ fn foo() { | |||
142 | struct Foo; | 142 | struct Foo; |
143 | //^^^ | 143 | //^^^ |
144 | impl Foo { | 144 | impl Foo { |
145 | fn f(&self<|>) {} | 145 | fn f(&self$0) {} |
146 | } | 146 | } |
147 | "#, | 147 | "#, |
148 | ) | 148 | ) |
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index f2ad95cb6..317b6f011 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use hir::{ | 1 | use hir::{ |
2 | Adt, AsAssocItem, AssocItemContainer, FieldSource, HasAttrs, HasSource, HirDisplay, Module, | 2 | Adt, AsAssocItem, AssocItemContainer, FieldSource, GenericParam, HasAttrs, HasSource, |
3 | ModuleDef, ModuleSource, Semantics, | 3 | HirDisplay, Module, ModuleDef, ModuleSource, Semantics, |
4 | }; | 4 | }; |
5 | use ide_db::base_db::SourceDatabase; | 5 | use ide_db::base_db::SourceDatabase; |
6 | use ide_db::{ | 6 | use ide_db::{ |
@@ -17,7 +17,7 @@ use crate::{ | |||
17 | doc_links::{remove_links, rewrite_links}, | 17 | doc_links::{remove_links, rewrite_links}, |
18 | markdown_remove::remove_markdown, | 18 | markdown_remove::remove_markdown, |
19 | markup::Markup, | 19 | markup::Markup, |
20 | runnables::runnable, | 20 | runnables::{runnable_fn, runnable_mod}, |
21 | FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, | 21 | FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, |
22 | }; | 22 | }; |
23 | 23 | ||
@@ -31,19 +31,6 @@ pub struct HoverConfig { | |||
31 | pub markdown: bool, | 31 | pub markdown: bool, |
32 | } | 32 | } |
33 | 33 | ||
34 | impl Default for HoverConfig { | ||
35 | fn default() -> Self { | ||
36 | Self { | ||
37 | implementations: true, | ||
38 | run: true, | ||
39 | debug: true, | ||
40 | goto_type_def: true, | ||
41 | links_in_hover: true, | ||
42 | markdown: true, | ||
43 | } | ||
44 | } | ||
45 | } | ||
46 | |||
47 | impl HoverConfig { | 34 | impl HoverConfig { |
48 | pub const NO_ACTIONS: Self = Self { | 35 | pub const NO_ACTIONS: Self = Self { |
49 | implementations: false, | 36 | implementations: false, |
@@ -188,12 +175,7 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov | |||
188 | Definition::SelfType(it) => it.target_ty(db).as_adt(), | 175 | Definition::SelfType(it) => it.target_ty(db).as_adt(), |
189 | _ => None, | 176 | _ => None, |
190 | }?; | 177 | }?; |
191 | match adt { | 178 | adt.try_to_nav(db).map(to_action) |
192 | Adt::Struct(it) => it.try_to_nav(db), | ||
193 | Adt::Union(it) => it.try_to_nav(db), | ||
194 | Adt::Enum(it) => it.try_to_nav(db), | ||
195 | } | ||
196 | .map(to_action) | ||
197 | } | 179 | } |
198 | 180 | ||
199 | fn runnable_action( | 181 | fn runnable_action( |
@@ -204,22 +186,20 @@ fn runnable_action( | |||
204 | match def { | 186 | match def { |
205 | Definition::ModuleDef(it) => match it { | 187 | Definition::ModuleDef(it) => match it { |
206 | ModuleDef::Module(it) => match it.definition_source(sema.db).value { | 188 | ModuleDef::Module(it) => match it.definition_source(sema.db).value { |
207 | ModuleSource::Module(it) => runnable(&sema, it.syntax().clone(), file_id) | 189 | ModuleSource::Module(it) => { |
208 | .map(|it| HoverAction::Runnable(it)), | 190 | runnable_mod(&sema, it).map(|it| HoverAction::Runnable(it)) |
191 | } | ||
209 | _ => None, | 192 | _ => None, |
210 | }, | 193 | }, |
211 | ModuleDef::Function(it) => { | 194 | ModuleDef::Function(func) => { |
212 | #[allow(deprecated)] | 195 | let src = func.source(sema.db)?; |
213 | let src = it.source(sema.db)?; | ||
214 | if src.file_id != file_id.into() { | 196 | if src.file_id != file_id.into() { |
215 | mark::hit!(hover_macro_generated_struct_fn_doc_comment); | 197 | mark::hit!(hover_macro_generated_struct_fn_doc_comment); |
216 | mark::hit!(hover_macro_generated_struct_fn_doc_attr); | 198 | mark::hit!(hover_macro_generated_struct_fn_doc_attr); |
217 | |||
218 | return None; | 199 | return None; |
219 | } | 200 | } |
220 | 201 | ||
221 | runnable(&sema, src.value.syntax().clone(), file_id) | 202 | runnable_fn(&sema, func).map(HoverAction::Runnable) |
222 | .map(|it| HoverAction::Runnable(it)) | ||
223 | } | 203 | } |
224 | _ => None, | 204 | _ => None, |
225 | }, | 205 | }, |
@@ -235,12 +215,12 @@ fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> { | |||
235 | } | 215 | } |
236 | }; | 216 | }; |
237 | 217 | ||
238 | if let Definition::TypeParam(it) = def { | 218 | if let Definition::GenericParam(GenericParam::TypeParam(it)) = def { |
239 | it.trait_bounds(db).into_iter().for_each(|it| push_new_def(it.into())); | 219 | it.trait_bounds(db).into_iter().for_each(|it| push_new_def(it.into())); |
240 | } else { | 220 | } else { |
241 | let ty = match def { | 221 | let ty = match def { |
242 | Definition::Local(it) => it.ty(db), | 222 | Definition::Local(it) => it.ty(db), |
243 | Definition::ConstParam(it) => it.ty(db), | 223 | Definition::GenericParam(GenericParam::ConstParam(it)) => it.ty(db), |
244 | _ => return None, | 224 | _ => return None, |
245 | }; | 225 | }; |
246 | 226 | ||
@@ -335,7 +315,6 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> { | |||
335 | from_def_source_labeled(db, it, Some(label), mod_path) | 315 | from_def_source_labeled(db, it, Some(label), mod_path) |
336 | } | 316 | } |
337 | Definition::Field(def) => { | 317 | Definition::Field(def) => { |
338 | #[allow(deprecated)] | ||
339 | let src = def.source(db)?.value; | 318 | let src = def.source(db)?.value; |
340 | if let FieldSource::Named(it) = src { | 319 | if let FieldSource::Named(it) = src { |
341 | from_def_source_labeled(db, def, it.short_label(), mod_path) | 320 | from_def_source_labeled(db, def, it.short_label(), mod_path) |
@@ -373,9 +352,11 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> { | |||
373 | }) | 352 | }) |
374 | } | 353 | } |
375 | Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))), | 354 | Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))), |
376 | Definition::LifetimeParam(it) => Some(Markup::fenced_block(&it.name(db))), | 355 | Definition::GenericParam(it) => match it { |
377 | Definition::TypeParam(type_param) => Some(Markup::fenced_block(&type_param.display(db))), | 356 | GenericParam::TypeParam(it) => Some(Markup::fenced_block(&it.display(db))), |
378 | Definition::ConstParam(it) => from_def_source(db, it, None), | 357 | GenericParam::LifetimeParam(it) => Some(Markup::fenced_block(&it.name(db))), |
358 | GenericParam::ConstParam(it) => from_def_source(db, it, None), | ||
359 | }, | ||
379 | }; | 360 | }; |
380 | 361 | ||
381 | fn from_def_source<A, D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<Markup> | 362 | fn from_def_source<A, D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<Markup> |
@@ -383,7 +364,6 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> { | |||
383 | D: HasSource<Ast = A> + HasAttrs + Copy, | 364 | D: HasSource<Ast = A> + HasAttrs + Copy, |
384 | A: ShortLabel, | 365 | A: ShortLabel, |
385 | { | 366 | { |
386 | #[allow(deprecated)] | ||
387 | let short_label = def.source(db)?.value.short_label(); | 367 | let short_label = def.source(db)?.value.short_label(); |
388 | from_def_source_labeled(db, def, short_label, mod_path) | 368 | from_def_source_labeled(db, def, short_label, mod_path) |
389 | } | 369 | } |
@@ -474,7 +454,7 @@ mod tests { | |||
474 | pub fn foo() -> u32 { 1 } | 454 | pub fn foo() -> u32 { 1 } |
475 | 455 | ||
476 | fn main() { | 456 | fn main() { |
477 | let foo_test = foo()<|>; | 457 | let foo_test = foo()$0; |
478 | } | 458 | } |
479 | "#, | 459 | "#, |
480 | expect![[r#" | 460 | expect![[r#" |
@@ -493,7 +473,7 @@ fn main() { | |||
493 | pub fn foo() -> u32 { 1 } | 473 | pub fn foo() -> u32 { 1 } |
494 | 474 | ||
495 | fn main() { | 475 | fn main() { |
496 | let foo_test = foo()<|>; | 476 | let foo_test = foo()$0; |
497 | } | 477 | } |
498 | "#, | 478 | "#, |
499 | expect![[r#" | 479 | expect![[r#" |
@@ -523,7 +503,7 @@ fn main() { | |||
523 | Option::Some(*memo + value) | 503 | Option::Some(*memo + value) |
524 | }; | 504 | }; |
525 | let number = 5u32; | 505 | let number = 5u32; |
526 | let mut iter<|> = scan(OtherStruct { i: num }, closure, number); | 506 | let mut iter$0 = scan(OtherStruct { i: num }, closure, number); |
527 | } | 507 | } |
528 | "#, | 508 | "#, |
529 | expect![[r#" | 509 | expect![[r#" |
@@ -543,7 +523,7 @@ fn main() { | |||
543 | r#" | 523 | r#" |
544 | pub fn foo() -> u32 { 1 } | 524 | pub fn foo() -> u32 { 1 } |
545 | 525 | ||
546 | fn main() { let foo_test = fo<|>o(); } | 526 | fn main() { let foo_test = fo$0o(); } |
547 | "#, | 527 | "#, |
548 | expect![[r#" | 528 | expect![[r#" |
549 | *foo* | 529 | *foo* |
@@ -575,7 +555,7 @@ mod a; | |||
575 | mod b; | 555 | mod b; |
576 | mod c; | 556 | mod c; |
577 | 557 | ||
578 | fn main() { let foo_test = fo<|>o(); } | 558 | fn main() { let foo_test = fo$0o(); } |
579 | "#, | 559 | "#, |
580 | expect![[r#" | 560 | expect![[r#" |
581 | *foo* | 561 | *foo* |
@@ -592,7 +572,7 @@ fn main() { let foo_test = fo<|>o(); } | |||
592 | r#" | 572 | r#" |
593 | pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str { } | 573 | pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str { } |
594 | 574 | ||
595 | fn main() { let foo_test = fo<|>o(); } | 575 | fn main() { let foo_test = fo$0o(); } |
596 | "#, | 576 | "#, |
597 | expect![[r#" | 577 | expect![[r#" |
598 | *foo* | 578 | *foo* |
@@ -612,7 +592,7 @@ fn main() { let foo_test = fo<|>o(); } | |||
612 | fn hover_shows_fn_signature_on_fn_name() { | 592 | fn hover_shows_fn_signature_on_fn_name() { |
613 | check( | 593 | check( |
614 | r#" | 594 | r#" |
615 | pub fn foo<|>(a: u32, b: u32) -> u32 {} | 595 | pub fn foo$0(a: u32, b: u32) -> u32 {} |
616 | 596 | ||
617 | fn main() { } | 597 | fn main() { } |
618 | "#, | 598 | "#, |
@@ -640,7 +620,7 @@ fn main() { } | |||
640 | /// # | 620 | /// # |
641 | /// foo(Path::new("hello, world!")) | 621 | /// foo(Path::new("hello, world!")) |
642 | /// ``` | 622 | /// ``` |
643 | pub fn foo<|>(_: &Path) {} | 623 | pub fn foo$0(_: &Path) {} |
644 | 624 | ||
645 | fn main() { } | 625 | fn main() { } |
646 | "#, | 626 | "#, |
@@ -673,7 +653,7 @@ fn main() { } | |||
673 | check( | 653 | check( |
674 | r##" | 654 | r##" |
675 | #[doc = r#"Raw string doc attr"#] | 655 | #[doc = r#"Raw string doc attr"#] |
676 | pub fn foo<|>(_: &Path) {} | 656 | pub fn foo$0(_: &Path) {} |
677 | 657 | ||
678 | fn main() { } | 658 | fn main() { } |
679 | "##, | 659 | "##, |
@@ -703,7 +683,7 @@ fn main() { } | |||
703 | struct Foo { field_a: u32 } | 683 | struct Foo { field_a: u32 } |
704 | 684 | ||
705 | fn main() { | 685 | fn main() { |
706 | let foo = Foo { field_a<|>: 0, }; | 686 | let foo = Foo { field_a$0: 0, }; |
707 | } | 687 | } |
708 | "#, | 688 | "#, |
709 | expect![[r#" | 689 | expect![[r#" |
@@ -722,7 +702,7 @@ fn main() { | |||
722 | // Hovering over the field in the definition | 702 | // Hovering over the field in the definition |
723 | check( | 703 | check( |
724 | r#" | 704 | r#" |
725 | struct Foo { field_a<|>: u32 } | 705 | struct Foo { field_a$0: u32 } |
726 | 706 | ||
727 | fn main() { | 707 | fn main() { |
728 | let foo = Foo { field_a: 0 }; | 708 | let foo = Foo { field_a: 0 }; |
@@ -745,7 +725,7 @@ fn main() { | |||
745 | #[test] | 725 | #[test] |
746 | fn hover_const_static() { | 726 | fn hover_const_static() { |
747 | check( | 727 | check( |
748 | r#"const foo<|>: u32 = 123;"#, | 728 | r#"const foo$0: u32 = 123;"#, |
749 | expect![[r#" | 729 | expect![[r#" |
750 | *foo* | 730 | *foo* |
751 | 731 | ||
@@ -759,7 +739,7 @@ fn main() { | |||
759 | "#]], | 739 | "#]], |
760 | ); | 740 | ); |
761 | check( | 741 | check( |
762 | r#"static foo<|>: u32 = 456;"#, | 742 | r#"static foo$0: u32 = 456;"#, |
763 | expect![[r#" | 743 | expect![[r#" |
764 | *foo* | 744 | *foo* |
765 | 745 | ||
@@ -781,7 +761,7 @@ fn main() { | |||
781 | struct Test<K, T = u8> { k: K, t: T } | 761 | struct Test<K, T = u8> { k: K, t: T } |
782 | 762 | ||
783 | fn main() { | 763 | fn main() { |
784 | let zz<|> = Test { t: 23u8, k: 33 }; | 764 | let zz$0 = Test { t: 23u8, k: 33 }; |
785 | }"#, | 765 | }"#, |
786 | expect![[r#" | 766 | expect![[r#" |
787 | *zz* | 767 | *zz* |
@@ -800,7 +780,7 @@ fn main() { | |||
800 | enum Option<T> { Some(T) } | 780 | enum Option<T> { Some(T) } |
801 | use Option::Some; | 781 | use Option::Some; |
802 | 782 | ||
803 | fn main() { So<|>me(12); } | 783 | fn main() { So$0me(12); } |
804 | "#, | 784 | "#, |
805 | expect![[r#" | 785 | expect![[r#" |
806 | *Some* | 786 | *Some* |
@@ -820,7 +800,7 @@ fn main() { So<|>me(12); } | |||
820 | enum Option<T> { Some(T) } | 800 | enum Option<T> { Some(T) } |
821 | use Option::Some; | 801 | use Option::Some; |
822 | 802 | ||
823 | fn main() { let b<|>ar = Some(12); } | 803 | fn main() { let b$0ar = Some(12); } |
824 | "#, | 804 | "#, |
825 | expect![[r#" | 805 | expect![[r#" |
826 | *bar* | 806 | *bar* |
@@ -838,7 +818,7 @@ fn main() { let b<|>ar = Some(12); } | |||
838 | r#" | 818 | r#" |
839 | enum Option<T> { | 819 | enum Option<T> { |
840 | /// The None variant | 820 | /// The None variant |
841 | Non<|>e | 821 | Non$0e |
842 | } | 822 | } |
843 | "#, | 823 | "#, |
844 | expect![[r#" | 824 | expect![[r#" |
@@ -865,7 +845,7 @@ enum Option<T> { | |||
865 | Some(T) | 845 | Some(T) |
866 | } | 846 | } |
867 | fn main() { | 847 | fn main() { |
868 | let s = Option::Som<|>e(12); | 848 | let s = Option::Som$0e(12); |
869 | } | 849 | } |
870 | "#, | 850 | "#, |
871 | expect![[r#" | 851 | expect![[r#" |
@@ -889,7 +869,7 @@ fn main() { | |||
889 | #[test] | 869 | #[test] |
890 | fn hover_for_local_variable() { | 870 | fn hover_for_local_variable() { |
891 | check( | 871 | check( |
892 | r#"fn func(foo: i32) { fo<|>o; }"#, | 872 | r#"fn func(foo: i32) { fo$0o; }"#, |
893 | expect![[r#" | 873 | expect![[r#" |
894 | *foo* | 874 | *foo* |
895 | 875 | ||
@@ -903,7 +883,7 @@ fn main() { | |||
903 | #[test] | 883 | #[test] |
904 | fn hover_for_local_variable_pat() { | 884 | fn hover_for_local_variable_pat() { |
905 | check( | 885 | check( |
906 | r#"fn func(fo<|>o: i32) {}"#, | 886 | r#"fn func(fo$0o: i32) {}"#, |
907 | expect![[r#" | 887 | expect![[r#" |
908 | *foo* | 888 | *foo* |
909 | 889 | ||
@@ -917,7 +897,7 @@ fn main() { | |||
917 | #[test] | 897 | #[test] |
918 | fn hover_local_var_edge() { | 898 | fn hover_local_var_edge() { |
919 | check( | 899 | check( |
920 | r#"fn func(foo: i32) { if true { <|>foo; }; }"#, | 900 | r#"fn func(foo: i32) { if true { $0foo; }; }"#, |
921 | expect![[r#" | 901 | expect![[r#" |
922 | *foo* | 902 | *foo* |
923 | 903 | ||
@@ -931,7 +911,7 @@ fn main() { | |||
931 | #[test] | 911 | #[test] |
932 | fn hover_for_param_edge() { | 912 | fn hover_for_param_edge() { |
933 | check( | 913 | check( |
934 | r#"fn func(<|>foo: i32) {}"#, | 914 | r#"fn func($0foo: i32) {}"#, |
935 | expect![[r#" | 915 | expect![[r#" |
936 | *foo* | 916 | *foo* |
937 | 917 | ||
@@ -951,7 +931,7 @@ fn main() { | |||
951 | trait DerefMut { | 931 | trait DerefMut { |
952 | type Target: ?Sized; | 932 | type Target: ?Sized; |
953 | } | 933 | } |
954 | fn f(_x<|>: impl Deref<Target=u8> + DerefMut<Target=u8>) {}"#, | 934 | fn f(_x$0: impl Deref<Target=u8> + DerefMut<Target=u8>) {}"#, |
955 | expect![[r#" | 935 | expect![[r#" |
956 | *_x* | 936 | *_x* |
957 | 937 | ||
@@ -972,7 +952,7 @@ impl Thing { | |||
972 | fn new() -> Thing { Thing { x: 0 } } | 952 | fn new() -> Thing { Thing { x: 0 } } |
973 | } | 953 | } |
974 | 954 | ||
975 | fn main() { let foo_<|>test = Thing::new(); } | 955 | fn main() { let foo_$0test = Thing::new(); } |
976 | "#, | 956 | "#, |
977 | expect![[r#" | 957 | expect![[r#" |
978 | *foo_test* | 958 | *foo_test* |
@@ -996,7 +976,7 @@ mod wrapper { | |||
996 | } | 976 | } |
997 | } | 977 | } |
998 | 978 | ||
999 | fn main() { let foo_test = wrapper::Thing::new<|>(); } | 979 | fn main() { let foo_test = wrapper::Thing::new$0(); } |
1000 | "#, | 980 | "#, |
1001 | expect![[r#" | 981 | expect![[r#" |
1002 | *new* | 982 | *new* |
@@ -1023,7 +1003,7 @@ impl X { | |||
1023 | 1003 | ||
1024 | fn main() { | 1004 | fn main() { |
1025 | match 1 { | 1005 | match 1 { |
1026 | X::C<|> => {}, | 1006 | X::C$0 => {}, |
1027 | 2 => {}, | 1007 | 2 => {}, |
1028 | _ => {} | 1008 | _ => {} |
1029 | }; | 1009 | }; |
@@ -1049,7 +1029,7 @@ fn main() { | |||
1049 | r#" | 1029 | r#" |
1050 | struct Thing { x: u32 } | 1030 | struct Thing { x: u32 } |
1051 | impl Thing { | 1031 | impl Thing { |
1052 | fn new() -> Self { Self<|> { x: 0 } } | 1032 | fn new() -> Self { Self$0 { x: 0 } } |
1053 | } | 1033 | } |
1054 | "#, | 1034 | "#, |
1055 | expect![[r#" | 1035 | expect![[r#" |
@@ -1068,7 +1048,7 @@ impl Thing { | |||
1068 | r#" | 1048 | r#" |
1069 | struct Thing { x: u32 } | 1049 | struct Thing { x: u32 } |
1070 | impl Thing { | 1050 | impl Thing { |
1071 | fn new() -> Self<|> { Self { x: 0 } } | 1051 | fn new() -> Self$0 { Self { x: 0 } } |
1072 | } | 1052 | } |
1073 | "#, | 1053 | "#, |
1074 | expect![[r#" | 1054 | expect![[r#" |
@@ -1087,7 +1067,7 @@ impl Thing { | |||
1087 | r#" | 1067 | r#" |
1088 | enum Thing { A } | 1068 | enum Thing { A } |
1089 | impl Thing { | 1069 | impl Thing { |
1090 | pub fn new() -> Self<|> { Thing::A } | 1070 | pub fn new() -> Self$0 { Thing::A } |
1091 | } | 1071 | } |
1092 | "#, | 1072 | "#, |
1093 | expect![[r#" | 1073 | expect![[r#" |
@@ -1106,7 +1086,7 @@ impl Thing { | |||
1106 | r#" | 1086 | r#" |
1107 | enum Thing { A } | 1087 | enum Thing { A } |
1108 | impl Thing { | 1088 | impl Thing { |
1109 | pub fn thing(a: Self<|>) {} | 1089 | pub fn thing(a: Self$0) {} |
1110 | } | 1090 | } |
1111 | "#, | 1091 | "#, |
1112 | expect![[r#" | 1092 | expect![[r#" |
@@ -1131,7 +1111,7 @@ fn x() {} | |||
1131 | 1111 | ||
1132 | fn y() { | 1112 | fn y() { |
1133 | let x = 0i32; | 1113 | let x = 0i32; |
1134 | x<|>; | 1114 | x$0; |
1135 | } | 1115 | } |
1136 | "#, | 1116 | "#, |
1137 | expect![[r#" | 1117 | expect![[r#" |
@@ -1150,7 +1130,7 @@ fn y() { | |||
1150 | r#" | 1130 | r#" |
1151 | macro_rules! foo { () => {} } | 1131 | macro_rules! foo { () => {} } |
1152 | 1132 | ||
1153 | fn f() { fo<|>o!(); } | 1133 | fn f() { fo$0o!(); } |
1154 | "#, | 1134 | "#, |
1155 | expect![[r#" | 1135 | expect![[r#" |
1156 | *foo* | 1136 | *foo* |
@@ -1169,7 +1149,7 @@ fn f() { fo<|>o!(); } | |||
1169 | #[test] | 1149 | #[test] |
1170 | fn test_hover_tuple_field() { | 1150 | fn test_hover_tuple_field() { |
1171 | check( | 1151 | check( |
1172 | r#"struct TS(String, i32<|>);"#, | 1152 | r#"struct TS(String, i32$0);"#, |
1173 | expect![[r#" | 1153 | expect![[r#" |
1174 | *i32* | 1154 | *i32* |
1175 | 1155 | ||
@@ -1187,7 +1167,7 @@ fn f() { fo<|>o!(); } | |||
1187 | macro_rules! id { ($($tt:tt)*) => { $($tt)* } } | 1167 | macro_rules! id { ($($tt:tt)*) => { $($tt)* } } |
1188 | fn foo() {} | 1168 | fn foo() {} |
1189 | id! { | 1169 | id! { |
1190 | fn bar() { fo<|>o(); } | 1170 | fn bar() { fo$0o(); } |
1191 | } | 1171 | } |
1192 | "#, | 1172 | "#, |
1193 | expect![[r#" | 1173 | expect![[r#" |
@@ -1209,7 +1189,7 @@ id! { | |||
1209 | check( | 1189 | check( |
1210 | r#" | 1190 | r#" |
1211 | macro_rules! id { ($($tt:tt)*) => { $($tt)* } } | 1191 | macro_rules! id { ($($tt:tt)*) => { $($tt)* } } |
1212 | fn foo(bar:u32) { let a = id!(ba<|>r); } | 1192 | fn foo(bar:u32) { let a = id!(ba$0r); } |
1213 | "#, | 1193 | "#, |
1214 | expect![[r#" | 1194 | expect![[r#" |
1215 | *bar* | 1195 | *bar* |
@@ -1227,7 +1207,7 @@ fn foo(bar:u32) { let a = id!(ba<|>r); } | |||
1227 | r#" | 1207 | r#" |
1228 | macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } } | 1208 | macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } } |
1229 | macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } } | 1209 | macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } } |
1230 | fn foo(bar:u32) { let a = id!(ba<|>r); } | 1210 | fn foo(bar:u32) { let a = id!(ba$0r); } |
1231 | "#, | 1211 | "#, |
1232 | expect![[r#" | 1212 | expect![[r#" |
1233 | *bar* | 1213 | *bar* |
@@ -1246,7 +1226,7 @@ fn foo(bar:u32) { let a = id!(ba<|>r); } | |||
1246 | macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } } | 1226 | macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } } |
1247 | macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } } | 1227 | macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } } |
1248 | fn bar() -> u32 { 0 } | 1228 | fn bar() -> u32 { 0 } |
1249 | fn foo() { let a = id!([0u32, bar(<|>)] ); } | 1229 | fn foo() { let a = id!([0u32, bar($0)] ); } |
1250 | "#, | 1230 | "#, |
1251 | expect![[r#" | 1231 | expect![[r#" |
1252 | *bar()* | 1232 | *bar()* |
@@ -1264,7 +1244,7 @@ fn foo() { let a = id!([0u32, bar(<|>)] ); } | |||
1264 | macro_rules! arr { ($($tt:tt)*) => { [$($tt)*)] } } | 1244 | macro_rules! arr { ($($tt:tt)*) => { [$($tt)*)] } } |
1265 | fn foo() { | 1245 | fn foo() { |
1266 | let mastered_for_itunes = ""; | 1246 | let mastered_for_itunes = ""; |
1267 | let _ = arr!("Tr<|>acks", &mastered_for_itunes); | 1247 | let _ = arr!("Tr$0acks", &mastered_for_itunes); |
1268 | } | 1248 | } |
1269 | "#, | 1249 | "#, |
1270 | expect![[r#" | 1250 | expect![[r#" |
@@ -1285,7 +1265,7 @@ macro_rules! assert {} | |||
1285 | 1265 | ||
1286 | fn bar() -> bool { true } | 1266 | fn bar() -> bool { true } |
1287 | fn foo() { | 1267 | fn foo() { |
1288 | assert!(ba<|>r()); | 1268 | assert!(ba$0r()); |
1289 | } | 1269 | } |
1290 | "#, | 1270 | "#, |
1291 | expect![[r#" | 1271 | expect![[r#" |
@@ -1310,7 +1290,7 @@ fn foo() { | |||
1310 | macro_rules! format {} | 1290 | macro_rules! format {} |
1311 | 1291 | ||
1312 | fn foo() { | 1292 | fn foo() { |
1313 | format!("hel<|>lo {}", 0); | 1293 | format!("hel$0lo {}", 0); |
1314 | } | 1294 | } |
1315 | "#, | 1295 | "#, |
1316 | ); | 1296 | ); |
@@ -1323,7 +1303,7 @@ fn foo() { | |||
1323 | /// <- `\u{3000}` here | 1303 | /// <- `\u{3000}` here |
1324 | fn foo() { } | 1304 | fn foo() { } |
1325 | 1305 | ||
1326 | fn bar() { fo<|>o(); } | 1306 | fn bar() { fo$0o(); } |
1327 | ", | 1307 | ", |
1328 | expect![[r#" | 1308 | expect![[r#" |
1329 | *foo* | 1309 | *foo* |
@@ -1346,7 +1326,7 @@ fn bar() { fo<|>o(); } | |||
1346 | #[test] | 1326 | #[test] |
1347 | fn test_hover_function_show_qualifiers() { | 1327 | fn test_hover_function_show_qualifiers() { |
1348 | check( | 1328 | check( |
1349 | r#"async fn foo<|>() {}"#, | 1329 | r#"async fn foo$0() {}"#, |
1350 | expect![[r#" | 1330 | expect![[r#" |
1351 | *foo* | 1331 | *foo* |
1352 | 1332 | ||
@@ -1360,7 +1340,7 @@ fn bar() { fo<|>o(); } | |||
1360 | "#]], | 1340 | "#]], |
1361 | ); | 1341 | ); |
1362 | check( | 1342 | check( |
1363 | r#"pub const unsafe fn foo<|>() {}"#, | 1343 | r#"pub const unsafe fn foo$0() {}"#, |
1364 | expect![[r#" | 1344 | expect![[r#" |
1365 | *foo* | 1345 | *foo* |
1366 | 1346 | ||
@@ -1374,7 +1354,7 @@ fn bar() { fo<|>o(); } | |||
1374 | "#]], | 1354 | "#]], |
1375 | ); | 1355 | ); |
1376 | check( | 1356 | check( |
1377 | r#"pub(crate) async unsafe extern "C" fn foo<|>() {}"#, | 1357 | r#"pub(crate) async unsafe extern "C" fn foo$0() {}"#, |
1378 | expect![[r#" | 1358 | expect![[r#" |
1379 | *foo* | 1359 | *foo* |
1380 | 1360 | ||
@@ -1392,7 +1372,7 @@ fn bar() { fo<|>o(); } | |||
1392 | #[test] | 1372 | #[test] |
1393 | fn test_hover_trait_show_qualifiers() { | 1373 | fn test_hover_trait_show_qualifiers() { |
1394 | check_actions( | 1374 | check_actions( |
1395 | r"unsafe trait foo<|>() {}", | 1375 | r"unsafe trait foo$0() {}", |
1396 | expect![[r#" | 1376 | expect![[r#" |
1397 | [ | 1377 | [ |
1398 | Implementation( | 1378 | Implementation( |
@@ -1413,7 +1393,7 @@ fn bar() { fo<|>o(); } | |||
1413 | check( | 1393 | check( |
1414 | r#" | 1394 | r#" |
1415 | //- /main.rs crate:main deps:std | 1395 | //- /main.rs crate:main deps:std |
1416 | extern crate st<|>d; | 1396 | extern crate st$0d; |
1417 | //- /std/lib.rs crate:std | 1397 | //- /std/lib.rs crate:std |
1418 | //! Standard library for this test | 1398 | //! Standard library for this test |
1419 | //! | 1399 | //! |
@@ -1431,7 +1411,7 @@ extern crate st<|>d; | |||
1431 | check( | 1411 | check( |
1432 | r#" | 1412 | r#" |
1433 | //- /main.rs crate:main deps:std | 1413 | //- /main.rs crate:main deps:std |
1434 | extern crate std as ab<|>c; | 1414 | extern crate std as ab$0c; |
1435 | //- /std/lib.rs crate:std | 1415 | //- /std/lib.rs crate:std |
1436 | //! Standard library for this test | 1416 | //! Standard library for this test |
1437 | //! | 1417 | //! |
@@ -1452,7 +1432,7 @@ extern crate std as ab<|>c; | |||
1452 | fn test_hover_mod_with_same_name_as_function() { | 1432 | fn test_hover_mod_with_same_name_as_function() { |
1453 | check( | 1433 | check( |
1454 | r#" | 1434 | r#" |
1455 | use self::m<|>y::Bar; | 1435 | use self::m$0y::Bar; |
1456 | mod my { pub struct Bar; } | 1436 | mod my { pub struct Bar; } |
1457 | 1437 | ||
1458 | fn my() {} | 1438 | fn my() {} |
@@ -1478,7 +1458,7 @@ fn my() {} | |||
1478 | /// bar docs | 1458 | /// bar docs |
1479 | struct Bar; | 1459 | struct Bar; |
1480 | 1460 | ||
1481 | fn foo() { let bar = Ba<|>r; } | 1461 | fn foo() { let bar = Ba$0r; } |
1482 | "#, | 1462 | "#, |
1483 | expect![[r#" | 1463 | expect![[r#" |
1484 | *Bar* | 1464 | *Bar* |
@@ -1505,7 +1485,7 @@ fn foo() { let bar = Ba<|>r; } | |||
1505 | #[doc = "bar docs"] | 1485 | #[doc = "bar docs"] |
1506 | struct Bar; | 1486 | struct Bar; |
1507 | 1487 | ||
1508 | fn foo() { let bar = Ba<|>r; } | 1488 | fn foo() { let bar = Ba$0r; } |
1509 | "#, | 1489 | "#, |
1510 | expect![[r#" | 1490 | expect![[r#" |
1511 | *Bar* | 1491 | *Bar* |
@@ -1534,7 +1514,7 @@ fn foo() { let bar = Ba<|>r; } | |||
1534 | #[doc = "bar docs 2"] | 1514 | #[doc = "bar docs 2"] |
1535 | struct Bar; | 1515 | struct Bar; |
1536 | 1516 | ||
1537 | fn foo() { let bar = Ba<|>r; } | 1517 | fn foo() { let bar = Ba$0r; } |
1538 | "#, | 1518 | "#, |
1539 | expect![[r#" | 1519 | expect![[r#" |
1540 | *Bar* | 1520 | *Bar* |
@@ -1562,7 +1542,7 @@ fn foo() { let bar = Ba<|>r; } | |||
1562 | r#" | 1542 | r#" |
1563 | pub struct Foo; | 1543 | pub struct Foo; |
1564 | /// [Foo](struct.Foo.html) | 1544 | /// [Foo](struct.Foo.html) |
1565 | pub struct B<|>ar | 1545 | pub struct B$0ar |
1566 | "#, | 1546 | "#, |
1567 | expect![[r#" | 1547 | expect![[r#" |
1568 | *Bar* | 1548 | *Bar* |
@@ -1588,7 +1568,7 @@ pub struct B<|>ar | |||
1588 | r#" | 1568 | r#" |
1589 | pub struct Foo; | 1569 | pub struct Foo; |
1590 | /// [struct Foo](struct.Foo.html) | 1570 | /// [struct Foo](struct.Foo.html) |
1591 | pub struct B<|>ar | 1571 | pub struct B$0ar |
1592 | "#, | 1572 | "#, |
1593 | expect![[r#" | 1573 | expect![[r#" |
1594 | *Bar* | 1574 | *Bar* |
@@ -1616,7 +1596,7 @@ pub struct B<|>ar | |||
1616 | pub struct Foo; | 1596 | pub struct Foo; |
1617 | pub struct Bar { | 1597 | pub struct Bar { |
1618 | /// [Foo](struct.Foo.html) | 1598 | /// [Foo](struct.Foo.html) |
1619 | fie<|>ld: () | 1599 | fie$0ld: () |
1620 | } | 1600 | } |
1621 | "#, | 1601 | "#, |
1622 | expect![[r#" | 1602 | expect![[r#" |
@@ -1645,7 +1625,7 @@ pub mod foo { | |||
1645 | pub struct Foo; | 1625 | pub struct Foo; |
1646 | } | 1626 | } |
1647 | /// [Foo](foo::Foo) | 1627 | /// [Foo](foo::Foo) |
1648 | pub struct B<|>ar | 1628 | pub struct B$0ar |
1649 | "#, | 1629 | "#, |
1650 | expect![[r#" | 1630 | expect![[r#" |
1651 | *Bar* | 1631 | *Bar* |
@@ -1675,7 +1655,7 @@ pub mod foo { | |||
1675 | pub struct Foo; | 1655 | pub struct Foo; |
1676 | } | 1656 | } |
1677 | /// [Foo](foo::Foo) | 1657 | /// [Foo](foo::Foo) |
1678 | pub struct B<|>ar | 1658 | pub struct B$0ar |
1679 | "#, | 1659 | "#, |
1680 | expect![[r#" | 1660 | expect![[r#" |
1681 | *Bar* | 1661 | *Bar* |
@@ -1701,7 +1681,7 @@ pub struct B<|>ar | |||
1701 | r#" | 1681 | r#" |
1702 | pub struct Foo; | 1682 | pub struct Foo; |
1703 | /// [Foo] | 1683 | /// [Foo] |
1704 | pub struct B<|>ar | 1684 | pub struct B$0ar |
1705 | "#, | 1685 | "#, |
1706 | expect![[r#" | 1686 | expect![[r#" |
1707 | *Bar* | 1687 | *Bar* |
@@ -1727,7 +1707,7 @@ pub struct B<|>ar | |||
1727 | r#" | 1707 | r#" |
1728 | pub struct Foo; | 1708 | pub struct Foo; |
1729 | /// [`Foo`] | 1709 | /// [`Foo`] |
1730 | pub struct B<|>ar | 1710 | pub struct B$0ar |
1731 | "#, | 1711 | "#, |
1732 | expect![[r#" | 1712 | expect![[r#" |
1733 | *Bar* | 1713 | *Bar* |
@@ -1754,7 +1734,7 @@ pub struct B<|>ar | |||
1754 | pub struct Foo; | 1734 | pub struct Foo; |
1755 | fn Foo() {} | 1735 | fn Foo() {} |
1756 | /// [Foo()] | 1736 | /// [Foo()] |
1757 | pub struct B<|>ar | 1737 | pub struct B$0ar |
1758 | "#, | 1738 | "#, |
1759 | expect![[r#" | 1739 | expect![[r#" |
1760 | *Bar* | 1740 | *Bar* |
@@ -1780,7 +1760,7 @@ pub struct B<|>ar | |||
1780 | r#" | 1760 | r#" |
1781 | pub struct Foo; | 1761 | pub struct Foo; |
1782 | /// [`struct Foo`] | 1762 | /// [`struct Foo`] |
1783 | pub struct B<|>ar | 1763 | pub struct B$0ar |
1784 | "#, | 1764 | "#, |
1785 | expect![[r#" | 1765 | expect![[r#" |
1786 | *Bar* | 1766 | *Bar* |
@@ -1806,7 +1786,7 @@ pub struct B<|>ar | |||
1806 | r#" | 1786 | r#" |
1807 | pub struct Foo; | 1787 | pub struct Foo; |
1808 | /// [`struct@Foo`] | 1788 | /// [`struct@Foo`] |
1809 | pub struct B<|>ar | 1789 | pub struct B$0ar |
1810 | "#, | 1790 | "#, |
1811 | expect![[r#" | 1791 | expect![[r#" |
1812 | *Bar* | 1792 | *Bar* |
@@ -1834,7 +1814,7 @@ pub struct Foo; | |||
1834 | /// [my Foo][foo] | 1814 | /// [my Foo][foo] |
1835 | /// | 1815 | /// |
1836 | /// [foo]: Foo | 1816 | /// [foo]: Foo |
1837 | pub struct B<|>ar | 1817 | pub struct B$0ar |
1838 | "#, | 1818 | "#, |
1839 | expect![[r#" | 1819 | expect![[r#" |
1840 | *Bar* | 1820 | *Bar* |
@@ -1860,7 +1840,7 @@ pub struct B<|>ar | |||
1860 | r#" | 1840 | r#" |
1861 | pub struct Foo; | 1841 | pub struct Foo; |
1862 | /// [external](https://www.google.com) | 1842 | /// [external](https://www.google.com) |
1863 | pub struct B<|>ar | 1843 | pub struct B$0ar |
1864 | "#, | 1844 | "#, |
1865 | expect![[r#" | 1845 | expect![[r#" |
1866 | *Bar* | 1846 | *Bar* |
@@ -1887,7 +1867,7 @@ pub struct B<|>ar | |||
1887 | r#" | 1867 | r#" |
1888 | pub struct Foo; | 1868 | pub struct Foo; |
1889 | /// [baz](Baz) | 1869 | /// [baz](Baz) |
1890 | pub struct B<|>ar | 1870 | pub struct B$0ar |
1891 | "#, | 1871 | "#, |
1892 | expect![[r#" | 1872 | expect![[r#" |
1893 | *Bar* | 1873 | *Bar* |
@@ -1913,7 +1893,7 @@ pub struct B<|>ar | |||
1913 | r#" | 1893 | r#" |
1914 | enum E { | 1894 | enum E { |
1915 | /// [E] | 1895 | /// [E] |
1916 | V<|> { field: i32 } | 1896 | V$0 { field: i32 } |
1917 | } | 1897 | } |
1918 | "#, | 1898 | "#, |
1919 | expect![[r#" | 1899 | expect![[r#" |
@@ -1940,7 +1920,7 @@ enum E { | |||
1940 | r#" | 1920 | r#" |
1941 | struct S { | 1921 | struct S { |
1942 | /// [`S`] | 1922 | /// [`S`] |
1943 | field<|>: i32 | 1923 | field$0: i32 |
1944 | } | 1924 | } |
1945 | "#, | 1925 | "#, |
1946 | expect![[r#" | 1926 | expect![[r#" |
@@ -1968,16 +1948,16 @@ struct S { | |||
1968 | /// Test cases: | 1948 | /// Test cases: |
1969 | /// case 1. bare URL: https://www.example.com/ | 1949 | /// case 1. bare URL: https://www.example.com/ |
1970 | /// case 2. inline URL with title: [example](https://www.example.com/) | 1950 | /// case 2. inline URL with title: [example](https://www.example.com/) |
1971 | /// case 3. code refrence: [`Result`] | 1951 | /// case 3. code reference: [`Result`] |
1972 | /// case 4. code refrence but miss footnote: [`String`] | 1952 | /// case 4. code reference but miss footnote: [`String`] |
1973 | /// case 5. autolink: <http://www.example.com/> | 1953 | /// case 5. autolink: <http://www.example.com/> |
1974 | /// case 6. email address: <[email protected]> | 1954 | /// case 6. email address: <[email protected]> |
1975 | /// case 7. refrence: [example][example] | 1955 | /// case 7. reference: [example][example] |
1976 | /// case 8. collapsed link: [example][] | 1956 | /// case 8. collapsed link: [example][] |
1977 | /// case 9. shortcut link: [example] | 1957 | /// case 9. shortcut link: [example] |
1978 | /// case 10. inline without URL: [example]() | 1958 | /// case 10. inline without URL: [example]() |
1979 | /// case 11. refrence: [foo][foo] | 1959 | /// case 11. reference: [foo][foo] |
1980 | /// case 12. refrence: [foo][bar] | 1960 | /// case 12. reference: [foo][bar] |
1981 | /// case 13. collapsed link: [foo][] | 1961 | /// case 13. collapsed link: [foo][] |
1982 | /// case 14. shortcut link: [foo] | 1962 | /// case 14. shortcut link: [foo] |
1983 | /// case 15. inline without URL: [foo]() | 1963 | /// case 15. inline without URL: [foo]() |
@@ -1986,7 +1966,7 @@ struct S { | |||
1986 | /// | 1966 | /// |
1987 | /// [`Result`]: ../../std/result/enum.Result.html | 1967 | /// [`Result`]: ../../std/result/enum.Result.html |
1988 | /// [^example]: https://www.example.com/ | 1968 | /// [^example]: https://www.example.com/ |
1989 | pub fn fo<|>o() {} | 1969 | pub fn fo$0o() {} |
1990 | "#, | 1970 | "#, |
1991 | expect![[r#" | 1971 | expect![[r#" |
1992 | *foo* | 1972 | *foo* |
@@ -2004,16 +1984,16 @@ pub fn fo<|>o() {} | |||
2004 | Test cases: | 1984 | Test cases: |
2005 | case 1. bare URL: https://www.example.com/ | 1985 | case 1. bare URL: https://www.example.com/ |
2006 | case 2. inline URL with title: [example](https://www.example.com/) | 1986 | case 2. inline URL with title: [example](https://www.example.com/) |
2007 | case 3. code refrence: `Result` | 1987 | case 3. code reference: `Result` |
2008 | case 4. code refrence but miss footnote: `String` | 1988 | case 4. code reference but miss footnote: `String` |
2009 | case 5. autolink: http://www.example.com/ | 1989 | case 5. autolink: http://www.example.com/ |
2010 | case 6. email address: [email protected] | 1990 | case 6. email address: [email protected] |
2011 | case 7. refrence: example | 1991 | case 7. reference: example |
2012 | case 8. collapsed link: example | 1992 | case 8. collapsed link: example |
2013 | case 9. shortcut link: example | 1993 | case 9. shortcut link: example |
2014 | case 10. inline without URL: example | 1994 | case 10. inline without URL: example |
2015 | case 11. refrence: foo | 1995 | case 11. reference: foo |
2016 | case 12. refrence: foo | 1996 | case 12. reference: foo |
2017 | case 13. collapsed link: foo | 1997 | case 13. collapsed link: foo |
2018 | case 14. shortcut link: foo | 1998 | case 14. shortcut link: foo |
2019 | case 15. inline without URL: foo | 1999 | case 15. inline without URL: foo |
@@ -2043,7 +2023,7 @@ macro_rules! bar { | |||
2043 | 2023 | ||
2044 | bar!(); | 2024 | bar!(); |
2045 | 2025 | ||
2046 | fn foo() { let bar = Bar; bar.fo<|>o(); } | 2026 | fn foo() { let bar = Bar; bar.fo$0o(); } |
2047 | "#, | 2027 | "#, |
2048 | expect![[r#" | 2028 | expect![[r#" |
2049 | *foo* | 2029 | *foo* |
@@ -2081,7 +2061,7 @@ macro_rules! bar { | |||
2081 | 2061 | ||
2082 | bar!(); | 2062 | bar!(); |
2083 | 2063 | ||
2084 | fn foo() { let bar = Bar; bar.fo<|>o(); } | 2064 | fn foo() { let bar = Bar; bar.fo$0o(); } |
2085 | "#, | 2065 | "#, |
2086 | expect![[r#" | 2066 | expect![[r#" |
2087 | *foo* | 2067 | *foo* |
@@ -2104,7 +2084,7 @@ fn foo() { let bar = Bar; bar.fo<|>o(); } | |||
2104 | #[test] | 2084 | #[test] |
2105 | fn test_hover_trait_has_impl_action() { | 2085 | fn test_hover_trait_has_impl_action() { |
2106 | check_actions( | 2086 | check_actions( |
2107 | r#"trait foo<|>() {}"#, | 2087 | r#"trait foo$0() {}"#, |
2108 | expect![[r#" | 2088 | expect![[r#" |
2109 | [ | 2089 | [ |
2110 | Implementation( | 2090 | Implementation( |
@@ -2123,7 +2103,7 @@ fn foo() { let bar = Bar; bar.fo<|>o(); } | |||
2123 | #[test] | 2103 | #[test] |
2124 | fn test_hover_struct_has_impl_action() { | 2104 | fn test_hover_struct_has_impl_action() { |
2125 | check_actions( | 2105 | check_actions( |
2126 | r"struct foo<|>() {}", | 2106 | r"struct foo$0() {}", |
2127 | expect![[r#" | 2107 | expect![[r#" |
2128 | [ | 2108 | [ |
2129 | Implementation( | 2109 | Implementation( |
@@ -2142,7 +2122,7 @@ fn foo() { let bar = Bar; bar.fo<|>o(); } | |||
2142 | #[test] | 2122 | #[test] |
2143 | fn test_hover_union_has_impl_action() { | 2123 | fn test_hover_union_has_impl_action() { |
2144 | check_actions( | 2124 | check_actions( |
2145 | r#"union foo<|>() {}"#, | 2125 | r#"union foo$0() {}"#, |
2146 | expect![[r#" | 2126 | expect![[r#" |
2147 | [ | 2127 | [ |
2148 | Implementation( | 2128 | Implementation( |
@@ -2161,7 +2141,7 @@ fn foo() { let bar = Bar; bar.fo<|>o(); } | |||
2161 | #[test] | 2141 | #[test] |
2162 | fn test_hover_enum_has_impl_action() { | 2142 | fn test_hover_enum_has_impl_action() { |
2163 | check_actions( | 2143 | check_actions( |
2164 | r"enum foo<|>() { A, B }", | 2144 | r"enum foo$0() { A, B }", |
2165 | expect![[r#" | 2145 | expect![[r#" |
2166 | [ | 2146 | [ |
2167 | Implementation( | 2147 | Implementation( |
@@ -2180,7 +2160,7 @@ fn foo() { let bar = Bar; bar.fo<|>o(); } | |||
2180 | #[test] | 2160 | #[test] |
2181 | fn test_hover_self_has_impl_action() { | 2161 | fn test_hover_self_has_impl_action() { |
2182 | check_actions( | 2162 | check_actions( |
2183 | r#"struct foo where Self<|>:;"#, | 2163 | r#"struct foo where Self$0:;"#, |
2184 | expect![[r#" | 2164 | expect![[r#" |
2185 | [ | 2165 | [ |
2186 | Implementation( | 2166 | Implementation( |
@@ -2201,7 +2181,7 @@ fn foo() { let bar = Bar; bar.fo<|>o(); } | |||
2201 | check_actions( | 2181 | check_actions( |
2202 | r#" | 2182 | r#" |
2203 | #[test] | 2183 | #[test] |
2204 | fn foo_<|>test() {} | 2184 | fn foo_$0test() {} |
2205 | "#, | 2185 | "#, |
2206 | expect![[r#" | 2186 | expect![[r#" |
2207 | [ | 2187 | [ |
@@ -2236,7 +2216,7 @@ fn foo_<|>test() {} | |||
2236 | fn test_hover_test_mod_has_action() { | 2216 | fn test_hover_test_mod_has_action() { |
2237 | check_actions( | 2217 | check_actions( |
2238 | r#" | 2218 | r#" |
2239 | mod tests<|> { | 2219 | mod tests$0 { |
2240 | #[test] | 2220 | #[test] |
2241 | fn foo_test() {} | 2221 | fn foo_test() {} |
2242 | } | 2222 | } |
@@ -2271,7 +2251,7 @@ mod tests<|> { | |||
2271 | r#" | 2251 | r#" |
2272 | struct S{ f1: u32 } | 2252 | struct S{ f1: u32 } |
2273 | 2253 | ||
2274 | fn main() { let s<|>t = S{ f1:0 }; } | 2254 | fn main() { let s$0t = S{ f1:0 }; } |
2275 | "#, | 2255 | "#, |
2276 | expect![[r#" | 2256 | expect![[r#" |
2277 | [ | 2257 | [ |
@@ -2304,7 +2284,7 @@ fn main() { let s<|>t = S{ f1:0 }; } | |||
2304 | struct Arg(u32); | 2284 | struct Arg(u32); |
2305 | struct S<T>{ f1: T } | 2285 | struct S<T>{ f1: T } |
2306 | 2286 | ||
2307 | fn main() { let s<|>t = S{ f1:Arg(0) }; } | 2287 | fn main() { let s$0t = S{ f1:Arg(0) }; } |
2308 | "#, | 2288 | "#, |
2309 | expect![[r#" | 2289 | expect![[r#" |
2310 | [ | 2290 | [ |
@@ -2350,7 +2330,7 @@ fn main() { let s<|>t = S{ f1:Arg(0) }; } | |||
2350 | struct Arg(u32); | 2330 | struct Arg(u32); |
2351 | struct S<T>{ f1: T } | 2331 | struct S<T>{ f1: T } |
2352 | 2332 | ||
2353 | fn main() { let s<|>t = S{ f1: S{ f1: Arg(0) } }; } | 2333 | fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; } |
2354 | "#, | 2334 | "#, |
2355 | expect![[r#" | 2335 | expect![[r#" |
2356 | [ | 2336 | [ |
@@ -2399,7 +2379,7 @@ mod M { | |||
2399 | pub struct C(u32); | 2379 | pub struct C(u32); |
2400 | } | 2380 | } |
2401 | 2381 | ||
2402 | fn main() { let s<|>t = (A(1), B(2), M::C(3) ); } | 2382 | fn main() { let s$0t = (A(1), B(2), M::C(3) ); } |
2403 | "#, | 2383 | "#, |
2404 | expect![[r#" | 2384 | expect![[r#" |
2405 | [ | 2385 | [ |
@@ -2458,7 +2438,7 @@ fn main() { let s<|>t = (A(1), B(2), M::C(3) ); } | |||
2458 | trait Foo {} | 2438 | trait Foo {} |
2459 | fn foo() -> impl Foo {} | 2439 | fn foo() -> impl Foo {} |
2460 | 2440 | ||
2461 | fn main() { let s<|>t = foo(); } | 2441 | fn main() { let s$0t = foo(); } |
2462 | "#, | 2442 | "#, |
2463 | expect![[r#" | 2443 | expect![[r#" |
2464 | [ | 2444 | [ |
@@ -2492,7 +2472,7 @@ trait Foo<T> {} | |||
2492 | struct S; | 2472 | struct S; |
2493 | fn foo() -> impl Foo<S> {} | 2473 | fn foo() -> impl Foo<S> {} |
2494 | 2474 | ||
2495 | fn main() { let s<|>t = foo(); } | 2475 | fn main() { let s$0t = foo(); } |
2496 | "#, | 2476 | "#, |
2497 | expect![[r#" | 2477 | expect![[r#" |
2498 | [ | 2478 | [ |
@@ -2539,7 +2519,7 @@ trait Foo {} | |||
2539 | trait Bar {} | 2519 | trait Bar {} |
2540 | fn foo() -> impl Foo + Bar {} | 2520 | fn foo() -> impl Foo + Bar {} |
2541 | 2521 | ||
2542 | fn main() { let s<|>t = foo(); } | 2522 | fn main() { let s$0t = foo(); } |
2543 | "#, | 2523 | "#, |
2544 | expect![[r#" | 2524 | expect![[r#" |
2545 | [ | 2525 | [ |
@@ -2589,7 +2569,7 @@ struct S2 {} | |||
2589 | 2569 | ||
2590 | fn foo() -> impl Foo<S1> + Bar<S2> {} | 2570 | fn foo() -> impl Foo<S1> + Bar<S2> {} |
2591 | 2571 | ||
2592 | fn main() { let s<|>t = foo(); } | 2572 | fn main() { let s$0t = foo(); } |
2593 | "#, | 2573 | "#, |
2594 | expect![[r#" | 2574 | expect![[r#" |
2595 | [ | 2575 | [ |
@@ -2659,7 +2639,7 @@ fn main() { let s<|>t = foo(); } | |||
2659 | check_actions( | 2639 | check_actions( |
2660 | r#" | 2640 | r#" |
2661 | trait Foo {} | 2641 | trait Foo {} |
2662 | fn foo(ar<|>g: &impl Foo) {} | 2642 | fn foo(ar$0g: &impl Foo) {} |
2663 | "#, | 2643 | "#, |
2664 | expect![[r#" | 2644 | expect![[r#" |
2665 | [ | 2645 | [ |
@@ -2693,7 +2673,7 @@ trait Foo {} | |||
2693 | trait Bar<T> {} | 2673 | trait Bar<T> {} |
2694 | struct S{} | 2674 | struct S{} |
2695 | 2675 | ||
2696 | fn foo(ar<|>g: &impl Foo + Bar<S>) {} | 2676 | fn foo(ar$0g: &impl Foo + Bar<S>) {} |
2697 | "#, | 2677 | "#, |
2698 | expect![[r#" | 2678 | expect![[r#" |
2699 | [ | 2679 | [ |
@@ -2751,7 +2731,7 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {} | |||
2751 | r#" | 2731 | r#" |
2752 | struct S; | 2732 | struct S; |
2753 | fn foo() { | 2733 | fn foo() { |
2754 | let fo<|>o = async { S }; | 2734 | let fo$0o = async { S }; |
2755 | } | 2735 | } |
2756 | 2736 | ||
2757 | #[prelude_import] use future::*; | 2737 | #[prelude_import] use future::*; |
@@ -2803,7 +2783,7 @@ mod future { | |||
2803 | r#" | 2783 | r#" |
2804 | trait Foo<T> {} | 2784 | trait Foo<T> {} |
2805 | struct S {} | 2785 | struct S {} |
2806 | fn foo(ar<|>g: &impl Foo<S>) {} | 2786 | fn foo(ar$0g: &impl Foo<S>) {} |
2807 | "#, | 2787 | "#, |
2808 | expect![[r#" | 2788 | expect![[r#" |
2809 | [ | 2789 | [ |
@@ -2853,7 +2833,7 @@ impl Foo for S {} | |||
2853 | struct B<T>{} | 2833 | struct B<T>{} |
2854 | fn foo() -> B<dyn Foo> {} | 2834 | fn foo() -> B<dyn Foo> {} |
2855 | 2835 | ||
2856 | fn main() { let s<|>t = foo(); } | 2836 | fn main() { let s$0t = foo(); } |
2857 | "#, | 2837 | "#, |
2858 | expect![[r#" | 2838 | expect![[r#" |
2859 | [ | 2839 | [ |
@@ -2897,7 +2877,7 @@ fn main() { let s<|>t = foo(); } | |||
2897 | check_actions( | 2877 | check_actions( |
2898 | r#" | 2878 | r#" |
2899 | trait Foo {} | 2879 | trait Foo {} |
2900 | fn foo(ar<|>g: &dyn Foo) {} | 2880 | fn foo(ar$0g: &dyn Foo) {} |
2901 | "#, | 2881 | "#, |
2902 | expect![[r#" | 2882 | expect![[r#" |
2903 | [ | 2883 | [ |
@@ -2929,7 +2909,7 @@ fn foo(ar<|>g: &dyn Foo) {} | |||
2929 | r#" | 2909 | r#" |
2930 | trait Foo<T> {} | 2910 | trait Foo<T> {} |
2931 | struct S {} | 2911 | struct S {} |
2932 | fn foo(ar<|>g: &dyn Foo<S>) {} | 2912 | fn foo(ar$0g: &dyn Foo<S>) {} |
2933 | "#, | 2913 | "#, |
2934 | expect![[r#" | 2914 | expect![[r#" |
2935 | [ | 2915 | [ |
@@ -2977,7 +2957,7 @@ trait DynTrait<T> {} | |||
2977 | struct B<T> {} | 2957 | struct B<T> {} |
2978 | struct S {} | 2958 | struct S {} |
2979 | 2959 | ||
2980 | fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {} | 2960 | fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {} |
2981 | "#, | 2961 | "#, |
2982 | expect![[r#" | 2962 | expect![[r#" |
2983 | [ | 2963 | [ |
@@ -3058,7 +3038,7 @@ impl Foo for S { type Item = Bar; } | |||
3058 | 3038 | ||
3059 | fn test() -> impl Foo { S {} } | 3039 | fn test() -> impl Foo { S {} } |
3060 | 3040 | ||
3061 | fn main() { let s<|>t = test().get(); } | 3041 | fn main() { let s$0t = test().get(); } |
3062 | "#, | 3042 | "#, |
3063 | expect![[r#" | 3043 | expect![[r#" |
3064 | [ | 3044 | [ |
@@ -3091,7 +3071,7 @@ fn main() { let s<|>t = test().get(); } | |||
3091 | struct Bar; | 3071 | struct Bar; |
3092 | struct Foo<const BAR: Bar>; | 3072 | struct Foo<const BAR: Bar>; |
3093 | 3073 | ||
3094 | impl<const BAR: Bar> Foo<BAR<|>> {} | 3074 | impl<const BAR: Bar> Foo<BAR$0> {} |
3095 | "#, | 3075 | "#, |
3096 | expect![[r#" | 3076 | expect![[r#" |
3097 | [ | 3077 | [ |
@@ -3123,7 +3103,7 @@ impl<const BAR: Bar> Foo<BAR<|>> {} | |||
3123 | r#" | 3103 | r#" |
3124 | trait Foo {} | 3104 | trait Foo {} |
3125 | 3105 | ||
3126 | fn foo<T: Foo>(t: T<|>){} | 3106 | fn foo<T: Foo>(t: T$0){} |
3127 | "#, | 3107 | "#, |
3128 | expect![[r#" | 3108 | expect![[r#" |
3129 | [ | 3109 | [ |
@@ -3163,7 +3143,7 @@ pub mod wrapper { | |||
3163 | } | 3143 | } |
3164 | 3144 | ||
3165 | //- /main.rs crate:main deps:name-with-dashes | 3145 | //- /main.rs crate:main deps:name-with-dashes |
3166 | fn main() { let foo_test = name_with_dashes::wrapper::Thing::new<|>(); } | 3146 | fn main() { let foo_test = name_with_dashes::wrapper::Thing::new$0(); } |
3167 | "#, | 3147 | "#, |
3168 | expect![[r#" | 3148 | expect![[r#" |
3169 | *new* | 3149 | *new* |
@@ -3189,7 +3169,7 @@ struct S { | |||
3189 | 3169 | ||
3190 | fn main() { | 3170 | fn main() { |
3191 | let s = S { f: 0 }; | 3171 | let s = S { f: 0 }; |
3192 | let S { f<|> } = &s; | 3172 | let S { f$0 } = &s; |
3193 | } | 3173 | } |
3194 | "#, | 3174 | "#, |
3195 | expect![[r#" | 3175 | expect![[r#" |
@@ -3208,7 +3188,7 @@ fn main() { | |||
3208 | r#" | 3188 | r#" |
3209 | struct Foo {} | 3189 | struct Foo {} |
3210 | impl Foo { | 3190 | impl Foo { |
3211 | fn bar(&sel<|>f) {} | 3191 | fn bar(&sel$0f) {} |
3212 | } | 3192 | } |
3213 | "#, | 3193 | "#, |
3214 | expect![[r#" | 3194 | expect![[r#" |
@@ -3227,7 +3207,7 @@ impl Foo { | |||
3227 | struct Arc<T>(T); | 3207 | struct Arc<T>(T); |
3228 | struct Foo {} | 3208 | struct Foo {} |
3229 | impl Foo { | 3209 | impl Foo { |
3230 | fn bar(sel<|>f: Arc<Foo>) {} | 3210 | fn bar(sel$0f: Arc<Foo>) {} |
3231 | } | 3211 | } |
3232 | "#, | 3212 | "#, |
3233 | expect![[r#" | 3213 | expect![[r#" |
@@ -3244,7 +3224,7 @@ impl Foo { | |||
3244 | check( | 3224 | check( |
3245 | r#" | 3225 | r#" |
3246 | /// Be quick; | 3226 | /// Be quick; |
3247 | mod Foo<|> { | 3227 | mod Foo$0 { |
3248 | //! time is mana | 3228 | //! time is mana |
3249 | 3229 | ||
3250 | /// This comment belongs to the function | 3230 | /// This comment belongs to the function |
@@ -3275,7 +3255,7 @@ mod Foo<|> { | |||
3275 | check( | 3255 | check( |
3276 | r#" | 3256 | r#" |
3277 | #[doc = "Be quick;"] | 3257 | #[doc = "Be quick;"] |
3278 | mod Foo<|> { | 3258 | mod Foo$0 { |
3279 | #![doc = "time is mana"] | 3259 | #![doc = "time is mana"] |
3280 | 3260 | ||
3281 | #[doc = "This comment belongs to the function"] | 3261 | #[doc = "This comment belongs to the function"] |
@@ -3306,7 +3286,7 @@ mod Foo<|> { | |||
3306 | check_hover_no_result( | 3286 | check_hover_no_result( |
3307 | r#" | 3287 | r#" |
3308 | fn no_hover() { | 3288 | fn no_hover() { |
3309 | // no<|>hover | 3289 | // no$0hover |
3310 | } | 3290 | } |
3311 | "#, | 3291 | "#, |
3312 | ); | 3292 | ); |
@@ -3317,7 +3297,7 @@ fn no_hover() { | |||
3317 | check( | 3297 | check( |
3318 | r#" | 3298 | r#" |
3319 | fn foo() { | 3299 | fn foo() { |
3320 | 'label<|>: loop {} | 3300 | 'label$0: loop {} |
3321 | } | 3301 | } |
3322 | "#, | 3302 | "#, |
3323 | expect![[r#" | 3303 | expect![[r#" |
@@ -3333,7 +3313,7 @@ fn foo() { | |||
3333 | #[test] | 3313 | #[test] |
3334 | fn hover_lifetime() { | 3314 | fn hover_lifetime() { |
3335 | check( | 3315 | check( |
3336 | r#"fn foo<'lifetime>(_: &'lifetime<|> ()) {}"#, | 3316 | r#"fn foo<'lifetime>(_: &'lifetime$0 ()) {}"#, |
3337 | expect![[r#" | 3317 | expect![[r#" |
3338 | *'lifetime* | 3318 | *'lifetime* |
3339 | 3319 | ||
@@ -3352,7 +3332,7 @@ struct Foo<T>(T); | |||
3352 | trait Copy {} | 3332 | trait Copy {} |
3353 | trait Clone {} | 3333 | trait Clone {} |
3354 | trait Sized {} | 3334 | trait Sized {} |
3355 | impl<T: Copy + Clone> Foo<T<|>> where T: Sized {} | 3335 | impl<T: Copy + Clone> Foo<T$0> where T: Sized {} |
3356 | "#, | 3336 | "#, |
3357 | expect![[r#" | 3337 | expect![[r#" |
3358 | *T* | 3338 | *T* |
@@ -3365,7 +3345,7 @@ impl<T: Copy + Clone> Foo<T<|>> where T: Sized {} | |||
3365 | check( | 3345 | check( |
3366 | r#" | 3346 | r#" |
3367 | struct Foo<T>(T); | 3347 | struct Foo<T>(T); |
3368 | impl<T> Foo<T<|>> {} | 3348 | impl<T> Foo<T$0> {} |
3369 | "#, | 3349 | "#, |
3370 | expect![[r#" | 3350 | expect![[r#" |
3371 | *T* | 3351 | *T* |
@@ -3379,7 +3359,7 @@ impl<T> Foo<T<|>> {} | |||
3379 | check( | 3359 | check( |
3380 | r#" | 3360 | r#" |
3381 | struct Foo<T>(T); | 3361 | struct Foo<T>(T); |
3382 | impl<T: 'static> Foo<T<|>> {} | 3362 | impl<T: 'static> Foo<T$0> {} |
3383 | "#, | 3363 | "#, |
3384 | expect![[r#" | 3364 | expect![[r#" |
3385 | *T* | 3365 | *T* |
@@ -3396,7 +3376,7 @@ impl<T: 'static> Foo<T<|>> {} | |||
3396 | check( | 3376 | check( |
3397 | r#" | 3377 | r#" |
3398 | struct Foo<const LEN: usize>; | 3378 | struct Foo<const LEN: usize>; |
3399 | impl<const LEN: usize> Foo<LEN<|>> {} | 3379 | impl<const LEN: usize> Foo<LEN$0> {} |
3400 | "#, | 3380 | "#, |
3401 | expect![[r#" | 3381 | expect![[r#" |
3402 | *LEN* | 3382 | *LEN* |
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 65df7979c..3e9a65d9c 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs | |||
@@ -18,12 +18,6 @@ pub struct InlayHintsConfig { | |||
18 | pub max_length: Option<usize>, | 18 | pub max_length: Option<usize>, |
19 | } | 19 | } |
20 | 20 | ||
21 | impl Default for InlayHintsConfig { | ||
22 | fn default() -> Self { | ||
23 | Self { type_hints: true, parameter_hints: true, chaining_hints: true, max_length: None } | ||
24 | } | ||
25 | } | ||
26 | |||
27 | #[derive(Clone, Debug, PartialEq, Eq)] | 21 | #[derive(Clone, Debug, PartialEq, Eq)] |
28 | pub enum InlayKind { | 22 | pub enum InlayKind { |
29 | TypeHint, | 23 | TypeHint, |
@@ -359,9 +353,25 @@ fn is_argument_similar_to_param_name( | |||
359 | } | 353 | } |
360 | match get_string_representation(argument) { | 354 | match get_string_representation(argument) { |
361 | None => false, | 355 | None => false, |
362 | Some(repr) => { | 356 | Some(argument_string) => { |
363 | let argument_string = repr.trim_start_matches('_'); | 357 | let num_leading_underscores = |
364 | argument_string.starts_with(param_name) || argument_string.ends_with(param_name) | 358 | argument_string.bytes().take_while(|&c| c == b'_').count(); |
359 | |||
360 | // Does the argument name begin with the parameter name? Ignore leading underscores. | ||
361 | let mut arg_bytes = argument_string.bytes().skip(num_leading_underscores); | ||
362 | let starts_with_pattern = param_name.bytes().all( | ||
363 | |expected| matches!(arg_bytes.next(), Some(actual) if expected.eq_ignore_ascii_case(&actual)), | ||
364 | ); | ||
365 | |||
366 | if starts_with_pattern { | ||
367 | return true; | ||
368 | } | ||
369 | |||
370 | // Does the argument name end with the parameter name? | ||
371 | let mut arg_bytes = argument_string.bytes().skip(num_leading_underscores); | ||
372 | param_name.bytes().rev().all( | ||
373 | |expected| matches!(arg_bytes.next_back(), Some(actual) if expected.eq_ignore_ascii_case(&actual)), | ||
374 | ) | ||
365 | } | 375 | } |
366 | } | 376 | } |
367 | } | 377 | } |
@@ -433,8 +443,15 @@ mod tests { | |||
433 | 443 | ||
434 | use crate::{fixture, inlay_hints::InlayHintsConfig}; | 444 | use crate::{fixture, inlay_hints::InlayHintsConfig}; |
435 | 445 | ||
446 | const TEST_CONFIG: InlayHintsConfig = InlayHintsConfig { | ||
447 | type_hints: true, | ||
448 | parameter_hints: true, | ||
449 | chaining_hints: true, | ||
450 | max_length: None, | ||
451 | }; | ||
452 | |||
436 | fn check(ra_fixture: &str) { | 453 | fn check(ra_fixture: &str) { |
437 | check_with_config(InlayHintsConfig::default(), ra_fixture); | 454 | check_with_config(TEST_CONFIG, ra_fixture); |
438 | } | 455 | } |
439 | 456 | ||
440 | fn check_with_config(config: InlayHintsConfig, ra_fixture: &str) { | 457 | fn check_with_config(config: InlayHintsConfig, ra_fixture: &str) { |
@@ -748,7 +765,7 @@ fn main() { | |||
748 | #[test] | 765 | #[test] |
749 | fn hint_truncation() { | 766 | fn hint_truncation() { |
750 | check_with_config( | 767 | check_with_config( |
751 | InlayHintsConfig { max_length: Some(8), ..Default::default() }, | 768 | InlayHintsConfig { max_length: Some(8), ..TEST_CONFIG }, |
752 | r#" | 769 | r#" |
753 | struct Smol<T>(T); | 770 | struct Smol<T>(T); |
754 | 771 | ||
@@ -831,7 +848,7 @@ fn main() { | |||
831 | #[test] | 848 | #[test] |
832 | fn omitted_parameters_hints_heuristics() { | 849 | fn omitted_parameters_hints_heuristics() { |
833 | check_with_config( | 850 | check_with_config( |
834 | InlayHintsConfig { max_length: Some(8), ..Default::default() }, | 851 | InlayHintsConfig { max_length: Some(8), ..TEST_CONFIG }, |
835 | r#" | 852 | r#" |
836 | fn map(f: i32) {} | 853 | fn map(f: i32) {} |
837 | fn filter(predicate: i32) {} | 854 | fn filter(predicate: i32) {} |
@@ -900,6 +917,9 @@ fn main() { | |||
900 | twiddle(true); | 917 | twiddle(true); |
901 | doo(true); | 918 | doo(true); |
902 | 919 | ||
920 | const TWIDDLE_UPPERCASE: bool = true; | ||
921 | twiddle(TWIDDLE_UPPERCASE); | ||
922 | |||
903 | let mut param_begin: Param = Param {}; | 923 | let mut param_begin: Param = Param {}; |
904 | different_order(¶m_begin); | 924 | different_order(¶m_begin); |
905 | different_order(&mut param_begin); | 925 | different_order(&mut param_begin); |
@@ -924,7 +944,7 @@ fn main() { | |||
924 | #[test] | 944 | #[test] |
925 | fn unit_structs_have_no_type_hints() { | 945 | fn unit_structs_have_no_type_hints() { |
926 | check_with_config( | 946 | check_with_config( |
927 | InlayHintsConfig { max_length: Some(8), ..Default::default() }, | 947 | InlayHintsConfig { max_length: Some(8), ..TEST_CONFIG }, |
928 | r#" | 948 | r#" |
929 | enum Result<T, E> { Ok(T), Err(E) } | 949 | enum Result<T, E> { Ok(T), Err(E) } |
930 | use Result::*; | 950 | use Result::*; |
diff --git a/crates/ide/src/join_lines.rs b/crates/ide/src/join_lines.rs index b5a6f66fd..05380f2a1 100644 --- a/crates/ide/src/join_lines.rs +++ b/crates/ide/src/join_lines.rs | |||
@@ -104,7 +104,7 @@ fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextS | |||
104 | // Special case that turns something like: | 104 | // Special case that turns something like: |
105 | // | 105 | // |
106 | // ``` | 106 | // ``` |
107 | // my_function({<|> | 107 | // my_function({$0 |
108 | // <some-expr> | 108 | // <some-expr> |
109 | // }) | 109 | // }) |
110 | // ``` | 110 | // ``` |
@@ -116,7 +116,7 @@ fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextS | |||
116 | // ditto for | 116 | // ditto for |
117 | // | 117 | // |
118 | // ``` | 118 | // ``` |
119 | // use foo::{<|> | 119 | // use foo::{$0 |
120 | // bar | 120 | // bar |
121 | // }; | 121 | // }; |
122 | // ``` | 122 | // ``` |
@@ -198,8 +198,8 @@ mod tests { | |||
198 | 198 | ||
199 | use super::*; | 199 | use super::*; |
200 | 200 | ||
201 | fn check_join_lines(before: &str, after: &str) { | 201 | fn check_join_lines(ra_fixture_before: &str, ra_fixture_after: &str) { |
202 | let (before_cursor_pos, before) = extract_offset(before); | 202 | let (before_cursor_pos, before) = extract_offset(ra_fixture_before); |
203 | let file = SourceFile::parse(&before).ok().unwrap(); | 203 | let file = SourceFile::parse(&before).ok().unwrap(); |
204 | 204 | ||
205 | let range = TextRange::empty(before_cursor_pos); | 205 | let range = TextRange::empty(before_cursor_pos); |
@@ -214,7 +214,7 @@ mod tests { | |||
214 | .apply_to_offset(before_cursor_pos) | 214 | .apply_to_offset(before_cursor_pos) |
215 | .expect("cursor position is affected by the edit"); | 215 | .expect("cursor position is affected by the edit"); |
216 | let actual = add_cursor(&actual, actual_cursor_pos); | 216 | let actual = add_cursor(&actual, actual_cursor_pos); |
217 | assert_eq_text!(after, &actual); | 217 | assert_eq_text!(ra_fixture_after, &actual); |
218 | } | 218 | } |
219 | 219 | ||
220 | #[test] | 220 | #[test] |
@@ -222,13 +222,13 @@ mod tests { | |||
222 | check_join_lines( | 222 | check_join_lines( |
223 | r" | 223 | r" |
224 | fn foo() { | 224 | fn foo() { |
225 | <|>foo(1, | 225 | $0foo(1, |
226 | ) | 226 | ) |
227 | } | 227 | } |
228 | ", | 228 | ", |
229 | r" | 229 | r" |
230 | fn foo() { | 230 | fn foo() { |
231 | <|>foo(1) | 231 | $0foo(1) |
232 | } | 232 | } |
233 | ", | 233 | ", |
234 | ); | 234 | ); |
@@ -239,14 +239,14 @@ fn foo() { | |||
239 | check_join_lines( | 239 | check_join_lines( |
240 | r" | 240 | r" |
241 | pub fn reparse(&self, edit: &AtomTextEdit) -> File { | 241 | pub fn reparse(&self, edit: &AtomTextEdit) -> File { |
242 | <|>self.incremental_reparse(edit).unwrap_or_else(|| { | 242 | $0self.incremental_reparse(edit).unwrap_or_else(|| { |
243 | self.full_reparse(edit) | 243 | self.full_reparse(edit) |
244 | }) | 244 | }) |
245 | } | 245 | } |
246 | ", | 246 | ", |
247 | r" | 247 | r" |
248 | pub fn reparse(&self, edit: &AtomTextEdit) -> File { | 248 | pub fn reparse(&self, edit: &AtomTextEdit) -> File { |
249 | <|>self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) | 249 | $0self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) |
250 | } | 250 | } |
251 | ", | 251 | ", |
252 | ); | 252 | ); |
@@ -257,13 +257,13 @@ pub fn reparse(&self, edit: &AtomTextEdit) -> File { | |||
257 | check_join_lines( | 257 | check_join_lines( |
258 | r" | 258 | r" |
259 | fn foo() { | 259 | fn foo() { |
260 | foo(<|>{ | 260 | foo($0{ |
261 | 92 | 261 | 92 |
262 | }) | 262 | }) |
263 | }", | 263 | }", |
264 | r" | 264 | r" |
265 | fn foo() { | 265 | fn foo() { |
266 | foo(<|>92) | 266 | foo($092) |
267 | }", | 267 | }", |
268 | ); | 268 | ); |
269 | } | 269 | } |
@@ -274,7 +274,7 @@ fn foo() { | |||
274 | fn foo() { | 274 | fn foo() { |
275 | loop { | 275 | loop { |
276 | match x { | 276 | match x { |
277 | 92 => <|>{ | 277 | 92 => $0{ |
278 | continue; | 278 | continue; |
279 | } | 279 | } |
280 | } | 280 | } |
@@ -285,7 +285,7 @@ fn foo() { | |||
285 | fn foo() { | 285 | fn foo() { |
286 | loop { | 286 | loop { |
287 | match x { | 287 | match x { |
288 | 92 => <|>continue, | 288 | 92 => $0continue, |
289 | } | 289 | } |
290 | } | 290 | } |
291 | } | 291 | } |
@@ -299,7 +299,7 @@ fn foo() { | |||
299 | r" | 299 | r" |
300 | fn foo(e: Result<U, V>) { | 300 | fn foo(e: Result<U, V>) { |
301 | match e { | 301 | match e { |
302 | Ok(u) => <|>{ | 302 | Ok(u) => $0{ |
303 | u.foo() | 303 | u.foo() |
304 | } | 304 | } |
305 | Err(v) => v, | 305 | Err(v) => v, |
@@ -308,7 +308,7 @@ fn foo(e: Result<U, V>) { | |||
308 | r" | 308 | r" |
309 | fn foo(e: Result<U, V>) { | 309 | fn foo(e: Result<U, V>) { |
310 | match e { | 310 | match e { |
311 | Ok(u) => <|>u.foo(), | 311 | Ok(u) => $0u.foo(), |
312 | Err(v) => v, | 312 | Err(v) => v, |
313 | } | 313 | } |
314 | }", | 314 | }", |
@@ -321,7 +321,7 @@ fn foo(e: Result<U, V>) { | |||
321 | r" | 321 | r" |
322 | fn foo() { | 322 | fn foo() { |
323 | match ty { | 323 | match ty { |
324 | <|> Some(ty) => { | 324 | $0 Some(ty) => { |
325 | match ty { | 325 | match ty { |
326 | _ => false, | 326 | _ => false, |
327 | } | 327 | } |
@@ -333,7 +333,7 @@ fn foo() { | |||
333 | r" | 333 | r" |
334 | fn foo() { | 334 | fn foo() { |
335 | match ty { | 335 | match ty { |
336 | <|> Some(ty) => match ty { | 336 | $0 Some(ty) => match ty { |
337 | _ => false, | 337 | _ => false, |
338 | }, | 338 | }, |
339 | _ => true, | 339 | _ => true, |
@@ -350,7 +350,7 @@ fn foo() { | |||
350 | r" | 350 | r" |
351 | fn foo(e: Result<U, V>) { | 351 | fn foo(e: Result<U, V>) { |
352 | match e { | 352 | match e { |
353 | Ok(u) => <|>{ | 353 | Ok(u) => $0{ |
354 | u.foo() | 354 | u.foo() |
355 | }, | 355 | }, |
356 | Err(v) => v, | 356 | Err(v) => v, |
@@ -359,7 +359,7 @@ fn foo(e: Result<U, V>) { | |||
359 | r" | 359 | r" |
360 | fn foo(e: Result<U, V>) { | 360 | fn foo(e: Result<U, V>) { |
361 | match e { | 361 | match e { |
362 | Ok(u) => <|>u.foo(), | 362 | Ok(u) => $0u.foo(), |
363 | Err(v) => v, | 363 | Err(v) => v, |
364 | } | 364 | } |
365 | }", | 365 | }", |
@@ -370,7 +370,7 @@ fn foo(e: Result<U, V>) { | |||
370 | r" | 370 | r" |
371 | fn foo(e: Result<U, V>) { | 371 | fn foo(e: Result<U, V>) { |
372 | match e { | 372 | match e { |
373 | Ok(u) => <|>{ | 373 | Ok(u) => $0{ |
374 | u.foo() | 374 | u.foo() |
375 | } , | 375 | } , |
376 | Err(v) => v, | 376 | Err(v) => v, |
@@ -379,7 +379,7 @@ fn foo(e: Result<U, V>) { | |||
379 | r" | 379 | r" |
380 | fn foo(e: Result<U, V>) { | 380 | fn foo(e: Result<U, V>) { |
381 | match e { | 381 | match e { |
382 | Ok(u) => <|>u.foo() , | 382 | Ok(u) => $0u.foo() , |
383 | Err(v) => v, | 383 | Err(v) => v, |
384 | } | 384 | } |
385 | }", | 385 | }", |
@@ -390,7 +390,7 @@ fn foo(e: Result<U, V>) { | |||
390 | r" | 390 | r" |
391 | fn foo(e: Result<U, V>) { | 391 | fn foo(e: Result<U, V>) { |
392 | match e { | 392 | match e { |
393 | Ok(u) => <|>{ | 393 | Ok(u) => $0{ |
394 | u.foo() | 394 | u.foo() |
395 | } | 395 | } |
396 | , | 396 | , |
@@ -400,7 +400,7 @@ fn foo(e: Result<U, V>) { | |||
400 | r" | 400 | r" |
401 | fn foo(e: Result<U, V>) { | 401 | fn foo(e: Result<U, V>) { |
402 | match e { | 402 | match e { |
403 | Ok(u) => <|>u.foo() | 403 | Ok(u) => $0u.foo() |
404 | , | 404 | , |
405 | Err(v) => v, | 405 | Err(v) => v, |
406 | } | 406 | } |
@@ -414,13 +414,13 @@ fn foo(e: Result<U, V>) { | |||
414 | check_join_lines( | 414 | check_join_lines( |
415 | r" | 415 | r" |
416 | fn foo() { | 416 | fn foo() { |
417 | let x = (<|>{ | 417 | let x = ($0{ |
418 | 4 | 418 | 4 |
419 | },); | 419 | },); |
420 | }", | 420 | }", |
421 | r" | 421 | r" |
422 | fn foo() { | 422 | fn foo() { |
423 | let x = (<|>4,); | 423 | let x = ($04,); |
424 | }", | 424 | }", |
425 | ); | 425 | ); |
426 | 426 | ||
@@ -428,13 +428,13 @@ fn foo() { | |||
428 | check_join_lines( | 428 | check_join_lines( |
429 | r" | 429 | r" |
430 | fn foo() { | 430 | fn foo() { |
431 | let x = (<|>{ | 431 | let x = ($0{ |
432 | 4 | 432 | 4 |
433 | } ,); | 433 | } ,); |
434 | }", | 434 | }", |
435 | r" | 435 | r" |
436 | fn foo() { | 436 | fn foo() { |
437 | let x = (<|>4 ,); | 437 | let x = ($04 ,); |
438 | }", | 438 | }", |
439 | ); | 439 | ); |
440 | 440 | ||
@@ -442,14 +442,14 @@ fn foo() { | |||
442 | check_join_lines( | 442 | check_join_lines( |
443 | r" | 443 | r" |
444 | fn foo() { | 444 | fn foo() { |
445 | let x = (<|>{ | 445 | let x = ($0{ |
446 | 4 | 446 | 4 |
447 | } | 447 | } |
448 | ,); | 448 | ,); |
449 | }", | 449 | }", |
450 | r" | 450 | r" |
451 | fn foo() { | 451 | fn foo() { |
452 | let x = (<|>4 | 452 | let x = ($04 |
453 | ,); | 453 | ,); |
454 | }", | 454 | }", |
455 | ); | 455 | ); |
@@ -460,11 +460,11 @@ fn foo() { | |||
460 | // No space after the '{' | 460 | // No space after the '{' |
461 | check_join_lines( | 461 | check_join_lines( |
462 | r" | 462 | r" |
463 | <|>use syntax::{ | 463 | $0use syntax::{ |
464 | TextSize, TextRange, | 464 | TextSize, TextRange, |
465 | };", | 465 | };", |
466 | r" | 466 | r" |
467 | <|>use syntax::{TextSize, TextRange, | 467 | $0use syntax::{TextSize, TextRange, |
468 | };", | 468 | };", |
469 | ); | 469 | ); |
470 | } | 470 | } |
@@ -475,11 +475,11 @@ fn foo() { | |||
475 | check_join_lines( | 475 | check_join_lines( |
476 | r" | 476 | r" |
477 | use syntax::{ | 477 | use syntax::{ |
478 | <|> TextSize, TextRange | 478 | $0 TextSize, TextRange |
479 | };", | 479 | };", |
480 | r" | 480 | r" |
481 | use syntax::{ | 481 | use syntax::{ |
482 | <|> TextSize, TextRange};", | 482 | $0 TextSize, TextRange};", |
483 | ); | 483 | ); |
484 | } | 484 | } |
485 | 485 | ||
@@ -489,11 +489,11 @@ use syntax::{ | |||
489 | check_join_lines( | 489 | check_join_lines( |
490 | r" | 490 | r" |
491 | use syntax::{ | 491 | use syntax::{ |
492 | <|> TextSize, TextRange, | 492 | $0 TextSize, TextRange, |
493 | };", | 493 | };", |
494 | r" | 494 | r" |
495 | use syntax::{ | 495 | use syntax::{ |
496 | <|> TextSize, TextRange};", | 496 | $0 TextSize, TextRange};", |
497 | ); | 497 | ); |
498 | } | 498 | } |
499 | 499 | ||
@@ -502,14 +502,14 @@ use syntax::{ | |||
502 | check_join_lines( | 502 | check_join_lines( |
503 | r" | 503 | r" |
504 | use syntax::{ | 504 | use syntax::{ |
505 | algo::<|>{ | 505 | algo::$0{ |
506 | find_token_at_offset, | 506 | find_token_at_offset, |
507 | }, | 507 | }, |
508 | ast, | 508 | ast, |
509 | };", | 509 | };", |
510 | r" | 510 | r" |
511 | use syntax::{ | 511 | use syntax::{ |
512 | algo::<|>find_token_at_offset, | 512 | algo::$0find_token_at_offset, |
513 | ast, | 513 | ast, |
514 | };", | 514 | };", |
515 | ); | 515 | ); |
@@ -520,13 +520,13 @@ use syntax::{ | |||
520 | check_join_lines( | 520 | check_join_lines( |
521 | r" | 521 | r" |
522 | fn foo() { | 522 | fn foo() { |
523 | // Hello<|> | 523 | // Hello$0 |
524 | // world! | 524 | // world! |
525 | } | 525 | } |
526 | ", | 526 | ", |
527 | r" | 527 | r" |
528 | fn foo() { | 528 | fn foo() { |
529 | // Hello<|> world! | 529 | // Hello$0 world! |
530 | } | 530 | } |
531 | ", | 531 | ", |
532 | ); | 532 | ); |
@@ -537,13 +537,13 @@ fn foo() { | |||
537 | check_join_lines( | 537 | check_join_lines( |
538 | r" | 538 | r" |
539 | fn foo() { | 539 | fn foo() { |
540 | /// Hello<|> | 540 | /// Hello$0 |
541 | /// world! | 541 | /// world! |
542 | } | 542 | } |
543 | ", | 543 | ", |
544 | r" | 544 | r" |
545 | fn foo() { | 545 | fn foo() { |
546 | /// Hello<|> world! | 546 | /// Hello$0 world! |
547 | } | 547 | } |
548 | ", | 548 | ", |
549 | ); | 549 | ); |
@@ -554,13 +554,13 @@ fn foo() { | |||
554 | check_join_lines( | 554 | check_join_lines( |
555 | r" | 555 | r" |
556 | fn foo() { | 556 | fn foo() { |
557 | //! Hello<|> | 557 | //! Hello$0 |
558 | //! world! | 558 | //! world! |
559 | } | 559 | } |
560 | ", | 560 | ", |
561 | r" | 561 | r" |
562 | fn foo() { | 562 | fn foo() { |
563 | //! Hello<|> world! | 563 | //! Hello$0 world! |
564 | } | 564 | } |
565 | ", | 565 | ", |
566 | ); | 566 | ); |
@@ -571,13 +571,13 @@ fn foo() { | |||
571 | check_join_lines( | 571 | check_join_lines( |
572 | r" | 572 | r" |
573 | fn foo() { | 573 | fn foo() { |
574 | // Hello<|> | 574 | // Hello$0 |
575 | /* world! */ | 575 | /* world! */ |
576 | } | 576 | } |
577 | ", | 577 | ", |
578 | r" | 578 | r" |
579 | fn foo() { | 579 | fn foo() { |
580 | // Hello<|> world! */ | 580 | // Hello$0 world! */ |
581 | } | 581 | } |
582 | ", | 582 | ", |
583 | ); | 583 | ); |
@@ -588,7 +588,7 @@ fn foo() { | |||
588 | check_join_lines( | 588 | check_join_lines( |
589 | r" | 589 | r" |
590 | fn foo() { | 590 | fn foo() { |
591 | // The<|> | 591 | // The$0 |
592 | /* quick | 592 | /* quick |
593 | brown | 593 | brown |
594 | fox! */ | 594 | fox! */ |
@@ -596,7 +596,7 @@ fn foo() { | |||
596 | ", | 596 | ", |
597 | r" | 597 | r" |
598 | fn foo() { | 598 | fn foo() { |
599 | // The<|> quick | 599 | // The$0 quick |
600 | brown | 600 | brown |
601 | fox! */ | 601 | fox! */ |
602 | } | 602 | } |
@@ -604,8 +604,8 @@ fn foo() { | |||
604 | ); | 604 | ); |
605 | } | 605 | } |
606 | 606 | ||
607 | fn check_join_lines_sel(before: &str, after: &str) { | 607 | fn check_join_lines_sel(ra_fixture_before: &str, ra_fixture_after: &str) { |
608 | let (sel, before) = extract_range(before); | 608 | let (sel, before) = extract_range(ra_fixture_before); |
609 | let parse = SourceFile::parse(&before); | 609 | let parse = SourceFile::parse(&before); |
610 | let result = join_lines(&parse.tree(), sel); | 610 | let result = join_lines(&parse.tree(), sel); |
611 | let actual = { | 611 | let actual = { |
@@ -613,7 +613,7 @@ fn foo() { | |||
613 | result.apply(&mut actual); | 613 | result.apply(&mut actual); |
614 | actual | 614 | actual |
615 | }; | 615 | }; |
616 | assert_eq_text!(after, &actual); | 616 | assert_eq_text!(ra_fixture_after, &actual); |
617 | } | 617 | } |
618 | 618 | ||
619 | #[test] | 619 | #[test] |
@@ -621,10 +621,10 @@ fn foo() { | |||
621 | check_join_lines_sel( | 621 | check_join_lines_sel( |
622 | r" | 622 | r" |
623 | fn foo() { | 623 | fn foo() { |
624 | <|>foo(1, | 624 | $0foo(1, |
625 | 2, | 625 | 2, |
626 | 3, | 626 | 3, |
627 | <|>) | 627 | $0) |
628 | } | 628 | } |
629 | ", | 629 | ", |
630 | r" | 630 | r" |
@@ -639,9 +639,9 @@ fn foo() { | |||
639 | fn test_join_lines_selection_struct() { | 639 | fn test_join_lines_selection_struct() { |
640 | check_join_lines_sel( | 640 | check_join_lines_sel( |
641 | r" | 641 | r" |
642 | struct Foo <|>{ | 642 | struct Foo $0{ |
643 | f: u32, | 643 | f: u32, |
644 | }<|> | 644 | }$0 |
645 | ", | 645 | ", |
646 | r" | 646 | r" |
647 | struct Foo { f: u32 } | 647 | struct Foo { f: u32 } |
@@ -654,9 +654,9 @@ struct Foo { f: u32 } | |||
654 | check_join_lines_sel( | 654 | check_join_lines_sel( |
655 | r" | 655 | r" |
656 | fn foo() { | 656 | fn foo() { |
657 | join(<|>type_params.type_params() | 657 | join($0type_params.type_params() |
658 | .filter_map(|it| it.name()) | 658 | .filter_map(|it| it.name()) |
659 | .map(|it| it.text())<|>) | 659 | .map(|it| it.text())$0) |
660 | }", | 660 | }", |
661 | r" | 661 | r" |
662 | fn foo() { | 662 | fn foo() { |
@@ -671,9 +671,9 @@ fn foo() { | |||
671 | r" | 671 | r" |
672 | pub fn handle_find_matching_brace() { | 672 | pub fn handle_find_matching_brace() { |
673 | params.offsets | 673 | params.offsets |
674 | .map(|offset| <|>{ | 674 | .map(|offset| $0{ |
675 | world.analysis().matching_brace(&file, offset).unwrap_or(offset) | 675 | world.analysis().matching_brace(&file, offset).unwrap_or(offset) |
676 | }<|>) | 676 | }$0) |
677 | .collect(); | 677 | .collect(); |
678 | }", | 678 | }", |
679 | r" | 679 | r" |
@@ -691,7 +691,7 @@ pub fn handle_find_matching_brace() { | |||
691 | r" | 691 | r" |
692 | fn main() { | 692 | fn main() { |
693 | let _ = { | 693 | let _ = { |
694 | // <|>foo | 694 | // $0foo |
695 | // bar | 695 | // bar |
696 | 92 | 696 | 92 |
697 | }; | 697 | }; |
@@ -700,7 +700,7 @@ fn main() { | |||
700 | r" | 700 | r" |
701 | fn main() { | 701 | fn main() { |
702 | let _ = { | 702 | let _ = { |
703 | // <|>foo bar | 703 | // $0foo bar |
704 | 92 | 704 | 92 |
705 | }; | 705 | }; |
706 | } | 706 | } |
@@ -712,12 +712,12 @@ fn main() { | |||
712 | fn join_lines_mandatory_blocks_block() { | 712 | fn join_lines_mandatory_blocks_block() { |
713 | check_join_lines( | 713 | check_join_lines( |
714 | r" | 714 | r" |
715 | <|>fn foo() { | 715 | $0fn foo() { |
716 | 92 | 716 | 92 |
717 | } | 717 | } |
718 | ", | 718 | ", |
719 | r" | 719 | r" |
720 | <|>fn foo() { 92 | 720 | $0fn foo() { 92 |
721 | } | 721 | } |
722 | ", | 722 | ", |
723 | ); | 723 | ); |
@@ -725,14 +725,14 @@ fn main() { | |||
725 | check_join_lines( | 725 | check_join_lines( |
726 | r" | 726 | r" |
727 | fn foo() { | 727 | fn foo() { |
728 | <|>if true { | 728 | $0if true { |
729 | 92 | 729 | 92 |
730 | } | 730 | } |
731 | } | 731 | } |
732 | ", | 732 | ", |
733 | r" | 733 | r" |
734 | fn foo() { | 734 | fn foo() { |
735 | <|>if true { 92 | 735 | $0if true { 92 |
736 | } | 736 | } |
737 | } | 737 | } |
738 | ", | 738 | ", |
@@ -741,14 +741,14 @@ fn foo() { | |||
741 | check_join_lines( | 741 | check_join_lines( |
742 | r" | 742 | r" |
743 | fn foo() { | 743 | fn foo() { |
744 | <|>loop { | 744 | $0loop { |
745 | 92 | 745 | 92 |
746 | } | 746 | } |
747 | } | 747 | } |
748 | ", | 748 | ", |
749 | r" | 749 | r" |
750 | fn foo() { | 750 | fn foo() { |
751 | <|>loop { 92 | 751 | $0loop { 92 |
752 | } | 752 | } |
753 | } | 753 | } |
754 | ", | 754 | ", |
@@ -757,14 +757,14 @@ fn foo() { | |||
757 | check_join_lines( | 757 | check_join_lines( |
758 | r" | 758 | r" |
759 | fn foo() { | 759 | fn foo() { |
760 | <|>unsafe { | 760 | $0unsafe { |
761 | 92 | 761 | 92 |
762 | } | 762 | } |
763 | } | 763 | } |
764 | ", | 764 | ", |
765 | r" | 765 | r" |
766 | fn foo() { | 766 | fn foo() { |
767 | <|>unsafe { 92 | 767 | $0unsafe { 92 |
768 | } | 768 | } |
769 | } | 769 | } |
770 | ", | 770 | ", |
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index a450794f3..1e03832ec 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs | |||
@@ -76,14 +76,14 @@ pub use crate::{ | |||
76 | references::{rename::RenameError, Declaration, ReferenceSearchResult}, | 76 | references::{rename::RenameError, Declaration, ReferenceSearchResult}, |
77 | runnables::{Runnable, RunnableKind, TestId}, | 77 | runnables::{Runnable, RunnableKind, TestId}, |
78 | syntax_highlighting::{ | 78 | syntax_highlighting::{ |
79 | tags::{Highlight, HighlightModifier, HighlightModifiers, HighlightTag}, | 79 | tags::{Highlight, HlMod, HlMods, HlPunct, HlTag}, |
80 | HighlightedRange, | 80 | HlRange, |
81 | }, | 81 | }, |
82 | }; | 82 | }; |
83 | pub use assists::{Assist, AssistConfig, AssistId, AssistKind}; | 83 | pub use assists::{Assist, AssistConfig, AssistId, AssistKind, InsertUseConfig}; |
84 | pub use completion::{ | 84 | pub use completion::{ |
85 | CompletionConfig, CompletionItem, CompletionItemKind, CompletionResolveCapability, | 85 | CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, ImportEdit, |
86 | CompletionScore, ImportEdit, InsertTextFormat, | 86 | InsertTextFormat, |
87 | }; | 87 | }; |
88 | pub use hir::{Documentation, Semantics}; | 88 | pub use hir::{Documentation, Semantics}; |
89 | pub use ide_db::base_db::{ | 89 | pub use ide_db::base_db::{ |
@@ -92,7 +92,7 @@ pub use ide_db::base_db::{ | |||
92 | }; | 92 | }; |
93 | pub use ide_db::{ | 93 | pub use ide_db::{ |
94 | call_info::CallInfo, | 94 | call_info::CallInfo, |
95 | search::{Reference, ReferenceAccess, ReferenceKind}, | 95 | search::{FileReference, ReferenceAccess, ReferenceKind}, |
96 | }; | 96 | }; |
97 | pub use ide_db::{ | 97 | pub use ide_db::{ |
98 | label::Label, | 98 | label::Label, |
@@ -449,12 +449,12 @@ impl Analysis { | |||
449 | } | 449 | } |
450 | 450 | ||
451 | /// Computes syntax highlighting for the given file | 451 | /// Computes syntax highlighting for the given file |
452 | pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> { | 452 | pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HlRange>> { |
453 | self.with_db(|db| syntax_highlighting::highlight(db, file_id, None, false)) | 453 | self.with_db(|db| syntax_highlighting::highlight(db, file_id, None, false)) |
454 | } | 454 | } |
455 | 455 | ||
456 | /// Computes syntax highlighting for the given file range. | 456 | /// Computes syntax highlighting for the given file range. |
457 | pub fn highlight_range(&self, frange: FileRange) -> Cancelable<Vec<HighlightedRange>> { | 457 | pub fn highlight_range(&self, frange: FileRange) -> Cancelable<Vec<HlRange>> { |
458 | self.with_db(|db| { | 458 | self.with_db(|db| { |
459 | syntax_highlighting::highlight(db, frange.file_id, Some(frange.range), false) | 459 | syntax_highlighting::highlight(db, frange.file_id, Some(frange.range), false) |
460 | }) | 460 | }) |
diff --git a/crates/ide/src/matching_brace.rs b/crates/ide/src/matching_brace.rs index d70248afe..1bfa1439d 100644 --- a/crates/ide/src/matching_brace.rs +++ b/crates/ide/src/matching_brace.rs | |||
@@ -58,15 +58,15 @@ mod tests { | |||
58 | assert_eq_text!(after, &actual); | 58 | assert_eq_text!(after, &actual); |
59 | } | 59 | } |
60 | 60 | ||
61 | do_check("struct Foo { a: i32, }<|>", "struct Foo <|>{ a: i32, }"); | 61 | do_check("struct Foo { a: i32, }$0", "struct Foo $0{ a: i32, }"); |
62 | do_check("fn main() { |x: i32|<|> x * 2;}", "fn main() { <|>|x: i32| x * 2;}"); | 62 | do_check("fn main() { |x: i32|$0 x * 2;}", "fn main() { $0|x: i32| x * 2;}"); |
63 | do_check("fn main() { <|>|x: i32| x * 2;}", "fn main() { |x: i32<|>| x * 2;}"); | 63 | do_check("fn main() { $0|x: i32| x * 2;}", "fn main() { |x: i32$0| x * 2;}"); |
64 | 64 | ||
65 | { | 65 | { |
66 | mark::check!(pipes_not_braces); | 66 | mark::check!(pipes_not_braces); |
67 | do_check( | 67 | do_check( |
68 | "fn main() { match 92 { 1 | 2 |<|> 3 => 92 } }", | 68 | "fn main() { match 92 { 1 | 2 |$0 3 => 92 } }", |
69 | "fn main() { match 92 { 1 | 2 |<|> 3 => 92 } }", | 69 | "fn main() { match 92 { 1 | 2 |$0 3 => 92 } }", |
70 | ); | 70 | ); |
71 | } | 71 | } |
72 | } | 72 | } |
diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs index be344a09b..d343638fb 100644 --- a/crates/ide/src/parent_module.rs +++ b/crates/ide/src/parent_module.rs | |||
@@ -74,7 +74,7 @@ mod tests { | |||
74 | //- /lib.rs | 74 | //- /lib.rs |
75 | mod foo; | 75 | mod foo; |
76 | //- /foo.rs | 76 | //- /foo.rs |
77 | <|>// empty | 77 | $0// empty |
78 | ", | 78 | ", |
79 | ); | 79 | ); |
80 | let nav = analysis.parent_module(pos).unwrap().pop().unwrap(); | 80 | let nav = analysis.parent_module(pos).unwrap().pop().unwrap(); |
@@ -90,7 +90,7 @@ mod tests { | |||
90 | mod foo; | 90 | mod foo; |
91 | 91 | ||
92 | //- /foo.rs | 92 | //- /foo.rs |
93 | mod <|>bar; | 93 | mod $0bar; |
94 | 94 | ||
95 | //- /foo/bar.rs | 95 | //- /foo/bar.rs |
96 | // empty | 96 | // empty |
@@ -107,7 +107,7 @@ mod tests { | |||
107 | //- /lib.rs | 107 | //- /lib.rs |
108 | mod foo { | 108 | mod foo { |
109 | mod bar { | 109 | mod bar { |
110 | mod baz { <|> } | 110 | mod baz { $0 } |
111 | } | 111 | } |
112 | } | 112 | } |
113 | ", | 113 | ", |
@@ -123,7 +123,7 @@ mod tests { | |||
123 | //- /main.rs | 123 | //- /main.rs |
124 | mod foo; | 124 | mod foo; |
125 | //- /foo.rs | 125 | //- /foo.rs |
126 | <|> | 126 | $0 |
127 | "#, | 127 | "#, |
128 | ); | 128 | ); |
129 | assert_eq!(analysis.crate_for(file_id).unwrap().len(), 1); | 129 | assert_eq!(analysis.crate_for(file_id).unwrap().len(), 1); |
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index fa58fc319..7d4757e02 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | //! or `ast::NameRef`. If it's a `ast::NameRef`, at the classification step we | 3 | //! or `ast::NameRef`. If it's a `ast::NameRef`, at the classification step we |
4 | //! try to resolve the direct tree parent of this element, otherwise we | 4 | //! try to resolve the direct tree parent of this element, otherwise we |
5 | //! already have a definition and just need to get its HIR together with | 5 | //! already have a definition and just need to get its HIR together with |
6 | //! some information that is needed for futher steps of searching. | 6 | //! some information that is needed for further steps of searching. |
7 | //! After that, we collect files that might contain references and look | 7 | //! After that, we collect files that might contain references and look |
8 | //! for text occurrences of the identifier. If there's an `ast::NameRef` | 8 | //! for text occurrences of the identifier. If there's an `ast::NameRef` |
9 | //! at the index that the match starts at and its tree parent is | 9 | //! at the index that the match starts at and its tree parent is |
@@ -13,15 +13,15 @@ pub(crate) mod rename; | |||
13 | 13 | ||
14 | use hir::Semantics; | 14 | use hir::Semantics; |
15 | use ide_db::{ | 15 | use ide_db::{ |
16 | base_db::FileId, | ||
16 | defs::{Definition, NameClass, NameRefClass}, | 17 | defs::{Definition, NameClass, NameRefClass}, |
17 | search::Reference, | 18 | search::{FileReference, ReferenceAccess, ReferenceKind, SearchScope, UsageSearchResult}, |
18 | search::{ReferenceAccess, ReferenceKind, SearchScope}, | ||
19 | RootDatabase, | 19 | RootDatabase, |
20 | }; | 20 | }; |
21 | use syntax::{ | 21 | use syntax::{ |
22 | algo::find_node_at_offset, | 22 | algo::find_node_at_offset, |
23 | ast::{self, NameOwner}, | 23 | ast::{self, NameOwner}, |
24 | match_ast, AstNode, SyntaxKind, SyntaxNode, TextRange, TokenAtOffset, | 24 | match_ast, AstNode, SyntaxNode, TextRange, TokenAtOffset, T, |
25 | }; | 25 | }; |
26 | 26 | ||
27 | use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo, SymbolKind}; | 27 | use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo, SymbolKind}; |
@@ -29,7 +29,7 @@ use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeI | |||
29 | #[derive(Debug, Clone)] | 29 | #[derive(Debug, Clone)] |
30 | pub struct ReferenceSearchResult { | 30 | pub struct ReferenceSearchResult { |
31 | declaration: Declaration, | 31 | declaration: Declaration, |
32 | references: Vec<Reference>, | 32 | references: UsageSearchResult, |
33 | } | 33 | } |
34 | 34 | ||
35 | #[derive(Debug, Clone)] | 35 | #[derive(Debug, Clone)] |
@@ -48,10 +48,21 @@ impl ReferenceSearchResult { | |||
48 | &self.declaration.nav | 48 | &self.declaration.nav |
49 | } | 49 | } |
50 | 50 | ||
51 | pub fn references(&self) -> &[Reference] { | 51 | pub fn references(&self) -> &UsageSearchResult { |
52 | &self.references | 52 | &self.references |
53 | } | 53 | } |
54 | 54 | ||
55 | pub fn references_with_declaration(mut self) -> UsageSearchResult { | ||
56 | let decl_ref = FileReference { | ||
57 | range: self.declaration.nav.focus_or_full_range(), | ||
58 | kind: self.declaration.kind, | ||
59 | access: self.declaration.access, | ||
60 | }; | ||
61 | let file_id = self.declaration.nav.file_id; | ||
62 | self.references.references.entry(file_id).or_default().push(decl_ref); | ||
63 | self.references | ||
64 | } | ||
65 | |||
55 | /// Total number of references | 66 | /// Total number of references |
56 | /// At least 1 since all valid references should | 67 | /// At least 1 since all valid references should |
57 | /// Have a declaration | 68 | /// Have a declaration |
@@ -63,21 +74,11 @@ impl ReferenceSearchResult { | |||
63 | // allow turning ReferenceSearchResult into an iterator | 74 | // allow turning ReferenceSearchResult into an iterator |
64 | // over References | 75 | // over References |
65 | impl IntoIterator for ReferenceSearchResult { | 76 | impl IntoIterator for ReferenceSearchResult { |
66 | type Item = Reference; | 77 | type Item = (FileId, Vec<FileReference>); |
67 | type IntoIter = std::vec::IntoIter<Reference>; | 78 | type IntoIter = std::collections::hash_map::IntoIter<FileId, Vec<FileReference>>; |
68 | 79 | ||
69 | fn into_iter(mut self) -> Self::IntoIter { | 80 | fn into_iter(self) -> Self::IntoIter { |
70 | let mut v = Vec::with_capacity(self.len()); | 81 | self.references_with_declaration().into_iter() |
71 | v.push(Reference { | ||
72 | file_range: FileRange { | ||
73 | file_id: self.declaration.nav.file_id, | ||
74 | range: self.declaration.nav.focus_or_full_range(), | ||
75 | }, | ||
76 | kind: self.declaration.kind, | ||
77 | access: self.declaration.access, | ||
78 | }); | ||
79 | v.append(&mut self.references); | ||
80 | v.into_iter() | ||
81 | } | 82 | } |
82 | } | 83 | } |
83 | 84 | ||
@@ -109,13 +110,12 @@ pub(crate) fn find_all_refs( | |||
109 | 110 | ||
110 | let RangeInfo { range, info: def } = find_name(&sema, &syntax, position, opt_name)?; | 111 | let RangeInfo { range, info: def } = find_name(&sema, &syntax, position, opt_name)?; |
111 | 112 | ||
112 | let references = def | 113 | let mut usages = def.usages(sema).set_scope(search_scope).all(); |
113 | .usages(sema) | 114 | usages |
114 | .set_scope(search_scope) | 115 | .references |
115 | .all() | 116 | .values_mut() |
116 | .into_iter() | 117 | .for_each(|it| it.retain(|r| search_kind == ReferenceKind::Other || search_kind == r.kind)); |
117 | .filter(|r| search_kind == ReferenceKind::Other || search_kind == r.kind) | 118 | usages.references.retain(|_, it| !it.is_empty()); |
118 | .collect(); | ||
119 | 119 | ||
120 | let nav = def.try_to_nav(sema.db)?; | 120 | let nav = def.try_to_nav(sema.db)?; |
121 | let decl_range = nav.focus_or_full_range(); | 121 | let decl_range = nav.focus_or_full_range(); |
@@ -130,13 +130,16 @@ pub(crate) fn find_all_refs( | |||
130 | kind = ReferenceKind::FieldShorthandForLocal; | 130 | kind = ReferenceKind::FieldShorthandForLocal; |
131 | } | 131 | } |
132 | } | 132 | } |
133 | } else if matches!(def, Definition::LifetimeParam(_) | Definition::Label(_)) { | 133 | } else if matches!( |
134 | def, | ||
135 | Definition::GenericParam(hir::GenericParam::LifetimeParam(_)) | Definition::Label(_) | ||
136 | ) { | ||
134 | kind = ReferenceKind::Lifetime; | 137 | kind = ReferenceKind::Lifetime; |
135 | }; | 138 | }; |
136 | 139 | ||
137 | let declaration = Declaration { nav, kind, access: decl_access(&def, &syntax, decl_range) }; | 140 | let declaration = Declaration { nav, kind, access: decl_access(&def, &syntax, decl_range) }; |
138 | 141 | ||
139 | Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references })) | 142 | Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references: usages })) |
140 | } | 143 | } |
141 | 144 | ||
142 | fn find_name( | 145 | fn find_name( |
@@ -200,7 +203,7 @@ fn get_struct_def_name_for_struct_literal_search( | |||
200 | position: FilePosition, | 203 | position: FilePosition, |
201 | ) -> Option<ast::Name> { | 204 | ) -> Option<ast::Name> { |
202 | if let TokenAtOffset::Between(ref left, ref right) = syntax.token_at_offset(position.offset) { | 205 | if let TokenAtOffset::Between(ref left, ref right) = syntax.token_at_offset(position.offset) { |
203 | if right.kind() != SyntaxKind::L_CURLY && right.kind() != SyntaxKind::L_PAREN { | 206 | if right.kind() != T!['{'] && right.kind() != T!['('] { |
204 | return None; | 207 | return None; |
205 | } | 208 | } |
206 | if let Some(name) = | 209 | if let Some(name) = |
@@ -227,7 +230,7 @@ fn get_enum_def_name_for_struct_literal_search( | |||
227 | position: FilePosition, | 230 | position: FilePosition, |
228 | ) -> Option<ast::Name> { | 231 | ) -> Option<ast::Name> { |
229 | if let TokenAtOffset::Between(ref left, ref right) = syntax.token_at_offset(position.offset) { | 232 | if let TokenAtOffset::Between(ref left, ref right) = syntax.token_at_offset(position.offset) { |
230 | if right.kind() != SyntaxKind::L_CURLY && right.kind() != SyntaxKind::L_PAREN { | 233 | if right.kind() != T!['{'] && right.kind() != T!['('] { |
231 | return None; | 234 | return None; |
232 | } | 235 | } |
233 | if let Some(name) = | 236 | if let Some(name) = |
@@ -252,8 +255,8 @@ fn try_find_self_references( | |||
252 | syntax: &SyntaxNode, | 255 | syntax: &SyntaxNode, |
253 | position: FilePosition, | 256 | position: FilePosition, |
254 | ) -> Option<RangeInfo<ReferenceSearchResult>> { | 257 | ) -> Option<RangeInfo<ReferenceSearchResult>> { |
255 | let self_token = | 258 | let FilePosition { file_id, offset } = position; |
256 | syntax.token_at_offset(position.offset).find(|t| t.kind() == SyntaxKind::SELF_KW)?; | 259 | let self_token = syntax.token_at_offset(offset).find(|t| t.kind() == T![self])?; |
257 | let parent = self_token.parent(); | 260 | let parent = self_token.parent(); |
258 | match_ast! { | 261 | match_ast! { |
259 | match parent { | 262 | match parent { |
@@ -274,7 +277,7 @@ fn try_find_self_references( | |||
274 | 277 | ||
275 | let declaration = Declaration { | 278 | let declaration = Declaration { |
276 | nav: NavigationTarget { | 279 | nav: NavigationTarget { |
277 | file_id: position.file_id, | 280 | file_id, |
278 | full_range: self_param.syntax().text_range(), | 281 | full_range: self_param.syntax().text_range(), |
279 | focus_range: Some(param_self_token.text_range()), | 282 | focus_range: Some(param_self_token.text_range()), |
280 | name: param_self_token.text().clone(), | 283 | name: param_self_token.text().clone(), |
@@ -290,7 +293,7 @@ fn try_find_self_references( | |||
290 | ReferenceAccess::Read | 293 | ReferenceAccess::Read |
291 | }), | 294 | }), |
292 | }; | 295 | }; |
293 | let references = function | 296 | let refs = function |
294 | .body() | 297 | .body() |
295 | .map(|body| { | 298 | .map(|body| { |
296 | body.syntax() | 299 | body.syntax() |
@@ -304,14 +307,16 @@ fn try_find_self_references( | |||
304 | None | 307 | None |
305 | } | 308 | } |
306 | }) | 309 | }) |
307 | .map(|token| Reference { | 310 | .map(|token| FileReference { |
308 | file_range: FileRange { file_id: position.file_id, range: token.text_range() }, | 311 | range: token.text_range(), |
309 | kind: ReferenceKind::SelfKw, | 312 | kind: ReferenceKind::SelfKw, |
310 | access: declaration.access, // FIXME: properly check access kind here instead of copying it from the declaration | 313 | access: declaration.access, // FIXME: properly check access kind here instead of copying it from the declaration |
311 | }) | 314 | }) |
312 | .collect() | 315 | .collect() |
313 | }) | 316 | }) |
314 | .unwrap_or_default(); | 317 | .unwrap_or_default(); |
318 | let mut references = UsageSearchResult::default(); | ||
319 | references.references.insert(file_id, refs); | ||
315 | 320 | ||
316 | Some(RangeInfo::new( | 321 | Some(RangeInfo::new( |
317 | param_self_token.text_range(), | 322 | param_self_token.text_range(), |
@@ -331,7 +336,7 @@ mod tests { | |||
331 | fn test_struct_literal_after_space() { | 336 | fn test_struct_literal_after_space() { |
332 | check( | 337 | check( |
333 | r#" | 338 | r#" |
334 | struct Foo <|>{ | 339 | struct Foo $0{ |
335 | a: i32, | 340 | a: i32, |
336 | } | 341 | } |
337 | impl Foo { | 342 | impl Foo { |
@@ -354,7 +359,7 @@ fn main() { | |||
354 | fn test_struct_literal_before_space() { | 359 | fn test_struct_literal_before_space() { |
355 | check( | 360 | check( |
356 | r#" | 361 | r#" |
357 | struct Foo<|> {} | 362 | struct Foo$0 {} |
358 | fn main() { | 363 | fn main() { |
359 | let f: Foo; | 364 | let f: Foo; |
360 | f = Foo {}; | 365 | f = Foo {}; |
@@ -373,7 +378,7 @@ struct Foo<|> {} | |||
373 | fn test_struct_literal_with_generic_type() { | 378 | fn test_struct_literal_with_generic_type() { |
374 | check( | 379 | check( |
375 | r#" | 380 | r#" |
376 | struct Foo<T> <|>{} | 381 | struct Foo<T> $0{} |
377 | fn main() { | 382 | fn main() { |
378 | let f: Foo::<i32>; | 383 | let f: Foo::<i32>; |
379 | f = Foo {}; | 384 | f = Foo {}; |
@@ -391,7 +396,7 @@ struct Foo<T> <|>{} | |||
391 | fn test_struct_literal_for_tuple() { | 396 | fn test_struct_literal_for_tuple() { |
392 | check( | 397 | check( |
393 | r#" | 398 | r#" |
394 | struct Foo<|>(i32); | 399 | struct Foo$0(i32); |
395 | 400 | ||
396 | fn main() { | 401 | fn main() { |
397 | let f: Foo; | 402 | let f: Foo; |
@@ -410,7 +415,7 @@ fn main() { | |||
410 | fn test_enum_after_space() { | 415 | fn test_enum_after_space() { |
411 | check( | 416 | check( |
412 | r#" | 417 | r#" |
413 | enum Foo <|>{ | 418 | enum Foo $0{ |
414 | A, | 419 | A, |
415 | B, | 420 | B, |
416 | } | 421 | } |
@@ -431,7 +436,7 @@ fn main() { | |||
431 | fn test_enum_before_space() { | 436 | fn test_enum_before_space() { |
432 | check( | 437 | check( |
433 | r#" | 438 | r#" |
434 | enum Foo<|> { | 439 | enum Foo$0 { |
435 | A, | 440 | A, |
436 | B, | 441 | B, |
437 | } | 442 | } |
@@ -453,7 +458,7 @@ fn main() { | |||
453 | fn test_enum_with_generic_type() { | 458 | fn test_enum_with_generic_type() { |
454 | check( | 459 | check( |
455 | r#" | 460 | r#" |
456 | enum Foo<T> <|>{ | 461 | enum Foo<T> $0{ |
457 | A(T), | 462 | A(T), |
458 | B, | 463 | B, |
459 | } | 464 | } |
@@ -474,7 +479,7 @@ fn main() { | |||
474 | fn test_enum_for_tuple() { | 479 | fn test_enum_for_tuple() { |
475 | check( | 480 | check( |
476 | r#" | 481 | r#" |
477 | enum Foo<|>{ | 482 | enum Foo$0{ |
478 | A(i8), | 483 | A(i8), |
479 | B(i8), | 484 | B(i8), |
480 | } | 485 | } |
@@ -498,7 +503,7 @@ fn main() { | |||
498 | fn main() { | 503 | fn main() { |
499 | let mut i = 1; | 504 | let mut i = 1; |
500 | let j = 1; | 505 | let j = 1; |
501 | i = i<|> + j; | 506 | i = i$0 + j; |
502 | 507 | ||
503 | { | 508 | { |
504 | i = 0; | 509 | i = 0; |
@@ -522,7 +527,7 @@ fn main() { | |||
522 | check( | 527 | check( |
523 | r#" | 528 | r#" |
524 | fn foo() { | 529 | fn foo() { |
525 | let spam<|> = 92; | 530 | let spam$0 = 92; |
526 | spam + spam | 531 | spam + spam |
527 | } | 532 | } |
528 | fn bar() { | 533 | fn bar() { |
@@ -543,7 +548,7 @@ fn bar() { | |||
543 | fn test_find_all_refs_for_param_inside() { | 548 | fn test_find_all_refs_for_param_inside() { |
544 | check( | 549 | check( |
545 | r#" | 550 | r#" |
546 | fn foo(i : u32) -> u32 { i<|> } | 551 | fn foo(i : u32) -> u32 { i$0 } |
547 | "#, | 552 | "#, |
548 | expect![[r#" | 553 | expect![[r#" |
549 | i ValueParam FileId(0) 7..8 Other | 554 | i ValueParam FileId(0) 7..8 Other |
@@ -557,7 +562,7 @@ fn foo(i : u32) -> u32 { i<|> } | |||
557 | fn test_find_all_refs_for_fn_param() { | 562 | fn test_find_all_refs_for_fn_param() { |
558 | check( | 563 | check( |
559 | r#" | 564 | r#" |
560 | fn foo(i<|> : u32) -> u32 { i } | 565 | fn foo(i$0 : u32) -> u32 { i } |
561 | "#, | 566 | "#, |
562 | expect![[r#" | 567 | expect![[r#" |
563 | i ValueParam FileId(0) 7..8 Other | 568 | i ValueParam FileId(0) 7..8 Other |
@@ -573,7 +578,7 @@ fn foo(i<|> : u32) -> u32 { i } | |||
573 | r#" | 578 | r#" |
574 | //- /lib.rs | 579 | //- /lib.rs |
575 | struct Foo { | 580 | struct Foo { |
576 | pub spam<|>: u32, | 581 | pub spam$0: u32, |
577 | } | 582 | } |
578 | 583 | ||
579 | fn main(s: Foo) { | 584 | fn main(s: Foo) { |
@@ -594,7 +599,7 @@ fn main(s: Foo) { | |||
594 | r#" | 599 | r#" |
595 | struct Foo; | 600 | struct Foo; |
596 | impl Foo { | 601 | impl Foo { |
597 | fn f<|>(&self) { } | 602 | fn f$0(&self) { } |
598 | } | 603 | } |
599 | "#, | 604 | "#, |
600 | expect![[r#" | 605 | expect![[r#" |
@@ -610,7 +615,7 @@ impl Foo { | |||
610 | r#" | 615 | r#" |
611 | enum Foo { | 616 | enum Foo { |
612 | A, | 617 | A, |
613 | B<|>, | 618 | B$0, |
614 | C, | 619 | C, |
615 | } | 620 | } |
616 | "#, | 621 | "#, |
@@ -627,7 +632,7 @@ enum Foo { | |||
627 | r#" | 632 | r#" |
628 | enum Foo { | 633 | enum Foo { |
629 | A, | 634 | A, |
630 | B { field<|>: u8 }, | 635 | B { field$0: u8 }, |
631 | C, | 636 | C, |
632 | } | 637 | } |
633 | "#, | 638 | "#, |
@@ -669,7 +674,7 @@ pub struct Bar { | |||
669 | } | 674 | } |
670 | 675 | ||
671 | fn f() { | 676 | fn f() { |
672 | let i = foo::Foo<|> { n: 5 }; | 677 | let i = foo::Foo$0 { n: 5 }; |
673 | } | 678 | } |
674 | "#, | 679 | "#, |
675 | expect![[r#" | 680 | expect![[r#" |
@@ -689,7 +694,7 @@ fn f() { | |||
689 | check( | 694 | check( |
690 | r#" | 695 | r#" |
691 | //- /lib.rs | 696 | //- /lib.rs |
692 | mod foo<|>; | 697 | mod foo$0; |
693 | 698 | ||
694 | use foo::Foo; | 699 | use foo::Foo; |
695 | 700 | ||
@@ -726,7 +731,7 @@ fn f() { | |||
726 | } | 731 | } |
727 | 732 | ||
728 | //- /foo/some.rs | 733 | //- /foo/some.rs |
729 | pub(super) struct Foo<|> { | 734 | pub(super) struct Foo$0 { |
730 | pub n: u32, | 735 | pub n: u32, |
731 | } | 736 | } |
732 | "#, | 737 | "#, |
@@ -746,7 +751,7 @@ pub(super) struct Foo<|> { | |||
746 | mod foo; | 751 | mod foo; |
747 | mod bar; | 752 | mod bar; |
748 | 753 | ||
749 | pub fn quux<|>() {} | 754 | pub fn quux$0() {} |
750 | 755 | ||
751 | //- /foo.rs | 756 | //- /foo.rs |
752 | fn f() { super::quux(); } | 757 | fn f() { super::quux(); } |
@@ -782,7 +787,7 @@ pub(super) struct Foo<|> { | |||
782 | check( | 787 | check( |
783 | r#" | 788 | r#" |
784 | #[macro_export] | 789 | #[macro_export] |
785 | macro_rules! m1<|> { () => (()) } | 790 | macro_rules! m1$0 { () => (()) } |
786 | 791 | ||
787 | fn foo() { | 792 | fn foo() { |
788 | m1(); | 793 | m1(); |
@@ -803,7 +808,7 @@ fn foo() { | |||
803 | check( | 808 | check( |
804 | r#" | 809 | r#" |
805 | fn foo() { | 810 | fn foo() { |
806 | let mut i<|> = 0; | 811 | let mut i$0 = 0; |
807 | i = i + 1; | 812 | i = i + 1; |
808 | } | 813 | } |
809 | "#, | 814 | "#, |
@@ -826,7 +831,7 @@ struct S { | |||
826 | 831 | ||
827 | fn foo() { | 832 | fn foo() { |
828 | let mut s = S{f: 0}; | 833 | let mut s = S{f: 0}; |
829 | s.f<|> = 0; | 834 | s.f$0 = 0; |
830 | } | 835 | } |
831 | "#, | 836 | "#, |
832 | expect![[r#" | 837 | expect![[r#" |
@@ -843,7 +848,7 @@ fn foo() { | |||
843 | check( | 848 | check( |
844 | r#" | 849 | r#" |
845 | fn foo() { | 850 | fn foo() { |
846 | let i<|>; | 851 | let i$0; |
847 | i = 1; | 852 | i = 1; |
848 | } | 853 | } |
849 | "#, | 854 | "#, |
@@ -863,7 +868,7 @@ mod foo { | |||
863 | pub struct Foo; | 868 | pub struct Foo; |
864 | 869 | ||
865 | impl Foo { | 870 | impl Foo { |
866 | pub fn new<|>() -> Foo { Foo } | 871 | pub fn new$0() -> Foo { Foo } |
867 | } | 872 | } |
868 | } | 873 | } |
869 | 874 | ||
@@ -886,7 +891,7 @@ fn main() { | |||
886 | //- /lib.rs | 891 | //- /lib.rs |
887 | mod foo { mod bar; } | 892 | mod foo { mod bar; } |
888 | 893 | ||
889 | fn f<|>() {} | 894 | fn f$0() {} |
890 | 895 | ||
891 | //- /foo/bar.rs | 896 | //- /foo/bar.rs |
892 | use crate::f; | 897 | use crate::f; |
@@ -907,7 +912,7 @@ fn g() { f(); } | |||
907 | check( | 912 | check( |
908 | r#" | 913 | r#" |
909 | struct S { | 914 | struct S { |
910 | field<|>: u8, | 915 | field$0: u8, |
911 | } | 916 | } |
912 | 917 | ||
913 | fn f(s: S) { | 918 | fn f(s: S) { |
@@ -930,7 +935,7 @@ fn f(s: S) { | |||
930 | r#" | 935 | r#" |
931 | enum En { | 936 | enum En { |
932 | Variant { | 937 | Variant { |
933 | field<|>: u8, | 938 | field$0: u8, |
934 | } | 939 | } |
935 | } | 940 | } |
936 | 941 | ||
@@ -955,7 +960,7 @@ fn f(e: En) { | |||
955 | mod m { | 960 | mod m { |
956 | pub enum En { | 961 | pub enum En { |
957 | Variant { | 962 | Variant { |
958 | field<|>: u8, | 963 | field$0: u8, |
959 | } | 964 | } |
960 | } | 965 | } |
961 | } | 966 | } |
@@ -980,7 +985,7 @@ struct Foo { bar: i32 } | |||
980 | 985 | ||
981 | impl Foo { | 986 | impl Foo { |
982 | fn foo(self) { | 987 | fn foo(self) { |
983 | let x = self<|>.bar; | 988 | let x = self$0.bar; |
984 | if true { | 989 | if true { |
985 | let _ = match () { | 990 | let _ = match () { |
986 | () => self, | 991 | () => self, |
@@ -1016,12 +1021,14 @@ impl Foo { | |||
1016 | actual += "\n\n"; | 1021 | actual += "\n\n"; |
1017 | } | 1022 | } |
1018 | 1023 | ||
1019 | for r in &refs.references { | 1024 | for (file_id, references) in refs.references { |
1020 | format_to!(actual, "{:?} {:?} {:?}", r.file_range.file_id, r.file_range.range, r.kind); | 1025 | for r in references { |
1021 | if let Some(access) = r.access { | 1026 | format_to!(actual, "{:?} {:?} {:?}", file_id, r.range, r.kind); |
1022 | format_to!(actual, " {:?}", access); | 1027 | if let Some(access) = r.access { |
1028 | format_to!(actual, " {:?}", access); | ||
1029 | } | ||
1030 | actual += "\n"; | ||
1023 | } | 1031 | } |
1024 | actual += "\n"; | ||
1025 | } | 1032 | } |
1026 | expect.assert_eq(&actual) | 1033 | expect.assert_eq(&actual) |
1027 | } | 1034 | } |
@@ -1032,7 +1039,7 @@ impl Foo { | |||
1032 | r#" | 1039 | r#" |
1033 | trait Foo<'a> {} | 1040 | trait Foo<'a> {} |
1034 | impl<'a> Foo<'a> for &'a () {} | 1041 | impl<'a> Foo<'a> for &'a () {} |
1035 | fn foo<'a, 'b: 'a>(x: &'a<|> ()) -> &'a () where &'a (): Foo<'a> { | 1042 | fn foo<'a, 'b: 'a>(x: &'a$0 ()) -> &'a () where &'a (): Foo<'a> { |
1036 | fn bar<'a>(_: &'a ()) {} | 1043 | fn bar<'a>(_: &'a ()) {} |
1037 | x | 1044 | x |
1038 | } | 1045 | } |
@@ -1053,7 +1060,7 @@ fn foo<'a, 'b: 'a>(x: &'a<|> ()) -> &'a () where &'a (): Foo<'a> { | |||
1053 | fn test_find_lifetimes_type_alias() { | 1060 | fn test_find_lifetimes_type_alias() { |
1054 | check( | 1061 | check( |
1055 | r#" | 1062 | r#" |
1056 | type Foo<'a, T> where T: 'a<|> = &'a T; | 1063 | type Foo<'a, T> where T: 'a$0 = &'a T; |
1057 | "#, | 1064 | "#, |
1058 | expect![[r#" | 1065 | expect![[r#" |
1059 | 'a LifetimeParam FileId(0) 9..11 9..11 Lifetime | 1066 | 'a LifetimeParam FileId(0) 9..11 9..11 Lifetime |
@@ -1072,7 +1079,7 @@ trait Foo<'a> { | |||
1072 | fn foo() -> &'a (); | 1079 | fn foo() -> &'a (); |
1073 | } | 1080 | } |
1074 | impl<'a> Foo<'a> for &'a () { | 1081 | impl<'a> Foo<'a> for &'a () { |
1075 | fn foo() -> &'a<|> () { | 1082 | fn foo() -> &'a$0 () { |
1076 | unimplemented!() | 1083 | unimplemented!() |
1077 | } | 1084 | } |
1078 | } | 1085 | } |
@@ -1093,7 +1100,7 @@ impl<'a> Foo<'a> for &'a () { | |||
1093 | r#" | 1100 | r#" |
1094 | macro_rules! foo {($i:ident) => {$i} } | 1101 | macro_rules! foo {($i:ident) => {$i} } |
1095 | fn main() { | 1102 | fn main() { |
1096 | let a<|> = "test"; | 1103 | let a$0 = "test"; |
1097 | foo!(a); | 1104 | foo!(a); |
1098 | } | 1105 | } |
1099 | "#, | 1106 | "#, |
@@ -1112,7 +1119,7 @@ fn main() { | |||
1112 | macro_rules! foo {($i:ident) => {$i} } | 1119 | macro_rules! foo {($i:ident) => {$i} } |
1113 | fn main() { | 1120 | fn main() { |
1114 | let a = "test"; | 1121 | let a = "test"; |
1115 | foo!(a<|>); | 1122 | foo!(a$0); |
1116 | } | 1123 | } |
1117 | "#, | 1124 | "#, |
1118 | expect![[r#" | 1125 | expect![[r#" |
@@ -1130,7 +1137,7 @@ fn main() { | |||
1130 | fn foo<'a>() -> &'a () { | 1137 | fn foo<'a>() -> &'a () { |
1131 | 'a: loop { | 1138 | 'a: loop { |
1132 | 'b: loop { | 1139 | 'b: loop { |
1133 | continue 'a<|>; | 1140 | continue 'a$0; |
1134 | } | 1141 | } |
1135 | break 'a; | 1142 | break 'a; |
1136 | } | 1143 | } |
@@ -1149,7 +1156,7 @@ fn foo<'a>() -> &'a () { | |||
1149 | fn test_find_const_param() { | 1156 | fn test_find_const_param() { |
1150 | check( | 1157 | check( |
1151 | r#" | 1158 | r#" |
1152 | fn foo<const FOO<|>: usize>() -> usize { | 1159 | fn foo<const FOO$0: usize>() -> usize { |
1153 | FOO | 1160 | FOO |
1154 | } | 1161 | } |
1155 | "#, | 1162 | "#, |
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index 854bf194e..c3ae568c2 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs | |||
@@ -1,29 +1,30 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | use std::{ | 2 | use std::{ |
3 | convert::TryInto, | 3 | convert::TryInto, |
4 | error::Error, | ||
5 | fmt::{self, Display}, | 4 | fmt::{self, Display}, |
6 | }; | 5 | }; |
7 | 6 | ||
8 | use hir::{Module, ModuleDef, ModuleSource, Semantics}; | 7 | use hir::{Module, ModuleDef, ModuleSource, Semantics}; |
9 | use ide_db::base_db::{AnchoredPathBuf, FileId, FileRange, SourceDatabaseExt}; | ||
10 | use ide_db::{ | 8 | use ide_db::{ |
9 | base_db::{AnchoredPathBuf, FileId, FileRange, SourceDatabaseExt}, | ||
11 | defs::{Definition, NameClass, NameRefClass}, | 10 | defs::{Definition, NameClass, NameRefClass}, |
11 | search::FileReference, | ||
12 | RootDatabase, | 12 | RootDatabase, |
13 | }; | 13 | }; |
14 | use syntax::{ | 14 | use syntax::{ |
15 | algo::find_node_at_offset, | 15 | algo::find_node_at_offset, |
16 | ast::{self, NameOwner}, | 16 | ast::{self, NameOwner}, |
17 | lex_single_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, SyntaxToken, | 17 | lex_single_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, SyntaxToken, T, |
18 | }; | 18 | }; |
19 | use test_utils::mark; | 19 | use test_utils::mark; |
20 | use text_edit::TextEdit; | 20 | use text_edit::TextEdit; |
21 | 21 | ||
22 | use crate::{ | 22 | use crate::{ |
23 | references::find_all_refs, FilePosition, FileSystemEdit, RangeInfo, Reference, ReferenceKind, | 23 | FilePosition, FileSystemEdit, RangeInfo, ReferenceKind, ReferenceSearchResult, SourceChange, |
24 | SourceChange, SourceFileEdit, TextRange, TextSize, | 24 | SourceFileEdit, TextRange, TextSize, |
25 | }; | 25 | }; |
26 | 26 | ||
27 | type RenameResult<T> = Result<T, RenameError>; | ||
27 | #[derive(Debug)] | 28 | #[derive(Debug)] |
28 | pub struct RenameError(pub(crate) String); | 29 | pub struct RenameError(pub(crate) String); |
29 | 30 | ||
@@ -33,26 +34,30 @@ impl fmt::Display for RenameError { | |||
33 | } | 34 | } |
34 | } | 35 | } |
35 | 36 | ||
36 | impl Error for RenameError {} | 37 | macro_rules! format_err { |
38 | ($fmt:expr) => {RenameError(format!($fmt))}; | ||
39 | ($fmt:expr, $($arg:tt)+) => {RenameError(format!($fmt, $($arg)+))} | ||
40 | } | ||
41 | |||
42 | macro_rules! bail { | ||
43 | ($($tokens:tt)*) => {return Err(format_err!($($tokens)*))} | ||
44 | } | ||
37 | 45 | ||
38 | pub(crate) fn prepare_rename( | 46 | pub(crate) fn prepare_rename( |
39 | db: &RootDatabase, | 47 | db: &RootDatabase, |
40 | position: FilePosition, | 48 | position: FilePosition, |
41 | ) -> Result<RangeInfo<()>, RenameError> { | 49 | ) -> RenameResult<RangeInfo<()>> { |
42 | let sema = Semantics::new(db); | 50 | let sema = Semantics::new(db); |
43 | let source_file = sema.parse(position.file_id); | 51 | let source_file = sema.parse(position.file_id); |
44 | let syntax = source_file.syntax(); | 52 | let syntax = source_file.syntax(); |
45 | if let Some(module) = find_module_at_offset(&sema, position, syntax) { | 53 | if let Some(module) = find_module_at_offset(&sema, position, syntax) { |
46 | rename_mod(&sema, position, module, "dummy") | 54 | rename_mod(&sema, position, module, "dummy") |
47 | } else if let Some(self_token) = | 55 | } else if let Some(self_token) = |
48 | syntax.token_at_offset(position.offset).find(|t| t.kind() == SyntaxKind::SELF_KW) | 56 | syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self]) |
49 | { | 57 | { |
50 | rename_self_to_param(&sema, position, self_token, "dummy") | 58 | rename_self_to_param(&sema, position, self_token, "dummy") |
51 | } else { | 59 | } else { |
52 | let range = match find_all_refs(&sema, position, None) { | 60 | let RangeInfo { range, .. } = find_all_refs(&sema, position)?; |
53 | Some(RangeInfo { range, .. }) => range, | ||
54 | None => return Err(RenameError("No references found at position".to_string())), | ||
55 | }; | ||
56 | Ok(RangeInfo::new(range, SourceChange::from(vec![]))) | 61 | Ok(RangeInfo::new(range, SourceChange::from(vec![]))) |
57 | } | 62 | } |
58 | .map(|info| RangeInfo::new(info.range, ())) | 63 | .map(|info| RangeInfo::new(info.range, ())) |
@@ -62,7 +67,7 @@ pub(crate) fn rename( | |||
62 | db: &RootDatabase, | 67 | db: &RootDatabase, |
63 | position: FilePosition, | 68 | position: FilePosition, |
64 | new_name: &str, | 69 | new_name: &str, |
65 | ) -> Result<RangeInfo<SourceChange>, RenameError> { | 70 | ) -> RenameResult<RangeInfo<SourceChange>> { |
66 | let sema = Semantics::new(db); | 71 | let sema = Semantics::new(db); |
67 | rename_with_semantics(&sema, position, new_name) | 72 | rename_with_semantics(&sema, position, new_name) |
68 | } | 73 | } |
@@ -71,42 +76,18 @@ pub(crate) fn rename_with_semantics( | |||
71 | sema: &Semantics<RootDatabase>, | 76 | sema: &Semantics<RootDatabase>, |
72 | position: FilePosition, | 77 | position: FilePosition, |
73 | new_name: &str, | 78 | new_name: &str, |
74 | ) -> Result<RangeInfo<SourceChange>, RenameError> { | 79 | ) -> RenameResult<RangeInfo<SourceChange>> { |
75 | let is_lifetime_name = match lex_single_syntax_kind(new_name) { | ||
76 | Some(res) => match res { | ||
77 | (SyntaxKind::IDENT, _) => false, | ||
78 | (SyntaxKind::UNDERSCORE, _) => false, | ||
79 | (SyntaxKind::SELF_KW, _) => return rename_to_self(&sema, position), | ||
80 | (SyntaxKind::LIFETIME_IDENT, _) if new_name != "'static" && new_name != "'_" => true, | ||
81 | (SyntaxKind::LIFETIME_IDENT, _) => { | ||
82 | return Err(RenameError(format!( | ||
83 | "Invalid name `{0}`: Cannot rename lifetime to {0}", | ||
84 | new_name | ||
85 | ))) | ||
86 | } | ||
87 | (_, Some(syntax_error)) => { | ||
88 | return Err(RenameError(format!("Invalid name `{}`: {}", new_name, syntax_error))) | ||
89 | } | ||
90 | (_, None) => { | ||
91 | return Err(RenameError(format!("Invalid name `{}`: not an identifier", new_name))) | ||
92 | } | ||
93 | }, | ||
94 | None => return Err(RenameError(format!("Invalid name `{}`: not an identifier", new_name))), | ||
95 | }; | ||
96 | |||
97 | let source_file = sema.parse(position.file_id); | 80 | let source_file = sema.parse(position.file_id); |
98 | let syntax = source_file.syntax(); | 81 | let syntax = source_file.syntax(); |
99 | // this is here to prevent lifetime renames from happening on modules and self | 82 | |
100 | if is_lifetime_name { | 83 | if let Some(module) = find_module_at_offset(&sema, position, syntax) { |
101 | rename_reference(&sema, position, new_name, is_lifetime_name) | ||
102 | } else if let Some(module) = find_module_at_offset(&sema, position, syntax) { | ||
103 | rename_mod(&sema, position, module, new_name) | 84 | rename_mod(&sema, position, module, new_name) |
104 | } else if let Some(self_token) = | 85 | } else if let Some(self_token) = |
105 | syntax.token_at_offset(position.offset).find(|t| t.kind() == SyntaxKind::SELF_KW) | 86 | syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self]) |
106 | { | 87 | { |
107 | rename_self_to_param(&sema, position, self_token, new_name) | 88 | rename_self_to_param(&sema, position, self_token, new_name) |
108 | } else { | 89 | } else { |
109 | rename_reference(&sema, position, new_name, is_lifetime_name) | 90 | rename_reference(&sema, position, new_name) |
110 | } | 91 | } |
111 | } | 92 | } |
112 | 93 | ||
@@ -127,6 +108,33 @@ pub(crate) fn will_rename_file( | |||
127 | Some(change) | 108 | Some(change) |
128 | } | 109 | } |
129 | 110 | ||
111 | #[derive(Debug, PartialEq)] | ||
112 | enum IdentifierKind { | ||
113 | Ident, | ||
114 | Lifetime, | ||
115 | ToSelf, | ||
116 | Underscore, | ||
117 | } | ||
118 | |||
119 | fn check_identifier(new_name: &str) -> RenameResult<IdentifierKind> { | ||
120 | match lex_single_syntax_kind(new_name) { | ||
121 | Some(res) => match res { | ||
122 | (SyntaxKind::IDENT, _) => Ok(IdentifierKind::Ident), | ||
123 | (T![_], _) => Ok(IdentifierKind::Underscore), | ||
124 | (T![self], _) => Ok(IdentifierKind::ToSelf), | ||
125 | (SyntaxKind::LIFETIME_IDENT, _) if new_name != "'static" && new_name != "'_" => { | ||
126 | Ok(IdentifierKind::Lifetime) | ||
127 | } | ||
128 | (SyntaxKind::LIFETIME_IDENT, _) => { | ||
129 | bail!("Invalid name `{0}`: Cannot rename lifetime to {0}", new_name) | ||
130 | } | ||
131 | (_, Some(syntax_error)) => bail!("Invalid name `{}`: {}", new_name, syntax_error), | ||
132 | (_, None) => bail!("Invalid name `{}`: not an identifier", new_name), | ||
133 | }, | ||
134 | None => bail!("Invalid name `{}`: not an identifier", new_name), | ||
135 | } | ||
136 | } | ||
137 | |||
130 | fn find_module_at_offset( | 138 | fn find_module_at_offset( |
131 | sema: &Semantics<RootDatabase>, | 139 | sema: &Semantics<RootDatabase>, |
132 | position: FilePosition, | 140 | position: FilePosition, |
@@ -155,39 +163,54 @@ fn find_module_at_offset( | |||
155 | Some(module) | 163 | Some(module) |
156 | } | 164 | } |
157 | 165 | ||
158 | fn source_edit_from_reference( | 166 | fn find_all_refs( |
167 | sema: &Semantics<RootDatabase>, | ||
168 | position: FilePosition, | ||
169 | ) -> RenameResult<RangeInfo<ReferenceSearchResult>> { | ||
170 | crate::references::find_all_refs(sema, position, None) | ||
171 | .ok_or_else(|| format_err!("No references found at position")) | ||
172 | } | ||
173 | |||
174 | fn source_edit_from_references( | ||
159 | sema: &Semantics<RootDatabase>, | 175 | sema: &Semantics<RootDatabase>, |
160 | reference: Reference, | 176 | file_id: FileId, |
177 | references: &[FileReference], | ||
161 | new_name: &str, | 178 | new_name: &str, |
162 | ) -> SourceFileEdit { | 179 | ) -> SourceFileEdit { |
163 | let mut replacement_text = String::new(); | 180 | let mut edit = TextEdit::builder(); |
164 | let range = match reference.kind { | 181 | for reference in references { |
165 | ReferenceKind::FieldShorthandForField => { | 182 | let mut replacement_text = String::new(); |
166 | mark::hit!(test_rename_struct_field_for_shorthand); | 183 | let range = match reference.kind { |
167 | replacement_text.push_str(new_name); | 184 | ReferenceKind::FieldShorthandForField => { |
168 | replacement_text.push_str(": "); | 185 | mark::hit!(test_rename_struct_field_for_shorthand); |
169 | TextRange::new(reference.file_range.range.start(), reference.file_range.range.start()) | 186 | replacement_text.push_str(new_name); |
170 | } | 187 | replacement_text.push_str(": "); |
171 | ReferenceKind::FieldShorthandForLocal => { | 188 | TextRange::new(reference.range.start(), reference.range.start()) |
172 | mark::hit!(test_rename_local_for_field_shorthand); | 189 | } |
173 | replacement_text.push_str(": "); | 190 | ReferenceKind::FieldShorthandForLocal => { |
174 | replacement_text.push_str(new_name); | 191 | mark::hit!(test_rename_local_for_field_shorthand); |
175 | TextRange::new(reference.file_range.range.end(), reference.file_range.range.end()) | 192 | replacement_text.push_str(": "); |
176 | } | 193 | replacement_text.push_str(new_name); |
177 | ReferenceKind::RecordFieldExprOrPat => { | 194 | TextRange::new(reference.range.end(), reference.range.end()) |
178 | mark::hit!(test_rename_field_expr_pat); | 195 | } |
179 | replacement_text.push_str(new_name); | 196 | ReferenceKind::RecordFieldExprOrPat => { |
180 | edit_text_range_for_record_field_expr_or_pat(sema, reference.file_range, new_name) | 197 | mark::hit!(test_rename_field_expr_pat); |
181 | } | 198 | replacement_text.push_str(new_name); |
182 | _ => { | 199 | edit_text_range_for_record_field_expr_or_pat( |
183 | replacement_text.push_str(new_name); | 200 | sema, |
184 | reference.file_range.range | 201 | FileRange { file_id, range: reference.range }, |
185 | } | 202 | new_name, |
186 | }; | 203 | ) |
187 | SourceFileEdit { | 204 | } |
188 | file_id: reference.file_range.file_id, | 205 | _ => { |
189 | edit: TextEdit::replace(range, replacement_text), | 206 | replacement_text.push_str(new_name); |
207 | reference.range | ||
208 | } | ||
209 | }; | ||
210 | edit.replace(range, replacement_text); | ||
190 | } | 211 | } |
212 | |||
213 | SourceFileEdit { file_id, edit: edit.finish() } | ||
191 | } | 214 | } |
192 | 215 | ||
193 | fn edit_text_range_for_record_field_expr_or_pat( | 216 | fn edit_text_range_for_record_field_expr_or_pat( |
@@ -223,7 +246,10 @@ fn rename_mod( | |||
223 | position: FilePosition, | 246 | position: FilePosition, |
224 | module: Module, | 247 | module: Module, |
225 | new_name: &str, | 248 | new_name: &str, |
226 | ) -> Result<RangeInfo<SourceChange>, RenameError> { | 249 | ) -> RenameResult<RangeInfo<SourceChange>> { |
250 | if IdentifierKind::Ident != check_identifier(new_name)? { | ||
251 | bail!("Invalid name `{0}`: cannot rename module to {0}", new_name); | ||
252 | } | ||
227 | let mut source_file_edits = Vec::new(); | 253 | let mut source_file_edits = Vec::new(); |
228 | let mut file_system_edits = Vec::new(); | 254 | let mut file_system_edits = Vec::new(); |
229 | 255 | ||
@@ -254,12 +280,10 @@ fn rename_mod( | |||
254 | source_file_edits.push(edit); | 280 | source_file_edits.push(edit); |
255 | } | 281 | } |
256 | 282 | ||
257 | let RangeInfo { range, info: refs } = find_all_refs(sema, position, None) | 283 | let RangeInfo { range, info: refs } = find_all_refs(sema, position)?; |
258 | .ok_or_else(|| RenameError("No references found at position".to_string()))?; | 284 | let ref_edits = refs.references().iter().map(|(&file_id, references)| { |
259 | let ref_edits = refs | 285 | source_edit_from_references(sema, file_id, references, new_name) |
260 | .references | 286 | }); |
261 | .into_iter() | ||
262 | .map(|reference| source_edit_from_reference(sema, reference, new_name)); | ||
263 | source_file_edits.extend(ref_edits); | 287 | source_file_edits.extend(ref_edits); |
264 | 288 | ||
265 | Ok(RangeInfo::new(range, SourceChange::from_edits(source_file_edits, file_system_edits))) | 289 | Ok(RangeInfo::new(range, SourceChange::from_edits(source_file_edits, file_system_edits))) |
@@ -274,27 +298,26 @@ fn rename_to_self( | |||
274 | 298 | ||
275 | let (fn_def, fn_ast) = find_node_at_offset::<ast::Fn>(syn, position.offset) | 299 | let (fn_def, fn_ast) = find_node_at_offset::<ast::Fn>(syn, position.offset) |
276 | .and_then(|fn_ast| sema.to_def(&fn_ast).zip(Some(fn_ast))) | 300 | .and_then(|fn_ast| sema.to_def(&fn_ast).zip(Some(fn_ast))) |
277 | .ok_or_else(|| RenameError("No surrounding method declaration found".to_string()))?; | 301 | .ok_or_else(|| format_err!("No surrounding method declaration found"))?; |
278 | let param_range = fn_ast | 302 | let param_range = fn_ast |
279 | .param_list() | 303 | .param_list() |
280 | .and_then(|p| p.params().next()) | 304 | .and_then(|p| p.params().next()) |
281 | .ok_or_else(|| RenameError("Method has no parameters".to_string()))? | 305 | .ok_or_else(|| format_err!("Method has no parameters"))? |
282 | .syntax() | 306 | .syntax() |
283 | .text_range(); | 307 | .text_range(); |
284 | if !param_range.contains(position.offset) { | 308 | if !param_range.contains(position.offset) { |
285 | return Err(RenameError("Only the first parameter can be self".to_string())); | 309 | bail!("Only the first parameter can be self"); |
286 | } | 310 | } |
287 | 311 | ||
288 | let impl_block = find_node_at_offset::<ast::Impl>(syn, position.offset) | 312 | let impl_block = find_node_at_offset::<ast::Impl>(syn, position.offset) |
289 | .and_then(|def| sema.to_def(&def)) | 313 | .and_then(|def| sema.to_def(&def)) |
290 | .ok_or_else(|| RenameError("No impl block found for function".to_string()))?; | 314 | .ok_or_else(|| format_err!("No impl block found for function"))?; |
291 | if fn_def.self_param(sema.db).is_some() { | 315 | if fn_def.self_param(sema.db).is_some() { |
292 | return Err(RenameError("Method already has a self parameter".to_string())); | 316 | bail!("Method already has a self parameter"); |
293 | } | 317 | } |
294 | 318 | ||
295 | let params = fn_def.assoc_fn_params(sema.db); | 319 | let params = fn_def.assoc_fn_params(sema.db); |
296 | let first_param = | 320 | let first_param = params.first().ok_or_else(|| format_err!("Method has no parameters"))?; |
297 | params.first().ok_or_else(|| RenameError("Method has no parameters".into()))?; | ||
298 | let first_param_ty = first_param.ty(); | 321 | let first_param_ty = first_param.ty(); |
299 | let impl_ty = impl_block.target_ty(sema.db); | 322 | let impl_ty = impl_block.target_ty(sema.db); |
300 | let (ty, self_param) = if impl_ty.remove_ref().is_some() { | 323 | let (ty, self_param) = if impl_ty.remove_ref().is_some() { |
@@ -307,23 +330,17 @@ fn rename_to_self( | |||
307 | }; | 330 | }; |
308 | 331 | ||
309 | if ty != impl_ty { | 332 | if ty != impl_ty { |
310 | return Err(RenameError("Parameter type differs from impl block type".to_string())); | 333 | bail!("Parameter type differs from impl block type"); |
311 | } | 334 | } |
312 | 335 | ||
313 | let RangeInfo { range, info: refs } = find_all_refs(sema, position, None) | 336 | let RangeInfo { range, info: refs } = find_all_refs(sema, position)?; |
314 | .ok_or_else(|| RenameError("No reference found at position".to_string()))?; | ||
315 | |||
316 | let (param_ref, usages): (Vec<Reference>, Vec<Reference>) = refs | ||
317 | .into_iter() | ||
318 | .partition(|reference| param_range.intersect(reference.file_range.range).is_some()); | ||
319 | |||
320 | if param_ref.is_empty() { | ||
321 | return Err(RenameError("Parameter to rename not found".to_string())); | ||
322 | } | ||
323 | 337 | ||
324 | let mut edits = usages | 338 | let mut edits = refs |
325 | .into_iter() | 339 | .references() |
326 | .map(|reference| source_edit_from_reference(sema, reference, "self")) | 340 | .iter() |
341 | .map(|(&file_id, references)| { | ||
342 | source_edit_from_references(sema, file_id, references, "self") | ||
343 | }) | ||
327 | .collect::<Vec<_>>(); | 344 | .collect::<Vec<_>>(); |
328 | 345 | ||
329 | edits.push(SourceFileEdit { | 346 | edits.push(SourceFileEdit { |
@@ -367,12 +384,22 @@ fn rename_self_to_param( | |||
367 | self_token: SyntaxToken, | 384 | self_token: SyntaxToken, |
368 | new_name: &str, | 385 | new_name: &str, |
369 | ) -> Result<RangeInfo<SourceChange>, RenameError> { | 386 | ) -> Result<RangeInfo<SourceChange>, RenameError> { |
387 | let ident_kind = check_identifier(new_name)?; | ||
388 | match ident_kind { | ||
389 | IdentifierKind::Lifetime => bail!("Invalid name `{}`: not an identifier", new_name), | ||
390 | IdentifierKind::ToSelf => { | ||
391 | // no-op | ||
392 | mark::hit!(rename_self_to_self); | ||
393 | return Ok(RangeInfo::new(self_token.text_range(), SourceChange::default())); | ||
394 | } | ||
395 | _ => (), | ||
396 | } | ||
370 | let source_file = sema.parse(position.file_id); | 397 | let source_file = sema.parse(position.file_id); |
371 | let syn = source_file.syntax(); | 398 | let syn = source_file.syntax(); |
372 | 399 | ||
373 | let text = sema.db.file_text(position.file_id); | 400 | let text = sema.db.file_text(position.file_id); |
374 | let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset) | 401 | let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset) |
375 | .ok_or_else(|| RenameError("No surrounding method declaration found".to_string()))?; | 402 | .ok_or_else(|| format_err!("No surrounding method declaration found"))?; |
376 | let search_range = fn_def.syntax().text_range(); | 403 | let search_range = fn_def.syntax().text_range(); |
377 | 404 | ||
378 | let mut edits: Vec<SourceFileEdit> = vec![]; | 405 | let mut edits: Vec<SourceFileEdit> = vec![]; |
@@ -382,12 +409,10 @@ fn rename_self_to_param( | |||
382 | if !search_range.contains_inclusive(offset) { | 409 | if !search_range.contains_inclusive(offset) { |
383 | continue; | 410 | continue; |
384 | } | 411 | } |
385 | if let Some(ref usage) = | 412 | if let Some(ref usage) = syn.token_at_offset(offset).find(|t| t.kind() == T![self]) { |
386 | syn.token_at_offset(offset).find(|t| t.kind() == SyntaxKind::SELF_KW) | ||
387 | { | ||
388 | let edit = if let Some(ref self_param) = ast::SelfParam::cast(usage.parent()) { | 413 | let edit = if let Some(ref self_param) = ast::SelfParam::cast(usage.parent()) { |
389 | text_edit_from_self_param(syn, self_param, new_name) | 414 | text_edit_from_self_param(syn, self_param, new_name) |
390 | .ok_or_else(|| RenameError("No target type found".to_string()))? | 415 | .ok_or_else(|| format_err!("No target type found"))? |
391 | } else { | 416 | } else { |
392 | TextEdit::replace(usage.text_range(), String::from(new_name)) | 417 | TextEdit::replace(usage.text_range(), String::from(new_name)) |
393 | }; | 418 | }; |
@@ -395,6 +420,10 @@ fn rename_self_to_param( | |||
395 | } | 420 | } |
396 | } | 421 | } |
397 | 422 | ||
423 | if edits.len() > 1 && ident_kind == IdentifierKind::Underscore { | ||
424 | bail!("Cannot rename reference to `_` as it is being referenced multiple times"); | ||
425 | } | ||
426 | |||
398 | let range = ast::SelfParam::cast(self_token.parent()) | 427 | let range = ast::SelfParam::cast(self_token.parent()) |
399 | .map_or(self_token.text_range(), |p| p.syntax().text_range()); | 428 | .map_or(self_token.text_range(), |p| p.syntax().text_range()); |
400 | 429 | ||
@@ -405,35 +434,43 @@ fn rename_reference( | |||
405 | sema: &Semantics<RootDatabase>, | 434 | sema: &Semantics<RootDatabase>, |
406 | position: FilePosition, | 435 | position: FilePosition, |
407 | new_name: &str, | 436 | new_name: &str, |
408 | is_lifetime_name: bool, | ||
409 | ) -> Result<RangeInfo<SourceChange>, RenameError> { | 437 | ) -> Result<RangeInfo<SourceChange>, RenameError> { |
410 | let RangeInfo { range, info: refs } = match find_all_refs(sema, position, None) { | 438 | let ident_kind = check_identifier(new_name)?; |
411 | Some(range_info) => range_info, | 439 | let RangeInfo { range, info: refs } = find_all_refs(sema, position)?; |
412 | None => return Err(RenameError("No references found at position".to_string())), | 440 | |
413 | }; | 441 | match (ident_kind, &refs.declaration.kind) { |
414 | 442 | (IdentifierKind::ToSelf, ReferenceKind::Lifetime) | |
415 | match (refs.declaration.kind == ReferenceKind::Lifetime, is_lifetime_name) { | 443 | | (IdentifierKind::Underscore, ReferenceKind::Lifetime) |
416 | (true, false) => { | 444 | | (IdentifierKind::Ident, ReferenceKind::Lifetime) => { |
417 | return Err(RenameError(format!( | 445 | mark::hit!(rename_not_a_lifetime_ident_ref); |
418 | "Invalid name `{}`: not a lifetime identifier", | 446 | bail!("Invalid name `{}`: not a lifetime identifier", new_name) |
419 | new_name | ||
420 | ))) | ||
421 | } | 447 | } |
422 | (false, true) => { | 448 | (IdentifierKind::Lifetime, ReferenceKind::Lifetime) => mark::hit!(rename_lifetime), |
423 | return Err(RenameError(format!("Invalid name `{}`: not an identifier", new_name))) | 449 | (IdentifierKind::Lifetime, _) => { |
450 | mark::hit!(rename_not_an_ident_ref); | ||
451 | bail!("Invalid name `{}`: not an identifier", new_name) | ||
424 | } | 452 | } |
425 | _ => (), | 453 | (IdentifierKind::ToSelf, ReferenceKind::SelfKw) => { |
454 | unreachable!("rename_self_to_param should've been called instead") | ||
455 | } | ||
456 | (IdentifierKind::ToSelf, _) => { | ||
457 | mark::hit!(rename_to_self); | ||
458 | return rename_to_self(sema, position); | ||
459 | } | ||
460 | (IdentifierKind::Underscore, _) if !refs.references.is_empty() => { | ||
461 | mark::hit!(rename_underscore_multiple); | ||
462 | bail!("Cannot rename reference to `_` as it is being referenced multiple times") | ||
463 | } | ||
464 | (IdentifierKind::Ident, _) | (IdentifierKind::Underscore, _) => mark::hit!(rename_ident), | ||
426 | } | 465 | } |
427 | 466 | ||
428 | let edit = refs | 467 | let edit = refs |
429 | .into_iter() | 468 | .into_iter() |
430 | .map(|reference| source_edit_from_reference(sema, reference, new_name)) | 469 | .map(|(file_id, references)| { |
470 | source_edit_from_references(sema, file_id, &references, new_name) | ||
471 | }) | ||
431 | .collect::<Vec<_>>(); | 472 | .collect::<Vec<_>>(); |
432 | 473 | ||
433 | if edit.is_empty() { | ||
434 | return Err(RenameError("No references found at position".to_string())); | ||
435 | } | ||
436 | |||
437 | Ok(RangeInfo::new(range, SourceChange::from(edit))) | 474 | Ok(RangeInfo::new(range, SourceChange::from(edit))) |
438 | } | 475 | } |
439 | 476 | ||
@@ -462,9 +499,11 @@ mod tests { | |||
462 | text_edit_builder.replace(indel.delete, indel.insert); | 499 | text_edit_builder.replace(indel.delete, indel.insert); |
463 | } | 500 | } |
464 | } | 501 | } |
465 | let mut result = analysis.file_text(file_id.unwrap()).unwrap().to_string(); | 502 | if let Some(file_id) = file_id { |
466 | text_edit_builder.finish().apply(&mut result); | 503 | let mut result = analysis.file_text(file_id).unwrap().to_string(); |
467 | assert_eq_text!(ra_fixture_after, &*result); | 504 | text_edit_builder.finish().apply(&mut result); |
505 | assert_eq_text!(ra_fixture_after, &*result); | ||
506 | } | ||
468 | } | 507 | } |
469 | Err(err) => { | 508 | Err(err) => { |
470 | if ra_fixture_after.starts_with("error:") { | 509 | if ra_fixture_after.starts_with("error:") { |
@@ -493,19 +532,19 @@ mod tests { | |||
493 | 532 | ||
494 | #[test] | 533 | #[test] |
495 | fn test_rename_to_underscore() { | 534 | fn test_rename_to_underscore() { |
496 | check("_", r#"fn main() { let i<|> = 1; }"#, r#"fn main() { let _ = 1; }"#); | 535 | check("_", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let _ = 1; }"#); |
497 | } | 536 | } |
498 | 537 | ||
499 | #[test] | 538 | #[test] |
500 | fn test_rename_to_raw_identifier() { | 539 | fn test_rename_to_raw_identifier() { |
501 | check("r#fn", r#"fn main() { let i<|> = 1; }"#, r#"fn main() { let r#fn = 1; }"#); | 540 | check("r#fn", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let r#fn = 1; }"#); |
502 | } | 541 | } |
503 | 542 | ||
504 | #[test] | 543 | #[test] |
505 | fn test_rename_to_invalid_identifier1() { | 544 | fn test_rename_to_invalid_identifier1() { |
506 | check( | 545 | check( |
507 | "invalid!", | 546 | "invalid!", |
508 | r#"fn main() { let i<|> = 1; }"#, | 547 | r#"fn main() { let i$0 = 1; }"#, |
509 | "error: Invalid name `invalid!`: not an identifier", | 548 | "error: Invalid name `invalid!`: not an identifier", |
510 | ); | 549 | ); |
511 | } | 550 | } |
@@ -514,7 +553,7 @@ mod tests { | |||
514 | fn test_rename_to_invalid_identifier2() { | 553 | fn test_rename_to_invalid_identifier2() { |
515 | check( | 554 | check( |
516 | "multiple tokens", | 555 | "multiple tokens", |
517 | r#"fn main() { let i<|> = 1; }"#, | 556 | r#"fn main() { let i$0 = 1; }"#, |
518 | "error: Invalid name `multiple tokens`: not an identifier", | 557 | "error: Invalid name `multiple tokens`: not an identifier", |
519 | ); | 558 | ); |
520 | } | 559 | } |
@@ -523,38 +562,60 @@ mod tests { | |||
523 | fn test_rename_to_invalid_identifier3() { | 562 | fn test_rename_to_invalid_identifier3() { |
524 | check( | 563 | check( |
525 | "let", | 564 | "let", |
526 | r#"fn main() { let i<|> = 1; }"#, | 565 | r#"fn main() { let i$0 = 1; }"#, |
527 | "error: Invalid name `let`: not an identifier", | 566 | "error: Invalid name `let`: not an identifier", |
528 | ); | 567 | ); |
529 | } | 568 | } |
530 | 569 | ||
531 | #[test] | 570 | #[test] |
532 | fn test_rename_to_invalid_identifier_lifetime() { | 571 | fn test_rename_to_invalid_identifier_lifetime() { |
572 | mark::check!(rename_not_an_ident_ref); | ||
533 | check( | 573 | check( |
534 | "'foo", | 574 | "'foo", |
535 | r#"fn main() { let i<|> = 1; }"#, | 575 | r#"fn main() { let i$0 = 1; }"#, |
536 | "error: Invalid name `'foo`: not an identifier", | 576 | "error: Invalid name `'foo`: not an identifier", |
537 | ); | 577 | ); |
538 | } | 578 | } |
539 | 579 | ||
540 | #[test] | 580 | #[test] |
541 | fn test_rename_to_invalid_identifier_lifetime2() { | 581 | fn test_rename_to_invalid_identifier_lifetime2() { |
582 | mark::check!(rename_not_a_lifetime_ident_ref); | ||
542 | check( | 583 | check( |
543 | "foo", | 584 | "foo", |
544 | r#"fn main<'a>(_: &'a<|> ()) {}"#, | 585 | r#"fn main<'a>(_: &'a$0 ()) {}"#, |
545 | "error: Invalid name `foo`: not a lifetime identifier", | 586 | "error: Invalid name `foo`: not a lifetime identifier", |
546 | ); | 587 | ); |
547 | } | 588 | } |
548 | 589 | ||
549 | #[test] | 590 | #[test] |
591 | fn test_rename_to_underscore_invalid() { | ||
592 | mark::check!(rename_underscore_multiple); | ||
593 | check( | ||
594 | "_", | ||
595 | r#"fn main(foo$0: ()) {foo;}"#, | ||
596 | "error: Cannot rename reference to `_` as it is being referenced multiple times", | ||
597 | ); | ||
598 | } | ||
599 | |||
600 | #[test] | ||
601 | fn test_rename_mod_invalid() { | ||
602 | check( | ||
603 | "'foo", | ||
604 | r#"mod foo$0 {}"#, | ||
605 | "error: Invalid name `'foo`: cannot rename module to 'foo", | ||
606 | ); | ||
607 | } | ||
608 | |||
609 | #[test] | ||
550 | fn test_rename_for_local() { | 610 | fn test_rename_for_local() { |
611 | mark::check!(rename_ident); | ||
551 | check( | 612 | check( |
552 | "k", | 613 | "k", |
553 | r#" | 614 | r#" |
554 | fn main() { | 615 | fn main() { |
555 | let mut i = 1; | 616 | let mut i = 1; |
556 | let j = 1; | 617 | let j = 1; |
557 | i = i<|> + j; | 618 | i = i$0 + j; |
558 | 619 | ||
559 | { i = 0; } | 620 | { i = 0; } |
560 | 621 | ||
@@ -579,7 +640,7 @@ fn main() { | |||
579 | fn test_rename_unresolved_reference() { | 640 | fn test_rename_unresolved_reference() { |
580 | check( | 641 | check( |
581 | "new_name", | 642 | "new_name", |
582 | r#"fn main() { let _ = unresolved_ref<|>; }"#, | 643 | r#"fn main() { let _ = unresolved_ref$0; }"#, |
583 | "error: No references found at position", | 644 | "error: No references found at position", |
584 | ); | 645 | ); |
585 | } | 646 | } |
@@ -591,7 +652,7 @@ fn main() { | |||
591 | r#" | 652 | r#" |
592 | macro_rules! foo {($i:ident) => {$i} } | 653 | macro_rules! foo {($i:ident) => {$i} } |
593 | fn main() { | 654 | fn main() { |
594 | let a<|> = "test"; | 655 | let a$0 = "test"; |
595 | foo!(a); | 656 | foo!(a); |
596 | } | 657 | } |
597 | "#, | 658 | "#, |
@@ -613,7 +674,7 @@ fn main() { | |||
613 | macro_rules! foo {($i:ident) => {$i} } | 674 | macro_rules! foo {($i:ident) => {$i} } |
614 | fn main() { | 675 | fn main() { |
615 | let a = "test"; | 676 | let a = "test"; |
616 | foo!(a<|>); | 677 | foo!(a$0); |
617 | } | 678 | } |
618 | "#, | 679 | "#, |
619 | r#" | 680 | r#" |
@@ -634,7 +695,7 @@ fn main() { | |||
634 | macro_rules! define_fn {($id:ident) => { fn $id{} }} | 695 | macro_rules! define_fn {($id:ident) => { fn $id{} }} |
635 | define_fn!(foo); | 696 | define_fn!(foo); |
636 | fn main() { | 697 | fn main() { |
637 | fo<|>o(); | 698 | fo$0o(); |
638 | } | 699 | } |
639 | "#, | 700 | "#, |
640 | r#" | 701 | r#" |
@@ -653,7 +714,7 @@ fn main() { | |||
653 | "bar", | 714 | "bar", |
654 | r#" | 715 | r#" |
655 | macro_rules! define_fn {($id:ident) => { fn $id{} }} | 716 | macro_rules! define_fn {($id:ident) => { fn $id{} }} |
656 | define_fn!(fo<|>o); | 717 | define_fn!(fo$0o); |
657 | fn main() { | 718 | fn main() { |
658 | foo(); | 719 | foo(); |
659 | } | 720 | } |
@@ -670,17 +731,17 @@ fn main() { | |||
670 | 731 | ||
671 | #[test] | 732 | #[test] |
672 | fn test_rename_for_param_inside() { | 733 | fn test_rename_for_param_inside() { |
673 | check("j", r#"fn foo(i : u32) -> u32 { i<|> }"#, r#"fn foo(j : u32) -> u32 { j }"#); | 734 | check("j", r#"fn foo(i : u32) -> u32 { i$0 }"#, r#"fn foo(j : u32) -> u32 { j }"#); |
674 | } | 735 | } |
675 | 736 | ||
676 | #[test] | 737 | #[test] |
677 | fn test_rename_refs_for_fn_param() { | 738 | fn test_rename_refs_for_fn_param() { |
678 | check("j", r#"fn foo(i<|> : u32) -> u32 { i }"#, r#"fn foo(j : u32) -> u32 { j }"#); | 739 | check("j", r#"fn foo(i$0 : u32) -> u32 { i }"#, r#"fn foo(j : u32) -> u32 { j }"#); |
679 | } | 740 | } |
680 | 741 | ||
681 | #[test] | 742 | #[test] |
682 | fn test_rename_for_mut_param() { | 743 | fn test_rename_for_mut_param() { |
683 | check("j", r#"fn foo(mut i<|> : u32) -> u32 { i }"#, r#"fn foo(mut j : u32) -> u32 { j }"#); | 744 | check("j", r#"fn foo(mut i$0 : u32) -> u32 { i }"#, r#"fn foo(mut j : u32) -> u32 { j }"#); |
684 | } | 745 | } |
685 | 746 | ||
686 | #[test] | 747 | #[test] |
@@ -688,7 +749,7 @@ fn main() { | |||
688 | check( | 749 | check( |
689 | "j", | 750 | "j", |
690 | r#" | 751 | r#" |
691 | struct Foo { i<|>: i32 } | 752 | struct Foo { i$0: i32 } |
692 | 753 | ||
693 | impl Foo { | 754 | impl Foo { |
694 | fn new(i: i32) -> Self { | 755 | fn new(i: i32) -> Self { |
@@ -714,7 +775,7 @@ impl Foo { | |||
714 | check( | 775 | check( |
715 | "j", | 776 | "j", |
716 | r#" | 777 | r#" |
717 | struct Foo { i<|>: i32 } | 778 | struct Foo { i$0: i32 } |
718 | 779 | ||
719 | impl Foo { | 780 | impl Foo { |
720 | fn new(i: i32) -> Self { | 781 | fn new(i: i32) -> Self { |
@@ -743,7 +804,7 @@ impl Foo { | |||
743 | struct Foo { i: i32 } | 804 | struct Foo { i: i32 } |
744 | 805 | ||
745 | impl Foo { | 806 | impl Foo { |
746 | fn new(i<|>: i32) -> Self { | 807 | fn new(i$0: i32) -> Self { |
747 | Self { i } | 808 | Self { i } |
748 | } | 809 | } |
749 | } | 810 | } |
@@ -765,7 +826,7 @@ impl Foo { | |||
765 | check( | 826 | check( |
766 | "j", | 827 | "j", |
767 | r#" | 828 | r#" |
768 | struct Foo { i<|>: i32 } | 829 | struct Foo { i$0: i32 } |
769 | struct Bar { i: i32 } | 830 | struct Bar { i: i32 } |
770 | 831 | ||
771 | impl Bar { | 832 | impl Bar { |
@@ -794,7 +855,7 @@ impl Bar { | |||
794 | r#" | 855 | r#" |
795 | struct Foo { i: i32 } | 856 | struct Foo { i: i32 } |
796 | 857 | ||
797 | fn baz(i<|>: i32) -> Self { | 858 | fn baz(i$0: i32) -> Self { |
798 | let x = Foo { i }; | 859 | let x = Foo { i }; |
799 | { | 860 | { |
800 | let i = 0; | 861 | let i = 0; |
@@ -825,7 +886,7 @@ fn baz(j: i32) -> Self { | |||
825 | mod bar; | 886 | mod bar; |
826 | 887 | ||
827 | //- /bar.rs | 888 | //- /bar.rs |
828 | mod foo<|>; | 889 | mod foo$0; |
829 | 890 | ||
830 | //- /bar/foo.rs | 891 | //- /bar/foo.rs |
831 | // empty | 892 | // empty |
@@ -883,7 +944,7 @@ fn main() {} | |||
883 | pub struct FooContent; | 944 | pub struct FooContent; |
884 | 945 | ||
885 | //- /bar.rs | 946 | //- /bar.rs |
886 | use crate::foo<|>::FooContent; | 947 | use crate::foo$0::FooContent; |
887 | "#, | 948 | "#, |
888 | expect![[r#" | 949 | expect![[r#" |
889 | RangeInfo { | 950 | RangeInfo { |
@@ -943,9 +1004,9 @@ use crate::foo<|>::FooContent; | |||
943 | "foo2", | 1004 | "foo2", |
944 | r#" | 1005 | r#" |
945 | //- /lib.rs | 1006 | //- /lib.rs |
946 | mod fo<|>o; | 1007 | mod fo$0o; |
947 | //- /foo/mod.rs | 1008 | //- /foo/mod.rs |
948 | // emtpy | 1009 | // empty |
949 | "#, | 1010 | "#, |
950 | expect![[r#" | 1011 | expect![[r#" |
951 | RangeInfo { | 1012 | RangeInfo { |
@@ -992,10 +1053,10 @@ mod fo<|>o; | |||
992 | "bar", | 1053 | "bar", |
993 | r#" | 1054 | r#" |
994 | //- /lib.rs | 1055 | //- /lib.rs |
995 | mod outer { mod fo<|>o; } | 1056 | mod outer { mod fo$0o; } |
996 | 1057 | ||
997 | //- /outer/foo.rs | 1058 | //- /outer/foo.rs |
998 | // emtpy | 1059 | // empty |
999 | "#, | 1060 | "#, |
1000 | expect![[r#" | 1061 | expect![[r#" |
1001 | RangeInfo { | 1062 | RangeInfo { |
@@ -1041,7 +1102,7 @@ mod outer { mod fo<|>o; } | |||
1041 | check( | 1102 | check( |
1042 | "baz", | 1103 | "baz", |
1043 | r#" | 1104 | r#" |
1044 | mod <|>foo { pub fn bar() {} } | 1105 | mod $0foo { pub fn bar() {} } |
1045 | 1106 | ||
1046 | fn main() { foo::bar(); } | 1107 | fn main() { foo::bar(); } |
1047 | "#, | 1108 | "#, |
@@ -1065,7 +1126,7 @@ fn f() { | |||
1065 | } | 1126 | } |
1066 | 1127 | ||
1067 | //- /bar.rs | 1128 | //- /bar.rs |
1068 | pub mod foo<|>; | 1129 | pub mod foo$0; |
1069 | 1130 | ||
1070 | //- /bar/foo.rs | 1131 | //- /bar/foo.rs |
1071 | // pub fn fun() {} | 1132 | // pub fn fun() {} |
@@ -1128,7 +1189,7 @@ pub mod foo<|>; | |||
1128 | "Baz", | 1189 | "Baz", |
1129 | r#" | 1190 | r#" |
1130 | mod foo { | 1191 | mod foo { |
1131 | pub enum Foo { Bar<|> } | 1192 | pub enum Foo { Bar$0 } |
1132 | } | 1193 | } |
1133 | 1194 | ||
1134 | fn func(f: foo::Foo) { | 1195 | fn func(f: foo::Foo) { |
@@ -1157,7 +1218,7 @@ fn func(f: foo::Foo) { | |||
1157 | "baz", | 1218 | "baz", |
1158 | r#" | 1219 | r#" |
1159 | mod foo { | 1220 | mod foo { |
1160 | pub struct Foo { pub bar<|>: uint } | 1221 | pub struct Foo { pub bar$0: uint } |
1161 | } | 1222 | } |
1162 | 1223 | ||
1163 | fn foo(f: foo::Foo) { | 1224 | fn foo(f: foo::Foo) { |
@@ -1178,13 +1239,14 @@ fn foo(f: foo::Foo) { | |||
1178 | 1239 | ||
1179 | #[test] | 1240 | #[test] |
1180 | fn test_parameter_to_self() { | 1241 | fn test_parameter_to_self() { |
1242 | mark::check!(rename_to_self); | ||
1181 | check( | 1243 | check( |
1182 | "self", | 1244 | "self", |
1183 | r#" | 1245 | r#" |
1184 | struct Foo { i: i32 } | 1246 | struct Foo { i: i32 } |
1185 | 1247 | ||
1186 | impl Foo { | 1248 | impl Foo { |
1187 | fn f(foo<|>: &mut Foo) -> i32 { | 1249 | fn f(foo$0: &mut Foo) -> i32 { |
1188 | foo.i | 1250 | foo.i |
1189 | } | 1251 | } |
1190 | } | 1252 | } |
@@ -1205,7 +1267,7 @@ impl Foo { | |||
1205 | struct Foo { i: i32 } | 1267 | struct Foo { i: i32 } |
1206 | 1268 | ||
1207 | impl Foo { | 1269 | impl Foo { |
1208 | fn f(foo<|>: Foo) -> i32 { | 1270 | fn f(foo$0: Foo) -> i32 { |
1209 | foo.i | 1271 | foo.i |
1210 | } | 1272 | } |
1211 | } | 1273 | } |
@@ -1229,7 +1291,7 @@ impl Foo { | |||
1229 | r#" | 1291 | r#" |
1230 | struct Foo { i: i32 } | 1292 | struct Foo { i: i32 } |
1231 | 1293 | ||
1232 | fn f(foo<|>: &mut Foo) -> i32 { | 1294 | fn f(foo$0: &mut Foo) -> i32 { |
1233 | foo.i | 1295 | foo.i |
1234 | } | 1296 | } |
1235 | "#, | 1297 | "#, |
@@ -1242,7 +1304,7 @@ struct Foo { i: i32 } | |||
1242 | struct Bar; | 1304 | struct Bar; |
1243 | 1305 | ||
1244 | impl Bar { | 1306 | impl Bar { |
1245 | fn f(foo<|>: &mut Foo) -> i32 { | 1307 | fn f(foo$0: &mut Foo) -> i32 { |
1246 | foo.i | 1308 | foo.i |
1247 | } | 1309 | } |
1248 | } | 1310 | } |
@@ -1258,7 +1320,7 @@ impl Bar { | |||
1258 | r#" | 1320 | r#" |
1259 | struct Foo { i: i32 } | 1321 | struct Foo { i: i32 } |
1260 | impl Foo { | 1322 | impl Foo { |
1261 | fn f(x: (), foo<|>: &mut Foo) -> i32 { | 1323 | fn f(x: (), foo$0: &mut Foo) -> i32 { |
1262 | foo.i | 1324 | foo.i |
1263 | } | 1325 | } |
1264 | } | 1326 | } |
@@ -1274,7 +1336,7 @@ impl Foo { | |||
1274 | r#" | 1336 | r#" |
1275 | struct Foo { i: i32 } | 1337 | struct Foo { i: i32 } |
1276 | impl &Foo { | 1338 | impl &Foo { |
1277 | fn f(foo<|>: &Foo) -> i32 { | 1339 | fn f(foo$0: &Foo) -> i32 { |
1278 | foo.i | 1340 | foo.i |
1279 | } | 1341 | } |
1280 | } | 1342 | } |
@@ -1298,7 +1360,7 @@ impl &Foo { | |||
1298 | struct Foo { i: i32 } | 1360 | struct Foo { i: i32 } |
1299 | 1361 | ||
1300 | impl Foo { | 1362 | impl Foo { |
1301 | fn f(&mut <|>self) -> i32 { | 1363 | fn f(&mut $0self) -> i32 { |
1302 | self.i | 1364 | self.i |
1303 | } | 1365 | } |
1304 | } | 1366 | } |
@@ -1323,7 +1385,7 @@ impl Foo { | |||
1323 | struct Foo { i: i32 } | 1385 | struct Foo { i: i32 } |
1324 | 1386 | ||
1325 | impl Foo { | 1387 | impl Foo { |
1326 | fn f(<|>self) -> i32 { | 1388 | fn f($0self) -> i32 { |
1327 | self.i | 1389 | self.i |
1328 | } | 1390 | } |
1329 | } | 1391 | } |
@@ -1350,7 +1412,7 @@ struct Foo { i: i32 } | |||
1350 | impl Foo { | 1412 | impl Foo { |
1351 | fn f(&self) -> i32 { | 1413 | fn f(&self) -> i32 { |
1352 | let self_var = 1; | 1414 | let self_var = 1; |
1353 | self<|>.i | 1415 | self$0.i |
1354 | } | 1416 | } |
1355 | } | 1417 | } |
1356 | "#, | 1418 | "#, |
@@ -1373,7 +1435,7 @@ impl Foo { | |||
1373 | check( | 1435 | check( |
1374 | "bar", | 1436 | "bar", |
1375 | r#" | 1437 | r#" |
1376 | struct Foo { i<|>: i32 } | 1438 | struct Foo { i$0: i32 } |
1377 | 1439 | ||
1378 | fn foo(bar: i32) -> Foo { | 1440 | fn foo(bar: i32) -> Foo { |
1379 | Foo { i: bar } | 1441 | Foo { i: bar } |
@@ -1394,7 +1456,7 @@ fn foo(bar: i32) -> Foo { | |||
1394 | check( | 1456 | check( |
1395 | "baz", | 1457 | "baz", |
1396 | r#" | 1458 | r#" |
1397 | struct Foo { i<|>: i32 } | 1459 | struct Foo { i$0: i32 } |
1398 | 1460 | ||
1399 | fn foo(foo: Foo) { | 1461 | fn foo(foo: Foo) { |
1400 | let Foo { i: baz } = foo; | 1462 | let Foo { i: baz } = foo; |
@@ -1433,7 +1495,7 @@ struct Foo { | |||
1433 | 1495 | ||
1434 | fn foo(foo: Foo) { | 1496 | fn foo(foo: Foo) { |
1435 | let Foo { i: b } = foo; | 1497 | let Foo { i: b } = foo; |
1436 | let _ = b<|>; | 1498 | let _ = b$0; |
1437 | } | 1499 | } |
1438 | "#, | 1500 | "#, |
1439 | expected_fixture, | 1501 | expected_fixture, |
@@ -1447,7 +1509,7 @@ struct Foo { | |||
1447 | 1509 | ||
1448 | fn foo(foo: Foo) { | 1510 | fn foo(foo: Foo) { |
1449 | let Foo { i } = foo; | 1511 | let Foo { i } = foo; |
1450 | let _ = i<|>; | 1512 | let _ = i$0; |
1451 | } | 1513 | } |
1452 | "#, | 1514 | "#, |
1453 | expected_fixture, | 1515 | expected_fixture, |
@@ -1464,7 +1526,7 @@ struct Foo { | |||
1464 | } | 1526 | } |
1465 | 1527 | ||
1466 | fn foo(Foo { i }: foo) -> i32 { | 1528 | fn foo(Foo { i }: foo) -> i32 { |
1467 | i<|> | 1529 | i$0 |
1468 | } | 1530 | } |
1469 | "#, | 1531 | "#, |
1470 | r#" | 1532 | r#" |
@@ -1481,6 +1543,7 @@ fn foo(Foo { i: bar }: foo) -> i32 { | |||
1481 | 1543 | ||
1482 | #[test] | 1544 | #[test] |
1483 | fn test_rename_lifetimes() { | 1545 | fn test_rename_lifetimes() { |
1546 | mark::check!(rename_lifetime); | ||
1484 | check( | 1547 | check( |
1485 | "'yeeee", | 1548 | "'yeeee", |
1486 | r#" | 1549 | r#" |
@@ -1488,7 +1551,7 @@ trait Foo<'a> { | |||
1488 | fn foo() -> &'a (); | 1551 | fn foo() -> &'a (); |
1489 | } | 1552 | } |
1490 | impl<'a> Foo<'a> for &'a () { | 1553 | impl<'a> Foo<'a> for &'a () { |
1491 | fn foo() -> &'a<|> () { | 1554 | fn foo() -> &'a$0 () { |
1492 | unimplemented!() | 1555 | unimplemented!() |
1493 | } | 1556 | } |
1494 | } | 1557 | } |
@@ -1520,7 +1583,7 @@ fn main() { | |||
1520 | let test_variable = CustomOption::Some(22); | 1583 | let test_variable = CustomOption::Some(22); |
1521 | 1584 | ||
1522 | match test_variable { | 1585 | match test_variable { |
1523 | CustomOption::Some(foo<|>) if foo == 11 => {} | 1586 | CustomOption::Some(foo$0) if foo == 11 => {} |
1524 | _ => (), | 1587 | _ => (), |
1525 | } | 1588 | } |
1526 | }"#, | 1589 | }"#, |
@@ -1549,7 +1612,7 @@ fn main() { | |||
1549 | fn foo<'a>() -> &'a () { | 1612 | fn foo<'a>() -> &'a () { |
1550 | 'a: { | 1613 | 'a: { |
1551 | 'b: loop { | 1614 | 'b: loop { |
1552 | break 'a<|>; | 1615 | break 'a$0; |
1553 | } | 1616 | } |
1554 | } | 1617 | } |
1555 | } | 1618 | } |
@@ -1565,4 +1628,24 @@ fn foo<'a>() -> &'a () { | |||
1565 | "#, | 1628 | "#, |
1566 | ) | 1629 | ) |
1567 | } | 1630 | } |
1631 | |||
1632 | #[test] | ||
1633 | fn test_self_to_self() { | ||
1634 | mark::check!(rename_self_to_self); | ||
1635 | check( | ||
1636 | "self", | ||
1637 | r#" | ||
1638 | struct Foo; | ||
1639 | impl Foo { | ||
1640 | fn foo(self$0) {} | ||
1641 | } | ||
1642 | "#, | ||
1643 | r#" | ||
1644 | struct Foo; | ||
1645 | impl Foo { | ||
1646 | fn foo(self) {} | ||
1647 | } | ||
1648 | "#, | ||
1649 | ) | ||
1650 | } | ||
1568 | } | 1651 | } |
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index c893afc7c..f5ee7de86 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs | |||
@@ -2,11 +2,11 @@ use std::fmt; | |||
2 | 2 | ||
3 | use assists::utils::test_related_attribute; | 3 | use assists::utils::test_related_attribute; |
4 | use cfg::CfgExpr; | 4 | use cfg::CfgExpr; |
5 | use hir::{AsAssocItem, HasAttrs, InFile, Semantics}; | 5 | use hir::{AsAssocItem, HasAttrs, HasSource, Semantics}; |
6 | use ide_db::RootDatabase; | 6 | use ide_db::{defs::Definition, RootDatabase}; |
7 | use itertools::Itertools; | 7 | use itertools::Itertools; |
8 | use syntax::{ | 8 | use syntax::{ |
9 | ast::{self, AstNode, AttrsOwner, ModuleItemOwner, NameOwner}, | 9 | ast::{self, AstNode, AttrsOwner, ModuleItemOwner}, |
10 | match_ast, SyntaxNode, | 10 | match_ast, SyntaxNode, |
11 | }; | 11 | }; |
12 | 12 | ||
@@ -96,41 +96,45 @@ impl Runnable { | |||
96 | pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> { | 96 | pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> { |
97 | let sema = Semantics::new(db); | 97 | let sema = Semantics::new(db); |
98 | let source_file = sema.parse(file_id); | 98 | let source_file = sema.parse(file_id); |
99 | source_file.syntax().descendants().filter_map(|i| runnable(&sema, i, file_id)).collect() | 99 | source_file |
100 | } | 100 | .syntax() |
101 | 101 | .descendants() | |
102 | pub(crate) fn runnable( | 102 | .filter_map(|item| { |
103 | sema: &Semantics<RootDatabase>, | 103 | let runnable = match_ast! { |
104 | item: SyntaxNode, | 104 | match item { |
105 | file_id: FileId, | 105 | ast::Fn(func) => { |
106 | ) -> Option<Runnable> { | 106 | let def = sema.to_def(&func)?; |
107 | let runnable_item = match_ast! { | 107 | runnable_fn(&sema, def) |
108 | match (item.clone()) { | 108 | }, |
109 | ast::Fn(it) => runnable_fn(sema, it, file_id), | 109 | ast::Module(it) => runnable_mod(&sema, it), |
110 | ast::Module(it) => runnable_mod(sema, it), | 110 | _ => None, |
111 | _ => None, | 111 | } |
112 | } | 112 | }; |
113 | }; | 113 | runnable.or_else(|| match doc_owner_to_def(&sema, item)? { |
114 | runnable_item.or_else(|| runnable_doctest(sema, item)) | 114 | Definition::ModuleDef(def) => module_def_doctest(&sema, def), |
115 | _ => None, | ||
116 | }) | ||
117 | }) | ||
118 | .collect() | ||
115 | } | 119 | } |
116 | 120 | ||
117 | fn runnable_fn(sema: &Semantics<RootDatabase>, func: ast::Fn, file_id: FileId) -> Option<Runnable> { | 121 | pub(crate) fn runnable_fn(sema: &Semantics<RootDatabase>, def: hir::Function) -> Option<Runnable> { |
118 | let def = sema.to_def(&func)?; | 122 | let func = def.source(sema.db)?; |
119 | let name_string = func.name()?.text().to_string(); | 123 | let name_string = def.name(sema.db).to_string(); |
120 | 124 | ||
121 | let kind = if name_string == "main" { | 125 | let kind = if name_string == "main" { |
122 | RunnableKind::Bin | 126 | RunnableKind::Bin |
123 | } else { | 127 | } else { |
124 | let canonical_path = sema.to_def(&func).and_then(|def| { | 128 | let canonical_path = { |
125 | let def: hir::ModuleDef = def.into(); | 129 | let def: hir::ModuleDef = def.into(); |
126 | def.canonical_path(sema.db) | 130 | def.canonical_path(sema.db) |
127 | }); | 131 | }; |
128 | let test_id = canonical_path.map(TestId::Path).unwrap_or(TestId::Name(name_string)); | 132 | let test_id = canonical_path.map(TestId::Path).unwrap_or(TestId::Name(name_string)); |
129 | 133 | ||
130 | if test_related_attribute(&func).is_some() { | 134 | if test_related_attribute(&func.value).is_some() { |
131 | let attr = TestAttr::from_fn(&func); | 135 | let attr = TestAttr::from_fn(&func.value); |
132 | RunnableKind::Test { test_id, attr } | 136 | RunnableKind::Test { test_id, attr } |
133 | } else if func.has_atom_attr("bench") { | 137 | } else if func.value.has_atom_attr("bench") { |
134 | RunnableKind::Bench { test_id } | 138 | RunnableKind::Bench { test_id } |
135 | } else { | 139 | } else { |
136 | return None; | 140 | return None; |
@@ -139,27 +143,56 @@ fn runnable_fn(sema: &Semantics<RootDatabase>, func: ast::Fn, file_id: FileId) - | |||
139 | 143 | ||
140 | let nav = NavigationTarget::from_named( | 144 | let nav = NavigationTarget::from_named( |
141 | sema.db, | 145 | sema.db, |
142 | InFile::new(file_id.into(), &func), | 146 | func.as_ref().map(|it| it as &dyn ast::NameOwner), |
143 | SymbolKind::Function, | 147 | SymbolKind::Function, |
144 | ); | 148 | ); |
145 | let cfg = def.attrs(sema.db).cfg(); | 149 | let cfg = def.attrs(sema.db).cfg(); |
146 | Some(Runnable { nav, kind, cfg }) | 150 | Some(Runnable { nav, kind, cfg }) |
147 | } | 151 | } |
148 | 152 | ||
149 | fn runnable_doctest(sema: &Semantics<RootDatabase>, item: SyntaxNode) -> Option<Runnable> { | 153 | pub(crate) fn runnable_mod( |
150 | match_ast! { | 154 | sema: &Semantics<RootDatabase>, |
155 | module: ast::Module, | ||
156 | ) -> Option<Runnable> { | ||
157 | if !has_test_function_or_multiple_test_submodules(&module) { | ||
158 | return None; | ||
159 | } | ||
160 | let module_def = sema.to_def(&module)?; | ||
161 | |||
162 | let path = module_def | ||
163 | .path_to_root(sema.db) | ||
164 | .into_iter() | ||
165 | .rev() | ||
166 | .filter_map(|it| it.name(sema.db)) | ||
167 | .join("::"); | ||
168 | |||
169 | let def = sema.to_def(&module)?; | ||
170 | let attrs = def.attrs(sema.db); | ||
171 | let cfg = attrs.cfg(); | ||
172 | let nav = module_def.to_nav(sema.db); | ||
173 | Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg }) | ||
174 | } | ||
175 | |||
176 | // FIXME: figure out a proper API here. | ||
177 | pub(crate) fn doc_owner_to_def( | ||
178 | sema: &Semantics<RootDatabase>, | ||
179 | item: SyntaxNode, | ||
180 | ) -> Option<Definition> { | ||
181 | let res: hir::ModuleDef = match_ast! { | ||
151 | match item { | 182 | match item { |
152 | ast::Fn(it) => module_def_doctest(sema, sema.to_def(&it)?.into()), | 183 | ast::SourceFile(it) => sema.scope(&item).module()?.into(), |
153 | ast::Struct(it) => module_def_doctest(sema, sema.to_def(&it)?.into()), | 184 | ast::Fn(it) => sema.to_def(&it)?.into(), |
154 | ast::Enum(it) => module_def_doctest(sema, sema.to_def(&it)?.into()), | 185 | ast::Struct(it) => sema.to_def(&it)?.into(), |
155 | ast::Union(it) => module_def_doctest(sema, sema.to_def(&it)?.into()), | 186 | ast::Enum(it) => sema.to_def(&it)?.into(), |
156 | ast::Trait(it) => module_def_doctest(sema, sema.to_def(&it)?.into()), | 187 | ast::Union(it) => sema.to_def(&it)?.into(), |
157 | ast::Const(it) => module_def_doctest(sema, sema.to_def(&it)?.into()), | 188 | ast::Trait(it) => sema.to_def(&it)?.into(), |
158 | ast::Static(it) => module_def_doctest(sema, sema.to_def(&it)?.into()), | 189 | ast::Const(it) => sema.to_def(&it)?.into(), |
159 | ast::TypeAlias(it) => module_def_doctest(sema, sema.to_def(&it)?.into()), | 190 | ast::Static(it) => sema.to_def(&it)?.into(), |
160 | _ => None, | 191 | ast::TypeAlias(it) => sema.to_def(&it)?.into(), |
192 | _ => return None, | ||
161 | } | 193 | } |
162 | } | 194 | }; |
195 | Some(Definition::ModuleDef(res)) | ||
163 | } | 196 | } |
164 | 197 | ||
165 | fn module_def_doctest(sema: &Semantics<RootDatabase>, def: hir::ModuleDef) -> Option<Runnable> { | 198 | fn module_def_doctest(sema: &Semantics<RootDatabase>, def: hir::ModuleDef) -> Option<Runnable> { |
@@ -254,26 +287,6 @@ fn has_runnable_doc_test(attrs: &hir::Attrs) -> bool { | |||
254 | }) | 287 | }) |
255 | } | 288 | } |
256 | 289 | ||
257 | fn runnable_mod(sema: &Semantics<RootDatabase>, module: ast::Module) -> Option<Runnable> { | ||
258 | if !has_test_function_or_multiple_test_submodules(&module) { | ||
259 | return None; | ||
260 | } | ||
261 | let module_def = sema.to_def(&module)?; | ||
262 | |||
263 | let path = module_def | ||
264 | .path_to_root(sema.db) | ||
265 | .into_iter() | ||
266 | .rev() | ||
267 | .filter_map(|it| it.name(sema.db)) | ||
268 | .join("::"); | ||
269 | |||
270 | let def = sema.to_def(&module)?; | ||
271 | let attrs = def.attrs(sema.db); | ||
272 | let cfg = attrs.cfg(); | ||
273 | let nav = module_def.to_nav(sema.db); | ||
274 | Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg }) | ||
275 | } | ||
276 | |||
277 | // We could create runnables for modules with number_of_test_submodules > 0, | 290 | // We could create runnables for modules with number_of_test_submodules > 0, |
278 | // but that bloats the runnables for no real benefit, since all tests can be run by the submodule already | 291 | // but that bloats the runnables for no real benefit, since all tests can be run by the submodule already |
279 | fn has_test_function_or_multiple_test_submodules(module: &ast::Module) -> bool { | 292 | fn has_test_function_or_multiple_test_submodules(module: &ast::Module) -> bool { |
@@ -330,7 +343,7 @@ mod tests { | |||
330 | check( | 343 | check( |
331 | r#" | 344 | r#" |
332 | //- /lib.rs | 345 | //- /lib.rs |
333 | <|> | 346 | $0 |
334 | fn main() {} | 347 | fn main() {} |
335 | 348 | ||
336 | #[test] | 349 | #[test] |
@@ -426,7 +439,7 @@ fn bench() {} | |||
426 | check( | 439 | check( |
427 | r#" | 440 | r#" |
428 | //- /lib.rs | 441 | //- /lib.rs |
429 | <|> | 442 | $0 |
430 | fn main() {} | 443 | fn main() {} |
431 | 444 | ||
432 | /// ``` | 445 | /// ``` |
@@ -574,7 +587,7 @@ struct StructWithRunnable(String); | |||
574 | check( | 587 | check( |
575 | r#" | 588 | r#" |
576 | //- /lib.rs | 589 | //- /lib.rs |
577 | <|> | 590 | $0 |
578 | fn main() {} | 591 | fn main() {} |
579 | 592 | ||
580 | struct Data; | 593 | struct Data; |
@@ -626,7 +639,7 @@ impl Data { | |||
626 | check( | 639 | check( |
627 | r#" | 640 | r#" |
628 | //- /lib.rs | 641 | //- /lib.rs |
629 | <|> | 642 | $0 |
630 | mod test_mod { | 643 | mod test_mod { |
631 | #[test] | 644 | #[test] |
632 | fn test_foo1() {} | 645 | fn test_foo1() {} |
@@ -680,7 +693,7 @@ mod test_mod { | |||
680 | check( | 693 | check( |
681 | r#" | 694 | r#" |
682 | //- /lib.rs | 695 | //- /lib.rs |
683 | <|> | 696 | $0 |
684 | mod root_tests { | 697 | mod root_tests { |
685 | mod nested_tests_0 { | 698 | mod nested_tests_0 { |
686 | mod nested_tests_1 { | 699 | mod nested_tests_1 { |
@@ -820,7 +833,7 @@ mod root_tests { | |||
820 | check( | 833 | check( |
821 | r#" | 834 | r#" |
822 | //- /lib.rs crate:foo cfg:feature=foo | 835 | //- /lib.rs crate:foo cfg:feature=foo |
823 | <|> | 836 | $0 |
824 | #[test] | 837 | #[test] |
825 | #[cfg(feature = "foo")] | 838 | #[cfg(feature = "foo")] |
826 | fn test_foo1() {} | 839 | fn test_foo1() {} |
@@ -865,7 +878,7 @@ fn test_foo1() {} | |||
865 | check( | 878 | check( |
866 | r#" | 879 | r#" |
867 | //- /lib.rs crate:foo cfg:feature=foo,feature=bar | 880 | //- /lib.rs crate:foo cfg:feature=foo,feature=bar |
868 | <|> | 881 | $0 |
869 | #[test] | 882 | #[test] |
870 | #[cfg(all(feature = "foo", feature = "bar"))] | 883 | #[cfg(all(feature = "foo", feature = "bar"))] |
871 | fn test_foo1() {} | 884 | fn test_foo1() {} |
@@ -920,7 +933,7 @@ fn test_foo1() {} | |||
920 | check( | 933 | check( |
921 | r#" | 934 | r#" |
922 | //- /lib.rs | 935 | //- /lib.rs |
923 | <|> | 936 | $0 |
924 | mod test_mod { | 937 | mod test_mod { |
925 | fn foo1() {} | 938 | fn foo1() {} |
926 | } | 939 | } |
@@ -939,7 +952,7 @@ mod test_mod { | |||
939 | //- /lib.rs | 952 | //- /lib.rs |
940 | mod foo; | 953 | mod foo; |
941 | //- /foo.rs | 954 | //- /foo.rs |
942 | struct Foo;<|> | 955 | struct Foo;$0 |
943 | impl Foo { | 956 | impl Foo { |
944 | /// ``` | 957 | /// ``` |
945 | /// let x = 5; | 958 | /// let x = 5; |
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index ba0085244..f2d4da78d 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs | |||
@@ -1,35 +1,39 @@ | |||
1 | pub(crate) mod tags; | ||
2 | |||
3 | mod highlights; | ||
4 | mod injector; | ||
5 | |||
6 | mod highlight; | ||
1 | mod format; | 7 | mod format; |
2 | mod html; | ||
3 | mod injection; | ||
4 | mod macro_rules; | 8 | mod macro_rules; |
5 | pub(crate) mod tags; | 9 | mod inject; |
10 | |||
11 | mod html; | ||
6 | #[cfg(test)] | 12 | #[cfg(test)] |
7 | mod tests; | 13 | mod tests; |
8 | 14 | ||
9 | use hir::{AsAssocItem, Local, Name, Semantics, VariantDef}; | 15 | use hir::{Name, Semantics}; |
10 | use ide_db::{ | 16 | use ide_db::RootDatabase; |
11 | defs::{Definition, NameClass, NameRefClass}, | ||
12 | RootDatabase, | ||
13 | }; | ||
14 | use rustc_hash::FxHashMap; | 17 | use rustc_hash::FxHashMap; |
15 | use syntax::{ | 18 | use syntax::{ |
16 | ast::{self, HasFormatSpecifier}, | 19 | ast::{self, HasFormatSpecifier}, |
17 | AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, | 20 | AstNode, AstToken, Direction, NodeOrToken, |
18 | SyntaxKind::{self, *}, | 21 | SyntaxKind::*, |
19 | SyntaxNode, SyntaxToken, TextRange, WalkEvent, T, | 22 | SyntaxNode, TextRange, WalkEvent, T, |
20 | }; | 23 | }; |
21 | 24 | ||
22 | use crate::{ | 25 | use crate::{ |
23 | syntax_highlighting::{ | 26 | syntax_highlighting::{ |
24 | format::FormatStringHighlighter, macro_rules::MacroRulesHighlighter, tags::Highlight, | 27 | format::highlight_format_string, highlights::Highlights, |
28 | macro_rules::MacroRulesHighlighter, tags::Highlight, | ||
25 | }, | 29 | }, |
26 | FileId, HighlightModifier, HighlightTag, SymbolKind, | 30 | FileId, HlMod, HlTag, SymbolKind, |
27 | }; | 31 | }; |
28 | 32 | ||
29 | pub(crate) use html::highlight_as_html; | 33 | pub(crate) use html::highlight_as_html; |
30 | 34 | ||
31 | #[derive(Debug, Clone)] | 35 | #[derive(Debug, Clone, Copy)] |
32 | pub struct HighlightedRange { | 36 | pub struct HlRange { |
33 | pub range: TextRange, | 37 | pub range: TextRange, |
34 | pub highlight: Highlight, | 38 | pub highlight: Highlight, |
35 | pub binding_hash: Option<u64>, | 39 | pub binding_hash: Option<u64>, |
@@ -49,7 +53,7 @@ pub(crate) fn highlight( | |||
49 | file_id: FileId, | 53 | file_id: FileId, |
50 | range_to_highlight: Option<TextRange>, | 54 | range_to_highlight: Option<TextRange>, |
51 | syntactic_name_ref_highlighting: bool, | 55 | syntactic_name_ref_highlighting: bool, |
52 | ) -> Vec<HighlightedRange> { | 56 | ) -> Vec<HlRange> { |
53 | let _p = profile::span("highlight"); | 57 | let _p = profile::span("highlight"); |
54 | let sema = Semantics::new(db); | 58 | let sema = Semantics::new(db); |
55 | 59 | ||
@@ -68,28 +72,30 @@ pub(crate) fn highlight( | |||
68 | } | 72 | } |
69 | }; | 73 | }; |
70 | 74 | ||
75 | let mut hl = highlights::Highlights::new(range_to_highlight); | ||
76 | traverse(&mut hl, &sema, &root, range_to_highlight, syntactic_name_ref_highlighting); | ||
77 | hl.to_vec() | ||
78 | } | ||
79 | |||
80 | fn traverse( | ||
81 | hl: &mut Highlights, | ||
82 | sema: &Semantics<RootDatabase>, | ||
83 | root: &SyntaxNode, | ||
84 | range_to_highlight: TextRange, | ||
85 | syntactic_name_ref_highlighting: bool, | ||
86 | ) { | ||
71 | let mut bindings_shadow_count: FxHashMap<Name, u32> = FxHashMap::default(); | 87 | let mut bindings_shadow_count: FxHashMap<Name, u32> = FxHashMap::default(); |
72 | // We use a stack for the DFS traversal below. | ||
73 | // When we leave a node, the we use it to flatten the highlighted ranges. | ||
74 | let mut stack = HighlightedRangeStack::new(); | ||
75 | 88 | ||
76 | let mut current_macro_call: Option<ast::MacroCall> = None; | 89 | let mut current_macro_call: Option<ast::MacroCall> = None; |
77 | let mut current_macro_rules: Option<ast::MacroRules> = None; | 90 | let mut current_macro_rules: Option<ast::MacroRules> = None; |
78 | let mut format_string_highlighter = FormatStringHighlighter::default(); | ||
79 | let mut macro_rules_highlighter = MacroRulesHighlighter::default(); | 91 | let mut macro_rules_highlighter = MacroRulesHighlighter::default(); |
80 | let mut inside_attribute = false; | 92 | let mut inside_attribute = false; |
81 | 93 | ||
82 | // Walk all nodes, keeping track of whether we are inside a macro or not. | 94 | // Walk all nodes, keeping track of whether we are inside a macro or not. |
83 | // If in macro, expand it first and highlight the expanded code. | 95 | // If in macro, expand it first and highlight the expanded code. |
84 | for event in root.preorder_with_tokens() { | 96 | for event in root.preorder_with_tokens() { |
85 | match &event { | ||
86 | WalkEvent::Enter(_) => stack.push(), | ||
87 | WalkEvent::Leave(_) => stack.pop(), | ||
88 | }; | ||
89 | |||
90 | let event_range = match &event { | 97 | let event_range = match &event { |
91 | WalkEvent::Enter(it) => it.text_range(), | 98 | WalkEvent::Enter(it) | WalkEvent::Leave(it) => it.text_range(), |
92 | WalkEvent::Leave(it) => it.text_range(), | ||
93 | }; | 99 | }; |
94 | 100 | ||
95 | // Element outside of the viewport, no need to highlight | 101 | // Element outside of the viewport, no need to highlight |
@@ -101,9 +107,9 @@ pub(crate) fn highlight( | |||
101 | match event.clone().map(|it| it.into_node().and_then(ast::MacroCall::cast)) { | 107 | match event.clone().map(|it| it.into_node().and_then(ast::MacroCall::cast)) { |
102 | WalkEvent::Enter(Some(mc)) => { | 108 | WalkEvent::Enter(Some(mc)) => { |
103 | if let Some(range) = macro_call_range(&mc) { | 109 | if let Some(range) = macro_call_range(&mc) { |
104 | stack.add(HighlightedRange { | 110 | hl.add(HlRange { |
105 | range, | 111 | range, |
106 | highlight: HighlightTag::Symbol(SymbolKind::Macro).into(), | 112 | highlight: HlTag::Symbol(SymbolKind::Macro).into(), |
107 | binding_hash: None, | 113 | binding_hash: None, |
108 | }); | 114 | }); |
109 | } | 115 | } |
@@ -113,7 +119,6 @@ pub(crate) fn highlight( | |||
113 | WalkEvent::Leave(Some(mc)) => { | 119 | WalkEvent::Leave(Some(mc)) => { |
114 | assert_eq!(current_macro_call, Some(mc)); | 120 | assert_eq!(current_macro_call, Some(mc)); |
115 | current_macro_call = None; | 121 | current_macro_call = None; |
116 | format_string_highlighter = FormatStringHighlighter::default(); | ||
117 | } | 122 | } |
118 | _ => (), | 123 | _ => (), |
119 | } | 124 | } |
@@ -131,33 +136,24 @@ pub(crate) fn highlight( | |||
131 | } | 136 | } |
132 | _ => (), | 137 | _ => (), |
133 | } | 138 | } |
134 | |||
135 | match &event { | 139 | match &event { |
136 | // Check for Rust code in documentation | ||
137 | WalkEvent::Leave(NodeOrToken::Node(node)) => { | ||
138 | if ast::Attr::can_cast(node.kind()) { | ||
139 | inside_attribute = false | ||
140 | } | ||
141 | if let Some((doctest, range_mapping, new_comments)) = | ||
142 | injection::extract_doc_comments(node) | ||
143 | { | ||
144 | injection::highlight_doc_comment( | ||
145 | doctest, | ||
146 | range_mapping, | ||
147 | new_comments, | ||
148 | &mut stack, | ||
149 | ); | ||
150 | } | ||
151 | } | ||
152 | WalkEvent::Enter(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => { | 140 | WalkEvent::Enter(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => { |
153 | inside_attribute = true | 141 | inside_attribute = true |
154 | } | 142 | } |
143 | WalkEvent::Leave(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => { | ||
144 | inside_attribute = false | ||
145 | } | ||
155 | _ => (), | 146 | _ => (), |
156 | } | 147 | } |
157 | 148 | ||
158 | let element = match event { | 149 | let element = match event { |
159 | WalkEvent::Enter(it) => it, | 150 | WalkEvent::Enter(it) => it, |
160 | WalkEvent::Leave(_) => continue, | 151 | WalkEvent::Leave(it) => { |
152 | if let Some(node) = it.as_node() { | ||
153 | inject::doc_comment(hl, node); | ||
154 | } | ||
155 | continue; | ||
156 | } | ||
161 | }; | 157 | }; |
162 | 158 | ||
163 | let range = element.text_range(); | 159 | let range = element.text_range(); |
@@ -177,8 +173,6 @@ pub(crate) fn highlight( | |||
177 | let token = sema.descend_into_macros(token.clone()); | 173 | let token = sema.descend_into_macros(token.clone()); |
178 | let parent = token.parent(); | 174 | let parent = token.parent(); |
179 | 175 | ||
180 | format_string_highlighter.check_for_format_string(&parent); | ||
181 | |||
182 | // We only care Name and Name_ref | 176 | // We only care Name and Name_ref |
183 | match (token.kind(), parent.kind()) { | 177 | match (token.kind(), parent.kind()) { |
184 | (IDENT, NAME) | (IDENT, NAME_REF) => parent.into(), | 178 | (IDENT, NAME) | (IDENT, NAME_REF) => parent.into(), |
@@ -191,213 +185,45 @@ pub(crate) fn highlight( | |||
191 | if let Some(token) = element.as_token().cloned().and_then(ast::String::cast) { | 185 | if let Some(token) = element.as_token().cloned().and_then(ast::String::cast) { |
192 | if token.is_raw() { | 186 | if token.is_raw() { |
193 | let expanded = element_to_highlight.as_token().unwrap().clone(); | 187 | let expanded = element_to_highlight.as_token().unwrap().clone(); |
194 | if injection::highlight_injection(&mut stack, &sema, token, expanded).is_some() { | 188 | if inject::ra_fixture(hl, &sema, token, expanded).is_some() { |
195 | continue; | 189 | continue; |
196 | } | 190 | } |
197 | } | 191 | } |
198 | } | 192 | } |
199 | 193 | ||
200 | if let Some((mut highlight, binding_hash)) = highlight_element( | 194 | if let Some(_) = macro_rules_highlighter.highlight(element_to_highlight.clone()) { |
195 | continue; | ||
196 | } | ||
197 | |||
198 | if let Some((mut highlight, binding_hash)) = highlight::element( | ||
201 | &sema, | 199 | &sema, |
202 | &mut bindings_shadow_count, | 200 | &mut bindings_shadow_count, |
203 | syntactic_name_ref_highlighting, | 201 | syntactic_name_ref_highlighting, |
204 | element_to_highlight.clone(), | 202 | element_to_highlight.clone(), |
205 | ) { | 203 | ) { |
206 | if inside_attribute { | 204 | if inside_attribute { |
207 | highlight = highlight | HighlightModifier::Attribute; | 205 | highlight = highlight | HlMod::Attribute; |
208 | } | ||
209 | |||
210 | if macro_rules_highlighter.highlight(element_to_highlight.clone()).is_none() { | ||
211 | stack.add(HighlightedRange { range, highlight, binding_hash }); | ||
212 | } | 206 | } |
213 | 207 | ||
214 | if let Some(string) = | 208 | hl.add(HlRange { range, highlight, binding_hash }); |
215 | element_to_highlight.as_token().cloned().and_then(ast::String::cast) | ||
216 | { | ||
217 | format_string_highlighter.highlight_format_string(&mut stack, &string, range); | ||
218 | // Highlight escape sequences | ||
219 | if let Some(char_ranges) = string.char_ranges() { | ||
220 | stack.push(); | ||
221 | for (piece_range, _) in char_ranges.iter().filter(|(_, char)| char.is_ok()) { | ||
222 | if string.text()[piece_range.start().into()..].starts_with('\\') { | ||
223 | stack.add(HighlightedRange { | ||
224 | range: piece_range + range.start(), | ||
225 | highlight: HighlightTag::EscapeSequence.into(), | ||
226 | binding_hash: None, | ||
227 | }); | ||
228 | } | ||
229 | } | ||
230 | stack.pop_and_inject(None); | ||
231 | } | ||
232 | } | ||
233 | } | 209 | } |
234 | } | ||
235 | |||
236 | stack.flattened() | ||
237 | } | ||
238 | |||
239 | #[derive(Debug)] | ||
240 | struct HighlightedRangeStack { | ||
241 | stack: Vec<Vec<HighlightedRange>>, | ||
242 | } | ||
243 | |||
244 | /// We use a stack to implement the flattening logic for the highlighted | ||
245 | /// syntax ranges. | ||
246 | impl HighlightedRangeStack { | ||
247 | fn new() -> Self { | ||
248 | Self { stack: vec![Vec::new()] } | ||
249 | } | ||
250 | |||
251 | fn push(&mut self) { | ||
252 | self.stack.push(Vec::new()); | ||
253 | } | ||
254 | |||
255 | /// Flattens the highlighted ranges. | ||
256 | /// | ||
257 | /// For example `#[cfg(feature = "foo")]` contains the nested ranges: | ||
258 | /// 1) parent-range: Attribute [0, 23) | ||
259 | /// 2) child-range: String [16, 21) | ||
260 | /// | ||
261 | /// The following code implements the flattening, for our example this results to: | ||
262 | /// `[Attribute [0, 16), String [16, 21), Attribute [21, 23)]` | ||
263 | fn pop(&mut self) { | ||
264 | let children = self.stack.pop().unwrap(); | ||
265 | let prev = self.stack.last_mut().unwrap(); | ||
266 | let needs_flattening = !children.is_empty() | ||
267 | && !prev.is_empty() | ||
268 | && prev.last().unwrap().range.contains_range(children.first().unwrap().range); | ||
269 | if !needs_flattening { | ||
270 | prev.extend(children); | ||
271 | } else { | ||
272 | let mut parent = prev.pop().unwrap(); | ||
273 | for ele in children { | ||
274 | assert!(parent.range.contains_range(ele.range)); | ||
275 | |||
276 | let cloned = Self::intersect(&mut parent, &ele); | ||
277 | if !parent.range.is_empty() { | ||
278 | prev.push(parent); | ||
279 | } | ||
280 | prev.push(ele); | ||
281 | parent = cloned; | ||
282 | } | ||
283 | if !parent.range.is_empty() { | ||
284 | prev.push(parent); | ||
285 | } | ||
286 | } | ||
287 | } | ||
288 | |||
289 | /// Intersects the `HighlightedRange` `parent` with `child`. | ||
290 | /// `parent` is mutated in place, becoming the range before `child`. | ||
291 | /// Returns the range (of the same type as `parent`) *after* `child`. | ||
292 | fn intersect(parent: &mut HighlightedRange, child: &HighlightedRange) -> HighlightedRange { | ||
293 | assert!(parent.range.contains_range(child.range)); | ||
294 | |||
295 | let mut cloned = parent.clone(); | ||
296 | parent.range = TextRange::new(parent.range.start(), child.range.start()); | ||
297 | cloned.range = TextRange::new(child.range.end(), cloned.range.end()); | ||
298 | 210 | ||
299 | cloned | 211 | if let Some(string) = element_to_highlight.as_token().cloned().and_then(ast::String::cast) { |
300 | } | 212 | highlight_format_string(hl, &string, range); |
301 | 213 | // Highlight escape sequences | |
302 | /// Remove the `HighlightRange` of `parent` that's currently covered by `child`. | 214 | if let Some(char_ranges) = string.char_ranges() { |
303 | fn intersect_partial(parent: &mut HighlightedRange, child: &HighlightedRange) { | 215 | for (piece_range, _) in char_ranges.iter().filter(|(_, char)| char.is_ok()) { |
304 | assert!( | 216 | if string.text()[piece_range.start().into()..].starts_with('\\') { |
305 | parent.range.start() <= child.range.start() | 217 | hl.add(HlRange { |
306 | && parent.range.end() >= child.range.start() | 218 | range: piece_range + range.start(), |
307 | && child.range.end() > parent.range.end() | 219 | highlight: HlTag::EscapeSequence.into(), |
308 | ); | 220 | binding_hash: None, |
309 | 221 | }); | |
310 | parent.range = TextRange::new(parent.range.start(), child.range.start()); | ||
311 | } | ||
312 | |||
313 | /// Similar to `pop`, but can modify arbitrary prior ranges (where `pop`) | ||
314 | /// can only modify the last range currently on the stack. | ||
315 | /// Can be used to do injections that span multiple ranges, like the | ||
316 | /// doctest injection below. | ||
317 | /// If `overwrite_parent` is non-optional, the highlighting of the parent range | ||
318 | /// is overwritten with the argument. | ||
319 | /// | ||
320 | /// Note that `pop` can be simulated by `pop_and_inject(false)` but the | ||
321 | /// latter is computationally more expensive. | ||
322 | fn pop_and_inject(&mut self, overwrite_parent: Option<Highlight>) { | ||
323 | let mut children = self.stack.pop().unwrap(); | ||
324 | let prev = self.stack.last_mut().unwrap(); | ||
325 | children.sort_by_key(|range| range.range.start()); | ||
326 | prev.sort_by_key(|range| range.range.start()); | ||
327 | |||
328 | for child in children { | ||
329 | if let Some(idx) = | ||
330 | prev.iter().position(|parent| parent.range.contains_range(child.range)) | ||
331 | { | ||
332 | if let Some(tag) = overwrite_parent { | ||
333 | prev[idx].highlight = tag; | ||
334 | } | ||
335 | |||
336 | let cloned = Self::intersect(&mut prev[idx], &child); | ||
337 | let insert_idx = if prev[idx].range.is_empty() { | ||
338 | prev.remove(idx); | ||
339 | idx | ||
340 | } else { | ||
341 | idx + 1 | ||
342 | }; | ||
343 | prev.insert(insert_idx, child); | ||
344 | if !cloned.range.is_empty() { | ||
345 | prev.insert(insert_idx + 1, cloned); | ||
346 | } | ||
347 | } else { | ||
348 | let maybe_idx = | ||
349 | prev.iter().position(|parent| parent.range.contains(child.range.start())); | ||
350 | match (overwrite_parent, maybe_idx) { | ||
351 | (Some(_), Some(idx)) => { | ||
352 | Self::intersect_partial(&mut prev[idx], &child); | ||
353 | let insert_idx = if prev[idx].range.is_empty() { | ||
354 | prev.remove(idx); | ||
355 | idx | ||
356 | } else { | ||
357 | idx + 1 | ||
358 | }; | ||
359 | prev.insert(insert_idx, child); | ||
360 | } | ||
361 | (_, None) => { | ||
362 | let idx = prev | ||
363 | .binary_search_by_key(&child.range.start(), |range| range.range.start()) | ||
364 | .unwrap_or_else(|x| x); | ||
365 | prev.insert(idx, child); | ||
366 | } | ||
367 | _ => { | ||
368 | unreachable!("child range should be completely contained in parent range"); | ||
369 | } | 222 | } |
370 | } | 223 | } |
371 | } | 224 | } |
372 | } | 225 | } |
373 | } | 226 | } |
374 | |||
375 | fn add(&mut self, range: HighlightedRange) { | ||
376 | self.stack | ||
377 | .last_mut() | ||
378 | .expect("during DFS traversal, the stack must not be empty") | ||
379 | .push(range) | ||
380 | } | ||
381 | |||
382 | fn flattened(mut self) -> Vec<HighlightedRange> { | ||
383 | assert_eq!( | ||
384 | self.stack.len(), | ||
385 | 1, | ||
386 | "after DFS traversal, the stack should only contain a single element" | ||
387 | ); | ||
388 | let mut res = self.stack.pop().unwrap(); | ||
389 | res.sort_by_key(|range| range.range.start()); | ||
390 | // Check that ranges are sorted and disjoint | ||
391 | for (left, right) in res.iter().zip(res.iter().skip(1)) { | ||
392 | assert!( | ||
393 | left.range.end() <= right.range.start(), | ||
394 | "left: {:#?}, right: {:#?}", | ||
395 | left, | ||
396 | right | ||
397 | ); | ||
398 | } | ||
399 | res | ||
400 | } | ||
401 | } | 227 | } |
402 | 228 | ||
403 | fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> { | 229 | fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> { |
@@ -415,524 +241,3 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> { | |||
415 | 241 | ||
416 | Some(TextRange::new(range_start, range_end)) | 242 | Some(TextRange::new(range_start, range_end)) |
417 | } | 243 | } |
418 | |||
419 | /// Returns true if the parent nodes of `node` all match the `SyntaxKind`s in `kinds` exactly. | ||
420 | fn parents_match(mut node: NodeOrToken<SyntaxNode, SyntaxToken>, mut kinds: &[SyntaxKind]) -> bool { | ||
421 | while let (Some(parent), [kind, rest @ ..]) = (&node.parent(), kinds) { | ||
422 | if parent.kind() != *kind { | ||
423 | return false; | ||
424 | } | ||
425 | |||
426 | // FIXME: Would be nice to get parent out of the match, but binding by-move and by-value | ||
427 | // in the same pattern is unstable: rust-lang/rust#68354. | ||
428 | node = node.parent().unwrap().into(); | ||
429 | kinds = rest; | ||
430 | } | ||
431 | |||
432 | // Only true if we matched all expected kinds | ||
433 | kinds.len() == 0 | ||
434 | } | ||
435 | |||
436 | fn is_consumed_lvalue( | ||
437 | node: NodeOrToken<SyntaxNode, SyntaxToken>, | ||
438 | local: &Local, | ||
439 | db: &RootDatabase, | ||
440 | ) -> bool { | ||
441 | // When lvalues are passed as arguments and they're not Copy, then mark them as Consuming. | ||
442 | parents_match(node, &[PATH_SEGMENT, PATH, PATH_EXPR, ARG_LIST]) && !local.ty(db).is_copy(db) | ||
443 | } | ||
444 | |||
445 | fn highlight_element( | ||
446 | sema: &Semantics<RootDatabase>, | ||
447 | bindings_shadow_count: &mut FxHashMap<Name, u32>, | ||
448 | syntactic_name_ref_highlighting: bool, | ||
449 | element: SyntaxElement, | ||
450 | ) -> Option<(Highlight, Option<u64>)> { | ||
451 | let db = sema.db; | ||
452 | let mut binding_hash = None; | ||
453 | let highlight: Highlight = match element.kind() { | ||
454 | FN => { | ||
455 | bindings_shadow_count.clear(); | ||
456 | return None; | ||
457 | } | ||
458 | |||
459 | // Highlight definitions depending on the "type" of the definition. | ||
460 | NAME => { | ||
461 | let name = element.into_node().and_then(ast::Name::cast).unwrap(); | ||
462 | let name_kind = NameClass::classify(sema, &name); | ||
463 | |||
464 | if let Some(NameClass::Definition(Definition::Local(local))) = &name_kind { | ||
465 | if let Some(name) = local.name(db) { | ||
466 | let shadow_count = bindings_shadow_count.entry(name.clone()).or_default(); | ||
467 | *shadow_count += 1; | ||
468 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) | ||
469 | } | ||
470 | }; | ||
471 | |||
472 | match name_kind { | ||
473 | Some(NameClass::ExternCrate(_)) => HighlightTag::Symbol(SymbolKind::Module).into(), | ||
474 | Some(NameClass::Definition(def)) => { | ||
475 | highlight_def(db, def) | HighlightModifier::Definition | ||
476 | } | ||
477 | Some(NameClass::ConstReference(def)) => highlight_def(db, def), | ||
478 | Some(NameClass::PatFieldShorthand { field_ref, .. }) => { | ||
479 | let mut h = HighlightTag::Symbol(SymbolKind::Field).into(); | ||
480 | if let Definition::Field(field) = field_ref { | ||
481 | if let VariantDef::Union(_) = field.parent_def(db) { | ||
482 | h |= HighlightModifier::Unsafe; | ||
483 | } | ||
484 | } | ||
485 | |||
486 | h | ||
487 | } | ||
488 | None => highlight_name_by_syntax(name) | HighlightModifier::Definition, | ||
489 | } | ||
490 | } | ||
491 | |||
492 | // Highlight references like the definitions they resolve to | ||
493 | NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => { | ||
494 | // even though we track whether we are in an attribute or not we still need this special case | ||
495 | // as otherwise we would emit unresolved references for name refs inside attributes | ||
496 | Highlight::from(HighlightTag::Symbol(SymbolKind::Function)) | ||
497 | } | ||
498 | NAME_REF => { | ||
499 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); | ||
500 | highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| { | ||
501 | match NameRefClass::classify(sema, &name_ref) { | ||
502 | Some(name_kind) => match name_kind { | ||
503 | NameRefClass::ExternCrate(_) => { | ||
504 | HighlightTag::Symbol(SymbolKind::Module).into() | ||
505 | } | ||
506 | NameRefClass::Definition(def) => { | ||
507 | if let Definition::Local(local) = &def { | ||
508 | if let Some(name) = local.name(db) { | ||
509 | let shadow_count = | ||
510 | bindings_shadow_count.entry(name.clone()).or_default(); | ||
511 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) | ||
512 | } | ||
513 | }; | ||
514 | |||
515 | let mut h = highlight_def(db, def); | ||
516 | |||
517 | if let Definition::Local(local) = &def { | ||
518 | if is_consumed_lvalue(name_ref.syntax().clone().into(), local, db) { | ||
519 | h |= HighlightModifier::Consuming; | ||
520 | } | ||
521 | } | ||
522 | |||
523 | if let Some(parent) = name_ref.syntax().parent() { | ||
524 | if matches!(parent.kind(), FIELD_EXPR | RECORD_PAT_FIELD) { | ||
525 | if let Definition::Field(field) = def { | ||
526 | if let VariantDef::Union(_) = field.parent_def(db) { | ||
527 | h |= HighlightModifier::Unsafe; | ||
528 | } | ||
529 | } | ||
530 | } | ||
531 | } | ||
532 | |||
533 | h | ||
534 | } | ||
535 | NameRefClass::FieldShorthand { .. } => { | ||
536 | HighlightTag::Symbol(SymbolKind::Field).into() | ||
537 | } | ||
538 | }, | ||
539 | None if syntactic_name_ref_highlighting => { | ||
540 | highlight_name_ref_by_syntax(name_ref, sema) | ||
541 | } | ||
542 | None => HighlightTag::UnresolvedReference.into(), | ||
543 | } | ||
544 | }) | ||
545 | } | ||
546 | |||
547 | // Simple token-based highlighting | ||
548 | COMMENT => { | ||
549 | let comment = element.into_token().and_then(ast::Comment::cast)?; | ||
550 | let h = HighlightTag::Comment; | ||
551 | match comment.kind().doc { | ||
552 | Some(_) => h | HighlightModifier::Documentation, | ||
553 | None => h.into(), | ||
554 | } | ||
555 | } | ||
556 | STRING | BYTE_STRING => HighlightTag::StringLiteral.into(), | ||
557 | ATTR => HighlightTag::Attribute.into(), | ||
558 | INT_NUMBER | FLOAT_NUMBER => HighlightTag::NumericLiteral.into(), | ||
559 | BYTE => HighlightTag::ByteLiteral.into(), | ||
560 | CHAR => HighlightTag::CharLiteral.into(), | ||
561 | QUESTION => Highlight::new(HighlightTag::Operator) | HighlightModifier::ControlFlow, | ||
562 | LIFETIME => { | ||
563 | let lifetime = element.into_node().and_then(ast::Lifetime::cast).unwrap(); | ||
564 | |||
565 | match NameClass::classify_lifetime(sema, &lifetime) { | ||
566 | Some(NameClass::Definition(def)) => { | ||
567 | highlight_def(db, def) | HighlightModifier::Definition | ||
568 | } | ||
569 | None => match NameRefClass::classify_lifetime(sema, &lifetime) { | ||
570 | Some(NameRefClass::Definition(def)) => highlight_def(db, def), | ||
571 | _ => Highlight::new(HighlightTag::Symbol(SymbolKind::LifetimeParam)), | ||
572 | }, | ||
573 | _ => { | ||
574 | Highlight::new(HighlightTag::Symbol(SymbolKind::LifetimeParam)) | ||
575 | | HighlightModifier::Definition | ||
576 | } | ||
577 | } | ||
578 | } | ||
579 | p if p.is_punct() => match p { | ||
580 | T![&] => { | ||
581 | let h = HighlightTag::Operator.into(); | ||
582 | let is_unsafe = element | ||
583 | .parent() | ||
584 | .and_then(ast::RefExpr::cast) | ||
585 | .map(|ref_expr| sema.is_unsafe_ref_expr(&ref_expr)) | ||
586 | .unwrap_or(false); | ||
587 | if is_unsafe { | ||
588 | h | HighlightModifier::Unsafe | ||
589 | } else { | ||
590 | h | ||
591 | } | ||
592 | } | ||
593 | T![::] | T![->] | T![=>] | T![..] | T![=] | T![@] | T![.] => { | ||
594 | HighlightTag::Operator.into() | ||
595 | } | ||
596 | T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { | ||
597 | HighlightTag::Symbol(SymbolKind::Macro).into() | ||
598 | } | ||
599 | T![!] if element.parent().and_then(ast::NeverType::cast).is_some() => { | ||
600 | HighlightTag::BuiltinType.into() | ||
601 | } | ||
602 | T![*] if element.parent().and_then(ast::PtrType::cast).is_some() => { | ||
603 | HighlightTag::Keyword.into() | ||
604 | } | ||
605 | T![*] if element.parent().and_then(ast::PrefixExpr::cast).is_some() => { | ||
606 | let prefix_expr = element.parent().and_then(ast::PrefixExpr::cast)?; | ||
607 | |||
608 | let expr = prefix_expr.expr()?; | ||
609 | let ty = sema.type_of_expr(&expr)?; | ||
610 | if ty.is_raw_ptr() { | ||
611 | HighlightTag::Operator | HighlightModifier::Unsafe | ||
612 | } else if let Some(ast::PrefixOp::Deref) = prefix_expr.op_kind() { | ||
613 | HighlightTag::Operator.into() | ||
614 | } else { | ||
615 | HighlightTag::Punctuation.into() | ||
616 | } | ||
617 | } | ||
618 | T![-] if element.parent().and_then(ast::PrefixExpr::cast).is_some() => { | ||
619 | let prefix_expr = element.parent().and_then(ast::PrefixExpr::cast)?; | ||
620 | |||
621 | let expr = prefix_expr.expr()?; | ||
622 | match expr { | ||
623 | ast::Expr::Literal(_) => HighlightTag::NumericLiteral, | ||
624 | _ => HighlightTag::Operator, | ||
625 | } | ||
626 | .into() | ||
627 | } | ||
628 | _ if element.parent().and_then(ast::PrefixExpr::cast).is_some() => { | ||
629 | HighlightTag::Operator.into() | ||
630 | } | ||
631 | _ if element.parent().and_then(ast::BinExpr::cast).is_some() => { | ||
632 | HighlightTag::Operator.into() | ||
633 | } | ||
634 | _ if element.parent().and_then(ast::RangeExpr::cast).is_some() => { | ||
635 | HighlightTag::Operator.into() | ||
636 | } | ||
637 | _ if element.parent().and_then(ast::RangePat::cast).is_some() => { | ||
638 | HighlightTag::Operator.into() | ||
639 | } | ||
640 | _ if element.parent().and_then(ast::RestPat::cast).is_some() => { | ||
641 | HighlightTag::Operator.into() | ||
642 | } | ||
643 | _ if element.parent().and_then(ast::Attr::cast).is_some() => { | ||
644 | HighlightTag::Attribute.into() | ||
645 | } | ||
646 | _ => HighlightTag::Punctuation.into(), | ||
647 | }, | ||
648 | |||
649 | k if k.is_keyword() => { | ||
650 | let h = Highlight::new(HighlightTag::Keyword); | ||
651 | match k { | ||
652 | T![break] | ||
653 | | T![continue] | ||
654 | | T![else] | ||
655 | | T![if] | ||
656 | | T![loop] | ||
657 | | T![match] | ||
658 | | T![return] | ||
659 | | T![while] | ||
660 | | T![in] => h | HighlightModifier::ControlFlow, | ||
661 | T![for] if !is_child_of_impl(&element) => h | HighlightModifier::ControlFlow, | ||
662 | T![unsafe] => h | HighlightModifier::Unsafe, | ||
663 | T![true] | T![false] => HighlightTag::BoolLiteral.into(), | ||
664 | T![self] => { | ||
665 | let self_param_is_mut = element | ||
666 | .parent() | ||
667 | .and_then(ast::SelfParam::cast) | ||
668 | .and_then(|p| p.mut_token()) | ||
669 | .is_some(); | ||
670 | let self_path = &element | ||
671 | .parent() | ||
672 | .as_ref() | ||
673 | .and_then(SyntaxNode::parent) | ||
674 | .and_then(ast::Path::cast) | ||
675 | .and_then(|p| sema.resolve_path(&p)); | ||
676 | let mut h = HighlightTag::Symbol(SymbolKind::SelfParam).into(); | ||
677 | if self_param_is_mut | ||
678 | || matches!(self_path, | ||
679 | Some(hir::PathResolution::Local(local)) | ||
680 | if local.is_self(db) | ||
681 | && (local.is_mut(db) || local.ty(db).is_mutable_reference()) | ||
682 | ) | ||
683 | { | ||
684 | h |= HighlightModifier::Mutable | ||
685 | } | ||
686 | |||
687 | if let Some(hir::PathResolution::Local(local)) = self_path { | ||
688 | if is_consumed_lvalue(element, &local, db) { | ||
689 | h |= HighlightModifier::Consuming; | ||
690 | } | ||
691 | } | ||
692 | |||
693 | h | ||
694 | } | ||
695 | T![ref] => element | ||
696 | .parent() | ||
697 | .and_then(ast::IdentPat::cast) | ||
698 | .and_then(|ident_pat| { | ||
699 | if sema.is_unsafe_ident_pat(&ident_pat) { | ||
700 | Some(HighlightModifier::Unsafe) | ||
701 | } else { | ||
702 | None | ||
703 | } | ||
704 | }) | ||
705 | .map(|modifier| h | modifier) | ||
706 | .unwrap_or(h), | ||
707 | _ => h, | ||
708 | } | ||
709 | } | ||
710 | |||
711 | _ => return None, | ||
712 | }; | ||
713 | |||
714 | return Some((highlight, binding_hash)); | ||
715 | |||
716 | fn calc_binding_hash(name: &Name, shadow_count: u32) -> u64 { | ||
717 | fn hash<T: std::hash::Hash + std::fmt::Debug>(x: T) -> u64 { | ||
718 | use std::{collections::hash_map::DefaultHasher, hash::Hasher}; | ||
719 | |||
720 | let mut hasher = DefaultHasher::new(); | ||
721 | x.hash(&mut hasher); | ||
722 | hasher.finish() | ||
723 | } | ||
724 | |||
725 | hash((name, shadow_count)) | ||
726 | } | ||
727 | } | ||
728 | |||
729 | fn is_child_of_impl(element: &SyntaxElement) -> bool { | ||
730 | match element.parent() { | ||
731 | Some(e) => e.kind() == IMPL, | ||
732 | _ => false, | ||
733 | } | ||
734 | } | ||
735 | |||
736 | fn highlight_func_by_name_ref( | ||
737 | sema: &Semantics<RootDatabase>, | ||
738 | name_ref: &ast::NameRef, | ||
739 | ) -> Option<Highlight> { | ||
740 | let method_call = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast)?; | ||
741 | highlight_method_call(sema, &method_call) | ||
742 | } | ||
743 | |||
744 | fn highlight_method_call( | ||
745 | sema: &Semantics<RootDatabase>, | ||
746 | method_call: &ast::MethodCallExpr, | ||
747 | ) -> Option<Highlight> { | ||
748 | let func = sema.resolve_method_call(&method_call)?; | ||
749 | let mut h = HighlightTag::Symbol(SymbolKind::Function).into(); | ||
750 | h |= HighlightModifier::Associated; | ||
751 | if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) { | ||
752 | h |= HighlightModifier::Unsafe; | ||
753 | } | ||
754 | if let Some(self_param) = func.self_param(sema.db) { | ||
755 | match self_param.access(sema.db) { | ||
756 | hir::Access::Shared => (), | ||
757 | hir::Access::Exclusive => h |= HighlightModifier::Mutable, | ||
758 | hir::Access::Owned => { | ||
759 | if let Some(receiver_ty) = | ||
760 | method_call.receiver().and_then(|it| sema.type_of_expr(&it)) | ||
761 | { | ||
762 | if !receiver_ty.is_copy(sema.db) { | ||
763 | h |= HighlightModifier::Consuming | ||
764 | } | ||
765 | } | ||
766 | } | ||
767 | } | ||
768 | } | ||
769 | Some(h) | ||
770 | } | ||
771 | |||
772 | fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { | ||
773 | match def { | ||
774 | Definition::Macro(_) => HighlightTag::Symbol(SymbolKind::Macro), | ||
775 | Definition::Field(_) => HighlightTag::Symbol(SymbolKind::Field), | ||
776 | Definition::ModuleDef(def) => match def { | ||
777 | hir::ModuleDef::Module(_) => HighlightTag::Symbol(SymbolKind::Module), | ||
778 | hir::ModuleDef::Function(func) => { | ||
779 | let mut h = Highlight::new(HighlightTag::Symbol(SymbolKind::Function)); | ||
780 | if func.as_assoc_item(db).is_some() { | ||
781 | h |= HighlightModifier::Associated; | ||
782 | if func.self_param(db).is_none() { | ||
783 | h |= HighlightModifier::Static | ||
784 | } | ||
785 | } | ||
786 | if func.is_unsafe(db) { | ||
787 | h |= HighlightModifier::Unsafe; | ||
788 | } | ||
789 | return h; | ||
790 | } | ||
791 | hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Symbol(SymbolKind::Struct), | ||
792 | hir::ModuleDef::Adt(hir::Adt::Enum(_)) => HighlightTag::Symbol(SymbolKind::Enum), | ||
793 | hir::ModuleDef::Adt(hir::Adt::Union(_)) => HighlightTag::Symbol(SymbolKind::Union), | ||
794 | hir::ModuleDef::Variant(_) => HighlightTag::Symbol(SymbolKind::Variant), | ||
795 | hir::ModuleDef::Const(konst) => { | ||
796 | let mut h = Highlight::new(HighlightTag::Symbol(SymbolKind::Const)); | ||
797 | if konst.as_assoc_item(db).is_some() { | ||
798 | h |= HighlightModifier::Associated | ||
799 | } | ||
800 | return h; | ||
801 | } | ||
802 | hir::ModuleDef::Trait(_) => HighlightTag::Symbol(SymbolKind::Trait), | ||
803 | hir::ModuleDef::TypeAlias(type_) => { | ||
804 | let mut h = Highlight::new(HighlightTag::Symbol(SymbolKind::TypeAlias)); | ||
805 | if type_.as_assoc_item(db).is_some() { | ||
806 | h |= HighlightModifier::Associated | ||
807 | } | ||
808 | return h; | ||
809 | } | ||
810 | hir::ModuleDef::BuiltinType(_) => HighlightTag::BuiltinType, | ||
811 | hir::ModuleDef::Static(s) => { | ||
812 | let mut h = Highlight::new(HighlightTag::Symbol(SymbolKind::Static)); | ||
813 | if s.is_mut(db) { | ||
814 | h |= HighlightModifier::Mutable; | ||
815 | h |= HighlightModifier::Unsafe; | ||
816 | } | ||
817 | return h; | ||
818 | } | ||
819 | }, | ||
820 | Definition::SelfType(_) => HighlightTag::Symbol(SymbolKind::Impl), | ||
821 | Definition::TypeParam(_) => HighlightTag::Symbol(SymbolKind::TypeParam), | ||
822 | Definition::ConstParam(_) => HighlightTag::Symbol(SymbolKind::ConstParam), | ||
823 | Definition::Local(local) => { | ||
824 | let tag = if local.is_param(db) { | ||
825 | HighlightTag::Symbol(SymbolKind::ValueParam) | ||
826 | } else { | ||
827 | HighlightTag::Symbol(SymbolKind::Local) | ||
828 | }; | ||
829 | let mut h = Highlight::new(tag); | ||
830 | if local.is_mut(db) || local.ty(db).is_mutable_reference() { | ||
831 | h |= HighlightModifier::Mutable; | ||
832 | } | ||
833 | if local.ty(db).as_callable(db).is_some() || local.ty(db).impls_fnonce(db) { | ||
834 | h |= HighlightModifier::Callable; | ||
835 | } | ||
836 | return h; | ||
837 | } | ||
838 | Definition::LifetimeParam(_) => HighlightTag::Symbol(SymbolKind::LifetimeParam), | ||
839 | Definition::Label(_) => HighlightTag::Symbol(SymbolKind::Label), | ||
840 | } | ||
841 | .into() | ||
842 | } | ||
843 | |||
844 | fn highlight_name_by_syntax(name: ast::Name) -> Highlight { | ||
845 | let default = HighlightTag::UnresolvedReference; | ||
846 | |||
847 | let parent = match name.syntax().parent() { | ||
848 | Some(it) => it, | ||
849 | _ => return default.into(), | ||
850 | }; | ||
851 | |||
852 | let tag = match parent.kind() { | ||
853 | STRUCT => HighlightTag::Symbol(SymbolKind::Struct), | ||
854 | ENUM => HighlightTag::Symbol(SymbolKind::Enum), | ||
855 | VARIANT => HighlightTag::Symbol(SymbolKind::Variant), | ||
856 | UNION => HighlightTag::Symbol(SymbolKind::Union), | ||
857 | TRAIT => HighlightTag::Symbol(SymbolKind::Trait), | ||
858 | TYPE_ALIAS => HighlightTag::Symbol(SymbolKind::TypeAlias), | ||
859 | TYPE_PARAM => HighlightTag::Symbol(SymbolKind::TypeParam), | ||
860 | RECORD_FIELD => HighlightTag::Symbol(SymbolKind::Field), | ||
861 | MODULE => HighlightTag::Symbol(SymbolKind::Module), | ||
862 | FN => HighlightTag::Symbol(SymbolKind::Function), | ||
863 | CONST => HighlightTag::Symbol(SymbolKind::Const), | ||
864 | STATIC => HighlightTag::Symbol(SymbolKind::Static), | ||
865 | IDENT_PAT => HighlightTag::Symbol(SymbolKind::Local), | ||
866 | _ => default, | ||
867 | }; | ||
868 | |||
869 | tag.into() | ||
870 | } | ||
871 | |||
872 | fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabase>) -> Highlight { | ||
873 | let default = HighlightTag::UnresolvedReference; | ||
874 | |||
875 | let parent = match name.syntax().parent() { | ||
876 | Some(it) => it, | ||
877 | _ => return default.into(), | ||
878 | }; | ||
879 | |||
880 | match parent.kind() { | ||
881 | METHOD_CALL_EXPR => { | ||
882 | return ast::MethodCallExpr::cast(parent) | ||
883 | .and_then(|method_call| highlight_method_call(sema, &method_call)) | ||
884 | .unwrap_or_else(|| HighlightTag::Symbol(SymbolKind::Function).into()); | ||
885 | } | ||
886 | FIELD_EXPR => { | ||
887 | let h = HighlightTag::Symbol(SymbolKind::Field); | ||
888 | let is_union = ast::FieldExpr::cast(parent) | ||
889 | .and_then(|field_expr| { | ||
890 | let field = sema.resolve_field(&field_expr)?; | ||
891 | Some(if let VariantDef::Union(_) = field.parent_def(sema.db) { | ||
892 | true | ||
893 | } else { | ||
894 | false | ||
895 | }) | ||
896 | }) | ||
897 | .unwrap_or(false); | ||
898 | if is_union { | ||
899 | h | HighlightModifier::Unsafe | ||
900 | } else { | ||
901 | h.into() | ||
902 | } | ||
903 | } | ||
904 | PATH_SEGMENT => { | ||
905 | let path = match parent.parent().and_then(ast::Path::cast) { | ||
906 | Some(it) => it, | ||
907 | _ => return default.into(), | ||
908 | }; | ||
909 | let expr = match path.syntax().parent().and_then(ast::PathExpr::cast) { | ||
910 | Some(it) => it, | ||
911 | _ => { | ||
912 | // within path, decide whether it is module or adt by checking for uppercase name | ||
913 | return if name.text().chars().next().unwrap_or_default().is_uppercase() { | ||
914 | HighlightTag::Symbol(SymbolKind::Struct) | ||
915 | } else { | ||
916 | HighlightTag::Symbol(SymbolKind::Module) | ||
917 | } | ||
918 | .into(); | ||
919 | } | ||
920 | }; | ||
921 | let parent = match expr.syntax().parent() { | ||
922 | Some(it) => it, | ||
923 | None => return default.into(), | ||
924 | }; | ||
925 | |||
926 | match parent.kind() { | ||
927 | CALL_EXPR => HighlightTag::Symbol(SymbolKind::Function).into(), | ||
928 | _ => if name.text().chars().next().unwrap_or_default().is_uppercase() { | ||
929 | HighlightTag::Symbol(SymbolKind::Struct) | ||
930 | } else { | ||
931 | HighlightTag::Symbol(SymbolKind::Const) | ||
932 | } | ||
933 | .into(), | ||
934 | } | ||
935 | } | ||
936 | _ => default.into(), | ||
937 | } | ||
938 | } | ||
diff --git a/crates/ide/src/syntax_highlighting/format.rs b/crates/ide/src/syntax_highlighting/format.rs index 26416022b..a74ca844b 100644 --- a/crates/ide/src/syntax_highlighting/format.rs +++ b/crates/ide/src/syntax_highlighting/format.rs | |||
@@ -1,65 +1,51 @@ | |||
1 | //! Syntax highlighting for format macro strings. | 1 | //! Syntax highlighting for format macro strings. |
2 | use syntax::{ | 2 | use syntax::{ |
3 | ast::{self, FormatSpecifier, HasFormatSpecifier}, | 3 | ast::{self, FormatSpecifier, HasFormatSpecifier}, |
4 | AstNode, AstToken, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, | 4 | AstNode, AstToken, TextRange, |
5 | }; | 5 | }; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{syntax_highlighting::highlights::Highlights, HlRange, HlTag, SymbolKind}; |
8 | syntax_highlighting::HighlightedRangeStack, HighlightTag, HighlightedRange, SymbolKind, | ||
9 | }; | ||
10 | |||
11 | #[derive(Default)] | ||
12 | pub(super) struct FormatStringHighlighter { | ||
13 | format_string: Option<SyntaxElement>, | ||
14 | } | ||
15 | 8 | ||
16 | impl FormatStringHighlighter { | 9 | pub(super) fn highlight_format_string( |
17 | pub(super) fn check_for_format_string(&mut self, parent: &SyntaxNode) { | 10 | stack: &mut Highlights, |
18 | // Check if macro takes a format string and remember it for highlighting later. | 11 | string: &ast::String, |
19 | // The macros that accept a format string expand to a compiler builtin macros | 12 | range: TextRange, |
20 | // `format_args` and `format_args_nl`. | 13 | ) { |
21 | if let Some(name) = parent | 14 | if is_format_string(string).is_none() { |
22 | .parent() | 15 | return; |
23 | .and_then(ast::MacroCall::cast) | ||
24 | .and_then(|mc| mc.path()) | ||
25 | .and_then(|p| p.segment()) | ||
26 | .and_then(|s| s.name_ref()) | ||
27 | { | ||
28 | match name.text().as_str() { | ||
29 | "format_args" | "format_args_nl" => { | ||
30 | self.format_string = parent | ||
31 | .children_with_tokens() | ||
32 | .filter(|t| t.kind() != SyntaxKind::WHITESPACE) | ||
33 | .nth(1) | ||
34 | .filter(|e| ast::String::can_cast(e.kind())) | ||
35 | } | ||
36 | _ => {} | ||
37 | } | ||
38 | } | ||
39 | } | 16 | } |
40 | pub(super) fn highlight_format_string( | 17 | |
41 | &self, | 18 | string.lex_format_specifier(|piece_range, kind| { |
42 | range_stack: &mut HighlightedRangeStack, | 19 | if let Some(highlight) = highlight_format_specifier(kind) { |
43 | string: &impl HasFormatSpecifier, | 20 | stack.add(HlRange { |
44 | range: TextRange, | 21 | range: piece_range + range.start(), |
45 | ) { | 22 | highlight: highlight.into(), |
46 | if self.format_string.as_ref() == Some(&SyntaxElement::from(string.syntax().clone())) { | 23 | binding_hash: None, |
47 | range_stack.push(); | ||
48 | string.lex_format_specifier(|piece_range, kind| { | ||
49 | if let Some(highlight) = highlight_format_specifier(kind) { | ||
50 | range_stack.add(HighlightedRange { | ||
51 | range: piece_range + range.start(), | ||
52 | highlight: highlight.into(), | ||
53 | binding_hash: None, | ||
54 | }); | ||
55 | } | ||
56 | }); | 24 | }); |
57 | range_stack.pop(); | ||
58 | } | 25 | } |
26 | }); | ||
27 | } | ||
28 | |||
29 | fn is_format_string(string: &ast::String) -> Option<()> { | ||
30 | let parent = string.syntax().parent(); | ||
31 | |||
32 | let name = parent.parent().and_then(ast::MacroCall::cast)?.path()?.segment()?.name_ref()?; | ||
33 | if !matches!(name.text().as_str(), "format_args" | "format_args_nl") { | ||
34 | return None; | ||
35 | } | ||
36 | |||
37 | let first_literal = parent | ||
38 | .children_with_tokens() | ||
39 | .filter_map(|it| it.as_token().cloned().and_then(ast::String::cast)) | ||
40 | .next()?; | ||
41 | if &first_literal != string { | ||
42 | return None; | ||
59 | } | 43 | } |
44 | |||
45 | Some(()) | ||
60 | } | 46 | } |
61 | 47 | ||
62 | fn highlight_format_specifier(kind: FormatSpecifier) -> Option<HighlightTag> { | 48 | fn highlight_format_specifier(kind: FormatSpecifier) -> Option<HlTag> { |
63 | Some(match kind { | 49 | Some(match kind { |
64 | FormatSpecifier::Open | 50 | FormatSpecifier::Open |
65 | | FormatSpecifier::Close | 51 | | FormatSpecifier::Close |
@@ -71,8 +57,10 @@ fn highlight_format_specifier(kind: FormatSpecifier) -> Option<HighlightTag> { | |||
71 | | FormatSpecifier::DollarSign | 57 | | FormatSpecifier::DollarSign |
72 | | FormatSpecifier::Dot | 58 | | FormatSpecifier::Dot |
73 | | FormatSpecifier::Asterisk | 59 | | FormatSpecifier::Asterisk |
74 | | FormatSpecifier::QuestionMark => HighlightTag::FormatSpecifier, | 60 | | FormatSpecifier::QuestionMark => HlTag::FormatSpecifier, |
75 | FormatSpecifier::Integer | FormatSpecifier::Zero => HighlightTag::NumericLiteral, | 61 | |
76 | FormatSpecifier::Identifier => HighlightTag::Symbol(SymbolKind::Local), | 62 | FormatSpecifier::Integer | FormatSpecifier::Zero => HlTag::NumericLiteral, |
63 | |||
64 | FormatSpecifier::Identifier => HlTag::Symbol(SymbolKind::Local), | ||
77 | }) | 65 | }) |
78 | } | 66 | } |
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs new file mode 100644 index 000000000..34bae49a8 --- /dev/null +++ b/crates/ide/src/syntax_highlighting/highlight.rs | |||
@@ -0,0 +1,530 @@ | |||
1 | //! Computes color for a single element. | ||
2 | |||
3 | use hir::{AsAssocItem, Semantics, VariantDef}; | ||
4 | use ide_db::{ | ||
5 | defs::{Definition, NameClass, NameRefClass}, | ||
6 | RootDatabase, | ||
7 | }; | ||
8 | use rustc_hash::FxHashMap; | ||
9 | use syntax::{ | ||
10 | ast, AstNode, AstToken, NodeOrToken, SyntaxElement, | ||
11 | SyntaxKind::{self, *}, | ||
12 | SyntaxNode, SyntaxToken, T, | ||
13 | }; | ||
14 | |||
15 | use crate::{syntax_highlighting::tags::HlPunct, Highlight, HlMod, HlTag, SymbolKind}; | ||
16 | |||
17 | pub(super) fn element( | ||
18 | sema: &Semantics<RootDatabase>, | ||
19 | bindings_shadow_count: &mut FxHashMap<hir::Name, u32>, | ||
20 | syntactic_name_ref_highlighting: bool, | ||
21 | element: SyntaxElement, | ||
22 | ) -> Option<(Highlight, Option<u64>)> { | ||
23 | let db = sema.db; | ||
24 | let mut binding_hash = None; | ||
25 | let highlight: Highlight = match element.kind() { | ||
26 | FN => { | ||
27 | bindings_shadow_count.clear(); | ||
28 | return None; | ||
29 | } | ||
30 | |||
31 | // Highlight definitions depending on the "type" of the definition. | ||
32 | NAME => { | ||
33 | let name = element.into_node().and_then(ast::Name::cast).unwrap(); | ||
34 | let name_kind = NameClass::classify(sema, &name); | ||
35 | |||
36 | if let Some(NameClass::Definition(Definition::Local(local))) = &name_kind { | ||
37 | if let Some(name) = local.name(db) { | ||
38 | let shadow_count = bindings_shadow_count.entry(name.clone()).or_default(); | ||
39 | *shadow_count += 1; | ||
40 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) | ||
41 | } | ||
42 | }; | ||
43 | |||
44 | match name_kind { | ||
45 | Some(NameClass::ExternCrate(_)) => HlTag::Symbol(SymbolKind::Module).into(), | ||
46 | Some(NameClass::Definition(def)) => highlight_def(db, def) | HlMod::Definition, | ||
47 | Some(NameClass::ConstReference(def)) => highlight_def(db, def), | ||
48 | Some(NameClass::PatFieldShorthand { field_ref, .. }) => { | ||
49 | let mut h = HlTag::Symbol(SymbolKind::Field).into(); | ||
50 | if let Definition::Field(field) = field_ref { | ||
51 | if let VariantDef::Union(_) = field.parent_def(db) { | ||
52 | h |= HlMod::Unsafe; | ||
53 | } | ||
54 | } | ||
55 | |||
56 | h | ||
57 | } | ||
58 | None => highlight_name_by_syntax(name) | HlMod::Definition, | ||
59 | } | ||
60 | } | ||
61 | |||
62 | // Highlight references like the definitions they resolve to | ||
63 | NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => { | ||
64 | // even though we track whether we are in an attribute or not we still need this special case | ||
65 | // as otherwise we would emit unresolved references for name refs inside attributes | ||
66 | Highlight::from(HlTag::Symbol(SymbolKind::Function)) | ||
67 | } | ||
68 | NAME_REF => { | ||
69 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); | ||
70 | highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| { | ||
71 | match NameRefClass::classify(sema, &name_ref) { | ||
72 | Some(name_kind) => match name_kind { | ||
73 | NameRefClass::ExternCrate(_) => HlTag::Symbol(SymbolKind::Module).into(), | ||
74 | NameRefClass::Definition(def) => { | ||
75 | if let Definition::Local(local) = &def { | ||
76 | if let Some(name) = local.name(db) { | ||
77 | let shadow_count = | ||
78 | bindings_shadow_count.entry(name.clone()).or_default(); | ||
79 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) | ||
80 | } | ||
81 | }; | ||
82 | |||
83 | let mut h = highlight_def(db, def); | ||
84 | |||
85 | if let Definition::Local(local) = &def { | ||
86 | if is_consumed_lvalue(name_ref.syntax().clone().into(), local, db) { | ||
87 | h |= HlMod::Consuming; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | if let Some(parent) = name_ref.syntax().parent() { | ||
92 | if matches!(parent.kind(), FIELD_EXPR | RECORD_PAT_FIELD) { | ||
93 | if let Definition::Field(field) = def { | ||
94 | if let VariantDef::Union(_) = field.parent_def(db) { | ||
95 | h |= HlMod::Unsafe; | ||
96 | } | ||
97 | } | ||
98 | } | ||
99 | } | ||
100 | |||
101 | h | ||
102 | } | ||
103 | NameRefClass::FieldShorthand { .. } => { | ||
104 | HlTag::Symbol(SymbolKind::Field).into() | ||
105 | } | ||
106 | }, | ||
107 | None if syntactic_name_ref_highlighting => { | ||
108 | highlight_name_ref_by_syntax(name_ref, sema) | ||
109 | } | ||
110 | None => HlTag::UnresolvedReference.into(), | ||
111 | } | ||
112 | }) | ||
113 | } | ||
114 | |||
115 | // Simple token-based highlighting | ||
116 | COMMENT => { | ||
117 | let comment = element.into_token().and_then(ast::Comment::cast)?; | ||
118 | let h = HlTag::Comment; | ||
119 | match comment.kind().doc { | ||
120 | Some(_) => h | HlMod::Documentation, | ||
121 | None => h.into(), | ||
122 | } | ||
123 | } | ||
124 | STRING | BYTE_STRING => HlTag::StringLiteral.into(), | ||
125 | ATTR => HlTag::Attribute.into(), | ||
126 | INT_NUMBER | FLOAT_NUMBER => HlTag::NumericLiteral.into(), | ||
127 | BYTE => HlTag::ByteLiteral.into(), | ||
128 | CHAR => HlTag::CharLiteral.into(), | ||
129 | QUESTION => Highlight::new(HlTag::Operator) | HlMod::ControlFlow, | ||
130 | LIFETIME => { | ||
131 | let lifetime = element.into_node().and_then(ast::Lifetime::cast).unwrap(); | ||
132 | |||
133 | match NameClass::classify_lifetime(sema, &lifetime) { | ||
134 | Some(NameClass::Definition(def)) => highlight_def(db, def) | HlMod::Definition, | ||
135 | None => match NameRefClass::classify_lifetime(sema, &lifetime) { | ||
136 | Some(NameRefClass::Definition(def)) => highlight_def(db, def), | ||
137 | _ => Highlight::new(HlTag::Symbol(SymbolKind::LifetimeParam)), | ||
138 | }, | ||
139 | _ => Highlight::new(HlTag::Symbol(SymbolKind::LifetimeParam)) | HlMod::Definition, | ||
140 | } | ||
141 | } | ||
142 | p if p.is_punct() => match p { | ||
143 | T![&] => { | ||
144 | let h = HlTag::Operator.into(); | ||
145 | let is_unsafe = element | ||
146 | .parent() | ||
147 | .and_then(ast::RefExpr::cast) | ||
148 | .map(|ref_expr| sema.is_unsafe_ref_expr(&ref_expr)) | ||
149 | .unwrap_or(false); | ||
150 | if is_unsafe { | ||
151 | h | HlMod::Unsafe | ||
152 | } else { | ||
153 | h | ||
154 | } | ||
155 | } | ||
156 | T![::] | T![->] | T![=>] | T![..] | T![=] | T![@] | T![.] => HlTag::Operator.into(), | ||
157 | T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { | ||
158 | HlTag::Symbol(SymbolKind::Macro).into() | ||
159 | } | ||
160 | T![!] if element.parent().and_then(ast::NeverType::cast).is_some() => { | ||
161 | HlTag::BuiltinType.into() | ||
162 | } | ||
163 | T![*] if element.parent().and_then(ast::PtrType::cast).is_some() => { | ||
164 | HlTag::Keyword.into() | ||
165 | } | ||
166 | T![*] if element.parent().and_then(ast::PrefixExpr::cast).is_some() => { | ||
167 | let prefix_expr = element.parent().and_then(ast::PrefixExpr::cast)?; | ||
168 | |||
169 | let expr = prefix_expr.expr()?; | ||
170 | let ty = sema.type_of_expr(&expr)?; | ||
171 | if ty.is_raw_ptr() { | ||
172 | HlTag::Operator | HlMod::Unsafe | ||
173 | } else if let Some(ast::PrefixOp::Deref) = prefix_expr.op_kind() { | ||
174 | HlTag::Operator.into() | ||
175 | } else { | ||
176 | HlTag::Punctuation(HlPunct::Other).into() | ||
177 | } | ||
178 | } | ||
179 | T![-] if element.parent().and_then(ast::PrefixExpr::cast).is_some() => { | ||
180 | let prefix_expr = element.parent().and_then(ast::PrefixExpr::cast)?; | ||
181 | |||
182 | let expr = prefix_expr.expr()?; | ||
183 | match expr { | ||
184 | ast::Expr::Literal(_) => HlTag::NumericLiteral, | ||
185 | _ => HlTag::Operator, | ||
186 | } | ||
187 | .into() | ||
188 | } | ||
189 | _ if element.parent().and_then(ast::PrefixExpr::cast).is_some() => { | ||
190 | HlTag::Operator.into() | ||
191 | } | ||
192 | _ if element.parent().and_then(ast::BinExpr::cast).is_some() => HlTag::Operator.into(), | ||
193 | _ if element.parent().and_then(ast::RangeExpr::cast).is_some() => { | ||
194 | HlTag::Operator.into() | ||
195 | } | ||
196 | _ if element.parent().and_then(ast::RangePat::cast).is_some() => HlTag::Operator.into(), | ||
197 | _ if element.parent().and_then(ast::RestPat::cast).is_some() => HlTag::Operator.into(), | ||
198 | _ if element.parent().and_then(ast::Attr::cast).is_some() => HlTag::Attribute.into(), | ||
199 | kind => HlTag::Punctuation(match kind { | ||
200 | T!['['] | T![']'] => HlPunct::Bracket, | ||
201 | T!['{'] | T!['}'] => HlPunct::Brace, | ||
202 | T!['('] | T![')'] => HlPunct::Parenthesis, | ||
203 | T![<] | T![>] => HlPunct::Angle, | ||
204 | T![,] => HlPunct::Comma, | ||
205 | T![:] => HlPunct::Colon, | ||
206 | T![;] => HlPunct::Semi, | ||
207 | T![.] => HlPunct::Dot, | ||
208 | _ => HlPunct::Other, | ||
209 | }) | ||
210 | .into(), | ||
211 | }, | ||
212 | |||
213 | k if k.is_keyword() => { | ||
214 | let h = Highlight::new(HlTag::Keyword); | ||
215 | match k { | ||
216 | T![break] | ||
217 | | T![continue] | ||
218 | | T![else] | ||
219 | | T![if] | ||
220 | | T![loop] | ||
221 | | T![match] | ||
222 | | T![return] | ||
223 | | T![while] | ||
224 | | T![in] => h | HlMod::ControlFlow, | ||
225 | T![for] if !is_child_of_impl(&element) => h | HlMod::ControlFlow, | ||
226 | T![unsafe] => h | HlMod::Unsafe, | ||
227 | T![true] | T![false] => HlTag::BoolLiteral.into(), | ||
228 | T![self] => { | ||
229 | let self_param_is_mut = element | ||
230 | .parent() | ||
231 | .and_then(ast::SelfParam::cast) | ||
232 | .and_then(|p| p.mut_token()) | ||
233 | .is_some(); | ||
234 | let self_path = &element | ||
235 | .parent() | ||
236 | .as_ref() | ||
237 | .and_then(SyntaxNode::parent) | ||
238 | .and_then(ast::Path::cast) | ||
239 | .and_then(|p| sema.resolve_path(&p)); | ||
240 | let mut h = HlTag::Symbol(SymbolKind::SelfParam).into(); | ||
241 | if self_param_is_mut | ||
242 | || matches!(self_path, | ||
243 | Some(hir::PathResolution::Local(local)) | ||
244 | if local.is_self(db) | ||
245 | && (local.is_mut(db) || local.ty(db).is_mutable_reference()) | ||
246 | ) | ||
247 | { | ||
248 | h |= HlMod::Mutable | ||
249 | } | ||
250 | |||
251 | if let Some(hir::PathResolution::Local(local)) = self_path { | ||
252 | if is_consumed_lvalue(element, &local, db) { | ||
253 | h |= HlMod::Consuming; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | h | ||
258 | } | ||
259 | T![ref] => element | ||
260 | .parent() | ||
261 | .and_then(ast::IdentPat::cast) | ||
262 | .and_then(|ident_pat| { | ||
263 | if sema.is_unsafe_ident_pat(&ident_pat) { | ||
264 | Some(HlMod::Unsafe) | ||
265 | } else { | ||
266 | None | ||
267 | } | ||
268 | }) | ||
269 | .map(|modifier| h | modifier) | ||
270 | .unwrap_or(h), | ||
271 | _ => h, | ||
272 | } | ||
273 | } | ||
274 | |||
275 | _ => return None, | ||
276 | }; | ||
277 | |||
278 | return Some((highlight, binding_hash)); | ||
279 | |||
280 | fn calc_binding_hash(name: &hir::Name, shadow_count: u32) -> u64 { | ||
281 | fn hash<T: std::hash::Hash + std::fmt::Debug>(x: T) -> u64 { | ||
282 | use std::{collections::hash_map::DefaultHasher, hash::Hasher}; | ||
283 | |||
284 | let mut hasher = DefaultHasher::new(); | ||
285 | x.hash(&mut hasher); | ||
286 | hasher.finish() | ||
287 | } | ||
288 | |||
289 | hash((name, shadow_count)) | ||
290 | } | ||
291 | } | ||
292 | |||
293 | fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { | ||
294 | match def { | ||
295 | Definition::Macro(_) => HlTag::Symbol(SymbolKind::Macro), | ||
296 | Definition::Field(_) => HlTag::Symbol(SymbolKind::Field), | ||
297 | Definition::ModuleDef(def) => match def { | ||
298 | hir::ModuleDef::Module(_) => HlTag::Symbol(SymbolKind::Module), | ||
299 | hir::ModuleDef::Function(func) => { | ||
300 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Function)); | ||
301 | if func.as_assoc_item(db).is_some() { | ||
302 | h |= HlMod::Associated; | ||
303 | if func.self_param(db).is_none() { | ||
304 | h |= HlMod::Static | ||
305 | } | ||
306 | } | ||
307 | if func.is_unsafe(db) { | ||
308 | h |= HlMod::Unsafe; | ||
309 | } | ||
310 | return h; | ||
311 | } | ||
312 | hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HlTag::Symbol(SymbolKind::Struct), | ||
313 | hir::ModuleDef::Adt(hir::Adt::Enum(_)) => HlTag::Symbol(SymbolKind::Enum), | ||
314 | hir::ModuleDef::Adt(hir::Adt::Union(_)) => HlTag::Symbol(SymbolKind::Union), | ||
315 | hir::ModuleDef::Variant(_) => HlTag::Symbol(SymbolKind::Variant), | ||
316 | hir::ModuleDef::Const(konst) => { | ||
317 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Const)); | ||
318 | if konst.as_assoc_item(db).is_some() { | ||
319 | h |= HlMod::Associated | ||
320 | } | ||
321 | return h; | ||
322 | } | ||
323 | hir::ModuleDef::Trait(_) => HlTag::Symbol(SymbolKind::Trait), | ||
324 | hir::ModuleDef::TypeAlias(type_) => { | ||
325 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::TypeAlias)); | ||
326 | if type_.as_assoc_item(db).is_some() { | ||
327 | h |= HlMod::Associated | ||
328 | } | ||
329 | return h; | ||
330 | } | ||
331 | hir::ModuleDef::BuiltinType(_) => HlTag::BuiltinType, | ||
332 | hir::ModuleDef::Static(s) => { | ||
333 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Static)); | ||
334 | if s.is_mut(db) { | ||
335 | h |= HlMod::Mutable; | ||
336 | h |= HlMod::Unsafe; | ||
337 | } | ||
338 | return h; | ||
339 | } | ||
340 | }, | ||
341 | Definition::SelfType(_) => HlTag::Symbol(SymbolKind::Impl), | ||
342 | Definition::GenericParam(it) => match it { | ||
343 | hir::GenericParam::TypeParam(_) => HlTag::Symbol(SymbolKind::TypeParam), | ||
344 | hir::GenericParam::ConstParam(_) => HlTag::Symbol(SymbolKind::ConstParam), | ||
345 | hir::GenericParam::LifetimeParam(_) => HlTag::Symbol(SymbolKind::LifetimeParam), | ||
346 | }, | ||
347 | Definition::Local(local) => { | ||
348 | let tag = if local.is_param(db) { | ||
349 | HlTag::Symbol(SymbolKind::ValueParam) | ||
350 | } else { | ||
351 | HlTag::Symbol(SymbolKind::Local) | ||
352 | }; | ||
353 | let mut h = Highlight::new(tag); | ||
354 | if local.is_mut(db) || local.ty(db).is_mutable_reference() { | ||
355 | h |= HlMod::Mutable; | ||
356 | } | ||
357 | if local.ty(db).as_callable(db).is_some() || local.ty(db).impls_fnonce(db) { | ||
358 | h |= HlMod::Callable; | ||
359 | } | ||
360 | return h; | ||
361 | } | ||
362 | Definition::Label(_) => HlTag::Symbol(SymbolKind::Label), | ||
363 | } | ||
364 | .into() | ||
365 | } | ||
366 | |||
367 | fn highlight_func_by_name_ref( | ||
368 | sema: &Semantics<RootDatabase>, | ||
369 | name_ref: &ast::NameRef, | ||
370 | ) -> Option<Highlight> { | ||
371 | let mc = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast)?; | ||
372 | highlight_method_call(sema, &mc) | ||
373 | } | ||
374 | |||
375 | fn highlight_method_call( | ||
376 | sema: &Semantics<RootDatabase>, | ||
377 | method_call: &ast::MethodCallExpr, | ||
378 | ) -> Option<Highlight> { | ||
379 | let func = sema.resolve_method_call(&method_call)?; | ||
380 | let mut h = HlTag::Symbol(SymbolKind::Function).into(); | ||
381 | h |= HlMod::Associated; | ||
382 | if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) { | ||
383 | h |= HlMod::Unsafe; | ||
384 | } | ||
385 | if let Some(self_param) = func.self_param(sema.db) { | ||
386 | match self_param.access(sema.db) { | ||
387 | hir::Access::Shared => (), | ||
388 | hir::Access::Exclusive => h |= HlMod::Mutable, | ||
389 | hir::Access::Owned => { | ||
390 | if let Some(receiver_ty) = | ||
391 | method_call.receiver().and_then(|it| sema.type_of_expr(&it)) | ||
392 | { | ||
393 | if !receiver_ty.is_copy(sema.db) { | ||
394 | h |= HlMod::Consuming | ||
395 | } | ||
396 | } | ||
397 | } | ||
398 | } | ||
399 | } | ||
400 | Some(h) | ||
401 | } | ||
402 | |||
403 | fn highlight_name_by_syntax(name: ast::Name) -> Highlight { | ||
404 | let default = HlTag::UnresolvedReference; | ||
405 | |||
406 | let parent = match name.syntax().parent() { | ||
407 | Some(it) => it, | ||
408 | _ => return default.into(), | ||
409 | }; | ||
410 | |||
411 | let tag = match parent.kind() { | ||
412 | STRUCT => HlTag::Symbol(SymbolKind::Struct), | ||
413 | ENUM => HlTag::Symbol(SymbolKind::Enum), | ||
414 | VARIANT => HlTag::Symbol(SymbolKind::Variant), | ||
415 | UNION => HlTag::Symbol(SymbolKind::Union), | ||
416 | TRAIT => HlTag::Symbol(SymbolKind::Trait), | ||
417 | TYPE_ALIAS => HlTag::Symbol(SymbolKind::TypeAlias), | ||
418 | TYPE_PARAM => HlTag::Symbol(SymbolKind::TypeParam), | ||
419 | RECORD_FIELD => HlTag::Symbol(SymbolKind::Field), | ||
420 | MODULE => HlTag::Symbol(SymbolKind::Module), | ||
421 | FN => HlTag::Symbol(SymbolKind::Function), | ||
422 | CONST => HlTag::Symbol(SymbolKind::Const), | ||
423 | STATIC => HlTag::Symbol(SymbolKind::Static), | ||
424 | IDENT_PAT => HlTag::Symbol(SymbolKind::Local), | ||
425 | _ => default, | ||
426 | }; | ||
427 | |||
428 | tag.into() | ||
429 | } | ||
430 | |||
431 | fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabase>) -> Highlight { | ||
432 | let default = HlTag::UnresolvedReference; | ||
433 | |||
434 | let parent = match name.syntax().parent() { | ||
435 | Some(it) => it, | ||
436 | _ => return default.into(), | ||
437 | }; | ||
438 | |||
439 | match parent.kind() { | ||
440 | METHOD_CALL_EXPR => { | ||
441 | return ast::MethodCallExpr::cast(parent) | ||
442 | .and_then(|it| highlight_method_call(sema, &it)) | ||
443 | .unwrap_or_else(|| HlTag::Symbol(SymbolKind::Function).into()); | ||
444 | } | ||
445 | FIELD_EXPR => { | ||
446 | let h = HlTag::Symbol(SymbolKind::Field); | ||
447 | let is_union = ast::FieldExpr::cast(parent) | ||
448 | .and_then(|field_expr| { | ||
449 | let field = sema.resolve_field(&field_expr)?; | ||
450 | Some(if let VariantDef::Union(_) = field.parent_def(sema.db) { | ||
451 | true | ||
452 | } else { | ||
453 | false | ||
454 | }) | ||
455 | }) | ||
456 | .unwrap_or(false); | ||
457 | if is_union { | ||
458 | h | HlMod::Unsafe | ||
459 | } else { | ||
460 | h.into() | ||
461 | } | ||
462 | } | ||
463 | PATH_SEGMENT => { | ||
464 | let path = match parent.parent().and_then(ast::Path::cast) { | ||
465 | Some(it) => it, | ||
466 | _ => return default.into(), | ||
467 | }; | ||
468 | let expr = match path.syntax().parent().and_then(ast::PathExpr::cast) { | ||
469 | Some(it) => it, | ||
470 | _ => { | ||
471 | // within path, decide whether it is module or adt by checking for uppercase name | ||
472 | return if name.text().chars().next().unwrap_or_default().is_uppercase() { | ||
473 | HlTag::Symbol(SymbolKind::Struct) | ||
474 | } else { | ||
475 | HlTag::Symbol(SymbolKind::Module) | ||
476 | } | ||
477 | .into(); | ||
478 | } | ||
479 | }; | ||
480 | let parent = match expr.syntax().parent() { | ||
481 | Some(it) => it, | ||
482 | None => return default.into(), | ||
483 | }; | ||
484 | |||
485 | match parent.kind() { | ||
486 | CALL_EXPR => HlTag::Symbol(SymbolKind::Function).into(), | ||
487 | _ => if name.text().chars().next().unwrap_or_default().is_uppercase() { | ||
488 | HlTag::Symbol(SymbolKind::Struct) | ||
489 | } else { | ||
490 | HlTag::Symbol(SymbolKind::Const) | ||
491 | } | ||
492 | .into(), | ||
493 | } | ||
494 | } | ||
495 | _ => default.into(), | ||
496 | } | ||
497 | } | ||
498 | |||
499 | fn is_consumed_lvalue( | ||
500 | node: NodeOrToken<SyntaxNode, SyntaxToken>, | ||
501 | local: &hir::Local, | ||
502 | db: &RootDatabase, | ||
503 | ) -> bool { | ||
504 | // When lvalues are passed as arguments and they're not Copy, then mark them as Consuming. | ||
505 | parents_match(node, &[PATH_SEGMENT, PATH, PATH_EXPR, ARG_LIST]) && !local.ty(db).is_copy(db) | ||
506 | } | ||
507 | |||
508 | /// Returns true if the parent nodes of `node` all match the `SyntaxKind`s in `kinds` exactly. | ||
509 | fn parents_match(mut node: NodeOrToken<SyntaxNode, SyntaxToken>, mut kinds: &[SyntaxKind]) -> bool { | ||
510 | while let (Some(parent), [kind, rest @ ..]) = (&node.parent(), kinds) { | ||
511 | if parent.kind() != *kind { | ||
512 | return false; | ||
513 | } | ||
514 | |||
515 | // FIXME: Would be nice to get parent out of the match, but binding by-move and by-value | ||
516 | // in the same pattern is unstable: rust-lang/rust#68354. | ||
517 | node = node.parent().unwrap().into(); | ||
518 | kinds = rest; | ||
519 | } | ||
520 | |||
521 | // Only true if we matched all expected kinds | ||
522 | kinds.len() == 0 | ||
523 | } | ||
524 | |||
525 | fn is_child_of_impl(element: &SyntaxElement) -> bool { | ||
526 | match element.parent() { | ||
527 | Some(e) => e.kind() == IMPL, | ||
528 | _ => false, | ||
529 | } | ||
530 | } | ||
diff --git a/crates/ide/src/syntax_highlighting/highlights.rs b/crates/ide/src/syntax_highlighting/highlights.rs new file mode 100644 index 000000000..c6f0417ec --- /dev/null +++ b/crates/ide/src/syntax_highlighting/highlights.rs | |||
@@ -0,0 +1,102 @@ | |||
1 | //! Collects a tree of highlighted ranges and flattens it. | ||
2 | use std::{cmp::Ordering, iter}; | ||
3 | |||
4 | use stdx::equal_range_by; | ||
5 | use syntax::TextRange; | ||
6 | |||
7 | use crate::{HlRange, HlTag}; | ||
8 | |||
9 | pub(super) struct Highlights { | ||
10 | root: Node, | ||
11 | } | ||
12 | |||
13 | struct Node { | ||
14 | hl_range: HlRange, | ||
15 | nested: Vec<Node>, | ||
16 | } | ||
17 | |||
18 | impl Highlights { | ||
19 | pub(super) fn new(range: TextRange) -> Highlights { | ||
20 | Highlights { | ||
21 | root: Node::new(HlRange { range, highlight: HlTag::None.into(), binding_hash: None }), | ||
22 | } | ||
23 | } | ||
24 | |||
25 | pub(super) fn add(&mut self, hl_range: HlRange) { | ||
26 | self.root.add(hl_range); | ||
27 | } | ||
28 | |||
29 | pub(super) fn to_vec(self) -> Vec<HlRange> { | ||
30 | let mut res = Vec::new(); | ||
31 | self.root.flatten(&mut res); | ||
32 | res | ||
33 | } | ||
34 | } | ||
35 | |||
36 | impl Node { | ||
37 | fn new(hl_range: HlRange) -> Node { | ||
38 | Node { hl_range, nested: Vec::new() } | ||
39 | } | ||
40 | |||
41 | fn add(&mut self, hl_range: HlRange) { | ||
42 | assert!(self.hl_range.range.contains_range(hl_range.range)); | ||
43 | |||
44 | // Fast path | ||
45 | if let Some(last) = self.nested.last_mut() { | ||
46 | if last.hl_range.range.contains_range(hl_range.range) { | ||
47 | return last.add(hl_range); | ||
48 | } | ||
49 | if last.hl_range.range.end() <= hl_range.range.start() { | ||
50 | return self.nested.push(Node::new(hl_range)); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | let overlapping = | ||
55 | equal_range_by(&self.nested, |n| ordering(n.hl_range.range, hl_range.range)); | ||
56 | |||
57 | if overlapping.len() == 1 | ||
58 | && self.nested[overlapping.start].hl_range.range.contains_range(hl_range.range) | ||
59 | { | ||
60 | return self.nested[overlapping.start].add(hl_range); | ||
61 | } | ||
62 | |||
63 | let nested = self | ||
64 | .nested | ||
65 | .splice(overlapping.clone(), iter::once(Node::new(hl_range))) | ||
66 | .collect::<Vec<_>>(); | ||
67 | self.nested[overlapping.start].nested = nested; | ||
68 | } | ||
69 | |||
70 | fn flatten(&self, acc: &mut Vec<HlRange>) { | ||
71 | let mut start = self.hl_range.range.start(); | ||
72 | let mut nested = self.nested.iter(); | ||
73 | loop { | ||
74 | let next = nested.next(); | ||
75 | let end = next.map_or(self.hl_range.range.end(), |it| it.hl_range.range.start()); | ||
76 | if start < end { | ||
77 | acc.push(HlRange { | ||
78 | range: TextRange::new(start, end), | ||
79 | highlight: self.hl_range.highlight, | ||
80 | binding_hash: self.hl_range.binding_hash, | ||
81 | }); | ||
82 | } | ||
83 | start = match next { | ||
84 | Some(child) => { | ||
85 | child.flatten(acc); | ||
86 | child.hl_range.range.end() | ||
87 | } | ||
88 | None => break, | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | } | ||
93 | |||
94 | pub(super) fn ordering(r1: TextRange, r2: TextRange) -> Ordering { | ||
95 | if r1.end() <= r2.start() { | ||
96 | Ordering::Less | ||
97 | } else if r2.end() <= r1.start() { | ||
98 | Ordering::Greater | ||
99 | } else { | ||
100 | Ordering::Equal | ||
101 | } | ||
102 | } | ||
diff --git a/crates/ide/src/syntax_highlighting/html.rs b/crates/ide/src/syntax_highlighting/html.rs index 99ba3a59d..0ee7bc96e 100644 --- a/crates/ide/src/syntax_highlighting/html.rs +++ b/crates/ide/src/syntax_highlighting/html.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use ide_db::base_db::SourceDatabase; | 3 | use ide_db::base_db::SourceDatabase; |
4 | use oorandom::Rand32; | 4 | use oorandom::Rand32; |
5 | use stdx::format_to; | 5 | use stdx::format_to; |
6 | use syntax::{AstNode, TextRange, TextSize}; | 6 | use syntax::AstNode; |
7 | 7 | ||
8 | use crate::{syntax_highlighting::highlight, FileId, RootDatabase}; | 8 | use crate::{syntax_highlighting::highlight, FileId, RootDatabase}; |
9 | 9 | ||
@@ -20,35 +20,27 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo | |||
20 | ) | 20 | ) |
21 | } | 21 | } |
22 | 22 | ||
23 | let ranges = highlight(db, file_id, None, false); | 23 | let hl_ranges = highlight(db, file_id, None, false); |
24 | let text = parse.tree().syntax().to_string(); | 24 | let text = parse.tree().syntax().to_string(); |
25 | let mut prev_pos = TextSize::from(0); | ||
26 | let mut buf = String::new(); | 25 | let mut buf = String::new(); |
27 | buf.push_str(&STYLE); | 26 | buf.push_str(&STYLE); |
28 | buf.push_str("<pre><code>"); | 27 | buf.push_str("<pre><code>"); |
29 | for range in &ranges { | 28 | for r in &hl_ranges { |
30 | if range.range.start() > prev_pos { | 29 | let chunk = html_escape(&text[r.range]); |
31 | let curr = &text[TextRange::new(prev_pos, range.range.start())]; | 30 | if r.highlight.is_empty() { |
32 | let text = html_escape(curr); | 31 | format_to!(buf, "{}", chunk); |
33 | buf.push_str(&text); | 32 | continue; |
34 | } | 33 | } |
35 | let curr = &text[TextRange::new(range.range.start(), range.range.end())]; | ||
36 | 34 | ||
37 | let class = range.highlight.to_string().replace('.', " "); | 35 | let class = r.highlight.to_string().replace('.', " "); |
38 | let color = match (rainbow, range.binding_hash) { | 36 | let color = match (rainbow, r.binding_hash) { |
39 | (true, Some(hash)) => { | 37 | (true, Some(hash)) => { |
40 | format!(" data-binding-hash=\"{}\" style=\"color: {};\"", hash, rainbowify(hash)) | 38 | format!(" data-binding-hash=\"{}\" style=\"color: {};\"", hash, rainbowify(hash)) |
41 | } | 39 | } |
42 | _ => "".into(), | 40 | _ => "".into(), |
43 | }; | 41 | }; |
44 | format_to!(buf, "<span class=\"{}\"{}>{}</span>", class, color, html_escape(curr)); | 42 | format_to!(buf, "<span class=\"{}\"{}>{}</span>", class, color, chunk); |
45 | |||
46 | prev_pos = range.range.end(); | ||
47 | } | 43 | } |
48 | // Add the remaining (non-highlighted) text | ||
49 | let curr = &text[TextRange::new(prev_pos, TextSize::of(&text))]; | ||
50 | let text = html_escape(curr); | ||
51 | buf.push_str(&text); | ||
52 | buf.push_str("</code></pre>"); | 44 | buf.push_str("</code></pre>"); |
53 | buf | 45 | buf |
54 | } | 46 | } |
diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs new file mode 100644 index 000000000..281461493 --- /dev/null +++ b/crates/ide/src/syntax_highlighting/inject.rs | |||
@@ -0,0 +1,158 @@ | |||
1 | //! "Recursive" Syntax highlighting for code in doctests and fixtures. | ||
2 | |||
3 | use hir::Semantics; | ||
4 | use ide_db::call_info::ActiveParameter; | ||
5 | use syntax::{ast, AstToken, SyntaxNode, SyntaxToken, TextRange, TextSize}; | ||
6 | |||
7 | use crate::{Analysis, HlMod, HlRange, HlTag, RootDatabase}; | ||
8 | |||
9 | use super::{highlights::Highlights, injector::Injector}; | ||
10 | |||
11 | pub(super) fn ra_fixture( | ||
12 | hl: &mut Highlights, | ||
13 | sema: &Semantics<RootDatabase>, | ||
14 | literal: ast::String, | ||
15 | expanded: SyntaxToken, | ||
16 | ) -> Option<()> { | ||
17 | let active_parameter = ActiveParameter::at_token(&sema, expanded)?; | ||
18 | if !active_parameter.name.starts_with("ra_fixture") { | ||
19 | return None; | ||
20 | } | ||
21 | let value = literal.value()?; | ||
22 | |||
23 | if let Some(range) = literal.open_quote_text_range() { | ||
24 | hl.add(HlRange { range, highlight: HlTag::StringLiteral.into(), binding_hash: None }) | ||
25 | } | ||
26 | |||
27 | let mut inj = Injector::default(); | ||
28 | |||
29 | let mut text = &*value; | ||
30 | let mut offset: TextSize = 0.into(); | ||
31 | |||
32 | while !text.is_empty() { | ||
33 | let marker = "$0"; | ||
34 | let idx = text.find(marker).unwrap_or(text.len()); | ||
35 | let (chunk, next) = text.split_at(idx); | ||
36 | inj.add(chunk, TextRange::at(offset, TextSize::of(chunk))); | ||
37 | |||
38 | text = next; | ||
39 | offset += TextSize::of(chunk); | ||
40 | |||
41 | if let Some(next) = text.strip_prefix(marker) { | ||
42 | if let Some(range) = literal.map_range_up(TextRange::at(offset, TextSize::of(marker))) { | ||
43 | hl.add(HlRange { range, highlight: HlTag::Keyword.into(), binding_hash: None }); | ||
44 | } | ||
45 | |||
46 | text = next; | ||
47 | |||
48 | let marker_len = TextSize::of(marker); | ||
49 | offset += marker_len; | ||
50 | } | ||
51 | } | ||
52 | |||
53 | let (analysis, tmp_file_id) = Analysis::from_single_file(inj.text().to_string()); | ||
54 | |||
55 | for mut hl_range in analysis.highlight(tmp_file_id).unwrap() { | ||
56 | for range in inj.map_range_up(hl_range.range) { | ||
57 | if let Some(range) = literal.map_range_up(range) { | ||
58 | hl_range.range = range; | ||
59 | hl.add(hl_range.clone()); | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | |||
64 | if let Some(range) = literal.close_quote_text_range() { | ||
65 | hl.add(HlRange { range, highlight: HlTag::StringLiteral.into(), binding_hash: None }) | ||
66 | } | ||
67 | |||
68 | Some(()) | ||
69 | } | ||
70 | |||
71 | const RUSTDOC_FENCE: &'static str = "```"; | ||
72 | const RUSTDOC_FENCE_TOKENS: &[&'static str] = &[ | ||
73 | "", | ||
74 | "rust", | ||
75 | "should_panic", | ||
76 | "ignore", | ||
77 | "no_run", | ||
78 | "compile_fail", | ||
79 | "edition2015", | ||
80 | "edition2018", | ||
81 | "edition2021", | ||
82 | ]; | ||
83 | |||
84 | /// Injection of syntax highlighting of doctests. | ||
85 | pub(super) fn doc_comment(hl: &mut Highlights, node: &SyntaxNode) { | ||
86 | let doc_comments = node | ||
87 | .children_with_tokens() | ||
88 | .filter_map(|it| it.into_token().and_then(ast::Comment::cast)) | ||
89 | .filter(|it| it.kind().doc.is_some()); | ||
90 | |||
91 | if !doc_comments.clone().any(|it| it.text().contains(RUSTDOC_FENCE)) { | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | let mut inj = Injector::default(); | ||
96 | inj.add_unmapped("fn doctest() {\n"); | ||
97 | |||
98 | let mut is_codeblock = false; | ||
99 | let mut is_doctest = false; | ||
100 | |||
101 | // Replace the original, line-spanning comment ranges by new, only comment-prefix | ||
102 | // spanning comment ranges. | ||
103 | let mut new_comments = Vec::new(); | ||
104 | for comment in doc_comments { | ||
105 | match comment.text().find(RUSTDOC_FENCE) { | ||
106 | Some(idx) => { | ||
107 | is_codeblock = !is_codeblock; | ||
108 | // Check whether code is rust by inspecting fence guards | ||
109 | let guards = &comment.text()[idx + RUSTDOC_FENCE.len()..]; | ||
110 | let is_rust = | ||
111 | guards.split(',').all(|sub| RUSTDOC_FENCE_TOKENS.contains(&sub.trim())); | ||
112 | is_doctest = is_codeblock && is_rust; | ||
113 | continue; | ||
114 | } | ||
115 | None if !is_doctest => continue, | ||
116 | None => (), | ||
117 | } | ||
118 | |||
119 | let line: &str = comment.text().as_str(); | ||
120 | let range = comment.syntax().text_range(); | ||
121 | |||
122 | let mut pos = TextSize::of(comment.prefix()); | ||
123 | // whitespace after comment is ignored | ||
124 | if let Some(ws) = line[pos.into()..].chars().next().filter(|c| c.is_whitespace()) { | ||
125 | pos += TextSize::of(ws); | ||
126 | } | ||
127 | // lines marked with `#` should be ignored in output, we skip the `#` char | ||
128 | if let Some(ws) = line[pos.into()..].chars().next().filter(|&c| c == '#') { | ||
129 | pos += TextSize::of(ws); | ||
130 | } | ||
131 | |||
132 | new_comments.push(TextRange::at(range.start(), pos)); | ||
133 | |||
134 | inj.add(&line[pos.into()..], TextRange::new(range.start() + pos, range.end())); | ||
135 | inj.add_unmapped("\n"); | ||
136 | } | ||
137 | inj.add_unmapped("\n}"); | ||
138 | |||
139 | let (analysis, tmp_file_id) = Analysis::from_single_file(inj.text().to_string()); | ||
140 | |||
141 | for h in analysis.with_db(|db| super::highlight(db, tmp_file_id, None, true)).unwrap() { | ||
142 | for r in inj.map_range_up(h.range) { | ||
143 | hl.add(HlRange { | ||
144 | range: r, | ||
145 | highlight: h.highlight | HlMod::Injected, | ||
146 | binding_hash: h.binding_hash, | ||
147 | }); | ||
148 | } | ||
149 | } | ||
150 | |||
151 | for range in new_comments { | ||
152 | hl.add(HlRange { | ||
153 | range, | ||
154 | highlight: HlTag::Comment | HlMod::Documentation, | ||
155 | binding_hash: None, | ||
156 | }); | ||
157 | } | ||
158 | } | ||
diff --git a/crates/ide/src/syntax_highlighting/injection.rs b/crates/ide/src/syntax_highlighting/injection.rs deleted file mode 100644 index 6cbd683c6..000000000 --- a/crates/ide/src/syntax_highlighting/injection.rs +++ /dev/null | |||
@@ -1,192 +0,0 @@ | |||
1 | //! Syntax highlighting injections such as highlighting of documentation tests. | ||
2 | |||
3 | use std::{collections::BTreeMap, convert::TryFrom}; | ||
4 | |||
5 | use hir::Semantics; | ||
6 | use ide_db::call_info::ActiveParameter; | ||
7 | use itertools::Itertools; | ||
8 | use syntax::{ast, AstToken, SyntaxNode, SyntaxToken, TextRange, TextSize}; | ||
9 | |||
10 | use crate::{Analysis, Highlight, HighlightModifier, HighlightTag, HighlightedRange, RootDatabase}; | ||
11 | |||
12 | use super::HighlightedRangeStack; | ||
13 | |||
14 | pub(super) fn highlight_injection( | ||
15 | acc: &mut HighlightedRangeStack, | ||
16 | sema: &Semantics<RootDatabase>, | ||
17 | literal: ast::String, | ||
18 | expanded: SyntaxToken, | ||
19 | ) -> Option<()> { | ||
20 | let active_parameter = ActiveParameter::at_token(&sema, expanded)?; | ||
21 | if !active_parameter.name.starts_with("ra_fixture") { | ||
22 | return None; | ||
23 | } | ||
24 | let value = literal.value()?; | ||
25 | let (analysis, tmp_file_id) = Analysis::from_single_file(value.into_owned()); | ||
26 | |||
27 | if let Some(range) = literal.open_quote_text_range() { | ||
28 | acc.add(HighlightedRange { | ||
29 | range, | ||
30 | highlight: HighlightTag::StringLiteral.into(), | ||
31 | binding_hash: None, | ||
32 | }) | ||
33 | } | ||
34 | |||
35 | for mut h in analysis.highlight(tmp_file_id).unwrap() { | ||
36 | if let Some(r) = literal.map_range_up(h.range) { | ||
37 | h.range = r; | ||
38 | acc.add(h) | ||
39 | } | ||
40 | } | ||
41 | |||
42 | if let Some(range) = literal.close_quote_text_range() { | ||
43 | acc.add(HighlightedRange { | ||
44 | range, | ||
45 | highlight: HighlightTag::StringLiteral.into(), | ||
46 | binding_hash: None, | ||
47 | }) | ||
48 | } | ||
49 | |||
50 | Some(()) | ||
51 | } | ||
52 | |||
53 | /// Mapping from extracted documentation code to original code | ||
54 | type RangesMap = BTreeMap<TextSize, TextSize>; | ||
55 | |||
56 | const RUSTDOC_FENCE: &'static str = "```"; | ||
57 | const RUSTDOC_FENCE_TOKENS: &[&'static str] = &[ | ||
58 | "", | ||
59 | "rust", | ||
60 | "should_panic", | ||
61 | "ignore", | ||
62 | "no_run", | ||
63 | "compile_fail", | ||
64 | "edition2015", | ||
65 | "edition2018", | ||
66 | "edition2021", | ||
67 | ]; | ||
68 | |||
69 | /// Extracts Rust code from documentation comments as well as a mapping from | ||
70 | /// the extracted source code back to the original source ranges. | ||
71 | /// Lastly, a vector of new comment highlight ranges (spanning only the | ||
72 | /// comment prefix) is returned which is used in the syntax highlighting | ||
73 | /// injection to replace the previous (line-spanning) comment ranges. | ||
74 | pub(super) fn extract_doc_comments( | ||
75 | node: &SyntaxNode, | ||
76 | ) -> Option<(String, RangesMap, Vec<HighlightedRange>)> { | ||
77 | // wrap the doctest into function body to get correct syntax highlighting | ||
78 | let prefix = "fn doctest() {\n"; | ||
79 | let suffix = "}\n"; | ||
80 | // Mapping from extracted documentation code to original code | ||
81 | let mut range_mapping: RangesMap = BTreeMap::new(); | ||
82 | let mut line_start = TextSize::try_from(prefix.len()).unwrap(); | ||
83 | let mut is_codeblock = false; | ||
84 | let mut is_doctest = false; | ||
85 | // Replace the original, line-spanning comment ranges by new, only comment-prefix | ||
86 | // spanning comment ranges. | ||
87 | let mut new_comments = Vec::new(); | ||
88 | let doctest = node | ||
89 | .children_with_tokens() | ||
90 | .filter_map(|el| el.into_token().and_then(ast::Comment::cast)) | ||
91 | .filter(|comment| comment.kind().doc.is_some()) | ||
92 | .filter(|comment| { | ||
93 | if let Some(idx) = comment.text().find(RUSTDOC_FENCE) { | ||
94 | is_codeblock = !is_codeblock; | ||
95 | // Check whether code is rust by inspecting fence guards | ||
96 | let guards = &comment.text()[idx + RUSTDOC_FENCE.len()..]; | ||
97 | let is_rust = | ||
98 | guards.split(',').all(|sub| RUSTDOC_FENCE_TOKENS.contains(&sub.trim())); | ||
99 | is_doctest = is_codeblock && is_rust; | ||
100 | false | ||
101 | } else { | ||
102 | is_doctest | ||
103 | } | ||
104 | }) | ||
105 | .map(|comment| { | ||
106 | let prefix_len = comment.prefix().len(); | ||
107 | let line: &str = comment.text().as_str(); | ||
108 | let range = comment.syntax().text_range(); | ||
109 | |||
110 | // whitespace after comment is ignored | ||
111 | let pos = if let Some(ws) = line.chars().nth(prefix_len).filter(|c| c.is_whitespace()) { | ||
112 | prefix_len + ws.len_utf8() | ||
113 | } else { | ||
114 | prefix_len | ||
115 | }; | ||
116 | |||
117 | // lines marked with `#` should be ignored in output, we skip the `#` char | ||
118 | let pos = if let Some(ws) = line.chars().nth(pos).filter(|&c| c == '#') { | ||
119 | pos + ws.len_utf8() | ||
120 | } else { | ||
121 | pos | ||
122 | }; | ||
123 | |||
124 | range_mapping.insert(line_start, range.start() + TextSize::try_from(pos).unwrap()); | ||
125 | new_comments.push(HighlightedRange { | ||
126 | range: TextRange::new( | ||
127 | range.start(), | ||
128 | range.start() + TextSize::try_from(pos).unwrap(), | ||
129 | ), | ||
130 | highlight: HighlightTag::Comment | HighlightModifier::Documentation, | ||
131 | binding_hash: None, | ||
132 | }); | ||
133 | line_start += range.len() - TextSize::try_from(pos).unwrap(); | ||
134 | line_start += TextSize::try_from('\n'.len_utf8()).unwrap(); | ||
135 | |||
136 | line[pos..].to_owned() | ||
137 | }) | ||
138 | .join("\n"); | ||
139 | |||
140 | if doctest.is_empty() { | ||
141 | return None; | ||
142 | } | ||
143 | |||
144 | let doctest = format!("{}{}{}", prefix, doctest, suffix); | ||
145 | Some((doctest, range_mapping, new_comments)) | ||
146 | } | ||
147 | |||
148 | /// Injection of syntax highlighting of doctests. | ||
149 | pub(super) fn highlight_doc_comment( | ||
150 | text: String, | ||
151 | range_mapping: RangesMap, | ||
152 | new_comments: Vec<HighlightedRange>, | ||
153 | stack: &mut HighlightedRangeStack, | ||
154 | ) { | ||
155 | let (analysis, tmp_file_id) = Analysis::from_single_file(text); | ||
156 | |||
157 | stack.push(); | ||
158 | for mut h in analysis.with_db(|db| super::highlight(db, tmp_file_id, None, true)).unwrap() { | ||
159 | // Determine start offset and end offset in case of multi-line ranges | ||
160 | let mut start_offset = None; | ||
161 | let mut end_offset = None; | ||
162 | for (line_start, orig_line_start) in range_mapping.range(..h.range.end()).rev() { | ||
163 | // It's possible for orig_line_start - line_start to be negative. Add h.range.start() | ||
164 | // here and remove it from the end range after the loop below so that the values are | ||
165 | // always non-negative. | ||
166 | let offset = h.range.start() + orig_line_start - line_start; | ||
167 | if line_start <= &h.range.start() { | ||
168 | start_offset.get_or_insert(offset); | ||
169 | break; | ||
170 | } else { | ||
171 | end_offset.get_or_insert(offset); | ||
172 | } | ||
173 | } | ||
174 | if let Some(start_offset) = start_offset { | ||
175 | h.range = TextRange::new( | ||
176 | start_offset, | ||
177 | h.range.end() + end_offset.unwrap_or(start_offset) - h.range.start(), | ||
178 | ); | ||
179 | |||
180 | h.highlight |= HighlightModifier::Injected; | ||
181 | stack.add(h); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | // Inject the comment prefix highlight ranges | ||
186 | stack.push(); | ||
187 | for comment in new_comments { | ||
188 | stack.add(comment); | ||
189 | } | ||
190 | stack.pop_and_inject(None); | ||
191 | stack.pop_and_inject(Some(Highlight::from(HighlightTag::Dummy) | HighlightModifier::Injected)); | ||
192 | } | ||
diff --git a/crates/ide/src/syntax_highlighting/injector.rs b/crates/ide/src/syntax_highlighting/injector.rs new file mode 100644 index 000000000..fd4025694 --- /dev/null +++ b/crates/ide/src/syntax_highlighting/injector.rs | |||
@@ -0,0 +1,80 @@ | |||
1 | //! Extracts a subsequence of a text document, remembering the mapping of ranges | ||
2 | //! between original and extracted texts. | ||
3 | use std::ops::{self, Sub}; | ||
4 | |||
5 | use stdx::equal_range_by; | ||
6 | use syntax::{TextRange, TextSize}; | ||
7 | |||
8 | use super::highlights::ordering; | ||
9 | |||
10 | #[derive(Default)] | ||
11 | pub(super) struct Injector { | ||
12 | buf: String, | ||
13 | ranges: Vec<(TextRange, Option<Delta<TextSize>>)>, | ||
14 | } | ||
15 | |||
16 | impl Injector { | ||
17 | pub(super) fn add(&mut self, text: &str, source_range: TextRange) { | ||
18 | let len = TextSize::of(text); | ||
19 | assert_eq!(len, source_range.len()); | ||
20 | self.add_impl(text, Some(source_range.start())); | ||
21 | } | ||
22 | pub(super) fn add_unmapped(&mut self, text: &str) { | ||
23 | self.add_impl(text, None); | ||
24 | } | ||
25 | fn add_impl(&mut self, text: &str, source: Option<TextSize>) { | ||
26 | let len = TextSize::of(text); | ||
27 | let target_range = TextRange::at(TextSize::of(&self.buf), len); | ||
28 | self.ranges.push((target_range, source.map(|it| Delta::new(target_range.start(), it)))); | ||
29 | self.buf.push_str(text); | ||
30 | } | ||
31 | |||
32 | pub(super) fn text(&self) -> &str { | ||
33 | &self.buf | ||
34 | } | ||
35 | pub(super) fn map_range_up(&self, range: TextRange) -> impl Iterator<Item = TextRange> + '_ { | ||
36 | equal_range_by(&self.ranges, |&(r, _)| ordering(r, range)).filter_map(move |i| { | ||
37 | let (target_range, delta) = self.ranges[i]; | ||
38 | let intersection = target_range.intersect(range).unwrap(); | ||
39 | Some(intersection + delta?) | ||
40 | }) | ||
41 | } | ||
42 | } | ||
43 | |||
44 | #[derive(Clone, Copy)] | ||
45 | enum Delta<T> { | ||
46 | Add(T), | ||
47 | Sub(T), | ||
48 | } | ||
49 | |||
50 | impl<T> Delta<T> { | ||
51 | fn new(from: T, to: T) -> Delta<T> | ||
52 | where | ||
53 | T: Ord + Sub<Output = T>, | ||
54 | { | ||
55 | if to >= from { | ||
56 | Delta::Add(to - from) | ||
57 | } else { | ||
58 | Delta::Sub(from - to) | ||
59 | } | ||
60 | } | ||
61 | } | ||
62 | |||
63 | impl ops::Add<Delta<TextSize>> for TextSize { | ||
64 | type Output = TextSize; | ||
65 | |||
66 | fn add(self, rhs: Delta<TextSize>) -> TextSize { | ||
67 | match rhs { | ||
68 | Delta::Add(it) => self + it, | ||
69 | Delta::Sub(it) => self - it, | ||
70 | } | ||
71 | } | ||
72 | } | ||
73 | |||
74 | impl ops::Add<Delta<TextSize>> for TextRange { | ||
75 | type Output = TextRange; | ||
76 | |||
77 | fn add(self, rhs: Delta<TextSize>) -> TextRange { | ||
78 | TextRange::at(self.start() + rhs, self.len()) | ||
79 | } | ||
80 | } | ||
diff --git a/crates/ide/src/syntax_highlighting/macro_rules.rs b/crates/ide/src/syntax_highlighting/macro_rules.rs index 4462af47e..44620e912 100644 --- a/crates/ide/src/syntax_highlighting/macro_rules.rs +++ b/crates/ide/src/syntax_highlighting/macro_rules.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! Syntax highlighting for macro_rules!. | 1 | //! Syntax highlighting for macro_rules!. |
2 | use syntax::{SyntaxElement, SyntaxKind, SyntaxToken, TextRange, T}; | 2 | use syntax::{SyntaxElement, SyntaxKind, SyntaxToken, TextRange, T}; |
3 | 3 | ||
4 | use crate::{HighlightTag, HighlightedRange}; | 4 | use crate::{HlRange, HlTag}; |
5 | 5 | ||
6 | #[derive(Default)] | 6 | #[derive(Default)] |
7 | pub(super) struct MacroRulesHighlighter { | 7 | pub(super) struct MacroRulesHighlighter { |
@@ -19,13 +19,13 @@ impl MacroRulesHighlighter { | |||
19 | } | 19 | } |
20 | } | 20 | } |
21 | 21 | ||
22 | pub(super) fn highlight(&self, element: SyntaxElement) -> Option<HighlightedRange> { | 22 | pub(super) fn highlight(&self, element: SyntaxElement) -> Option<HlRange> { |
23 | if let Some(state) = self.state.as_ref() { | 23 | if let Some(state) = self.state.as_ref() { |
24 | if matches!(state.rule_state, RuleState::Matcher | RuleState::Expander) { | 24 | if matches!(state.rule_state, RuleState::Matcher | RuleState::Expander) { |
25 | if let Some(range) = is_metavariable(element) { | 25 | if let Some(range) = is_metavariable(element) { |
26 | return Some(HighlightedRange { | 26 | return Some(HlRange { |
27 | range, | 27 | range, |
28 | highlight: HighlightTag::UnresolvedReference.into(), | 28 | highlight: HlTag::UnresolvedReference.into(), |
29 | binding_hash: None, | 29 | binding_hash: None, |
30 | }); | 30 | }); |
31 | } | 31 | } |
@@ -119,7 +119,7 @@ fn is_metavariable(element: SyntaxElement) -> Option<TextRange> { | |||
119 | let tok = element.as_token()?; | 119 | let tok = element.as_token()?; |
120 | match tok.kind() { | 120 | match tok.kind() { |
121 | kind if kind == SyntaxKind::IDENT || kind.is_keyword() => { | 121 | kind if kind == SyntaxKind::IDENT || kind.is_keyword() => { |
122 | if let Some(_dollar) = tok.prev_token().filter(|t| t.kind() == SyntaxKind::DOLLAR) { | 122 | if let Some(_dollar) = tok.prev_token().filter(|t| t.kind() == T![$]) { |
123 | return Some(tok.text_range()); | 123 | return Some(tok.text_range()); |
124 | } | 124 | } |
125 | } | 125 | } |
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs index 8b8867079..8dd05ac52 100644 --- a/crates/ide/src/syntax_highlighting/tags.rs +++ b/crates/ide/src/syntax_highlighting/tags.rs | |||
@@ -7,15 +7,15 @@ use crate::SymbolKind; | |||
7 | 7 | ||
8 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] | 8 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] |
9 | pub struct Highlight { | 9 | pub struct Highlight { |
10 | pub tag: HighlightTag, | 10 | pub tag: HlTag, |
11 | pub modifiers: HighlightModifiers, | 11 | pub mods: HlMods, |
12 | } | 12 | } |
13 | 13 | ||
14 | #[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] | 14 | #[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] |
15 | pub struct HighlightModifiers(u32); | 15 | pub struct HlMods(u32); |
16 | 16 | ||
17 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] | 17 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] |
18 | pub enum HighlightTag { | 18 | pub enum HlTag { |
19 | Symbol(SymbolKind), | 19 | Symbol(SymbolKind), |
20 | 20 | ||
21 | BoolLiteral, | 21 | BoolLiteral, |
@@ -29,17 +29,17 @@ pub enum HighlightTag { | |||
29 | EscapeSequence, | 29 | EscapeSequence, |
30 | FormatSpecifier, | 30 | FormatSpecifier, |
31 | Keyword, | 31 | Keyword, |
32 | Punctuation, | 32 | Punctuation(HlPunct), |
33 | Operator, | 33 | Operator, |
34 | UnresolvedReference, | 34 | UnresolvedReference, |
35 | 35 | ||
36 | // For things which don't have proper Tag, but want to use modifiers. | 36 | // For things which don't have a specific highlight. |
37 | Dummy, | 37 | None, |
38 | } | 38 | } |
39 | 39 | ||
40 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] | 40 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] |
41 | #[repr(u8)] | 41 | #[repr(u8)] |
42 | pub enum HighlightModifier { | 42 | pub enum HlMod { |
43 | /// Used to differentiate individual elements within attributes. | 43 | /// Used to differentiate individual elements within attributes. |
44 | Attribute = 0, | 44 | Attribute = 0, |
45 | /// Used with keywords like `if` and `break`. | 45 | /// Used with keywords like `if` and `break`. |
@@ -61,10 +61,32 @@ pub enum HighlightModifier { | |||
61 | Unsafe, | 61 | Unsafe, |
62 | } | 62 | } |
63 | 63 | ||
64 | impl HighlightTag { | 64 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] |
65 | pub enum HlPunct { | ||
66 | /// [] | ||
67 | Bracket, | ||
68 | /// {} | ||
69 | Brace, | ||
70 | /// () | ||
71 | Parenthesis, | ||
72 | /// <> | ||
73 | Angle, | ||
74 | /// , | ||
75 | Comma, | ||
76 | /// . | ||
77 | Dot, | ||
78 | /// : | ||
79 | Colon, | ||
80 | /// ; | ||
81 | Semi, | ||
82 | /// | ||
83 | Other, | ||
84 | } | ||
85 | |||
86 | impl HlTag { | ||
65 | fn as_str(self) -> &'static str { | 87 | fn as_str(self) -> &'static str { |
66 | match self { | 88 | match self { |
67 | HighlightTag::Symbol(symbol) => match symbol { | 89 | HlTag::Symbol(symbol) => match symbol { |
68 | SymbolKind::Const => "constant", | 90 | SymbolKind::Const => "constant", |
69 | SymbolKind::Static => "static", | 91 | SymbolKind::Static => "static", |
70 | SymbolKind::Enum => "enum", | 92 | SymbolKind::Enum => "enum", |
@@ -86,59 +108,69 @@ impl HighlightTag { | |||
86 | SymbolKind::SelfParam => "self_keyword", | 108 | SymbolKind::SelfParam => "self_keyword", |
87 | SymbolKind::Impl => "self_type", | 109 | SymbolKind::Impl => "self_type", |
88 | }, | 110 | }, |
89 | HighlightTag::Attribute => "attribute", | 111 | HlTag::Attribute => "attribute", |
90 | HighlightTag::BoolLiteral => "bool_literal", | 112 | HlTag::BoolLiteral => "bool_literal", |
91 | HighlightTag::BuiltinType => "builtin_type", | 113 | HlTag::BuiltinType => "builtin_type", |
92 | HighlightTag::ByteLiteral => "byte_literal", | 114 | HlTag::ByteLiteral => "byte_literal", |
93 | HighlightTag::CharLiteral => "char_literal", | 115 | HlTag::CharLiteral => "char_literal", |
94 | HighlightTag::Comment => "comment", | 116 | HlTag::Comment => "comment", |
95 | HighlightTag::EscapeSequence => "escape_sequence", | 117 | HlTag::EscapeSequence => "escape_sequence", |
96 | HighlightTag::FormatSpecifier => "format_specifier", | 118 | HlTag::FormatSpecifier => "format_specifier", |
97 | HighlightTag::Dummy => "dummy", | 119 | HlTag::Keyword => "keyword", |
98 | HighlightTag::Keyword => "keyword", | 120 | HlTag::Punctuation(punct) => match punct { |
99 | HighlightTag::Punctuation => "punctuation", | 121 | HlPunct::Bracket => "bracket", |
100 | HighlightTag::NumericLiteral => "numeric_literal", | 122 | HlPunct::Brace => "brace", |
101 | HighlightTag::Operator => "operator", | 123 | HlPunct::Parenthesis => "parenthesis", |
102 | HighlightTag::StringLiteral => "string_literal", | 124 | HlPunct::Angle => "angle", |
103 | HighlightTag::UnresolvedReference => "unresolved_reference", | 125 | HlPunct::Comma => "comma", |
126 | HlPunct::Dot => "dot", | ||
127 | HlPunct::Colon => "colon", | ||
128 | HlPunct::Semi => "semicolon", | ||
129 | HlPunct::Other => "punctuation", | ||
130 | }, | ||
131 | HlTag::NumericLiteral => "numeric_literal", | ||
132 | HlTag::Operator => "operator", | ||
133 | HlTag::StringLiteral => "string_literal", | ||
134 | HlTag::UnresolvedReference => "unresolved_reference", | ||
135 | HlTag::None => "none", | ||
104 | } | 136 | } |
105 | } | 137 | } |
106 | } | 138 | } |
107 | 139 | ||
108 | impl fmt::Display for HighlightTag { | 140 | impl fmt::Display for HlTag { |
109 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 141 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
110 | fmt::Display::fmt(self.as_str(), f) | 142 | fmt::Display::fmt(self.as_str(), f) |
111 | } | 143 | } |
112 | } | 144 | } |
113 | 145 | ||
114 | impl HighlightModifier { | 146 | impl HlMod { |
115 | const ALL: &'static [HighlightModifier; HighlightModifier::Unsafe as u8 as usize + 1] = &[ | 147 | const ALL: &'static [HlMod; HlMod::Unsafe as u8 as usize + 1] = &[ |
116 | HighlightModifier::Attribute, | 148 | HlMod::Attribute, |
117 | HighlightModifier::ControlFlow, | 149 | HlMod::ControlFlow, |
118 | HighlightModifier::Definition, | 150 | HlMod::Definition, |
119 | HighlightModifier::Documentation, | 151 | HlMod::Documentation, |
120 | HighlightModifier::Injected, | 152 | HlMod::Injected, |
121 | HighlightModifier::Mutable, | 153 | HlMod::Mutable, |
122 | HighlightModifier::Consuming, | 154 | HlMod::Consuming, |
123 | HighlightModifier::Callable, | 155 | HlMod::Callable, |
124 | HighlightModifier::Static, | 156 | HlMod::Static, |
125 | HighlightModifier::Associated, | 157 | HlMod::Associated, |
126 | HighlightModifier::Unsafe, | 158 | HlMod::Unsafe, |
127 | ]; | 159 | ]; |
128 | 160 | ||
129 | fn as_str(self) -> &'static str { | 161 | fn as_str(self) -> &'static str { |
130 | match self { | 162 | match self { |
131 | HighlightModifier::Attribute => "attribute", | 163 | HlMod::Attribute => "attribute", |
132 | HighlightModifier::ControlFlow => "control", | 164 | HlMod::ControlFlow => "control", |
133 | HighlightModifier::Definition => "declaration", | 165 | HlMod::Definition => "declaration", |
134 | HighlightModifier::Documentation => "documentation", | 166 | HlMod::Documentation => "documentation", |
135 | HighlightModifier::Injected => "injected", | 167 | HlMod::Injected => "injected", |
136 | HighlightModifier::Mutable => "mutable", | 168 | HlMod::Mutable => "mutable", |
137 | HighlightModifier::Consuming => "consuming", | 169 | HlMod::Consuming => "consuming", |
138 | HighlightModifier::Unsafe => "unsafe", | 170 | HlMod::Unsafe => "unsafe", |
139 | HighlightModifier::Callable => "callable", | 171 | HlMod::Callable => "callable", |
140 | HighlightModifier::Static => "static", | 172 | HlMod::Static => "static", |
141 | HighlightModifier::Associated => "associated", | 173 | HlMod::Associated => "associated", |
142 | } | 174 | } |
143 | } | 175 | } |
144 | 176 | ||
@@ -147,7 +179,7 @@ impl HighlightModifier { | |||
147 | } | 179 | } |
148 | } | 180 | } |
149 | 181 | ||
150 | impl fmt::Display for HighlightModifier { | 182 | impl fmt::Display for HlMod { |
151 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 183 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
152 | fmt::Display::fmt(self.as_str(), f) | 184 | fmt::Display::fmt(self.as_str(), f) |
153 | } | 185 | } |
@@ -156,60 +188,63 @@ impl fmt::Display for HighlightModifier { | |||
156 | impl fmt::Display for Highlight { | 188 | impl fmt::Display for Highlight { |
157 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 189 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
158 | write!(f, "{}", self.tag)?; | 190 | write!(f, "{}", self.tag)?; |
159 | for modifier in self.modifiers.iter() { | 191 | for modifier in self.mods.iter() { |
160 | write!(f, ".{}", modifier)? | 192 | write!(f, ".{}", modifier)? |
161 | } | 193 | } |
162 | Ok(()) | 194 | Ok(()) |
163 | } | 195 | } |
164 | } | 196 | } |
165 | 197 | ||
166 | impl From<HighlightTag> for Highlight { | 198 | impl From<HlTag> for Highlight { |
167 | fn from(tag: HighlightTag) -> Highlight { | 199 | fn from(tag: HlTag) -> Highlight { |
168 | Highlight::new(tag) | 200 | Highlight::new(tag) |
169 | } | 201 | } |
170 | } | 202 | } |
171 | 203 | ||
172 | impl Highlight { | 204 | impl Highlight { |
173 | pub(crate) fn new(tag: HighlightTag) -> Highlight { | 205 | pub(crate) fn new(tag: HlTag) -> Highlight { |
174 | Highlight { tag, modifiers: HighlightModifiers::default() } | 206 | Highlight { tag, mods: HlMods::default() } |
207 | } | ||
208 | pub fn is_empty(&self) -> bool { | ||
209 | self.tag == HlTag::None && self.mods == HlMods::default() | ||
175 | } | 210 | } |
176 | } | 211 | } |
177 | 212 | ||
178 | impl ops::BitOr<HighlightModifier> for HighlightTag { | 213 | impl ops::BitOr<HlMod> for HlTag { |
179 | type Output = Highlight; | 214 | type Output = Highlight; |
180 | 215 | ||
181 | fn bitor(self, rhs: HighlightModifier) -> Highlight { | 216 | fn bitor(self, rhs: HlMod) -> Highlight { |
182 | Highlight::new(self) | rhs | 217 | Highlight::new(self) | rhs |
183 | } | 218 | } |
184 | } | 219 | } |
185 | 220 | ||
186 | impl ops::BitOrAssign<HighlightModifier> for HighlightModifiers { | 221 | impl ops::BitOrAssign<HlMod> for HlMods { |
187 | fn bitor_assign(&mut self, rhs: HighlightModifier) { | 222 | fn bitor_assign(&mut self, rhs: HlMod) { |
188 | self.0 |= rhs.mask(); | 223 | self.0 |= rhs.mask(); |
189 | } | 224 | } |
190 | } | 225 | } |
191 | 226 | ||
192 | impl ops::BitOrAssign<HighlightModifier> for Highlight { | 227 | impl ops::BitOrAssign<HlMod> for Highlight { |
193 | fn bitor_assign(&mut self, rhs: HighlightModifier) { | 228 | fn bitor_assign(&mut self, rhs: HlMod) { |
194 | self.modifiers |= rhs; | 229 | self.mods |= rhs; |
195 | } | 230 | } |
196 | } | 231 | } |
197 | 232 | ||
198 | impl ops::BitOr<HighlightModifier> for Highlight { | 233 | impl ops::BitOr<HlMod> for Highlight { |
199 | type Output = Highlight; | 234 | type Output = Highlight; |
200 | 235 | ||
201 | fn bitor(mut self, rhs: HighlightModifier) -> Highlight { | 236 | fn bitor(mut self, rhs: HlMod) -> Highlight { |
202 | self |= rhs; | 237 | self |= rhs; |
203 | self | 238 | self |
204 | } | 239 | } |
205 | } | 240 | } |
206 | 241 | ||
207 | impl HighlightModifiers { | 242 | impl HlMods { |
208 | pub fn contains(self, m: HighlightModifier) -> bool { | 243 | pub fn contains(self, m: HlMod) -> bool { |
209 | self.0 & m.mask() == m.mask() | 244 | self.0 & m.mask() == m.mask() |
210 | } | 245 | } |
211 | 246 | ||
212 | pub fn iter(self) -> impl Iterator<Item = HighlightModifier> { | 247 | pub fn iter(self) -> impl Iterator<Item = HlMod> { |
213 | HighlightModifier::ALL.iter().copied().filter(move |it| self.0 & it.mask() == it.mask()) | 248 | HlMod::ALL.iter().copied().filter(move |it| self.0 & it.mask() == it.mask()) |
214 | } | 249 | } |
215 | } | 250 | } |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html index 506ebe60e..e36e6fc3f 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html | |||
@@ -36,22 +36,22 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
36 | 36 | ||
37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } | 37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } |
38 | </style> | 38 | </style> |
39 | <pre><code><span class="keyword">fn</span> <span class="function declaration">not_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 39 | <pre><code><span class="keyword">fn</span> <span class="function declaration">not_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
40 | 40 | ||
41 | <span class="keyword">struct</span> <span class="struct declaration">foo</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 41 | <span class="keyword">struct</span> <span class="struct declaration">foo</span> <span class="brace">{</span><span class="brace">}</span> |
42 | 42 | ||
43 | <span class="keyword">impl</span> <span class="struct">foo</span> <span class="punctuation">{</span> | 43 | <span class="keyword">impl</span> <span class="struct">foo</span> <span class="brace">{</span> |
44 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 44 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
45 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 45 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
46 | <span class="punctuation">}</span> | 46 | <span class="brace">}</span> |
47 | 47 | ||
48 | <span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="punctuation">{</span> | 48 | <span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="brace">{</span> |
49 | <span class="keyword">fn</span> <span class="function declaration static associated">t_is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 49 | <span class="keyword">fn</span> <span class="function declaration static associated">t_is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
50 | <span class="keyword">fn</span> <span class="function declaration associated">t_is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 50 | <span class="keyword">fn</span> <span class="function declaration associated">t_is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
51 | <span class="punctuation">}</span> | 51 | <span class="brace">}</span> |
52 | 52 | ||
53 | <span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="punctuation">{</span> | 53 | <span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="brace">{</span> |
54 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 54 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
55 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 55 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
56 | <span class="punctuation">}</span> | 56 | <span class="brace">}</span> |
57 | </code></pre> \ No newline at end of file | 57 | </code></pre> \ No newline at end of file |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html index 4dd7413ba..6dadda1c1 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html | |||
@@ -37,67 +37,72 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } | 37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } |
38 | </style> | 38 | </style> |
39 | <pre><code><span class="comment documentation">/// ```</span> | 39 | <pre><code><span class="comment documentation">/// ```</span> |
40 | <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="punctuation injected">_</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="string_literal injected">"early doctests should not go boom"</span><span class="punctuation injected">;</span><span class="punctuation injected"> | 40 | <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="punctuation injected">_</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="string_literal injected">"early doctests should not go boom"</span><span class="semicolon injected">;</span> |
41 | </span><span class="comment documentation">/// ```</span> | 41 | <span class="comment documentation">/// ```</span> |
42 | <span class="keyword">struct</span> <span class="struct declaration">Foo</span> <span class="punctuation">{</span> | 42 | <span class="keyword">struct</span> <span class="struct declaration">Foo</span> <span class="brace">{</span> |
43 | <span class="field declaration">bar</span><span class="punctuation">:</span> <span class="builtin_type">bool</span><span class="punctuation">,</span> | 43 | <span class="field declaration">bar</span><span class="colon">:</span> <span class="builtin_type">bool</span><span class="comma">,</span> |
44 | <span class="punctuation">}</span> | 44 | <span class="brace">}</span> |
45 | 45 | ||
46 | <span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span> | 46 | <span class="keyword">impl</span> <span class="struct">Foo</span> <span class="brace">{</span> |
47 | <span class="keyword">pub</span> <span class="keyword">const</span> <span class="constant declaration associated">bar</span><span class="punctuation">:</span> <span class="builtin_type">bool</span> <span class="operator">=</span> <span class="bool_literal">true</span><span class="punctuation">;</span> | 47 | <span class="comment documentation">/// ```</span> |
48 | <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="punctuation injected">_</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="string_literal injected">"Call me</span> | ||
49 | <span class="comment">// KILLER WHALE</span> | ||
50 | <span class="comment documentation">/// </span><span class="string_literal injected"> Ishmael."</span><span class="semicolon injected">;</span> | ||
51 | <span class="comment documentation">/// ```</span> | ||
52 | <span class="keyword">pub</span> <span class="keyword">const</span> <span class="constant declaration associated">bar</span><span class="colon">:</span> <span class="builtin_type">bool</span> <span class="operator">=</span> <span class="bool_literal">true</span><span class="semicolon">;</span> | ||
48 | 53 | ||
49 | <span class="comment documentation">/// Constructs a new `Foo`.</span> | 54 | <span class="comment documentation">/// Constructs a new `Foo`.</span> |
50 | <span class="comment documentation">///</span> | 55 | <span class="comment documentation">///</span> |
51 | <span class="comment documentation">/// # Examples</span> | 56 | <span class="comment documentation">/// # Examples</span> |
52 | <span class="comment documentation">///</span> | 57 | <span class="comment documentation">///</span> |
53 | <span class="comment documentation">/// ```</span> | 58 | <span class="comment documentation">/// ```</span> |
54 | <span class="comment documentation">/// #</span><span class="dummy injected"> </span><span class="attribute attribute injected">#</span><span class="attribute attribute injected">!</span><span class="attribute attribute injected">[</span><span class="function attribute injected">allow</span><span class="punctuation attribute injected">(</span><span class="attribute attribute injected">unused_mut</span><span class="punctuation attribute injected">)</span><span class="attribute attribute injected">]</span> | 59 | <span class="comment documentation">/// #</span><span class="none injected"> </span><span class="attribute attribute injected">#</span><span class="attribute attribute injected">!</span><span class="attribute attribute injected">[</span><span class="function attribute injected">allow</span><span class="parenthesis attribute injected">(</span><span class="attribute attribute injected">unused_mut</span><span class="parenthesis attribute injected">)</span><span class="attribute attribute injected">]</span> |
55 | <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="keyword injected">mut</span><span class="dummy injected"> </span><span class="variable declaration injected mutable">foo</span><span class="punctuation injected">:</span><span class="dummy injected"> </span><span class="struct injected">Foo</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected"> | 60 | <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="keyword injected">mut</span><span class="none injected"> </span><span class="variable declaration injected mutable">foo</span><span class="colon injected">:</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span> |
56 | </span> <span class="comment documentation">/// ```</span> | 61 | <span class="comment documentation">/// ```</span> |
57 | <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration static associated">new</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="struct">Foo</span> <span class="punctuation">{</span> | 62 | <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration static associated">new</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="struct">Foo</span> <span class="brace">{</span> |
58 | <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">bar</span><span class="punctuation">:</span> <span class="bool_literal">true</span> <span class="punctuation">}</span> | 63 | <span class="struct">Foo</span> <span class="brace">{</span> <span class="field">bar</span><span class="colon">:</span> <span class="bool_literal">true</span> <span class="brace">}</span> |
59 | <span class="punctuation">}</span> | 64 | <span class="brace">}</span> |
60 | 65 | ||
61 | <span class="comment documentation">/// `bar` method on `Foo`.</span> | 66 | <span class="comment documentation">/// `bar` method on `Foo`.</span> |
62 | <span class="comment documentation">///</span> | 67 | <span class="comment documentation">///</span> |
63 | <span class="comment documentation">/// # Examples</span> | 68 | <span class="comment documentation">/// # Examples</span> |
64 | <span class="comment documentation">///</span> | 69 | <span class="comment documentation">///</span> |
65 | <span class="comment documentation">/// ```</span> | 70 | <span class="comment documentation">/// ```</span> |
66 | <span class="comment documentation">/// </span><span class="keyword injected">use</span><span class="dummy injected"> </span><span class="module injected">x</span><span class="operator injected">::</span><span class="module injected">y</span><span class="punctuation injected">;</span> | 71 | <span class="comment documentation">/// </span><span class="keyword injected">use</span><span class="none injected"> </span><span class="module injected">x</span><span class="operator injected">::</span><span class="module injected">y</span><span class="semicolon injected">;</span> |
67 | <span class="comment documentation">///</span> | 72 | <span class="comment documentation">///</span> |
68 | <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="variable declaration injected">foo</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span> | 73 | <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">foo</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span> |
69 | <span class="comment documentation">///</span> | 74 | <span class="comment documentation">///</span> |
70 | <span class="comment documentation">/// </span><span class="comment injected">// calls bar on foo</span> | 75 | <span class="comment documentation">/// </span><span class="comment injected">// calls bar on foo</span> |
71 | <span class="comment documentation">/// </span><span class="macro injected">assert!</span><span class="punctuation injected">(</span><span class="dummy injected">foo</span><span class="operator injected">.</span><span class="dummy injected">bar</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span> | 76 | <span class="comment documentation">/// </span><span class="macro injected">assert!</span><span class="parenthesis injected">(</span><span class="none injected">foo</span><span class="operator injected">.</span><span class="none injected">bar</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span> |
72 | <span class="comment documentation">///</span> | 77 | <span class="comment documentation">///</span> |
73 | <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="variable declaration injected">bar</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="variable injected">foo</span><span class="operator injected">.</span><span class="field injected">bar</span><span class="dummy injected"> </span><span class="operator injected">||</span><span class="dummy injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="constant injected">bar</span><span class="punctuation injected">;</span> | 78 | <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">bar</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="variable injected">foo</span><span class="operator injected">.</span><span class="field injected">bar</span><span class="none injected"> </span><span class="operator injected">||</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="constant injected">bar</span><span class="semicolon injected">;</span> |
74 | <span class="comment documentation">///</span> | 79 | <span class="comment documentation">///</span> |
75 | <span class="comment documentation">/// </span><span class="comment injected">/* multi-line | 80 | <span class="comment documentation">/// </span><span class="comment injected">/* multi-line</span> |
76 | </span><span class="comment documentation">/// </span><span class="comment injected"> comment */</span> | 81 | <span class="comment documentation">/// </span><span class="comment injected"> comment */</span> |
77 | <span class="comment documentation">///</span> | 82 | <span class="comment documentation">///</span> |
78 | <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="variable declaration injected">multi_line_string</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="string_literal injected">"Foo | 83 | <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">multi_line_string</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="string_literal injected">"Foo</span> |
79 | </span><span class="comment documentation">/// </span><span class="string_literal injected"> bar | 84 | <span class="comment documentation">/// </span><span class="string_literal injected"> bar</span> |
80 | </span><span class="comment documentation">/// </span><span class="string_literal injected"> "</span><span class="punctuation injected">;</span> | 85 | <span class="comment documentation">/// </span><span class="string_literal injected"> "</span><span class="semicolon injected">;</span> |
81 | <span class="comment documentation">///</span> | 86 | <span class="comment documentation">///</span> |
82 | <span class="comment documentation">/// ```</span> | 87 | <span class="comment documentation">/// ```</span> |
83 | <span class="comment documentation">///</span> | 88 | <span class="comment documentation">///</span> |
84 | <span class="comment documentation">/// ```rust,no_run</span> | 89 | <span class="comment documentation">/// ```rust,no_run</span> |
85 | <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="variable declaration injected">foobar</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="operator injected">.</span><span class="function injected">bar</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected"> | 90 | <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">foobar</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="operator injected">.</span><span class="function injected">bar</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span> |
86 | </span> <span class="comment documentation">/// ```</span> | 91 | <span class="comment documentation">/// ```</span> |
87 | <span class="comment documentation">///</span> | 92 | <span class="comment documentation">///</span> |
88 | <span class="comment documentation">/// ```sh</span> | 93 | <span class="comment documentation">/// ```sh</span> |
89 | <span class="comment documentation">/// echo 1</span> | 94 | <span class="comment documentation">/// echo 1</span> |
90 | <span class="comment documentation">/// ```</span> | 95 | <span class="comment documentation">/// ```</span> |
91 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">foo</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">bool</span> <span class="punctuation">{</span> | 96 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">foo</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">bool</span> <span class="brace">{</span> |
92 | <span class="bool_literal">true</span> | 97 | <span class="bool_literal">true</span> |
93 | <span class="punctuation">}</span> | 98 | <span class="brace">}</span> |
94 | <span class="punctuation">}</span> | 99 | <span class="brace">}</span> |
95 | 100 | ||
96 | <span class="comment documentation">/// ```</span> | 101 | <span class="comment documentation">/// ```</span> |
97 | <span class="comment documentation">/// </span><span class="macro injected">noop!</span><span class="punctuation injected">(</span><span class="numeric_literal injected">1</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected"> | 102 | <span class="comment documentation">/// </span><span class="macro injected">noop!</span><span class="parenthesis injected">(</span><span class="numeric_literal injected">1</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span> |
98 | </span><span class="comment documentation">/// ```</span> | 103 | <span class="comment documentation">/// ```</span> |
99 | <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">noop</span> <span class="punctuation">{</span> | 104 | <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">noop</span> <span class="brace">{</span> |
100 | <span class="punctuation">(</span><span class="punctuation">$</span>expr<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">></span> <span class="punctuation">{</span> | 105 | <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">></span> <span class="brace">{</span> |
101 | <span class="punctuation">$</span>expr | 106 | <span class="punctuation">$</span>expr |
102 | <span class="punctuation">}</span> | 107 | <span class="brace">}</span> |
103 | <span class="punctuation">}</span></code></pre> \ No newline at end of file | 108 | <span class="brace">}</span></code></pre> \ No newline at end of file |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html index ed452586a..6f7a7ffff 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html | |||
@@ -36,6 +36,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
36 | 36 | ||
37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } | 37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } |
38 | </style> | 38 | </style> |
39 | <pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module">std</span><span class="punctuation">;</span> | 39 | <pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module">std</span><span class="semicolon">;</span> |
40 | <span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module">alloc</span> <span class="keyword">as</span> <span class="module">abc</span><span class="punctuation">;</span> | 40 | <span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module">alloc</span> <span class="keyword">as</span> <span class="module">abc</span><span class="semicolon">;</span> |
41 | </code></pre> \ No newline at end of file | 41 | </code></pre> \ No newline at end of file |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html index 92e7dc3e4..753b535b5 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html | |||
@@ -36,14 +36,14 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
36 | 36 | ||
37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } | 37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } |
38 | </style> | 38 | </style> |
39 | <pre><code><span class="keyword">fn</span> <span class="function declaration">fixture</span><span class="punctuation">(</span><span class="value_param declaration">ra_fixture</span><span class="punctuation">:</span> <span class="operator">&</span><span class="builtin_type">str</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 39 | <pre><code><span class="keyword">fn</span> <span class="function declaration">fixture</span><span class="parenthesis">(</span><span class="value_param declaration">ra_fixture</span><span class="colon">:</span> <span class="operator">&</span><span class="builtin_type">str</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
40 | 40 | ||
41 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 41 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> |
42 | <span class="function">fixture</span><span class="punctuation">(</span><span class="string_literal">r#"</span> | 42 | <span class="function">fixture</span><span class="parenthesis">(</span><span class="string_literal">r#"</span> |
43 | <span class="keyword">trait</span> <span class="trait declaration">Foo</span> <span class="punctuation">{</span> | 43 | <span class="keyword">trait</span> <span class="trait declaration">Foo</span> <span class="brace">{</span> |
44 | <span class="keyword">fn</span> <span class="function declaration static associated">foo</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 44 | <span class="keyword">fn</span> <span class="function declaration static associated">foo</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> |
45 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"2 + 2 = {}"</span><span class="punctuation">,</span> <span class="numeric_literal">4</span><span class="punctuation">)</span><span class="punctuation">;</span> | 45 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"2 + 2 = {}"</span><span class="comma">,</span> <span class="numeric_literal">4</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
46 | <span class="punctuation">}</span> | 46 | <span class="brace">}</span> |
47 | <span class="punctuation">}</span><span class="string_literal">"#</span> | 47 | <span class="brace">}</span><span class="string_literal">"#</span> |
48 | <span class="punctuation">)</span><span class="punctuation">;</span> | 48 | <span class="parenthesis">)</span><span class="semicolon">;</span> |
49 | <span class="punctuation">}</span></code></pre> \ No newline at end of file | 49 | <span class="brace">}</span></code></pre> \ No newline at end of file |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index 31dad5d42..66d80c4b6 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html | |||
@@ -36,64 +36,64 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
36 | 36 | ||
37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } | 37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } |
38 | </style> | 38 | </style> |
39 | <pre><code><span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">println</span> <span class="punctuation">{</span> | 39 | <pre><code><span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">println</span> <span class="brace">{</span> |
40 | <span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>arg<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">></span> <span class="punctuation">(</span><span class="punctuation">{</span> | 40 | <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">></span> <span class="parenthesis">(</span><span class="brace">{</span> |
41 | <span class="punctuation">$</span>crate<span class="punctuation">:</span><span class="punctuation">:</span>io<span class="punctuation">:</span><span class="punctuation">:</span>_print<span class="punctuation">(</span><span class="punctuation">$</span>crate<span class="punctuation">:</span><span class="punctuation">:</span>format_args_nl<span class="punctuation">!</span><span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>arg<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span><span class="punctuation">)</span><span class="punctuation">;</span> | 41 | <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>io<span class="colon">:</span><span class="colon">:</span>_print<span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>format_args_nl<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
42 | <span class="punctuation">}</span><span class="punctuation">)</span> | 42 | <span class="brace">}</span><span class="parenthesis">)</span> |
43 | <span class="punctuation">}</span> | 43 | <span class="brace">}</span> |
44 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">rustc_builtin_macro</span><span class="attribute attribute">]</span> | 44 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">rustc_builtin_macro</span><span class="attribute attribute">]</span> |
45 | <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">format_args_nl</span> <span class="punctuation">{</span> | 45 | <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">format_args_nl</span> <span class="brace">{</span> |
46 | <span class="punctuation">(</span><span class="punctuation">$</span>fmt<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">></span> <span class="punctuation">{</span><span class="punctuation">{</span> <span class="comment">/* compiler built-in */</span> <span class="punctuation">}</span><span class="punctuation">}</span><span class="punctuation">;</span> | 46 | <span class="parenthesis">(</span><span class="punctuation">$</span>fmt<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">></span> <span class="brace">{</span><span class="brace">{</span> <span class="comment">/* compiler built-in */</span> <span class="brace">}</span><span class="brace">}</span><span class="semicolon">;</span> |
47 | <span class="punctuation">(</span><span class="punctuation">$</span>fmt<span class="punctuation">:</span>expr<span class="punctuation">,</span> <span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>args<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">></span> <span class="punctuation">{</span><span class="punctuation">{</span> <span class="comment">/* compiler built-in */</span> <span class="punctuation">}</span><span class="punctuation">}</span><span class="punctuation">;</span> | 47 | <span class="parenthesis">(</span><span class="punctuation">$</span>fmt<span class="colon">:</span>expr<span class="comma">,</span> <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>args<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">></span> <span class="brace">{</span><span class="brace">{</span> <span class="comment">/* compiler built-in */</span> <span class="brace">}</span><span class="brace">}</span><span class="semicolon">;</span> |
48 | <span class="punctuation">}</span> | 48 | <span class="brace">}</span> |
49 | 49 | ||
50 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 50 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> |
51 | <span class="comment">// from https://doc.rust-lang.org/std/fmt/index.html</span> | 51 | <span class="comment">// from https://doc.rust-lang.org/std/fmt/index.html</span> |
52 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello"</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// => "Hello"</span> | 52 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello"</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="comment">// => "Hello"</span> |
53 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"world"</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// => "Hello, world!"</span> | 53 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="string_literal">"world"</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="comment">// => "Hello, world!"</span> |
54 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"The number is </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="numeric_literal">1</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// => "The number is 1"</span> | 54 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"The number is </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> <span class="numeric_literal">1</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="comment">// => "The number is 1"</span> |
55 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="punctuation">(</span><span class="numeric_literal">3</span><span class="punctuation">,</span> <span class="numeric_literal">4</span><span class="punctuation">)</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// => "(3, 4)"</span> | 55 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> <span class="parenthesis">(</span><span class="numeric_literal">3</span><span class="comma">,</span> <span class="numeric_literal">4</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="comment">// => "(3, 4)"</span> |
56 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">value</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> value<span class="operator">=</span><span class="numeric_literal">4</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// => "4"</span> | 56 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">value</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> value<span class="operator">=</span><span class="numeric_literal">4</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="comment">// => "4"</span> |
57 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="numeric_literal">1</span><span class="punctuation">,</span> <span class="numeric_literal">2</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// => "1 2"</span> | 57 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> <span class="numeric_literal">1</span><span class="comma">,</span> <span class="numeric_literal">2</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="comment">// => "1 2"</span> |
58 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">4</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="numeric_literal">42</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// => "0042" with leading zerosV</span> | 58 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">4</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> <span class="numeric_literal">42</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="comment">// => "0042" with leading zerosV</span> |
59 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="numeric_literal">1</span><span class="punctuation">,</span> <span class="numeric_literal">2</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// => "2 1 1 2"</span> | 59 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> <span class="numeric_literal">1</span><span class="comma">,</span> <span class="numeric_literal">2</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="comment">// => "2 1 1 2"</span> |
60 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">argument</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> argument <span class="operator">=</span> <span class="string_literal">"test"</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// => "test"</span> | 60 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">argument</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> argument <span class="operator">=</span> <span class="string_literal">"test"</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="comment">// => "test"</span> |
61 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="numeric_literal">1</span><span class="punctuation">,</span> name <span class="operator">=</span> <span class="numeric_literal">2</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// => "2 1"</span> | 61 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> <span class="numeric_literal">1</span><span class="comma">,</span> name <span class="operator">=</span> <span class="numeric_literal">2</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="comment">// => "2 1"</span> |
62 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">a</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="variable">c</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="variable">b</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> a<span class="operator">=</span><span class="string_literal">"a"</span><span class="punctuation">,</span> b<span class="operator">=</span><span class="char_literal">'b'</span><span class="punctuation">,</span> c<span class="operator">=</span><span class="numeric_literal">3</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// => "a 3 b"</span> | 62 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">a</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="variable">c</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="variable">b</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> a<span class="operator">=</span><span class="string_literal">"a"</span><span class="comma">,</span> b<span class="operator">=</span><span class="char_literal">'b'</span><span class="comma">,</span> c<span class="operator">=</span><span class="numeric_literal">3</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="comment">// => "a 3 b"</span> |
63 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"{{</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">}}"</span><span class="punctuation">,</span> <span class="numeric_literal">2</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// => "{2}"</span> | 63 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"{{</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">}}"</span><span class="comma">,</span> <span class="numeric_literal">2</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="comment">// => "{2}"</span> |
64 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">)</span><span class="punctuation">;</span> | 64 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
65 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">,</span> <span class="numeric_literal">5</span><span class="punctuation">)</span><span class="punctuation">;</span> | 65 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="comma">,</span> <span class="numeric_literal">5</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
66 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="numeric_literal">5</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">)</span><span class="punctuation">;</span> | 66 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="numeric_literal">5</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
67 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">width</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">,</span> width <span class="operator">=</span> <span class="numeric_literal">5</span><span class="punctuation">)</span><span class="punctuation">;</span> | 67 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">width</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="comma">,</span> width <span class="operator">=</span> <span class="numeric_literal">5</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
68 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier"><</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">)</span><span class="punctuation">;</span> | 68 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier"><</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
69 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">-</span><span class="format_specifier"><</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">)</span><span class="punctuation">;</span> | 69 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">-</span><span class="format_specifier"><</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
70 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">^</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">)</span><span class="punctuation">;</span> | 70 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">^</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
71 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">></span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">)</span><span class="punctuation">;</span> | 71 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">></span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
72 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">+</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="numeric_literal">5</span><span class="punctuation">)</span><span class="punctuation">;</span> | 72 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">+</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="numeric_literal">5</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
73 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="numeric_literal">27</span><span class="punctuation">)</span><span class="punctuation">;</span> | 73 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="numeric_literal">27</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
74 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="numeric_literal">5</span><span class="punctuation">)</span><span class="punctuation">;</span> | 74 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="numeric_literal">5</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
75 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="punctuation">-</span><span class="numeric_literal">5</span><span class="punctuation">)</span><span class="punctuation">;</span> | 75 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="punctuation">-</span><span class="numeric_literal">5</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
76 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="numeric_literal">0</span><span class="numeric_literal">10</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="numeric_literal">27</span><span class="punctuation">)</span><span class="punctuation">;</span> | 76 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="numeric_literal">0</span><span class="numeric_literal">10</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="numeric_literal">27</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
77 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">,</span> <span class="numeric_literal">0.01</span><span class="punctuation">)</span><span class="punctuation">;</span> | 77 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="comma">,</span> <span class="numeric_literal">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
78 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="numeric_literal">5</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">,</span> <span class="numeric_literal">0.01</span><span class="punctuation">)</span><span class="punctuation">;</span> | 78 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> <span class="numeric_literal">5</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="comma">,</span> <span class="numeric_literal">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
79 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">,</span> <span class="numeric_literal">5</span><span class="punctuation">,</span> <span class="numeric_literal">0.01</span><span class="punctuation">)</span><span class="punctuation">;</span> | 79 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="comma">,</span> <span class="numeric_literal">5</span><span class="comma">,</span> <span class="numeric_literal">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
80 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">,</span> <span class="numeric_literal">5</span><span class="punctuation">,</span> <span class="numeric_literal">0.01</span><span class="punctuation">)</span><span class="punctuation">;</span> | 80 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="comma">,</span> <span class="numeric_literal">5</span><span class="comma">,</span> <span class="numeric_literal">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
81 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">,</span> <span class="numeric_literal">5</span><span class="punctuation">,</span> <span class="numeric_literal">0.01</span><span class="punctuation">)</span><span class="punctuation">;</span> | 81 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="comma">,</span> <span class="numeric_literal">5</span><span class="comma">,</span> <span class="numeric_literal">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
82 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="variable">number</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="variable">prec</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">,</span> prec <span class="operator">=</span> <span class="numeric_literal">5</span><span class="punctuation">,</span> number <span class="operator">=</span> <span class="numeric_literal">0.01</span><span class="punctuation">)</span><span class="punctuation">;</span> | 82 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="variable">number</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="variable">prec</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="comma">,</span> prec <span class="operator">=</span> <span class="numeric_literal">5</span><span class="comma">,</span> number <span class="operator">=</span> <span class="numeric_literal">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
83 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 fractional digits"</span><span class="punctuation">,</span> <span class="string_literal">"Hello"</span><span class="punctuation">,</span> <span class="numeric_literal">3</span><span class="punctuation">,</span> name<span class="operator">=</span><span class="numeric_literal">1234.56</span><span class="punctuation">)</span><span class="punctuation">;</span> | 83 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 fractional digits"</span><span class="comma">,</span> <span class="string_literal">"Hello"</span><span class="comma">,</span> <span class="numeric_literal">3</span><span class="comma">,</span> name<span class="operator">=</span><span class="numeric_literal">1234.56</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
84 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 characters"</span><span class="punctuation">,</span> <span class="string_literal">"Hello"</span><span class="punctuation">,</span> <span class="numeric_literal">3</span><span class="punctuation">,</span> name<span class="operator">=</span><span class="string_literal">"1234.56"</span><span class="punctuation">)</span><span class="punctuation">;</span> | 84 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 characters"</span><span class="comma">,</span> <span class="string_literal">"Hello"</span><span class="comma">,</span> <span class="numeric_literal">3</span><span class="comma">,</span> name<span class="operator">=</span><span class="string_literal">"1234.56"</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
85 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">></span><span class="numeric_literal">8</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 right-aligned characters"</span><span class="punctuation">,</span> <span class="string_literal">"Hello"</span><span class="punctuation">,</span> <span class="numeric_literal">3</span><span class="punctuation">,</span> name<span class="operator">=</span><span class="string_literal">"1234.56"</span><span class="punctuation">)</span><span class="punctuation">;</span> | 85 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">></span><span class="numeric_literal">8</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 right-aligned characters"</span><span class="comma">,</span> <span class="string_literal">"Hello"</span><span class="comma">,</span> <span class="numeric_literal">3</span><span class="comma">,</span> name<span class="operator">=</span><span class="string_literal">"1234.56"</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
86 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello {{}}"</span><span class="punctuation">)</span><span class="punctuation">;</span> | 86 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello {{}}"</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
87 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"{{ Hello"</span><span class="punctuation">)</span><span class="punctuation">;</span> | 87 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"{{ Hello"</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
88 | 88 | ||
89 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">r"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"world"</span><span class="punctuation">)</span><span class="punctuation">;</span> | 89 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">r"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="string_literal">"world"</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
90 | 90 | ||
91 | <span class="comment">// escape sequences</span> | 91 | <span class="comment">// escape sequences</span> |
92 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello</span><span class="escape_sequence">\n</span><span class="string_literal">World"</span><span class="punctuation">)</span><span class="punctuation">;</span> | 92 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello</span><span class="escape_sequence">\n</span><span class="string_literal">World"</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
93 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="escape_sequence">\u{48}</span><span class="escape_sequence">\x65</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6F</span><span class="string_literal"> World"</span><span class="punctuation">)</span><span class="punctuation">;</span> | 93 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="escape_sequence">\u{48}</span><span class="escape_sequence">\x65</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6F</span><span class="string_literal"> World"</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
94 | 94 | ||
95 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> A <span class="operator">=</span> <span class="numeric_literal">92</span><span class="punctuation">)</span><span class="punctuation">;</span> | 95 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> A <span class="operator">=</span> <span class="numeric_literal">92</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
96 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> ничоси <span class="operator">=</span> <span class="numeric_literal">92</span><span class="punctuation">)</span><span class="punctuation">;</span> | 96 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> ничоси <span class="operator">=</span> <span class="numeric_literal">92</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
97 | 97 | ||
98 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">x</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> "</span><span class="punctuation">,</span> thingy<span class="punctuation">,</span> n2<span class="punctuation">)</span><span class="punctuation">;</span> | 98 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">x</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> "</span><span class="comma">,</span> thingy<span class="comma">,</span> n2<span class="parenthesis">)</span><span class="semicolon">;</span> |
99 | <span class="punctuation">}</span></code></pre> \ No newline at end of file | 99 | <span class="brace">}</span></code></pre> \ No newline at end of file |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html index e3a0aa317..9d4d6d4a0 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html | |||
@@ -36,65 +36,65 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
36 | 36 | ||
37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } | 37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } |
38 | </style> | 38 | </style> |
39 | <pre><code><span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 39 | <pre><code><span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
40 | 40 | ||
41 | <span class="keyword">union</span> <span class="union declaration">Union</span> <span class="punctuation">{</span> | 41 | <span class="keyword">union</span> <span class="union declaration">Union</span> <span class="brace">{</span> |
42 | <span class="field declaration">a</span><span class="punctuation">:</span> <span class="builtin_type">u32</span><span class="punctuation">,</span> | 42 | <span class="field declaration">a</span><span class="colon">:</span> <span class="builtin_type">u32</span><span class="comma">,</span> |
43 | <span class="field declaration">b</span><span class="punctuation">:</span> <span class="builtin_type">f32</span><span class="punctuation">,</span> | 43 | <span class="field declaration">b</span><span class="colon">:</span> <span class="builtin_type">f32</span><span class="comma">,</span> |
44 | <span class="punctuation">}</span> | 44 | <span class="brace">}</span> |
45 | 45 | ||
46 | <span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="punctuation">;</span> | 46 | <span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="semicolon">;</span> |
47 | 47 | ||
48 | <span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="punctuation">{</span> | 48 | <span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="brace">{</span> |
49 | <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration associated unsafe">unsafe_method</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 49 | <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration associated unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
50 | <span class="punctuation">}</span> | 50 | <span class="brace">}</span> |
51 | 51 | ||
52 | <span class="keyword">struct</span> <span class="struct declaration">TypeForStaticMut</span> <span class="punctuation">{</span> | 52 | <span class="keyword">struct</span> <span class="struct declaration">TypeForStaticMut</span> <span class="brace">{</span> |
53 | <span class="field declaration">a</span><span class="punctuation">:</span> <span class="builtin_type">u8</span> | 53 | <span class="field declaration">a</span><span class="colon">:</span> <span class="builtin_type">u8</span> |
54 | <span class="punctuation">}</span> | 54 | <span class="brace">}</span> |
55 | 55 | ||
56 | <span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">global_mut</span><span class="punctuation">:</span> <span class="struct">TypeForStaticMut</span> <span class="operator">=</span> <span class="struct">TypeForStaticMut</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span> | 56 | <span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">global_mut</span><span class="colon">:</span> <span class="struct">TypeForStaticMut</span> <span class="operator">=</span> <span class="struct">TypeForStaticMut</span> <span class="brace">{</span> <span class="field">a</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span><span class="semicolon">;</span> |
57 | 57 | ||
58 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">repr</span><span class="punctuation attribute">(</span><span class="attribute attribute">packed</span><span class="punctuation attribute">)</span><span class="attribute attribute">]</span> | 58 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">repr</span><span class="parenthesis attribute">(</span><span class="attribute attribute">packed</span><span class="parenthesis attribute">)</span><span class="attribute attribute">]</span> |
59 | <span class="keyword">struct</span> <span class="struct declaration">Packed</span> <span class="punctuation">{</span> | 59 | <span class="keyword">struct</span> <span class="struct declaration">Packed</span> <span class="brace">{</span> |
60 | <span class="field declaration">a</span><span class="punctuation">:</span> <span class="builtin_type">u16</span><span class="punctuation">,</span> | 60 | <span class="field declaration">a</span><span class="colon">:</span> <span class="builtin_type">u16</span><span class="comma">,</span> |
61 | <span class="punctuation">}</span> | 61 | <span class="brace">}</span> |
62 | 62 | ||
63 | <span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="punctuation">{</span> | 63 | <span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="brace">{</span> |
64 | <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span><span class="punctuation">;</span> | 64 | <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
65 | <span class="punctuation">}</span> | 65 | <span class="brace">}</span> |
66 | 66 | ||
67 | <span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="punctuation">{</span> | 67 | <span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="brace">{</span> |
68 | <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 68 | <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
69 | <span class="punctuation">}</span> | 69 | <span class="brace">}</span> |
70 | 70 | ||
71 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 71 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> |
72 | <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="operator">=</span> <span class="operator">&</span><span class="numeric_literal">5</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="punctuation">_</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">usize</span><span class="punctuation">;</span> | 72 | <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="operator">=</span> <span class="operator">&</span><span class="numeric_literal">5</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="punctuation">_</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">usize</span><span class="semicolon">;</span> |
73 | <span class="keyword">let</span> <span class="variable declaration">u</span> <span class="operator">=</span> <span class="union">Union</span> <span class="punctuation">{</span> <span class="field">b</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span> | 73 | <span class="keyword">let</span> <span class="variable declaration">u</span> <span class="operator">=</span> <span class="union">Union</span> <span class="brace">{</span> <span class="field">b</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span><span class="semicolon">;</span> |
74 | <span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span> | 74 | <span class="keyword unsafe">unsafe</span> <span class="brace">{</span> |
75 | <span class="comment">// unsafe fn and method calls</span> | 75 | <span class="comment">// unsafe fn and method calls</span> |
76 | <span class="function unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 76 | <span class="function unsafe">unsafe_fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
77 | <span class="keyword">let</span> <span class="variable declaration">b</span> <span class="operator">=</span> <span class="variable">u</span><span class="operator">.</span><span class="field unsafe">b</span><span class="punctuation">;</span> | 77 | <span class="keyword">let</span> <span class="variable declaration">b</span> <span class="operator">=</span> <span class="variable">u</span><span class="operator">.</span><span class="field unsafe">b</span><span class="semicolon">;</span> |
78 | <span class="keyword control">match</span> <span class="variable">u</span> <span class="punctuation">{</span> | 78 | <span class="keyword control">match</span> <span class="variable">u</span> <span class="brace">{</span> |
79 | <span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">b</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span> <span class="operator">=></span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span> | 79 | <span class="union">Union</span> <span class="brace">{</span> <span class="field unsafe">b</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span> <span class="operator">=></span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span> |
80 | <span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">a</span> <span class="punctuation">}</span> <span class="operator">=></span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span> | 80 | <span class="union">Union</span> <span class="brace">{</span> <span class="field unsafe">a</span> <span class="brace">}</span> <span class="operator">=></span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span> |
81 | <span class="punctuation">}</span> | 81 | <span class="brace">}</span> |
82 | <span class="struct">HasUnsafeFn</span><span class="operator">.</span><span class="function associated unsafe">unsafe_method</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 82 | <span class="struct">HasUnsafeFn</span><span class="operator">.</span><span class="function associated unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
83 | 83 | ||
84 | <span class="comment">// unsafe deref</span> | 84 | <span class="comment">// unsafe deref</span> |
85 | <span class="keyword">let</span> <span class="variable declaration">y</span> <span class="operator">=</span> <span class="operator unsafe">*</span><span class="variable">x</span><span class="punctuation">;</span> | 85 | <span class="keyword">let</span> <span class="variable declaration">y</span> <span class="operator">=</span> <span class="operator unsafe">*</span><span class="variable">x</span><span class="semicolon">;</span> |
86 | 86 | ||
87 | <span class="comment">// unsafe access to a static mut</span> | 87 | <span class="comment">// unsafe access to a static mut</span> |
88 | <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="static mutable unsafe">global_mut</span><span class="operator">.</span><span class="field">a</span><span class="punctuation">;</span> | 88 | <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="static mutable unsafe">global_mut</span><span class="operator">.</span><span class="field">a</span><span class="semicolon">;</span> |
89 | 89 | ||
90 | <span class="comment">// unsafe ref of packed fields</span> | 90 | <span class="comment">// unsafe ref of packed fields</span> |
91 | <span class="keyword">let</span> <span class="variable declaration">packed</span> <span class="operator">=</span> <span class="struct">Packed</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span> | 91 | <span class="keyword">let</span> <span class="variable declaration">packed</span> <span class="operator">=</span> <span class="struct">Packed</span> <span class="brace">{</span> <span class="field">a</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span><span class="semicolon">;</span> |
92 | <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="operator unsafe">&</span><span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="punctuation">;</span> | 92 | <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="operator unsafe">&</span><span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="semicolon">;</span> |
93 | <span class="keyword">let</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="punctuation">;</span> | 93 | <span class="keyword">let</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="semicolon">;</span> |
94 | <span class="keyword">let</span> <span class="struct">Packed</span> <span class="punctuation">{</span> <span class="keyword unsafe">ref</span> <span class="field">a</span> <span class="punctuation">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="punctuation">;</span> | 94 | <span class="keyword">let</span> <span class="struct">Packed</span> <span class="brace">{</span> <span class="keyword unsafe">ref</span> <span class="field">a</span> <span class="brace">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="semicolon">;</span> |
95 | <span class="keyword">let</span> <span class="struct">Packed</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">_a</span> <span class="punctuation">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="punctuation">;</span> | 95 | <span class="keyword">let</span> <span class="struct">Packed</span> <span class="brace">{</span> <span class="field">a</span><span class="colon">:</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">_a</span> <span class="brace">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="semicolon">;</span> |
96 | 96 | ||
97 | <span class="comment">// unsafe auto ref of packed field</span> | 97 | <span class="comment">// unsafe auto ref of packed field</span> |
98 | <span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="operator">.</span><span class="function associated unsafe">calls_autoref</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 98 | <span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="operator">.</span><span class="function associated unsafe">calls_autoref</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
99 | <span class="punctuation">}</span> | 99 | <span class="brace">}</span> |
100 | <span class="punctuation">}</span></code></pre> \ No newline at end of file | 100 | <span class="brace">}</span></code></pre> \ No newline at end of file |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html index 02270b077..6b7447c46 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html | |||
@@ -36,187 +36,187 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
36 | 36 | ||
37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } | 37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } |
38 | </style> | 38 | </style> |
39 | <pre><code><span class="keyword">use</span> <span class="module">inner</span><span class="operator">::</span><span class="punctuation">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="module declaration">inner_mod</span><span class="punctuation">}</span><span class="punctuation">;</span> | 39 | <pre><code><span class="keyword">use</span> <span class="module">inner</span><span class="operator">::</span><span class="brace">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="module declaration">inner_mod</span><span class="brace">}</span><span class="semicolon">;</span> |
40 | <span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 40 | <span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span><span class="brace">}</span> |
41 | 41 | ||
42 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">rustc_builtin_macro</span><span class="attribute attribute">]</span> | 42 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">rustc_builtin_macro</span><span class="attribute attribute">]</span> |
43 | <span class="keyword">macro</span> <span class="unresolved_reference declaration">Copy</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 43 | <span class="keyword">macro</span> <span class="unresolved_reference declaration">Copy</span> <span class="brace">{</span><span class="brace">}</span> |
44 | 44 | ||
45 | <span class="comment">// Needed for function consuming vs normal</span> | 45 | <span class="comment">// Needed for function consuming vs normal</span> |
46 | <span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration">marker</span> <span class="punctuation">{</span> | 46 | <span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration">marker</span> <span class="brace">{</span> |
47 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">lang</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"copy"</span><span class="attribute attribute">]</span> | 47 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">lang</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"copy"</span><span class="attribute attribute">]</span> |
48 | <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">Copy</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 48 | <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">Copy</span> <span class="brace">{</span><span class="brace">}</span> |
49 | <span class="punctuation">}</span> | 49 | <span class="brace">}</span> |
50 | 50 | ||
51 | <span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration">ops</span> <span class="punctuation">{</span> | 51 | <span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration">ops</span> <span class="brace">{</span> |
52 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">lang</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"fn_once"</span><span class="attribute attribute">]</span> | 52 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">lang</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"fn_once"</span><span class="attribute attribute">]</span> |
53 | <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">FnOnce</span><span class="punctuation"><</span><span class="type_param declaration">Args</span><span class="punctuation">></span> <span class="punctuation">{</span><span class="punctuation">}</span> | 53 | <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">FnOnce</span><span class="angle"><</span><span class="type_param declaration">Args</span><span class="angle">></span> <span class="brace">{</span><span class="brace">}</span> |
54 | 54 | ||
55 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">lang</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"fn_mut"</span><span class="attribute attribute">]</span> | 55 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">lang</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"fn_mut"</span><span class="attribute attribute">]</span> |
56 | <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">FnMut</span><span class="punctuation"><</span><span class="type_param declaration">Args</span><span class="punctuation">></span><span class="punctuation">:</span> <span class="trait">FnOnce</span><span class="punctuation"><</span><span class="type_param">Args</span><span class="punctuation">></span> <span class="punctuation">{</span><span class="punctuation">}</span> | 56 | <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">FnMut</span><span class="angle"><</span><span class="type_param declaration">Args</span><span class="angle">></span><span class="colon">:</span> <span class="trait">FnOnce</span><span class="angle"><</span><span class="type_param">Args</span><span class="angle">></span> <span class="brace">{</span><span class="brace">}</span> |
57 | 57 | ||
58 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">lang</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"fn"</span><span class="attribute attribute">]</span> | 58 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">lang</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"fn"</span><span class="attribute attribute">]</span> |
59 | <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">Fn</span><span class="punctuation"><</span><span class="type_param declaration">Args</span><span class="punctuation">></span><span class="punctuation">:</span> <span class="trait">FnMut</span><span class="punctuation"><</span><span class="type_param">Args</span><span class="punctuation">></span> <span class="punctuation">{</span><span class="punctuation">}</span> | 59 | <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">Fn</span><span class="angle"><</span><span class="type_param declaration">Args</span><span class="angle">></span><span class="colon">:</span> <span class="trait">FnMut</span><span class="angle"><</span><span class="type_param">Args</span><span class="angle">></span> <span class="brace">{</span><span class="brace">}</span> |
60 | <span class="punctuation">}</span> | 60 | <span class="brace">}</span> |
61 | 61 | ||
62 | 62 | ||
63 | <span class="keyword">struct</span> <span class="struct declaration">Foo</span> <span class="punctuation">{</span> | 63 | <span class="keyword">struct</span> <span class="struct declaration">Foo</span> <span class="brace">{</span> |
64 | <span class="keyword">pub</span> <span class="field declaration">x</span><span class="punctuation">:</span> <span class="builtin_type">i32</span><span class="punctuation">,</span> | 64 | <span class="keyword">pub</span> <span class="field declaration">x</span><span class="colon">:</span> <span class="builtin_type">i32</span><span class="comma">,</span> |
65 | <span class="keyword">pub</span> <span class="field declaration">y</span><span class="punctuation">:</span> <span class="builtin_type">i32</span><span class="punctuation">,</span> | 65 | <span class="keyword">pub</span> <span class="field declaration">y</span><span class="colon">:</span> <span class="builtin_type">i32</span><span class="comma">,</span> |
66 | <span class="punctuation">}</span> | 66 | <span class="brace">}</span> |
67 | 67 | ||
68 | <span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="punctuation">{</span> | 68 | <span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="brace">{</span> |
69 | <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span><span class="punctuation">;</span> | 69 | <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span><span class="semicolon">;</span> |
70 | <span class="punctuation">}</span> | 70 | <span class="brace">}</span> |
71 | 71 | ||
72 | <span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="punctuation">{</span> | 72 | <span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="brace">{</span> |
73 | <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="punctuation">{</span> | 73 | <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="brace">{</span> |
74 | <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> | 74 | <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> |
75 | <span class="punctuation">}</span> | 75 | <span class="brace">}</span> |
76 | <span class="punctuation">}</span> | 76 | <span class="brace">}</span> |
77 | 77 | ||
78 | <span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span> | 78 | <span class="keyword">impl</span> <span class="struct">Foo</span> <span class="brace">{</span> |
79 | <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="punctuation">(</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">,</span> <span class="value_param declaration">f</span><span class="punctuation">:</span> <span class="struct">Foo</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="punctuation">{</span> | 79 | <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="parenthesis">(</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">Foo</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="brace">{</span> |
80 | <span class="value_param">f</span><span class="operator">.</span><span class="function consuming associated">baz</span><span class="punctuation">(</span><span class="self_keyword mutable consuming">self</span><span class="punctuation">)</span> | 80 | <span class="value_param">f</span><span class="operator">.</span><span class="function consuming associated">baz</span><span class="parenthesis">(</span><span class="self_keyword mutable consuming">self</span><span class="parenthesis">)</span> |
81 | <span class="punctuation">}</span> | 81 | <span class="brace">}</span> |
82 | 82 | ||
83 | <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 83 | <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span> |
84 | <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span> | 84 | <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span> |
85 | <span class="punctuation">}</span> | 85 | <span class="brace">}</span> |
86 | 86 | ||
87 | <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="punctuation">{</span> | 87 | <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="brace">{</span> |
88 | <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> | 88 | <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> |
89 | <span class="punctuation">}</span> | 89 | <span class="brace">}</span> |
90 | <span class="punctuation">}</span> | 90 | <span class="brace">}</span> |
91 | 91 | ||
92 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">derive</span><span class="punctuation attribute">(</span><span class="attribute attribute">Copy</span><span class="punctuation attribute">)</span><span class="attribute attribute">]</span> | 92 | <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">derive</span><span class="parenthesis attribute">(</span><span class="attribute attribute">Copy</span><span class="parenthesis attribute">)</span><span class="attribute attribute">]</span> |
93 | <span class="keyword">struct</span> <span class="struct declaration">FooCopy</span> <span class="punctuation">{</span> | 93 | <span class="keyword">struct</span> <span class="struct declaration">FooCopy</span> <span class="brace">{</span> |
94 | <span class="field declaration">x</span><span class="punctuation">:</span> <span class="builtin_type">u32</span><span class="punctuation">,</span> | 94 | <span class="field declaration">x</span><span class="colon">:</span> <span class="builtin_type">u32</span><span class="comma">,</span> |
95 | <span class="punctuation">}</span> | 95 | <span class="brace">}</span> |
96 | 96 | ||
97 | <span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="punctuation">{</span> | 97 | <span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="brace">{</span> |
98 | <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">,</span> <span class="value_param declaration">f</span><span class="punctuation">:</span> <span class="struct">FooCopy</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">u32</span> <span class="punctuation">{</span> | 98 | <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">FooCopy</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">u32</span> <span class="brace">{</span> |
99 | <span class="value_param">f</span><span class="operator">.</span><span class="function associated">baz</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">)</span> | 99 | <span class="value_param">f</span><span class="operator">.</span><span class="function associated">baz</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="parenthesis">)</span> |
100 | <span class="punctuation">}</span> | 100 | <span class="brace">}</span> |
101 | 101 | ||
102 | <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 102 | <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="parenthesis">)</span> <span class="brace">{</span> |
103 | <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span> | 103 | <span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span> |
104 | <span class="punctuation">}</span> | 104 | <span class="brace">}</span> |
105 | 105 | ||
106 | <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">u32</span> <span class="punctuation">{</span> | 106 | <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">u32</span> <span class="brace">{</span> |
107 | <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> | 107 | <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> |
108 | <span class="punctuation">}</span> | 108 | <span class="brace">}</span> |
109 | <span class="punctuation">}</span> | 109 | <span class="brace">}</span> |
110 | 110 | ||
111 | <span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">STATIC_MUT</span><span class="punctuation">:</span> <span class="builtin_type">i32</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span> | 111 | <span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">STATIC_MUT</span><span class="colon">:</span> <span class="builtin_type">i32</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span> |
112 | 112 | ||
113 | <span class="keyword">fn</span> <span class="function declaration">foo</span><span class="punctuation"><</span><span class="lifetime declaration">'a</span><span class="punctuation">,</span> <span class="type_param declaration">T</span><span class="punctuation">></span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="type_param">T</span> <span class="punctuation">{</span> | 113 | <span class="keyword">fn</span> <span class="function declaration">foo</span><span class="angle"><</span><span class="lifetime declaration">'a</span><span class="comma">,</span> <span class="type_param declaration">T</span><span class="angle">></span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="type_param">T</span> <span class="brace">{</span> |
114 | <span class="function">foo</span><span class="operator">::</span><span class="punctuation"><</span><span class="lifetime">'a</span><span class="punctuation">,</span> <span class="builtin_type">i32</span><span class="punctuation">></span><span class="punctuation">(</span><span class="punctuation">)</span> | 114 | <span class="function">foo</span><span class="operator">::</span><span class="angle"><</span><span class="lifetime">'a</span><span class="comma">,</span> <span class="builtin_type">i32</span><span class="angle">></span><span class="parenthesis">(</span><span class="parenthesis">)</span> |
115 | <span class="punctuation">}</span> | 115 | <span class="brace">}</span> |
116 | 116 | ||
117 | <span class="keyword">fn</span> <span class="function declaration">never</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">!</span> <span class="punctuation">{</span> | 117 | <span class="keyword">fn</span> <span class="function declaration">never</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">!</span> <span class="brace">{</span> |
118 | <span class="keyword control">loop</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 118 | <span class="keyword control">loop</span> <span class="brace">{</span><span class="brace">}</span> |
119 | <span class="punctuation">}</span> | 119 | <span class="brace">}</span> |
120 | 120 | ||
121 | <span class="keyword">fn</span> <span class="function declaration">const_param</span><span class="punctuation"><</span><span class="keyword">const</span> <span class="const_param declaration">FOO</span><span class="punctuation">:</span> <span class="builtin_type">usize</span><span class="punctuation">></span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">usize</span> <span class="punctuation">{</span> | 121 | <span class="keyword">fn</span> <span class="function declaration">const_param</span><span class="angle"><</span><span class="keyword">const</span> <span class="const_param declaration">FOO</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="angle">></span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">usize</span> <span class="brace">{</span> |
122 | <span class="const_param">FOO</span> | 122 | <span class="const_param">FOO</span> |
123 | <span class="punctuation">}</span> | 123 | <span class="brace">}</span> |
124 | 124 | ||
125 | <span class="keyword">use</span> <span class="module">ops</span><span class="operator">::</span><span class="trait">Fn</span><span class="punctuation">;</span> | 125 | <span class="keyword">use</span> <span class="module">ops</span><span class="operator">::</span><span class="trait">Fn</span><span class="semicolon">;</span> |
126 | <span class="keyword">fn</span> <span class="function declaration">baz</span><span class="punctuation"><</span><span class="type_param declaration">F</span><span class="punctuation">:</span> <span class="trait">Fn</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">></span><span class="punctuation">(</span><span class="value_param declaration callable">f</span><span class="punctuation">:</span> <span class="type_param">F</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 126 | <span class="keyword">fn</span> <span class="function declaration">baz</span><span class="angle"><</span><span class="type_param declaration">F</span><span class="colon">:</span> <span class="trait">Fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="angle">></span><span class="parenthesis">(</span><span class="value_param declaration callable">f</span><span class="colon">:</span> <span class="type_param">F</span><span class="parenthesis">)</span> <span class="brace">{</span> |
127 | <span class="value_param callable">f</span><span class="punctuation">(</span><span class="punctuation">)</span> | 127 | <span class="value_param callable">f</span><span class="parenthesis">(</span><span class="parenthesis">)</span> |
128 | <span class="punctuation">}</span> | 128 | <span class="brace">}</span> |
129 | 129 | ||
130 | <span class="keyword">fn</span> <span class="function declaration">foobar</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="keyword">impl</span> <span class="macro">Copy</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 130 | <span class="keyword">fn</span> <span class="function declaration">foobar</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="keyword">impl</span> <span class="macro">Copy</span> <span class="brace">{</span><span class="brace">}</span> |
131 | 131 | ||
132 | <span class="keyword">fn</span> <span class="function declaration">foo</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 132 | <span class="keyword">fn</span> <span class="function declaration">foo</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> |
133 | <span class="keyword">let</span> <span class="variable declaration">bar</span> <span class="operator">=</span> <span class="function">foobar</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 133 | <span class="keyword">let</span> <span class="variable declaration">bar</span> <span class="operator">=</span> <span class="function">foobar</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
134 | <span class="punctuation">}</span> | 134 | <span class="brace">}</span> |
135 | 135 | ||
136 | <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">def_fn</span> <span class="punctuation">{</span> | 136 | <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">def_fn</span> <span class="brace">{</span> |
137 | <span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>tt<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">></span> <span class="punctuation">{</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">}</span> | 137 | <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">></span> <span class="brace">{</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="brace">}</span> |
138 | <span class="punctuation">}</span> | 138 | <span class="brace">}</span> |
139 | 139 | ||
140 | <span class="macro">def_fn!</span> <span class="punctuation">{</span> | 140 | <span class="macro">def_fn!</span> <span class="brace">{</span> |
141 | <span class="keyword">fn</span> <span class="function declaration">bar</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-</span><span class="operator">></span> <span class="builtin_type">u32</span> <span class="punctuation">{</span> | 141 | <span class="keyword">fn</span> <span class="function declaration">bar</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-</span><span class="operator">></span> <span class="builtin_type">u32</span> <span class="brace">{</span> |
142 | <span class="numeric_literal">100</span> | 142 | <span class="numeric_literal">100</span> |
143 | <span class="punctuation">}</span> | 143 | <span class="brace">}</span> |
144 | <span class="punctuation">}</span> | 144 | <span class="brace">}</span> |
145 | 145 | ||
146 | <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">noop</span> <span class="punctuation">{</span> | 146 | <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">noop</span> <span class="brace">{</span> |
147 | <span class="punctuation">(</span><span class="punctuation">$</span>expr<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">></span> <span class="punctuation">{</span> | 147 | <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">></span> <span class="brace">{</span> |
148 | <span class="punctuation">$</span>expr | 148 | <span class="punctuation">$</span>expr |
149 | <span class="punctuation">}</span> | 149 | <span class="brace">}</span> |
150 | <span class="punctuation">}</span> | 150 | <span class="brace">}</span> |
151 | 151 | ||
152 | <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">keyword_frag</span> <span class="punctuation">{</span> | 152 | <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">keyword_frag</span> <span class="brace">{</span> |
153 | <span class="punctuation">(</span><span class="punctuation">$</span>type<span class="punctuation">:</span>ty<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">></span> <span class="punctuation">(</span><span class="punctuation">$</span>type<span class="punctuation">)</span> | 153 | <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="colon">:</span>ty<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">></span> <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="parenthesis">)</span> |
154 | <span class="punctuation">}</span> | 154 | <span class="brace">}</span> |
155 | 155 | ||
156 | <span class="comment">// comment</span> | 156 | <span class="comment">// comment</span> |
157 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 157 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> |
158 | <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello, {}!"</span><span class="punctuation">,</span> <span class="numeric_literal">92</span><span class="punctuation">)</span><span class="punctuation">;</span> | 158 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello, {}!"</span><span class="comma">,</span> <span class="numeric_literal">92</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
159 | 159 | ||
160 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">vec</span> <span class="operator">=</span> <span class="unresolved_reference">Vec</span><span class="operator">::</span><span class="unresolved_reference">new</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 160 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">vec</span> <span class="operator">=</span> <span class="unresolved_reference">Vec</span><span class="operator">::</span><span class="unresolved_reference">new</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
161 | <span class="keyword control">if</span> <span class="bool_literal">true</span> <span class="punctuation">{</span> | 161 | <span class="keyword control">if</span> <span class="bool_literal">true</span> <span class="brace">{</span> |
162 | <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="operator">=</span> <span class="numeric_literal">92</span><span class="punctuation">;</span> | 162 | <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="operator">=</span> <span class="numeric_literal">92</span><span class="semicolon">;</span> |
163 | <span class="variable mutable">vec</span><span class="operator">.</span><span class="unresolved_reference">push</span><span class="punctuation">(</span><span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">,</span> <span class="field">y</span><span class="punctuation">:</span> <span class="numeric_literal">1</span> <span class="punctuation">}</span><span class="punctuation">)</span><span class="punctuation">;</span> | 163 | <span class="variable mutable">vec</span><span class="operator">.</span><span class="unresolved_reference">push</span><span class="parenthesis">(</span><span class="struct">Foo</span> <span class="brace">{</span> <span class="field">x</span><span class="comma">,</span> <span class="field">y</span><span class="colon">:</span> <span class="numeric_literal">1</span> <span class="brace">}</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
164 | <span class="punctuation">}</span> | 164 | <span class="brace">}</span> |
165 | <span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span> | 165 | <span class="keyword unsafe">unsafe</span> <span class="brace">{</span> |
166 | <span class="variable mutable">vec</span><span class="operator">.</span><span class="unresolved_reference">set_len</span><span class="punctuation">(</span><span class="numeric_literal">0</span><span class="punctuation">)</span><span class="punctuation">;</span> | 166 | <span class="variable mutable">vec</span><span class="operator">.</span><span class="unresolved_reference">set_len</span><span class="parenthesis">(</span><span class="numeric_literal">0</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
167 | <span class="static mutable unsafe">STATIC_MUT</span> <span class="operator">=</span> <span class="numeric_literal">1</span><span class="punctuation">;</span> | 167 | <span class="static mutable unsafe">STATIC_MUT</span> <span class="operator">=</span> <span class="numeric_literal">1</span><span class="semicolon">;</span> |
168 | <span class="punctuation">}</span> | 168 | <span class="brace">}</span> |
169 | 169 | ||
170 | <span class="keyword control">for</span> <span class="variable declaration">e</span> <span class="keyword control">in</span> <span class="variable mutable">vec</span> <span class="punctuation">{</span> | 170 | <span class="keyword control">for</span> <span class="variable declaration">e</span> <span class="keyword control">in</span> <span class="variable mutable">vec</span> <span class="brace">{</span> |
171 | <span class="comment">// Do nothing</span> | 171 | <span class="comment">// Do nothing</span> |
172 | <span class="punctuation">}</span> | 172 | <span class="brace">}</span> |
173 | 173 | ||
174 | <span class="macro">noop!</span><span class="punctuation">(</span><span class="macro">noop</span><span class="macro">!</span><span class="punctuation">(</span><span class="numeric_literal">1</span><span class="punctuation">)</span><span class="punctuation">)</span><span class="punctuation">;</span> | 174 | <span class="macro">noop!</span><span class="parenthesis">(</span><span class="macro">noop</span><span class="macro">!</span><span class="parenthesis">(</span><span class="numeric_literal">1</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
175 | 175 | ||
176 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> <span class="operator">=</span> <span class="numeric_literal">42</span><span class="punctuation">;</span> | 176 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> <span class="operator">=</span> <span class="numeric_literal">42</span><span class="semicolon">;</span> |
177 | <span class="keyword">let</span> <span class="variable declaration mutable">y</span> <span class="operator">=</span> <span class="operator">&</span><span class="keyword">mut</span> <span class="variable mutable">x</span><span class="punctuation">;</span> | 177 | <span class="keyword">let</span> <span class="variable declaration mutable">y</span> <span class="operator">=</span> <span class="operator">&</span><span class="keyword">mut</span> <span class="variable mutable">x</span><span class="semicolon">;</span> |
178 | <span class="keyword">let</span> <span class="variable declaration">z</span> <span class="operator">=</span> <span class="operator">&</span><span class="variable mutable">y</span><span class="punctuation">;</span> | 178 | <span class="keyword">let</span> <span class="variable declaration">z</span> <span class="operator">=</span> <span class="operator">&</span><span class="variable mutable">y</span><span class="semicolon">;</span> |
179 | 179 | ||
180 | <span class="keyword">let</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">:</span> <span class="variable declaration">z</span><span class="punctuation">,</span> <span class="field">y</span> <span class="punctuation">}</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">:</span> <span class="variable">z</span><span class="punctuation">,</span> <span class="field">y</span> <span class="punctuation">}</span><span class="punctuation">;</span> | 180 | <span class="keyword">let</span> <span class="struct">Foo</span> <span class="brace">{</span> <span class="field">x</span><span class="colon">:</span> <span class="variable declaration">z</span><span class="comma">,</span> <span class="field">y</span> <span class="brace">}</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="brace">{</span> <span class="field">x</span><span class="colon">:</span> <span class="variable">z</span><span class="comma">,</span> <span class="field">y</span> <span class="brace">}</span><span class="semicolon">;</span> |
181 | 181 | ||
182 | <span class="variable">y</span><span class="punctuation">;</span> | 182 | <span class="variable">y</span><span class="semicolon">;</span> |
183 | 183 | ||
184 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">,</span> <span class="field">y</span><span class="punctuation">:</span> <span class="variable mutable">x</span> <span class="punctuation">}</span><span class="punctuation">;</span> | 184 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="brace">{</span> <span class="field">x</span><span class="comma">,</span> <span class="field">y</span><span class="colon">:</span> <span class="variable mutable">x</span> <span class="brace">}</span><span class="semicolon">;</span> |
185 | <span class="keyword">let</span> <span class="variable declaration">foo2</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">,</span> <span class="field">y</span><span class="punctuation">:</span> <span class="variable mutable">x</span> <span class="punctuation">}</span><span class="punctuation">;</span> | 185 | <span class="keyword">let</span> <span class="variable declaration">foo2</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="brace">{</span> <span class="field">x</span><span class="comma">,</span> <span class="field">y</span><span class="colon">:</span> <span class="variable mutable">x</span> <span class="brace">}</span><span class="semicolon">;</span> |
186 | <span class="variable mutable">foo</span><span class="operator">.</span><span class="function associated">quop</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 186 | <span class="variable mutable">foo</span><span class="operator">.</span><span class="function associated">quop</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
187 | <span class="variable mutable">foo</span><span class="operator">.</span><span class="function mutable associated">qux</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 187 | <span class="variable mutable">foo</span><span class="operator">.</span><span class="function mutable associated">qux</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
188 | <span class="variable mutable">foo</span><span class="operator">.</span><span class="function consuming associated">baz</span><span class="punctuation">(</span><span class="variable consuming">foo2</span><span class="punctuation">)</span><span class="punctuation">;</span> | 188 | <span class="variable mutable">foo</span><span class="operator">.</span><span class="function consuming associated">baz</span><span class="parenthesis">(</span><span class="variable consuming">foo2</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
189 | 189 | ||
190 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">copy</span> <span class="operator">=</span> <span class="struct">FooCopy</span> <span class="punctuation">{</span> <span class="field">x</span> <span class="punctuation">}</span><span class="punctuation">;</span> | 190 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">copy</span> <span class="operator">=</span> <span class="struct">FooCopy</span> <span class="brace">{</span> <span class="field">x</span> <span class="brace">}</span><span class="semicolon">;</span> |
191 | <span class="variable mutable">copy</span><span class="operator">.</span><span class="function associated">quop</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 191 | <span class="variable mutable">copy</span><span class="operator">.</span><span class="function associated">quop</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
192 | <span class="variable mutable">copy</span><span class="operator">.</span><span class="function mutable associated">qux</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 192 | <span class="variable mutable">copy</span><span class="operator">.</span><span class="function mutable associated">qux</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
193 | <span class="variable mutable">copy</span><span class="operator">.</span><span class="function associated">baz</span><span class="punctuation">(</span><span class="variable mutable">copy</span><span class="punctuation">)</span><span class="punctuation">;</span> | 193 | <span class="variable mutable">copy</span><span class="operator">.</span><span class="function associated">baz</span><span class="parenthesis">(</span><span class="variable mutable">copy</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
194 | 194 | ||
195 | <span class="keyword">let</span> <span class="variable declaration callable">a</span> <span class="operator">=</span> <span class="punctuation">|</span><span class="value_param declaration">x</span><span class="punctuation">|</span> <span class="value_param">x</span><span class="punctuation">;</span> | 195 | <span class="keyword">let</span> <span class="variable declaration callable">a</span> <span class="operator">=</span> <span class="punctuation">|</span><span class="value_param declaration">x</span><span class="punctuation">|</span> <span class="value_param">x</span><span class="semicolon">;</span> |
196 | <span class="keyword">let</span> <span class="variable declaration callable">bar</span> <span class="operator">=</span> <span class="struct">Foo</span><span class="operator">::</span><span class="function associated">baz</span><span class="punctuation">;</span> | 196 | <span class="keyword">let</span> <span class="variable declaration callable">bar</span> <span class="operator">=</span> <span class="struct">Foo</span><span class="operator">::</span><span class="function associated">baz</span><span class="semicolon">;</span> |
197 | 197 | ||
198 | <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="numeric_literal">-</span><span class="numeric_literal">42</span><span class="punctuation">;</span> | 198 | <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="numeric_literal">-</span><span class="numeric_literal">42</span><span class="semicolon">;</span> |
199 | <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="operator">-</span><span class="variable">baz</span><span class="punctuation">;</span> | 199 | <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="operator">-</span><span class="variable">baz</span><span class="semicolon">;</span> |
200 | 200 | ||
201 | <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="operator">!</span><span class="bool_literal">true</span><span class="punctuation">;</span> | 201 | <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="operator">!</span><span class="bool_literal">true</span><span class="semicolon">;</span> |
202 | 202 | ||
203 | <span class="label declaration">'foo</span><span class="punctuation">:</span> <span class="keyword control">loop</span> <span class="punctuation">{</span> | 203 | <span class="label declaration">'foo</span><span class="colon">:</span> <span class="keyword control">loop</span> <span class="brace">{</span> |
204 | <span class="keyword control">break</span> <span class="label">'foo</span><span class="punctuation">;</span> | 204 | <span class="keyword control">break</span> <span class="label">'foo</span><span class="semicolon">;</span> |
205 | <span class="keyword control">continue</span> <span class="label">'foo</span><span class="punctuation">;</span> | 205 | <span class="keyword control">continue</span> <span class="label">'foo</span><span class="semicolon">;</span> |
206 | <span class="punctuation">}</span> | 206 | <span class="brace">}</span> |
207 | <span class="punctuation">}</span> | 207 | <span class="brace">}</span> |
208 | 208 | ||
209 | <span class="keyword">enum</span> <span class="enum declaration">Option</span><span class="punctuation"><</span><span class="type_param declaration">T</span><span class="punctuation">></span> <span class="punctuation">{</span> | 209 | <span class="keyword">enum</span> <span class="enum declaration">Option</span><span class="angle"><</span><span class="type_param declaration">T</span><span class="angle">></span> <span class="brace">{</span> |
210 | <span class="enum_variant declaration">Some</span><span class="punctuation">(</span><span class="type_param">T</span><span class="punctuation">)</span><span class="punctuation">,</span> | 210 | <span class="enum_variant declaration">Some</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="parenthesis">)</span><span class="comma">,</span> |
211 | <span class="enum_variant declaration">None</span><span class="punctuation">,</span> | 211 | <span class="enum_variant declaration">None</span><span class="comma">,</span> |
212 | <span class="punctuation">}</span> | 212 | <span class="brace">}</span> |
213 | <span class="keyword">use</span> <span class="enum">Option</span><span class="operator">::</span><span class="punctuation">*</span><span class="punctuation">;</span> | 213 | <span class="keyword">use</span> <span class="enum">Option</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span> |
214 | 214 | ||
215 | <span class="keyword">impl</span><span class="punctuation"><</span><span class="type_param declaration">T</span><span class="punctuation">></span> <span class="enum">Option</span><span class="punctuation"><</span><span class="type_param">T</span><span class="punctuation">></span> <span class="punctuation">{</span> | 215 | <span class="keyword">impl</span><span class="angle"><</span><span class="type_param declaration">T</span><span class="angle">></span> <span class="enum">Option</span><span class="angle"><</span><span class="type_param">T</span><span class="angle">></span> <span class="brace">{</span> |
216 | <span class="keyword">fn</span> <span class="function declaration associated">and</span><span class="punctuation"><</span><span class="type_param declaration">U</span><span class="punctuation">></span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">,</span> <span class="value_param declaration">other</span><span class="punctuation">:</span> <span class="enum">Option</span><span class="punctuation"><</span><span class="type_param">U</span><span class="punctuation">></span><span class="punctuation">)</span> <span class="operator">-></span> <span class="enum">Option</span><span class="punctuation"><</span><span class="punctuation">(</span><span class="type_param">T</span><span class="punctuation">,</span> <span class="type_param">U</span><span class="punctuation">)</span><span class="punctuation">></span> <span class="punctuation">{</span> | 216 | <span class="keyword">fn</span> <span class="function declaration associated">and</span><span class="angle"><</span><span class="type_param declaration">U</span><span class="angle">></span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="comma">,</span> <span class="value_param declaration">other</span><span class="colon">:</span> <span class="enum">Option</span><span class="angle"><</span><span class="type_param">U</span><span class="angle">></span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="enum">Option</span><span class="angle"><</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="comma">,</span> <span class="type_param">U</span><span class="parenthesis">)</span><span class="angle">></span> <span class="brace">{</span> |
217 | <span class="keyword control">match</span> <span class="value_param">other</span> <span class="punctuation">{</span> | 217 | <span class="keyword control">match</span> <span class="value_param">other</span> <span class="brace">{</span> |
218 | <span class="enum_variant">None</span> <span class="operator">=></span> <span class="macro">unimplemented!</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span> | 218 | <span class="enum_variant">None</span> <span class="operator">=></span> <span class="macro">unimplemented!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span> |
219 | <span class="variable declaration">Nope</span> <span class="operator">=></span> <span class="variable">Nope</span><span class="punctuation">,</span> | 219 | <span class="variable declaration">Nope</span> <span class="operator">=></span> <span class="variable">Nope</span><span class="comma">,</span> |
220 | <span class="punctuation">}</span> | 220 | <span class="brace">}</span> |
221 | <span class="punctuation">}</span> | 221 | <span class="brace">}</span> |
222 | <span class="punctuation">}</span></code></pre> \ No newline at end of file | 222 | <span class="brace">}</span></code></pre> \ No newline at end of file |
diff --git a/crates/ide/src/syntax_highlighting/test_data/injection.html b/crates/ide/src/syntax_highlighting/test_data/injection.html new file mode 100644 index 000000000..78dfec951 --- /dev/null +++ b/crates/ide/src/syntax_highlighting/test_data/injection.html | |||
@@ -0,0 +1,48 @@ | |||
1 | |||
2 | <style> | ||
3 | body { margin: 0; } | ||
4 | pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } | ||
5 | |||
6 | .lifetime { color: #DFAF8F; font-style: italic; } | ||
7 | .label { color: #DFAF8F; font-style: italic; } | ||
8 | .comment { color: #7F9F7F; } | ||
9 | .documentation { color: #629755; } | ||
10 | .injected { opacity: 0.65 ; } | ||
11 | .struct, .enum { color: #7CB8BB; } | ||
12 | .enum_variant { color: #BDE0F3; } | ||
13 | .string_literal { color: #CC9393; } | ||
14 | .field { color: #94BFF3; } | ||
15 | .function { color: #93E0E3; } | ||
16 | .function.unsafe { color: #BC8383; } | ||
17 | .operator.unsafe { color: #BC8383; } | ||
18 | .parameter { color: #94BFF3; } | ||
19 | .text { color: #DCDCCC; } | ||
20 | .type { color: #7CB8BB; } | ||
21 | .builtin_type { color: #8CD0D3; } | ||
22 | .type_param { color: #DFAF8F; } | ||
23 | .attribute { color: #94BFF3; } | ||
24 | .numeric_literal { color: #BFEBBF; } | ||
25 | .bool_literal { color: #BFE6EB; } | ||
26 | .macro { color: #94BFF3; } | ||
27 | .module { color: #AFD8AF; } | ||
28 | .value_param { color: #DCDCCC; } | ||
29 | .variable { color: #DCDCCC; } | ||
30 | .format_specifier { color: #CC696B; } | ||
31 | .mutable { text-decoration: underline; } | ||
32 | .escape_sequence { color: #94BFF3; } | ||
33 | .keyword { color: #F0DFAF; font-weight: bold; } | ||
34 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | ||
35 | .control { font-style: italic; } | ||
36 | |||
37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } | ||
38 | </style> | ||
39 | <pre><code><span class="keyword">fn</span> <span class="function declaration">f</span><span class="parenthesis">(</span><span class="value_param declaration">ra_fixture</span><span class="colon">:</span> <span class="operator">&</span><span class="builtin_type">str</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> | ||
40 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> | ||
41 | <span class="function">f</span><span class="parenthesis">(</span><span class="string_literal">r"</span> | ||
42 | <span class="keyword">fn</span> <span class="function declaration">foo</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> | ||
43 | <span class="function">foo</span><span class="parenthesis">(</span><span class="keyword">$0</span><span class="brace">{</span> | ||
44 | <span class="numeric_literal">92</span> | ||
45 | <span class="brace">}</span><span class="keyword">$0</span><span class="parenthesis">)</span> | ||
46 | <span class="brace">}</span><span class="string_literal">"</span><span class="parenthesis">)</span><span class="semicolon">;</span> | ||
47 | <span class="brace">}</span> | ||
48 | </code></pre> \ No newline at end of file | ||
diff --git a/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html b/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html index 8b3dfa69f..e64f2e5e9 100644 --- a/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html | |||
@@ -36,15 +36,15 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
36 | 36 | ||
37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } | 37 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } |
38 | </style> | 38 | </style> |
39 | <pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 39 | <pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> |
40 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="punctuation">;</span> | 40 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span> |
41 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="2705725358298919760" style="color: hsl(76,47%,83%);">x</span> <span class="operator">=</span> <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 41 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="2705725358298919760" style="color: hsl(76,47%,83%);">x</span> <span class="operator">=</span> <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
42 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="3365759661443752373" style="color: hsl(15,86%,51%);">y</span> <span class="operator">=</span> <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 42 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="3365759661443752373" style="color: hsl(15,86%,51%);">y</span> <span class="operator">=</span> <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
43 | 43 | ||
44 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="794745962933817518" style="color: hsl(127,71%,87%);">x</span> <span class="operator">=</span> <span class="string_literal">"other color please!"</span><span class="punctuation">;</span> | 44 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="794745962933817518" style="color: hsl(127,71%,87%);">x</span> <span class="operator">=</span> <span class="string_literal">"other color please!"</span><span class="semicolon">;</span> |
45 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="6717528807933952652" style="color: hsl(90,74%,79%);">y</span> <span class="operator">=</span> <span class="variable" data-binding-hash="794745962933817518" style="color: hsl(127,71%,87%);">x</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 45 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="6717528807933952652" style="color: hsl(90,74%,79%);">y</span> <span class="operator">=</span> <span class="variable" data-binding-hash="794745962933817518" style="color: hsl(127,71%,87%);">x</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
46 | <span class="punctuation">}</span> | 46 | <span class="brace">}</span> |
47 | 47 | ||
48 | <span class="keyword">fn</span> <span class="function declaration">bar</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 48 | <span class="keyword">fn</span> <span class="function declaration">bar</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> |
49 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="punctuation">;</span> | 49 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span> |
50 | <span class="punctuation">}</span></code></pre> \ No newline at end of file | 50 | <span class="brace">}</span></code></pre> \ No newline at end of file |
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index 30b5b648e..a62704c39 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs | |||
@@ -446,6 +446,11 @@ struct Foo { | |||
446 | } | 446 | } |
447 | 447 | ||
448 | impl Foo { | 448 | impl Foo { |
449 | /// ``` | ||
450 | /// let _ = "Call me | ||
451 | // KILLER WHALE | ||
452 | /// Ishmael."; | ||
453 | /// ``` | ||
449 | pub const bar: bool = true; | 454 | pub const bar: bool = true; |
450 | 455 | ||
451 | /// Constructs a new `Foo`. | 456 | /// Constructs a new `Foo`. |
@@ -555,6 +560,25 @@ impl t for foo { | |||
555 | ) | 560 | ) |
556 | } | 561 | } |
557 | 562 | ||
563 | #[test] | ||
564 | fn test_injection() { | ||
565 | check_highlighting( | ||
566 | r##" | ||
567 | fn f(ra_fixture: &str) {} | ||
568 | fn main() { | ||
569 | f(r" | ||
570 | fn foo() { | ||
571 | foo(\$0{ | ||
572 | 92 | ||
573 | }\$0) | ||
574 | }"); | ||
575 | } | ||
576 | "##, | ||
577 | expect_file!["./test_data/injection.html"], | ||
578 | false, | ||
579 | ); | ||
580 | } | ||
581 | |||
558 | /// Highlights the code given by the `ra_fixture` argument, renders the | 582 | /// Highlights the code given by the `ra_fixture` argument, renders the |
559 | /// result as HTML, and compares it with the HTML file given as `snapshot`. | 583 | /// result as HTML, and compares it with the HTML file given as `snapshot`. |
560 | /// Note that the `snapshot` file is overwritten by the rendered HTML. | 584 | /// Note that the `snapshot` file is overwritten by the rendered HTML. |
diff --git a/crates/ide/src/syntax_tree.rs b/crates/ide/src/syntax_tree.rs index 6dd05c05d..1f26f8043 100644 --- a/crates/ide/src/syntax_tree.rs +++ b/crates/ide/src/syntax_tree.rs | |||
@@ -85,7 +85,7 @@ fn syntax_tree_for_token(node: &SyntaxToken, text_range: TextRange) -> Option<St | |||
85 | .trim_end_matches('"') | 85 | .trim_end_matches('"') |
86 | .trim() | 86 | .trim() |
87 | // Remove custom markers | 87 | // Remove custom markers |
88 | .replace("<|>", ""); | 88 | .replace("$0", ""); |
89 | 89 | ||
90 | let parsed = SourceFile::parse(&text); | 90 | let parsed = SourceFile::parse(&text); |
91 | 91 | ||
@@ -182,7 +182,7 @@ [email protected] | |||
182 | 182 | ||
183 | #[test] | 183 | #[test] |
184 | fn test_syntax_tree_with_range() { | 184 | fn test_syntax_tree_with_range() { |
185 | let (analysis, range) = fixture::range(r#"<|>fn foo() {}<|>"#.trim()); | 185 | let (analysis, range) = fixture::range(r#"$0fn foo() {}$0"#.trim()); |
186 | let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); | 186 | let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); |
187 | 187 | ||
188 | assert_eq_text!( | 188 | assert_eq_text!( |
@@ -206,10 +206,10 @@ [email protected] | |||
206 | 206 | ||
207 | let (analysis, range) = fixture::range( | 207 | let (analysis, range) = fixture::range( |
208 | r#"fn test() { | 208 | r#"fn test() { |
209 | <|>assert!(" | 209 | $0assert!(" |
210 | fn foo() { | 210 | fn foo() { |
211 | } | 211 | } |
212 | ", "");<|> | 212 | ", "");$0 |
213 | }"# | 213 | }"# |
214 | .trim(), | 214 | .trim(), |
215 | ); | 215 | ); |
@@ -243,8 +243,8 @@ [email protected] | |||
243 | let (analysis, range) = fixture::range( | 243 | let (analysis, range) = fixture::range( |
244 | r#"fn test() { | 244 | r#"fn test() { |
245 | assert!(" | 245 | assert!(" |
246 | <|>fn foo() { | 246 | $0fn foo() { |
247 | }<|> | 247 | }$0 |
248 | fn bar() { | 248 | fn bar() { |
249 | } | 249 | } |
250 | ", ""); | 250 | ", ""); |
@@ -277,8 +277,8 @@ [email protected] | |||
277 | let (analysis, range) = fixture::range( | 277 | let (analysis, range) = fixture::range( |
278 | r###"fn test() { | 278 | r###"fn test() { |
279 | assert!(r#" | 279 | assert!(r#" |
280 | <|>fn foo() { | 280 | $0fn foo() { |
281 | }<|> | 281 | }$0 |
282 | fn bar() { | 282 | fn bar() { |
283 | } | 283 | } |
284 | "#, ""); | 284 | "#, ""); |
@@ -310,11 +310,11 @@ [email protected] | |||
310 | // With a raw string | 310 | // With a raw string |
311 | let (analysis, range) = fixture::range( | 311 | let (analysis, range) = fixture::range( |
312 | r###"fn test() { | 312 | r###"fn test() { |
313 | assert!(r<|>#" | 313 | assert!(r$0#" |
314 | fn foo() { | 314 | fn foo() { |
315 | } | 315 | } |
316 | fn bar() { | 316 | fn bar() { |
317 | }"<|>#, ""); | 317 | }"$0#, ""); |
318 | }"### | 318 | }"### |
319 | .trim(), | 319 | .trim(), |
320 | ); | 320 | ); |
diff --git a/crates/ide/src/typing.rs b/crates/ide/src/typing.rs index 43458a3a2..88c905003 100644 --- a/crates/ide/src/typing.rs +++ b/crates/ide/src/typing.rs | |||
@@ -170,7 +170,7 @@ mod tests { | |||
170 | fn test_on_eq_typed() { | 170 | fn test_on_eq_typed() { |
171 | // do_check(r" | 171 | // do_check(r" |
172 | // fn foo() { | 172 | // fn foo() { |
173 | // let foo =<|> | 173 | // let foo =$0 |
174 | // } | 174 | // } |
175 | // ", r" | 175 | // ", r" |
176 | // fn foo() { | 176 | // fn foo() { |
@@ -181,7 +181,7 @@ mod tests { | |||
181 | '=', | 181 | '=', |
182 | r" | 182 | r" |
183 | fn foo() { | 183 | fn foo() { |
184 | let foo <|> 1 + 1 | 184 | let foo $0 1 + 1 |
185 | } | 185 | } |
186 | ", | 186 | ", |
187 | r" | 187 | r" |
@@ -192,7 +192,7 @@ fn foo() { | |||
192 | ); | 192 | ); |
193 | // do_check(r" | 193 | // do_check(r" |
194 | // fn foo() { | 194 | // fn foo() { |
195 | // let foo =<|> | 195 | // let foo =$0 |
196 | // let bar = 1; | 196 | // let bar = 1; |
197 | // } | 197 | // } |
198 | // ", r" | 198 | // ", r" |
@@ -210,7 +210,7 @@ fn foo() { | |||
210 | r" | 210 | r" |
211 | fn main() { | 211 | fn main() { |
212 | xs.foo() | 212 | xs.foo() |
213 | <|> | 213 | $0 |
214 | } | 214 | } |
215 | ", | 215 | ", |
216 | r" | 216 | r" |
@@ -225,7 +225,7 @@ fn foo() { | |||
225 | r" | 225 | r" |
226 | fn main() { | 226 | fn main() { |
227 | xs.foo() | 227 | xs.foo() |
228 | <|> | 228 | $0 |
229 | } | 229 | } |
230 | ", | 230 | ", |
231 | ) | 231 | ) |
@@ -238,7 +238,7 @@ fn foo() { | |||
238 | r" | 238 | r" |
239 | fn main() { | 239 | fn main() { |
240 | xs.foo() | 240 | xs.foo() |
241 | <|>; | 241 | $0; |
242 | } | 242 | } |
243 | ", | 243 | ", |
244 | r" | 244 | r" |
@@ -253,7 +253,7 @@ fn foo() { | |||
253 | r" | 253 | r" |
254 | fn main() { | 254 | fn main() { |
255 | xs.foo() | 255 | xs.foo() |
256 | <|>; | 256 | $0; |
257 | } | 257 | } |
258 | ", | 258 | ", |
259 | ) | 259 | ) |
@@ -266,7 +266,7 @@ fn foo() { | |||
266 | r#" | 266 | r#" |
267 | fn main() { | 267 | fn main() { |
268 | let _ = foo | 268 | let _ = foo |
269 | <|> | 269 | $0 |
270 | bar() | 270 | bar() |
271 | } | 271 | } |
272 | "#, | 272 | "#, |
@@ -288,7 +288,7 @@ fn main() { | |||
288 | fn main() { | 288 | fn main() { |
289 | xs.foo() | 289 | xs.foo() |
290 | .first() | 290 | .first() |
291 | <|> | 291 | $0 |
292 | } | 292 | } |
293 | ", | 293 | ", |
294 | r" | 294 | r" |
@@ -305,7 +305,7 @@ fn main() { | |||
305 | fn main() { | 305 | fn main() { |
306 | xs.foo() | 306 | xs.foo() |
307 | .first() | 307 | .first() |
308 | <|> | 308 | $0 |
309 | } | 309 | } |
310 | ", | 310 | ", |
311 | ); | 311 | ); |
@@ -318,7 +318,7 @@ fn main() { | |||
318 | r" | 318 | r" |
319 | fn source_impl() { | 319 | fn source_impl() { |
320 | let var = enum_defvariant_list().unwrap() | 320 | let var = enum_defvariant_list().unwrap() |
321 | <|> | 321 | $0 |
322 | .nth(92) | 322 | .nth(92) |
323 | .unwrap(); | 323 | .unwrap(); |
324 | } | 324 | } |
@@ -337,7 +337,7 @@ fn main() { | |||
337 | r" | 337 | r" |
338 | fn source_impl() { | 338 | fn source_impl() { |
339 | let var = enum_defvariant_list().unwrap() | 339 | let var = enum_defvariant_list().unwrap() |
340 | <|> | 340 | $0 |
341 | .nth(92) | 341 | .nth(92) |
342 | .unwrap(); | 342 | .unwrap(); |
343 | } | 343 | } |
@@ -351,7 +351,7 @@ fn main() { | |||
351 | '.', | 351 | '.', |
352 | r" | 352 | r" |
353 | fn main() { | 353 | fn main() { |
354 | <|> | 354 | $0 |
355 | } | 355 | } |
356 | ", | 356 | ", |
357 | ); | 357 | ); |
@@ -359,7 +359,7 @@ fn main() { | |||
359 | '.', | 359 | '.', |
360 | r" | 360 | r" |
361 | fn main() { | 361 | fn main() { |
362 | <|> | 362 | $0 |
363 | } | 363 | } |
364 | ", | 364 | ", |
365 | ); | 365 | ); |
@@ -367,6 +367,6 @@ fn main() { | |||
367 | 367 | ||
368 | #[test] | 368 | #[test] |
369 | fn adds_space_after_return_type() { | 369 | fn adds_space_after_return_type() { |
370 | type_char('>', "fn foo() -<|>{ 92 }", "fn foo() -> { 92 }") | 370 | type_char('>', "fn foo() -$0{ 92 }", "fn foo() -> { 92 }") |
371 | } | 371 | } |
372 | } | 372 | } |
diff --git a/crates/ide/src/typing/on_enter.rs b/crates/ide/src/typing/on_enter.rs index f4ea30352..63cd51b69 100644 --- a/crates/ide/src/typing/on_enter.rs +++ b/crates/ide/src/typing/on_enter.rs | |||
@@ -136,7 +136,7 @@ mod tests { | |||
136 | fn continues_doc_comment() { | 136 | fn continues_doc_comment() { |
137 | do_check( | 137 | do_check( |
138 | r" | 138 | r" |
139 | /// Some docs<|> | 139 | /// Some docs$0 |
140 | fn foo() { | 140 | fn foo() { |
141 | } | 141 | } |
142 | ", | 142 | ", |
@@ -151,7 +151,7 @@ fn foo() { | |||
151 | do_check( | 151 | do_check( |
152 | r" | 152 | r" |
153 | impl S { | 153 | impl S { |
154 | /// Some<|> docs. | 154 | /// Some$0 docs. |
155 | fn foo() {} | 155 | fn foo() {} |
156 | } | 156 | } |
157 | ", | 157 | ", |
@@ -166,7 +166,7 @@ impl S { | |||
166 | 166 | ||
167 | do_check( | 167 | do_check( |
168 | r" | 168 | r" |
169 | ///<|> Some docs | 169 | ///$0 Some docs |
170 | fn foo() { | 170 | fn foo() { |
171 | } | 171 | } |
172 | ", | 172 | ", |
@@ -181,7 +181,7 @@ fn foo() { | |||
181 | 181 | ||
182 | #[test] | 182 | #[test] |
183 | fn does_not_continue_before_doc_comment() { | 183 | fn does_not_continue_before_doc_comment() { |
184 | do_check_noop(r"<|>//! docz"); | 184 | do_check_noop(r"$0//! docz"); |
185 | } | 185 | } |
186 | 186 | ||
187 | #[test] | 187 | #[test] |
@@ -189,7 +189,7 @@ fn foo() { | |||
189 | do_check( | 189 | do_check( |
190 | r" | 190 | r" |
191 | fn main() { | 191 | fn main() { |
192 | // Fix<|> me | 192 | // Fix$0 me |
193 | let x = 1 + 1; | 193 | let x = 1 + 1; |
194 | } | 194 | } |
195 | ", | 195 | ", |
@@ -208,7 +208,7 @@ fn main() { | |||
208 | do_check( | 208 | do_check( |
209 | r" | 209 | r" |
210 | fn main() { | 210 | fn main() { |
211 | // Fix<|> | 211 | // Fix$0 |
212 | // me | 212 | // me |
213 | let x = 1 + 1; | 213 | let x = 1 + 1; |
214 | } | 214 | } |
@@ -229,7 +229,7 @@ fn main() { | |||
229 | do_check_noop( | 229 | do_check_noop( |
230 | r" | 230 | r" |
231 | fn main() { | 231 | fn main() { |
232 | // Fix me<|> | 232 | // Fix me$0 |
233 | let x = 1 + 1; | 233 | let x = 1 + 1; |
234 | } | 234 | } |
235 | ", | 235 | ", |
@@ -242,7 +242,7 @@ fn main() { | |||
242 | do_check( | 242 | do_check( |
243 | r#" | 243 | r#" |
244 | fn main() { | 244 | fn main() { |
245 | // Fix me <|> | 245 | // Fix me $0 |
246 | let x = 1 + 1; | 246 | let x = 1 + 1; |
247 | } | 247 | } |
248 | "#, | 248 | "#, |
@@ -261,7 +261,7 @@ fn main() { | |||
261 | do_check( | 261 | do_check( |
262 | " | 262 | " |
263 | fn main() { | 263 | fn main() { |
264 | // Fix me \t\t <|> | 264 | // Fix me \t\t $0 |
265 | let x = 1 + 1; | 265 | let x = 1 + 1; |
266 | } | 266 | } |
267 | ", | 267 | ", |
diff --git a/crates/ide_db/src/apply_change.rs b/crates/ide_db/src/apply_change.rs index 71c19ed13..c770a236b 100644 --- a/crates/ide_db/src/apply_change.rs +++ b/crates/ide_db/src/apply_change.rs | |||
@@ -145,6 +145,7 @@ impl RootDatabase { | |||
145 | hir::db::MacroDefQuery | 145 | hir::db::MacroDefQuery |
146 | hir::db::ParseMacroExpansionQuery | 146 | hir::db::ParseMacroExpansionQuery |
147 | hir::db::MacroExpandQuery | 147 | hir::db::MacroExpandQuery |
148 | hir::db::HygieneFrameQuery | ||
148 | 149 | ||
149 | // DefDatabase | 150 | // DefDatabase |
150 | hir::db::ItemTreeQuery | 151 | hir::db::ItemTreeQuery |
diff --git a/crates/ide_db/src/call_info/tests.rs b/crates/ide_db/src/call_info/tests.rs index 9335aeaa5..c714cf280 100644 --- a/crates/ide_db/src/call_info/tests.rs +++ b/crates/ide_db/src/call_info/tests.rs | |||
@@ -3,12 +3,12 @@ use base_db::{fixture::ChangeFixture, FilePosition}; | |||
3 | use expect_test::{expect, Expect}; | 3 | use expect_test::{expect, Expect}; |
4 | use test_utils::{mark, RangeOrOffset}; | 4 | use test_utils::{mark, RangeOrOffset}; |
5 | 5 | ||
6 | /// Creates analysis from a multi-file fixture, returns positions marked with <|>. | 6 | /// Creates analysis from a multi-file fixture, returns positions marked with $0. |
7 | pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) { | 7 | pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) { |
8 | let change_fixture = ChangeFixture::parse(ra_fixture); | 8 | let change_fixture = ChangeFixture::parse(ra_fixture); |
9 | let mut database = RootDatabase::default(); | 9 | let mut database = RootDatabase::default(); |
10 | database.apply_change(change_fixture.change); | 10 | database.apply_change(change_fixture.change); |
11 | let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker (<|>)"); | 11 | let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker ($0)"); |
12 | let offset = match range_or_offset { | 12 | let offset = match range_or_offset { |
13 | RangeOrOffset::Range(_) => panic!(), | 13 | RangeOrOffset::Range(_) => panic!(), |
14 | RangeOrOffset::Offset(it) => it, | 14 | RangeOrOffset::Offset(it) => it, |
@@ -49,7 +49,7 @@ fn test_fn_signature_two_args() { | |||
49 | check( | 49 | check( |
50 | r#" | 50 | r#" |
51 | fn foo(x: u32, y: u32) -> u32 {x + y} | 51 | fn foo(x: u32, y: u32) -> u32 {x + y} |
52 | fn bar() { foo(<|>3, ); } | 52 | fn bar() { foo($03, ); } |
53 | "#, | 53 | "#, |
54 | expect![[r#" | 54 | expect![[r#" |
55 | fn foo(x: u32, y: u32) -> u32 | 55 | fn foo(x: u32, y: u32) -> u32 |
@@ -59,7 +59,7 @@ fn bar() { foo(<|>3, ); } | |||
59 | check( | 59 | check( |
60 | r#" | 60 | r#" |
61 | fn foo(x: u32, y: u32) -> u32 {x + y} | 61 | fn foo(x: u32, y: u32) -> u32 {x + y} |
62 | fn bar() { foo(3<|>, ); } | 62 | fn bar() { foo(3$0, ); } |
63 | "#, | 63 | "#, |
64 | expect![[r#" | 64 | expect![[r#" |
65 | fn foo(x: u32, y: u32) -> u32 | 65 | fn foo(x: u32, y: u32) -> u32 |
@@ -69,7 +69,7 @@ fn bar() { foo(3<|>, ); } | |||
69 | check( | 69 | check( |
70 | r#" | 70 | r#" |
71 | fn foo(x: u32, y: u32) -> u32 {x + y} | 71 | fn foo(x: u32, y: u32) -> u32 {x + y} |
72 | fn bar() { foo(3,<|> ); } | 72 | fn bar() { foo(3,$0 ); } |
73 | "#, | 73 | "#, |
74 | expect![[r#" | 74 | expect![[r#" |
75 | fn foo(x: u32, y: u32) -> u32 | 75 | fn foo(x: u32, y: u32) -> u32 |
@@ -79,7 +79,7 @@ fn bar() { foo(3,<|> ); } | |||
79 | check( | 79 | check( |
80 | r#" | 80 | r#" |
81 | fn foo(x: u32, y: u32) -> u32 {x + y} | 81 | fn foo(x: u32, y: u32) -> u32 {x + y} |
82 | fn bar() { foo(3, <|>); } | 82 | fn bar() { foo(3, $0); } |
83 | "#, | 83 | "#, |
84 | expect![[r#" | 84 | expect![[r#" |
85 | fn foo(x: u32, y: u32) -> u32 | 85 | fn foo(x: u32, y: u32) -> u32 |
@@ -93,7 +93,7 @@ fn test_fn_signature_two_args_empty() { | |||
93 | check( | 93 | check( |
94 | r#" | 94 | r#" |
95 | fn foo(x: u32, y: u32) -> u32 {x + y} | 95 | fn foo(x: u32, y: u32) -> u32 {x + y} |
96 | fn bar() { foo(<|>); } | 96 | fn bar() { foo($0); } |
97 | "#, | 97 | "#, |
98 | expect![[r#" | 98 | expect![[r#" |
99 | fn foo(x: u32, y: u32) -> u32 | 99 | fn foo(x: u32, y: u32) -> u32 |
@@ -110,7 +110,7 @@ fn foo<T, U: Copy + Display>(x: T, y: U) -> u32 | |||
110 | where T: Copy + Display, U: Debug | 110 | where T: Copy + Display, U: Debug |
111 | { x + y } | 111 | { x + y } |
112 | 112 | ||
113 | fn bar() { foo(<|>3, ); } | 113 | fn bar() { foo($03, ); } |
114 | "#, | 114 | "#, |
115 | expect![[r#" | 115 | expect![[r#" |
116 | fn foo(x: i32, y: {unknown}) -> u32 | 116 | fn foo(x: i32, y: {unknown}) -> u32 |
@@ -124,7 +124,7 @@ fn test_fn_signature_no_params() { | |||
124 | check( | 124 | check( |
125 | r#" | 125 | r#" |
126 | fn foo<T>() -> T where T: Copy + Display {} | 126 | fn foo<T>() -> T where T: Copy + Display {} |
127 | fn bar() { foo(<|>); } | 127 | fn bar() { foo($0); } |
128 | "#, | 128 | "#, |
129 | expect![[r#" | 129 | expect![[r#" |
130 | fn foo() -> {unknown} | 130 | fn foo() -> {unknown} |
@@ -140,7 +140,7 @@ fn test_fn_signature_for_impl() { | |||
140 | struct F; | 140 | struct F; |
141 | impl F { pub fn new() { } } | 141 | impl F { pub fn new() { } } |
142 | fn bar() { | 142 | fn bar() { |
143 | let _ : F = F::new(<|>); | 143 | let _ : F = F::new($0); |
144 | } | 144 | } |
145 | "#, | 145 | "#, |
146 | expect![[r#" | 146 | expect![[r#" |
@@ -159,7 +159,7 @@ impl S { pub fn do_it(&self) {} } | |||
159 | 159 | ||
160 | fn bar() { | 160 | fn bar() { |
161 | let s: S = S; | 161 | let s: S = S; |
162 | s.do_it(<|>); | 162 | s.do_it($0); |
163 | } | 163 | } |
164 | "#, | 164 | "#, |
165 | expect![[r#" | 165 | expect![[r#" |
@@ -178,7 +178,7 @@ impl S { | |||
178 | fn foo(&self, x: i32) {} | 178 | fn foo(&self, x: i32) {} |
179 | } | 179 | } |
180 | 180 | ||
181 | fn main() { S.foo(<|>); } | 181 | fn main() { S.foo($0); } |
182 | "#, | 182 | "#, |
183 | expect![[r#" | 183 | expect![[r#" |
184 | fn foo(&self, x: i32) | 184 | fn foo(&self, x: i32) |
@@ -196,7 +196,7 @@ impl S { | |||
196 | fn foo(&self, x: i32) {} | 196 | fn foo(&self, x: i32) {} |
197 | } | 197 | } |
198 | 198 | ||
199 | fn main() { S::foo(<|>); } | 199 | fn main() { S::foo($0); } |
200 | "#, | 200 | "#, |
201 | expect![[r#" | 201 | expect![[r#" |
202 | fn foo(self: &S, x: i32) | 202 | fn foo(self: &S, x: i32) |
@@ -216,7 +216,7 @@ fn foo(j: u32) -> u32 { | |||
216 | } | 216 | } |
217 | 217 | ||
218 | fn bar() { | 218 | fn bar() { |
219 | let _ = foo(<|>); | 219 | let _ = foo($0); |
220 | } | 220 | } |
221 | "#, | 221 | "#, |
222 | expect![[r#" | 222 | expect![[r#" |
@@ -246,7 +246,7 @@ pub fn add_one(x: i32) -> i32 { | |||
246 | } | 246 | } |
247 | 247 | ||
248 | pub fn do() { | 248 | pub fn do() { |
249 | add_one(<|> | 249 | add_one($0 |
250 | }"#, | 250 | }"#, |
251 | expect![[r##" | 251 | expect![[r##" |
252 | Adds one to the number given. | 252 | Adds one to the number given. |
@@ -287,7 +287,7 @@ impl addr { | |||
287 | 287 | ||
288 | pub fn do_it() { | 288 | pub fn do_it() { |
289 | addr {}; | 289 | addr {}; |
290 | addr::add_one(<|>); | 290 | addr::add_one($0); |
291 | } | 291 | } |
292 | "#, | 292 | "#, |
293 | expect![[r##" | 293 | expect![[r##" |
@@ -331,7 +331,7 @@ impl<E> WriteHandler<E> { | |||
331 | } | 331 | } |
332 | 332 | ||
333 | pub fn foo(mut r: WriteHandler<()>) { | 333 | pub fn foo(mut r: WriteHandler<()>) { |
334 | r.finished(<|>); | 334 | r.finished($0); |
335 | } | 335 | } |
336 | "#, | 336 | "#, |
337 | expect![[r#" | 337 | expect![[r#" |
@@ -351,7 +351,7 @@ fn call_info_bad_offset() { | |||
351 | check( | 351 | check( |
352 | r#" | 352 | r#" |
353 | fn foo(x: u32, y: u32) -> u32 {x + y} | 353 | fn foo(x: u32, y: u32) -> u32 {x + y} |
354 | fn bar() { foo <|> (3, ); } | 354 | fn bar() { foo $0 (3, ); } |
355 | "#, | 355 | "#, |
356 | expect![[""]], | 356 | expect![[""]], |
357 | ); | 357 | ); |
@@ -368,7 +368,7 @@ fn bar(_: u32) { } | |||
368 | 368 | ||
369 | fn main() { | 369 | fn main() { |
370 | let foo = Foo; | 370 | let foo = Foo; |
371 | std::thread::spawn(move || foo.bar(<|>)); | 371 | std::thread::spawn(move || foo.bar($0)); |
372 | } | 372 | } |
373 | "#, | 373 | "#, |
374 | expect![[r#" | 374 | expect![[r#" |
@@ -385,7 +385,7 @@ fn works_for_tuple_structs() { | |||
385 | /// A cool tuple struct | 385 | /// A cool tuple struct |
386 | struct S(u32, i32); | 386 | struct S(u32, i32); |
387 | fn main() { | 387 | fn main() { |
388 | let s = S(0, <|>); | 388 | let s = S(0, $0); |
389 | } | 389 | } |
390 | "#, | 390 | "#, |
391 | expect![[r#" | 391 | expect![[r#" |
@@ -403,7 +403,7 @@ fn generic_struct() { | |||
403 | r#" | 403 | r#" |
404 | struct S<T>(T); | 404 | struct S<T>(T); |
405 | fn main() { | 405 | fn main() { |
406 | let s = S(<|>); | 406 | let s = S($0); |
407 | } | 407 | } |
408 | "#, | 408 | "#, |
409 | expect![[r#" | 409 | expect![[r#" |
@@ -427,7 +427,7 @@ enum E { | |||
427 | } | 427 | } |
428 | 428 | ||
429 | fn main() { | 429 | fn main() { |
430 | let a = E::A(<|>); | 430 | let a = E::A($0); |
431 | } | 431 | } |
432 | "#, | 432 | "#, |
433 | expect![[r#" | 433 | expect![[r#" |
@@ -445,7 +445,7 @@ fn cant_call_struct_record() { | |||
445 | r#" | 445 | r#" |
446 | struct S { x: u32, y: i32 } | 446 | struct S { x: u32, y: i32 } |
447 | fn main() { | 447 | fn main() { |
448 | let s = S(<|>); | 448 | let s = S($0); |
449 | } | 449 | } |
450 | "#, | 450 | "#, |
451 | expect![[""]], | 451 | expect![[""]], |
@@ -466,7 +466,7 @@ enum E { | |||
466 | } | 466 | } |
467 | 467 | ||
468 | fn main() { | 468 | fn main() { |
469 | let a = E::C(<|>); | 469 | let a = E::C($0); |
470 | } | 470 | } |
471 | "#, | 471 | "#, |
472 | expect![[""]], | 472 | expect![[""]], |
@@ -480,7 +480,7 @@ fn fn_signature_for_call_in_macro() { | |||
480 | macro_rules! id { ($($tt:tt)*) => { $($tt)* } } | 480 | macro_rules! id { ($($tt:tt)*) => { $($tt)* } } |
481 | fn foo() { } | 481 | fn foo() { } |
482 | id! { | 482 | id! { |
483 | fn bar() { foo(<|>); } | 483 | fn bar() { foo($0); } |
484 | } | 484 | } |
485 | "#, | 485 | "#, |
486 | expect![[r#" | 486 | expect![[r#" |
@@ -497,7 +497,7 @@ fn call_info_for_lambdas() { | |||
497 | struct S; | 497 | struct S; |
498 | fn foo(s: S) -> i32 { 92 } | 498 | fn foo(s: S) -> i32 { 92 } |
499 | fn main() { | 499 | fn main() { |
500 | (|s| foo(s))(<|>) | 500 | (|s| foo(s))($0) |
501 | } | 501 | } |
502 | "#, | 502 | "#, |
503 | expect![[r#" | 503 | expect![[r#" |
@@ -512,7 +512,7 @@ fn call_info_for_fn_ptr() { | |||
512 | check( | 512 | check( |
513 | r#" | 513 | r#" |
514 | fn main(f: fn(i32, f64) -> char) { | 514 | fn main(f: fn(i32, f64) -> char) { |
515 | f(0, <|>) | 515 | f(0, $0) |
516 | } | 516 | } |
517 | "#, | 517 | "#, |
518 | expect![[r#" | 518 | expect![[r#" |
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs index cc5078bf0..d68fe42b0 100644 --- a/crates/ide_db/src/defs.rs +++ b/crates/ide_db/src/defs.rs | |||
@@ -6,8 +6,8 @@ | |||
6 | // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). | 6 | // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). |
7 | 7 | ||
8 | use hir::{ | 8 | use hir::{ |
9 | db::HirDatabase, ConstParam, Crate, Field, HasVisibility, Impl, Label, LifetimeParam, Local, | 9 | db::HirDatabase, Crate, Field, GenericParam, HasVisibility, Impl, Label, Local, MacroDef, |
10 | MacroDef, Module, ModuleDef, Name, PathResolution, Semantics, TypeParam, Visibility, | 10 | Module, ModuleDef, Name, PathResolution, Semantics, Visibility, |
11 | }; | 11 | }; |
12 | use syntax::{ | 12 | use syntax::{ |
13 | ast::{self, AstNode}, | 13 | ast::{self, AstNode}, |
@@ -24,9 +24,7 @@ pub enum Definition { | |||
24 | ModuleDef(ModuleDef), | 24 | ModuleDef(ModuleDef), |
25 | SelfType(Impl), | 25 | SelfType(Impl), |
26 | Local(Local), | 26 | Local(Local), |
27 | TypeParam(TypeParam), | 27 | GenericParam(GenericParam), |
28 | LifetimeParam(LifetimeParam), | ||
29 | ConstParam(ConstParam), | ||
30 | Label(Label), | 28 | Label(Label), |
31 | } | 29 | } |
32 | 30 | ||
@@ -38,9 +36,7 @@ impl Definition { | |||
38 | Definition::ModuleDef(it) => it.module(db), | 36 | Definition::ModuleDef(it) => it.module(db), |
39 | Definition::SelfType(it) => Some(it.module(db)), | 37 | Definition::SelfType(it) => Some(it.module(db)), |
40 | Definition::Local(it) => Some(it.module(db)), | 38 | Definition::Local(it) => Some(it.module(db)), |
41 | Definition::TypeParam(it) => Some(it.module(db)), | 39 | Definition::GenericParam(it) => Some(it.module(db)), |
42 | Definition::LifetimeParam(it) => Some(it.module(db)), | ||
43 | Definition::ConstParam(it) => Some(it.module(db)), | ||
44 | Definition::Label(it) => Some(it.module(db)), | 40 | Definition::Label(it) => Some(it.module(db)), |
45 | } | 41 | } |
46 | } | 42 | } |
@@ -52,9 +48,7 @@ impl Definition { | |||
52 | Definition::ModuleDef(def) => def.definition_visibility(db), | 48 | Definition::ModuleDef(def) => def.definition_visibility(db), |
53 | Definition::SelfType(_) => None, | 49 | Definition::SelfType(_) => None, |
54 | Definition::Local(_) => None, | 50 | Definition::Local(_) => None, |
55 | Definition::TypeParam(_) => None, | 51 | Definition::GenericParam(_) => None, |
56 | Definition::LifetimeParam(_) => None, | ||
57 | Definition::ConstParam(_) => None, | ||
58 | Definition::Label(_) => None, | 52 | Definition::Label(_) => None, |
59 | } | 53 | } |
60 | } | 54 | } |
@@ -80,9 +74,7 @@ impl Definition { | |||
80 | }, | 74 | }, |
81 | Definition::SelfType(_) => return None, | 75 | Definition::SelfType(_) => return None, |
82 | Definition::Local(it) => it.name(db)?, | 76 | Definition::Local(it) => it.name(db)?, |
83 | Definition::TypeParam(it) => it.name(db), | 77 | Definition::GenericParam(it) => it.name(db), |
84 | Definition::LifetimeParam(it) => it.name(db), | ||
85 | Definition::ConstParam(it) => it.name(db), | ||
86 | Definition::Label(it) => it.name(db), | 78 | Definition::Label(it) => it.name(db), |
87 | }; | 79 | }; |
88 | Some(name) | 80 | Some(name) |
@@ -235,11 +227,11 @@ impl NameClass { | |||
235 | }, | 227 | }, |
236 | ast::TypeParam(it) => { | 228 | ast::TypeParam(it) => { |
237 | let def = sema.to_def(&it)?; | 229 | let def = sema.to_def(&it)?; |
238 | Some(NameClass::Definition(Definition::TypeParam(def))) | 230 | Some(NameClass::Definition(Definition::GenericParam(def.into()))) |
239 | }, | 231 | }, |
240 | ast::ConstParam(it) => { | 232 | ast::ConstParam(it) => { |
241 | let def = sema.to_def(&it)?; | 233 | let def = sema.to_def(&it)?; |
242 | Some(NameClass::Definition(Definition::ConstParam(def))) | 234 | Some(NameClass::Definition(Definition::GenericParam(def.into()))) |
243 | }, | 235 | }, |
244 | _ => None, | 236 | _ => None, |
245 | } | 237 | } |
@@ -257,7 +249,7 @@ impl NameClass { | |||
257 | match parent { | 249 | match parent { |
258 | ast::LifetimeParam(it) => { | 250 | ast::LifetimeParam(it) => { |
259 | let def = sema.to_def(&it)?; | 251 | let def = sema.to_def(&it)?; |
260 | Some(NameClass::Definition(Definition::LifetimeParam(def))) | 252 | Some(NameClass::Definition(Definition::GenericParam(def.into()))) |
261 | }, | 253 | }, |
262 | ast::Label(it) => { | 254 | ast::Label(it) => { |
263 | let def = sema.to_def(&it)?; | 255 | let def = sema.to_def(&it)?; |
@@ -358,7 +350,7 @@ impl NameRefClass { | |||
358 | if let Some(path) = macro_call.path() { | 350 | if let Some(path) = macro_call.path() { |
359 | if path.qualifier().is_none() { | 351 | if path.qualifier().is_none() { |
360 | // Only use this to resolve single-segment macro calls like `foo!()`. Multi-segment | 352 | // Only use this to resolve single-segment macro calls like `foo!()`. Multi-segment |
361 | // paths are handled below (allowing `log<|>::info!` to resolve to the log crate). | 353 | // paths are handled below (allowing `log$0::info!` to resolve to the log crate). |
362 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { | 354 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { |
363 | return Some(NameRefClass::Definition(Definition::Macro(macro_def))); | 355 | return Some(NameRefClass::Definition(Definition::Macro(macro_def))); |
364 | } | 356 | } |
@@ -393,7 +385,8 @@ impl NameRefClass { | |||
393 | | SyntaxKind::WHERE_PRED | 385 | | SyntaxKind::WHERE_PRED |
394 | | SyntaxKind::REF_TYPE => sema | 386 | | SyntaxKind::REF_TYPE => sema |
395 | .resolve_lifetime_param(lifetime) | 387 | .resolve_lifetime_param(lifetime) |
396 | .map(Definition::LifetimeParam) | 388 | .map(GenericParam::LifetimeParam) |
389 | .map(Definition::GenericParam) | ||
397 | .map(NameRefClass::Definition), | 390 | .map(NameRefClass::Definition), |
398 | // lifetime bounds, as in the 'b in 'a: 'b aren't wrapped in TypeBound nodes so we gotta check | 391 | // lifetime bounds, as in the 'b in 'a: 'b aren't wrapped in TypeBound nodes so we gotta check |
399 | // if our lifetime is in a LifetimeParam without being the constrained lifetime | 392 | // if our lifetime is in a LifetimeParam without being the constrained lifetime |
@@ -401,7 +394,8 @@ impl NameRefClass { | |||
401 | != Some(lifetime) => | 394 | != Some(lifetime) => |
402 | { | 395 | { |
403 | sema.resolve_lifetime_param(lifetime) | 396 | sema.resolve_lifetime_param(lifetime) |
404 | .map(Definition::LifetimeParam) | 397 | .map(GenericParam::LifetimeParam) |
398 | .map(Definition::GenericParam) | ||
405 | .map(NameRefClass::Definition) | 399 | .map(NameRefClass::Definition) |
406 | } | 400 | } |
407 | _ => None, | 401 | _ => None, |
@@ -422,10 +416,10 @@ impl From<PathResolution> for Definition { | |||
422 | Definition::ModuleDef(def) | 416 | Definition::ModuleDef(def) |
423 | } | 417 | } |
424 | PathResolution::Local(local) => Definition::Local(local), | 418 | PathResolution::Local(local) => Definition::Local(local), |
425 | PathResolution::TypeParam(par) => Definition::TypeParam(par), | 419 | PathResolution::TypeParam(par) => Definition::GenericParam(par.into()), |
426 | PathResolution::Macro(def) => Definition::Macro(def), | 420 | PathResolution::Macro(def) => Definition::Macro(def), |
427 | PathResolution::SelfType(impl_def) => Definition::SelfType(impl_def), | 421 | PathResolution::SelfType(impl_def) => Definition::SelfType(impl_def), |
428 | PathResolution::ConstParam(par) => Definition::ConstParam(par), | 422 | PathResolution::ConstParam(par) => Definition::GenericParam(par.into()), |
429 | } | 423 | } |
430 | } | 424 | } |
431 | } | 425 | } |
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs index d988588ff..e3e5670f1 100644 --- a/crates/ide_db/src/helpers.rs +++ b/crates/ide_db/src/helpers.rs | |||
@@ -1,9 +1,10 @@ | |||
1 | //! A module with ide helpers for high-level ide features. | 1 | //! A module with ide helpers for high-level ide features. |
2 | use crate::RootDatabase; | 2 | pub mod insert_use; |
3 | |||
3 | use hir::{Crate, Enum, Module, ScopeDef, Semantics, Trait}; | 4 | use hir::{Crate, Enum, Module, ScopeDef, Semantics, Trait}; |
4 | use syntax::ast::{self, make}; | 5 | use syntax::ast::{self, make}; |
5 | 6 | ||
6 | pub mod insert_use; | 7 | use crate::RootDatabase; |
7 | 8 | ||
8 | /// Converts the mod path struct into its ast representation. | 9 | /// Converts the mod path struct into its ast representation. |
9 | pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path { | 10 | pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path { |
@@ -201,3 +202,18 @@ pub use prelude::*; | |||
201 | Some(def) | 202 | Some(def) |
202 | } | 203 | } |
203 | } | 204 | } |
205 | |||
206 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||
207 | pub struct SnippetCap { | ||
208 | _private: (), | ||
209 | } | ||
210 | |||
211 | impl SnippetCap { | ||
212 | pub const fn new(allow_snippets: bool) -> Option<SnippetCap> { | ||
213 | if allow_snippets { | ||
214 | Some(SnippetCap { _private: () }) | ||
215 | } else { | ||
216 | None | ||
217 | } | ||
218 | } | ||
219 | } | ||
diff --git a/crates/ide_db/src/imports_locator.rs b/crates/ide_db/src/imports_locator.rs index 0782ab070..e9f23adf8 100644 --- a/crates/ide_db/src/imports_locator.rs +++ b/crates/ide_db/src/imports_locator.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! This module contains an import search funcionality that is provided to the assists module. | 1 | //! This module contains an import search functionality that is provided to the assists module. |
2 | //! Later, this should be moved away to a separate crate that is accessible from the assists module. | 2 | //! Later, this should be moved away to a separate crate that is accessible from the assists module. |
3 | 3 | ||
4 | use hir::{import_map, AsAssocItem, Crate, MacroDef, ModuleDef, Semantics}; | 4 | use hir::{import_map, AsAssocItem, Crate, MacroDef, ModuleDef, Semantics}; |
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index 436c59d2c..b5fa46642 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs | |||
@@ -18,9 +18,43 @@ use crate::{ | |||
18 | RootDatabase, | 18 | RootDatabase, |
19 | }; | 19 | }; |
20 | 20 | ||
21 | #[derive(Debug, Default, Clone)] | ||
22 | pub struct UsageSearchResult { | ||
23 | pub references: FxHashMap<FileId, Vec<FileReference>>, | ||
24 | } | ||
25 | |||
26 | impl UsageSearchResult { | ||
27 | pub fn is_empty(&self) -> bool { | ||
28 | self.references.is_empty() | ||
29 | } | ||
30 | |||
31 | pub fn len(&self) -> usize { | ||
32 | self.references.len() | ||
33 | } | ||
34 | |||
35 | pub fn iter(&self) -> impl Iterator<Item = (&FileId, &Vec<FileReference>)> + '_ { | ||
36 | self.references.iter() | ||
37 | } | ||
38 | |||
39 | pub fn file_ranges(&self) -> impl Iterator<Item = FileRange> + '_ { | ||
40 | self.references.iter().flat_map(|(&file_id, refs)| { | ||
41 | refs.iter().map(move |&FileReference { range, .. }| FileRange { file_id, range }) | ||
42 | }) | ||
43 | } | ||
44 | } | ||
45 | |||
46 | impl IntoIterator for UsageSearchResult { | ||
47 | type Item = (FileId, Vec<FileReference>); | ||
48 | type IntoIter = <FxHashMap<FileId, Vec<FileReference>> as IntoIterator>::IntoIter; | ||
49 | |||
50 | fn into_iter(self) -> Self::IntoIter { | ||
51 | self.references.into_iter() | ||
52 | } | ||
53 | } | ||
54 | |||
21 | #[derive(Debug, Clone)] | 55 | #[derive(Debug, Clone)] |
22 | pub struct Reference { | 56 | pub struct FileReference { |
23 | pub file_range: FileRange, | 57 | pub range: TextRange, |
24 | pub kind: ReferenceKind, | 58 | pub kind: ReferenceKind, |
25 | pub access: Option<ReferenceAccess>, | 59 | pub access: Option<ReferenceAccess>, |
26 | } | 60 | } |
@@ -136,8 +170,7 @@ impl Definition { | |||
136 | return SearchScope::new(res); | 170 | return SearchScope::new(res); |
137 | } | 171 | } |
138 | 172 | ||
139 | if let Definition::LifetimeParam(param) = self { | 173 | if let Definition::GenericParam(hir::GenericParam::LifetimeParam(param)) = self { |
140 | #[allow(deprecated)] | ||
141 | let range = match param.parent(db) { | 174 | let range = match param.parent(db) { |
142 | hir::GenericDef::Function(it) => { | 175 | hir::GenericDef::Function(it) => { |
143 | it.source(db).and_then(|src| Some(src.value.syntax().text_range())) | 176 | it.source(db).and_then(|src| Some(src.value.syntax().text_range())) |
@@ -253,23 +286,23 @@ impl<'a> FindUsages<'a> { | |||
253 | 286 | ||
254 | pub fn at_least_one(self) -> bool { | 287 | pub fn at_least_one(self) -> bool { |
255 | let mut found = false; | 288 | let mut found = false; |
256 | self.search(&mut |_reference| { | 289 | self.search(&mut |_, _| { |
257 | found = true; | 290 | found = true; |
258 | true | 291 | true |
259 | }); | 292 | }); |
260 | found | 293 | found |
261 | } | 294 | } |
262 | 295 | ||
263 | pub fn all(self) -> Vec<Reference> { | 296 | pub fn all(self) -> UsageSearchResult { |
264 | let mut res = Vec::new(); | 297 | let mut res = UsageSearchResult::default(); |
265 | self.search(&mut |reference| { | 298 | self.search(&mut |file_id, reference| { |
266 | res.push(reference); | 299 | res.references.entry(file_id).or_default().push(reference); |
267 | false | 300 | false |
268 | }); | 301 | }); |
269 | res | 302 | res |
270 | } | 303 | } |
271 | 304 | ||
272 | fn search(self, sink: &mut dyn FnMut(Reference) -> bool) { | 305 | fn search(self, sink: &mut dyn FnMut(FileId, FileReference) -> bool) { |
273 | let _p = profile::span("FindUsages:search"); | 306 | let _p = profile::span("FindUsages:search"); |
274 | let sema = self.sema; | 307 | let sema = self.sema; |
275 | 308 | ||
@@ -321,16 +354,14 @@ impl<'a> FindUsages<'a> { | |||
321 | fn found_lifetime( | 354 | fn found_lifetime( |
322 | &self, | 355 | &self, |
323 | lifetime: &ast::Lifetime, | 356 | lifetime: &ast::Lifetime, |
324 | sink: &mut dyn FnMut(Reference) -> bool, | 357 | sink: &mut dyn FnMut(FileId, FileReference) -> bool, |
325 | ) -> bool { | 358 | ) -> bool { |
326 | match NameRefClass::classify_lifetime(self.sema, lifetime) { | 359 | match NameRefClass::classify_lifetime(self.sema, lifetime) { |
327 | Some(NameRefClass::Definition(def)) if &def == self.def => { | 360 | Some(NameRefClass::Definition(def)) if &def == self.def => { |
328 | let reference = Reference { | 361 | let FileRange { file_id, range } = self.sema.original_range(lifetime.syntax()); |
329 | file_range: self.sema.original_range(lifetime.syntax()), | 362 | let reference = |
330 | kind: ReferenceKind::Lifetime, | 363 | FileReference { range, kind: ReferenceKind::Lifetime, access: None }; |
331 | access: None, | 364 | sink(file_id, reference) |
332 | }; | ||
333 | sink(reference) | ||
334 | } | 365 | } |
335 | _ => false, // not a usage | 366 | _ => false, // not a usage |
336 | } | 367 | } |
@@ -339,7 +370,7 @@ impl<'a> FindUsages<'a> { | |||
339 | fn found_name_ref( | 370 | fn found_name_ref( |
340 | &self, | 371 | &self, |
341 | name_ref: &ast::NameRef, | 372 | name_ref: &ast::NameRef, |
342 | sink: &mut dyn FnMut(Reference) -> bool, | 373 | sink: &mut dyn FnMut(FileId, FileReference) -> bool, |
343 | ) -> bool { | 374 | ) -> bool { |
344 | match NameRefClass::classify(self.sema, &name_ref) { | 375 | match NameRefClass::classify(self.sema, &name_ref) { |
345 | Some(NameRefClass::Definition(def)) if &def == self.def => { | 376 | Some(NameRefClass::Definition(def)) if &def == self.def => { |
@@ -353,46 +384,50 @@ impl<'a> FindUsages<'a> { | |||
353 | ReferenceKind::Other | 384 | ReferenceKind::Other |
354 | }; | 385 | }; |
355 | 386 | ||
356 | let reference = Reference { | 387 | let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax()); |
357 | file_range: self.sema.original_range(name_ref.syntax()), | 388 | let reference = |
358 | kind, | 389 | FileReference { range, kind, access: reference_access(&def, &name_ref) }; |
359 | access: reference_access(&def, &name_ref), | 390 | sink(file_id, reference) |
360 | }; | ||
361 | sink(reference) | ||
362 | } | 391 | } |
363 | Some(NameRefClass::FieldShorthand { local_ref: local, field_ref: field }) => { | 392 | Some(NameRefClass::FieldShorthand { local_ref: local, field_ref: field }) => { |
393 | let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax()); | ||
364 | let reference = match self.def { | 394 | let reference = match self.def { |
365 | Definition::Field(_) if &field == self.def => Reference { | 395 | Definition::Field(_) if &field == self.def => FileReference { |
366 | file_range: self.sema.original_range(name_ref.syntax()), | 396 | range, |
367 | kind: ReferenceKind::FieldShorthandForField, | 397 | kind: ReferenceKind::FieldShorthandForField, |
368 | access: reference_access(&field, &name_ref), | 398 | access: reference_access(&field, &name_ref), |
369 | }, | 399 | }, |
370 | Definition::Local(l) if &local == l => Reference { | 400 | Definition::Local(l) if &local == l => FileReference { |
371 | file_range: self.sema.original_range(name_ref.syntax()), | 401 | range, |
372 | kind: ReferenceKind::FieldShorthandForLocal, | 402 | kind: ReferenceKind::FieldShorthandForLocal, |
373 | access: reference_access(&Definition::Local(local), &name_ref), | 403 | access: reference_access(&Definition::Local(local), &name_ref), |
374 | }, | 404 | }, |
375 | _ => return false, // not a usage | 405 | _ => return false, // not a usage |
376 | }; | 406 | }; |
377 | sink(reference) | 407 | sink(file_id, reference) |
378 | } | 408 | } |
379 | _ => false, // not a usage | 409 | _ => false, // not a usage |
380 | } | 410 | } |
381 | } | 411 | } |
382 | 412 | ||
383 | fn found_name(&self, name: &ast::Name, sink: &mut dyn FnMut(Reference) -> bool) -> bool { | 413 | fn found_name( |
414 | &self, | ||
415 | name: &ast::Name, | ||
416 | sink: &mut dyn FnMut(FileId, FileReference) -> bool, | ||
417 | ) -> bool { | ||
384 | match NameClass::classify(self.sema, name) { | 418 | match NameClass::classify(self.sema, name) { |
385 | Some(NameClass::PatFieldShorthand { local_def: _, field_ref }) => { | 419 | Some(NameClass::PatFieldShorthand { local_def: _, field_ref }) => { |
386 | let reference = match self.def { | 420 | if !matches!(self.def, Definition::Field(_) if &field_ref == self.def) { |
387 | Definition::Field(_) if &field_ref == self.def => Reference { | 421 | return false; |
388 | file_range: self.sema.original_range(name.syntax()), | 422 | } |
389 | kind: ReferenceKind::FieldShorthandForField, | 423 | let FileRange { file_id, range } = self.sema.original_range(name.syntax()); |
390 | // FIXME: mutable patterns should have `Write` access | 424 | let reference = FileReference { |
391 | access: Some(ReferenceAccess::Read), | 425 | range, |
392 | }, | 426 | kind: ReferenceKind::FieldShorthandForField, |
393 | _ => return false, // not a usage | 427 | // FIXME: mutable patterns should have `Write` access |
428 | access: Some(ReferenceAccess::Read), | ||
394 | }; | 429 | }; |
395 | sink(reference) | 430 | sink(file_id, reference) |
396 | } | 431 | } |
397 | _ => false, // not a usage | 432 | _ => false, // not a usage |
398 | } | 433 | } |
diff --git a/crates/ide_db/src/traits/tests.rs b/crates/ide_db/src/traits/tests.rs index 09c7ac3ec..84bb25505 100644 --- a/crates/ide_db/src/traits/tests.rs +++ b/crates/ide_db/src/traits/tests.rs | |||
@@ -5,12 +5,12 @@ use hir::Semantics; | |||
5 | use syntax::ast::{self, AstNode}; | 5 | use syntax::ast::{self, AstNode}; |
6 | use test_utils::RangeOrOffset; | 6 | use test_utils::RangeOrOffset; |
7 | 7 | ||
8 | /// Creates analysis from a multi-file fixture, returns positions marked with <|>. | 8 | /// Creates analysis from a multi-file fixture, returns positions marked with $0. |
9 | pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) { | 9 | pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) { |
10 | let change_fixture = ChangeFixture::parse(ra_fixture); | 10 | let change_fixture = ChangeFixture::parse(ra_fixture); |
11 | let mut database = RootDatabase::default(); | 11 | let mut database = RootDatabase::default(); |
12 | database.apply_change(change_fixture.change); | 12 | database.apply_change(change_fixture.change); |
13 | let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker (<|>)"); | 13 | let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker ($0)"); |
14 | let offset = match range_or_offset { | 14 | let offset = match range_or_offset { |
15 | RangeOrOffset::Range(_) => panic!(), | 15 | RangeOrOffset::Range(_) => panic!(), |
16 | RangeOrOffset::Offset(it) => it, | 16 | RangeOrOffset::Offset(it) => it, |
@@ -55,7 +55,7 @@ pub trait Foo { | |||
55 | fn bar(); | 55 | fn bar(); |
56 | } | 56 | } |
57 | impl Foo for u8 { | 57 | impl Foo for u8 { |
58 | <|> | 58 | $0 |
59 | } | 59 | } |
60 | "#, | 60 | "#, |
61 | expect![["Foo"]], | 61 | expect![["Foo"]], |
@@ -68,7 +68,7 @@ pub trait Foo { | |||
68 | impl Foo for u8 { | 68 | impl Foo for u8 { |
69 | fn bar() { | 69 | fn bar() { |
70 | fn baz() { | 70 | fn baz() { |
71 | <|> | 71 | $0 |
72 | } | 72 | } |
73 | baz(); | 73 | baz(); |
74 | } | 74 | } |
@@ -83,7 +83,7 @@ pub trait Foo { | |||
83 | } | 83 | } |
84 | pub struct Bar; | 84 | pub struct Bar; |
85 | impl Bar { | 85 | impl Bar { |
86 | <|> | 86 | $0 |
87 | } | 87 | } |
88 | "#, | 88 | "#, |
89 | expect![[""]], | 89 | expect![[""]], |
@@ -99,7 +99,7 @@ pub trait Foo { | |||
99 | fn bar(); | 99 | fn bar(); |
100 | } | 100 | } |
101 | impl Foo for u8 { | 101 | impl Foo for u8 { |
102 | <|> | 102 | $0 |
103 | }"#, | 103 | }"#, |
104 | expect![[r#" | 104 | expect![[r#" |
105 | FOO | 105 | FOO |
@@ -114,7 +114,7 @@ pub trait Foo { | |||
114 | } | 114 | } |
115 | impl Foo for u8 { | 115 | impl Foo for u8 { |
116 | const FOO: u8 = 10; | 116 | const FOO: u8 = 10; |
117 | <|> | 117 | $0 |
118 | }"#, | 118 | }"#, |
119 | expect![[r#" | 119 | expect![[r#" |
120 | bar"#]], | 120 | bar"#]], |
@@ -128,7 +128,7 @@ pub trait Foo { | |||
128 | } | 128 | } |
129 | impl Foo for u8 { | 129 | impl Foo for u8 { |
130 | const FOO: u8 = 10; | 130 | const FOO: u8 = 10; |
131 | fn bar() {<|>} | 131 | fn bar() {$0} |
132 | }"#, | 132 | }"#, |
133 | expect![[r#""#]], | 133 | expect![[r#""#]], |
134 | ); | 134 | ); |
@@ -137,7 +137,7 @@ impl Foo for u8 { | |||
137 | r#" | 137 | r#" |
138 | pub struct Foo; | 138 | pub struct Foo; |
139 | impl Foo { | 139 | impl Foo { |
140 | fn bar() {<|>} | 140 | fn bar() {$0} |
141 | }"#, | 141 | }"#, |
142 | expect![[r#""#]], | 142 | expect![[r#""#]], |
143 | ); | 143 | ); |
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs index b3472879d..19543d777 100644 --- a/crates/mbe/src/lib.rs +++ b/crates/mbe/src/lib.rs | |||
@@ -24,7 +24,7 @@ use crate::{ | |||
24 | #[derive(Debug, PartialEq, Eq)] | 24 | #[derive(Debug, PartialEq, Eq)] |
25 | pub enum ParseError { | 25 | pub enum ParseError { |
26 | Expected(String), | 26 | Expected(String), |
27 | RepetitionEmtpyTokenTree, | 27 | RepetitionEmptyTokenTree, |
28 | } | 28 | } |
29 | 29 | ||
30 | #[derive(Debug, PartialEq, Eq, Clone)] | 30 | #[derive(Debug, PartialEq, Eq, Clone)] |
@@ -270,7 +270,7 @@ fn validate(pattern: &MetaTemplate) -> Result<(), ParseError> { | |||
270 | } | 270 | } |
271 | false | 271 | false |
272 | }) { | 272 | }) { |
273 | return Err(ParseError::RepetitionEmtpyTokenTree); | 273 | return Err(ParseError::RepetitionEmptyTokenTree); |
274 | } | 274 | } |
275 | } | 275 | } |
276 | validate(subtree)? | 276 | validate(subtree)? |
diff --git a/crates/mbe/src/mbe_expander/matcher.rs b/crates/mbe/src/mbe_expander/matcher.rs index fdc8844ce..d32e60521 100644 --- a/crates/mbe/src/mbe_expander/matcher.rs +++ b/crates/mbe/src/mbe_expander/matcher.rs | |||
@@ -150,7 +150,7 @@ fn match_subtree( | |||
150 | res.add_err(err!("leftover tokens")); | 150 | res.add_err(err!("leftover tokens")); |
151 | } | 151 | } |
152 | } | 152 | } |
153 | Op::Var { name, kind } => { | 153 | Op::Var { name, kind, .. } => { |
154 | let kind = match kind { | 154 | let kind = match kind { |
155 | Some(k) => k, | 155 | Some(k) => k, |
156 | None => { | 156 | None => { |
@@ -378,7 +378,7 @@ pub(super) fn match_repeat( | |||
378 | src: &mut TtIter, | 378 | src: &mut TtIter, |
379 | ) -> Result<(), ExpandError> { | 379 | ) -> Result<(), ExpandError> { |
380 | // Dirty hack to make macro-expansion terminate. | 380 | // Dirty hack to make macro-expansion terminate. |
381 | // This should be replaced by a propper macro-by-example implementation | 381 | // This should be replaced by a proper macro-by-example implementation |
382 | let mut limit = 65536; | 382 | let mut limit = 65536; |
383 | let mut counter = 0; | 383 | let mut counter = 0; |
384 | 384 | ||
diff --git a/crates/mbe/src/mbe_expander/transcriber.rs b/crates/mbe/src/mbe_expander/transcriber.rs index 720531237..59a3c80a8 100644 --- a/crates/mbe/src/mbe_expander/transcriber.rs +++ b/crates/mbe/src/mbe_expander/transcriber.rs | |||
@@ -67,7 +67,7 @@ struct NestingState { | |||
67 | /// because there is no variable in use by the current repetition | 67 | /// because there is no variable in use by the current repetition |
68 | hit: bool, | 68 | hit: bool, |
69 | /// `at_end` is currently necessary to tell `expand_repeat` if it should stop | 69 | /// `at_end` is currently necessary to tell `expand_repeat` if it should stop |
70 | /// because there is no more value avaible for the current repetition | 70 | /// because there is no more value available for the current repetition |
71 | at_end: bool, | 71 | at_end: bool, |
72 | } | 72 | } |
73 | 73 | ||
@@ -100,8 +100,8 @@ fn expand_subtree( | |||
100 | err = err.or(e); | 100 | err = err.or(e); |
101 | arena.push(tt.into()); | 101 | arena.push(tt.into()); |
102 | } | 102 | } |
103 | Op::Var { name, .. } => { | 103 | Op::Var { name, id, .. } => { |
104 | let ExpandResult { value: fragment, err: e } = expand_var(ctx, &name); | 104 | let ExpandResult { value: fragment, err: e } = expand_var(ctx, &name, *id); |
105 | err = err.or(e); | 105 | err = err.or(e); |
106 | push_fragment(arena, fragment); | 106 | push_fragment(arena, fragment); |
107 | } | 107 | } |
@@ -118,14 +118,11 @@ fn expand_subtree( | |||
118 | ExpandResult { value: tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err } | 118 | ExpandResult { value: tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err } |
119 | } | 119 | } |
120 | 120 | ||
121 | fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> { | 121 | fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr, id: tt::TokenId) -> ExpandResult<Fragment> { |
122 | if v == "crate" { | 122 | // We already handle $crate case in mbe parser |
123 | // We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path. | 123 | debug_assert!(v != "crate"); |
124 | let tt = | 124 | |
125 | tt::Leaf::from(tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() }) | 125 | if !ctx.bindings.contains(v) { |
126 | .into(); | ||
127 | ExpandResult::ok(Fragment::Tokens(tt)) | ||
128 | } else if !ctx.bindings.contains(v) { | ||
129 | // Note that it is possible to have a `$var` inside a macro which is not bound. | 126 | // Note that it is possible to have a `$var` inside a macro which is not bound. |
130 | // For example: | 127 | // For example: |
131 | // ``` | 128 | // ``` |
@@ -142,14 +139,8 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> { | |||
142 | let tt = tt::Subtree { | 139 | let tt = tt::Subtree { |
143 | delimiter: None, | 140 | delimiter: None, |
144 | token_trees: vec![ | 141 | token_trees: vec![ |
145 | tt::Leaf::from(tt::Punct { | 142 | tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, id }).into(), |
146 | char: '$', | 143 | tt::Leaf::from(tt::Ident { text: v.clone(), id }).into(), |
147 | spacing: tt::Spacing::Alone, | ||
148 | id: tt::TokenId::unspecified(), | ||
149 | }) | ||
150 | .into(), | ||
151 | tt::Leaf::from(tt::Ident { text: v.clone(), id: tt::TokenId::unspecified() }) | ||
152 | .into(), | ||
153 | ], | 144 | ], |
154 | } | 145 | } |
155 | .into(); | 146 | .into(); |
@@ -188,11 +179,7 @@ fn expand_repeat( | |||
188 | 179 | ||
189 | counter += 1; | 180 | counter += 1; |
190 | if counter == limit { | 181 | if counter == limit { |
191 | log::warn!( | 182 | log::warn!("expand_tt in repeat pattern exceed limit => {:#?}\n{:#?}", template, ctx); |
192 | "expand_tt excced in repeat pattern exceed limit => {:#?}\n{:#?}", | ||
193 | template, | ||
194 | ctx | ||
195 | ); | ||
196 | break; | 183 | break; |
197 | } | 184 | } |
198 | 185 | ||
diff --git a/crates/mbe/src/parser.rs b/crates/mbe/src/parser.rs index 2f3ebc831..f3047972d 100644 --- a/crates/mbe/src/parser.rs +++ b/crates/mbe/src/parser.rs | |||
@@ -8,7 +8,7 @@ use crate::{tt_iter::TtIter, ExpandError, MetaTemplate}; | |||
8 | 8 | ||
9 | #[derive(Clone, Debug, PartialEq, Eq)] | 9 | #[derive(Clone, Debug, PartialEq, Eq)] |
10 | pub(crate) enum Op { | 10 | pub(crate) enum Op { |
11 | Var { name: SmolStr, kind: Option<SmolStr> }, | 11 | Var { name: SmolStr, kind: Option<SmolStr>, id: tt::TokenId }, |
12 | Repeat { subtree: MetaTemplate, kind: RepeatKind, separator: Option<Separator> }, | 12 | Repeat { subtree: MetaTemplate, kind: RepeatKind, separator: Option<Separator> }, |
13 | Leaf(tt::Leaf), | 13 | Leaf(tt::Leaf), |
14 | Subtree(MetaTemplate), | 14 | Subtree(MetaTemplate), |
@@ -106,18 +106,25 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul | |||
106 | } | 106 | } |
107 | let name = UNDERSCORE.clone(); | 107 | let name = UNDERSCORE.clone(); |
108 | let kind = eat_fragment_kind(src, mode)?; | 108 | let kind = eat_fragment_kind(src, mode)?; |
109 | Op::Var { name, kind } | 109 | let id = punct.id; |
110 | Op::Var { name, kind, id } | ||
111 | } | ||
112 | tt::Leaf::Ident(ident) if ident.text == "crate" => { | ||
113 | // We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path. | ||
114 | Op::Leaf(tt::Leaf::from(tt::Ident { text: "$crate".into(), id: ident.id })) | ||
110 | } | 115 | } |
111 | tt::Leaf::Ident(ident) => { | 116 | tt::Leaf::Ident(ident) => { |
112 | let name = ident.text.clone(); | 117 | let name = ident.text.clone(); |
113 | let kind = eat_fragment_kind(src, mode)?; | 118 | let kind = eat_fragment_kind(src, mode)?; |
114 | Op::Var { name, kind } | 119 | let id = ident.id; |
120 | Op::Var { name, kind, id } | ||
115 | } | 121 | } |
116 | tt::Leaf::Literal(lit) => { | 122 | tt::Leaf::Literal(lit) => { |
117 | if is_boolean_literal(&lit) { | 123 | if is_boolean_literal(&lit) { |
118 | let name = lit.text.clone(); | 124 | let name = lit.text.clone(); |
119 | let kind = eat_fragment_kind(src, mode)?; | 125 | let kind = eat_fragment_kind(src, mode)?; |
120 | Op::Var { name, kind } | 126 | let id = lit.id; |
127 | Op::Var { name, kind, id } | ||
121 | } else { | 128 | } else { |
122 | bail!("bad var 2"); | 129 | bail!("bad var 2"); |
123 | } | 130 | } |
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs index 671036e1c..e648519f9 100644 --- a/crates/mbe/src/syntax_bridge.rs +++ b/crates/mbe/src/syntax_bridge.rs | |||
@@ -149,7 +149,7 @@ impl TokenMap { | |||
149 | } | 149 | } |
150 | 150 | ||
151 | fn remove_delim(&mut self, idx: usize) { | 151 | fn remove_delim(&mut self, idx: usize) { |
152 | // FIXME: This could be accidently quadratic | 152 | // FIXME: This could be accidentally quadratic |
153 | self.entries.remove(idx); | 153 | self.entries.remove(idx); |
154 | } | 154 | } |
155 | } | 155 | } |
@@ -476,14 +476,14 @@ impl Convertor { | |||
476 | 476 | ||
477 | #[derive(Debug)] | 477 | #[derive(Debug)] |
478 | enum SynToken { | 478 | enum SynToken { |
479 | Ordiniary(SyntaxToken), | 479 | Ordinary(SyntaxToken), |
480 | Punch(SyntaxToken, TextSize), | 480 | Punch(SyntaxToken, TextSize), |
481 | } | 481 | } |
482 | 482 | ||
483 | impl SynToken { | 483 | impl SynToken { |
484 | fn token(&self) -> &SyntaxToken { | 484 | fn token(&self) -> &SyntaxToken { |
485 | match self { | 485 | match self { |
486 | SynToken::Ordiniary(it) => it, | 486 | SynToken::Ordinary(it) => it, |
487 | SynToken::Punch(it, _) => it, | 487 | SynToken::Punch(it, _) => it, |
488 | } | 488 | } |
489 | } | 489 | } |
@@ -495,7 +495,7 @@ impl SrcToken for SynToken { | |||
495 | } | 495 | } |
496 | fn to_char(&self) -> Option<char> { | 496 | fn to_char(&self) -> Option<char> { |
497 | match self { | 497 | match self { |
498 | SynToken::Ordiniary(_) => None, | 498 | SynToken::Ordinary(_) => None, |
499 | SynToken::Punch(it, i) => it.text().chars().nth((*i).into()), | 499 | SynToken::Punch(it, i) => it.text().chars().nth((*i).into()), |
500 | } | 500 | } |
501 | } | 501 | } |
@@ -535,7 +535,7 @@ impl TokenConvertor for Convertor { | |||
535 | } else { | 535 | } else { |
536 | self.punct_offset = None; | 536 | self.punct_offset = None; |
537 | let range = curr.text_range(); | 537 | let range = curr.text_range(); |
538 | (SynToken::Ordiniary(curr), range) | 538 | (SynToken::Ordinary(curr), range) |
539 | }; | 539 | }; |
540 | 540 | ||
541 | Some(token) | 541 | Some(token) |
@@ -557,7 +557,7 @@ impl TokenConvertor for Convertor { | |||
557 | let token = if curr.kind().is_punct() { | 557 | let token = if curr.kind().is_punct() { |
558 | SynToken::Punch(curr, 0.into()) | 558 | SynToken::Punch(curr, 0.into()) |
559 | } else { | 559 | } else { |
560 | SynToken::Ordiniary(curr) | 560 | SynToken::Ordinary(curr) |
561 | }; | 561 | }; |
562 | Some(token) | 562 | Some(token) |
563 | } | 563 | } |
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs index 1d9afb4fb..ecea15c11 100644 --- a/crates/mbe/src/tests.rs +++ b/crates/mbe/src/tests.rs | |||
@@ -1080,6 +1080,19 @@ fn test_vertical_bar_with_pat() { | |||
1080 | } | 1080 | } |
1081 | 1081 | ||
1082 | #[test] | 1082 | #[test] |
1083 | fn test_dollar_crate_lhs_is_not_meta() { | ||
1084 | parse_macro( | ||
1085 | r#" | ||
1086 | macro_rules! foo { | ||
1087 | ($crate) => {}; | ||
1088 | () => {0}; | ||
1089 | } | ||
1090 | "#, | ||
1091 | ) | ||
1092 | .assert_expand_items(r#"foo!{}"#, r#"0"#); | ||
1093 | } | ||
1094 | |||
1095 | #[test] | ||
1083 | fn test_lifetime() { | 1096 | fn test_lifetime() { |
1084 | parse_macro( | 1097 | parse_macro( |
1085 | r#" | 1098 | r#" |
@@ -1954,7 +1967,7 @@ fn test_no_space_after_semi_colon() { | |||
1954 | #[test] | 1967 | #[test] |
1955 | fn test_rustc_issue_57597() { | 1968 | fn test_rustc_issue_57597() { |
1956 | fn test_error(fixture: &str) { | 1969 | fn test_error(fixture: &str) { |
1957 | assert_eq!(parse_macro_error(fixture), ParseError::RepetitionEmtpyTokenTree); | 1970 | assert_eq!(parse_macro_error(fixture), ParseError::RepetitionEmptyTokenTree); |
1958 | } | 1971 | } |
1959 | 1972 | ||
1960 | test_error("macro_rules! foo { ($($($i:ident)?)+) => {}; }"); | 1973 | test_error("macro_rules! foo { ($($($i:ident)?)+) => {}; }"); |
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs index c7a3556a7..d61950b96 100644 --- a/crates/parser/src/grammar/expressions/atom.rs +++ b/crates/parser/src/grammar/expressions/atom.rs | |||
@@ -15,8 +15,16 @@ use super::*; | |||
15 | // let _ = b"e"; | 15 | // let _ = b"e"; |
16 | // let _ = br"f"; | 16 | // let _ = br"f"; |
17 | // } | 17 | // } |
18 | pub(crate) const LITERAL_FIRST: TokenSet = | 18 | pub(crate) const LITERAL_FIRST: TokenSet = TokenSet::new(&[ |
19 | TokenSet::new(&[TRUE_KW, FALSE_KW, INT_NUMBER, FLOAT_NUMBER, BYTE, CHAR, STRING, BYTE_STRING]); | 19 | T![true], |
20 | T![false], | ||
21 | INT_NUMBER, | ||
22 | FLOAT_NUMBER, | ||
23 | BYTE, | ||
24 | CHAR, | ||
25 | STRING, | ||
26 | BYTE_STRING, | ||
27 | ]); | ||
20 | 28 | ||
21 | pub(crate) fn literal(p: &mut Parser) -> Option<CompletedMarker> { | 29 | pub(crate) fn literal(p: &mut Parser) -> Option<CompletedMarker> { |
22 | if !p.at_ts(LITERAL_FIRST) { | 30 | if !p.at_ts(LITERAL_FIRST) { |
diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs index cf4168d32..2070ce163 100644 --- a/crates/parser/src/grammar/items.rs +++ b/crates/parser/src/grammar/items.rs | |||
@@ -27,19 +27,19 @@ pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) { | |||
27 | } | 27 | } |
28 | 28 | ||
29 | pub(super) const ITEM_RECOVERY_SET: TokenSet = TokenSet::new(&[ | 29 | pub(super) const ITEM_RECOVERY_SET: TokenSet = TokenSet::new(&[ |
30 | FN_KW, | 30 | T![fn], |
31 | STRUCT_KW, | 31 | T![struct], |
32 | ENUM_KW, | 32 | T![enum], |
33 | IMPL_KW, | 33 | T![impl], |
34 | TRAIT_KW, | 34 | T![trait], |
35 | CONST_KW, | 35 | T![const], |
36 | STATIC_KW, | 36 | T![static], |
37 | LET_KW, | 37 | T![let], |
38 | MOD_KW, | 38 | T![mod], |
39 | PUB_KW, | 39 | T![pub], |
40 | CRATE_KW, | 40 | T![crate], |
41 | USE_KW, | 41 | T![use], |
42 | MACRO_KW, | 42 | T![macro], |
43 | T![;], | 43 | T![;], |
44 | ]); | 44 | ]); |
45 | 45 | ||
diff --git a/crates/parser/src/grammar/items/traits.rs b/crates/parser/src/grammar/items/traits.rs index ab9a12b4d..d076974ed 100644 --- a/crates/parser/src/grammar/items/traits.rs +++ b/crates/parser/src/grammar/items/traits.rs | |||
@@ -110,7 +110,7 @@ fn choose_type_params_over_qpath(p: &Parser) -> bool { | |||
110 | if !p.at(T![<]) { | 110 | if !p.at(T![<]) { |
111 | return false; | 111 | return false; |
112 | } | 112 | } |
113 | if p.nth(1) == T![#] || p.nth(1) == T![>] || p.nth(1) == CONST_KW { | 113 | if p.nth(1) == T![#] || p.nth(1) == T![>] || p.nth(1) == T![const] { |
114 | return true; | 114 | return true; |
115 | } | 115 | } |
116 | (p.nth(1) == LIFETIME_IDENT || p.nth(1) == IDENT) | 116 | (p.nth(1) == LIFETIME_IDENT || p.nth(1) == IDENT) |
diff --git a/crates/parser/src/grammar/items/use_item.rs b/crates/parser/src/grammar/items/use_item.rs index 20e6a13cf..5cb8b08e7 100644 --- a/crates/parser/src/grammar/items/use_item.rs +++ b/crates/parser/src/grammar/items/use_item.rs | |||
@@ -46,7 +46,7 @@ fn use_tree(p: &mut Parser, top_level: bool) { | |||
46 | // test use_tree_list | 46 | // test use_tree_list |
47 | // use {crate::path::from::root, or::path::from::crate_name}; // Rust 2018 (with a crate named `or`) | 47 | // use {crate::path::from::root, or::path::from::crate_name}; // Rust 2018 (with a crate named `or`) |
48 | // use {path::from::root}; // Rust 2015 | 48 | // use {path::from::root}; // Rust 2015 |
49 | // use ::{some::arbritrary::path}; // Rust 2015 | 49 | // use ::{some::arbitrary::path}; // Rust 2015 |
50 | // use ::{{{root::export}}}; // Nonsensical but perfectly legal nesting | 50 | // use ::{{{root::export}}}; // Nonsensical but perfectly legal nesting |
51 | T!['{'] => { | 51 | T!['{'] => { |
52 | use_tree_list(p); | 52 | use_tree_list(p); |
diff --git a/crates/parser/src/grammar/patterns.rs b/crates/parser/src/grammar/patterns.rs index b53d5749f..da71498a8 100644 --- a/crates/parser/src/grammar/patterns.rs +++ b/crates/parser/src/grammar/patterns.rs | |||
@@ -83,7 +83,7 @@ fn pattern_single_r(p: &mut Parser, recovery_set: TokenSet) { | |||
83 | } | 83 | } |
84 | 84 | ||
85 | const PAT_RECOVERY_SET: TokenSet = | 85 | const PAT_RECOVERY_SET: TokenSet = |
86 | TokenSet::new(&[LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA]); | 86 | TokenSet::new(&[T![let], T![if], T![while], T![loop], T![match], T![')'], T![,]]); |
87 | 87 | ||
88 | fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> { | 88 | fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> { |
89 | let m = match p.nth(0) { | 89 | let m = match p.nth(0) { |
diff --git a/crates/parser/src/grammar/type_args.rs b/crates/parser/src/grammar/type_args.rs index a013c49b9..42cd426bd 100644 --- a/crates/parser/src/grammar/type_args.rs +++ b/crates/parser/src/grammar/type_args.rs | |||
@@ -26,7 +26,7 @@ pub(super) fn opt_generic_arg_list(p: &mut Parser, colon_colon_required: bool) { | |||
26 | } | 26 | } |
27 | 27 | ||
28 | // test type_arg | 28 | // test type_arg |
29 | // type A = B<'static, i32, 1, { 2 }, Item=u64>; | 29 | // type A = B<'static, i32, 1, { 2 }, Item=u64, true, false>; |
30 | fn generic_arg(p: &mut Parser) { | 30 | fn generic_arg(p: &mut Parser) { |
31 | let m = p.start(); | 31 | let m = p.start(); |
32 | match p.current() { | 32 | match p.current() { |
@@ -55,6 +55,10 @@ fn generic_arg(p: &mut Parser) { | |||
55 | expressions::literal(p); | 55 | expressions::literal(p); |
56 | m.complete(p, CONST_ARG); | 56 | m.complete(p, CONST_ARG); |
57 | } | 57 | } |
58 | T![true] | T![false] => { | ||
59 | expressions::literal(p); | ||
60 | m.complete(p, CONST_ARG); | ||
61 | } | ||
58 | _ => { | 62 | _ => { |
59 | types::type_(p); | 63 | types::type_(p); |
60 | m.complete(p, TYPE_ARG); | 64 | m.complete(p, TYPE_ARG); |
diff --git a/crates/parser/src/grammar/type_params.rs b/crates/parser/src/grammar/type_params.rs index 4aeccd193..3de5248da 100644 --- a/crates/parser/src/grammar/type_params.rs +++ b/crates/parser/src/grammar/type_params.rs | |||
@@ -25,7 +25,7 @@ fn generic_param_list(p: &mut Parser) { | |||
25 | match p.current() { | 25 | match p.current() { |
26 | LIFETIME_IDENT => lifetime_param(p, m), | 26 | LIFETIME_IDENT => lifetime_param(p, m), |
27 | IDENT => type_param(p, m), | 27 | IDENT => type_param(p, m), |
28 | CONST_KW => const_param(p, m), | 28 | T![const] => const_param(p, m), |
29 | _ => { | 29 | _ => { |
30 | m.abandon(p); | 30 | m.abandon(p); |
31 | p.err_and_bump("expected type parameter") | 31 | p.err_and_bump("expected type parameter") |
@@ -66,7 +66,7 @@ fn type_param(p: &mut Parser, m: Marker) { | |||
66 | // test const_param | 66 | // test const_param |
67 | // struct S<const N: u32>; | 67 | // struct S<const N: u32>; |
68 | fn const_param(p: &mut Parser, m: Marker) { | 68 | fn const_param(p: &mut Parser, m: Marker) { |
69 | assert!(p.at(CONST_KW)); | 69 | assert!(p.at(T![const])); |
70 | p.bump(T![const]); | 70 | p.bump(T![const]); |
71 | name(p); | 71 | name(p); |
72 | types::ascription(p); | 72 | types::ascription(p); |
diff --git a/crates/proc_macro_api/src/msg.rs b/crates/proc_macro_api/src/msg.rs index 4cd572101..970f165ed 100644 --- a/crates/proc_macro_api/src/msg.rs +++ b/crates/proc_macro_api/src/msg.rs | |||
@@ -79,7 +79,7 @@ impl Message for Response {} | |||
79 | fn read_json(inp: &mut impl BufRead) -> io::Result<Option<String>> { | 79 | fn read_json(inp: &mut impl BufRead) -> io::Result<Option<String>> { |
80 | let mut buf = String::new(); | 80 | let mut buf = String::new(); |
81 | inp.read_line(&mut buf)?; | 81 | inp.read_line(&mut buf)?; |
82 | buf.pop(); // Remove traling '\n' | 82 | buf.pop(); // Remove trailing '\n' |
83 | Ok(match buf.len() { | 83 | Ok(match buf.len() { |
84 | 0 => None, | 84 | 0 => None, |
85 | _ => Some(buf), | 85 | _ => Some(buf), |
diff --git a/crates/proc_macro_srv/Cargo.toml b/crates/proc_macro_srv/Cargo.toml index df9a55c10..83f9ead17 100644 --- a/crates/proc_macro_srv/Cargo.toml +++ b/crates/proc_macro_srv/Cargo.toml | |||
@@ -20,8 +20,7 @@ proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" } | |||
20 | test_utils = { path = "../test_utils", version = "0.0.0" } | 20 | test_utils = { path = "../test_utils", version = "0.0.0" } |
21 | 21 | ||
22 | [dev-dependencies] | 22 | [dev-dependencies] |
23 | cargo_metadata = "=0.12.0" | 23 | cargo_metadata = "0.12.2" |
24 | difference = "2.0.0" | ||
25 | 24 | ||
26 | # used as proc macro test targets | 25 | # used as proc macro test targets |
27 | serde_derive = "1.0.106" | 26 | serde_derive = "1.0.106" |
diff --git a/crates/proc_macro_srv/src/proc_macro/bridge/rpc.rs b/crates/proc_macro_srv/src/proc_macro/bridge/rpc.rs index 3528d5c99..bd1e7c2fc 100644 --- a/crates/proc_macro_srv/src/proc_macro/bridge/rpc.rs +++ b/crates/proc_macro_srv/src/proc_macro/bridge/rpc.rs | |||
@@ -251,7 +251,7 @@ impl<S> DecodeMut<'_, '_, S> for String { | |||
251 | } | 251 | } |
252 | } | 252 | } |
253 | 253 | ||
254 | /// Simplied version of panic payloads, ignoring | 254 | /// Simplified version of panic payloads, ignoring |
255 | /// types other than `&'static str` and `String`. | 255 | /// types other than `&'static str` and `String`. |
256 | #[derive(Debug)] | 256 | #[derive(Debug)] |
257 | pub enum PanicMessage { | 257 | pub enum PanicMessage { |
diff --git a/crates/proc_macro_srv/src/rustc_server.rs b/crates/proc_macro_srv/src/rustc_server.rs index b54aa1f3b..e6006a3c8 100644 --- a/crates/proc_macro_srv/src/rustc_server.rs +++ b/crates/proc_macro_srv/src/rustc_server.rs | |||
@@ -4,7 +4,7 @@ | |||
4 | //! The lib-proc-macro server backend is `TokenStream`-agnostic, such that | 4 | //! The lib-proc-macro server backend is `TokenStream`-agnostic, such that |
5 | //! we could provide any TokenStream implementation. | 5 | //! we could provide any TokenStream implementation. |
6 | //! The original idea from fedochet is using proc-macro2 as backend, | 6 | //! The original idea from fedochet is using proc-macro2 as backend, |
7 | //! we use tt instead for better intergation with RA. | 7 | //! we use tt instead for better integration with RA. |
8 | //! | 8 | //! |
9 | //! FIXME: No span and source file information is implemented yet | 9 | //! FIXME: No span and source file information is implemented yet |
10 | 10 | ||
diff --git a/crates/profile/src/stop_watch.rs b/crates/profile/src/stop_watch.rs index 5e276190e..cb6915d45 100644 --- a/crates/profile/src/stop_watch.rs +++ b/crates/profile/src/stop_watch.rs | |||
@@ -76,7 +76,11 @@ impl fmt::Display for StopWatchSpan { | |||
76 | instructions /= 1000; | 76 | instructions /= 1000; |
77 | prefix = "m" | 77 | prefix = "m" |
78 | } | 78 | } |
79 | write!(f, ", {}{}i", instructions, prefix)?; | 79 | if instructions > 10000 { |
80 | instructions /= 1000; | ||
81 | prefix = "g" | ||
82 | } | ||
83 | write!(f, ", {}{}instr", instructions, prefix)?; | ||
80 | } | 84 | } |
81 | if let Some(memory) = self.memory { | 85 | if let Some(memory) = self.memory { |
82 | write!(f, ", {}", memory)?; | 86 | write!(f, ", {}", memory)?; |
diff --git a/crates/project_model/Cargo.toml b/crates/project_model/Cargo.toml index a65e42261..855fb83ea 100644 --- a/crates/project_model/Cargo.toml +++ b/crates/project_model/Cargo.toml | |||
@@ -12,7 +12,7 @@ doctest = false | |||
12 | [dependencies] | 12 | [dependencies] |
13 | log = "0.4.8" | 13 | log = "0.4.8" |
14 | rustc-hash = "1.1.0" | 14 | rustc-hash = "1.1.0" |
15 | cargo_metadata = "=0.12.0" | 15 | cargo_metadata = "0.12.2" |
16 | serde = { version = "1.0.106", features = ["derive"] } | 16 | serde = { version = "1.0.106", features = ["derive"] } |
17 | serde_json = "1.0.48" | 17 | serde_json = "1.0.48" |
18 | anyhow = "1.0.26" | 18 | anyhow = "1.0.26" |
diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs index 1700cb8a7..2ee4e88b2 100644 --- a/crates/project_model/src/cargo_workspace.rs +++ b/crates/project_model/src/cargo_workspace.rs | |||
@@ -3,9 +3,10 @@ | |||
3 | use std::{ | 3 | use std::{ |
4 | convert::TryInto, | 4 | convert::TryInto, |
5 | ffi::OsStr, | 5 | ffi::OsStr, |
6 | io::BufReader, | ||
6 | ops, | 7 | ops, |
7 | path::{Path, PathBuf}, | 8 | path::{Path, PathBuf}, |
8 | process::Command, | 9 | process::{Command, Stdio}, |
9 | }; | 10 | }; |
10 | 11 | ||
11 | use anyhow::{Context, Result}; | 12 | use anyhow::{Context, Result}; |
@@ -15,6 +16,7 @@ use cargo_metadata::{BuildScript, CargoOpt, Message, MetadataCommand, PackageId} | |||
15 | use itertools::Itertools; | 16 | use itertools::Itertools; |
16 | use paths::{AbsPath, AbsPathBuf}; | 17 | use paths::{AbsPath, AbsPathBuf}; |
17 | use rustc_hash::FxHashMap; | 18 | use rustc_hash::FxHashMap; |
19 | use stdx::JodChild; | ||
18 | 20 | ||
19 | use crate::cfg_flag::CfgFlag; | 21 | use crate::cfg_flag::CfgFlag; |
20 | use crate::utf8_stdout; | 22 | use crate::utf8_stdout; |
@@ -80,19 +82,35 @@ pub type Package = Idx<PackageData>; | |||
80 | 82 | ||
81 | pub type Target = Idx<TargetData>; | 83 | pub type Target = Idx<TargetData>; |
82 | 84 | ||
85 | /// Information associated with a cargo crate | ||
83 | #[derive(Debug, Clone, Eq, PartialEq)] | 86 | #[derive(Debug, Clone, Eq, PartialEq)] |
84 | pub struct PackageData { | 87 | pub struct PackageData { |
88 | /// Version given in the `Cargo.toml` | ||
85 | pub version: String, | 89 | pub version: String, |
90 | /// Name as given in the `Cargo.toml` | ||
86 | pub name: String, | 91 | pub name: String, |
92 | /// Path containing the `Cargo.toml` | ||
87 | pub manifest: AbsPathBuf, | 93 | pub manifest: AbsPathBuf, |
94 | /// Targets provided by the crate (lib, bin, example, test, ...) | ||
88 | pub targets: Vec<Target>, | 95 | pub targets: Vec<Target>, |
96 | /// Is this package a member of the current workspace | ||
89 | pub is_member: bool, | 97 | pub is_member: bool, |
98 | /// List of packages this package depends on | ||
90 | pub dependencies: Vec<PackageDependency>, | 99 | pub dependencies: Vec<PackageDependency>, |
100 | /// Rust edition for this package | ||
91 | pub edition: Edition, | 101 | pub edition: Edition, |
102 | /// List of features to activate | ||
92 | pub features: Vec<String>, | 103 | pub features: Vec<String>, |
104 | /// List of config flags defined by this package's build script | ||
93 | pub cfgs: Vec<CfgFlag>, | 105 | pub cfgs: Vec<CfgFlag>, |
106 | /// List of cargo-related environment variables with their value | ||
107 | /// | ||
108 | /// If the package has a build script which defines environment variables, | ||
109 | /// they can also be found here. | ||
94 | pub envs: Vec<(String, String)>, | 110 | pub envs: Vec<(String, String)>, |
111 | /// Directory where a build script might place its output | ||
95 | pub out_dir: Option<AbsPathBuf>, | 112 | pub out_dir: Option<AbsPathBuf>, |
113 | /// Path to the proc-macro library file if this package exposes proc-macros | ||
96 | pub proc_macro_dylib_path: Option<AbsPathBuf>, | 114 | pub proc_macro_dylib_path: Option<AbsPathBuf>, |
97 | } | 115 | } |
98 | 116 | ||
@@ -102,12 +120,18 @@ pub struct PackageDependency { | |||
102 | pub name: String, | 120 | pub name: String, |
103 | } | 121 | } |
104 | 122 | ||
123 | /// Information associated with a package's target | ||
105 | #[derive(Debug, Clone, Eq, PartialEq)] | 124 | #[derive(Debug, Clone, Eq, PartialEq)] |
106 | pub struct TargetData { | 125 | pub struct TargetData { |
126 | /// Package that provided this target | ||
107 | pub package: Package, | 127 | pub package: Package, |
128 | /// Name as given in the `Cargo.toml` or generated from the file name | ||
108 | pub name: String, | 129 | pub name: String, |
130 | /// Path to the main source file of the target | ||
109 | pub root: AbsPathBuf, | 131 | pub root: AbsPathBuf, |
132 | /// Kind of target | ||
110 | pub kind: TargetKind, | 133 | pub kind: TargetKind, |
134 | /// Is this target a proc-macro | ||
111 | pub is_proc_macro: bool, | 135 | pub is_proc_macro: bool, |
112 | } | 136 | } |
113 | 137 | ||
@@ -149,6 +173,7 @@ impl CargoWorkspace { | |||
149 | pub fn from_cargo_metadata( | 173 | pub fn from_cargo_metadata( |
150 | cargo_toml: &AbsPath, | 174 | cargo_toml: &AbsPath, |
151 | config: &CargoConfig, | 175 | config: &CargoConfig, |
176 | progress: &dyn Fn(String), | ||
152 | ) -> Result<CargoWorkspace> { | 177 | ) -> Result<CargoWorkspace> { |
153 | let mut meta = MetadataCommand::new(); | 178 | let mut meta = MetadataCommand::new(); |
154 | meta.cargo_path(toolchain::cargo()); | 179 | meta.cargo_path(toolchain::cargo()); |
@@ -198,6 +223,9 @@ impl CargoWorkspace { | |||
198 | meta.other_options(vec![String::from("--filter-platform"), target]); | 223 | meta.other_options(vec![String::from("--filter-platform"), target]); |
199 | } | 224 | } |
200 | 225 | ||
226 | // FIXME: Currently MetadataCommand is not based on parse_stream, | ||
227 | // So we just report it as a whole | ||
228 | progress("metadata".to_string()); | ||
201 | let mut meta = meta.exec().with_context(|| { | 229 | let mut meta = meta.exec().with_context(|| { |
202 | let cwd: Option<AbsPathBuf> = | 230 | let cwd: Option<AbsPathBuf> = |
203 | std::env::current_dir().ok().and_then(|p| p.try_into().ok()); | 231 | std::env::current_dir().ok().and_then(|p| p.try_into().ok()); |
@@ -221,7 +249,7 @@ impl CargoWorkspace { | |||
221 | let mut envs = FxHashMap::default(); | 249 | let mut envs = FxHashMap::default(); |
222 | let mut proc_macro_dylib_paths = FxHashMap::default(); | 250 | let mut proc_macro_dylib_paths = FxHashMap::default(); |
223 | if config.load_out_dirs_from_check { | 251 | if config.load_out_dirs_from_check { |
224 | let resources = load_extern_resources(cargo_toml, config)?; | 252 | let resources = load_extern_resources(cargo_toml, config, progress)?; |
225 | out_dir_by_id = resources.out_dirs; | 253 | out_dir_by_id = resources.out_dirs; |
226 | cfgs = resources.cfgs; | 254 | cfgs = resources.cfgs; |
227 | envs = resources.env; | 255 | envs = resources.env; |
@@ -346,6 +374,7 @@ pub(crate) struct ExternResources { | |||
346 | pub(crate) fn load_extern_resources( | 374 | pub(crate) fn load_extern_resources( |
347 | cargo_toml: &Path, | 375 | cargo_toml: &Path, |
348 | cargo_features: &CargoConfig, | 376 | cargo_features: &CargoConfig, |
377 | progress: &dyn Fn(String), | ||
349 | ) -> Result<ExternResources> { | 378 | ) -> Result<ExternResources> { |
350 | let mut cmd = Command::new(toolchain::cargo()); | 379 | let mut cmd = Command::new(toolchain::cargo()); |
351 | cmd.args(&["check", "--message-format=json", "--manifest-path"]).arg(cargo_toml); | 380 | cmd.args(&["check", "--message-format=json", "--manifest-path"]).arg(cargo_toml); |
@@ -373,11 +402,14 @@ pub(crate) fn load_extern_resources( | |||
373 | } | 402 | } |
374 | } | 403 | } |
375 | 404 | ||
376 | let output = cmd.output()?; | 405 | cmd.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null()); |
377 | 406 | ||
378 | let mut res = ExternResources::default(); | 407 | let mut child = cmd.spawn().map(JodChild)?; |
408 | let child_stdout = child.stdout.take().unwrap(); | ||
409 | let stdout = BufReader::new(child_stdout); | ||
379 | 410 | ||
380 | for message in cargo_metadata::Message::parse_stream(output.stdout.as_slice()) { | 411 | let mut res = ExternResources::default(); |
412 | for message in cargo_metadata::Message::parse_stream(stdout) { | ||
381 | if let Ok(message) = message { | 413 | if let Ok(message) = message { |
382 | match message { | 414 | match message { |
383 | Message::BuildScriptExecuted(BuildScript { | 415 | Message::BuildScriptExecuted(BuildScript { |
@@ -410,6 +442,8 @@ pub(crate) fn load_extern_resources( | |||
410 | res.env.insert(package_id, env); | 442 | res.env.insert(package_id, env); |
411 | } | 443 | } |
412 | Message::CompilerArtifact(message) => { | 444 | Message::CompilerArtifact(message) => { |
445 | progress(format!("metadata {}", message.target.name)); | ||
446 | |||
413 | if message.target.kind.contains(&"proc-macro".to_string()) { | 447 | if message.target.kind.contains(&"proc-macro".to_string()) { |
414 | let package_id = message.package_id; | 448 | let package_id = message.package_id; |
415 | // Skip rmeta file | 449 | // Skip rmeta file |
@@ -420,7 +454,9 @@ pub(crate) fn load_extern_resources( | |||
420 | } | 454 | } |
421 | } | 455 | } |
422 | } | 456 | } |
423 | Message::CompilerMessage(_) => (), | 457 | Message::CompilerMessage(message) => { |
458 | progress(message.target.name.clone()); | ||
459 | } | ||
424 | Message::Unknown => (), | 460 | Message::Unknown => (), |
425 | Message::BuildFinished(_) => {} | 461 | Message::BuildFinished(_) => {} |
426 | Message::TextLine(_) => {} | 462 | Message::TextLine(_) => {} |
diff --git a/crates/project_model/src/lib.rs b/crates/project_model/src/lib.rs index 24aa9b8fa..aabb7a47d 100644 --- a/crates/project_model/src/lib.rs +++ b/crates/project_model/src/lib.rs | |||
@@ -1,9 +1,9 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | mod cargo_workspace; | 3 | mod cargo_workspace; |
4 | mod cfg_flag; | ||
4 | mod project_json; | 5 | mod project_json; |
5 | mod sysroot; | 6 | mod sysroot; |
6 | mod cfg_flag; | ||
7 | mod workspace; | 7 | mod workspace; |
8 | 8 | ||
9 | use std::{ | 9 | use std::{ |
@@ -17,7 +17,10 @@ use paths::{AbsPath, AbsPathBuf}; | |||
17 | use rustc_hash::FxHashSet; | 17 | use rustc_hash::FxHashSet; |
18 | 18 | ||
19 | pub use crate::{ | 19 | pub use crate::{ |
20 | cargo_workspace::{CargoConfig, CargoWorkspace, Package, Target, TargetKind}, | 20 | cargo_workspace::{ |
21 | CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, Target, TargetData, | ||
22 | TargetKind, | ||
23 | }, | ||
21 | project_json::{ProjectJson, ProjectJsonData}, | 24 | project_json::{ProjectJson, ProjectJsonData}, |
22 | sysroot::Sysroot, | 25 | sysroot::Sysroot, |
23 | workspace::{PackageRoot, ProjectWorkspace}, | 26 | workspace::{PackageRoot, ProjectWorkspace}, |
diff --git a/crates/project_model/src/project_json.rs b/crates/project_model/src/project_json.rs index af884eb84..41a2ac03e 100644 --- a/crates/project_model/src/project_json.rs +++ b/crates/project_model/src/project_json.rs | |||
@@ -110,13 +110,13 @@ impl ProjectJson { | |||
110 | } | 110 | } |
111 | } | 111 | } |
112 | 112 | ||
113 | #[derive(Deserialize)] | 113 | #[derive(Deserialize, Debug, Clone)] |
114 | pub struct ProjectJsonData { | 114 | pub struct ProjectJsonData { |
115 | sysroot_src: Option<PathBuf>, | 115 | sysroot_src: Option<PathBuf>, |
116 | crates: Vec<CrateData>, | 116 | crates: Vec<CrateData>, |
117 | } | 117 | } |
118 | 118 | ||
119 | #[derive(Deserialize)] | 119 | #[derive(Deserialize, Debug, Clone)] |
120 | struct CrateData { | 120 | struct CrateData { |
121 | display_name: Option<String>, | 121 | display_name: Option<String>, |
122 | root_module: PathBuf, | 122 | root_module: PathBuf, |
@@ -132,7 +132,7 @@ struct CrateData { | |||
132 | source: Option<CrateSource>, | 132 | source: Option<CrateSource>, |
133 | } | 133 | } |
134 | 134 | ||
135 | #[derive(Deserialize)] | 135 | #[derive(Deserialize, Debug, Clone)] |
136 | #[serde(rename = "edition")] | 136 | #[serde(rename = "edition")] |
137 | enum EditionData { | 137 | enum EditionData { |
138 | #[serde(rename = "2015")] | 138 | #[serde(rename = "2015")] |
@@ -153,7 +153,7 @@ impl From<EditionData> for Edition { | |||
153 | } | 153 | } |
154 | } | 154 | } |
155 | 155 | ||
156 | #[derive(Deserialize)] | 156 | #[derive(Deserialize, Debug, Clone)] |
157 | struct DepData { | 157 | struct DepData { |
158 | /// Identifies a crate by position in the crates array. | 158 | /// Identifies a crate by position in the crates array. |
159 | #[serde(rename = "crate")] | 159 | #[serde(rename = "crate")] |
@@ -162,7 +162,7 @@ struct DepData { | |||
162 | name: CrateName, | 162 | name: CrateName, |
163 | } | 163 | } |
164 | 164 | ||
165 | #[derive(Deserialize)] | 165 | #[derive(Deserialize, Debug, Clone)] |
166 | struct CrateSource { | 166 | struct CrateSource { |
167 | include_dirs: Vec<PathBuf>, | 167 | include_dirs: Vec<PathBuf>, |
168 | exclude_dirs: Vec<PathBuf>, | 168 | exclude_dirs: Vec<PathBuf>, |
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 68a235ce3..06a0be284 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs | |||
@@ -64,7 +64,11 @@ impl fmt::Debug for ProjectWorkspace { | |||
64 | } | 64 | } |
65 | 65 | ||
66 | impl ProjectWorkspace { | 66 | impl ProjectWorkspace { |
67 | pub fn load(manifest: ProjectManifest, config: &CargoConfig) -> Result<ProjectWorkspace> { | 67 | pub fn load( |
68 | manifest: ProjectManifest, | ||
69 | config: &CargoConfig, | ||
70 | progress: &dyn Fn(String), | ||
71 | ) -> Result<ProjectWorkspace> { | ||
68 | let res = match manifest { | 72 | let res = match manifest { |
69 | ProjectManifest::ProjectJson(project_json) => { | 73 | ProjectManifest::ProjectJson(project_json) => { |
70 | let file = fs::read_to_string(&project_json).with_context(|| { | 74 | let file = fs::read_to_string(&project_json).with_context(|| { |
@@ -84,15 +88,14 @@ impl ProjectWorkspace { | |||
84 | cmd | 88 | cmd |
85 | })?; | 89 | })?; |
86 | 90 | ||
87 | let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, config).with_context( | 91 | let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, config, progress) |
88 | || { | 92 | .with_context(|| { |
89 | format!( | 93 | format!( |
90 | "Failed to read Cargo metadata from Cargo.toml file {}, {}", | 94 | "Failed to read Cargo metadata from Cargo.toml file {}, {}", |
91 | cargo_toml.display(), | 95 | cargo_toml.display(), |
92 | cargo_version | 96 | cargo_version |
93 | ) | 97 | ) |
94 | }, | 98 | })?; |
95 | )?; | ||
96 | let sysroot = if config.no_sysroot { | 99 | let sysroot = if config.no_sysroot { |
97 | Sysroot::default() | 100 | Sysroot::default() |
98 | } else { | 101 | } else { |
@@ -105,9 +108,12 @@ impl ProjectWorkspace { | |||
105 | }; | 108 | }; |
106 | 109 | ||
107 | let rustc = if let Some(rustc_dir) = &config.rustc_source { | 110 | let rustc = if let Some(rustc_dir) = &config.rustc_source { |
108 | Some(CargoWorkspace::from_cargo_metadata(&rustc_dir, config).with_context( | 111 | Some( |
109 | || format!("Failed to read Cargo metadata for Rust sources"), | 112 | CargoWorkspace::from_cargo_metadata(&rustc_dir, config, progress) |
110 | )?) | 113 | .with_context(|| { |
114 | format!("Failed to read Cargo metadata for Rust sources") | ||
115 | })?, | ||
116 | ) | ||
111 | } else { | 117 | } else { |
112 | None | 118 | None |
113 | }; | 119 | }; |
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index defdcbd74..3af3c59d8 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs | |||
@@ -8,11 +8,7 @@ use std::{convert::TryFrom, env, fs, path::PathBuf, process}; | |||
8 | 8 | ||
9 | use lsp_server::Connection; | 9 | use lsp_server::Connection; |
10 | use project_model::ProjectManifest; | 10 | use project_model::ProjectManifest; |
11 | use rust_analyzer::{ | 11 | use rust_analyzer::{cli, config::Config, from_json, Result}; |
12 | cli, | ||
13 | config::{Config, LinkedProject}, | ||
14 | from_json, Result, | ||
15 | }; | ||
16 | use vfs::AbsPathBuf; | 12 | use vfs::AbsPathBuf; |
17 | 13 | ||
18 | #[cfg(all(feature = "mimalloc"))] | 14 | #[cfg(all(feature = "mimalloc"))] |
@@ -138,13 +134,12 @@ fn run_server() -> Result<()> { | |||
138 | } | 134 | } |
139 | }; | 135 | }; |
140 | 136 | ||
141 | let mut config = Config::new(root_path); | 137 | let mut config = Config::new(root_path, initialize_params.capabilities); |
142 | if let Some(json) = initialize_params.initialization_options { | 138 | if let Some(json) = initialize_params.initialization_options { |
143 | config.update(json); | 139 | config.update(json); |
144 | } | 140 | } |
145 | config.update_caps(&initialize_params.capabilities); | ||
146 | 141 | ||
147 | if config.linked_projects.is_empty() { | 142 | if config.linked_projects().is_empty() { |
148 | let workspace_roots = initialize_params | 143 | let workspace_roots = initialize_params |
149 | .workspace_folders | 144 | .workspace_folders |
150 | .map(|workspaces| { | 145 | .map(|workspaces| { |
@@ -163,7 +158,7 @@ fn run_server() -> Result<()> { | |||
163 | log::error!("failed to find any projects in {:?}", workspace_roots); | 158 | log::error!("failed to find any projects in {:?}", workspace_roots); |
164 | } | 159 | } |
165 | 160 | ||
166 | config.linked_projects = discovered.into_iter().map(LinkedProject::from).collect(); | 161 | config.discovered_projects = Some(discovered); |
167 | } | 162 | } |
168 | 163 | ||
169 | config | 164 | config |
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs index 076e191d9..f148521a2 100644 --- a/crates/rust-analyzer/src/caps.rs +++ b/crates/rust-analyzer/src/caps.rs | |||
@@ -1,7 +1,6 @@ | |||
1 | //! Advertizes the capabilities of the LSP Server. | 1 | //! Advertizes the capabilities of the LSP Server. |
2 | use std::env; | 2 | use std::env; |
3 | 3 | ||
4 | use ide::CompletionResolveCapability; | ||
5 | use lsp_types::{ | 4 | use lsp_types::{ |
6 | CallHierarchyServerCapability, ClientCapabilities, CodeActionKind, CodeActionOptions, | 5 | CallHierarchyServerCapability, ClientCapabilities, CodeActionKind, CodeActionOptions, |
7 | CodeActionProviderCapability, CodeLensOptions, CompletionOptions, | 6 | CodeActionProviderCapability, CodeLensOptions, CompletionOptions, |
@@ -14,7 +13,6 @@ use lsp_types::{ | |||
14 | WorkDoneProgressOptions, WorkspaceFileOperationsServerCapabilities, | 13 | WorkDoneProgressOptions, WorkspaceFileOperationsServerCapabilities, |
15 | WorkspaceServerCapabilities, | 14 | WorkspaceServerCapabilities, |
16 | }; | 15 | }; |
17 | use rustc_hash::FxHashSet; | ||
18 | use serde_json::json; | 16 | use serde_json::json; |
19 | 17 | ||
20 | use crate::semantic_tokens; | 18 | use crate::semantic_tokens; |
@@ -128,37 +126,31 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti | |||
128 | } | 126 | } |
129 | 127 | ||
130 | fn completions_resolve_provider(client_caps: &ClientCapabilities) -> Option<bool> { | 128 | fn completions_resolve_provider(client_caps: &ClientCapabilities) -> Option<bool> { |
131 | if enabled_completions_resolve_capabilities(client_caps)?.is_empty() { | 129 | if completion_item_edit_resolve(client_caps) { |
130 | Some(true) | ||
131 | } else { | ||
132 | log::info!("No `additionalTextEdits` completion resolve capability was found in the client capabilities, autoimport completion is disabled"); | 132 | log::info!("No `additionalTextEdits` completion resolve capability was found in the client capabilities, autoimport completion is disabled"); |
133 | None | 133 | None |
134 | } else { | ||
135 | Some(true) | ||
136 | } | 134 | } |
137 | } | 135 | } |
138 | 136 | ||
139 | /// Parses client capabilities and returns all completion resolve capabilities rust-analyzer supports. | 137 | /// Parses client capabilities and returns all completion resolve capabilities rust-analyzer supports. |
140 | pub(crate) fn enabled_completions_resolve_capabilities( | 138 | pub(crate) fn completion_item_edit_resolve(caps: &ClientCapabilities) -> bool { |
141 | caps: &ClientCapabilities, | 139 | (|| { |
142 | ) -> Option<FxHashSet<CompletionResolveCapability>> { | 140 | Some( |
143 | Some( | 141 | caps.text_document |
144 | caps.text_document | 142 | .as_ref()? |
145 | .as_ref()? | 143 | .completion |
146 | .completion | 144 | .as_ref()? |
147 | .as_ref()? | 145 | .completion_item |
148 | .completion_item | 146 | .as_ref()? |
149 | .as_ref()? | 147 | .resolve_support |
150 | .resolve_support | 148 | .as_ref()? |
151 | .as_ref()? | 149 | .properties |
152 | .properties | 150 | .iter() |
153 | .iter() | 151 | .any(|cap_string| cap_string.as_str() == "additionalTextEdits"), |
154 | .filter_map(|cap_string| match cap_string.as_str() { | 152 | ) |
155 | "additionalTextEdits" => Some(CompletionResolveCapability::AdditionalTextEdits), | 153 | })() == Some(true) |
156 | "detail" => Some(CompletionResolveCapability::Detail), | ||
157 | "documentation" => Some(CompletionResolveCapability::Documentation), | ||
158 | _unsupported => None, | ||
159 | }) | ||
160 | .collect(), | ||
161 | ) | ||
162 | } | 154 | } |
163 | 155 | ||
164 | fn code_action_capabilities(client_caps: &ClientCapabilities) -> CodeActionProviderCapability { | 156 | fn code_action_capabilities(client_caps: &ClientCapabilities) -> CodeActionProviderCapability { |
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs index 8a8b4a32c..5af0802a2 100644 --- a/crates/rust-analyzer/src/cargo_target_spec.rs +++ b/crates/rust-analyzer/src/cargo_target_spec.rs | |||
@@ -84,14 +84,15 @@ impl CargoTargetSpec { | |||
84 | } | 84 | } |
85 | } | 85 | } |
86 | 86 | ||
87 | if snap.config.cargo.all_features { | 87 | let cargo_config = snap.config.cargo(); |
88 | if cargo_config.all_features { | ||
88 | args.push("--all-features".to_string()); | 89 | args.push("--all-features".to_string()); |
89 | } else { | 90 | } else { |
90 | let mut features = Vec::new(); | 91 | let mut features = Vec::new(); |
91 | if let Some(cfg) = cfg.as_ref() { | 92 | if let Some(cfg) = cfg.as_ref() { |
92 | required_features(cfg, &mut features); | 93 | required_features(cfg, &mut features); |
93 | } | 94 | } |
94 | for feature in &snap.config.cargo.features { | 95 | for feature in cargo_config.features { |
95 | features.push(feature.clone()); | 96 | features.push(feature.clone()); |
96 | } | 97 | } |
97 | features.dedup(); | 98 | features.dedup(); |
diff --git a/crates/rust-analyzer/src/cli/analysis_bench.rs b/crates/rust-analyzer/src/cli/analysis_bench.rs index 5a8484c62..7d3fda7a8 100644 --- a/crates/rust-analyzer/src/cli/analysis_bench.rs +++ b/crates/rust-analyzer/src/cli/analysis_bench.rs | |||
@@ -6,9 +6,12 @@ use anyhow::{bail, format_err, Result}; | |||
6 | use ide::{ | 6 | use ide::{ |
7 | Analysis, AnalysisHost, Change, CompletionConfig, DiagnosticsConfig, FilePosition, LineCol, | 7 | Analysis, AnalysisHost, Change, CompletionConfig, DiagnosticsConfig, FilePosition, LineCol, |
8 | }; | 8 | }; |
9 | use ide_db::base_db::{ | 9 | use ide_db::{ |
10 | salsa::{Database, Durability}, | 10 | base_db::{ |
11 | FileId, | 11 | salsa::{Database, Durability}, |
12 | FileId, | ||
13 | }, | ||
14 | helpers::SnippetCap, | ||
12 | }; | 15 | }; |
13 | use vfs::AbsPathBuf; | 16 | use vfs::AbsPathBuf; |
14 | 17 | ||
@@ -87,7 +90,14 @@ impl BenchCmd { | |||
87 | let file_position = FilePosition { file_id, offset }; | 90 | let file_position = FilePosition { file_id, offset }; |
88 | 91 | ||
89 | if is_completion { | 92 | if is_completion { |
90 | let options = CompletionConfig::default(); | 93 | let options = CompletionConfig { |
94 | enable_postfix_completions: true, | ||
95 | enable_autoimport_completions: true, | ||
96 | add_call_parenthesis: true, | ||
97 | add_call_argument_snippets: true, | ||
98 | snippet_cap: SnippetCap::new(true), | ||
99 | merge: None, | ||
100 | }; | ||
91 | let res = do_work(&mut host, file_id, |analysis| { | 101 | let res = do_work(&mut host, file_id, |analysis| { |
92 | analysis.completions(&options, file_position) | 102 | analysis.completions(&options, file_position) |
93 | }); | 103 | }); |
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 9445aec07..fd1407e60 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs | |||
@@ -58,7 +58,7 @@ impl AnalysisStatsCmd { | |||
58 | let mut db_load_sw = self.stop_watch(); | 58 | let mut db_load_sw = self.stop_watch(); |
59 | let (host, vfs) = load_cargo(&self.path, self.load_output_dirs, self.with_proc_macro)?; | 59 | let (host, vfs) = load_cargo(&self.path, self.load_output_dirs, self.with_proc_macro)?; |
60 | let db = host.raw_database(); | 60 | let db = host.raw_database(); |
61 | eprintln!("Database loaded {}", db_load_sw.elapsed()); | 61 | eprintln!("{:<20} {}", "Database loaded:", db_load_sw.elapsed()); |
62 | 62 | ||
63 | let mut analysis_sw = self.stop_watch(); | 63 | let mut analysis_sw = self.stop_watch(); |
64 | let mut num_crates = 0; | 64 | let mut num_crates = 0; |
@@ -85,7 +85,7 @@ impl AnalysisStatsCmd { | |||
85 | shuffle(&mut rng, &mut visit_queue); | 85 | shuffle(&mut rng, &mut visit_queue); |
86 | } | 86 | } |
87 | 87 | ||
88 | eprintln!("Crates in this dir: {}", num_crates); | 88 | eprint!(" crates: {}", num_crates); |
89 | let mut num_decls = 0; | 89 | let mut num_decls = 0; |
90 | let mut funcs = Vec::new(); | 90 | let mut funcs = Vec::new(); |
91 | while let Some(module) = visit_queue.pop() { | 91 | while let Some(module) = visit_queue.pop() { |
@@ -109,10 +109,8 @@ impl AnalysisStatsCmd { | |||
109 | } | 109 | } |
110 | } | 110 | } |
111 | } | 111 | } |
112 | eprintln!("Total modules found: {}", visited_modules.len()); | 112 | eprintln!(", mods: {}, decls: {}, fns: {}", visited_modules.len(), num_decls, funcs.len()); |
113 | eprintln!("Total declarations: {}", num_decls); | 113 | eprintln!("{:<20} {}", "Item Collection:", analysis_sw.elapsed()); |
114 | eprintln!("Total functions: {}", funcs.len()); | ||
115 | eprintln!("Item Collection: {}", analysis_sw.elapsed()); | ||
116 | 114 | ||
117 | if self.randomize { | 115 | if self.randomize { |
118 | shuffle(&mut rng, &mut funcs); | 116 | shuffle(&mut rng, &mut funcs); |
@@ -135,7 +133,7 @@ impl AnalysisStatsCmd { | |||
135 | snap.0.infer(f_id.into()); | 133 | snap.0.infer(f_id.into()); |
136 | }) | 134 | }) |
137 | .count(); | 135 | .count(); |
138 | eprintln!("Parallel Inference: {}", inference_sw.elapsed()); | 136 | eprintln!("{:<20} {}", "Parallel Inference:", inference_sw.elapsed()); |
139 | } | 137 | } |
140 | 138 | ||
141 | let mut inference_sw = self.stop_watch(); | 139 | let mut inference_sw = self.stop_watch(); |
@@ -273,27 +271,22 @@ impl AnalysisStatsCmd { | |||
273 | bar.inc(1); | 271 | bar.inc(1); |
274 | } | 272 | } |
275 | bar.finish_and_clear(); | 273 | bar.finish_and_clear(); |
276 | eprintln!("Total expressions: {}", num_exprs); | ||
277 | eprintln!( | 274 | eprintln!( |
278 | "Expressions of unknown type: {} ({}%)", | 275 | " exprs: {}, ??ty: {} ({}%), ?ty: {} ({}%), !ty: {}", |
276 | num_exprs, | ||
279 | num_exprs_unknown, | 277 | num_exprs_unknown, |
280 | if num_exprs > 0 { num_exprs_unknown * 100 / num_exprs } else { 100 } | 278 | percentage(num_exprs_unknown, num_exprs), |
281 | ); | ||
282 | report_metric("unknown type", num_exprs_unknown, "#"); | ||
283 | |||
284 | eprintln!( | ||
285 | "Expressions of partially unknown type: {} ({}%)", | ||
286 | num_exprs_partially_unknown, | 279 | num_exprs_partially_unknown, |
287 | if num_exprs > 0 { num_exprs_partially_unknown * 100 / num_exprs } else { 100 } | 280 | percentage(num_exprs_partially_unknown, num_exprs), |
281 | num_type_mismatches | ||
288 | ); | 282 | ); |
289 | 283 | report_metric("unknown type", num_exprs_unknown, "#"); | |
290 | eprintln!("Type mismatches: {}", num_type_mismatches); | ||
291 | report_metric("type mismatches", num_type_mismatches, "#"); | 284 | report_metric("type mismatches", num_type_mismatches, "#"); |
292 | 285 | ||
293 | eprintln!("Inference: {}", inference_sw.elapsed()); | 286 | eprintln!("{:<20} {}", "Inference:", inference_sw.elapsed()); |
294 | 287 | ||
295 | let total_span = analysis_sw.elapsed(); | 288 | let total_span = analysis_sw.elapsed(); |
296 | eprintln!("Total: {}", total_span); | 289 | eprintln!("{:<20} {}", "Total:", total_span); |
297 | report_metric("total time", total_span.time.as_millis() as u64, "ms"); | 290 | report_metric("total time", total_span.time.as_millis() as u64, "ms"); |
298 | if let Some(instructions) = total_span.instructions { | 291 | if let Some(instructions) = total_span.instructions { |
299 | report_metric("total instructions", instructions, "#instr"); | 292 | report_metric("total instructions", instructions, "#instr"); |
@@ -302,7 +295,7 @@ impl AnalysisStatsCmd { | |||
302 | report_metric("total memory", memory.allocated.megabytes() as u64, "MB"); | 295 | report_metric("total memory", memory.allocated.megabytes() as u64, "MB"); |
303 | } | 296 | } |
304 | 297 | ||
305 | if self.memory_usage { | 298 | if self.memory_usage && verbosity.is_verbose() { |
306 | print_memory_usage(host, vfs); | 299 | print_memory_usage(host, vfs); |
307 | } | 300 | } |
308 | 301 | ||
@@ -325,3 +318,7 @@ fn shuffle<T>(rng: &mut Rand32, slice: &mut [T]) { | |||
325 | slice.swap(0, idx); | 318 | slice.swap(0, idx); |
326 | } | 319 | } |
327 | } | 320 | } |
321 | |||
322 | fn percentage(n: u64, total: u64) -> u64 { | ||
323 | (n * 100).checked_div(total).unwrap_or(100) | ||
324 | } | ||
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index e5ab6c73b..31a16ca46 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs | |||
@@ -21,6 +21,7 @@ pub fn load_cargo( | |||
21 | let ws = ProjectWorkspace::load( | 21 | let ws = ProjectWorkspace::load( |
22 | root, | 22 | root, |
23 | &CargoConfig { load_out_dirs_from_check, ..Default::default() }, | 23 | &CargoConfig { load_out_dirs_from_check, ..Default::default() }, |
24 | &|_| {}, | ||
24 | )?; | 25 | )?; |
25 | 26 | ||
26 | let (sender, receiver) = unbounded(); | 27 | let (sender, receiver) = unbounded(); |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index a80652e83..27b92a5a9 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -7,12 +7,15 @@ | |||
7 | //! configure the server itself, feature flags are passed into analysis, and | 7 | //! configure the server itself, feature flags are passed into analysis, and |
8 | //! tweak things like automatic insertion of `()` in completions. | 8 | //! tweak things like automatic insertion of `()` in completions. |
9 | 9 | ||
10 | use std::{convert::TryFrom, ffi::OsString, path::PathBuf}; | 10 | use std::{convert::TryFrom, ffi::OsString, iter, path::PathBuf}; |
11 | 11 | ||
12 | use flycheck::FlycheckConfig; | 12 | use flycheck::FlycheckConfig; |
13 | use hir::PrefixKind; | 13 | use hir::PrefixKind; |
14 | use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig}; | 14 | use ide::{ |
15 | use ide_db::helpers::insert_use::MergeBehavior; | 15 | AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig, |
16 | InsertUseConfig, | ||
17 | }; | ||
18 | use ide_db::helpers::{insert_use::MergeBehavior, SnippetCap}; | ||
16 | use itertools::Itertools; | 19 | use itertools::Itertools; |
17 | use lsp_types::{ClientCapabilities, MarkupKind}; | 20 | use lsp_types::{ClientCapabilities, MarkupKind}; |
18 | use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest}; | 21 | use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest}; |
@@ -20,12 +23,13 @@ use rustc_hash::FxHashSet; | |||
20 | use serde::{de::DeserializeOwned, Deserialize}; | 23 | use serde::{de::DeserializeOwned, Deserialize}; |
21 | use vfs::AbsPathBuf; | 24 | use vfs::AbsPathBuf; |
22 | 25 | ||
23 | use crate::{caps::enabled_completions_resolve_capabilities, diagnostics::DiagnosticsMapConfig}; | 26 | use crate::{caps::completion_item_edit_resolve, diagnostics::DiagnosticsMapConfig}; |
24 | 27 | ||
25 | config_data! { | 28 | config_data! { |
26 | struct ConfigData { | 29 | struct ConfigData { |
27 | /// The strategy to use when inserting new imports or merging imports. | 30 | /// The strategy to use when inserting new imports or merging imports. |
28 | assist_importMergeBehaviour: MergeBehaviorDef = "\"full\"", | 31 | assist_importMergeBehavior | |
32 | assist_importMergeBehaviour: MergeBehaviorDef = "\"full\"", | ||
29 | /// The path structure for newly inserted paths to use. | 33 | /// The path structure for newly inserted paths to use. |
30 | assist_importPrefix: ImportPrefixDef = "\"plain\"", | 34 | assist_importPrefix: ImportPrefixDef = "\"plain\"", |
31 | 35 | ||
@@ -148,13 +152,19 @@ config_data! { | |||
148 | /// of projects.\n\nElements must be paths pointing to `Cargo.toml`, | 152 | /// of projects.\n\nElements must be paths pointing to `Cargo.toml`, |
149 | /// `rust-project.json`, or JSON objects in `rust-project.json` format. | 153 | /// `rust-project.json`, or JSON objects in `rust-project.json` format. |
150 | linkedProjects: Vec<ManifestOrProjectJson> = "[]", | 154 | linkedProjects: Vec<ManifestOrProjectJson> = "[]", |
155 | |||
151 | /// Number of syntax trees rust-analyzer keeps in memory. Defaults to 128. | 156 | /// Number of syntax trees rust-analyzer keeps in memory. Defaults to 128. |
152 | lruCapacity: Option<usize> = "null", | 157 | lruCapacity: Option<usize> = "null", |
158 | |||
153 | /// Whether to show `can't find Cargo.toml` error message. | 159 | /// Whether to show `can't find Cargo.toml` error message. |
154 | notifications_cargoTomlNotFound: bool = "true", | 160 | notifications_cargoTomlNotFound: bool = "true", |
161 | |||
155 | /// Enable Proc macro support, `#rust-analyzer.cargo.loadOutDirsFromCheck#` must be | 162 | /// Enable Proc macro support, `#rust-analyzer.cargo.loadOutDirsFromCheck#` must be |
156 | /// enabled. | 163 | /// enabled. |
157 | procMacro_enable: bool = "false", | 164 | procMacro_enable: bool = "false", |
165 | /// Internal config, path to proc-macro server executable (typically, | ||
166 | /// this is rust-analyzer itself, but we override this in tests). | ||
167 | procMacro_server: Option<PathBuf> = "null", | ||
158 | 168 | ||
159 | /// Command to be executed instead of 'cargo' for runnables. | 169 | /// Command to be executed instead of 'cargo' for runnables. |
160 | runnables_overrideCargo: Option<String> = "null", | 170 | runnables_overrideCargo: Option<String> = "null", |
@@ -163,7 +173,7 @@ config_data! { | |||
163 | runnables_cargoExtraArgs: Vec<String> = "[]", | 173 | runnables_cargoExtraArgs: Vec<String> = "[]", |
164 | 174 | ||
165 | /// Path to the rust compiler sources, for usage in rustc_private projects. | 175 | /// Path to the rust compiler sources, for usage in rustc_private projects. |
166 | rustcSource : Option<String> = "null", | 176 | rustcSource : Option<PathBuf> = "null", |
167 | 177 | ||
168 | /// Additional arguments to `rustfmt`. | 178 | /// Additional arguments to `rustfmt`. |
169 | rustfmt_extraArgs: Vec<String> = "[]", | 179 | rustfmt_extraArgs: Vec<String> = "[]", |
@@ -173,34 +183,17 @@ config_data! { | |||
173 | } | 183 | } |
174 | } | 184 | } |
175 | 185 | ||
186 | impl Default for ConfigData { | ||
187 | fn default() -> Self { | ||
188 | ConfigData::from_json(serde_json::Value::Null) | ||
189 | } | ||
190 | } | ||
191 | |||
176 | #[derive(Debug, Clone)] | 192 | #[derive(Debug, Clone)] |
177 | pub struct Config { | 193 | pub struct Config { |
178 | pub caps: lsp_types::ClientCapabilities, | 194 | caps: lsp_types::ClientCapabilities, |
179 | 195 | data: ConfigData, | |
180 | pub publish_diagnostics: bool, | 196 | pub discovered_projects: Option<Vec<ProjectManifest>>, |
181 | pub diagnostics: DiagnosticsConfig, | ||
182 | pub diagnostics_map: DiagnosticsMapConfig, | ||
183 | pub lru_capacity: Option<usize>, | ||
184 | pub proc_macro_srv: Option<(PathBuf, Vec<OsString>)>, | ||
185 | pub files: FilesConfig, | ||
186 | pub notifications: NotificationsConfig, | ||
187 | |||
188 | pub cargo_autoreload: bool, | ||
189 | pub cargo: CargoConfig, | ||
190 | pub rustfmt: RustfmtConfig, | ||
191 | pub flycheck: Option<FlycheckConfig>, | ||
192 | pub runnables: RunnablesConfig, | ||
193 | |||
194 | pub inlay_hints: InlayHintsConfig, | ||
195 | pub completion: CompletionConfig, | ||
196 | pub assist: AssistConfig, | ||
197 | pub call_info_full: bool, | ||
198 | pub lens: LensConfig, | ||
199 | pub hover: HoverConfig, | ||
200 | pub semantic_tokens_refresh: bool, | ||
201 | pub code_lens_refresh: bool, | ||
202 | |||
203 | pub linked_projects: Vec<LinkedProject>, | ||
204 | pub root_path: AbsPathBuf, | 197 | pub root_path: AbsPathBuf, |
205 | } | 198 | } |
206 | 199 | ||
@@ -230,12 +223,6 @@ pub struct LensConfig { | |||
230 | pub method_refs: bool, | 223 | pub method_refs: bool, |
231 | } | 224 | } |
232 | 225 | ||
233 | impl Default for LensConfig { | ||
234 | fn default() -> Self { | ||
235 | Self { run: true, debug: true, implementations: true, method_refs: false } | ||
236 | } | ||
237 | } | ||
238 | |||
239 | impl LensConfig { | 226 | impl LensConfig { |
240 | pub fn any(&self) -> bool { | 227 | pub fn any(&self) -> bool { |
241 | self.implementations || self.runnable() || self.references() | 228 | self.implementations || self.runnable() || self.references() |
@@ -278,7 +265,7 @@ pub enum RustfmtConfig { | |||
278 | } | 265 | } |
279 | 266 | ||
280 | /// Configuration for runnable items, such as `main` function or tests. | 267 | /// Configuration for runnable items, such as `main` function or tests. |
281 | #[derive(Debug, Clone, Default)] | 268 | #[derive(Debug, Clone)] |
282 | pub struct RunnablesConfig { | 269 | pub struct RunnablesConfig { |
283 | /// Custom command to be executed instead of `cargo` for runnables. | 270 | /// Custom command to be executed instead of `cargo` for runnables. |
284 | pub override_cargo: Option<String>, | 271 | pub override_cargo: Option<String>, |
@@ -287,250 +274,15 @@ pub struct RunnablesConfig { | |||
287 | } | 274 | } |
288 | 275 | ||
289 | impl Config { | 276 | impl Config { |
290 | pub fn new(root_path: AbsPathBuf) -> Self { | 277 | pub fn new(root_path: AbsPathBuf, caps: ClientCapabilities) -> Self { |
291 | // Defaults here don't matter, we'll immediately re-write them with | 278 | Config { caps, data: ConfigData::default(), discovered_projects: None, root_path } |
292 | // ConfigData. | ||
293 | let mut res = Config { | ||
294 | caps: lsp_types::ClientCapabilities::default(), | ||
295 | |||
296 | publish_diagnostics: false, | ||
297 | diagnostics: DiagnosticsConfig::default(), | ||
298 | diagnostics_map: DiagnosticsMapConfig::default(), | ||
299 | lru_capacity: None, | ||
300 | proc_macro_srv: None, | ||
301 | files: FilesConfig { watcher: FilesWatcher::Notify, exclude: Vec::new() }, | ||
302 | notifications: NotificationsConfig { cargo_toml_not_found: false }, | ||
303 | |||
304 | cargo_autoreload: false, | ||
305 | cargo: CargoConfig::default(), | ||
306 | rustfmt: RustfmtConfig::Rustfmt { extra_args: Vec::new() }, | ||
307 | flycheck: Some(FlycheckConfig::CargoCommand { | ||
308 | command: String::new(), | ||
309 | target_triple: None, | ||
310 | no_default_features: false, | ||
311 | all_targets: false, | ||
312 | all_features: false, | ||
313 | extra_args: Vec::new(), | ||
314 | features: Vec::new(), | ||
315 | }), | ||
316 | runnables: RunnablesConfig::default(), | ||
317 | |||
318 | inlay_hints: InlayHintsConfig { | ||
319 | type_hints: false, | ||
320 | parameter_hints: false, | ||
321 | chaining_hints: false, | ||
322 | max_length: None, | ||
323 | }, | ||
324 | completion: CompletionConfig::default(), | ||
325 | assist: AssistConfig::default(), | ||
326 | call_info_full: false, | ||
327 | lens: LensConfig::default(), | ||
328 | hover: HoverConfig::default(), | ||
329 | semantic_tokens_refresh: false, | ||
330 | code_lens_refresh: false, | ||
331 | linked_projects: Vec::new(), | ||
332 | root_path, | ||
333 | }; | ||
334 | res.do_update(serde_json::json!({})); | ||
335 | res | ||
336 | } | 279 | } |
337 | pub fn update(&mut self, json: serde_json::Value) { | 280 | pub fn update(&mut self, json: serde_json::Value) { |
338 | log::info!("updating config from JSON: {:#}", json); | 281 | log::info!("updating config from JSON: {:#}", json); |
339 | if json.is_null() || json.as_object().map_or(false, |it| it.is_empty()) { | 282 | if json.is_null() || json.as_object().map_or(false, |it| it.is_empty()) { |
340 | return; | 283 | return; |
341 | } | 284 | } |
342 | self.do_update(json); | 285 | self.data = ConfigData::from_json(json); |
343 | log::info!("updated config: {:#?}", self); | ||
344 | } | ||
345 | fn do_update(&mut self, json: serde_json::Value) { | ||
346 | let data = ConfigData::from_json(json); | ||
347 | |||
348 | self.publish_diagnostics = data.diagnostics_enable; | ||
349 | self.diagnostics = DiagnosticsConfig { | ||
350 | disable_experimental: !data.diagnostics_enableExperimental, | ||
351 | disabled: data.diagnostics_disabled, | ||
352 | }; | ||
353 | self.diagnostics_map = DiagnosticsMapConfig { | ||
354 | warnings_as_info: data.diagnostics_warningsAsInfo, | ||
355 | warnings_as_hint: data.diagnostics_warningsAsHint, | ||
356 | }; | ||
357 | self.lru_capacity = data.lruCapacity; | ||
358 | self.files.watcher = match data.files_watcher.as_str() { | ||
359 | "notify" => FilesWatcher::Notify, | ||
360 | "client" | _ => FilesWatcher::Client, | ||
361 | }; | ||
362 | self.notifications = | ||
363 | NotificationsConfig { cargo_toml_not_found: data.notifications_cargoTomlNotFound }; | ||
364 | self.cargo_autoreload = data.cargo_autoreload; | ||
365 | |||
366 | let rustc_source = if let Some(rustc_source) = data.rustcSource { | ||
367 | let rustpath: PathBuf = rustc_source.into(); | ||
368 | AbsPathBuf::try_from(rustpath) | ||
369 | .map_err(|_| { | ||
370 | log::error!("rustc source directory must be an absolute path"); | ||
371 | }) | ||
372 | .ok() | ||
373 | } else { | ||
374 | None | ||
375 | }; | ||
376 | |||
377 | self.cargo = CargoConfig { | ||
378 | no_default_features: data.cargo_noDefaultFeatures, | ||
379 | all_features: data.cargo_allFeatures, | ||
380 | features: data.cargo_features.clone(), | ||
381 | load_out_dirs_from_check: data.cargo_loadOutDirsFromCheck, | ||
382 | target: data.cargo_target.clone(), | ||
383 | rustc_source: rustc_source, | ||
384 | no_sysroot: data.cargo_noSysroot, | ||
385 | }; | ||
386 | self.runnables = RunnablesConfig { | ||
387 | override_cargo: data.runnables_overrideCargo, | ||
388 | cargo_extra_args: data.runnables_cargoExtraArgs, | ||
389 | }; | ||
390 | |||
391 | self.proc_macro_srv = if data.procMacro_enable { | ||
392 | std::env::current_exe().ok().map(|path| (path, vec!["proc-macro".into()])) | ||
393 | } else { | ||
394 | None | ||
395 | }; | ||
396 | |||
397 | self.rustfmt = match data.rustfmt_overrideCommand { | ||
398 | Some(mut args) if !args.is_empty() => { | ||
399 | let command = args.remove(0); | ||
400 | RustfmtConfig::CustomCommand { command, args } | ||
401 | } | ||
402 | Some(_) | None => RustfmtConfig::Rustfmt { extra_args: data.rustfmt_extraArgs }, | ||
403 | }; | ||
404 | |||
405 | self.flycheck = if data.checkOnSave_enable { | ||
406 | let flycheck_config = match data.checkOnSave_overrideCommand { | ||
407 | Some(mut args) if !args.is_empty() => { | ||
408 | let command = args.remove(0); | ||
409 | FlycheckConfig::CustomCommand { command, args } | ||
410 | } | ||
411 | Some(_) | None => FlycheckConfig::CargoCommand { | ||
412 | command: data.checkOnSave_command, | ||
413 | target_triple: data.checkOnSave_target.or(data.cargo_target), | ||
414 | all_targets: data.checkOnSave_allTargets, | ||
415 | no_default_features: data | ||
416 | .checkOnSave_noDefaultFeatures | ||
417 | .unwrap_or(data.cargo_noDefaultFeatures), | ||
418 | all_features: data.checkOnSave_allFeatures.unwrap_or(data.cargo_allFeatures), | ||
419 | features: data.checkOnSave_features.unwrap_or(data.cargo_features), | ||
420 | extra_args: data.checkOnSave_extraArgs, | ||
421 | }, | ||
422 | }; | ||
423 | Some(flycheck_config) | ||
424 | } else { | ||
425 | None | ||
426 | }; | ||
427 | |||
428 | self.inlay_hints = InlayHintsConfig { | ||
429 | type_hints: data.inlayHints_typeHints, | ||
430 | parameter_hints: data.inlayHints_parameterHints, | ||
431 | chaining_hints: data.inlayHints_chainingHints, | ||
432 | max_length: data.inlayHints_maxLength, | ||
433 | }; | ||
434 | |||
435 | self.assist.insert_use.merge = match data.assist_importMergeBehaviour { | ||
436 | MergeBehaviorDef::None => None, | ||
437 | MergeBehaviorDef::Full => Some(MergeBehavior::Full), | ||
438 | MergeBehaviorDef::Last => Some(MergeBehavior::Last), | ||
439 | }; | ||
440 | self.assist.insert_use.prefix_kind = match data.assist_importPrefix { | ||
441 | ImportPrefixDef::Plain => PrefixKind::Plain, | ||
442 | ImportPrefixDef::ByCrate => PrefixKind::ByCrate, | ||
443 | ImportPrefixDef::BySelf => PrefixKind::BySelf, | ||
444 | }; | ||
445 | |||
446 | self.completion.enable_postfix_completions = data.completion_postfix_enable; | ||
447 | self.completion.enable_autoimport_completions = data.completion_autoimport_enable; | ||
448 | self.completion.add_call_parenthesis = data.completion_addCallParenthesis; | ||
449 | self.completion.add_call_argument_snippets = data.completion_addCallArgumentSnippets; | ||
450 | self.completion.merge = self.assist.insert_use.merge; | ||
451 | |||
452 | self.call_info_full = data.callInfo_full; | ||
453 | |||
454 | self.lens = LensConfig { | ||
455 | run: data.lens_enable && data.lens_run, | ||
456 | debug: data.lens_enable && data.lens_debug, | ||
457 | implementations: data.lens_enable && data.lens_implementations, | ||
458 | method_refs: data.lens_enable && data.lens_methodReferences, | ||
459 | }; | ||
460 | |||
461 | if !data.linkedProjects.is_empty() { | ||
462 | self.linked_projects.clear(); | ||
463 | for linked_project in data.linkedProjects { | ||
464 | let linked_project = match linked_project { | ||
465 | ManifestOrProjectJson::Manifest(it) => { | ||
466 | let path = self.root_path.join(it); | ||
467 | match ProjectManifest::from_manifest_file(path) { | ||
468 | Ok(it) => it.into(), | ||
469 | Err(e) => { | ||
470 | log::error!("failed to load linked project: {}", e); | ||
471 | continue; | ||
472 | } | ||
473 | } | ||
474 | } | ||
475 | ManifestOrProjectJson::ProjectJson(it) => { | ||
476 | ProjectJson::new(&self.root_path, it).into() | ||
477 | } | ||
478 | }; | ||
479 | self.linked_projects.push(linked_project); | ||
480 | } | ||
481 | } | ||
482 | |||
483 | self.hover = HoverConfig { | ||
484 | implementations: data.hoverActions_enable && data.hoverActions_implementations, | ||
485 | run: data.hoverActions_enable && data.hoverActions_run, | ||
486 | debug: data.hoverActions_enable && data.hoverActions_debug, | ||
487 | goto_type_def: data.hoverActions_enable && data.hoverActions_gotoTypeDef, | ||
488 | links_in_hover: data.hoverActions_linksInHover, | ||
489 | markdown: true, | ||
490 | }; | ||
491 | } | ||
492 | |||
493 | pub fn update_caps(&mut self, caps: &ClientCapabilities) { | ||
494 | self.caps = caps.clone(); | ||
495 | if let Some(doc_caps) = caps.text_document.as_ref() { | ||
496 | if let Some(value) = doc_caps.hover.as_ref().and_then(|it| it.content_format.as_ref()) { | ||
497 | self.hover.markdown = value.contains(&MarkupKind::Markdown) | ||
498 | } | ||
499 | |||
500 | self.completion.allow_snippets(false); | ||
501 | self.completion.active_resolve_capabilities = | ||
502 | enabled_completions_resolve_capabilities(caps).unwrap_or_default(); | ||
503 | if let Some(completion) = &doc_caps.completion { | ||
504 | if let Some(completion_item) = &completion.completion_item { | ||
505 | if let Some(value) = completion_item.snippet_support { | ||
506 | self.completion.allow_snippets(value); | ||
507 | } | ||
508 | } | ||
509 | } | ||
510 | } | ||
511 | |||
512 | self.assist.allow_snippets(false); | ||
513 | if let Some(experimental) = &caps.experimental { | ||
514 | let get_bool = | ||
515 | |index: &str| experimental.get(index).and_then(|it| it.as_bool()) == Some(true); | ||
516 | |||
517 | let snippet_text_edit = get_bool("snippetTextEdit"); | ||
518 | self.assist.allow_snippets(snippet_text_edit); | ||
519 | } | ||
520 | |||
521 | if let Some(workspace_caps) = caps.workspace.as_ref() { | ||
522 | if let Some(refresh_support) = | ||
523 | workspace_caps.semantic_tokens.as_ref().and_then(|it| it.refresh_support) | ||
524 | { | ||
525 | self.semantic_tokens_refresh = refresh_support; | ||
526 | } | ||
527 | |||
528 | if let Some(refresh_support) = | ||
529 | workspace_caps.code_lens.as_ref().and_then(|it| it.refresh_support) | ||
530 | { | ||
531 | self.code_lens_refresh = refresh_support; | ||
532 | } | ||
533 | } | ||
534 | } | 286 | } |
535 | 287 | ||
536 | pub fn json_schema() -> serde_json::Value { | 288 | pub fn json_schema() -> serde_json::Value { |
@@ -550,6 +302,50 @@ macro_rules! try_or { | |||
550 | } | 302 | } |
551 | 303 | ||
552 | impl Config { | 304 | impl Config { |
305 | pub fn linked_projects(&self) -> Vec<LinkedProject> { | ||
306 | if self.data.linkedProjects.is_empty() { | ||
307 | self.discovered_projects | ||
308 | .as_ref() | ||
309 | .into_iter() | ||
310 | .flatten() | ||
311 | .cloned() | ||
312 | .map(LinkedProject::from) | ||
313 | .collect() | ||
314 | } else { | ||
315 | self.data | ||
316 | .linkedProjects | ||
317 | .iter() | ||
318 | .filter_map(|linked_project| { | ||
319 | let res = match linked_project { | ||
320 | ManifestOrProjectJson::Manifest(it) => { | ||
321 | let path = self.root_path.join(it); | ||
322 | ProjectManifest::from_manifest_file(path) | ||
323 | .map_err(|e| log::error!("failed to load linked project: {}", e)) | ||
324 | .ok()? | ||
325 | .into() | ||
326 | } | ||
327 | ManifestOrProjectJson::ProjectJson(it) => { | ||
328 | ProjectJson::new(&self.root_path, it.clone()).into() | ||
329 | } | ||
330 | }; | ||
331 | Some(res) | ||
332 | }) | ||
333 | .collect() | ||
334 | } | ||
335 | } | ||
336 | |||
337 | pub fn did_save_text_document_dynamic_registration(&self) -> bool { | ||
338 | let caps = | ||
339 | try_or!(self.caps.text_document.as_ref()?.synchronization.clone()?, Default::default()); | ||
340 | caps.did_save == Some(true) && caps.dynamic_registration == Some(true) | ||
341 | } | ||
342 | pub fn did_change_watched_files_dynamic_registration(&self) -> bool { | ||
343 | try_or!( | ||
344 | self.caps.workspace.as_ref()?.did_change_watched_files.as_ref()?.dynamic_registration?, | ||
345 | false | ||
346 | ) | ||
347 | } | ||
348 | |||
553 | pub fn location_link(&self) -> bool { | 349 | pub fn location_link(&self) -> bool { |
554 | try_or!(self.caps.text_document.as_ref()?.definition?.link_support?, false) | 350 | try_or!(self.caps.text_document.as_ref()?.definition?.link_support?, false) |
555 | } | 351 | } |
@@ -625,16 +421,218 @@ impl Config { | |||
625 | pub fn status_notification(&self) -> bool { | 421 | pub fn status_notification(&self) -> bool { |
626 | self.experimental("statusNotification") | 422 | self.experimental("statusNotification") |
627 | } | 423 | } |
424 | |||
425 | pub fn publish_diagnostics(&self) -> bool { | ||
426 | self.data.diagnostics_enable | ||
427 | } | ||
428 | pub fn diagnostics(&self) -> DiagnosticsConfig { | ||
429 | DiagnosticsConfig { | ||
430 | disable_experimental: !self.data.diagnostics_enableExperimental, | ||
431 | disabled: self.data.diagnostics_disabled.clone(), | ||
432 | } | ||
433 | } | ||
434 | pub fn diagnostics_map(&self) -> DiagnosticsMapConfig { | ||
435 | DiagnosticsMapConfig { | ||
436 | warnings_as_info: self.data.diagnostics_warningsAsInfo.clone(), | ||
437 | warnings_as_hint: self.data.diagnostics_warningsAsHint.clone(), | ||
438 | } | ||
439 | } | ||
440 | pub fn lru_capacity(&self) -> Option<usize> { | ||
441 | self.data.lruCapacity | ||
442 | } | ||
443 | pub fn proc_macro_srv(&self) -> Option<(PathBuf, Vec<OsString>)> { | ||
444 | if !self.data.procMacro_enable { | ||
445 | return None; | ||
446 | } | ||
447 | |||
448 | let path = self.data.procMacro_server.clone().or_else(|| std::env::current_exe().ok())?; | ||
449 | Some((path, vec!["proc-macro".into()])) | ||
450 | } | ||
451 | pub fn files(&self) -> FilesConfig { | ||
452 | FilesConfig { | ||
453 | watcher: match self.data.files_watcher.as_str() { | ||
454 | "notify" => FilesWatcher::Notify, | ||
455 | "client" | _ => FilesWatcher::Client, | ||
456 | }, | ||
457 | exclude: Vec::new(), | ||
458 | } | ||
459 | } | ||
460 | pub fn notifications(&self) -> NotificationsConfig { | ||
461 | NotificationsConfig { cargo_toml_not_found: self.data.notifications_cargoTomlNotFound } | ||
462 | } | ||
463 | pub fn cargo_autoreload(&self) -> bool { | ||
464 | self.data.cargo_autoreload | ||
465 | } | ||
466 | pub fn cargo(&self) -> CargoConfig { | ||
467 | let rustc_source = self.data.rustcSource.clone().and_then(|it| { | ||
468 | AbsPathBuf::try_from(it) | ||
469 | .map_err(|_| log::error!("rustc source directory must be an absolute path")) | ||
470 | .ok() | ||
471 | }); | ||
472 | |||
473 | CargoConfig { | ||
474 | no_default_features: self.data.cargo_noDefaultFeatures, | ||
475 | all_features: self.data.cargo_allFeatures, | ||
476 | features: self.data.cargo_features.clone(), | ||
477 | load_out_dirs_from_check: self.data.cargo_loadOutDirsFromCheck, | ||
478 | target: self.data.cargo_target.clone(), | ||
479 | rustc_source, | ||
480 | no_sysroot: self.data.cargo_noSysroot, | ||
481 | } | ||
482 | } | ||
483 | pub fn rustfmt(&self) -> RustfmtConfig { | ||
484 | match &self.data.rustfmt_overrideCommand { | ||
485 | Some(args) if !args.is_empty() => { | ||
486 | let mut args = args.clone(); | ||
487 | let command = args.remove(0); | ||
488 | RustfmtConfig::CustomCommand { command, args } | ||
489 | } | ||
490 | Some(_) | None => { | ||
491 | RustfmtConfig::Rustfmt { extra_args: self.data.rustfmt_extraArgs.clone() } | ||
492 | } | ||
493 | } | ||
494 | } | ||
495 | pub fn flycheck(&self) -> Option<FlycheckConfig> { | ||
496 | if !self.data.checkOnSave_enable { | ||
497 | return None; | ||
498 | } | ||
499 | let flycheck_config = match &self.data.checkOnSave_overrideCommand { | ||
500 | Some(args) if !args.is_empty() => { | ||
501 | let mut args = args.clone(); | ||
502 | let command = args.remove(0); | ||
503 | FlycheckConfig::CustomCommand { command, args } | ||
504 | } | ||
505 | Some(_) | None => FlycheckConfig::CargoCommand { | ||
506 | command: self.data.checkOnSave_command.clone(), | ||
507 | target_triple: self | ||
508 | .data | ||
509 | .checkOnSave_target | ||
510 | .clone() | ||
511 | .or(self.data.cargo_target.clone()), | ||
512 | all_targets: self.data.checkOnSave_allTargets, | ||
513 | no_default_features: self | ||
514 | .data | ||
515 | .checkOnSave_noDefaultFeatures | ||
516 | .unwrap_or(self.data.cargo_noDefaultFeatures), | ||
517 | all_features: self | ||
518 | .data | ||
519 | .checkOnSave_allFeatures | ||
520 | .unwrap_or(self.data.cargo_allFeatures), | ||
521 | features: self | ||
522 | .data | ||
523 | .checkOnSave_features | ||
524 | .clone() | ||
525 | .unwrap_or(self.data.cargo_features.clone()), | ||
526 | extra_args: self.data.checkOnSave_extraArgs.clone(), | ||
527 | }, | ||
528 | }; | ||
529 | Some(flycheck_config) | ||
530 | } | ||
531 | pub fn runnables(&self) -> RunnablesConfig { | ||
532 | RunnablesConfig { | ||
533 | override_cargo: self.data.runnables_overrideCargo.clone(), | ||
534 | cargo_extra_args: self.data.runnables_cargoExtraArgs.clone(), | ||
535 | } | ||
536 | } | ||
537 | pub fn inlay_hints(&self) -> InlayHintsConfig { | ||
538 | InlayHintsConfig { | ||
539 | type_hints: self.data.inlayHints_typeHints, | ||
540 | parameter_hints: self.data.inlayHints_parameterHints, | ||
541 | chaining_hints: self.data.inlayHints_chainingHints, | ||
542 | max_length: self.data.inlayHints_maxLength, | ||
543 | } | ||
544 | } | ||
545 | fn merge_behavior(&self) -> Option<MergeBehavior> { | ||
546 | match self.data.assist_importMergeBehavior { | ||
547 | MergeBehaviorDef::None => None, | ||
548 | MergeBehaviorDef::Full => Some(MergeBehavior::Full), | ||
549 | MergeBehaviorDef::Last => Some(MergeBehavior::Last), | ||
550 | } | ||
551 | } | ||
552 | pub fn completion(&self) -> CompletionConfig { | ||
553 | CompletionConfig { | ||
554 | enable_postfix_completions: self.data.completion_postfix_enable, | ||
555 | enable_autoimport_completions: self.data.completion_autoimport_enable | ||
556 | && completion_item_edit_resolve(&self.caps), | ||
557 | add_call_parenthesis: self.data.completion_addCallParenthesis, | ||
558 | add_call_argument_snippets: self.data.completion_addCallArgumentSnippets, | ||
559 | merge: self.merge_behavior(), | ||
560 | snippet_cap: SnippetCap::new(try_or!( | ||
561 | self.caps | ||
562 | .text_document | ||
563 | .as_ref()? | ||
564 | .completion | ||
565 | .as_ref()? | ||
566 | .completion_item | ||
567 | .as_ref()? | ||
568 | .snippet_support?, | ||
569 | false | ||
570 | )), | ||
571 | } | ||
572 | } | ||
573 | pub fn assist(&self) -> AssistConfig { | ||
574 | AssistConfig { | ||
575 | snippet_cap: SnippetCap::new(self.experimental("snippetTextEdit")), | ||
576 | allowed: None, | ||
577 | insert_use: InsertUseConfig { | ||
578 | merge: self.merge_behavior(), | ||
579 | prefix_kind: match self.data.assist_importPrefix { | ||
580 | ImportPrefixDef::Plain => PrefixKind::Plain, | ||
581 | ImportPrefixDef::ByCrate => PrefixKind::ByCrate, | ||
582 | ImportPrefixDef::BySelf => PrefixKind::BySelf, | ||
583 | }, | ||
584 | }, | ||
585 | } | ||
586 | } | ||
587 | pub fn call_info_full(&self) -> bool { | ||
588 | self.data.callInfo_full | ||
589 | } | ||
590 | pub fn lens(&self) -> LensConfig { | ||
591 | LensConfig { | ||
592 | run: self.data.lens_enable && self.data.lens_run, | ||
593 | debug: self.data.lens_enable && self.data.lens_debug, | ||
594 | implementations: self.data.lens_enable && self.data.lens_implementations, | ||
595 | method_refs: self.data.lens_enable && self.data.lens_methodReferences, | ||
596 | } | ||
597 | } | ||
598 | pub fn hover(&self) -> HoverConfig { | ||
599 | HoverConfig { | ||
600 | implementations: self.data.hoverActions_enable | ||
601 | && self.data.hoverActions_implementations, | ||
602 | run: self.data.hoverActions_enable && self.data.hoverActions_run, | ||
603 | debug: self.data.hoverActions_enable && self.data.hoverActions_debug, | ||
604 | goto_type_def: self.data.hoverActions_enable && self.data.hoverActions_gotoTypeDef, | ||
605 | links_in_hover: self.data.hoverActions_linksInHover, | ||
606 | markdown: try_or!( | ||
607 | self.caps | ||
608 | .text_document | ||
609 | .as_ref()? | ||
610 | .hover | ||
611 | .as_ref()? | ||
612 | .content_format | ||
613 | .as_ref()? | ||
614 | .as_slice(), | ||
615 | &[] | ||
616 | ) | ||
617 | .contains(&MarkupKind::Markdown), | ||
618 | } | ||
619 | } | ||
620 | pub fn semantic_tokens_refresh(&self) -> bool { | ||
621 | try_or!(self.caps.workspace.as_ref()?.semantic_tokens.as_ref()?.refresh_support?, false) | ||
622 | } | ||
623 | pub fn code_lens_refresh(&self) -> bool { | ||
624 | try_or!(self.caps.workspace.as_ref()?.code_lens.as_ref()?.refresh_support?, false) | ||
625 | } | ||
628 | } | 626 | } |
629 | 627 | ||
630 | #[derive(Deserialize)] | 628 | #[derive(Deserialize, Debug, Clone)] |
631 | #[serde(untagged)] | 629 | #[serde(untagged)] |
632 | enum ManifestOrProjectJson { | 630 | enum ManifestOrProjectJson { |
633 | Manifest(PathBuf), | 631 | Manifest(PathBuf), |
634 | ProjectJson(ProjectJsonData), | 632 | ProjectJson(ProjectJsonData), |
635 | } | 633 | } |
636 | 634 | ||
637 | #[derive(Deserialize)] | 635 | #[derive(Deserialize, Debug, Clone)] |
638 | #[serde(rename_all = "snake_case")] | 636 | #[serde(rename_all = "snake_case")] |
639 | enum MergeBehaviorDef { | 637 | enum MergeBehaviorDef { |
640 | None, | 638 | None, |
@@ -642,7 +640,7 @@ enum MergeBehaviorDef { | |||
642 | Last, | 640 | Last, |
643 | } | 641 | } |
644 | 642 | ||
645 | #[derive(Deserialize)] | 643 | #[derive(Deserialize, Debug, Clone)] |
646 | #[serde(rename_all = "snake_case")] | 644 | #[serde(rename_all = "snake_case")] |
647 | enum ImportPrefixDef { | 645 | enum ImportPrefixDef { |
648 | Plain, | 646 | Plain, |
@@ -654,15 +652,21 @@ macro_rules! _config_data { | |||
654 | (struct $name:ident { | 652 | (struct $name:ident { |
655 | $( | 653 | $( |
656 | $(#[doc=$doc:literal])* | 654 | $(#[doc=$doc:literal])* |
657 | $field:ident: $ty:ty = $default:expr, | 655 | $field:ident $(| $alias:ident)?: $ty:ty = $default:expr, |
658 | )* | 656 | )* |
659 | }) => { | 657 | }) => { |
660 | #[allow(non_snake_case)] | 658 | #[allow(non_snake_case)] |
659 | #[derive(Debug, Clone)] | ||
661 | struct $name { $($field: $ty,)* } | 660 | struct $name { $($field: $ty,)* } |
662 | impl $name { | 661 | impl $name { |
663 | fn from_json(mut json: serde_json::Value) -> $name { | 662 | fn from_json(mut json: serde_json::Value) -> $name { |
664 | $name {$( | 663 | $name {$( |
665 | $field: get_field(&mut json, stringify!($field), $default), | 664 | $field: get_field( |
665 | &mut json, | ||
666 | stringify!($field), | ||
667 | None$(.or(Some(stringify!($alias))))?, | ||
668 | $default, | ||
669 | ), | ||
666 | )*} | 670 | )*} |
667 | } | 671 | } |
668 | 672 | ||
@@ -694,14 +698,21 @@ use _config_data as config_data; | |||
694 | fn get_field<T: DeserializeOwned>( | 698 | fn get_field<T: DeserializeOwned>( |
695 | json: &mut serde_json::Value, | 699 | json: &mut serde_json::Value, |
696 | field: &'static str, | 700 | field: &'static str, |
701 | alias: Option<&'static str>, | ||
697 | default: &str, | 702 | default: &str, |
698 | ) -> T { | 703 | ) -> T { |
699 | let default = serde_json::from_str(default).unwrap(); | 704 | let default = serde_json::from_str(default).unwrap(); |
700 | 705 | ||
701 | let mut pointer = field.replace('_', "/"); | 706 | // XXX: check alias first, to work-around the VS Code where it pre-fills the |
702 | pointer.insert(0, '/'); | 707 | // defaults instead of sending an empty object. |
703 | json.pointer_mut(&pointer) | 708 | alias |
704 | .and_then(|it| serde_json::from_value(it.take()).ok()) | 709 | .into_iter() |
710 | .chain(iter::once(field)) | ||
711 | .find_map(move |field| { | ||
712 | let mut pointer = field.replace('_', "/"); | ||
713 | pointer.insert(0, '/'); | ||
714 | json.pointer_mut(&pointer).and_then(|it| serde_json::from_value(it.take()).ok()) | ||
715 | }) | ||
705 | .unwrap_or(default) | 716 | .unwrap_or(default) |
706 | } | 717 | } |
707 | 718 | ||
@@ -763,6 +774,9 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json | |||
763 | "Option<String>" => set! { | 774 | "Option<String>" => set! { |
764 | "type": ["null", "string"], | 775 | "type": ["null", "string"], |
765 | }, | 776 | }, |
777 | "Option<PathBuf>" => set! { | ||
778 | "type": ["null", "string"], | ||
779 | }, | ||
766 | "Option<bool>" => set! { | 780 | "Option<bool>" => set! { |
767 | "type": ["null", "boolean"], | 781 | "type": ["null", "boolean"], |
768 | }, | 782 | }, |
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 71dc56915..442fbd14c 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs | |||
@@ -22,6 +22,7 @@ use crate::{ | |||
22 | from_proto, | 22 | from_proto, |
23 | line_endings::LineEndings, | 23 | line_endings::LineEndings, |
24 | main_loop::Task, | 24 | main_loop::Task, |
25 | op_queue::OpQueue, | ||
25 | reload::SourceRootConfig, | 26 | reload::SourceRootConfig, |
26 | request_metrics::{LatestRequests, RequestMetrics}, | 27 | request_metrics::{LatestRequests, RequestMetrics}, |
27 | thread_pool::TaskPool, | 28 | thread_pool::TaskPool, |
@@ -67,7 +68,7 @@ pub(crate) struct GlobalState { | |||
67 | pub(crate) flycheck: Vec<FlycheckHandle>, | 68 | pub(crate) flycheck: Vec<FlycheckHandle>, |
68 | pub(crate) flycheck_sender: Sender<flycheck::Message>, | 69 | pub(crate) flycheck_sender: Sender<flycheck::Message>, |
69 | pub(crate) flycheck_receiver: Receiver<flycheck::Message>, | 70 | pub(crate) flycheck_receiver: Receiver<flycheck::Message>, |
70 | pub(crate) config: Config, | 71 | pub(crate) config: Arc<Config>, |
71 | pub(crate) analysis_host: AnalysisHost, | 72 | pub(crate) analysis_host: AnalysisHost, |
72 | pub(crate) diagnostics: DiagnosticCollection, | 73 | pub(crate) diagnostics: DiagnosticCollection, |
73 | pub(crate) mem_docs: FxHashMap<VfsPath, DocumentData>, | 74 | pub(crate) mem_docs: FxHashMap<VfsPath, DocumentData>, |
@@ -78,12 +79,13 @@ pub(crate) struct GlobalState { | |||
78 | pub(crate) source_root_config: SourceRootConfig, | 79 | pub(crate) source_root_config: SourceRootConfig, |
79 | pub(crate) proc_macro_client: Option<ProcMacroClient>, | 80 | pub(crate) proc_macro_client: Option<ProcMacroClient>, |
80 | pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>, | 81 | pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>, |
82 | pub(crate) fetch_workspaces_queue: OpQueue, | ||
81 | latest_requests: Arc<RwLock<LatestRequests>>, | 83 | latest_requests: Arc<RwLock<LatestRequests>>, |
82 | } | 84 | } |
83 | 85 | ||
84 | /// An immutable snapshot of the world's state at a point in time. | 86 | /// An immutable snapshot of the world's state at a point in time. |
85 | pub(crate) struct GlobalStateSnapshot { | 87 | pub(crate) struct GlobalStateSnapshot { |
86 | pub(crate) config: Config, | 88 | pub(crate) config: Arc<Config>, |
87 | pub(crate) analysis: Analysis, | 89 | pub(crate) analysis: Analysis, |
88 | pub(crate) check_fixes: CheckFixes, | 90 | pub(crate) check_fixes: CheckFixes, |
89 | pub(crate) latest_requests: Arc<RwLock<LatestRequests>>, | 91 | pub(crate) latest_requests: Arc<RwLock<LatestRequests>>, |
@@ -109,7 +111,7 @@ impl GlobalState { | |||
109 | Handle { handle, receiver } | 111 | Handle { handle, receiver } |
110 | }; | 112 | }; |
111 | 113 | ||
112 | let analysis_host = AnalysisHost::new(config.lru_capacity); | 114 | let analysis_host = AnalysisHost::new(config.lru_capacity()); |
113 | let (flycheck_sender, flycheck_receiver) = unbounded(); | 115 | let (flycheck_sender, flycheck_receiver) = unbounded(); |
114 | GlobalState { | 116 | GlobalState { |
115 | sender, | 117 | sender, |
@@ -119,7 +121,7 @@ impl GlobalState { | |||
119 | flycheck: Vec::new(), | 121 | flycheck: Vec::new(), |
120 | flycheck_sender, | 122 | flycheck_sender, |
121 | flycheck_receiver, | 123 | flycheck_receiver, |
122 | config, | 124 | config: Arc::new(config), |
123 | analysis_host, | 125 | analysis_host, |
124 | diagnostics: Default::default(), | 126 | diagnostics: Default::default(), |
125 | mem_docs: FxHashMap::default(), | 127 | mem_docs: FxHashMap::default(), |
@@ -130,6 +132,7 @@ impl GlobalState { | |||
130 | source_root_config: SourceRootConfig::default(), | 132 | source_root_config: SourceRootConfig::default(), |
131 | proc_macro_client: None, | 133 | proc_macro_client: None, |
132 | workspaces: Arc::new(Vec::new()), | 134 | workspaces: Arc::new(Vec::new()), |
135 | fetch_workspaces_queue: OpQueue::default(), | ||
133 | latest_requests: Default::default(), | 136 | latest_requests: Default::default(), |
134 | } | 137 | } |
135 | } | 138 | } |
@@ -184,7 +187,7 @@ impl GlobalState { | |||
184 | 187 | ||
185 | pub(crate) fn snapshot(&self) -> GlobalStateSnapshot { | 188 | pub(crate) fn snapshot(&self) -> GlobalStateSnapshot { |
186 | GlobalStateSnapshot { | 189 | GlobalStateSnapshot { |
187 | config: self.config.clone(), | 190 | config: Arc::clone(&self.config), |
188 | workspaces: Arc::clone(&self.workspaces), | 191 | workspaces: Arc::clone(&self.workspaces), |
189 | analysis: self.analysis_host.analysis(), | 192 | analysis: self.analysis_host.analysis(), |
190 | vfs: Arc::clone(&self.vfs), | 193 | vfs: Arc::clone(&self.vfs), |
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index bfd92159c..dc81f55d6 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -9,9 +9,8 @@ use std::{ | |||
9 | }; | 9 | }; |
10 | 10 | ||
11 | use ide::{ | 11 | use ide::{ |
12 | AssistConfig, CompletionResolveCapability, FileId, FilePosition, FileRange, HoverAction, | 12 | FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, LineIndex, NavigationTarget, |
13 | HoverGotoTypeData, LineIndex, NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, | 13 | Query, RangeInfo, Runnable, RunnableKind, SearchScope, SourceChange, SymbolKind, TextEdit, |
14 | SearchScope, SourceChange, SymbolKind, TextEdit, | ||
15 | }; | 14 | }; |
16 | use itertools::Itertools; | 15 | use itertools::Itertools; |
17 | use lsp_server::ErrorCode; | 16 | use lsp_server::ErrorCode; |
@@ -19,8 +18,8 @@ use lsp_types::{ | |||
19 | CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem, | 18 | CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem, |
20 | CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams, | 19 | CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams, |
21 | CodeActionKind, CodeLens, Command, CompletionItem, Diagnostic, DiagnosticTag, | 20 | CodeActionKind, CodeLens, Command, CompletionItem, Diagnostic, DiagnosticTag, |
22 | DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange, FoldingRangeParams, | 21 | DocumentFormattingParams, DocumentHighlight, FoldingRange, FoldingRangeParams, HoverContents, |
23 | HoverContents, Location, NumberOrString, Position, PrepareRenameResponse, Range, RenameParams, | 22 | Location, NumberOrString, Position, PrepareRenameResponse, Range, RenameParams, |
24 | SemanticTokensDeltaParams, SemanticTokensFullDeltaResult, SemanticTokensParams, | 23 | SemanticTokensDeltaParams, SemanticTokensFullDeltaResult, SemanticTokensParams, |
25 | SemanticTokensRangeParams, SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation, | 24 | SemanticTokensRangeParams, SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation, |
26 | SymbolTag, TextDocumentIdentifier, TextDocumentPositionParams, Url, WorkspaceEdit, | 25 | SymbolTag, TextDocumentIdentifier, TextDocumentPositionParams, Url, WorkspaceEdit, |
@@ -31,12 +30,13 @@ use serde_json::to_value; | |||
31 | use stdx::{format_to, split_once}; | 30 | use stdx::{format_to, split_once}; |
32 | use syntax::{algo, ast, AstNode, TextRange, TextSize}; | 31 | use syntax::{algo, ast, AstNode, TextRange, TextSize}; |
33 | 32 | ||
34 | use crate::diff::diff; | ||
35 | use crate::{ | 33 | use crate::{ |
36 | cargo_target_spec::CargoTargetSpec, | 34 | cargo_target_spec::CargoTargetSpec, |
37 | config::RustfmtConfig, | 35 | config::RustfmtConfig, |
36 | diff::diff, | ||
38 | from_json, from_proto, | 37 | from_json, from_proto, |
39 | global_state::{GlobalState, GlobalStateSnapshot}, | 38 | global_state::{GlobalState, GlobalStateSnapshot}, |
39 | line_endings::LineEndings, | ||
40 | lsp_ext::{self, InlayHint, InlayHintsParams}, | 40 | lsp_ext::{self, InlayHint, InlayHintsParams}, |
41 | lsp_utils::all_edits_are_disjoint, | 41 | lsp_utils::all_edits_are_disjoint, |
42 | to_proto, LspError, Result, | 42 | to_proto, LspError, Result, |
@@ -280,7 +280,7 @@ pub(crate) fn handle_document_symbol( | |||
280 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 280 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
281 | let line_index = snap.analysis.file_line_index(file_id)?; | 281 | let line_index = snap.analysis.file_line_index(file_id)?; |
282 | 282 | ||
283 | let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new(); | 283 | let mut parents: Vec<(lsp_types::DocumentSymbol, Option<usize>)> = Vec::new(); |
284 | 284 | ||
285 | for symbol in snap.analysis.file_structure(file_id)? { | 285 | for symbol in snap.analysis.file_structure(file_id)? { |
286 | let mut tags = Vec::new(); | 286 | let mut tags = Vec::new(); |
@@ -289,7 +289,7 @@ pub(crate) fn handle_document_symbol( | |||
289 | }; | 289 | }; |
290 | 290 | ||
291 | #[allow(deprecated)] | 291 | #[allow(deprecated)] |
292 | let doc_symbol = DocumentSymbol { | 292 | let doc_symbol = lsp_types::DocumentSymbol { |
293 | name: symbol.label, | 293 | name: symbol.label, |
294 | detail: symbol.detail, | 294 | detail: symbol.detail, |
295 | kind: to_proto::symbol_kind(symbol.kind), | 295 | kind: to_proto::symbol_kind(symbol.kind), |
@@ -333,7 +333,7 @@ pub(crate) fn handle_document_symbol( | |||
333 | return Ok(Some(res)); | 333 | return Ok(Some(res)); |
334 | 334 | ||
335 | fn flatten_document_symbol( | 335 | fn flatten_document_symbol( |
336 | symbol: &DocumentSymbol, | 336 | symbol: &lsp_types::DocumentSymbol, |
337 | container_name: Option<String>, | 337 | container_name: Option<String>, |
338 | url: &Url, | 338 | url: &Url, |
339 | res: &mut Vec<SymbolInformation>, | 339 | res: &mut Vec<SymbolInformation>, |
@@ -565,7 +565,7 @@ pub(crate) fn handle_runnables( | |||
565 | } | 565 | } |
566 | 566 | ||
567 | // Add `cargo check` and `cargo test` for all targets of the whole package | 567 | // Add `cargo check` and `cargo test` for all targets of the whole package |
568 | let config = &snap.config.runnables; | 568 | let config = snap.config.runnables(); |
569 | match cargo_spec { | 569 | match cargo_spec { |
570 | Some(spec) => { | 570 | Some(spec) => { |
571 | for &cmd in ["check", "test"].iter() { | 571 | for &cmd in ["check", "test"].iter() { |
@@ -596,9 +596,9 @@ pub(crate) fn handle_runnables( | |||
596 | kind: lsp_ext::RunnableKind::Cargo, | 596 | kind: lsp_ext::RunnableKind::Cargo, |
597 | args: lsp_ext::CargoRunnable { | 597 | args: lsp_ext::CargoRunnable { |
598 | workspace_root: None, | 598 | workspace_root: None, |
599 | override_cargo: config.override_cargo.clone(), | 599 | override_cargo: config.override_cargo, |
600 | cargo_args: vec!["check".to_string(), "--workspace".to_string()], | 600 | cargo_args: vec!["check".to_string(), "--workspace".to_string()], |
601 | cargo_extra_args: config.cargo_extra_args.clone(), | 601 | cargo_extra_args: config.cargo_extra_args, |
602 | executable_args: Vec::new(), | 602 | executable_args: Vec::new(), |
603 | expect_test: None, | 603 | expect_test: None, |
604 | }, | 604 | }, |
@@ -637,7 +637,8 @@ pub(crate) fn handle_completion( | |||
637 | return Ok(None); | 637 | return Ok(None); |
638 | } | 638 | } |
639 | 639 | ||
640 | let items = match snap.analysis.completions(&snap.config.completion, position)? { | 640 | let completion_config = &snap.config.completion(); |
641 | let items = match snap.analysis.completions(completion_config, position)? { | ||
641 | None => return Ok(None), | 642 | None => return Ok(None), |
642 | Some(items) => items, | 643 | Some(items) => items, |
643 | }; | 644 | }; |
@@ -650,10 +651,9 @@ pub(crate) fn handle_completion( | |||
650 | let mut new_completion_items = | 651 | let mut new_completion_items = |
651 | to_proto::completion_item(&line_index, line_endings, item.clone()); | 652 | to_proto::completion_item(&line_index, line_endings, item.clone()); |
652 | 653 | ||
653 | if snap.config.completion.resolve_additional_edits_lazily() { | 654 | if completion_config.enable_autoimport_completions { |
654 | for new_item in &mut new_completion_items { | 655 | for new_item in &mut new_completion_items { |
655 | let _ = fill_resolve_data(&mut new_item.data, &item, &text_document_position) | 656 | fill_resolve_data(&mut new_item.data, &item, &text_document_position); |
656 | .take(); | ||
657 | } | 657 | } |
658 | } | 658 | } |
659 | 659 | ||
@@ -679,16 +679,6 @@ pub(crate) fn handle_completion_resolve( | |||
679 | .into()); | 679 | .into()); |
680 | } | 680 | } |
681 | 681 | ||
682 | // FIXME resolve the other capabilities also? | ||
683 | if !snap | ||
684 | .config | ||
685 | .completion | ||
686 | .active_resolve_capabilities | ||
687 | .contains(&CompletionResolveCapability::AdditionalTextEdits) | ||
688 | { | ||
689 | return Ok(original_completion); | ||
690 | } | ||
691 | |||
692 | let resolve_data = match original_completion | 682 | let resolve_data = match original_completion |
693 | .data | 683 | .data |
694 | .take() | 684 | .take() |
@@ -707,7 +697,7 @@ pub(crate) fn handle_completion_resolve( | |||
707 | let additional_edits = snap | 697 | let additional_edits = snap |
708 | .analysis | 698 | .analysis |
709 | .resolve_completion_edits( | 699 | .resolve_completion_edits( |
710 | &snap.config.completion, | 700 | &snap.config.completion(), |
711 | FilePosition { file_id, offset }, | 701 | FilePosition { file_id, offset }, |
712 | &resolve_data.full_import_path, | 702 | &resolve_data.full_import_path, |
713 | resolve_data.imported_name, | 703 | resolve_data.imported_name, |
@@ -763,7 +753,7 @@ pub(crate) fn handle_signature_help( | |||
763 | Some(it) => it, | 753 | Some(it) => it, |
764 | None => return Ok(None), | 754 | None => return Ok(None), |
765 | }; | 755 | }; |
766 | let concise = !snap.config.call_info_full; | 756 | let concise = !snap.config.call_info_full(); |
767 | let res = | 757 | let res = |
768 | to_proto::signature_help(call_info, concise, snap.config.signature_help_label_offsets()); | 758 | to_proto::signature_help(call_info, concise, snap.config.signature_help_label_offsets()); |
769 | Ok(Some(res)) | 759 | Ok(Some(res)) |
@@ -775,14 +765,12 @@ pub(crate) fn handle_hover( | |||
775 | ) -> Result<Option<lsp_ext::Hover>> { | 765 | ) -> Result<Option<lsp_ext::Hover>> { |
776 | let _p = profile::span("handle_hover"); | 766 | let _p = profile::span("handle_hover"); |
777 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; | 767 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; |
778 | let info = match snap.analysis.hover( | 768 | let hover_config = snap.config.hover(); |
779 | position, | 769 | let info = |
780 | snap.config.hover.links_in_hover, | 770 | match snap.analysis.hover(position, hover_config.links_in_hover, hover_config.markdown)? { |
781 | snap.config.hover.markdown, | 771 | None => return Ok(None), |
782 | )? { | 772 | Some(info) => info, |
783 | None => return Ok(None), | 773 | }; |
784 | Some(info) => info, | ||
785 | }; | ||
786 | let line_index = snap.analysis.file_line_index(position.file_id)?; | 774 | let line_index = snap.analysis.file_line_index(position.file_id)?; |
787 | let range = to_proto::range(&line_index, info.range); | 775 | let range = to_proto::range(&line_index, info.range); |
788 | let hover = lsp_ext::Hover { | 776 | let hover = lsp_ext::Hover { |
@@ -803,7 +791,8 @@ pub(crate) fn handle_prepare_rename( | |||
803 | let _p = profile::span("handle_prepare_rename"); | 791 | let _p = profile::span("handle_prepare_rename"); |
804 | let position = from_proto::file_position(&snap, params)?; | 792 | let position = from_proto::file_position(&snap, params)?; |
805 | 793 | ||
806 | let change = snap.analysis.prepare_rename(position)??; | 794 | let change = snap.analysis.prepare_rename(position)?.map_err(to_proto::rename_error)?; |
795 | |||
807 | let line_index = snap.analysis.file_line_index(position.file_id)?; | 796 | let line_index = snap.analysis.file_line_index(position.file_id)?; |
808 | let range = to_proto::range(&line_index, change.range); | 797 | let range = to_proto::range(&line_index, change.range); |
809 | Ok(Some(PrepareRenameResponse::Range(range))) | 798 | Ok(Some(PrepareRenameResponse::Range(range))) |
@@ -816,15 +805,8 @@ pub(crate) fn handle_rename( | |||
816 | let _p = profile::span("handle_rename"); | 805 | let _p = profile::span("handle_rename"); |
817 | let position = from_proto::file_position(&snap, params.text_document_position)?; | 806 | let position = from_proto::file_position(&snap, params.text_document_position)?; |
818 | 807 | ||
819 | if params.new_name.is_empty() { | 808 | let change = |
820 | return Err(LspError::new( | 809 | snap.analysis.rename(position, &*params.new_name)?.map_err(to_proto::rename_error)?; |
821 | ErrorCode::InvalidParams as i32, | ||
822 | "New Name cannot be empty".into(), | ||
823 | ) | ||
824 | .into()); | ||
825 | } | ||
826 | |||
827 | let change = snap.analysis.rename(position, &*params.new_name)??; | ||
828 | let workspace_edit = to_proto::workspace_edit(&snap, change.info)?; | 810 | let workspace_edit = to_proto::workspace_edit(&snap, change.info)?; |
829 | Ok(Some(workspace_edit)) | 811 | Ok(Some(workspace_edit)) |
830 | } | 812 | } |
@@ -842,14 +824,15 @@ pub(crate) fn handle_references( | |||
842 | }; | 824 | }; |
843 | 825 | ||
844 | let locations = if params.context.include_declaration { | 826 | let locations = if params.context.include_declaration { |
845 | refs.into_iter() | 827 | refs.references_with_declaration() |
846 | .filter_map(|reference| to_proto::location(&snap, reference.file_range).ok()) | 828 | .file_ranges() |
829 | .filter_map(|frange| to_proto::location(&snap, frange).ok()) | ||
847 | .collect() | 830 | .collect() |
848 | } else { | 831 | } else { |
849 | // Only iterate over the references if include_declaration was false | 832 | // Only iterate over the references if include_declaration was false |
850 | refs.references() | 833 | refs.references() |
851 | .iter() | 834 | .file_ranges() |
852 | .filter_map(|reference| to_proto::location(&snap, reference.file_range).ok()) | 835 | .filter_map(|frange| to_proto::location(&snap, frange).ok()) |
853 | .collect() | 836 | .collect() |
854 | }; | 837 | }; |
855 | 838 | ||
@@ -868,7 +851,7 @@ pub(crate) fn handle_formatting( | |||
868 | let file_line_index = snap.analysis.file_line_index(file_id)?; | 851 | let file_line_index = snap.analysis.file_line_index(file_id)?; |
869 | let file_line_endings = snap.file_line_endings(file_id); | 852 | let file_line_endings = snap.file_line_endings(file_id); |
870 | 853 | ||
871 | let mut rustfmt = match &snap.config.rustfmt { | 854 | let mut rustfmt = match snap.config.rustfmt() { |
872 | RustfmtConfig::Rustfmt { extra_args } => { | 855 | RustfmtConfig::Rustfmt { extra_args } => { |
873 | let mut cmd = process::Command::new(toolchain::rustfmt()); | 856 | let mut cmd = process::Command::new(toolchain::rustfmt()); |
874 | cmd.args(extra_args); | 857 | cmd.args(extra_args); |
@@ -924,14 +907,25 @@ pub(crate) fn handle_formatting( | |||
924 | } | 907 | } |
925 | } | 908 | } |
926 | 909 | ||
927 | if *file == captured_stdout { | 910 | let (new_text, new_line_endings) = LineEndings::normalize(captured_stdout); |
911 | |||
912 | if file_line_endings != new_line_endings { | ||
913 | // If line endings are different, send the entire file. | ||
914 | // Diffing would not work here, as the line endings might be the only | ||
915 | // difference. | ||
916 | Ok(Some(to_proto::text_edit_vec( | ||
917 | &file_line_index, | ||
918 | new_line_endings, | ||
919 | TextEdit::replace(TextRange::up_to(TextSize::of(&*file)), new_text), | ||
920 | ))) | ||
921 | } else if *file == new_text { | ||
928 | // The document is already formatted correctly -- no edits needed. | 922 | // The document is already formatted correctly -- no edits needed. |
929 | Ok(None) | 923 | Ok(None) |
930 | } else { | 924 | } else { |
931 | Ok(Some(to_proto::text_edit_vec( | 925 | Ok(Some(to_proto::text_edit_vec( |
932 | &file_line_index, | 926 | &file_line_index, |
933 | file_line_endings, | 927 | file_line_endings, |
934 | diff(&file, &captured_stdout), | 928 | diff(&file, &new_text), |
935 | ))) | 929 | ))) |
936 | } | 930 | } |
937 | } | 931 | } |
@@ -953,14 +947,12 @@ pub(crate) fn handle_code_action( | |||
953 | let range = from_proto::text_range(&line_index, params.range); | 947 | let range = from_proto::text_range(&line_index, params.range); |
954 | let frange = FileRange { file_id, range }; | 948 | let frange = FileRange { file_id, range }; |
955 | 949 | ||
956 | let assists_config = AssistConfig { | 950 | let mut assists_config = snap.config.assist(); |
957 | allowed: params | 951 | assists_config.allowed = params |
958 | .clone() | 952 | .clone() |
959 | .context | 953 | .context |
960 | .only | 954 | .only |
961 | .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect()), | 955 | .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect()); |
962 | ..snap.config.assist | ||
963 | }; | ||
964 | 956 | ||
965 | let mut res: Vec<lsp_ext::CodeAction> = Vec::new(); | 957 | let mut res: Vec<lsp_ext::CodeAction> = Vec::new(); |
966 | 958 | ||
@@ -995,7 +987,7 @@ fn add_quick_fixes( | |||
995 | line_index: &Arc<LineIndex>, | 987 | line_index: &Arc<LineIndex>, |
996 | acc: &mut Vec<lsp_ext::CodeAction>, | 988 | acc: &mut Vec<lsp_ext::CodeAction>, |
997 | ) -> Result<()> { | 989 | ) -> Result<()> { |
998 | let diagnostics = snap.analysis.diagnostics(&snap.config.diagnostics, frange.file_id)?; | 990 | let diagnostics = snap.analysis.diagnostics(&snap.config.diagnostics(), frange.file_id)?; |
999 | 991 | ||
1000 | for fix in diagnostics | 992 | for fix in diagnostics |
1001 | .into_iter() | 993 | .into_iter() |
@@ -1024,7 +1016,7 @@ fn add_quick_fixes( | |||
1024 | } | 1016 | } |
1025 | 1017 | ||
1026 | pub(crate) fn handle_code_action_resolve( | 1018 | pub(crate) fn handle_code_action_resolve( |
1027 | mut snap: GlobalStateSnapshot, | 1019 | snap: GlobalStateSnapshot, |
1028 | mut code_action: lsp_ext::CodeAction, | 1020 | mut code_action: lsp_ext::CodeAction, |
1029 | ) -> Result<lsp_ext::CodeAction> { | 1021 | ) -> Result<lsp_ext::CodeAction> { |
1030 | let _p = profile::span("handle_code_action_resolve"); | 1022 | let _p = profile::span("handle_code_action_resolve"); |
@@ -1038,13 +1030,14 @@ pub(crate) fn handle_code_action_resolve( | |||
1038 | let range = from_proto::text_range(&line_index, params.code_action_params.range); | 1030 | let range = from_proto::text_range(&line_index, params.code_action_params.range); |
1039 | let frange = FileRange { file_id, range }; | 1031 | let frange = FileRange { file_id, range }; |
1040 | 1032 | ||
1041 | snap.config.assist.allowed = params | 1033 | let mut assists_config = snap.config.assist(); |
1034 | assists_config.allowed = params | ||
1042 | .code_action_params | 1035 | .code_action_params |
1043 | .context | 1036 | .context |
1044 | .only | 1037 | .only |
1045 | .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect()); | 1038 | .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect()); |
1046 | 1039 | ||
1047 | let assists = snap.analysis.assists(&snap.config.assist, true, frange)?; | 1040 | let assists = snap.analysis.assists(&assists_config, true, frange)?; |
1048 | let (id, index) = split_once(¶ms.id, ':').unwrap(); | 1041 | let (id, index) = split_once(¶ms.id, ':').unwrap(); |
1049 | let index = index.parse::<usize>().unwrap(); | 1042 | let index = index.parse::<usize>().unwrap(); |
1050 | let assist = &assists[index]; | 1043 | let assist = &assists[index]; |
@@ -1061,7 +1054,8 @@ pub(crate) fn handle_code_lens( | |||
1061 | let _p = profile::span("handle_code_lens"); | 1054 | let _p = profile::span("handle_code_lens"); |
1062 | let mut lenses: Vec<CodeLens> = Default::default(); | 1055 | let mut lenses: Vec<CodeLens> = Default::default(); |
1063 | 1056 | ||
1064 | if snap.config.lens.none() { | 1057 | let lens_config = snap.config.lens(); |
1058 | if lens_config.none() { | ||
1065 | // early return before any db query! | 1059 | // early return before any db query! |
1066 | return Ok(Some(lenses)); | 1060 | return Ok(Some(lenses)); |
1067 | } | 1061 | } |
@@ -1070,7 +1064,7 @@ pub(crate) fn handle_code_lens( | |||
1070 | let line_index = snap.analysis.file_line_index(file_id)?; | 1064 | let line_index = snap.analysis.file_line_index(file_id)?; |
1071 | let cargo_spec = CargoTargetSpec::for_file(&snap, file_id)?; | 1065 | let cargo_spec = CargoTargetSpec::for_file(&snap, file_id)?; |
1072 | 1066 | ||
1073 | if snap.config.lens.runnable() { | 1067 | if lens_config.runnable() { |
1074 | // Gather runnables | 1068 | // Gather runnables |
1075 | for runnable in snap.analysis.runnables(file_id)? { | 1069 | for runnable in snap.analysis.runnables(file_id)? { |
1076 | if should_skip_target(&runnable, cargo_spec.as_ref()) { | 1070 | if should_skip_target(&runnable, cargo_spec.as_ref()) { |
@@ -1080,7 +1074,7 @@ pub(crate) fn handle_code_lens( | |||
1080 | let action = runnable.action(); | 1074 | let action = runnable.action(); |
1081 | let range = to_proto::range(&line_index, runnable.nav.full_range); | 1075 | let range = to_proto::range(&line_index, runnable.nav.full_range); |
1082 | let r = to_proto::runnable(&snap, file_id, runnable)?; | 1076 | let r = to_proto::runnable(&snap, file_id, runnable)?; |
1083 | if snap.config.lens.run { | 1077 | if lens_config.run { |
1084 | let lens = CodeLens { | 1078 | let lens = CodeLens { |
1085 | range, | 1079 | range, |
1086 | command: Some(run_single_command(&r, action.run_title)), | 1080 | command: Some(run_single_command(&r, action.run_title)), |
@@ -1089,7 +1083,7 @@ pub(crate) fn handle_code_lens( | |||
1089 | lenses.push(lens); | 1083 | lenses.push(lens); |
1090 | } | 1084 | } |
1091 | 1085 | ||
1092 | if action.debugee && snap.config.lens.debug { | 1086 | if action.debugee && lens_config.debug { |
1093 | let debug_lens = | 1087 | let debug_lens = |
1094 | CodeLens { range, command: Some(debug_single_command(&r)), data: None }; | 1088 | CodeLens { range, command: Some(debug_single_command(&r)), data: None }; |
1095 | lenses.push(debug_lens); | 1089 | lenses.push(debug_lens); |
@@ -1097,7 +1091,7 @@ pub(crate) fn handle_code_lens( | |||
1097 | } | 1091 | } |
1098 | } | 1092 | } |
1099 | 1093 | ||
1100 | if snap.config.lens.implementations { | 1094 | if lens_config.implementations { |
1101 | // Handle impls | 1095 | // Handle impls |
1102 | lenses.extend( | 1096 | lenses.extend( |
1103 | snap.analysis | 1097 | snap.analysis |
@@ -1132,7 +1126,7 @@ pub(crate) fn handle_code_lens( | |||
1132 | ); | 1126 | ); |
1133 | } | 1127 | } |
1134 | 1128 | ||
1135 | if snap.config.lens.references() { | 1129 | if lens_config.references() { |
1136 | lenses.extend(snap.analysis.find_all_methods(file_id)?.into_iter().map(|it| { | 1130 | lenses.extend(snap.analysis.find_all_methods(file_id)?.into_iter().map(|it| { |
1137 | let range = to_proto::range(&line_index, it.range); | 1131 | let range = to_proto::range(&line_index, it.range); |
1138 | let position = to_proto::position(&line_index, it.range.start()); | 1132 | let position = to_proto::position(&line_index, it.range.start()); |
@@ -1194,8 +1188,8 @@ pub(crate) fn handle_code_lens_resolve( | |||
1194 | .unwrap_or(None) | 1188 | .unwrap_or(None) |
1195 | .map(|r| { | 1189 | .map(|r| { |
1196 | r.references() | 1190 | r.references() |
1197 | .iter() | 1191 | .file_ranges() |
1198 | .filter_map(|it| to_proto::location(&snap, it.file_range).ok()) | 1192 | .filter_map(|frange| to_proto::location(&snap, frange).ok()) |
1199 | .collect_vec() | 1193 | .collect_vec() |
1200 | }) | 1194 | }) |
1201 | .unwrap_or_default(); | 1195 | .unwrap_or_default(); |
@@ -1239,13 +1233,19 @@ pub(crate) fn handle_document_highlight( | |||
1239 | }; | 1233 | }; |
1240 | 1234 | ||
1241 | let res = refs | 1235 | let res = refs |
1242 | .into_iter() | 1236 | .references_with_declaration() |
1243 | .filter(|reference| reference.file_range.file_id == position.file_id) | 1237 | .references |
1244 | .map(|reference| DocumentHighlight { | 1238 | .get(&position.file_id) |
1245 | range: to_proto::range(&line_index, reference.file_range.range), | 1239 | .map(|file_refs| { |
1246 | kind: reference.access.map(to_proto::document_highlight_kind), | 1240 | file_refs |
1241 | .into_iter() | ||
1242 | .map(|r| DocumentHighlight { | ||
1243 | range: to_proto::range(&line_index, r.range), | ||
1244 | kind: r.access.map(to_proto::document_highlight_kind), | ||
1245 | }) | ||
1246 | .collect() | ||
1247 | }) | 1247 | }) |
1248 | .collect(); | 1248 | .unwrap_or_default(); |
1249 | Ok(Some(res)) | 1249 | Ok(Some(res)) |
1250 | } | 1250 | } |
1251 | 1251 | ||
@@ -1278,7 +1278,7 @@ pub(crate) fn publish_diagnostics( | |||
1278 | 1278 | ||
1279 | let diagnostics: Vec<Diagnostic> = snap | 1279 | let diagnostics: Vec<Diagnostic> = snap |
1280 | .analysis | 1280 | .analysis |
1281 | .diagnostics(&snap.config.diagnostics, file_id)? | 1281 | .diagnostics(&snap.config.diagnostics(), file_id)? |
1282 | .into_iter() | 1282 | .into_iter() |
1283 | .map(|d| Diagnostic { | 1283 | .map(|d| Diagnostic { |
1284 | range: to_proto::range(&line_index, d.range), | 1284 | range: to_proto::range(&line_index, d.range), |
@@ -1311,7 +1311,7 @@ pub(crate) fn handle_inlay_hints( | |||
1311 | let line_index = snap.analysis.file_line_index(file_id)?; | 1311 | let line_index = snap.analysis.file_line_index(file_id)?; |
1312 | Ok(snap | 1312 | Ok(snap |
1313 | .analysis | 1313 | .analysis |
1314 | .inlay_hints(file_id, &snap.config.inlay_hints)? | 1314 | .inlay_hints(file_id, &snap.config.inlay_hints())? |
1315 | .into_iter() | 1315 | .into_iter() |
1316 | .map(|it| to_proto::inlay_hint(&line_index, it)) | 1316 | .map(|it| to_proto::inlay_hint(&line_index, it)) |
1317 | .collect()) | 1317 | .collect()) |
@@ -1581,7 +1581,7 @@ fn show_impl_command_link( | |||
1581 | snap: &GlobalStateSnapshot, | 1581 | snap: &GlobalStateSnapshot, |
1582 | position: &FilePosition, | 1582 | position: &FilePosition, |
1583 | ) -> Option<lsp_ext::CommandLinkGroup> { | 1583 | ) -> Option<lsp_ext::CommandLinkGroup> { |
1584 | if snap.config.hover.implementations { | 1584 | if snap.config.hover().implementations { |
1585 | if let Some(nav_data) = snap.analysis.goto_implementation(*position).unwrap_or(None) { | 1585 | if let Some(nav_data) = snap.analysis.goto_implementation(*position).unwrap_or(None) { |
1586 | let uri = to_proto::url(snap, position.file_id); | 1586 | let uri = to_proto::url(snap, position.file_id); |
1587 | let line_index = snap.analysis.file_line_index(position.file_id).ok()?; | 1587 | let line_index = snap.analysis.file_line_index(position.file_id).ok()?; |
@@ -1609,7 +1609,8 @@ fn runnable_action_links( | |||
1609 | runnable: Runnable, | 1609 | runnable: Runnable, |
1610 | ) -> Option<lsp_ext::CommandLinkGroup> { | 1610 | ) -> Option<lsp_ext::CommandLinkGroup> { |
1611 | let cargo_spec = CargoTargetSpec::for_file(&snap, file_id).ok()?; | 1611 | let cargo_spec = CargoTargetSpec::for_file(&snap, file_id).ok()?; |
1612 | if !snap.config.hover.runnable() || should_skip_target(&runnable, cargo_spec.as_ref()) { | 1612 | let hover_config = snap.config.hover(); |
1613 | if !hover_config.runnable() || should_skip_target(&runnable, cargo_spec.as_ref()) { | ||
1613 | return None; | 1614 | return None; |
1614 | } | 1615 | } |
1615 | 1616 | ||
@@ -1617,12 +1618,12 @@ fn runnable_action_links( | |||
1617 | to_proto::runnable(snap, file_id, runnable).ok().map(|r| { | 1618 | to_proto::runnable(snap, file_id, runnable).ok().map(|r| { |
1618 | let mut group = lsp_ext::CommandLinkGroup::default(); | 1619 | let mut group = lsp_ext::CommandLinkGroup::default(); |
1619 | 1620 | ||
1620 | if snap.config.hover.run { | 1621 | if hover_config.run { |
1621 | let run_command = run_single_command(&r, action.run_title); | 1622 | let run_command = run_single_command(&r, action.run_title); |
1622 | group.commands.push(to_command_link(run_command, r.label.clone())); | 1623 | group.commands.push(to_command_link(run_command, r.label.clone())); |
1623 | } | 1624 | } |
1624 | 1625 | ||
1625 | if snap.config.hover.debug { | 1626 | if hover_config.debug { |
1626 | let dbg_command = debug_single_command(&r); | 1627 | let dbg_command = debug_single_command(&r); |
1627 | group.commands.push(to_command_link(dbg_command, r.label)); | 1628 | group.commands.push(to_command_link(dbg_command, r.label)); |
1628 | } | 1629 | } |
@@ -1635,7 +1636,7 @@ fn goto_type_action_links( | |||
1635 | snap: &GlobalStateSnapshot, | 1636 | snap: &GlobalStateSnapshot, |
1636 | nav_targets: &[HoverGotoTypeData], | 1637 | nav_targets: &[HoverGotoTypeData], |
1637 | ) -> Option<lsp_ext::CommandLinkGroup> { | 1638 | ) -> Option<lsp_ext::CommandLinkGroup> { |
1638 | if !snap.config.hover.goto_type_def || nav_targets.is_empty() { | 1639 | if !snap.config.hover().goto_type_def || nav_targets.is_empty() { |
1639 | return None; | 1640 | return None; |
1640 | } | 1641 | } |
1641 | 1642 | ||
@@ -1656,7 +1657,7 @@ fn prepare_hover_actions( | |||
1656 | file_id: FileId, | 1657 | file_id: FileId, |
1657 | actions: &[HoverAction], | 1658 | actions: &[HoverAction], |
1658 | ) -> Vec<lsp_ext::CommandLinkGroup> { | 1659 | ) -> Vec<lsp_ext::CommandLinkGroup> { |
1659 | if snap.config.hover.none() || !snap.config.hover_actions() { | 1660 | if snap.config.hover().none() || !snap.config.hover_actions() { |
1660 | return Vec::new(); | 1661 | return Vec::new(); |
1661 | } | 1662 | } |
1662 | 1663 | ||
diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs index c9494e300..2207b9a87 100644 --- a/crates/rust-analyzer/src/lib.rs +++ b/crates/rust-analyzer/src/lib.rs | |||
@@ -35,6 +35,7 @@ mod lsp_utils; | |||
35 | mod thread_pool; | 35 | mod thread_pool; |
36 | mod document; | 36 | mod document; |
37 | mod diff; | 37 | mod diff; |
38 | mod op_queue; | ||
38 | pub mod lsp_ext; | 39 | pub mod lsp_ext; |
39 | pub mod config; | 40 | pub mod config; |
40 | 41 | ||
diff --git a/crates/rust-analyzer/src/lsp_utils.rs b/crates/rust-analyzer/src/lsp_utils.rs index 40de56dad..2d06fe538 100644 --- a/crates/rust-analyzer/src/lsp_utils.rs +++ b/crates/rust-analyzer/src/lsp_utils.rs | |||
@@ -130,7 +130,7 @@ pub(crate) fn apply_document_changes( | |||
130 | } | 130 | } |
131 | 131 | ||
132 | /// Checks that the edits inside the completion and the additional edits do not overlap. | 132 | /// Checks that the edits inside the completion and the additional edits do not overlap. |
133 | /// LSP explicitly forbits the additional edits to overlap both with the main edit and themselves. | 133 | /// LSP explicitly forbids the additional edits to overlap both with the main edit and themselves. |
134 | pub(crate) fn all_edits_are_disjoint( | 134 | pub(crate) fn all_edits_are_disjoint( |
135 | completion: &lsp_types::CompletionItem, | 135 | completion: &lsp_types::CompletionItem, |
136 | additional_edits: &[lsp_types::TextEdit], | 136 | additional_edits: &[lsp_types::TextEdit], |
@@ -290,7 +290,7 @@ mod tests { | |||
290 | Some(vec![disjoint_edit.clone(), joint_edit.clone()]); | 290 | Some(vec![disjoint_edit.clone(), joint_edit.clone()]); |
291 | assert!( | 291 | assert!( |
292 | !all_edits_are_disjoint(&completion_with_joint_edits, &[]), | 292 | !all_edits_are_disjoint(&completion_with_joint_edits, &[]), |
293 | "Completion with disjoint edits fails the validaton even with empty extra edits" | 293 | "Completion with disjoint edits fails the validation even with empty extra edits" |
294 | ); | 294 | ); |
295 | 295 | ||
296 | completion_with_joint_edits.text_edit = | 296 | completion_with_joint_edits.text_edit = |
@@ -298,7 +298,7 @@ mod tests { | |||
298 | completion_with_joint_edits.additional_text_edits = Some(vec![joint_edit.clone()]); | 298 | completion_with_joint_edits.additional_text_edits = Some(vec![joint_edit.clone()]); |
299 | assert!( | 299 | assert!( |
300 | !all_edits_are_disjoint(&completion_with_joint_edits, &[]), | 300 | !all_edits_are_disjoint(&completion_with_joint_edits, &[]), |
301 | "Completion with disjoint edits fails the validaton even with empty extra edits" | 301 | "Completion with disjoint edits fails the validation even with empty extra edits" |
302 | ); | 302 | ); |
303 | 303 | ||
304 | completion_with_joint_edits.text_edit = | 304 | completion_with_joint_edits.text_edit = |
@@ -310,7 +310,7 @@ mod tests { | |||
310 | completion_with_joint_edits.additional_text_edits = None; | 310 | completion_with_joint_edits.additional_text_edits = None; |
311 | assert!( | 311 | assert!( |
312 | !all_edits_are_disjoint(&completion_with_joint_edits, &[]), | 312 | !all_edits_are_disjoint(&completion_with_joint_edits, &[]), |
313 | "Completion with disjoint edits fails the validaton even with empty extra edits" | 313 | "Completion with disjoint edits fails the validation even with empty extra edits" |
314 | ); | 314 | ); |
315 | 315 | ||
316 | completion_with_joint_edits.text_edit = | 316 | completion_with_joint_edits.text_edit = |
@@ -322,7 +322,7 @@ mod tests { | |||
322 | completion_with_joint_edits.additional_text_edits = Some(vec![joint_edit]); | 322 | completion_with_joint_edits.additional_text_edits = Some(vec![joint_edit]); |
323 | assert!( | 323 | assert!( |
324 | !all_edits_are_disjoint(&completion_with_joint_edits, &[]), | 324 | !all_edits_are_disjoint(&completion_with_joint_edits, &[]), |
325 | "Completion with disjoint edits fails the validaton even with empty extra edits" | 325 | "Completion with disjoint edits fails the validation even with empty extra edits" |
326 | ); | 326 | ); |
327 | } | 327 | } |
328 | 328 | ||
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 8eca79f7e..6d2475a59 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -11,7 +11,6 @@ use ide::{Canceled, FileId}; | |||
11 | use ide_db::base_db::VfsPath; | 11 | use ide_db::base_db::VfsPath; |
12 | use lsp_server::{Connection, Notification, Request, Response}; | 12 | use lsp_server::{Connection, Notification, Request, Response}; |
13 | use lsp_types::notification::Notification as _; | 13 | use lsp_types::notification::Notification as _; |
14 | use project_model::ProjectWorkspace; | ||
15 | use vfs::ChangeKind; | 14 | use vfs::ChangeKind; |
16 | 15 | ||
17 | use crate::{ | 16 | use crate::{ |
@@ -22,6 +21,7 @@ use crate::{ | |||
22 | global_state::{file_id_to_url, url_to_file_id, GlobalState, Status}, | 21 | global_state::{file_id_to_url, url_to_file_id, GlobalState, Status}, |
23 | handlers, lsp_ext, | 22 | handlers, lsp_ext, |
24 | lsp_utils::{apply_document_changes, is_canceled, notification_is, Progress}, | 23 | lsp_utils::{apply_document_changes, is_canceled, notification_is, Progress}, |
24 | reload::ProjectWorkspaceProgress, | ||
25 | Result, | 25 | Result, |
26 | }; | 26 | }; |
27 | 27 | ||
@@ -61,8 +61,8 @@ enum Event { | |||
61 | pub(crate) enum Task { | 61 | pub(crate) enum Task { |
62 | Response(Response), | 62 | Response(Response), |
63 | Diagnostics(Vec<(FileId, Vec<lsp_types::Diagnostic>)>), | 63 | Diagnostics(Vec<(FileId, Vec<lsp_types::Diagnostic>)>), |
64 | Workspaces(Vec<anyhow::Result<ProjectWorkspace>>), | ||
65 | PrimeCaches(PrimeCachesProgress), | 64 | PrimeCaches(PrimeCachesProgress), |
65 | FetchWorkspace(ProjectWorkspaceProgress), | ||
66 | } | 66 | } |
67 | 67 | ||
68 | impl fmt::Debug for Event { | 68 | impl fmt::Debug for Event { |
@@ -99,7 +99,8 @@ impl fmt::Debug for Event { | |||
99 | 99 | ||
100 | impl GlobalState { | 100 | impl GlobalState { |
101 | fn run(mut self, inbox: Receiver<lsp_server::Message>) -> Result<()> { | 101 | fn run(mut self, inbox: Receiver<lsp_server::Message>) -> Result<()> { |
102 | if self.config.linked_projects.is_empty() && self.config.notifications.cargo_toml_not_found | 102 | if self.config.linked_projects().is_empty() |
103 | && self.config.notifications().cargo_toml_not_found | ||
103 | { | 104 | { |
104 | self.show_message( | 105 | self.show_message( |
105 | lsp_types::MessageType::Error, | 106 | lsp_types::MessageType::Error, |
@@ -107,40 +108,43 @@ impl GlobalState { | |||
107 | ); | 108 | ); |
108 | }; | 109 | }; |
109 | 110 | ||
110 | let save_registration_options = lsp_types::TextDocumentSaveRegistrationOptions { | 111 | if self.config.did_save_text_document_dynamic_registration() { |
111 | include_text: Some(false), | 112 | let save_registration_options = lsp_types::TextDocumentSaveRegistrationOptions { |
112 | text_document_registration_options: lsp_types::TextDocumentRegistrationOptions { | 113 | include_text: Some(false), |
113 | document_selector: Some(vec![ | 114 | text_document_registration_options: lsp_types::TextDocumentRegistrationOptions { |
114 | lsp_types::DocumentFilter { | 115 | document_selector: Some(vec![ |
115 | language: None, | 116 | lsp_types::DocumentFilter { |
116 | scheme: None, | 117 | language: None, |
117 | pattern: Some("**/*.rs".into()), | 118 | scheme: None, |
118 | }, | 119 | pattern: Some("**/*.rs".into()), |
119 | lsp_types::DocumentFilter { | 120 | }, |
120 | language: None, | 121 | lsp_types::DocumentFilter { |
121 | scheme: None, | 122 | language: None, |
122 | pattern: Some("**/Cargo.toml".into()), | 123 | scheme: None, |
123 | }, | 124 | pattern: Some("**/Cargo.toml".into()), |
124 | lsp_types::DocumentFilter { | 125 | }, |
125 | language: None, | 126 | lsp_types::DocumentFilter { |
126 | scheme: None, | 127 | language: None, |
127 | pattern: Some("**/Cargo.lock".into()), | 128 | scheme: None, |
128 | }, | 129 | pattern: Some("**/Cargo.lock".into()), |
129 | ]), | 130 | }, |
130 | }, | 131 | ]), |
131 | }; | 132 | }, |
132 | 133 | }; | |
133 | let registration = lsp_types::Registration { | 134 | |
134 | id: "textDocument/didSave".to_string(), | 135 | let registration = lsp_types::Registration { |
135 | method: "textDocument/didSave".to_string(), | 136 | id: "textDocument/didSave".to_string(), |
136 | register_options: Some(serde_json::to_value(save_registration_options).unwrap()), | 137 | method: "textDocument/didSave".to_string(), |
137 | }; | 138 | register_options: Some(serde_json::to_value(save_registration_options).unwrap()), |
138 | self.send_request::<lsp_types::request::RegisterCapability>( | 139 | }; |
139 | lsp_types::RegistrationParams { registrations: vec![registration] }, | 140 | self.send_request::<lsp_types::request::RegisterCapability>( |
140 | |_, _| (), | 141 | lsp_types::RegistrationParams { registrations: vec![registration] }, |
141 | ); | 142 | |_, _| (), |
143 | ); | ||
144 | } | ||
142 | 145 | ||
143 | self.fetch_workspaces(); | 146 | self.fetch_workspaces_request(); |
147 | self.fetch_workspaces_if_needed(); | ||
144 | 148 | ||
145 | while let Some(event) = self.next_event(&inbox) { | 149 | while let Some(event) = self.next_event(&inbox) { |
146 | if let Event::Lsp(lsp_server::Message::Notification(not)) = &event { | 150 | if let Event::Lsp(lsp_server::Message::Notification(not)) = &event { |
@@ -201,7 +205,6 @@ impl GlobalState { | |||
201 | self.diagnostics.set_native_diagnostics(file_id, diagnostics) | 205 | self.diagnostics.set_native_diagnostics(file_id, diagnostics) |
202 | } | 206 | } |
203 | } | 207 | } |
204 | Task::Workspaces(workspaces) => self.switch_workspaces(workspaces), | ||
205 | Task::PrimeCaches(progress) => match progress { | 208 | Task::PrimeCaches(progress) => match progress { |
206 | PrimeCachesProgress::Started => prime_caches_progress.push(progress), | 209 | PrimeCachesProgress::Started => prime_caches_progress.push(progress), |
207 | PrimeCachesProgress::StartedOnCrate { .. } => { | 210 | PrimeCachesProgress::StartedOnCrate { .. } => { |
@@ -215,6 +218,20 @@ impl GlobalState { | |||
215 | } | 218 | } |
216 | PrimeCachesProgress::Finished => prime_caches_progress.push(progress), | 219 | PrimeCachesProgress::Finished => prime_caches_progress.push(progress), |
217 | }, | 220 | }, |
221 | Task::FetchWorkspace(progress) => { | ||
222 | let (state, msg) = match progress { | ||
223 | ProjectWorkspaceProgress::Begin => (Progress::Begin, None), | ||
224 | ProjectWorkspaceProgress::Report(msg) => { | ||
225 | (Progress::Report, Some(msg)) | ||
226 | } | ||
227 | ProjectWorkspaceProgress::End(workspaces) => { | ||
228 | self.fetch_workspaces_completed(); | ||
229 | self.switch_workspaces(workspaces); | ||
230 | (Progress::End, None) | ||
231 | } | ||
232 | }; | ||
233 | self.report_progress("fetching", state, msg, None); | ||
234 | } | ||
218 | } | 235 | } |
219 | // Coalesce multiple task events into one loop turn | 236 | // Coalesce multiple task events into one loop turn |
220 | task = match self.task_pool.receiver.try_recv() { | 237 | task = match self.task_pool.receiver.try_recv() { |
@@ -296,7 +313,7 @@ impl GlobalState { | |||
296 | flycheck::Message::AddDiagnostic { workspace_root, diagnostic } => { | 313 | flycheck::Message::AddDiagnostic { workspace_root, diagnostic } => { |
297 | let diagnostics = | 314 | let diagnostics = |
298 | crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp( | 315 | crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp( |
299 | &self.config.diagnostics_map, | 316 | &self.config.diagnostics_map(), |
300 | &diagnostic, | 317 | &diagnostic, |
301 | &workspace_root, | 318 | &workspace_root, |
302 | ); | 319 | ); |
@@ -365,13 +382,13 @@ impl GlobalState { | |||
365 | self.update_file_notifications_on_threadpool(); | 382 | self.update_file_notifications_on_threadpool(); |
366 | 383 | ||
367 | // Refresh semantic tokens if the client supports it. | 384 | // Refresh semantic tokens if the client supports it. |
368 | if self.config.semantic_tokens_refresh { | 385 | if self.config.semantic_tokens_refresh() { |
369 | self.semantic_tokens_cache.lock().clear(); | 386 | self.semantic_tokens_cache.lock().clear(); |
370 | self.send_request::<lsp_types::request::SemanticTokensRefesh>((), |_, _| ()); | 387 | self.send_request::<lsp_types::request::SemanticTokensRefesh>((), |_, _| ()); |
371 | } | 388 | } |
372 | 389 | ||
373 | // Refresh code lens if the client supports it. | 390 | // Refresh code lens if the client supports it. |
374 | if self.config.code_lens_refresh { | 391 | if self.config.code_lens_refresh() { |
375 | self.send_request::<lsp_types::request::CodeLensRefresh>((), |_, _| ()); | 392 | self.send_request::<lsp_types::request::CodeLensRefresh>((), |_, _| ()); |
376 | } | 393 | } |
377 | } | 394 | } |
@@ -390,6 +407,8 @@ impl GlobalState { | |||
390 | } | 407 | } |
391 | } | 408 | } |
392 | 409 | ||
410 | self.fetch_workspaces_if_needed(); | ||
411 | |||
393 | let loop_duration = loop_start.elapsed(); | 412 | let loop_duration = loop_start.elapsed(); |
394 | if loop_duration > Duration::from_millis(100) { | 413 | if loop_duration > Duration::from_millis(100) { |
395 | log::warn!("overly long loop turn: {:?}", loop_duration); | 414 | log::warn!("overly long loop turn: {:?}", loop_duration); |
@@ -427,7 +446,7 @@ impl GlobalState { | |||
427 | } | 446 | } |
428 | 447 | ||
429 | RequestDispatcher { req: Some(req), global_state: self } | 448 | RequestDispatcher { req: Some(req), global_state: self } |
430 | .on_sync::<lsp_ext::ReloadWorkspace>(|s, ()| Ok(s.fetch_workspaces()))? | 449 | .on_sync::<lsp_ext::ReloadWorkspace>(|s, ()| Ok(s.fetch_workspaces_request()))? |
431 | .on_sync::<lsp_ext::JoinLines>(|s, p| handlers::handle_join_lines(s.snapshot(), p))? | 450 | .on_sync::<lsp_ext::JoinLines>(|s, p| handlers::handle_join_lines(s.snapshot(), p))? |
432 | .on_sync::<lsp_ext::OnEnter>(|s, p| handlers::handle_on_enter(s.snapshot(), p))? | 451 | .on_sync::<lsp_ext::OnEnter>(|s, p| handlers::handle_on_enter(s.snapshot(), p))? |
433 | .on_sync::<lsp_types::request::Shutdown>(|s, ()| { | 452 | .on_sync::<lsp_types::request::Shutdown>(|s, ()| { |
@@ -608,7 +627,7 @@ impl GlobalState { | |||
608 | if let Some(json) = configs.get_mut(0) { | 627 | if let Some(json) = configs.get_mut(0) { |
609 | // Note that json can be null according to the spec if the client can't | 628 | // Note that json can be null according to the spec if the client can't |
610 | // provide a configuration. This is handled in Config::update below. | 629 | // provide a configuration. This is handled in Config::update below. |
611 | let mut config = this.config.clone(); | 630 | let mut config = Config::clone(&*this.config); |
612 | config.update(json.take()); | 631 | config.update(json.take()); |
613 | this.update_configuration(config); | 632 | this.update_configuration(config); |
614 | } | 633 | } |
@@ -658,7 +677,7 @@ impl GlobalState { | |||
658 | .collect::<Vec<_>>(); | 677 | .collect::<Vec<_>>(); |
659 | 678 | ||
660 | log::trace!("updating notifications for {:?}", subscriptions); | 679 | log::trace!("updating notifications for {:?}", subscriptions); |
661 | if self.config.publish_diagnostics { | 680 | if self.config.publish_diagnostics() { |
662 | let snapshot = self.snapshot(); | 681 | let snapshot = self.snapshot(); |
663 | self.task_pool.handle.spawn(move || { | 682 | self.task_pool.handle.spawn(move || { |
664 | let diagnostics = subscriptions | 683 | let diagnostics = subscriptions |
diff --git a/crates/rust-analyzer/src/markdown.rs b/crates/rust-analyzer/src/markdown.rs index a49a58c00..865eaae9b 100644 --- a/crates/rust-analyzer/src/markdown.rs +++ b/crates/rust-analyzer/src/markdown.rs | |||
@@ -106,7 +106,7 @@ mod tests { | |||
106 | 106 | ||
107 | #[test] | 107 | #[test] |
108 | fn test_format_docs_preserves_newlines() { | 108 | fn test_format_docs_preserves_newlines() { |
109 | let comment = "this\nis\nultiline"; | 109 | let comment = "this\nis\nmultiline"; |
110 | assert_eq!(format_docs(comment), comment); | 110 | assert_eq!(format_docs(comment), comment); |
111 | } | 111 | } |
112 | 112 | ||
diff --git a/crates/rust-analyzer/src/op_queue.rs b/crates/rust-analyzer/src/op_queue.rs new file mode 100644 index 000000000..51d66f4b3 --- /dev/null +++ b/crates/rust-analyzer/src/op_queue.rs | |||
@@ -0,0 +1,25 @@ | |||
1 | //! Bookkeeping to make sure only one long-running operation is executed. | ||
2 | |||
3 | #[derive(Default)] | ||
4 | pub(crate) struct OpQueue { | ||
5 | op_scheduled: bool, | ||
6 | op_in_progress: bool, | ||
7 | } | ||
8 | |||
9 | impl OpQueue { | ||
10 | pub(crate) fn request_op(&mut self) { | ||
11 | self.op_scheduled = true; | ||
12 | } | ||
13 | pub(crate) fn should_start_op(&mut self) -> bool { | ||
14 | if !self.op_in_progress && self.op_scheduled { | ||
15 | self.op_in_progress = true; | ||
16 | self.op_scheduled = false; | ||
17 | return true; | ||
18 | } | ||
19 | false | ||
20 | } | ||
21 | pub(crate) fn op_completed(&mut self) { | ||
22 | assert!(self.op_in_progress); | ||
23 | self.op_in_progress = false; | ||
24 | } | ||
25 | } | ||
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index ce5cedeb3..97e20362f 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs | |||
@@ -15,16 +15,23 @@ use crate::{ | |||
15 | }; | 15 | }; |
16 | use lsp_ext::StatusParams; | 16 | use lsp_ext::StatusParams; |
17 | 17 | ||
18 | #[derive(Debug)] | ||
19 | pub(crate) enum ProjectWorkspaceProgress { | ||
20 | Begin, | ||
21 | Report(String), | ||
22 | End(Vec<anyhow::Result<ProjectWorkspace>>), | ||
23 | } | ||
24 | |||
18 | impl GlobalState { | 25 | impl GlobalState { |
19 | pub(crate) fn update_configuration(&mut self, config: Config) { | 26 | pub(crate) fn update_configuration(&mut self, config: Config) { |
20 | let _p = profile::span("GlobalState::update_configuration"); | 27 | let _p = profile::span("GlobalState::update_configuration"); |
21 | let old_config = mem::replace(&mut self.config, config); | 28 | let old_config = mem::replace(&mut self.config, Arc::new(config)); |
22 | if self.config.lru_capacity != old_config.lru_capacity { | 29 | if self.config.lru_capacity() != old_config.lru_capacity() { |
23 | self.analysis_host.update_lru_capacity(old_config.lru_capacity); | 30 | self.analysis_host.update_lru_capacity(self.config.lru_capacity()); |
24 | } | 31 | } |
25 | if self.config.linked_projects != old_config.linked_projects { | 32 | if self.config.linked_projects() != old_config.linked_projects() { |
26 | self.fetch_workspaces() | 33 | self.fetch_workspaces_request() |
27 | } else if self.config.flycheck != old_config.flycheck { | 34 | } else if self.config.flycheck() != old_config.flycheck() { |
28 | self.reload_flycheck(); | 35 | self.reload_flycheck(); |
29 | } | 36 | } |
30 | } | 37 | } |
@@ -36,8 +43,8 @@ impl GlobalState { | |||
36 | Status::Loading | Status::NeedsReload => return, | 43 | Status::Loading | Status::NeedsReload => return, |
37 | Status::Ready | Status::Invalid => (), | 44 | Status::Ready | Status::Invalid => (), |
38 | } | 45 | } |
39 | if self.config.cargo_autoreload { | 46 | if self.config.cargo_autoreload() { |
40 | self.fetch_workspaces(); | 47 | self.fetch_workspaces_request(); |
41 | } else { | 48 | } else { |
42 | self.transition(Status::NeedsReload); | 49 | self.transition(Status::NeedsReload); |
43 | } | 50 | } |
@@ -91,28 +98,59 @@ impl GlobalState { | |||
91 | }); | 98 | }); |
92 | } | 99 | } |
93 | } | 100 | } |
94 | pub(crate) fn fetch_workspaces(&mut self) { | 101 | |
102 | pub(crate) fn fetch_workspaces_request(&mut self) { | ||
103 | self.fetch_workspaces_queue.request_op() | ||
104 | } | ||
105 | pub(crate) fn fetch_workspaces_if_needed(&mut self) { | ||
95 | log::info!("will fetch workspaces"); | 106 | log::info!("will fetch workspaces"); |
96 | self.task_pool.handle.spawn({ | 107 | if !self.fetch_workspaces_queue.should_start_op() { |
97 | let linked_projects = self.config.linked_projects.clone(); | 108 | return; |
98 | let cargo_config = self.config.cargo.clone(); | 109 | } |
99 | move || { | 110 | |
111 | self.task_pool.handle.spawn_with_sender({ | ||
112 | let linked_projects = self.config.linked_projects(); | ||
113 | let cargo_config = self.config.cargo(); | ||
114 | |||
115 | move |sender| { | ||
116 | let progress = { | ||
117 | let sender = sender.clone(); | ||
118 | move |msg| { | ||
119 | sender | ||
120 | .send(Task::FetchWorkspace(ProjectWorkspaceProgress::Report(msg))) | ||
121 | .unwrap() | ||
122 | } | ||
123 | }; | ||
124 | |||
125 | sender.send(Task::FetchWorkspace(ProjectWorkspaceProgress::Begin)).unwrap(); | ||
126 | |||
100 | let workspaces = linked_projects | 127 | let workspaces = linked_projects |
101 | .iter() | 128 | .iter() |
102 | .map(|project| match project { | 129 | .map(|project| match project { |
103 | LinkedProject::ProjectManifest(manifest) => { | 130 | LinkedProject::ProjectManifest(manifest) => { |
104 | project_model::ProjectWorkspace::load(manifest.clone(), &cargo_config) | 131 | project_model::ProjectWorkspace::load( |
132 | manifest.clone(), | ||
133 | &cargo_config, | ||
134 | &progress, | ||
135 | ) | ||
105 | } | 136 | } |
106 | LinkedProject::InlineJsonProject(it) => { | 137 | LinkedProject::InlineJsonProject(it) => { |
107 | project_model::ProjectWorkspace::load_inline(it.clone()) | 138 | project_model::ProjectWorkspace::load_inline(it.clone()) |
108 | } | 139 | } |
109 | }) | 140 | }) |
110 | .collect::<Vec<_>>(); | 141 | .collect::<Vec<_>>(); |
142 | |||
111 | log::info!("did fetch workspaces {:?}", workspaces); | 143 | log::info!("did fetch workspaces {:?}", workspaces); |
112 | Task::Workspaces(workspaces) | 144 | sender |
145 | .send(Task::FetchWorkspace(ProjectWorkspaceProgress::End(workspaces))) | ||
146 | .unwrap(); | ||
113 | } | 147 | } |
114 | }); | 148 | }); |
115 | } | 149 | } |
150 | pub(crate) fn fetch_workspaces_completed(&mut self) { | ||
151 | self.fetch_workspaces_queue.op_completed() | ||
152 | } | ||
153 | |||
116 | pub(crate) fn switch_workspaces(&mut self, workspaces: Vec<anyhow::Result<ProjectWorkspace>>) { | 154 | pub(crate) fn switch_workspaces(&mut self, workspaces: Vec<anyhow::Result<ProjectWorkspace>>) { |
117 | let _p = profile::span("GlobalState::switch_workspaces"); | 155 | let _p = profile::span("GlobalState::switch_workspaces"); |
118 | log::info!("will switch workspaces: {:?}", workspaces); | 156 | log::info!("will switch workspaces: {:?}", workspaces); |
@@ -143,36 +181,41 @@ impl GlobalState { | |||
143 | return; | 181 | return; |
144 | } | 182 | } |
145 | 183 | ||
146 | if let FilesWatcher::Client = self.config.files.watcher { | 184 | if let FilesWatcher::Client = self.config.files().watcher { |
147 | let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions { | 185 | if self.config.did_change_watched_files_dynamic_registration() { |
148 | watchers: workspaces | 186 | let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions { |
149 | .iter() | 187 | watchers: workspaces |
150 | .flat_map(ProjectWorkspace::to_roots) | 188 | .iter() |
151 | .filter(|it| it.is_member) | 189 | .flat_map(ProjectWorkspace::to_roots) |
152 | .flat_map(|root| { | 190 | .filter(|it| it.is_member) |
153 | root.include.into_iter().map(|it| format!("{}/**/*.rs", it.display())) | 191 | .flat_map(|root| { |
154 | }) | 192 | root.include.into_iter().map(|it| format!("{}/**/*.rs", it.display())) |
155 | .map(|glob_pattern| lsp_types::FileSystemWatcher { glob_pattern, kind: None }) | 193 | }) |
156 | .collect(), | 194 | .map(|glob_pattern| lsp_types::FileSystemWatcher { |
157 | }; | 195 | glob_pattern, |
158 | let registration = lsp_types::Registration { | 196 | kind: None, |
159 | id: "workspace/didChangeWatchedFiles".to_string(), | 197 | }) |
160 | method: "workspace/didChangeWatchedFiles".to_string(), | 198 | .collect(), |
161 | register_options: Some(serde_json::to_value(registration_options).unwrap()), | 199 | }; |
162 | }; | 200 | let registration = lsp_types::Registration { |
163 | self.send_request::<lsp_types::request::RegisterCapability>( | 201 | id: "workspace/didChangeWatchedFiles".to_string(), |
164 | lsp_types::RegistrationParams { registrations: vec![registration] }, | 202 | method: "workspace/didChangeWatchedFiles".to_string(), |
165 | |_, _| (), | 203 | register_options: Some(serde_json::to_value(registration_options).unwrap()), |
166 | ); | 204 | }; |
205 | self.send_request::<lsp_types::request::RegisterCapability>( | ||
206 | lsp_types::RegistrationParams { registrations: vec![registration] }, | ||
207 | |_, _| (), | ||
208 | ); | ||
209 | } | ||
167 | } | 210 | } |
168 | 211 | ||
169 | let mut change = Change::new(); | 212 | let mut change = Change::new(); |
170 | 213 | ||
171 | let project_folders = ProjectFolders::new(&workspaces); | 214 | let project_folders = ProjectFolders::new(&workspaces); |
172 | 215 | ||
173 | self.proc_macro_client = match &self.config.proc_macro_srv { | 216 | self.proc_macro_client = match self.config.proc_macro_srv() { |
174 | None => None, | 217 | None => None, |
175 | Some((path, args)) => match ProcMacroClient::extern_process(path.into(), args) { | 218 | Some((path, args)) => match ProcMacroClient::extern_process(path.clone(), args) { |
176 | Ok(it) => Some(it), | 219 | Ok(it) => Some(it), |
177 | Err(err) => { | 220 | Err(err) => { |
178 | log::error!( | 221 | log::error!( |
@@ -185,7 +228,7 @@ impl GlobalState { | |||
185 | }, | 228 | }, |
186 | }; | 229 | }; |
187 | 230 | ||
188 | let watch = match self.config.files.watcher { | 231 | let watch = match self.config.files().watcher { |
189 | FilesWatcher::Client => vec![], | 232 | FilesWatcher::Client => vec![], |
190 | FilesWatcher::Notify => project_folders.watch, | 233 | FilesWatcher::Notify => project_folders.watch, |
191 | }; | 234 | }; |
@@ -211,7 +254,7 @@ impl GlobalState { | |||
211 | }; | 254 | }; |
212 | for ws in workspaces.iter() { | 255 | for ws in workspaces.iter() { |
213 | crate_graph.extend(ws.to_crate_graph( | 256 | crate_graph.extend(ws.to_crate_graph( |
214 | self.config.cargo.target.as_deref(), | 257 | self.config.cargo().target.as_deref(), |
215 | self.proc_macro_client.as_ref(), | 258 | self.proc_macro_client.as_ref(), |
216 | &mut load, | 259 | &mut load, |
217 | )); | 260 | )); |
@@ -231,7 +274,7 @@ impl GlobalState { | |||
231 | } | 274 | } |
232 | 275 | ||
233 | fn reload_flycheck(&mut self) { | 276 | fn reload_flycheck(&mut self) { |
234 | let config = match self.config.flycheck.clone() { | 277 | let config = match self.config.flycheck() { |
235 | Some(it) => it, | 278 | Some(it) => it, |
236 | None => { | 279 | None => { |
237 | self.flycheck = Vec::new(); | 280 | self.flycheck = Vec::new(); |
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs index 5c4366f16..7ce9a4ab6 100644 --- a/crates/rust-analyzer/src/semantic_tokens.rs +++ b/crates/rust-analyzer/src/semantic_tokens.rs | |||
@@ -38,17 +38,25 @@ macro_rules! define_semantic_token_types { | |||
38 | } | 38 | } |
39 | 39 | ||
40 | define_semantic_token_types![ | 40 | define_semantic_token_types![ |
41 | (ANGLE, "angle"), | ||
41 | (ATTRIBUTE, "attribute"), | 42 | (ATTRIBUTE, "attribute"), |
42 | (BOOLEAN, "boolean"), | 43 | (BOOLEAN, "boolean"), |
44 | (BRACE, "brace"), | ||
45 | (BRACKET, "bracket"), | ||
43 | (BUILTIN_TYPE, "builtinType"), | 46 | (BUILTIN_TYPE, "builtinType"), |
47 | (COMMA, "comma"), | ||
48 | (COLON, "colon"), | ||
49 | (DOT, "dot"), | ||
44 | (ESCAPE_SEQUENCE, "escapeSequence"), | 50 | (ESCAPE_SEQUENCE, "escapeSequence"), |
45 | (FORMAT_SPECIFIER, "formatSpecifier"), | 51 | (FORMAT_SPECIFIER, "formatSpecifier"), |
46 | (GENERIC, "generic"), | 52 | (GENERIC, "generic"), |
47 | (CONST_PARAMETER, "constParameter"), | 53 | (CONST_PARAMETER, "constParameter"), |
48 | (LIFETIME, "lifetime"), | 54 | (LIFETIME, "lifetime"), |
49 | (LABEL, "label"), | 55 | (LABEL, "label"), |
56 | (PARENTHESIS, "parenthesis"), | ||
50 | (PUNCTUATION, "punctuation"), | 57 | (PUNCTUATION, "punctuation"), |
51 | (SELF_KEYWORD, "selfKeyword"), | 58 | (SELF_KEYWORD, "selfKeyword"), |
59 | (SEMICOLON, "semicolon"), | ||
52 | (TYPE_ALIAS, "typeAlias"), | 60 | (TYPE_ALIAS, "typeAlias"), |
53 | (UNION, "union"), | 61 | (UNION, "union"), |
54 | (UNRESOLVED_REFERENCE, "unresolvedReference"), | 62 | (UNRESOLVED_REFERENCE, "unresolvedReference"), |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index e0413ec06..a7ff8975a 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -6,10 +6,10 @@ use std::{ | |||
6 | 6 | ||
7 | use ide::{ | 7 | use ide::{ |
8 | Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation, FileId, | 8 | Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation, FileId, |
9 | FileRange, FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag, | 9 | FileRange, FileSystemEdit, Fold, FoldKind, Highlight, HlMod, HlPunct, HlRange, HlTag, Indel, |
10 | HighlightedRange, Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup, | 10 | InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup, NavigationTarget, ReferenceAccess, |
11 | NavigationTarget, ReferenceAccess, Runnable, Severity, SourceChange, SourceFileEdit, | 11 | RenameError, Runnable, Severity, SourceChange, SourceFileEdit, SymbolKind, TextEdit, TextRange, |
12 | SymbolKind, TextEdit, TextRange, TextSize, | 12 | TextSize, |
13 | }; | 13 | }; |
14 | use itertools::Itertools; | 14 | use itertools::Itertools; |
15 | 15 | ||
@@ -337,12 +337,15 @@ static TOKEN_RESULT_COUNTER: AtomicU32 = AtomicU32::new(1); | |||
337 | pub(crate) fn semantic_tokens( | 337 | pub(crate) fn semantic_tokens( |
338 | text: &str, | 338 | text: &str, |
339 | line_index: &LineIndex, | 339 | line_index: &LineIndex, |
340 | highlights: Vec<HighlightedRange>, | 340 | highlights: Vec<HlRange>, |
341 | ) -> lsp_types::SemanticTokens { | 341 | ) -> lsp_types::SemanticTokens { |
342 | let id = TOKEN_RESULT_COUNTER.fetch_add(1, Ordering::SeqCst).to_string(); | 342 | let id = TOKEN_RESULT_COUNTER.fetch_add(1, Ordering::SeqCst).to_string(); |
343 | let mut builder = semantic_tokens::SemanticTokensBuilder::new(id); | 343 | let mut builder = semantic_tokens::SemanticTokensBuilder::new(id); |
344 | 344 | ||
345 | for highlight_range in highlights { | 345 | for highlight_range in highlights { |
346 | if highlight_range.highlight.is_empty() { | ||
347 | continue; | ||
348 | } | ||
346 | let (type_, mods) = semantic_token_type_and_modifiers(highlight_range.highlight); | 349 | let (type_, mods) = semantic_token_type_and_modifiers(highlight_range.highlight); |
347 | let token_index = semantic_tokens::type_index(type_); | 350 | let token_index = semantic_tokens::type_index(type_); |
348 | let modifier_bitset = mods.0; | 351 | let modifier_bitset = mods.0; |
@@ -374,7 +377,7 @@ fn semantic_token_type_and_modifiers( | |||
374 | ) -> (lsp_types::SemanticTokenType, semantic_tokens::ModifierSet) { | 377 | ) -> (lsp_types::SemanticTokenType, semantic_tokens::ModifierSet) { |
375 | let mut mods = semantic_tokens::ModifierSet::default(); | 378 | let mut mods = semantic_tokens::ModifierSet::default(); |
376 | let type_ = match highlight.tag { | 379 | let type_ = match highlight.tag { |
377 | HighlightTag::Symbol(symbol) => match symbol { | 380 | HlTag::Symbol(symbol) => match symbol { |
378 | SymbolKind::Module => lsp_types::SemanticTokenType::NAMESPACE, | 381 | SymbolKind::Module => lsp_types::SemanticTokenType::NAMESPACE, |
379 | SymbolKind::Impl => lsp_types::SemanticTokenType::TYPE, | 382 | SymbolKind::Impl => lsp_types::SemanticTokenType::TYPE, |
380 | SymbolKind::Field => lsp_types::SemanticTokenType::PROPERTY, | 383 | SymbolKind::Field => lsp_types::SemanticTokenType::PROPERTY, |
@@ -386,7 +389,7 @@ fn semantic_token_type_and_modifiers( | |||
386 | SymbolKind::SelfParam => semantic_tokens::SELF_KEYWORD, | 389 | SymbolKind::SelfParam => semantic_tokens::SELF_KEYWORD, |
387 | SymbolKind::Local => lsp_types::SemanticTokenType::VARIABLE, | 390 | SymbolKind::Local => lsp_types::SemanticTokenType::VARIABLE, |
388 | SymbolKind::Function => { | 391 | SymbolKind::Function => { |
389 | if highlight.modifiers.contains(HighlightModifier::Associated) { | 392 | if highlight.mods.contains(HlMod::Associated) { |
390 | lsp_types::SemanticTokenType::METHOD | 393 | lsp_types::SemanticTokenType::METHOD |
391 | } else { | 394 | } else { |
392 | lsp_types::SemanticTokenType::FUNCTION | 395 | lsp_types::SemanticTokenType::FUNCTION |
@@ -409,38 +412,44 @@ fn semantic_token_type_and_modifiers( | |||
409 | SymbolKind::Trait => lsp_types::SemanticTokenType::INTERFACE, | 412 | SymbolKind::Trait => lsp_types::SemanticTokenType::INTERFACE, |
410 | SymbolKind::Macro => lsp_types::SemanticTokenType::MACRO, | 413 | SymbolKind::Macro => lsp_types::SemanticTokenType::MACRO, |
411 | }, | 414 | }, |
412 | HighlightTag::BuiltinType => semantic_tokens::BUILTIN_TYPE, | 415 | HlTag::BuiltinType => semantic_tokens::BUILTIN_TYPE, |
413 | HighlightTag::Dummy => semantic_tokens::GENERIC, | 416 | HlTag::None => semantic_tokens::GENERIC, |
414 | HighlightTag::ByteLiteral | HighlightTag::NumericLiteral => { | 417 | HlTag::ByteLiteral | HlTag::NumericLiteral => lsp_types::SemanticTokenType::NUMBER, |
415 | lsp_types::SemanticTokenType::NUMBER | 418 | HlTag::BoolLiteral => semantic_tokens::BOOLEAN, |
416 | } | 419 | HlTag::CharLiteral | HlTag::StringLiteral => lsp_types::SemanticTokenType::STRING, |
417 | HighlightTag::BoolLiteral => semantic_tokens::BOOLEAN, | 420 | HlTag::Comment => lsp_types::SemanticTokenType::COMMENT, |
418 | HighlightTag::CharLiteral | HighlightTag::StringLiteral => { | 421 | HlTag::Attribute => semantic_tokens::ATTRIBUTE, |
419 | lsp_types::SemanticTokenType::STRING | 422 | HlTag::Keyword => lsp_types::SemanticTokenType::KEYWORD, |
420 | } | 423 | HlTag::UnresolvedReference => semantic_tokens::UNRESOLVED_REFERENCE, |
421 | HighlightTag::Comment => lsp_types::SemanticTokenType::COMMENT, | 424 | HlTag::FormatSpecifier => semantic_tokens::FORMAT_SPECIFIER, |
422 | HighlightTag::Attribute => semantic_tokens::ATTRIBUTE, | 425 | HlTag::Operator => lsp_types::SemanticTokenType::OPERATOR, |
423 | HighlightTag::Keyword => lsp_types::SemanticTokenType::KEYWORD, | 426 | HlTag::EscapeSequence => semantic_tokens::ESCAPE_SEQUENCE, |
424 | HighlightTag::UnresolvedReference => semantic_tokens::UNRESOLVED_REFERENCE, | 427 | HlTag::Punctuation(punct) => match punct { |
425 | HighlightTag::FormatSpecifier => semantic_tokens::FORMAT_SPECIFIER, | 428 | HlPunct::Bracket => semantic_tokens::BRACKET, |
426 | HighlightTag::Operator => lsp_types::SemanticTokenType::OPERATOR, | 429 | HlPunct::Brace => semantic_tokens::BRACE, |
427 | HighlightTag::EscapeSequence => semantic_tokens::ESCAPE_SEQUENCE, | 430 | HlPunct::Parenthesis => semantic_tokens::PARENTHESIS, |
428 | HighlightTag::Punctuation => semantic_tokens::PUNCTUATION, | 431 | HlPunct::Angle => semantic_tokens::ANGLE, |
432 | HlPunct::Comma => semantic_tokens::COMMA, | ||
433 | HlPunct::Dot => semantic_tokens::DOT, | ||
434 | HlPunct::Colon => semantic_tokens::COLON, | ||
435 | HlPunct::Semi => semantic_tokens::SEMICOLON, | ||
436 | HlPunct::Other => semantic_tokens::PUNCTUATION, | ||
437 | }, | ||
429 | }; | 438 | }; |
430 | 439 | ||
431 | for modifier in highlight.modifiers.iter() { | 440 | for modifier in highlight.mods.iter() { |
432 | let modifier = match modifier { | 441 | let modifier = match modifier { |
433 | HighlightModifier::Attribute => semantic_tokens::ATTRIBUTE_MODIFIER, | 442 | HlMod::Attribute => semantic_tokens::ATTRIBUTE_MODIFIER, |
434 | HighlightModifier::Definition => lsp_types::SemanticTokenModifier::DECLARATION, | 443 | HlMod::Definition => lsp_types::SemanticTokenModifier::DECLARATION, |
435 | HighlightModifier::Documentation => lsp_types::SemanticTokenModifier::DOCUMENTATION, | 444 | HlMod::Documentation => lsp_types::SemanticTokenModifier::DOCUMENTATION, |
436 | HighlightModifier::Injected => semantic_tokens::INJECTED, | 445 | HlMod::Injected => semantic_tokens::INJECTED, |
437 | HighlightModifier::ControlFlow => semantic_tokens::CONTROL_FLOW, | 446 | HlMod::ControlFlow => semantic_tokens::CONTROL_FLOW, |
438 | HighlightModifier::Mutable => semantic_tokens::MUTABLE, | 447 | HlMod::Mutable => semantic_tokens::MUTABLE, |
439 | HighlightModifier::Consuming => semantic_tokens::CONSUMING, | 448 | HlMod::Consuming => semantic_tokens::CONSUMING, |
440 | HighlightModifier::Unsafe => semantic_tokens::UNSAFE, | 449 | HlMod::Unsafe => semantic_tokens::UNSAFE, |
441 | HighlightModifier::Callable => semantic_tokens::CALLABLE, | 450 | HlMod::Callable => semantic_tokens::CALLABLE, |
442 | HighlightModifier::Static => lsp_types::SemanticTokenModifier::STATIC, | 451 | HlMod::Static => lsp_types::SemanticTokenModifier::STATIC, |
443 | HighlightModifier::Associated => continue, | 452 | HlMod::Associated => continue, |
444 | }; | 453 | }; |
445 | mods |= modifier; | 454 | mods |= modifier; |
446 | } | 455 | } |
@@ -818,7 +827,7 @@ pub(crate) fn runnable( | |||
818 | file_id: FileId, | 827 | file_id: FileId, |
819 | runnable: Runnable, | 828 | runnable: Runnable, |
820 | ) -> Result<lsp_ext::Runnable> { | 829 | ) -> Result<lsp_ext::Runnable> { |
821 | let config = &snap.config.runnables; | 830 | let config = snap.config.runnables(); |
822 | let spec = CargoTargetSpec::for_file(snap, file_id)?; | 831 | let spec = CargoTargetSpec::for_file(snap, file_id)?; |
823 | let workspace_root = spec.as_ref().map(|it| it.workspace_root.clone()); | 832 | let workspace_root = spec.as_ref().map(|it| it.workspace_root.clone()); |
824 | let target = spec.as_ref().map(|s| s.target.clone()); | 833 | let target = spec.as_ref().map(|s| s.target.clone()); |
@@ -833,9 +842,9 @@ pub(crate) fn runnable( | |||
833 | kind: lsp_ext::RunnableKind::Cargo, | 842 | kind: lsp_ext::RunnableKind::Cargo, |
834 | args: lsp_ext::CargoRunnable { | 843 | args: lsp_ext::CargoRunnable { |
835 | workspace_root: workspace_root.map(|it| it.into()), | 844 | workspace_root: workspace_root.map(|it| it.into()), |
836 | override_cargo: config.override_cargo.clone(), | 845 | override_cargo: config.override_cargo, |
837 | cargo_args, | 846 | cargo_args, |
838 | cargo_extra_args: config.cargo_extra_args.clone(), | 847 | cargo_extra_args: config.cargo_extra_args, |
839 | executable_args, | 848 | executable_args, |
840 | expect_test: None, | 849 | expect_test: None, |
841 | }, | 850 | }, |
@@ -847,9 +856,14 @@ pub(crate) fn markup_content(markup: Markup) -> lsp_types::MarkupContent { | |||
847 | lsp_types::MarkupContent { kind: lsp_types::MarkupKind::Markdown, value } | 856 | lsp_types::MarkupContent { kind: lsp_types::MarkupKind::Markdown, value } |
848 | } | 857 | } |
849 | 858 | ||
859 | pub(crate) fn rename_error(err: RenameError) -> crate::LspError { | ||
860 | crate::LspError { code: lsp_server::ErrorCode::InvalidParams as i32, message: err.to_string() } | ||
861 | } | ||
862 | |||
850 | #[cfg(test)] | 863 | #[cfg(test)] |
851 | mod tests { | 864 | mod tests { |
852 | use ide::Analysis; | 865 | use ide::Analysis; |
866 | use ide_db::helpers::SnippetCap; | ||
853 | 867 | ||
854 | use super::*; | 868 | use super::*; |
855 | 869 | ||
@@ -860,7 +874,7 @@ mod tests { | |||
860 | fn foo(arg: &Foo) {} | 874 | fn foo(arg: &Foo) {} |
861 | fn main() { | 875 | fn main() { |
862 | let arg = Foo; | 876 | let arg = Foo; |
863 | foo(<|>) | 877 | foo($0) |
864 | }"#; | 878 | }"#; |
865 | 879 | ||
866 | let (offset, text) = test_utils::extract_offset(fixture); | 880 | let (offset, text) = test_utils::extract_offset(fixture); |
@@ -868,7 +882,14 @@ mod tests { | |||
868 | let (analysis, file_id) = Analysis::from_single_file(text); | 882 | let (analysis, file_id) = Analysis::from_single_file(text); |
869 | let completions: Vec<(String, Option<String>)> = analysis | 883 | let completions: Vec<(String, Option<String>)> = analysis |
870 | .completions( | 884 | .completions( |
871 | &ide::CompletionConfig::default(), | 885 | &ide::CompletionConfig { |
886 | enable_postfix_completions: true, | ||
887 | enable_autoimport_completions: true, | ||
888 | add_call_parenthesis: true, | ||
889 | add_call_argument_snippets: true, | ||
890 | snippet_cap: SnippetCap::new(true), | ||
891 | merge: None, | ||
892 | }, | ||
872 | ide_db::base_db::FilePosition { file_id, offset }, | 893 | ide_db::base_db::FilePosition { file_id, offset }, |
873 | ) | 894 | ) |
874 | .unwrap() | 895 | .unwrap() |
diff --git a/crates/rust-analyzer/tests/rust-analyzer/main.rs b/crates/rust-analyzer/tests/rust-analyzer/main.rs index 3d99c1f52..80bde29b9 100644 --- a/crates/rust-analyzer/tests/rust-analyzer/main.rs +++ b/crates/rust-analyzer/tests/rust-analyzer/main.rs | |||
@@ -13,6 +13,7 @@ mod support; | |||
13 | 13 | ||
14 | use std::{collections::HashMap, path::PathBuf, time::Instant}; | 14 | use std::{collections::HashMap, path::PathBuf, time::Instant}; |
15 | 15 | ||
16 | use expect_test::expect; | ||
16 | use lsp_types::{ | 17 | use lsp_types::{ |
17 | notification::DidOpenTextDocument, | 18 | notification::DidOpenTextDocument, |
18 | request::{ | 19 | request::{ |
@@ -572,9 +573,9 @@ fn main() { | |||
572 | } | 573 | } |
573 | "###, | 574 | "###, |
574 | ) | 575 | ) |
575 | .with_config(|config| { | 576 | .with_config(serde_json::json!({ |
576 | config.cargo.load_out_dirs_from_check = true; | 577 | "cargo": { "loadOutDirsFromCheck": true } |
577 | }) | 578 | })) |
578 | .server() | 579 | .server() |
579 | .wait_until_workspace_is_loaded(); | 580 | .wait_until_workspace_is_loaded(); |
580 | 581 | ||
@@ -715,12 +716,13 @@ pub fn foo(_input: TokenStream) -> TokenStream { | |||
715 | 716 | ||
716 | "###, | 717 | "###, |
717 | ) | 718 | ) |
718 | .with_config(|config| { | 719 | .with_config(serde_json::json!({ |
719 | let macro_srv_path = PathBuf::from(env!("CARGO_BIN_EXE_rust-analyzer")); | 720 | "cargo": { "loadOutDirsFromCheck": true }, |
720 | 721 | "procMacro": { | |
721 | config.cargo.load_out_dirs_from_check = true; | 722 | "enable": true, |
722 | config.proc_macro_srv = Some((macro_srv_path, vec!["proc-macro".into()])); | 723 | "server": PathBuf::from(env!("CARGO_BIN_EXE_rust-analyzer")), |
723 | }) | 724 | } |
725 | })) | ||
724 | .root("foo") | 726 | .root("foo") |
725 | .root("bar") | 727 | .root("bar") |
726 | .server() | 728 | .server() |
@@ -733,8 +735,18 @@ pub fn foo(_input: TokenStream) -> TokenStream { | |||
733 | ), | 735 | ), |
734 | work_done_progress_params: Default::default(), | 736 | work_done_progress_params: Default::default(), |
735 | }); | 737 | }); |
736 | let value = res.get("contents").unwrap().get("value").unwrap().to_string(); | 738 | let value = res.get("contents").unwrap().get("value").unwrap().as_str().unwrap(); |
737 | assert_eq!(value, r#""\n```rust\nfoo::Bar\n```\n\n```rust\nfn bar()\n```""#) | 739 | |
740 | expect![[r#" | ||
741 | |||
742 | ```rust | ||
743 | foo::Bar | ||
744 | ``` | ||
745 | |||
746 | ```rust | ||
747 | fn bar() | ||
748 | ```"#]] | ||
749 | .assert_eq(&value); | ||
738 | } | 750 | } |
739 | 751 | ||
740 | #[test] | 752 | #[test] |
diff --git a/crates/rust-analyzer/tests/rust-analyzer/support.rs b/crates/rust-analyzer/tests/rust-analyzer/support.rs index aac7dbcce..2658ee185 100644 --- a/crates/rust-analyzer/tests/rust-analyzer/support.rs +++ b/crates/rust-analyzer/tests/rust-analyzer/support.rs | |||
@@ -12,11 +12,8 @@ use lsp_types::{ | |||
12 | notification::Exit, request::Shutdown, TextDocumentIdentifier, Url, WorkDoneProgress, | 12 | notification::Exit, request::Shutdown, TextDocumentIdentifier, Url, WorkDoneProgress, |
13 | }; | 13 | }; |
14 | use lsp_types::{ProgressParams, ProgressParamsValue}; | 14 | use lsp_types::{ProgressParams, ProgressParamsValue}; |
15 | use project_model::{CargoConfig, ProjectManifest}; | 15 | use project_model::ProjectManifest; |
16 | use rust_analyzer::{ | 16 | use rust_analyzer::{config::Config, main_loop}; |
17 | config::{Config, FilesConfig, FilesWatcher, LinkedProject}, | ||
18 | main_loop, | ||
19 | }; | ||
20 | use serde::Serialize; | 17 | use serde::Serialize; |
21 | use serde_json::{to_string_pretty, Value}; | 18 | use serde_json::{to_string_pretty, Value}; |
22 | use test_utils::{find_mismatch, Fixture}; | 19 | use test_utils::{find_mismatch, Fixture}; |
@@ -29,12 +26,18 @@ pub(crate) struct Project<'a> { | |||
29 | with_sysroot: bool, | 26 | with_sysroot: bool, |
30 | tmp_dir: Option<TestDir>, | 27 | tmp_dir: Option<TestDir>, |
31 | roots: Vec<PathBuf>, | 28 | roots: Vec<PathBuf>, |
32 | config: Option<Box<dyn Fn(&mut Config)>>, | 29 | config: serde_json::Value, |
33 | } | 30 | } |
34 | 31 | ||
35 | impl<'a> Project<'a> { | 32 | impl<'a> Project<'a> { |
36 | pub(crate) fn with_fixture(fixture: &str) -> Project { | 33 | pub(crate) fn with_fixture(fixture: &str) -> Project { |
37 | Project { fixture, tmp_dir: None, roots: vec![], with_sysroot: false, config: None } | 34 | Project { |
35 | fixture, | ||
36 | tmp_dir: None, | ||
37 | roots: vec![], | ||
38 | with_sysroot: false, | ||
39 | config: serde_json::Value::Null, | ||
40 | } | ||
38 | } | 41 | } |
39 | 42 | ||
40 | pub(crate) fn tmp_dir(mut self, tmp_dir: TestDir) -> Project<'a> { | 43 | pub(crate) fn tmp_dir(mut self, tmp_dir: TestDir) -> Project<'a> { |
@@ -52,8 +55,8 @@ impl<'a> Project<'a> { | |||
52 | self | 55 | self |
53 | } | 56 | } |
54 | 57 | ||
55 | pub(crate) fn with_config(mut self, config: impl Fn(&mut Config) + 'static) -> Project<'a> { | 58 | pub(crate) fn with_config(mut self, config: serde_json::Value) -> Project<'a> { |
56 | self.config = Some(Box::new(config)); | 59 | self.config = config; |
57 | self | 60 | self |
58 | } | 61 | } |
59 | 62 | ||
@@ -77,14 +80,14 @@ impl<'a> Project<'a> { | |||
77 | if roots.is_empty() { | 80 | if roots.is_empty() { |
78 | roots.push(tmp_dir_path.clone()); | 81 | roots.push(tmp_dir_path.clone()); |
79 | } | 82 | } |
80 | let linked_projects = roots | 83 | let discovered_projects = roots |
81 | .into_iter() | 84 | .into_iter() |
82 | .map(|it| ProjectManifest::discover_single(&it).unwrap()) | 85 | .map(|it| ProjectManifest::discover_single(&it).unwrap()) |
83 | .map(LinkedProject::from) | ||
84 | .collect::<Vec<_>>(); | 86 | .collect::<Vec<_>>(); |
85 | 87 | ||
86 | let mut config = Config { | 88 | let mut config = Config::new( |
87 | caps: lsp_types::ClientCapabilities { | 89 | tmp_dir_path, |
90 | lsp_types::ClientCapabilities { | ||
88 | text_document: Some(lsp_types::TextDocumentClientCapabilities { | 91 | text_document: Some(lsp_types::TextDocumentClientCapabilities { |
89 | definition: Some(lsp_types::GotoCapability { | 92 | definition: Some(lsp_types::GotoCapability { |
90 | link_support: Some(true), | 93 | link_support: Some(true), |
@@ -96,6 +99,10 @@ impl<'a> Project<'a> { | |||
96 | ), | 99 | ), |
97 | ..Default::default() | 100 | ..Default::default() |
98 | }), | 101 | }), |
102 | hover: Some(lsp_types::HoverClientCapabilities { | ||
103 | content_format: Some(vec![lsp_types::MarkupKind::Markdown]), | ||
104 | ..Default::default() | ||
105 | }), | ||
99 | ..Default::default() | 106 | ..Default::default() |
100 | }), | 107 | }), |
101 | window: Some(lsp_types::WindowClientCapabilities { | 108 | window: Some(lsp_types::WindowClientCapabilities { |
@@ -104,14 +111,9 @@ impl<'a> Project<'a> { | |||
104 | }), | 111 | }), |
105 | ..Default::default() | 112 | ..Default::default() |
106 | }, | 113 | }, |
107 | cargo: CargoConfig { no_sysroot: !self.with_sysroot, ..Default::default() }, | 114 | ); |
108 | linked_projects, | 115 | config.discovered_projects = Some(discovered_projects); |
109 | files: FilesConfig { watcher: FilesWatcher::Client, exclude: Vec::new() }, | 116 | config.update(self.config); |
110 | ..Config::new(tmp_dir_path) | ||
111 | }; | ||
112 | if let Some(f) = &self.config { | ||
113 | f(&mut config) | ||
114 | } | ||
115 | 117 | ||
116 | Server::new(tmp_dir, config) | 118 | Server::new(tmp_dir, config) |
117 | } | 119 | } |
diff --git a/crates/ssr/src/search.rs b/crates/ssr/src/search.rs index 44b5db029..836eb94b2 100644 --- a/crates/ssr/src/search.rs +++ b/crates/ssr/src/search.rs | |||
@@ -5,10 +5,10 @@ use crate::{ | |||
5 | resolving::{ResolvedPath, ResolvedPattern, ResolvedRule}, | 5 | resolving::{ResolvedPath, ResolvedPattern, ResolvedRule}, |
6 | Match, MatchFinder, | 6 | Match, MatchFinder, |
7 | }; | 7 | }; |
8 | use ide_db::base_db::{FileId, FileRange}; | ||
9 | use ide_db::{ | 8 | use ide_db::{ |
9 | base_db::{FileId, FileRange}, | ||
10 | defs::Definition, | 10 | defs::Definition, |
11 | search::{Reference, SearchScope}, | 11 | search::{SearchScope, UsageSearchResult}, |
12 | }; | 12 | }; |
13 | use rustc_hash::FxHashSet; | 13 | use rustc_hash::FxHashSet; |
14 | use syntax::{ast, AstNode, SyntaxKind, SyntaxNode}; | 14 | use syntax::{ast, AstNode, SyntaxKind, SyntaxNode}; |
@@ -20,7 +20,7 @@ use test_utils::mark; | |||
20 | /// them more than once. | 20 | /// them more than once. |
21 | #[derive(Default)] | 21 | #[derive(Default)] |
22 | pub(crate) struct UsageCache { | 22 | pub(crate) struct UsageCache { |
23 | usages: Vec<(Definition, Vec<Reference>)>, | 23 | usages: Vec<(Definition, UsageSearchResult)>, |
24 | } | 24 | } |
25 | 25 | ||
26 | impl<'db> MatchFinder<'db> { | 26 | impl<'db> MatchFinder<'db> { |
@@ -58,8 +58,8 @@ impl<'db> MatchFinder<'db> { | |||
58 | ) { | 58 | ) { |
59 | if let Some(resolved_path) = pick_path_for_usages(pattern) { | 59 | if let Some(resolved_path) = pick_path_for_usages(pattern) { |
60 | let definition: Definition = resolved_path.resolution.clone().into(); | 60 | let definition: Definition = resolved_path.resolution.clone().into(); |
61 | for reference in self.find_usages(usage_cache, definition) { | 61 | for file_range in self.find_usages(usage_cache, definition).file_ranges() { |
62 | if let Some(node_to_match) = self.find_node_to_match(resolved_path, reference) { | 62 | if let Some(node_to_match) = self.find_node_to_match(resolved_path, file_range) { |
63 | if !is_search_permitted_ancestors(&node_to_match) { | 63 | if !is_search_permitted_ancestors(&node_to_match) { |
64 | mark::hit!(use_declaration_with_braces); | 64 | mark::hit!(use_declaration_with_braces); |
65 | continue; | 65 | continue; |
@@ -73,11 +73,11 @@ impl<'db> MatchFinder<'db> { | |||
73 | fn find_node_to_match( | 73 | fn find_node_to_match( |
74 | &self, | 74 | &self, |
75 | resolved_path: &ResolvedPath, | 75 | resolved_path: &ResolvedPath, |
76 | reference: &Reference, | 76 | file_range: FileRange, |
77 | ) -> Option<SyntaxNode> { | 77 | ) -> Option<SyntaxNode> { |
78 | let file = self.sema.parse(reference.file_range.file_id); | 78 | let file = self.sema.parse(file_range.file_id); |
79 | let depth = resolved_path.depth as usize; | 79 | let depth = resolved_path.depth as usize; |
80 | let offset = reference.file_range.range.start(); | 80 | let offset = file_range.range.start(); |
81 | if let Some(path) = | 81 | if let Some(path) = |
82 | self.sema.find_node_at_offset_with_descend::<ast::Path>(file.syntax(), offset) | 82 | self.sema.find_node_at_offset_with_descend::<ast::Path>(file.syntax(), offset) |
83 | { | 83 | { |
@@ -108,7 +108,7 @@ impl<'db> MatchFinder<'db> { | |||
108 | &self, | 108 | &self, |
109 | usage_cache: &'a mut UsageCache, | 109 | usage_cache: &'a mut UsageCache, |
110 | definition: Definition, | 110 | definition: Definition, |
111 | ) -> &'a [Reference] { | 111 | ) -> &'a UsageSearchResult { |
112 | // Logically if a lookup succeeds we should just return it. Unfortunately returning it would | 112 | // Logically if a lookup succeeds we should just return it. Unfortunately returning it would |
113 | // extend the lifetime of the borrow, then we wouldn't be able to do the insertion on a | 113 | // extend the lifetime of the borrow, then we wouldn't be able to do the insertion on a |
114 | // cache miss. This is a limitation of NLL and is fixed with Polonius. For now we do two | 114 | // cache miss. This is a limitation of NLL and is fixed with Polonius. For now we do two |
@@ -250,7 +250,7 @@ fn is_search_permitted(node: &SyntaxNode) -> bool { | |||
250 | } | 250 | } |
251 | 251 | ||
252 | impl UsageCache { | 252 | impl UsageCache { |
253 | fn find(&mut self, definition: &Definition) -> Option<&[Reference]> { | 253 | fn find(&mut self, definition: &Definition) -> Option<&UsageSearchResult> { |
254 | // We expect a very small number of cache entries (generally 1), so a linear scan should be | 254 | // We expect a very small number of cache entries (generally 1), so a linear scan should be |
255 | // fast enough and avoids the need to implement Hash for Definition. | 255 | // fast enough and avoids the need to implement Hash for Definition. |
256 | for (d, refs) in &self.usages { | 256 | for (d, refs) in &self.usages { |
diff --git a/crates/ssr/src/tests.rs b/crates/ssr/src/tests.rs index db9cb8ca1..d6918c22d 100644 --- a/crates/ssr/src/tests.rs +++ b/crates/ssr/src/tests.rs | |||
@@ -59,7 +59,7 @@ fn parser_undefined_placeholder_in_replacement() { | |||
59 | ); | 59 | ); |
60 | } | 60 | } |
61 | 61 | ||
62 | /// `code` may optionally contain a cursor marker `<|>`. If it doesn't, then the position will be | 62 | /// `code` may optionally contain a cursor marker `$0`. If it doesn't, then the position will be |
63 | /// the start of the file. If there's a second cursor marker, then we'll return a single range. | 63 | /// the start of the file. If there's a second cursor marker, then we'll return a single range. |
64 | pub(crate) fn single_file(code: &str) -> (ide_db::RootDatabase, FilePosition, Vec<FileRange>) { | 64 | pub(crate) fn single_file(code: &str) -> (ide_db::RootDatabase, FilePosition, Vec<FileRange>) { |
65 | use ide_db::base_db::fixture::WithFixture; | 65 | use ide_db::base_db::fixture::WithFixture; |
@@ -596,7 +596,7 @@ fn replace_function_call() { | |||
596 | // This test also makes sure that we ignore empty-ranges. | 596 | // This test also makes sure that we ignore empty-ranges. |
597 | assert_ssr_transform( | 597 | assert_ssr_transform( |
598 | "foo() ==>> bar()", | 598 | "foo() ==>> bar()", |
599 | "fn foo() {<|><|>} fn bar() {} fn f1() {foo(); foo();}", | 599 | "fn foo() {$0$0} fn bar() {} fn f1() {foo(); foo();}", |
600 | expect![["fn foo() {} fn bar() {} fn f1() {bar(); bar();}"]], | 600 | expect![["fn foo() {} fn bar() {} fn f1() {bar(); bar();}"]], |
601 | ); | 601 | ); |
602 | } | 602 | } |
@@ -706,7 +706,7 @@ fn replace_associated_trait_constant() { | |||
706 | 706 | ||
707 | #[test] | 707 | #[test] |
708 | fn replace_path_in_different_contexts() { | 708 | fn replace_path_in_different_contexts() { |
709 | // Note the <|> inside module a::b which marks the point where the rule is interpreted. We | 709 | // Note the $0 inside module a::b which marks the point where the rule is interpreted. We |
710 | // replace foo with bar, but both need different path qualifiers in different contexts. In f4, | 710 | // replace foo with bar, but both need different path qualifiers in different contexts. In f4, |
711 | // foo is unqualified because of a use statement, however the replacement needs to be fully | 711 | // foo is unqualified because of a use statement, however the replacement needs to be fully |
712 | // qualified. | 712 | // qualified. |
@@ -714,7 +714,7 @@ fn replace_path_in_different_contexts() { | |||
714 | "c::foo() ==>> c::bar()", | 714 | "c::foo() ==>> c::bar()", |
715 | r#" | 715 | r#" |
716 | mod a { | 716 | mod a { |
717 | pub mod b {<|> | 717 | pub mod b {$0 |
718 | pub mod c { | 718 | pub mod c { |
719 | pub fn foo() {} | 719 | pub fn foo() {} |
720 | pub fn bar() {} | 720 | pub fn bar() {} |
@@ -1096,7 +1096,7 @@ fn pattern_is_a_single_segment_path() { | |||
1096 | fn f1() -> i32 { | 1096 | fn f1() -> i32 { |
1097 | let foo = 1; | 1097 | let foo = 1; |
1098 | let bar = 2; | 1098 | let bar = 2; |
1099 | foo<|> | 1099 | foo$0 |
1100 | } | 1100 | } |
1101 | "#, | 1101 | "#, |
1102 | expect![[r#" | 1102 | expect![[r#" |
@@ -1128,7 +1128,7 @@ fn replace_local_variable_reference() { | |||
1128 | let foo = 5; | 1128 | let foo = 5; |
1129 | res += foo + 1; | 1129 | res += foo + 1; |
1130 | let foo = 10; | 1130 | let foo = 10; |
1131 | res += foo + 2;<|> | 1131 | res += foo + 2;$0 |
1132 | res += foo + 3; | 1132 | res += foo + 3; |
1133 | let foo = 15; | 1133 | let foo = 15; |
1134 | res += foo + 4; | 1134 | res += foo + 4; |
@@ -1160,9 +1160,9 @@ fn replace_path_within_selection() { | |||
1160 | let foo = 41; | 1160 | let foo = 41; |
1161 | let bar = 42; | 1161 | let bar = 42; |
1162 | do_stuff(foo); | 1162 | do_stuff(foo); |
1163 | do_stuff(foo);<|> | 1163 | do_stuff(foo);$0 |
1164 | do_stuff(foo); | 1164 | do_stuff(foo); |
1165 | do_stuff(foo);<|> | 1165 | do_stuff(foo);$0 |
1166 | do_stuff(foo); | 1166 | do_stuff(foo); |
1167 | }"#, | 1167 | }"#, |
1168 | expect![[r#" | 1168 | expect![[r#" |
@@ -1185,9 +1185,9 @@ fn replace_nonpath_within_selection() { | |||
1185 | "$a + $b ==>> $b * $a", | 1185 | "$a + $b ==>> $b * $a", |
1186 | r#" | 1186 | r#" |
1187 | fn main() { | 1187 | fn main() { |
1188 | let v = 1 + 2;<|> | 1188 | let v = 1 + 2;$0 |
1189 | let v2 = 3 + 3; | 1189 | let v2 = 3 + 3; |
1190 | let v3 = 4 + 5;<|> | 1190 | let v3 = 4 + 5;$0 |
1191 | let v4 = 6 + 7; | 1191 | let v4 = 6 + 7; |
1192 | }"#, | 1192 | }"#, |
1193 | expect![[r#" | 1193 | expect![[r#" |
@@ -1212,7 +1212,7 @@ fn replace_self() { | |||
1212 | fn bar(_: &S1) {} | 1212 | fn bar(_: &S1) {} |
1213 | impl S1 { | 1213 | impl S1 { |
1214 | fn f1(&self) { | 1214 | fn f1(&self) { |
1215 | foo(self)<|> | 1215 | foo(self)$0 |
1216 | } | 1216 | } |
1217 | fn f2(&self) { | 1217 | fn f2(&self) { |
1218 | foo(self) | 1218 | foo(self) |
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index 374ed5910..13aab1451 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | //! Missing batteries for standard libraries. | 1 | //! Missing batteries for standard libraries. |
2 | use std::time::Instant; | 2 | use std::{cmp::Ordering, ops, process, time::Instant}; |
3 | 3 | ||
4 | mod macros; | 4 | mod macros; |
5 | pub mod panic_context; | 5 | pub mod panic_context; |
@@ -117,7 +117,12 @@ impl<'a> Iterator for LinesWithEnds<'a> { | |||
117 | } | 117 | } |
118 | } | 118 | } |
119 | 119 | ||
120 | // https://github.com/rust-lang/rust/issues/73831 | 120 | /// Returns `idx` such that: |
121 | /// | ||
122 | /// ∀ x in slice[..idx]: pred(x) | ||
123 | /// && ∀ x in slice[idx..]: !pred(x) | ||
124 | /// | ||
125 | /// https://github.com/rust-lang/rust/issues/73831 | ||
121 | pub fn partition_point<T, P>(slice: &[T], mut pred: P) -> usize | 126 | pub fn partition_point<T, P>(slice: &[T], mut pred: P) -> usize |
122 | where | 127 | where |
123 | P: FnMut(&T) -> bool, | 128 | P: FnMut(&T) -> bool, |
@@ -147,6 +152,36 @@ where | |||
147 | left | 152 | left |
148 | } | 153 | } |
149 | 154 | ||
155 | pub fn equal_range_by<T, F>(slice: &[T], mut key: F) -> ops::Range<usize> | ||
156 | where | ||
157 | F: FnMut(&T) -> Ordering, | ||
158 | { | ||
159 | let start = partition_point(slice, |it| key(it) == Ordering::Less); | ||
160 | let len = partition_point(&slice[start..], |it| key(it) == Ordering::Equal); | ||
161 | start..start + len | ||
162 | } | ||
163 | |||
164 | pub struct JodChild(pub process::Child); | ||
165 | |||
166 | impl ops::Deref for JodChild { | ||
167 | type Target = process::Child; | ||
168 | fn deref(&self) -> &process::Child { | ||
169 | &self.0 | ||
170 | } | ||
171 | } | ||
172 | |||
173 | impl ops::DerefMut for JodChild { | ||
174 | fn deref_mut(&mut self) -> &mut process::Child { | ||
175 | &mut self.0 | ||
176 | } | ||
177 | } | ||
178 | |||
179 | impl Drop for JodChild { | ||
180 | fn drop(&mut self) { | ||
181 | let _ = self.0.kill(); | ||
182 | } | ||
183 | } | ||
184 | |||
150 | #[cfg(test)] | 185 | #[cfg(test)] |
151 | mod tests { | 186 | mod tests { |
152 | use super::*; | 187 | use super::*; |
diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs index 5696c014f..384d031e7 100644 --- a/crates/syntax/src/algo.rs +++ b/crates/syntax/src/algo.rs | |||
@@ -19,7 +19,7 @@ use crate::{ | |||
19 | 19 | ||
20 | /// Returns ancestors of the node at the offset, sorted by length. This should | 20 | /// Returns ancestors of the node at the offset, sorted by length. This should |
21 | /// do the right thing at an edge, e.g. when searching for expressions at `{ | 21 | /// do the right thing at an edge, e.g. when searching for expressions at `{ |
22 | /// <|>foo }` we will get the name reference instead of the whole block, which | 22 | /// $0foo }` we will get the name reference instead of the whole block, which |
23 | /// we would get if we just did `find_token_at_offset(...).flat_map(|t| | 23 | /// we would get if we just did `find_token_at_offset(...).flat_map(|t| |
24 | /// t.parent().ancestors())`. | 24 | /// t.parent().ancestors())`. |
25 | pub fn ancestors_at_offset( | 25 | pub fn ancestors_at_offset( |
@@ -88,8 +88,8 @@ pub fn least_common_ancestor(u: &SyntaxNode, v: &SyntaxNode) -> Option<SyntaxNod | |||
88 | let keep = u_depth.min(v_depth); | 88 | let keep = u_depth.min(v_depth); |
89 | 89 | ||
90 | let u_candidates = u.ancestors().skip(u_depth - keep); | 90 | let u_candidates = u.ancestors().skip(u_depth - keep); |
91 | let v_canidates = v.ancestors().skip(v_depth - keep); | 91 | let v_candidates = v.ancestors().skip(v_depth - keep); |
92 | let (res, _) = u_candidates.zip(v_canidates).find(|(x, y)| x == y)?; | 92 | let (res, _) = u_candidates.zip(v_candidates).find(|(x, y)| x == y)?; |
93 | Some(res) | 93 | Some(res) |
94 | } | 94 | } |
95 | 95 | ||
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index cafa4c198..1ed8a96e5 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs | |||
@@ -241,7 +241,7 @@ pub fn wildcard_pat() -> ast::WildcardPat { | |||
241 | } | 241 | } |
242 | } | 242 | } |
243 | 243 | ||
244 | /// Creates a tuple of patterns from an interator of patterns. | 244 | /// Creates a tuple of patterns from an iterator of patterns. |
245 | /// | 245 | /// |
246 | /// Invariant: `pats` must be length > 1 | 246 | /// Invariant: `pats` must be length > 1 |
247 | /// | 247 | /// |
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 2aa472fb4..27381ba80 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs | |||
@@ -133,7 +133,7 @@ impl ast::Attr { | |||
133 | first_token.and_then(|token| token.next_token()).as_ref().map(SyntaxToken::kind); | 133 | first_token.and_then(|token| token.next_token()).as_ref().map(SyntaxToken::kind); |
134 | 134 | ||
135 | match (first_token_kind, second_token_kind) { | 135 | match (first_token_kind, second_token_kind) { |
136 | (Some(SyntaxKind::POUND), Some(T![!])) => AttrKind::Inner, | 136 | (Some(T![#]), Some(T![!])) => AttrKind::Inner, |
137 | _ => AttrKind::Outer, | 137 | _ => AttrKind::Outer, |
138 | } | 138 | } |
139 | } | 139 | } |
diff --git a/crates/syntax/src/parsing/lexer.rs b/crates/syntax/src/parsing/lexer.rs index 0cbba73c5..7c8d0a4c4 100644 --- a/crates/syntax/src/parsing/lexer.rs +++ b/crates/syntax/src/parsing/lexer.rs | |||
@@ -24,7 +24,7 @@ pub struct Token { | |||
24 | /// Beware that it checks for shebang first and its length contributes to resulting | 24 | /// Beware that it checks for shebang first and its length contributes to resulting |
25 | /// tokens offsets. | 25 | /// tokens offsets. |
26 | pub fn tokenize(text: &str) -> (Vec<Token>, Vec<SyntaxError>) { | 26 | pub fn tokenize(text: &str) -> (Vec<Token>, Vec<SyntaxError>) { |
27 | // non-empty string is a precondtion of `rustc_lexer::strip_shebang()`. | 27 | // non-empty string is a precondition of `rustc_lexer::strip_shebang()`. |
28 | if text.is_empty() { | 28 | if text.is_empty() { |
29 | return Default::default(); | 29 | return Default::default(); |
30 | } | 30 | } |
@@ -76,7 +76,7 @@ pub fn lex_single_syntax_kind(text: &str) -> Option<(SyntaxKind, Option<SyntaxEr | |||
76 | } | 76 | } |
77 | 77 | ||
78 | /// The same as `lex_single_syntax_kind()` but returns only `SyntaxKind` and | 78 | /// The same as `lex_single_syntax_kind()` but returns only `SyntaxKind` and |
79 | /// returns `None` if any tokenization error occured. | 79 | /// returns `None` if any tokenization error occurred. |
80 | /// | 80 | /// |
81 | /// Beware that unescape errors are not checked at tokenization time. | 81 | /// Beware that unescape errors are not checked at tokenization time. |
82 | pub fn lex_single_valid_syntax_kind(text: &str) -> Option<SyntaxKind> { | 82 | pub fn lex_single_valid_syntax_kind(text: &str) -> Option<SyntaxKind> { |
@@ -96,7 +96,7 @@ pub fn lex_single_valid_syntax_kind(text: &str) -> Option<SyntaxKind> { | |||
96 | /// | 96 | /// |
97 | /// Beware that unescape errors are not checked at tokenization time. | 97 | /// Beware that unescape errors are not checked at tokenization time. |
98 | fn lex_first_token(text: &str) -> Option<(Token, Option<SyntaxError>)> { | 98 | fn lex_first_token(text: &str) -> Option<(Token, Option<SyntaxError>)> { |
99 | // non-empty string is a precondtion of `rustc_lexer::first_token()`. | 99 | // non-empty string is a precondition of `rustc_lexer::first_token()`. |
100 | if text.is_empty() { | 100 | if text.is_empty() { |
101 | return None; | 101 | return None; |
102 | } | 102 | } |
@@ -117,7 +117,7 @@ fn rustc_token_kind_to_syntax_kind( | |||
117 | token_text: &str, | 117 | token_text: &str, |
118 | ) -> (SyntaxKind, Option<&'static str>) { | 118 | ) -> (SyntaxKind, Option<&'static str>) { |
119 | // A note on an intended tradeoff: | 119 | // A note on an intended tradeoff: |
120 | // We drop some useful infromation here (see patterns with double dots `..`) | 120 | // We drop some useful information here (see patterns with double dots `..`) |
121 | // Storing that info in `SyntaxKind` is not possible due to its layout requirements of | 121 | // Storing that info in `SyntaxKind` is not possible due to its layout requirements of |
122 | // being `u16` that come from `rowan::SyntaxKind`. | 122 | // being `u16` that come from `rowan::SyntaxKind`. |
123 | 123 | ||
diff --git a/crates/syntax/src/parsing/reparsing.rs b/crates/syntax/src/parsing/reparsing.rs index 190f5f67a..78eaf3410 100644 --- a/crates/syntax/src/parsing/reparsing.rs +++ b/crates/syntax/src/parsing/reparsing.rs | |||
@@ -223,7 +223,7 @@ mod tests { | |||
223 | do_check( | 223 | do_check( |
224 | r" | 224 | r" |
225 | fn foo() { | 225 | fn foo() { |
226 | let x = foo + <|>bar<|> | 226 | let x = foo + $0bar$0 |
227 | } | 227 | } |
228 | ", | 228 | ", |
229 | "baz", | 229 | "baz", |
@@ -232,7 +232,7 @@ fn foo() { | |||
232 | do_check( | 232 | do_check( |
233 | r" | 233 | r" |
234 | fn foo() { | 234 | fn foo() { |
235 | let x = foo<|> + bar<|> | 235 | let x = foo$0 + bar$0 |
236 | } | 236 | } |
237 | ", | 237 | ", |
238 | "baz", | 238 | "baz", |
@@ -241,7 +241,7 @@ fn foo() { | |||
241 | do_check( | 241 | do_check( |
242 | r" | 242 | r" |
243 | struct Foo { | 243 | struct Foo { |
244 | f: foo<|><|> | 244 | f: foo$0$0 |
245 | } | 245 | } |
246 | ", | 246 | ", |
247 | ",\n g: (),", | 247 | ",\n g: (),", |
@@ -252,7 +252,7 @@ struct Foo { | |||
252 | fn foo { | 252 | fn foo { |
253 | let; | 253 | let; |
254 | 1 + 1; | 254 | 1 + 1; |
255 | <|>92<|>; | 255 | $092$0; |
256 | } | 256 | } |
257 | ", | 257 | ", |
258 | "62", | 258 | "62", |
@@ -261,7 +261,7 @@ fn foo { | |||
261 | do_check( | 261 | do_check( |
262 | r" | 262 | r" |
263 | mod foo { | 263 | mod foo { |
264 | fn <|><|> | 264 | fn $0$0 |
265 | } | 265 | } |
266 | ", | 266 | ", |
267 | "bar", | 267 | "bar", |
@@ -271,7 +271,7 @@ mod foo { | |||
271 | do_check( | 271 | do_check( |
272 | r" | 272 | r" |
273 | trait Foo { | 273 | trait Foo { |
274 | type <|>Foo<|>; | 274 | type $0Foo$0; |
275 | } | 275 | } |
276 | ", | 276 | ", |
277 | "Output", | 277 | "Output", |
@@ -280,17 +280,17 @@ trait Foo { | |||
280 | do_check( | 280 | do_check( |
281 | r" | 281 | r" |
282 | impl IntoIterator<Item=i32> for Foo { | 282 | impl IntoIterator<Item=i32> for Foo { |
283 | f<|><|> | 283 | f$0$0 |
284 | } | 284 | } |
285 | ", | 285 | ", |
286 | "n next(", | 286 | "n next(", |
287 | 9, | 287 | 9, |
288 | ); | 288 | ); |
289 | do_check(r"use a::b::{foo,<|>,bar<|>};", "baz", 10); | 289 | do_check(r"use a::b::{foo,$0,bar$0};", "baz", 10); |
290 | do_check( | 290 | do_check( |
291 | r" | 291 | r" |
292 | pub enum A { | 292 | pub enum A { |
293 | Foo<|><|> | 293 | Foo$0$0 |
294 | } | 294 | } |
295 | ", | 295 | ", |
296 | "\nBar;\n", | 296 | "\nBar;\n", |
@@ -298,7 +298,7 @@ pub enum A { | |||
298 | ); | 298 | ); |
299 | do_check( | 299 | do_check( |
300 | r" | 300 | r" |
301 | foo!{a, b<|><|> d} | 301 | foo!{a, b$0$0 d} |
302 | ", | 302 | ", |
303 | ", c[3]", | 303 | ", c[3]", |
304 | 8, | 304 | 8, |
@@ -306,7 +306,7 @@ foo!{a, b<|><|> d} | |||
306 | do_check( | 306 | do_check( |
307 | r" | 307 | r" |
308 | fn foo() { | 308 | fn foo() { |
309 | vec![<|><|>] | 309 | vec![$0$0] |
310 | } | 310 | } |
311 | ", | 311 | ", |
312 | "123", | 312 | "123", |
@@ -315,7 +315,7 @@ fn foo() { | |||
315 | do_check( | 315 | do_check( |
316 | r" | 316 | r" |
317 | extern { | 317 | extern { |
318 | fn<|>;<|> | 318 | fn$0;$0 |
319 | } | 319 | } |
320 | ", | 320 | ", |
321 | " exit(code: c_int)", | 321 | " exit(code: c_int)", |
@@ -326,7 +326,7 @@ extern { | |||
326 | #[test] | 326 | #[test] |
327 | fn reparse_token_tests() { | 327 | fn reparse_token_tests() { |
328 | do_check( | 328 | do_check( |
329 | r"<|><|> | 329 | r"$0$0 |
330 | fn foo() -> i32 { 1 } | 330 | fn foo() -> i32 { 1 } |
331 | ", | 331 | ", |
332 | "\n\n\n \n", | 332 | "\n\n\n \n", |
@@ -334,49 +334,49 @@ fn foo() -> i32 { 1 } | |||
334 | ); | 334 | ); |
335 | do_check( | 335 | do_check( |
336 | r" | 336 | r" |
337 | fn foo() -> <|><|> {} | 337 | fn foo() -> $0$0 {} |
338 | ", | 338 | ", |
339 | " \n", | 339 | " \n", |
340 | 2, | 340 | 2, |
341 | ); | 341 | ); |
342 | do_check( | 342 | do_check( |
343 | r" | 343 | r" |
344 | fn <|>foo<|>() -> i32 { 1 } | 344 | fn $0foo$0() -> i32 { 1 } |
345 | ", | 345 | ", |
346 | "bar", | 346 | "bar", |
347 | 3, | 347 | 3, |
348 | ); | 348 | ); |
349 | do_check( | 349 | do_check( |
350 | r" | 350 | r" |
351 | fn foo<|><|>foo() { } | 351 | fn foo$0$0foo() { } |
352 | ", | 352 | ", |
353 | "bar", | 353 | "bar", |
354 | 6, | 354 | 6, |
355 | ); | 355 | ); |
356 | do_check( | 356 | do_check( |
357 | r" | 357 | r" |
358 | fn foo /* <|><|> */ () {} | 358 | fn foo /* $0$0 */ () {} |
359 | ", | 359 | ", |
360 | "some comment", | 360 | "some comment", |
361 | 6, | 361 | 6, |
362 | ); | 362 | ); |
363 | do_check( | 363 | do_check( |
364 | r" | 364 | r" |
365 | fn baz <|><|> () {} | 365 | fn baz $0$0 () {} |
366 | ", | 366 | ", |
367 | " \t\t\n\n", | 367 | " \t\t\n\n", |
368 | 2, | 368 | 2, |
369 | ); | 369 | ); |
370 | do_check( | 370 | do_check( |
371 | r" | 371 | r" |
372 | fn baz <|><|> () {} | 372 | fn baz $0$0 () {} |
373 | ", | 373 | ", |
374 | " \t\t\n\n", | 374 | " \t\t\n\n", |
375 | 2, | 375 | 2, |
376 | ); | 376 | ); |
377 | do_check( | 377 | do_check( |
378 | r" | 378 | r" |
379 | /// foo <|><|>omment | 379 | /// foo $0$0omment |
380 | mod { } | 380 | mod { } |
381 | ", | 381 | ", |
382 | "c", | 382 | "c", |
@@ -384,28 +384,28 @@ mod { } | |||
384 | ); | 384 | ); |
385 | do_check( | 385 | do_check( |
386 | r#" | 386 | r#" |
387 | fn -> &str { "Hello<|><|>" } | 387 | fn -> &str { "Hello$0$0" } |
388 | "#, | 388 | "#, |
389 | ", world", | 389 | ", world", |
390 | 7, | 390 | 7, |
391 | ); | 391 | ); |
392 | do_check( | 392 | do_check( |
393 | r#" | 393 | r#" |
394 | fn -> &str { // "Hello<|><|>" | 394 | fn -> &str { // "Hello$0$0" |
395 | "#, | 395 | "#, |
396 | ", world", | 396 | ", world", |
397 | 10, | 397 | 10, |
398 | ); | 398 | ); |
399 | do_check( | 399 | do_check( |
400 | r##" | 400 | r##" |
401 | fn -> &str { r#"Hello<|><|>"# | 401 | fn -> &str { r#"Hello$0$0"# |
402 | "##, | 402 | "##, |
403 | ", world", | 403 | ", world", |
404 | 10, | 404 | 10, |
405 | ); | 405 | ); |
406 | do_check( | 406 | do_check( |
407 | r" | 407 | r" |
408 | #[derive(<|>Copy<|>)] | 408 | #[derive($0Copy$0)] |
409 | enum Foo { | 409 | enum Foo { |
410 | 410 | ||
411 | } | 411 | } |
@@ -417,12 +417,12 @@ enum Foo { | |||
417 | 417 | ||
418 | #[test] | 418 | #[test] |
419 | fn reparse_str_token_with_error_unchanged() { | 419 | fn reparse_str_token_with_error_unchanged() { |
420 | do_check(r#""<|>Unclosed<|> string literal"#, "Still unclosed", 24); | 420 | do_check(r#""$0Unclosed$0 string literal"#, "Still unclosed", 24); |
421 | } | 421 | } |
422 | 422 | ||
423 | #[test] | 423 | #[test] |
424 | fn reparse_str_token_with_error_fixed() { | 424 | fn reparse_str_token_with_error_fixed() { |
425 | do_check(r#""unterinated<|><|>"#, "\"", 12); | 425 | do_check(r#""unterinated$0$0"#, "\"", 12); |
426 | } | 426 | } |
427 | 427 | ||
428 | #[test] | 428 | #[test] |
@@ -430,7 +430,7 @@ enum Foo { | |||
430 | do_check( | 430 | do_check( |
431 | r#"fn main() { | 431 | r#"fn main() { |
432 | if {} | 432 | if {} |
433 | 32 + 4<|><|> | 433 | 32 + 4$0$0 |
434 | return | 434 | return |
435 | if {} | 435 | if {} |
436 | }"#, | 436 | }"#, |
@@ -444,7 +444,7 @@ enum Foo { | |||
444 | do_check( | 444 | do_check( |
445 | r#"fn main() { | 445 | r#"fn main() { |
446 | if {} | 446 | if {} |
447 | 32 + 4<|><|> | 447 | 32 + 4$0$0 |
448 | return | 448 | return |
449 | if {} | 449 | if {} |
450 | }"#, | 450 | }"#, |
diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index 2ddaeb176..bfa2dc4ba 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs | |||
@@ -173,7 +173,7 @@ pub(crate) fn validate_block_structure(root: &SyntaxNode) { | |||
173 | assert_eq!( | 173 | assert_eq!( |
174 | node.parent(), | 174 | node.parent(), |
175 | pair.parent(), | 175 | pair.parent(), |
176 | "\nunpaired curleys:\n{}\n{:#?}\n", | 176 | "\nunpaired curlys:\n{}\n{:#?}\n", |
177 | root.text(), | 177 | root.text(), |
178 | root, | 178 | root, |
179 | ); | 179 | ); |
@@ -344,9 +344,9 @@ fn validate_trait_object_ty(ty: ast::DynTraitType) -> Option<SyntaxError> { | |||
344 | 344 | ||
345 | if tbl.bounds().count() > 1 { | 345 | if tbl.bounds().count() > 1 { |
346 | let dyn_token = ty.dyn_token()?; | 346 | let dyn_token = ty.dyn_token()?; |
347 | let potential_parentheses = | 347 | let potential_parenthesis = |
348 | algo::skip_trivia_token(dyn_token.prev_token()?, Direction::Prev)?; | 348 | algo::skip_trivia_token(dyn_token.prev_token()?, Direction::Prev)?; |
349 | let kind = potential_parentheses.kind(); | 349 | let kind = potential_parenthesis.kind(); |
350 | if !matches!(kind, T!['('] | T![<] | T![=]) { | 350 | if !matches!(kind, T!['('] | T![<] | T![=]) { |
351 | return Some(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range())); | 351 | return Some(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range())); |
352 | } | 352 | } |
diff --git a/crates/syntax/test_data/parser/inline/ok/0002_use_tree_list.rast b/crates/syntax/test_data/parser/inline/ok/0002_use_tree_list.rast index b1fb75ed1..f40500e38 100644 --- a/crates/syntax/test_data/parser/inline/ok/0002_use_tree_list.rast +++ b/crates/syntax/test_data/parser/inline/ok/0002_use_tree_list.rast | |||
@@ -1,4 +1,4 @@ | |||
1 | [email protected]9 | 1 | [email protected]8 |
2 | [email protected] | 2 | [email protected] |
3 | [email protected] "use" | 3 | [email protected] "use" |
4 | [email protected] " " | 4 | [email protected] " " |
@@ -75,62 +75,62 @@ [email protected] | |||
75 | [email protected] "}" | 75 | [email protected] "}" |
76 | [email protected] ";" | 76 | [email protected] ";" |
77 | [email protected] " " | 77 | [email protected] " " |
78 | [email protected]6 | 78 | [email protected]5 |
79 | [email protected] "// Rust 2015" | 79 | [email protected] "// Rust 2015" |
80 | [email protected] "\n" | 80 | [email protected] "\n" |
81 | [email protected] "use" | 81 | [email protected] "use" |
82 | [email protected] " " | 82 | [email protected] " " |
83 | [email protected]5 | 83 | [email protected]4 |
84 | [email protected] "::" | 84 | [email protected] "::" |
85 | [email protected]5 | 85 | [email protected]4 |
86 | [email protected] "{" | 86 | [email protected] "{" |
87 | [email protected]4 | 87 | [email protected]3 |
88 | [email protected]4 | 88 | [email protected]3 |
89 | [email protected]8 | 89 | [email protected]7 |
90 | [email protected] | 90 | [email protected] |
91 | [email protected] | 91 | [email protected] |
92 | [email protected] | 92 | [email protected] |
93 | [email protected] "some" | 93 | [email protected] "some" |
94 | [email protected] "::" | 94 | [email protected] "::" |
95 | [email protected]8 | 95 | [email protected]7 |
96 | [email protected]8 | 96 | [email protected]7 |
97 | [email protected]8 "arbritrary" | 97 | [email protected]7 "arbitrary" |
98 | COLON2@158..160 "::" | 98 | COLON2@157..159 "::" |
99 | PATH_SEGMENT@160..164 | 99 | PATH_SEGMENT@159..163 |
100 | NAME_REF@160..164 | 100 | NAME_REF@159..163 |
101 | IDENT@160..164 "path" | 101 | IDENT@159..163 "path" |
102 | R_CURLY@164..165 "}" | 102 | R_CURLY@163..164 "}" |
103 | SEMICOLON@165..166 ";" | 103 | SEMICOLON@164..165 ";" |
104 | WHITESPACE@166..167 " " | 104 | WHITESPACE@165..166 " " |
105 | USE@167..205 | 105 | USE@166..204 |
106 | COMMENT@167..179 "// Rust 2015" | 106 | COMMENT@166..178 "// Rust 2015" |
107 | WHITESPACE@179..180 "\n" | 107 | WHITESPACE@178..179 "\n" |
108 | USE_KW@180..183 "use" | 108 | USE_KW@179..182 "use" |
109 | WHITESPACE@183..184 " " | 109 | WHITESPACE@182..183 " " |
110 | USE_TREE@184..204 | 110 | USE_TREE@183..203 |
111 | COLON2@184..186 "::" | 111 | COLON2@183..185 "::" |
112 | USE_TREE_LIST@186..204 | 112 | USE_TREE_LIST@185..203 |
113 | L_CURLY@186..187 "{" | 113 | L_CURLY@185..186 "{" |
114 | USE_TREE@187..203 | 114 | USE_TREE@186..202 |
115 | USE_TREE_LIST@187..203 | 115 | USE_TREE_LIST@186..202 |
116 | L_CURLY@187..188 "{" | 116 | L_CURLY@186..187 "{" |
117 | USE_TREE@188..202 | 117 | USE_TREE@187..201 |
118 | USE_TREE_LIST@188..202 | 118 | USE_TREE_LIST@187..201 |
119 | L_CURLY@188..189 "{" | 119 | L_CURLY@187..188 "{" |
120 | USE_TREE@189..201 | 120 | USE_TREE@188..200 |
121 | PATH@189..201 | 121 | PATH@188..200 |
122 | PATH@189..193 | 122 | PATH@188..192 |
123 | PATH_SEGMENT@189..193 | 123 | PATH_SEGMENT@188..192 |
124 | NAME_REF@189..193 | 124 | NAME_REF@188..192 |
125 | IDENT@189..193 "root" | 125 | IDENT@188..192 "root" |
126 | COLON2@193..195 "::" | 126 | COLON2@192..194 "::" |
127 | PATH_SEGMENT@195..201 | 127 | PATH_SEGMENT@194..200 |
128 | NAME_REF@195..201 | 128 | NAME_REF@194..200 |
129 | IDENT@195..201 "export" | 129 | IDENT@194..200 "export" |
130 | R_CURLY@201..202 "}" | 130 | R_CURLY@200..201 "}" |
131 | R_CURLY@202..203 "}" | 131 | R_CURLY@201..202 "}" |
132 | R_CURLY@203..204 "}" | 132 | R_CURLY@202..203 "}" |
133 | SEMICOLON@204..205 ";" | 133 | SEMICOLON@203..204 ";" |
134 | WHITESPACE@205..206 " " | 134 | WHITESPACE@204..205 " " |
135 | COMMENT@206..248 "// Nonsensical but pe ..." | 135 | COMMENT@205..247 "// Nonsensical but pe ..." |
136 | WHITESPACE@248..249 "\n" | 136 | WHITESPACE@247..248 "\n" |
diff --git a/crates/syntax/test_data/parser/inline/ok/0002_use_tree_list.rs b/crates/syntax/test_data/parser/inline/ok/0002_use_tree_list.rs index 381cba1e2..02af4b446 100644 --- a/crates/syntax/test_data/parser/inline/ok/0002_use_tree_list.rs +++ b/crates/syntax/test_data/parser/inline/ok/0002_use_tree_list.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use {crate::path::from::root, or::path::from::crate_name}; // Rust 2018 (with a crate named `or`) | 1 | use {crate::path::from::root, or::path::from::crate_name}; // Rust 2018 (with a crate named `or`) |
2 | use {path::from::root}; // Rust 2015 | 2 | use {path::from::root}; // Rust 2015 |
3 | use ::{some::arbritrary::path}; // Rust 2015 | 3 | use ::{some::arbitrary::path}; // Rust 2015 |
4 | use ::{{{root::export}}}; // Nonsensical but perfectly legal nesting | 4 | use ::{{{root::export}}}; // Nonsensical but perfectly legal nesting |
diff --git a/crates/syntax/test_data/parser/inline/ok/0039_type_arg.rast b/crates/syntax/test_data/parser/inline/ok/0039_type_arg.rast index 51e881a8e..68c0f1c66 100644 --- a/crates/syntax/test_data/parser/inline/ok/0039_type_arg.rast +++ b/crates/syntax/test_data/parser/inline/ok/0039_type_arg.rast | |||
@@ -1,5 +1,5 @@ | |||
1 | SOURCE_FILE@0..46 | 1 | SOURCE_FILE@0..59 |
2 | TYPE_ALIAS@0..45 | 2 | [email protected]8 |
3 | [email protected] "type" | 3 | [email protected] "type" |
4 | [email protected] " " | 4 | [email protected] " " |
5 | [email protected] | 5 | [email protected] |
@@ -7,12 +7,12 @@ [email protected] | |||
7 | [email protected] " " | 7 | [email protected] " " |
8 | [email protected] "=" | 8 | [email protected] "=" |
9 | [email protected] " " | 9 | [email protected] " " |
10 | PATH_TYPE@9..44 | 10 | PATH_TYPE@9..57 |
11 | PATH@9..44 | 11 | PATH@9..57 |
12 | PATH_SEGMENT@9..44 | 12 | PATH_SEGMENT@9..57 |
13 | [email protected] | 13 | [email protected] |
14 | [email protected] "B" | 14 | [email protected] "B" |
15 | GENERIC_ARG_LIST@10..44 | 15 | GENERIC_ARG_LIST@10..57 |
16 | [email protected] "<" | 16 | [email protected] "<" |
17 | [email protected] | 17 | [email protected] |
18 | [email protected] | 18 | [email protected] |
@@ -51,6 +51,16 @@ [email protected] | |||
51 | [email protected] | 51 | [email protected] |
52 | [email protected] | 52 | [email protected] |
53 | [email protected] "u64" | 53 | [email protected] "u64" |
54 | [email protected] ">" | 54 | [email protected] "," |
55 | [email protected] ";" | 55 | [email protected] " " |
56 | [email protected] "\n" | 56 | [email protected] |
57 | [email protected] | ||
58 | [email protected] "true" | ||
59 | [email protected] "," | ||
60 | [email protected] " " | ||
61 | [email protected] | ||
62 | [email protected] | ||
63 | [email protected] "false" | ||
64 | [email protected] ">" | ||
65 | [email protected] ";" | ||
66 | [email protected] "\n" | ||
diff --git a/crates/syntax/test_data/parser/inline/ok/0039_type_arg.rs b/crates/syntax/test_data/parser/inline/ok/0039_type_arg.rs index 0d07d7651..6a8721a73 100644 --- a/crates/syntax/test_data/parser/inline/ok/0039_type_arg.rs +++ b/crates/syntax/test_data/parser/inline/ok/0039_type_arg.rs | |||
@@ -1 +1 @@ | |||
type A = B<'static, i32, 1, { 2 }, Item=u64>; | type A = B<'static, i32, 1, { 2 }, Item=u64, true, false>; | ||
diff --git a/crates/test_utils/Cargo.toml b/crates/test_utils/Cargo.toml index 93eecc678..06341f003 100644 --- a/crates/test_utils/Cargo.toml +++ b/crates/test_utils/Cargo.toml | |||
@@ -11,7 +11,7 @@ doctest = false | |||
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | # Avoid adding deps here, this crate is widely used in tests it should compile fast! | 13 | # Avoid adding deps here, this crate is widely used in tests it should compile fast! |
14 | difference = "2.0.0" | 14 | dissimilar = "1.0.2" |
15 | text-size = "1.0.0" | 15 | text-size = "1.0.0" |
16 | serde_json = "1.0.48" | 16 | serde_json = "1.0.48" |
17 | rustc-hash = "1.1.0" | 17 | rustc-hash = "1.1.0" |
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index 05940a546..e19d2ad61 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | //! Most notable things are: | 3 | //! Most notable things are: |
4 | //! | 4 | //! |
5 | //! * Rich text comparison, which outputs a diff. | 5 | //! * Rich text comparison, which outputs a diff. |
6 | //! * Extracting markup (mainly, `<|>` markers) out of fixture strings. | 6 | //! * Extracting markup (mainly, `$0` markers) out of fixture strings. |
7 | //! * marks (see the eponymous module). | 7 | //! * marks (see the eponymous module). |
8 | 8 | ||
9 | #[macro_use] | 9 | #[macro_use] |
@@ -20,12 +20,13 @@ use serde_json::Value; | |||
20 | use stdx::lines_with_ends; | 20 | use stdx::lines_with_ends; |
21 | use text_size::{TextRange, TextSize}; | 21 | use text_size::{TextRange, TextSize}; |
22 | 22 | ||
23 | pub use difference::Changeset as __Changeset; | 23 | pub use dissimilar::diff as __diff; |
24 | pub use rustc_hash::FxHashMap; | 24 | pub use rustc_hash::FxHashMap; |
25 | 25 | ||
26 | pub use crate::fixture::Fixture; | 26 | pub use crate::fixture::Fixture; |
27 | 27 | ||
28 | pub const CURSOR_MARKER: &str = "<|>"; | 28 | pub const CURSOR_MARKER: &str = "$0"; |
29 | pub const ESCAPED_CURSOR_MARKER: &str = "\\$0"; | ||
29 | 30 | ||
30 | /// Asserts that two strings are equal, otherwise displays a rich diff between them. | 31 | /// Asserts that two strings are equal, otherwise displays a rich diff between them. |
31 | /// | 32 | /// |
@@ -45,8 +46,8 @@ macro_rules! assert_eq_text { | |||
45 | if left.trim() == right.trim() { | 46 | if left.trim() == right.trim() { |
46 | std::eprintln!("Left:\n{:?}\n\nRight:\n{:?}\n\nWhitespace difference\n", left, right); | 47 | std::eprintln!("Left:\n{:?}\n\nRight:\n{:?}\n\nWhitespace difference\n", left, right); |
47 | } else { | 48 | } else { |
48 | let changeset = $crate::__Changeset::new(left, right, "\n"); | 49 | let diff = $crate::__diff(left, right); |
49 | std::eprintln!("Left:\n{}\n\nRight:\n{}\n\nDiff:\n{}\n", left, right, changeset); | 50 | std::eprintln!("Left:\n{}\n\nRight:\n{}\n\nDiff:\n{}\n", left, right, $crate::format_diff(diff)); |
50 | } | 51 | } |
51 | std::eprintln!($($tt)*); | 52 | std::eprintln!($($tt)*); |
52 | panic!("text differs"); | 53 | panic!("text differs"); |
@@ -62,7 +63,7 @@ pub fn extract_offset(text: &str) -> (TextSize, String) { | |||
62 | } | 63 | } |
63 | } | 64 | } |
64 | 65 | ||
65 | /// Returns the offset of the first occurence of `<|>` marker and the copy of `text` | 66 | /// Returns the offset of the first occurrence of `$0` marker and the copy of `text` |
66 | /// without the marker. | 67 | /// without the marker. |
67 | fn try_extract_offset(text: &str) -> Option<(TextSize, String)> { | 68 | fn try_extract_offset(text: &str) -> Option<(TextSize, String)> { |
68 | let cursor_pos = text.find(CURSOR_MARKER)?; | 69 | let cursor_pos = text.find(CURSOR_MARKER)?; |
@@ -81,7 +82,7 @@ pub fn extract_range(text: &str) -> (TextRange, String) { | |||
81 | } | 82 | } |
82 | } | 83 | } |
83 | 84 | ||
84 | /// Returns `TextRange` between the first two markers `<|>...<|>` and the copy | 85 | /// Returns `TextRange` between the first two markers `$0...$0` and the copy |
85 | /// of `text` without both of these markers. | 86 | /// of `text` without both of these markers. |
86 | fn try_extract_range(text: &str) -> Option<(TextRange, String)> { | 87 | fn try_extract_range(text: &str) -> Option<(TextRange, String)> { |
87 | let (start, text) = try_extract_offset(text)?; | 88 | let (start, text) = try_extract_offset(text)?; |
@@ -104,11 +105,11 @@ impl From<RangeOrOffset> for TextRange { | |||
104 | } | 105 | } |
105 | } | 106 | } |
106 | 107 | ||
107 | /// Extracts `TextRange` or `TextSize` depending on the amount of `<|>` markers | 108 | /// Extracts `TextRange` or `TextSize` depending on the amount of `$0` markers |
108 | /// found in `text`. | 109 | /// found in `text`. |
109 | /// | 110 | /// |
110 | /// # Panics | 111 | /// # Panics |
111 | /// Panics if no `<|>` marker is present in the `text`. | 112 | /// Panics if no `$0` marker is present in the `text`. |
112 | pub fn extract_range_or_offset(text: &str) -> (RangeOrOffset, String) { | 113 | pub fn extract_range_or_offset(text: &str) -> (RangeOrOffset, String) { |
113 | if let Some((range, text)) = try_extract_range(text) { | 114 | if let Some((range, text)) = try_extract_range(text) { |
114 | return (RangeOrOffset::Range(range), text); | 115 | return (RangeOrOffset::Range(range), text); |
@@ -164,12 +165,12 @@ fn test_extract_tags() { | |||
164 | assert_eq!(actual, vec![("fn main() {}", Some("fn".into())), ("main", None),]); | 165 | assert_eq!(actual, vec![("fn main() {}", Some("fn".into())), ("main", None),]); |
165 | } | 166 | } |
166 | 167 | ||
167 | /// Inserts `<|>` marker into the `text` at `offset`. | 168 | /// Inserts `$0` marker into the `text` at `offset`. |
168 | pub fn add_cursor(text: &str, offset: TextSize) -> String { | 169 | pub fn add_cursor(text: &str, offset: TextSize) -> String { |
169 | let offset: usize = offset.into(); | 170 | let offset: usize = offset.into(); |
170 | let mut res = String::new(); | 171 | let mut res = String::new(); |
171 | res.push_str(&text[..offset]); | 172 | res.push_str(&text[..offset]); |
172 | res.push_str("<|>"); | 173 | res.push_str("$0"); |
173 | res.push_str(&text[offset..]); | 174 | res.push_str(&text[offset..]); |
174 | res | 175 | res |
175 | } | 176 | } |
@@ -392,3 +393,16 @@ pub fn project_dir() -> PathBuf { | |||
392 | let dir = env!("CARGO_MANIFEST_DIR"); | 393 | let dir = env!("CARGO_MANIFEST_DIR"); |
393 | PathBuf::from(dir).parent().unwrap().parent().unwrap().to_owned() | 394 | PathBuf::from(dir).parent().unwrap().parent().unwrap().to_owned() |
394 | } | 395 | } |
396 | |||
397 | pub fn format_diff(chunks: Vec<dissimilar::Chunk>) -> String { | ||
398 | let mut buf = String::new(); | ||
399 | for chunk in chunks { | ||
400 | let formatted = match chunk { | ||
401 | dissimilar::Chunk::Equal(text) => text.into(), | ||
402 | dissimilar::Chunk::Delete(text) => format!("\x1b[41m{}\x1b[0m", text), | ||
403 | dissimilar::Chunk::Insert(text) => format!("\x1b[42m{}\x1b[0m", text), | ||
404 | }; | ||
405 | buf.push_str(&formatted); | ||
406 | } | ||
407 | buf | ||
408 | } | ||
diff --git a/crates/vfs/src/lib.rs b/crates/vfs/src/lib.rs index 9cf2afd33..2b7b14524 100644 --- a/crates/vfs/src/lib.rs +++ b/crates/vfs/src/lib.rs | |||
@@ -2,43 +2,46 @@ | |||
2 | //! | 2 | //! |
3 | //! VFS stores all files read by rust-analyzer. Reading file contents from VFS | 3 | //! VFS stores all files read by rust-analyzer. Reading file contents from VFS |
4 | //! always returns the same contents, unless VFS was explicitly modified with | 4 | //! always returns the same contents, unless VFS was explicitly modified with |
5 | //! `set_file_contents`. All changes to VFS are logged, and can be retrieved via | 5 | //! [`set_file_contents`]. All changes to VFS are logged, and can be retrieved via |
6 | //! `take_changes` method. The pack of changes is then pushed to `salsa` and | 6 | //! [`take_changes`] method. The pack of changes is then pushed to `salsa` and |
7 | //! triggers incremental recomputation. | 7 | //! triggers incremental recomputation. |
8 | //! | 8 | //! |
9 | //! Files in VFS are identified with `FileId`s -- interned paths. The notion of | 9 | //! Files in VFS are identified with [`FileId`]s -- interned paths. The notion of |
10 | //! the path, `VfsPath` is somewhat abstract: at the moment, it is represented | 10 | //! the path, [`VfsPath`] is somewhat abstract: at the moment, it is represented |
11 | //! as an `std::path::PathBuf` internally, but this is an implementation detail. | 11 | //! as an [`std::path::PathBuf`] internally, but this is an implementation detail. |
12 | //! | 12 | //! |
13 | //! VFS doesn't do IO or file watching itself. For that, see the `loader` | 13 | //! VFS doesn't do IO or file watching itself. For that, see the [`loader`] |
14 | //! module. `loader::Handle` is an object-safe trait which abstracts both file | 14 | //! module. [`loader::Handle`] is an object-safe trait which abstracts both file |
15 | //! loading and file watching. `Handle` is dynamically configured with a set of | 15 | //! loading and file watching. [`Handle`] is dynamically configured with a set of |
16 | //! directory entries which should be scanned and watched. `Handle` then | 16 | //! directory entries which should be scanned and watched. [`Handle`] then |
17 | //! asynchronously pushes file changes. Directory entries are configured in | 17 | //! asynchronously pushes file changes. Directory entries are configured in |
18 | //! free-form via list of globs, it's up to the `Handle` to interpret the globs | 18 | //! free-form via list of globs, it's up to the [`Handle`] to interpret the globs |
19 | //! in any specific way. | 19 | //! in any specific way. |
20 | //! | 20 | //! |
21 | //! A simple `WalkdirLoaderHandle` is provided, which doesn't implement watching | 21 | //! VFS stores a flat list of files. [`file_set::FileSet`] can partition this list |
22 | //! and just scans the directory using walkdir. | 22 | //! of files into disjoint sets of files. Traversal-like operations (including |
23 | //! | 23 | //! getting the neighbor file by the relative path) are handled by the [`FileSet`]. |
24 | //! VFS stores a flat list of files. `FileSet` can partition this list of files | 24 | //! [`FileSet`]s are also pushed to salsa and cause it to re-check `mod foo;` |
25 | //! into disjoint sets of files. Traversal-like operations (including getting | ||
26 | //! the neighbor file by the relative path) are handled by the `FileSet`. | ||
27 | //! `FileSet`s are also pushed to salsa and cause it to re-check `mod foo;` | ||
28 | //! declarations when files are created or deleted. | 25 | //! declarations when files are created or deleted. |
29 | //! | 26 | //! |
30 | //! `file_set::FileSet` and `loader::Entry` play similar, but different roles. | 27 | //! [`FileSet`] and [`loader::Entry`] play similar, but different roles. |
31 | //! Both specify the "set of paths/files", one is geared towards file watching, | 28 | //! Both specify the "set of paths/files", one is geared towards file watching, |
32 | //! the other towards salsa changes. In particular, single `file_set::FileSet` | 29 | //! the other towards salsa changes. In particular, single [`FileSet`] |
33 | //! may correspond to several `loader::Entry`. For example, a crate from | 30 | //! may correspond to several [`loader::Entry`]. For example, a crate from |
34 | //! crates.io which uses code generation would have two `Entries` -- for sources | 31 | //! crates.io which uses code generation would have two [`Entries`] -- for sources |
35 | //! in `~/.cargo`, and for generated code in `./target/debug/build`. It will | 32 | //! in `~/.cargo`, and for generated code in `./target/debug/build`. It will |
36 | //! have a single `FileSet` which unions the two sources. | 33 | //! have a single [`FileSet`] which unions the two sources. |
37 | mod vfs_path; | 34 | //! |
38 | mod path_interner; | 35 | //! [`set_file_contents`]: Vfs::set_file_contents |
36 | //! [`take_changes`]: Vfs::take_changes | ||
37 | //! [`FileSet`]: file_set::FileSet | ||
38 | //! [`Handle`]: loader::Handle | ||
39 | //! [`Entries`]: loader::Entry | ||
39 | mod anchored_path; | 40 | mod anchored_path; |
40 | pub mod file_set; | 41 | pub mod file_set; |
41 | pub mod loader; | 42 | pub mod loader; |
43 | mod path_interner; | ||
44 | mod vfs_path; | ||
42 | 45 | ||
43 | use std::{fmt, mem}; | 46 | use std::{fmt, mem}; |
44 | 47 | ||