diff options
Diffstat (limited to 'crates')
22 files changed, 429 insertions, 114 deletions
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs index edd8255f4..ee614de72 100644 --- a/crates/ra_assists/src/assist_context.rs +++ b/crates/ra_assists/src/assist_context.rs | |||
@@ -252,7 +252,7 @@ impl AssistBuilder { | |||
252 | pub(crate) fn rewrite(&mut self, rewriter: SyntaxRewriter) { | 252 | pub(crate) fn rewrite(&mut self, rewriter: SyntaxRewriter) { |
253 | let node = rewriter.rewrite_root().unwrap(); | 253 | let node = rewriter.rewrite_root().unwrap(); |
254 | let new = rewriter.rewrite(&node); | 254 | let new = rewriter.rewrite(&node); |
255 | algo::diff(&node, &new).into_text_edit(&mut self.edit) | 255 | algo::diff(&node, &new).into_text_edit(&mut self.edit); |
256 | } | 256 | } |
257 | 257 | ||
258 | // FIXME: kill this API | 258 | // FIXME: kill this API |
diff --git a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs index 0197a8cf0..b4784c333 100644 --- a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs +++ b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs | |||
@@ -1,7 +1,10 @@ | |||
1 | use hir; | 1 | use hir; |
2 | use ra_syntax::{ast, AstNode, SmolStr, TextRange}; | 2 | use ra_syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SmolStr, SyntaxNode}; |
3 | 3 | ||
4 | use crate::{utils::insert_use_statement, AssistContext, AssistId, Assists}; | 4 | use crate::{ |
5 | utils::{find_insert_use_container, insert_use_statement}, | ||
6 | AssistContext, AssistId, Assists, | ||
7 | }; | ||
5 | 8 | ||
6 | // Assist: replace_qualified_name_with_use | 9 | // Assist: replace_qualified_name_with_use |
7 | // | 10 | // |
@@ -39,16 +42,18 @@ pub(crate) fn replace_qualified_name_with_use( | |||
39 | target, | 42 | target, |
40 | |builder| { | 43 | |builder| { |
41 | let path_to_import = hir_path.mod_path().clone(); | 44 | let path_to_import = hir_path.mod_path().clone(); |
45 | let container = match find_insert_use_container(path.syntax(), ctx) { | ||
46 | Some(c) => c, | ||
47 | None => return, | ||
48 | }; | ||
42 | insert_use_statement(path.syntax(), &path_to_import, ctx, builder.text_edit_builder()); | 49 | insert_use_statement(path.syntax(), &path_to_import, ctx, builder.text_edit_builder()); |
43 | 50 | ||
44 | if let Some(last) = path.segment() { | 51 | // Now that we've brought the name into scope, re-qualify all paths that could be |
45 | // Here we are assuming the assist will provide a correct use statement | 52 | // affected (that is, all paths inside the node we added the `use` to). |
46 | // so we can delete the path qualifier | 53 | let mut rewriter = SyntaxRewriter::default(); |
47 | builder.delete(TextRange::new( | 54 | let syntax = container.either(|l| l.syntax().clone(), |r| r.syntax().clone()); |
48 | path.syntax().text_range().start(), | 55 | shorten_paths(&mut rewriter, syntax, path); |
49 | last.syntax().text_range().start(), | 56 | builder.rewrite(rewriter); |
50 | )); | ||
51 | } | ||
52 | }, | 57 | }, |
53 | ) | 58 | ) |
54 | } | 59 | } |
@@ -73,6 +78,69 @@ fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> { | |||
73 | Some(ps) | 78 | Some(ps) |
74 | } | 79 | } |
75 | 80 | ||
81 | /// Adds replacements to `re` that shorten `path` in all descendants of `node`. | ||
82 | fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: ast::Path) { | ||
83 | for child in node.children() { | ||
84 | match_ast! { | ||
85 | match child { | ||
86 | // Don't modify `use` items, as this can break the `use` item when injecting a new | ||
87 | // import into the use tree. | ||
88 | ast::UseItem(_it) => continue, | ||
89 | // Don't descend into submodules, they don't have the same `use` items in scope. | ||
90 | ast::Module(_it) => continue, | ||
91 | |||
92 | ast::Path(p) => { | ||
93 | match maybe_replace_path(rewriter, p.clone(), path.clone()) { | ||
94 | Some(()) => {}, | ||
95 | None => shorten_paths(rewriter, p.syntax().clone(), path.clone()), | ||
96 | } | ||
97 | }, | ||
98 | _ => shorten_paths(rewriter, child, path.clone()), | ||
99 | } | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | |||
104 | fn maybe_replace_path( | ||
105 | rewriter: &mut SyntaxRewriter<'static>, | ||
106 | path: ast::Path, | ||
107 | target: ast::Path, | ||
108 | ) -> Option<()> { | ||
109 | if !path_eq(path.clone(), target.clone()) { | ||
110 | return None; | ||
111 | } | ||
112 | |||
113 | // Shorten `path`, leaving only its last segment. | ||
114 | if let Some(parent) = path.qualifier() { | ||
115 | rewriter.delete(parent.syntax()); | ||
116 | } | ||
117 | if let Some(double_colon) = path.coloncolon_token() { | ||
118 | rewriter.delete(&double_colon); | ||
119 | } | ||
120 | |||
121 | Some(()) | ||
122 | } | ||
123 | |||
124 | fn path_eq(lhs: ast::Path, rhs: ast::Path) -> bool { | ||
125 | let mut lhs_curr = lhs; | ||
126 | let mut rhs_curr = rhs; | ||
127 | loop { | ||
128 | match (lhs_curr.segment(), rhs_curr.segment()) { | ||
129 | (Some(lhs), Some(rhs)) if lhs.syntax().text() == rhs.syntax().text() => (), | ||
130 | _ => return false, | ||
131 | } | ||
132 | |||
133 | match (lhs_curr.qualifier(), rhs_curr.qualifier()) { | ||
134 | (Some(lhs), Some(rhs)) => { | ||
135 | lhs_curr = lhs; | ||
136 | rhs_curr = rhs; | ||
137 | } | ||
138 | (None, None) => return true, | ||
139 | _ => return false, | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | |||
76 | #[cfg(test)] | 144 | #[cfg(test)] |
77 | mod tests { | 145 | mod tests { |
78 | use crate::tests::{check_assist, check_assist_not_applicable}; | 146 | use crate::tests::{check_assist, check_assist_not_applicable}; |
@@ -83,10 +151,10 @@ mod tests { | |||
83 | fn test_replace_add_use_no_anchor() { | 151 | fn test_replace_add_use_no_anchor() { |
84 | check_assist( | 152 | check_assist( |
85 | replace_qualified_name_with_use, | 153 | replace_qualified_name_with_use, |
86 | " | 154 | r" |
87 | std::fmt::Debug<|> | 155 | std::fmt::Debug<|> |
88 | ", | 156 | ", |
89 | " | 157 | r" |
90 | use std::fmt::Debug; | 158 | use std::fmt::Debug; |
91 | 159 | ||
92 | Debug | 160 | Debug |
@@ -97,13 +165,13 @@ Debug | |||
97 | fn test_replace_add_use_no_anchor_with_item_below() { | 165 | fn test_replace_add_use_no_anchor_with_item_below() { |
98 | check_assist( | 166 | check_assist( |
99 | replace_qualified_name_with_use, | 167 | replace_qualified_name_with_use, |
100 | " | 168 | r" |
101 | std::fmt::Debug<|> | 169 | std::fmt::Debug<|> |
102 | 170 | ||
103 | fn main() { | 171 | fn main() { |
104 | } | 172 | } |
105 | ", | 173 | ", |
106 | " | 174 | r" |
107 | use std::fmt::Debug; | 175 | use std::fmt::Debug; |
108 | 176 | ||
109 | Debug | 177 | Debug |
@@ -118,13 +186,13 @@ fn main() { | |||
118 | fn test_replace_add_use_no_anchor_with_item_above() { | 186 | fn test_replace_add_use_no_anchor_with_item_above() { |
119 | check_assist( | 187 | check_assist( |
120 | replace_qualified_name_with_use, | 188 | replace_qualified_name_with_use, |
121 | " | 189 | r" |
122 | fn main() { | 190 | fn main() { |
123 | } | 191 | } |
124 | 192 | ||
125 | std::fmt::Debug<|> | 193 | std::fmt::Debug<|> |
126 | ", | 194 | ", |
127 | " | 195 | r" |
128 | use std::fmt::Debug; | 196 | use std::fmt::Debug; |
129 | 197 | ||
130 | fn main() { | 198 | fn main() { |
@@ -139,10 +207,10 @@ Debug | |||
139 | fn test_replace_add_use_no_anchor_2seg() { | 207 | fn test_replace_add_use_no_anchor_2seg() { |
140 | check_assist( | 208 | check_assist( |
141 | replace_qualified_name_with_use, | 209 | replace_qualified_name_with_use, |
142 | " | 210 | r" |
143 | std::fmt<|>::Debug | 211 | std::fmt<|>::Debug |
144 | ", | 212 | ", |
145 | " | 213 | r" |
146 | use std::fmt; | 214 | use std::fmt; |
147 | 215 | ||
148 | fmt::Debug | 216 | fmt::Debug |
@@ -154,13 +222,13 @@ fmt::Debug | |||
154 | fn test_replace_add_use() { | 222 | fn test_replace_add_use() { |
155 | check_assist( | 223 | check_assist( |
156 | replace_qualified_name_with_use, | 224 | replace_qualified_name_with_use, |
157 | " | 225 | r" |
158 | use stdx; | 226 | use stdx; |
159 | 227 | ||
160 | impl std::fmt::Debug<|> for Foo { | 228 | impl std::fmt::Debug<|> for Foo { |
161 | } | 229 | } |
162 | ", | 230 | ", |
163 | " | 231 | r" |
164 | use stdx; | 232 | use stdx; |
165 | use std::fmt::Debug; | 233 | use std::fmt::Debug; |
166 | 234 | ||
@@ -174,11 +242,11 @@ impl Debug for Foo { | |||
174 | fn test_replace_file_use_other_anchor() { | 242 | fn test_replace_file_use_other_anchor() { |
175 | check_assist( | 243 | check_assist( |
176 | replace_qualified_name_with_use, | 244 | replace_qualified_name_with_use, |
177 | " | 245 | r" |
178 | impl std::fmt::Debug<|> for Foo { | 246 | impl std::fmt::Debug<|> for Foo { |
179 | } | 247 | } |
180 | ", | 248 | ", |
181 | " | 249 | r" |
182 | use std::fmt::Debug; | 250 | use std::fmt::Debug; |
183 | 251 | ||
184 | impl Debug for Foo { | 252 | impl Debug for Foo { |
@@ -191,11 +259,11 @@ impl Debug for Foo { | |||
191 | fn test_replace_add_use_other_anchor_indent() { | 259 | fn test_replace_add_use_other_anchor_indent() { |
192 | check_assist( | 260 | check_assist( |
193 | replace_qualified_name_with_use, | 261 | replace_qualified_name_with_use, |
194 | " | 262 | r" |
195 | impl std::fmt::Debug<|> for Foo { | 263 | impl std::fmt::Debug<|> for Foo { |
196 | } | 264 | } |
197 | ", | 265 | ", |
198 | " | 266 | r" |
199 | use std::fmt::Debug; | 267 | use std::fmt::Debug; |
200 | 268 | ||
201 | impl Debug for Foo { | 269 | impl Debug for Foo { |
@@ -208,13 +276,13 @@ impl Debug for Foo { | |||
208 | fn test_replace_split_different() { | 276 | fn test_replace_split_different() { |
209 | check_assist( | 277 | check_assist( |
210 | replace_qualified_name_with_use, | 278 | replace_qualified_name_with_use, |
211 | " | 279 | r" |
212 | use std::fmt; | 280 | use std::fmt; |
213 | 281 | ||
214 | impl std::io<|> for Foo { | 282 | impl std::io<|> for Foo { |
215 | } | 283 | } |
216 | ", | 284 | ", |
217 | " | 285 | r" |
218 | use std::{io, fmt}; | 286 | use std::{io, fmt}; |
219 | 287 | ||
220 | impl io for Foo { | 288 | impl io for Foo { |
@@ -227,13 +295,13 @@ impl io for Foo { | |||
227 | fn test_replace_split_self_for_use() { | 295 | fn test_replace_split_self_for_use() { |
228 | check_assist( | 296 | check_assist( |
229 | replace_qualified_name_with_use, | 297 | replace_qualified_name_with_use, |
230 | " | 298 | r" |
231 | use std::fmt; | 299 | use std::fmt; |
232 | 300 | ||
233 | impl std::fmt::Debug<|> for Foo { | 301 | impl std::fmt::Debug<|> for Foo { |
234 | } | 302 | } |
235 | ", | 303 | ", |
236 | " | 304 | r" |
237 | use std::fmt::{self, Debug, }; | 305 | use std::fmt::{self, Debug, }; |
238 | 306 | ||
239 | impl Debug for Foo { | 307 | impl Debug for Foo { |
@@ -246,13 +314,13 @@ impl Debug for Foo { | |||
246 | fn test_replace_split_self_for_target() { | 314 | fn test_replace_split_self_for_target() { |
247 | check_assist( | 315 | check_assist( |
248 | replace_qualified_name_with_use, | 316 | replace_qualified_name_with_use, |
249 | " | 317 | r" |
250 | use std::fmt::Debug; | 318 | use std::fmt::Debug; |
251 | 319 | ||
252 | impl std::fmt<|> for Foo { | 320 | impl std::fmt<|> for Foo { |
253 | } | 321 | } |
254 | ", | 322 | ", |
255 | " | 323 | r" |
256 | use std::fmt::{self, Debug}; | 324 | use std::fmt::{self, Debug}; |
257 | 325 | ||
258 | impl fmt for Foo { | 326 | impl fmt for Foo { |
@@ -265,13 +333,13 @@ impl fmt for Foo { | |||
265 | fn test_replace_add_to_nested_self_nested() { | 333 | fn test_replace_add_to_nested_self_nested() { |
266 | check_assist( | 334 | check_assist( |
267 | replace_qualified_name_with_use, | 335 | replace_qualified_name_with_use, |
268 | " | 336 | r" |
269 | use std::fmt::{Debug, nested::{Display}}; | 337 | use std::fmt::{Debug, nested::{Display}}; |
270 | 338 | ||
271 | impl std::fmt::nested<|> for Foo { | 339 | impl std::fmt::nested<|> for Foo { |
272 | } | 340 | } |
273 | ", | 341 | ", |
274 | " | 342 | r" |
275 | use std::fmt::{Debug, nested::{Display, self}}; | 343 | use std::fmt::{Debug, nested::{Display, self}}; |
276 | 344 | ||
277 | impl nested for Foo { | 345 | impl nested for Foo { |
@@ -284,13 +352,13 @@ impl nested for Foo { | |||
284 | fn test_replace_add_to_nested_self_already_included() { | 352 | fn test_replace_add_to_nested_self_already_included() { |
285 | check_assist( | 353 | check_assist( |
286 | replace_qualified_name_with_use, | 354 | replace_qualified_name_with_use, |
287 | " | 355 | r" |
288 | use std::fmt::{Debug, nested::{self, Display}}; | 356 | use std::fmt::{Debug, nested::{self, Display}}; |
289 | 357 | ||
290 | impl std::fmt::nested<|> for Foo { | 358 | impl std::fmt::nested<|> for Foo { |
291 | } | 359 | } |
292 | ", | 360 | ", |
293 | " | 361 | r" |
294 | use std::fmt::{Debug, nested::{self, Display}}; | 362 | use std::fmt::{Debug, nested::{self, Display}}; |
295 | 363 | ||
296 | impl nested for Foo { | 364 | impl nested for Foo { |
@@ -303,13 +371,13 @@ impl nested for Foo { | |||
303 | fn test_replace_add_to_nested_nested() { | 371 | fn test_replace_add_to_nested_nested() { |
304 | check_assist( | 372 | check_assist( |
305 | replace_qualified_name_with_use, | 373 | replace_qualified_name_with_use, |
306 | " | 374 | r" |
307 | use std::fmt::{Debug, nested::{Display}}; | 375 | use std::fmt::{Debug, nested::{Display}}; |
308 | 376 | ||
309 | impl std::fmt::nested::Debug<|> for Foo { | 377 | impl std::fmt::nested::Debug<|> for Foo { |
310 | } | 378 | } |
311 | ", | 379 | ", |
312 | " | 380 | r" |
313 | use std::fmt::{Debug, nested::{Display, Debug}}; | 381 | use std::fmt::{Debug, nested::{Display, Debug}}; |
314 | 382 | ||
315 | impl Debug for Foo { | 383 | impl Debug for Foo { |
@@ -322,13 +390,13 @@ impl Debug for Foo { | |||
322 | fn test_replace_split_common_target_longer() { | 390 | fn test_replace_split_common_target_longer() { |
323 | check_assist( | 391 | check_assist( |
324 | replace_qualified_name_with_use, | 392 | replace_qualified_name_with_use, |
325 | " | 393 | r" |
326 | use std::fmt::Debug; | 394 | use std::fmt::Debug; |
327 | 395 | ||
328 | impl std::fmt::nested::Display<|> for Foo { | 396 | impl std::fmt::nested::Display<|> for Foo { |
329 | } | 397 | } |
330 | ", | 398 | ", |
331 | " | 399 | r" |
332 | use std::fmt::{nested::Display, Debug}; | 400 | use std::fmt::{nested::Display, Debug}; |
333 | 401 | ||
334 | impl Display for Foo { | 402 | impl Display for Foo { |
@@ -341,13 +409,13 @@ impl Display for Foo { | |||
341 | fn test_replace_split_common_use_longer() { | 409 | fn test_replace_split_common_use_longer() { |
342 | check_assist( | 410 | check_assist( |
343 | replace_qualified_name_with_use, | 411 | replace_qualified_name_with_use, |
344 | " | 412 | r" |
345 | use std::fmt::nested::Debug; | 413 | use std::fmt::nested::Debug; |
346 | 414 | ||
347 | impl std::fmt::Display<|> for Foo { | 415 | impl std::fmt::Display<|> for Foo { |
348 | } | 416 | } |
349 | ", | 417 | ", |
350 | " | 418 | r" |
351 | use std::fmt::{Display, nested::Debug}; | 419 | use std::fmt::{Display, nested::Debug}; |
352 | 420 | ||
353 | impl Display for Foo { | 421 | impl Display for Foo { |
@@ -360,7 +428,7 @@ impl Display for Foo { | |||
360 | fn test_replace_use_nested_import() { | 428 | fn test_replace_use_nested_import() { |
361 | check_assist( | 429 | check_assist( |
362 | replace_qualified_name_with_use, | 430 | replace_qualified_name_with_use, |
363 | " | 431 | r" |
364 | use crate::{ | 432 | use crate::{ |
365 | ty::{Substs, Ty}, | 433 | ty::{Substs, Ty}, |
366 | AssocItem, | 434 | AssocItem, |
@@ -368,7 +436,7 @@ use crate::{ | |||
368 | 436 | ||
369 | fn foo() { crate::ty::lower<|>::trait_env() } | 437 | fn foo() { crate::ty::lower<|>::trait_env() } |
370 | ", | 438 | ", |
371 | " | 439 | r" |
372 | use crate::{ | 440 | use crate::{ |
373 | ty::{Substs, Ty, lower}, | 441 | ty::{Substs, Ty, lower}, |
374 | AssocItem, | 442 | AssocItem, |
@@ -383,13 +451,13 @@ fn foo() { lower::trait_env() } | |||
383 | fn test_replace_alias() { | 451 | fn test_replace_alias() { |
384 | check_assist( | 452 | check_assist( |
385 | replace_qualified_name_with_use, | 453 | replace_qualified_name_with_use, |
386 | " | 454 | r" |
387 | use std::fmt as foo; | 455 | use std::fmt as foo; |
388 | 456 | ||
389 | impl foo::Debug<|> for Foo { | 457 | impl foo::Debug<|> for Foo { |
390 | } | 458 | } |
391 | ", | 459 | ", |
392 | " | 460 | r" |
393 | use std::fmt as foo; | 461 | use std::fmt as foo; |
394 | 462 | ||
395 | impl Debug for Foo { | 463 | impl Debug for Foo { |
@@ -402,7 +470,7 @@ impl Debug for Foo { | |||
402 | fn test_replace_not_applicable_one_segment() { | 470 | fn test_replace_not_applicable_one_segment() { |
403 | check_assist_not_applicable( | 471 | check_assist_not_applicable( |
404 | replace_qualified_name_with_use, | 472 | replace_qualified_name_with_use, |
405 | " | 473 | r" |
406 | impl foo<|> for Foo { | 474 | impl foo<|> for Foo { |
407 | } | 475 | } |
408 | ", | 476 | ", |
@@ -413,7 +481,7 @@ impl foo<|> for Foo { | |||
413 | fn test_replace_not_applicable_in_use() { | 481 | fn test_replace_not_applicable_in_use() { |
414 | check_assist_not_applicable( | 482 | check_assist_not_applicable( |
415 | replace_qualified_name_with_use, | 483 | replace_qualified_name_with_use, |
416 | " | 484 | r" |
417 | use std::fmt<|>; | 485 | use std::fmt<|>; |
418 | ", | 486 | ", |
419 | ); | 487 | ); |
@@ -423,14 +491,14 @@ use std::fmt<|>; | |||
423 | fn test_replace_add_use_no_anchor_in_mod_mod() { | 491 | fn test_replace_add_use_no_anchor_in_mod_mod() { |
424 | check_assist( | 492 | check_assist( |
425 | replace_qualified_name_with_use, | 493 | replace_qualified_name_with_use, |
426 | " | 494 | r" |
427 | mod foo { | 495 | mod foo { |
428 | mod bar { | 496 | mod bar { |
429 | std::fmt::Debug<|> | 497 | std::fmt::Debug<|> |
430 | } | 498 | } |
431 | } | 499 | } |
432 | ", | 500 | ", |
433 | " | 501 | r" |
434 | mod foo { | 502 | mod foo { |
435 | mod bar { | 503 | mod bar { |
436 | use std::fmt::Debug; | 504 | use std::fmt::Debug; |
@@ -446,14 +514,14 @@ mod foo { | |||
446 | fn inserts_imports_after_inner_attributes() { | 514 | fn inserts_imports_after_inner_attributes() { |
447 | check_assist( | 515 | check_assist( |
448 | replace_qualified_name_with_use, | 516 | replace_qualified_name_with_use, |
449 | " | 517 | r" |
450 | #![allow(dead_code)] | 518 | #![allow(dead_code)] |
451 | 519 | ||
452 | fn main() { | 520 | fn main() { |
453 | std::fmt::Debug<|> | 521 | std::fmt::Debug<|> |
454 | } | 522 | } |
455 | ", | 523 | ", |
456 | " | 524 | r" |
457 | #![allow(dead_code)] | 525 | #![allow(dead_code)] |
458 | use std::fmt::Debug; | 526 | use std::fmt::Debug; |
459 | 527 | ||
@@ -463,4 +531,116 @@ fn main() { | |||
463 | ", | 531 | ", |
464 | ); | 532 | ); |
465 | } | 533 | } |
534 | |||
535 | #[test] | ||
536 | fn replaces_all_affected_paths() { | ||
537 | check_assist( | ||
538 | replace_qualified_name_with_use, | ||
539 | r" | ||
540 | fn main() { | ||
541 | std::fmt::Debug<|>; | ||
542 | let x: std::fmt::Debug = std::fmt::Debug; | ||
543 | } | ||
544 | ", | ||
545 | r" | ||
546 | use std::fmt::Debug; | ||
547 | |||
548 | fn main() { | ||
549 | Debug; | ||
550 | let x: Debug = Debug; | ||
551 | } | ||
552 | ", | ||
553 | ); | ||
554 | } | ||
555 | |||
556 | #[test] | ||
557 | fn replaces_all_affected_paths_mod() { | ||
558 | check_assist( | ||
559 | replace_qualified_name_with_use, | ||
560 | r" | ||
561 | mod m { | ||
562 | fn f() { | ||
563 | std::fmt::Debug<|>; | ||
564 | let x: std::fmt::Debug = std::fmt::Debug; | ||
565 | } | ||
566 | fn g() { | ||
567 | std::fmt::Debug; | ||
568 | } | ||
569 | } | ||
570 | |||
571 | fn f() { | ||
572 | std::fmt::Debug; | ||
573 | } | ||
574 | ", | ||
575 | r" | ||
576 | mod m { | ||
577 | use std::fmt::Debug; | ||
578 | |||
579 | fn f() { | ||
580 | Debug; | ||
581 | let x: Debug = Debug; | ||
582 | } | ||
583 | fn g() { | ||
584 | Debug; | ||
585 | } | ||
586 | } | ||
587 | |||
588 | fn f() { | ||
589 | std::fmt::Debug; | ||
590 | } | ||
591 | ", | ||
592 | ); | ||
593 | } | ||
594 | |||
595 | #[test] | ||
596 | fn does_not_replace_in_submodules() { | ||
597 | check_assist( | ||
598 | replace_qualified_name_with_use, | ||
599 | r" | ||
600 | fn main() { | ||
601 | std::fmt::Debug<|>; | ||
602 | } | ||
603 | |||
604 | mod sub { | ||
605 | fn f() { | ||
606 | std::fmt::Debug; | ||
607 | } | ||
608 | } | ||
609 | ", | ||
610 | r" | ||
611 | use std::fmt::Debug; | ||
612 | |||
613 | fn main() { | ||
614 | Debug; | ||
615 | } | ||
616 | |||
617 | mod sub { | ||
618 | fn f() { | ||
619 | std::fmt::Debug; | ||
620 | } | ||
621 | } | ||
622 | ", | ||
623 | ); | ||
624 | } | ||
625 | |||
626 | #[test] | ||
627 | fn does_not_replace_in_use() { | ||
628 | check_assist( | ||
629 | replace_qualified_name_with_use, | ||
630 | r" | ||
631 | use std::fmt::Display; | ||
632 | |||
633 | fn main() { | ||
634 | std::fmt<|>; | ||
635 | } | ||
636 | ", | ||
637 | r" | ||
638 | use std::fmt::{self, Display}; | ||
639 | |||
640 | fn main() { | ||
641 | fmt; | ||
642 | } | ||
643 | ", | ||
644 | ); | ||
645 | } | ||
466 | } | 646 | } |
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs index 0038a9764..c1ff0de7b 100644 --- a/crates/ra_assists/src/utils.rs +++ b/crates/ra_assists/src/utils.rs | |||
@@ -13,7 +13,7 @@ use rustc_hash::FxHashSet; | |||
13 | 13 | ||
14 | use crate::assist_config::SnippetCap; | 14 | use crate::assist_config::SnippetCap; |
15 | 15 | ||
16 | pub(crate) use insert_use::insert_use_statement; | 16 | pub(crate) use insert_use::{find_insert_use_container, insert_use_statement}; |
17 | 17 | ||
18 | #[derive(Clone, Copy, Debug)] | 18 | #[derive(Clone, Copy, Debug)] |
19 | pub(crate) enum Cursor<'a> { | 19 | pub(crate) enum Cursor<'a> { |
diff --git a/crates/ra_assists/src/utils/insert_use.rs b/crates/ra_assists/src/utils/insert_use.rs index 0ee43482f..8c4f33e59 100644 --- a/crates/ra_assists/src/utils/insert_use.rs +++ b/crates/ra_assists/src/utils/insert_use.rs | |||
@@ -12,6 +12,20 @@ use ra_syntax::{ | |||
12 | use ra_text_edit::TextEditBuilder; | 12 | use ra_text_edit::TextEditBuilder; |
13 | 13 | ||
14 | use crate::assist_context::AssistContext; | 14 | use crate::assist_context::AssistContext; |
15 | use either::Either; | ||
16 | |||
17 | /// Determines the containing syntax node in which to insert a `use` statement affecting `position`. | ||
18 | pub(crate) fn find_insert_use_container( | ||
19 | position: &SyntaxNode, | ||
20 | ctx: &AssistContext, | ||
21 | ) -> Option<Either<ast::ItemList, ast::SourceFile>> { | ||
22 | ctx.sema.ancestors_with_macros(position.clone()).find_map(|n| { | ||
23 | if let Some(module) = ast::Module::cast(n.clone()) { | ||
24 | return module.item_list().map(|it| Either::Left(it)); | ||
25 | } | ||
26 | Some(Either::Right(ast::SourceFile::cast(n)?)) | ||
27 | }) | ||
28 | } | ||
15 | 29 | ||
16 | /// Creates and inserts a use statement for the given path to import. | 30 | /// Creates and inserts a use statement for the given path to import. |
17 | /// The use statement is inserted in the scope most appropriate to the | 31 | /// The use statement is inserted in the scope most appropriate to the |
@@ -24,15 +38,11 @@ pub(crate) fn insert_use_statement( | |||
24 | builder: &mut TextEditBuilder, | 38 | builder: &mut TextEditBuilder, |
25 | ) { | 39 | ) { |
26 | let target = path_to_import.to_string().split("::").map(SmolStr::new).collect::<Vec<_>>(); | 40 | let target = path_to_import.to_string().split("::").map(SmolStr::new).collect::<Vec<_>>(); |
27 | let container = ctx.sema.ancestors_with_macros(position.clone()).find_map(|n| { | 41 | let container = find_insert_use_container(position, ctx); |
28 | if let Some(module) = ast::Module::cast(n.clone()) { | ||
29 | return module.item_list().map(|it| it.syntax().clone()); | ||
30 | } | ||
31 | ast::SourceFile::cast(n).map(|it| it.syntax().clone()) | ||
32 | }); | ||
33 | 42 | ||
34 | if let Some(container) = container { | 43 | if let Some(container) = container { |
35 | let action = best_action_for_target(container, position.clone(), &target); | 44 | let syntax = container.either(|l| l.syntax().clone(), |r| r.syntax().clone()); |
45 | let action = best_action_for_target(syntax, position.clone(), &target); | ||
36 | make_assist(&action, &target, builder); | 46 | make_assist(&action, &target, builder); |
37 | } | 47 | } |
38 | } | 48 | } |
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 28f686767..375da1f45 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -440,12 +440,14 @@ impl Analysis { | |||
440 | 440 | ||
441 | /// Computes syntax highlighting for the given file | 441 | /// Computes syntax highlighting for the given file |
442 | pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> { | 442 | pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> { |
443 | self.with_db(|db| syntax_highlighting::highlight(db, file_id, None)) | 443 | self.with_db(|db| syntax_highlighting::highlight(db, file_id, None, false)) |
444 | } | 444 | } |
445 | 445 | ||
446 | /// Computes syntax highlighting for the given file range. | 446 | /// Computes syntax highlighting for the given file range. |
447 | pub fn highlight_range(&self, frange: FileRange) -> Cancelable<Vec<HighlightedRange>> { | 447 | pub fn highlight_range(&self, frange: FileRange) -> Cancelable<Vec<HighlightedRange>> { |
448 | self.with_db(|db| syntax_highlighting::highlight(db, frange.file_id, Some(frange.range))) | 448 | self.with_db(|db| { |
449 | syntax_highlighting::highlight(db, frange.file_id, Some(frange.range), false) | ||
450 | }) | ||
449 | } | 451 | } |
450 | 452 | ||
451 | /// Computes syntax highlighting for the given file. | 453 | /// Computes syntax highlighting for the given file. |
diff --git a/crates/ra_ide/src/prime_caches.rs b/crates/ra_ide/src/prime_caches.rs index 90bf7d25f..c5ab5a1d8 100644 --- a/crates/ra_ide/src/prime_caches.rs +++ b/crates/ra_ide/src/prime_caches.rs | |||
@@ -7,6 +7,6 @@ use crate::{FileId, RootDatabase}; | |||
7 | 7 | ||
8 | pub(crate) fn prime_caches(db: &RootDatabase, files: Vec<FileId>) { | 8 | pub(crate) fn prime_caches(db: &RootDatabase, files: Vec<FileId>) { |
9 | for file in files { | 9 | for file in files { |
10 | let _ = crate::syntax_highlighting::highlight(db, file, None); | 10 | let _ = crate::syntax_highlighting::highlight(db, file, None, false); |
11 | } | 11 | } |
12 | } | 12 | } |
diff --git a/crates/ra_ide/src/snapshots/highlight_doctest.html b/crates/ra_ide/src/snapshots/highlight_doctest.html index 0ae8c7efc..5228df267 100644 --- a/crates/ra_ide/src/snapshots/highlight_doctest.html +++ b/crates/ra_ide/src/snapshots/highlight_doctest.html | |||
@@ -25,22 +25,29 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
25 | .variable { color: #DCDCCC; } | 25 | .variable { color: #DCDCCC; } |
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | ||
28 | 29 | ||
29 | .keyword { color: #F0DFAF; font-weight: bold; } | 30 | .keyword { color: #F0DFAF; font-weight: bold; } |
30 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 31 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
31 | .control { font-style: italic; } | 32 | .control { font-style: italic; } |
32 | </style> | 33 | </style> |
33 | <pre><code><span class="keyword">impl</span> <span class="unresolved_reference">Foo</span> { | 34 | <pre><code><span class="keyword">struct</span> <span class="struct declaration">Foo</span> { |
35 | <span class="field declaration">bar</span>: <span class="builtin_type">bool</span>, | ||
36 | } | ||
37 | |||
38 | <span class="keyword">impl</span> <span class="struct">Foo</span> { | ||
39 | <span class="keyword">pub</span> <span class="keyword">const</span> <span class="constant declaration">bar</span>: <span class="builtin_type">bool</span> = <span class="bool_literal">true</span>; | ||
40 | |||
34 | <span class="comment">/// Constructs a new `Foo`.</span> | 41 | <span class="comment">/// Constructs a new `Foo`.</span> |
35 | <span class="comment">///</span> | 42 | <span class="comment">///</span> |
36 | <span class="comment">/// # Examples</span> | 43 | <span class="comment">/// # Examples</span> |
37 | <span class="comment">///</span> | 44 | <span class="comment">///</span> |
38 | <span class="comment">/// ```</span> | 45 | <span class="comment">/// ```</span> |
39 | <span class="comment">/// #</span> <span class="attribute">#![</span><span class="function attribute">allow</span><span class="attribute">(unused_mut)]</span> | 46 | <span class="comment">/// #</span> <span class="attribute">#![</span><span class="function attribute">allow</span><span class="attribute">(unused_mut)]</span> |
40 | <span class="comment">/// </span><span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span>: <span class="unresolved_reference">Foo</span> = <span class="unresolved_reference">Foo</span>::<span class="unresolved_reference">new</span>(); | 47 | <span class="comment">/// </span><span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span>: <span class="struct">Foo</span> = <span class="struct">Foo</span>::<span class="function">new</span>(); |
41 | <span class="comment">/// ```</span> | 48 | <span class="comment">/// ```</span> |
42 | <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration">new</span>() -> <span class="unresolved_reference">Foo</span> { | 49 | <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration">new</span>() -> <span class="struct">Foo</span> { |
43 | <span class="unresolved_reference">Foo</span> { } | 50 | <span class="struct">Foo</span> { <span class="field">bar</span>: <span class="bool_literal">true</span> } |
44 | } | 51 | } |
45 | 52 | ||
46 | <span class="comment">/// `bar` method on `Foo`.</span> | 53 | <span class="comment">/// `bar` method on `Foo`.</span> |
@@ -48,11 +55,15 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
48 | <span class="comment">/// # Examples</span> | 55 | <span class="comment">/// # Examples</span> |
49 | <span class="comment">///</span> | 56 | <span class="comment">///</span> |
50 | <span class="comment">/// ```</span> | 57 | <span class="comment">/// ```</span> |
51 | <span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">foo</span> = <span class="unresolved_reference">Foo</span>::<span class="unresolved_reference">new</span>(); | 58 | <span class="comment">/// </span><span class="keyword">use</span> <span class="module">x</span>::<span class="module">y</span>; |
59 | <span class="comment">///</span> | ||
60 | <span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">foo</span> = <span class="struct">Foo</span>::<span class="function">new</span>(); | ||
52 | <span class="comment">///</span> | 61 | <span class="comment">///</span> |
53 | <span class="comment">/// </span><span class="comment">// calls bar on foo</span> | 62 | <span class="comment">/// </span><span class="comment">// calls bar on foo</span> |
54 | <span class="comment">/// </span><span class="macro">assert!</span>(foo.bar()); | 63 | <span class="comment">/// </span><span class="macro">assert!</span>(foo.bar()); |
55 | <span class="comment">///</span> | 64 | <span class="comment">///</span> |
65 | <span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">bar</span> = <span class="variable">foo</span>.<span class="field">bar</span> || <span class="struct">Foo</span>::<span class="constant">bar</span>; | ||
66 | <span class="comment">///</span> | ||
56 | <span class="comment">/// </span><span class="comment">/* multi-line | 67 | <span class="comment">/// </span><span class="comment">/* multi-line |
57 | </span><span class="comment">/// </span><span class="comment"> comment */</span> | 68 | </span><span class="comment">/// </span><span class="comment"> comment */</span> |
58 | <span class="comment">///</span> | 69 | <span class="comment">///</span> |
@@ -63,7 +74,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
63 | <span class="comment">/// ```</span> | 74 | <span class="comment">/// ```</span> |
64 | <span class="comment">///</span> | 75 | <span class="comment">///</span> |
65 | <span class="comment">/// ```</span> | 76 | <span class="comment">/// ```</span> |
66 | <span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">foobar</span> = <span class="unresolved_reference">Foo</span>::<span class="unresolved_reference">new</span>().<span class="unresolved_reference">bar</span>(); | 77 | <span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">foobar</span> = <span class="struct">Foo</span>::<span class="function">new</span>().<span class="function">bar</span>(); |
67 | <span class="comment">/// ```</span> | 78 | <span class="comment">/// ```</span> |
68 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">foo</span>(&<span class="self_keyword">self</span>) -> <span class="builtin_type">bool</span> { | 79 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">foo</span>(&<span class="self_keyword">self</span>) -> <span class="builtin_type">bool</span> { |
69 | <span class="bool_literal">true</span> | 80 | <span class="bool_literal">true</span> |
diff --git a/crates/ra_ide/src/snapshots/highlight_injection.html b/crates/ra_ide/src/snapshots/highlight_injection.html index dec06eb51..e1c9d3523 100644 --- a/crates/ra_ide/src/snapshots/highlight_injection.html +++ b/crates/ra_ide/src/snapshots/highlight_injection.html | |||
@@ -25,6 +25,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
25 | .variable { color: #DCDCCC; } | 25 | .variable { color: #DCDCCC; } |
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | ||
28 | 29 | ||
29 | .keyword { color: #F0DFAF; font-weight: bold; } | 30 | .keyword { color: #F0DFAF; font-weight: bold; } |
30 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 31 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
diff --git a/crates/ra_ide/src/snapshots/highlight_strings.html b/crates/ra_ide/src/snapshots/highlight_strings.html index 849eb3b73..666b48fd0 100644 --- a/crates/ra_ide/src/snapshots/highlight_strings.html +++ b/crates/ra_ide/src/snapshots/highlight_strings.html | |||
@@ -25,6 +25,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
25 | .variable { color: #DCDCCC; } | 25 | .variable { color: #DCDCCC; } |
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | ||
28 | 29 | ||
29 | .keyword { color: #F0DFAF; font-weight: bold; } | 30 | .keyword { color: #F0DFAF; font-weight: bold; } |
30 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 31 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
diff --git a/crates/ra_ide/src/snapshots/highlight_unsafe.html b/crates/ra_ide/src/snapshots/highlight_unsafe.html index bd24e6e38..e1540499b 100644 --- a/crates/ra_ide/src/snapshots/highlight_unsafe.html +++ b/crates/ra_ide/src/snapshots/highlight_unsafe.html | |||
@@ -25,6 +25,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
25 | .variable { color: #DCDCCC; } | 25 | .variable { color: #DCDCCC; } |
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | ||
28 | 29 | ||
29 | .keyword { color: #F0DFAF; font-weight: bold; } | 30 | .keyword { color: #F0DFAF; font-weight: bold; } |
30 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 31 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html index 33548d43c..52912dc93 100644 --- a/crates/ra_ide/src/snapshots/highlighting.html +++ b/crates/ra_ide/src/snapshots/highlighting.html | |||
@@ -25,6 +25,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
25 | .variable { color: #DCDCCC; } | 25 | .variable { color: #DCDCCC; } |
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | ||
28 | 29 | ||
29 | .keyword { color: #F0DFAF; font-weight: bold; } | 30 | .keyword { color: #F0DFAF; font-weight: bold; } |
30 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 31 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
@@ -62,6 +63,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
62 | } | 63 | } |
63 | } | 64 | } |
64 | 65 | ||
66 | <span class="macro">macro_rules!</span> <span class="macro declaration">noop</span> { | ||
67 | ($expr:expr) => { | ||
68 | $expr | ||
69 | } | ||
70 | } | ||
71 | |||
65 | <span class="comment">// comment</span> | 72 | <span class="comment">// comment</span> |
66 | <span class="keyword">fn</span> <span class="function declaration">main</span>() { | 73 | <span class="keyword">fn</span> <span class="function declaration">main</span>() { |
67 | <span class="macro">println!</span>(<span class="string_literal">"Hello, {}!"</span>, <span class="numeric_literal">92</span>); | 74 | <span class="macro">println!</span>(<span class="string_literal">"Hello, {}!"</span>, <span class="numeric_literal">92</span>); |
@@ -80,6 +87,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
80 | <span class="comment">// Do nothing</span> | 87 | <span class="comment">// Do nothing</span> |
81 | } | 88 | } |
82 | 89 | ||
90 | <span class="macro">noop!</span>(<span class="macro">noop</span><span class="macro">!</span>(<span class="numeric_literal">1</span>)); | ||
91 | |||
83 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> = <span class="numeric_literal">42</span>; | 92 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> = <span class="numeric_literal">42</span>; |
84 | <span class="keyword">let</span> <span class="variable declaration mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>; | 93 | <span class="keyword">let</span> <span class="variable declaration mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>; |
85 | <span class="keyword">let</span> <span class="variable declaration">z</span> = &<span class="variable mutable">y</span>; | 94 | <span class="keyword">let</span> <span class="variable declaration">z</span> = &<span class="variable mutable">y</span>; |
diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html index 1ab06182c..1d7f04882 100644 --- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html +++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html | |||
@@ -25,6 +25,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
25 | .variable { color: #DCDCCC; } | 25 | .variable { color: #DCDCCC; } |
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | ||
28 | 29 | ||
29 | .keyword { color: #F0DFAF; font-weight: bold; } | 30 | .keyword { color: #F0DFAF; font-weight: bold; } |
30 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 31 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index ab45c364a..5a4de450c 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -44,6 +44,7 @@ pub(crate) fn highlight( | |||
44 | db: &RootDatabase, | 44 | db: &RootDatabase, |
45 | file_id: FileId, | 45 | file_id: FileId, |
46 | range_to_highlight: Option<TextRange>, | 46 | range_to_highlight: Option<TextRange>, |
47 | syntactic_name_ref_highlighting: bool, | ||
47 | ) -> Vec<HighlightedRange> { | 48 | ) -> Vec<HighlightedRange> { |
48 | let _p = profile("highlight"); | 49 | let _p = profile("highlight"); |
49 | let sema = Semantics::new(db); | 50 | let sema = Semantics::new(db); |
@@ -104,6 +105,7 @@ pub(crate) fn highlight( | |||
104 | if let Some((highlight, binding_hash)) = highlight_element( | 105 | if let Some((highlight, binding_hash)) = highlight_element( |
105 | &sema, | 106 | &sema, |
106 | &mut bindings_shadow_count, | 107 | &mut bindings_shadow_count, |
108 | syntactic_name_ref_highlighting, | ||
107 | name.syntax().clone().into(), | 109 | name.syntax().clone().into(), |
108 | ) { | 110 | ) { |
109 | stack.add(HighlightedRange { | 111 | stack.add(HighlightedRange { |
@@ -160,23 +162,25 @@ pub(crate) fn highlight( | |||
160 | // Check if macro takes a format string and remember it for highlighting later. | 162 | // Check if macro takes a format string and remember it for highlighting later. |
161 | // The macros that accept a format string expand to a compiler builtin macros | 163 | // The macros that accept a format string expand to a compiler builtin macros |
162 | // `format_args` and `format_args_nl`. | 164 | // `format_args` and `format_args_nl`. |
163 | if let Some(fmt_macro_call) = parent.parent().and_then(ast::MacroCall::cast) { | 165 | if let Some(name) = parent |
164 | if let Some(name) = | 166 | .parent() |
165 | fmt_macro_call.path().and_then(|p| p.segment()).and_then(|s| s.name_ref()) | 167 | .and_then(ast::MacroCall::cast) |
166 | { | 168 | .and_then(|mc| mc.path()) |
167 | match name.text().as_str() { | 169 | .and_then(|p| p.segment()) |
168 | "format_args" | "format_args_nl" => { | 170 | .and_then(|s| s.name_ref()) |
169 | format_string = parent | 171 | { |
170 | .children_with_tokens() | 172 | match name.text().as_str() { |
171 | .filter(|t| t.kind() != WHITESPACE) | 173 | "format_args" | "format_args_nl" => { |
172 | .nth(1) | 174 | format_string = parent |
173 | .filter(|e| { | 175 | .children_with_tokens() |
174 | ast::String::can_cast(e.kind()) | 176 | .filter(|t| t.kind() != WHITESPACE) |
175 | || ast::RawString::can_cast(e.kind()) | 177 | .nth(1) |
176 | }) | 178 | .filter(|e| { |
177 | } | 179 | ast::String::can_cast(e.kind()) |
178 | _ => {} | 180 | || ast::RawString::can_cast(e.kind()) |
181 | }) | ||
179 | } | 182 | } |
183 | _ => {} | ||
180 | } | 184 | } |
181 | } | 185 | } |
182 | 186 | ||
@@ -198,9 +202,12 @@ pub(crate) fn highlight( | |||
198 | 202 | ||
199 | let is_format_string = format_string.as_ref() == Some(&element_to_highlight); | 203 | let is_format_string = format_string.as_ref() == Some(&element_to_highlight); |
200 | 204 | ||
201 | if let Some((highlight, binding_hash)) = | 205 | if let Some((highlight, binding_hash)) = highlight_element( |
202 | highlight_element(&sema, &mut bindings_shadow_count, element_to_highlight.clone()) | 206 | &sema, |
203 | { | 207 | &mut bindings_shadow_count, |
208 | syntactic_name_ref_highlighting, | ||
209 | element_to_highlight.clone(), | ||
210 | ) { | ||
204 | stack.add(HighlightedRange { range, highlight, binding_hash }); | 211 | stack.add(HighlightedRange { range, highlight, binding_hash }); |
205 | if let Some(string) = | 212 | if let Some(string) = |
206 | element_to_highlight.as_token().cloned().and_then(ast::String::cast) | 213 | element_to_highlight.as_token().cloned().and_then(ast::String::cast) |
@@ -408,6 +415,7 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> { | |||
408 | fn highlight_element( | 415 | fn highlight_element( |
409 | sema: &Semantics<RootDatabase>, | 416 | sema: &Semantics<RootDatabase>, |
410 | bindings_shadow_count: &mut FxHashMap<Name, u32>, | 417 | bindings_shadow_count: &mut FxHashMap<Name, u32>, |
418 | syntactic_name_ref_highlighting: bool, | ||
411 | element: SyntaxElement, | 419 | element: SyntaxElement, |
412 | ) -> Option<(Highlight, Option<u64>)> { | 420 | ) -> Option<(Highlight, Option<u64>)> { |
413 | let db = sema.db; | 421 | let db = sema.db; |
@@ -461,6 +469,7 @@ fn highlight_element( | |||
461 | } | 469 | } |
462 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), | 470 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), |
463 | }, | 471 | }, |
472 | None if syntactic_name_ref_highlighting => highlight_name_ref_by_syntax(name_ref), | ||
464 | None => HighlightTag::UnresolvedReference.into(), | 473 | None => HighlightTag::UnresolvedReference.into(), |
465 | } | 474 | } |
466 | } | 475 | } |
@@ -493,6 +502,9 @@ fn highlight_element( | |||
493 | h |= HighlightModifier::Unsafe; | 502 | h |= HighlightModifier::Unsafe; |
494 | h | 503 | h |
495 | } | 504 | } |
505 | T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { | ||
506 | Highlight::new(HighlightTag::Macro) | ||
507 | } | ||
496 | 508 | ||
497 | k if k.is_keyword() => { | 509 | k if k.is_keyword() => { |
498 | let h = Highlight::new(HighlightTag::Keyword); | 510 | let h = Highlight::new(HighlightTag::Keyword); |
@@ -609,3 +621,53 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight { | |||
609 | 621 | ||
610 | tag.into() | 622 | tag.into() |
611 | } | 623 | } |
624 | |||
625 | fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight { | ||
626 | let default = HighlightTag::UnresolvedReference; | ||
627 | |||
628 | let parent = match name.syntax().parent() { | ||
629 | Some(it) => it, | ||
630 | _ => return default.into(), | ||
631 | }; | ||
632 | |||
633 | let tag = match parent.kind() { | ||
634 | METHOD_CALL_EXPR => HighlightTag::Function, | ||
635 | FIELD_EXPR => HighlightTag::Field, | ||
636 | PATH_SEGMENT => { | ||
637 | let path = match parent.parent().and_then(ast::Path::cast) { | ||
638 | Some(it) => it, | ||
639 | _ => return default.into(), | ||
640 | }; | ||
641 | let expr = match path.syntax().parent().and_then(ast::PathExpr::cast) { | ||
642 | Some(it) => it, | ||
643 | _ => { | ||
644 | // within path, decide whether it is module or adt by checking for uppercase name | ||
645 | return if name.text().chars().next().unwrap_or_default().is_uppercase() { | ||
646 | HighlightTag::Struct | ||
647 | } else { | ||
648 | HighlightTag::Module | ||
649 | } | ||
650 | .into(); | ||
651 | } | ||
652 | }; | ||
653 | let parent = match expr.syntax().parent() { | ||
654 | Some(it) => it, | ||
655 | None => return default.into(), | ||
656 | }; | ||
657 | |||
658 | match parent.kind() { | ||
659 | CALL_EXPR => HighlightTag::Function, | ||
660 | _ => { | ||
661 | if name.text().chars().next().unwrap_or_default().is_uppercase() { | ||
662 | HighlightTag::Struct | ||
663 | } else { | ||
664 | HighlightTag::Constant | ||
665 | } | ||
666 | } | ||
667 | } | ||
668 | } | ||
669 | _ => default, | ||
670 | }; | ||
671 | |||
672 | tag.into() | ||
673 | } | ||
diff --git a/crates/ra_ide/src/syntax_highlighting/html.rs b/crates/ra_ide/src/syntax_highlighting/html.rs index 5bada6252..853b4a20f 100644 --- a/crates/ra_ide/src/syntax_highlighting/html.rs +++ b/crates/ra_ide/src/syntax_highlighting/html.rs | |||
@@ -19,7 +19,7 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo | |||
19 | ) | 19 | ) |
20 | } | 20 | } |
21 | 21 | ||
22 | let ranges = highlight(db, file_id, None); | 22 | let ranges = highlight(db, file_id, None, false); |
23 | let text = parse.tree().syntax().to_string(); | 23 | let text = parse.tree().syntax().to_string(); |
24 | let mut prev_pos = TextSize::from(0); | 24 | let mut prev_pos = TextSize::from(0); |
25 | let mut buf = String::new(); | 25 | let mut buf = String::new(); |
@@ -84,6 +84,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
84 | .variable { color: #DCDCCC; } | 84 | .variable { color: #DCDCCC; } |
85 | .format_specifier { color: #CC696B; } | 85 | .format_specifier { color: #CC696B; } |
86 | .mutable { text-decoration: underline; } | 86 | .mutable { text-decoration: underline; } |
87 | .unresolved_reference { color: #FC5555; } | ||
87 | 88 | ||
88 | .keyword { color: #F0DFAF; font-weight: bold; } | 89 | .keyword { color: #F0DFAF; font-weight: bold; } |
89 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 90 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
diff --git a/crates/ra_ide/src/syntax_highlighting/injection.rs b/crates/ra_ide/src/syntax_highlighting/injection.rs index 3575a0fc6..a02ffe59e 100644 --- a/crates/ra_ide/src/syntax_highlighting/injection.rs +++ b/crates/ra_ide/src/syntax_highlighting/injection.rs | |||
@@ -137,7 +137,7 @@ pub(super) fn highlight_doc_comment( | |||
137 | let (analysis, tmp_file_id) = Analysis::from_single_file(text); | 137 | let (analysis, tmp_file_id) = Analysis::from_single_file(text); |
138 | 138 | ||
139 | stack.push(); | 139 | stack.push(); |
140 | for mut h in analysis.highlight(tmp_file_id).unwrap() { | 140 | for mut h in analysis.with_db(|db| super::highlight(db, tmp_file_id, None, true)).unwrap() { |
141 | // Determine start offset and end offset in case of multi-line ranges | 141 | // Determine start offset and end offset in case of multi-line ranges |
142 | let mut start_offset = None; | 142 | let mut start_offset = None; |
143 | let mut end_offset = None; | 143 | let mut end_offset = None; |
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs index 949bf59a0..062b3ff4a 100644 --- a/crates/ra_ide/src/syntax_highlighting/tests.rs +++ b/crates/ra_ide/src/syntax_highlighting/tests.rs | |||
@@ -43,6 +43,12 @@ def_fn! { | |||
43 | } | 43 | } |
44 | } | 44 | } |
45 | 45 | ||
46 | macro_rules! noop { | ||
47 | ($expr:expr) => { | ||
48 | $expr | ||
49 | } | ||
50 | } | ||
51 | |||
46 | // comment | 52 | // comment |
47 | fn main() { | 53 | fn main() { |
48 | println!("Hello, {}!", 92); | 54 | println!("Hello, {}!", 92); |
@@ -61,6 +67,8 @@ fn main() { | |||
61 | // Do nothing | 67 | // Do nothing |
62 | } | 68 | } |
63 | 69 | ||
70 | noop!(noop!(1)); | ||
71 | |||
64 | let mut x = 42; | 72 | let mut x = 42; |
65 | let y = &mut x; | 73 | let y = &mut x; |
66 | let z = &y; | 74 | let z = &y; |
@@ -279,7 +287,13 @@ fn main() { | |||
279 | fn test_highlight_doctest() { | 287 | fn test_highlight_doctest() { |
280 | check_highlighting( | 288 | check_highlighting( |
281 | r#" | 289 | r#" |
290 | struct Foo { | ||
291 | bar: bool, | ||
292 | } | ||
293 | |||
282 | impl Foo { | 294 | impl Foo { |
295 | pub const bar: bool = true; | ||
296 | |||
283 | /// Constructs a new `Foo`. | 297 | /// Constructs a new `Foo`. |
284 | /// | 298 | /// |
285 | /// # Examples | 299 | /// # Examples |
@@ -289,7 +303,7 @@ impl Foo { | |||
289 | /// let mut foo: Foo = Foo::new(); | 303 | /// let mut foo: Foo = Foo::new(); |
290 | /// ``` | 304 | /// ``` |
291 | pub const fn new() -> Foo { | 305 | pub const fn new() -> Foo { |
292 | Foo { } | 306 | Foo { bar: true } |
293 | } | 307 | } |
294 | 308 | ||
295 | /// `bar` method on `Foo`. | 309 | /// `bar` method on `Foo`. |
@@ -297,11 +311,15 @@ impl Foo { | |||
297 | /// # Examples | 311 | /// # Examples |
298 | /// | 312 | /// |
299 | /// ``` | 313 | /// ``` |
314 | /// use x::y; | ||
315 | /// | ||
300 | /// let foo = Foo::new(); | 316 | /// let foo = Foo::new(); |
301 | /// | 317 | /// |
302 | /// // calls bar on foo | 318 | /// // calls bar on foo |
303 | /// assert!(foo.bar()); | 319 | /// assert!(foo.bar()); |
304 | /// | 320 | /// |
321 | /// let bar = foo.bar || Foo::bar; | ||
322 | /// | ||
305 | /// /* multi-line | 323 | /// /* multi-line |
306 | /// comment */ | 324 | /// comment */ |
307 | /// | 325 | /// |
@@ -322,7 +340,7 @@ impl Foo { | |||
322 | .trim(), | 340 | .trim(), |
323 | "crates/ra_ide/src/snapshots/highlight_doctest.html", | 341 | "crates/ra_ide/src/snapshots/highlight_doctest.html", |
324 | false, | 342 | false, |
325 | ) | 343 | ); |
326 | } | 344 | } |
327 | 345 | ||
328 | /// Highlights the code given by the `ra_fixture` argument, renders the | 346 | /// Highlights the code given by the `ra_fixture` argument, renders the |
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index cb0e27dce..9541362f5 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -29,13 +29,7 @@ pub enum ProjectWorkspace { | |||
29 | /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`. | 29 | /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`. |
30 | Cargo { cargo: CargoWorkspace, sysroot: Sysroot }, | 30 | Cargo { cargo: CargoWorkspace, sysroot: Sysroot }, |
31 | /// Project workspace was manually specified using a `rust-project.json` file. | 31 | /// Project workspace was manually specified using a `rust-project.json` file. |
32 | Json { project: JsonProject }, | 32 | Json { project: JsonProject, project_location: PathBuf }, |
33 | } | ||
34 | |||
35 | impl From<JsonProject> for ProjectWorkspace { | ||
36 | fn from(project: JsonProject) -> ProjectWorkspace { | ||
37 | ProjectWorkspace::Json { project } | ||
38 | } | ||
39 | } | 33 | } |
40 | 34 | ||
41 | /// `PackageRoot` describes a package root folder. | 35 | /// `PackageRoot` describes a package root folder. |
@@ -164,10 +158,15 @@ impl ProjectWorkspace { | |||
164 | format!("Failed to open json file {}", project_json.display()) | 158 | format!("Failed to open json file {}", project_json.display()) |
165 | })?; | 159 | })?; |
166 | let reader = BufReader::new(file); | 160 | let reader = BufReader::new(file); |
161 | let project_location = match project_json.parent() { | ||
162 | Some(parent) => PathBuf::from(parent), | ||
163 | None => PathBuf::new(), | ||
164 | }; | ||
167 | ProjectWorkspace::Json { | 165 | ProjectWorkspace::Json { |
168 | project: from_reader(reader).with_context(|| { | 166 | project: from_reader(reader).with_context(|| { |
169 | format!("Failed to deserialize json file {}", project_json.display()) | 167 | format!("Failed to deserialize json file {}", project_json.display()) |
170 | })?, | 168 | })?, |
169 | project_location: project_location, | ||
171 | } | 170 | } |
172 | } | 171 | } |
173 | ProjectManifest::CargoToml(cargo_toml) => { | 172 | ProjectManifest::CargoToml(cargo_toml) => { |
@@ -200,9 +199,11 @@ impl ProjectWorkspace { | |||
200 | /// the root is a member of the current workspace | 199 | /// the root is a member of the current workspace |
201 | pub fn to_roots(&self) -> Vec<PackageRoot> { | 200 | pub fn to_roots(&self) -> Vec<PackageRoot> { |
202 | match self { | 201 | match self { |
203 | ProjectWorkspace::Json { project } => { | 202 | ProjectWorkspace::Json { project, project_location } => project |
204 | project.roots.iter().map(|r| PackageRoot::new_member(r.path.clone())).collect() | 203 | .roots |
205 | } | 204 | .iter() |
205 | .map(|r| PackageRoot::new_member(project_location.join(&r.path))) | ||
206 | .collect(), | ||
206 | ProjectWorkspace::Cargo { cargo, sysroot } => cargo | 207 | ProjectWorkspace::Cargo { cargo, sysroot } => cargo |
207 | .packages() | 208 | .packages() |
208 | .map(|pkg| PackageRoot { | 209 | .map(|pkg| PackageRoot { |
@@ -219,7 +220,7 @@ impl ProjectWorkspace { | |||
219 | 220 | ||
220 | pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> { | 221 | pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> { |
221 | match self { | 222 | match self { |
222 | ProjectWorkspace::Json { project } => project | 223 | ProjectWorkspace::Json { project, .. } => project |
223 | .crates | 224 | .crates |
224 | .iter() | 225 | .iter() |
225 | .filter_map(|krate| krate.proc_macro_dylib_path.as_ref()) | 226 | .filter_map(|krate| krate.proc_macro_dylib_path.as_ref()) |
@@ -235,7 +236,7 @@ impl ProjectWorkspace { | |||
235 | 236 | ||
236 | pub fn n_packages(&self) -> usize { | 237 | pub fn n_packages(&self) -> usize { |
237 | match self { | 238 | match self { |
238 | ProjectWorkspace::Json { project } => project.crates.len(), | 239 | ProjectWorkspace::Json { project, .. } => project.crates.len(), |
239 | ProjectWorkspace::Cargo { cargo, sysroot } => { | 240 | ProjectWorkspace::Cargo { cargo, sysroot } => { |
240 | cargo.packages().len() + sysroot.crates().len() | 241 | cargo.packages().len() + sysroot.crates().len() |
241 | } | 242 | } |
@@ -251,13 +252,14 @@ impl ProjectWorkspace { | |||
251 | ) -> CrateGraph { | 252 | ) -> CrateGraph { |
252 | let mut crate_graph = CrateGraph::default(); | 253 | let mut crate_graph = CrateGraph::default(); |
253 | match self { | 254 | match self { |
254 | ProjectWorkspace::Json { project } => { | 255 | ProjectWorkspace::Json { project, project_location } => { |
255 | let crates: FxHashMap<_, _> = project | 256 | let crates: FxHashMap<_, _> = project |
256 | .crates | 257 | .crates |
257 | .iter() | 258 | .iter() |
258 | .enumerate() | 259 | .enumerate() |
259 | .filter_map(|(seq_index, krate)| { | 260 | .filter_map(|(seq_index, krate)| { |
260 | let file_id = load(&krate.root_module)?; | 261 | let file_path = project_location.join(&krate.root_module); |
262 | let file_id = load(&file_path)?; | ||
261 | let edition = match krate.edition { | 263 | let edition = match krate.edition { |
262 | json_project::Edition::Edition2015 => Edition::Edition2015, | 264 | json_project::Edition::Edition2015 => Edition::Edition2015, |
263 | json_project::Edition::Edition2018 => Edition::Edition2018, | 265 | json_project::Edition::Edition2018 => Edition::Edition2018, |
@@ -540,7 +542,7 @@ impl ProjectWorkspace { | |||
540 | ProjectWorkspace::Cargo { cargo, .. } => { | 542 | ProjectWorkspace::Cargo { cargo, .. } => { |
541 | Some(cargo.workspace_root()).filter(|root| path.starts_with(root)) | 543 | Some(cargo.workspace_root()).filter(|root| path.starts_with(root)) |
542 | } | 544 | } |
543 | ProjectWorkspace::Json { project: JsonProject { roots, .. } } => roots | 545 | ProjectWorkspace::Json { project: JsonProject { roots, .. }, .. } => roots |
544 | .iter() | 546 | .iter() |
545 | .find(|root| path.starts_with(&root.path)) | 547 | .find(|root| path.starts_with(&root.path)) |
546 | .map(|root| root.path.as_ref()), | 548 | .map(|root| root.path.as_ref()), |
diff --git a/crates/ra_syntax/src/algo.rs b/crates/ra_syntax/src/algo.rs index 664894d1f..f7a885eb3 100644 --- a/crates/ra_syntax/src/algo.rs +++ b/crates/ra_syntax/src/algo.rs | |||
@@ -290,6 +290,11 @@ impl<'a> SyntaxRewriter<'a> { | |||
290 | N::cast(self.rewrite(node.syntax())).unwrap() | 290 | N::cast(self.rewrite(node.syntax())).unwrap() |
291 | } | 291 | } |
292 | 292 | ||
293 | /// Returns a node that encompasses all replacements to be done by this rewriter. | ||
294 | /// | ||
295 | /// Passing the returned node to `rewrite` will apply all replacements queued up in `self`. | ||
296 | /// | ||
297 | /// Returns `None` when there are no replacements. | ||
293 | pub fn rewrite_root(&self) -> Option<SyntaxNode> { | 298 | pub fn rewrite_root(&self) -> Option<SyntaxNode> { |
294 | assert!(self.f.is_none()); | 299 | assert!(self.f.is_none()); |
295 | self.replacements | 300 | self.replacements |
@@ -298,6 +303,9 @@ impl<'a> SyntaxRewriter<'a> { | |||
298 | SyntaxElement::Node(it) => it.clone(), | 303 | SyntaxElement::Node(it) => it.clone(), |
299 | SyntaxElement::Token(it) => it.parent(), | 304 | SyntaxElement::Token(it) => it.parent(), |
300 | }) | 305 | }) |
306 | // If we only have one replacement, we must return its parent node, since `rewrite` does | ||
307 | // not replace the node passed to it. | ||
308 | .map(|it| it.parent().unwrap_or(it)) | ||
301 | .fold1(|a, b| least_common_ancestor(&a, &b).unwrap()) | 309 | .fold1(|a, b| least_common_ancestor(&a, &b).unwrap()) |
302 | } | 310 | } |
303 | 311 | ||
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index 61e686da5..a33a35cc1 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs | |||
@@ -51,7 +51,8 @@ pub use crate::{ | |||
51 | ptr::{AstPtr, SyntaxNodePtr}, | 51 | ptr::{AstPtr, SyntaxNodePtr}, |
52 | syntax_error::SyntaxError, | 52 | syntax_error::SyntaxError, |
53 | syntax_node::{ | 53 | syntax_node::{ |
54 | Direction, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken, SyntaxTreeBuilder, | 54 | Direction, NodeOrToken, SyntaxElement, SyntaxElementChildren, SyntaxNode, |
55 | SyntaxNodeChildren, SyntaxToken, SyntaxTreeBuilder, | ||
55 | }, | 56 | }, |
56 | }; | 57 | }; |
57 | pub use ra_parser::{SyntaxKind, T}; | 58 | pub use ra_parser::{SyntaxKind, T}; |
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index 8d071ab1c..99e3f7173 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs | |||
@@ -108,11 +108,11 @@ fn run_server() -> Result<()> { | |||
108 | config.update(value); | 108 | config.update(value); |
109 | } | 109 | } |
110 | config.update_caps(&initialize_params.capabilities); | 110 | config.update_caps(&initialize_params.capabilities); |
111 | let cwd = std::env::current_dir()?; | ||
112 | config.root_path = | ||
113 | initialize_params.root_uri.and_then(|it| it.to_file_path().ok()).unwrap_or(cwd); | ||
111 | 114 | ||
112 | if config.linked_projects.is_empty() { | 115 | if config.linked_projects.is_empty() { |
113 | let cwd = std::env::current_dir()?; | ||
114 | let root = | ||
115 | initialize_params.root_uri.and_then(|it| it.to_file_path().ok()).unwrap_or(cwd); | ||
116 | let workspace_roots = initialize_params | 116 | let workspace_roots = initialize_params |
117 | .workspace_folders | 117 | .workspace_folders |
118 | .map(|workspaces| { | 118 | .map(|workspaces| { |
@@ -122,7 +122,7 @@ fn run_server() -> Result<()> { | |||
122 | .collect::<Vec<_>>() | 122 | .collect::<Vec<_>>() |
123 | }) | 123 | }) |
124 | .filter(|workspaces| !workspaces.is_empty()) | 124 | .filter(|workspaces| !workspaces.is_empty()) |
125 | .unwrap_or_else(|| vec![root]); | 125 | .unwrap_or_else(|| vec![config.root_path.clone()]); |
126 | 126 | ||
127 | config.linked_projects = ProjectManifest::discover_all(&workspace_roots) | 127 | config.linked_projects = ProjectManifest::discover_all(&workspace_roots) |
128 | .into_iter() | 128 | .into_iter() |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 1253db836..0e7a937a0 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -38,12 +38,13 @@ pub struct Config { | |||
38 | 38 | ||
39 | pub with_sysroot: bool, | 39 | pub with_sysroot: bool, |
40 | pub linked_projects: Vec<LinkedProject>, | 40 | pub linked_projects: Vec<LinkedProject>, |
41 | pub root_path: PathBuf, | ||
41 | } | 42 | } |
42 | 43 | ||
43 | #[derive(Debug, Clone)] | 44 | #[derive(Debug, Clone)] |
44 | pub enum LinkedProject { | 45 | pub enum LinkedProject { |
45 | ProjectManifest(ProjectManifest), | 46 | ProjectManifest(ProjectManifest), |
46 | JsonProject(JsonProject), | 47 | InlineJsonProject(JsonProject), |
47 | } | 48 | } |
48 | 49 | ||
49 | impl From<ProjectManifest> for LinkedProject { | 50 | impl From<ProjectManifest> for LinkedProject { |
@@ -54,7 +55,7 @@ impl From<ProjectManifest> for LinkedProject { | |||
54 | 55 | ||
55 | impl From<JsonProject> for LinkedProject { | 56 | impl From<JsonProject> for LinkedProject { |
56 | fn from(v: JsonProject) -> Self { | 57 | fn from(v: JsonProject) -> Self { |
57 | LinkedProject::JsonProject(v) | 58 | LinkedProject::InlineJsonProject(v) |
58 | } | 59 | } |
59 | } | 60 | } |
60 | 61 | ||
@@ -167,6 +168,7 @@ impl Default for Config { | |||
167 | lens: LensConfig::default(), | 168 | lens: LensConfig::default(), |
168 | hover: HoverConfig::default(), | 169 | hover: HoverConfig::default(), |
169 | linked_projects: Vec::new(), | 170 | linked_projects: Vec::new(), |
171 | root_path: PathBuf::new(), | ||
170 | } | 172 | } |
171 | } | 173 | } |
172 | } | 174 | } |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 8ec571b70..cc9bb1726 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -121,7 +121,12 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> { | |||
121 | }) | 121 | }) |
122 | .ok() | 122 | .ok() |
123 | } | 123 | } |
124 | LinkedProject::JsonProject(it) => Some(it.clone().into()), | 124 | LinkedProject::InlineJsonProject(it) => { |
125 | Some(ra_project_model::ProjectWorkspace::Json { | ||
126 | project: it.clone(), | ||
127 | project_location: config.root_path.clone(), | ||
128 | }) | ||
129 | } | ||
125 | }) | 130 | }) |
126 | .collect::<Vec<_>>() | 131 | .collect::<Vec<_>>() |
127 | }; | 132 | }; |