aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide')
-rw-r--r--crates/ra_ide/src/call_hierarchy.rs40
-rw-r--r--crates/ra_ide/src/completion.rs4
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs2
-rw-r--r--crates/ra_ide/src/diagnostics.rs42
-rw-r--r--crates/ra_ide/src/display/structure.rs428
-rw-r--r--crates/ra_ide/src/expand_macro.rs241
-rw-r--r--crates/ra_ide/src/folding_ranges.rs161
-rw-r--r--crates/ra_ide/src/goto_implementation.rs4
-rw-r--r--crates/ra_ide/src/goto_type_definition.rs14
-rw-r--r--crates/ra_ide/src/hover.rs72
-rw-r--r--crates/ra_ide/src/inlay_hints.rs174
-rw-r--r--crates/ra_ide/src/lib.rs6
-rw-r--r--crates/ra_ide/src/mock_analysis.rs2
-rw-r--r--crates/ra_ide/src/references.rs9
-rw-r--r--crates/ra_ide/src/references/rename.rs44
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tests.rs22
-rw-r--r--crates/ra_ide/test_data/highlight_doctest.html (renamed from crates/ra_ide/src/snapshots/highlight_doctest.html)0
-rw-r--r--crates/ra_ide/test_data/highlight_injection.html (renamed from crates/ra_ide/src/snapshots/highlight_injection.html)0
-rw-r--r--crates/ra_ide/test_data/highlight_strings.html (renamed from crates/ra_ide/src/snapshots/highlight_strings.html)0
-rw-r--r--crates/ra_ide/test_data/highlight_unsafe.html (renamed from crates/ra_ide/src/snapshots/highlight_unsafe.html)0
-rw-r--r--crates/ra_ide/test_data/highlighting.html (renamed from crates/ra_ide/src/snapshots/highlighting.html)0
-rw-r--r--crates/ra_ide/test_data/rainbow_highlighting.html (renamed from crates/ra_ide/src/snapshots/rainbow_highlighting.html)0
22 files changed, 664 insertions, 601 deletions
diff --git a/crates/ra_ide/src/call_hierarchy.rs b/crates/ra_ide/src/call_hierarchy.rs
index 1e3a31602..884353808 100644
--- a/crates/ra_ide/src/call_hierarchy.rs
+++ b/crates/ra_ide/src/call_hierarchy.rs
@@ -39,10 +39,11 @@ pub(crate) fn call_hierarchy(
39 39
40pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Option<Vec<CallItem>> { 40pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Option<Vec<CallItem>> {
41 let sema = Semantics::new(db); 41 let sema = Semantics::new(db);
42
42 // 1. Find all refs 43 // 1. Find all refs
43 // 2. Loop through refs and determine unique fndef. This will become our `from: CallHierarchyItem,` in the reply. 44 // 2. Loop through refs and determine unique fndef. This will become our `from: CallHierarchyItem,` in the reply.
44 // 3. Add ranges relative to the start of the fndef. 45 // 3. Add ranges relative to the start of the fndef.
45 let refs = references::find_all_refs(db, position, None)?; 46 let refs = references::find_all_refs(&sema, position, None)?;
46 47
47 let mut calls = CallLocations::default(); 48 let mut calls = CallLocations::default();
48 49
@@ -355,4 +356,41 @@ fn caller3() {
355 &["caller3 FN_DEF FileId(1) 66..83 69..76 : [52..59]"], 356 &["caller3 FN_DEF FileId(1) 66..83 69..76 : [52..59]"],
356 ); 357 );
357 } 358 }
359
360 #[test]
361 fn test_call_hierarchy_issue_5103() {
362 check_hierarchy(
363 r#"
364fn a() {
365 b()
366}
367
368fn b() {}
369
370fn main() {
371 a<|>()
372}
373"#,
374 "a FN_DEF FileId(1) 0..18 3..4",
375 &["main FN_DEF FileId(1) 31..52 34..38 : [47..48]"],
376 &["b FN_DEF FileId(1) 20..29 23..24 : [13..14]"],
377 );
378
379 check_hierarchy(
380 r#"
381fn a() {
382 b<|>()
383}
384
385fn b() {}
386
387fn main() {
388 a()
389}
390"#,
391 "b FN_DEF FileId(1) 20..29 23..24",
392 &["a FN_DEF FileId(1) 0..18 3..4 : [13..14]"],
393 &[],
394 );
395 }
358} 396}
diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs
index e1fcf379d..69ea754b3 100644
--- a/crates/ra_ide/src/completion.rs
+++ b/crates/ra_ide/src/completion.rs
@@ -137,8 +137,8 @@ mod tests {
137 documentation: &'a str, 137 documentation: &'a str,
138 } 138 }
139 139
140 fn check_detail_and_documentation(fixture: &str, expected: DetailAndDocumentation) { 140 fn check_detail_and_documentation(ra_fixture: &str, expected: DetailAndDocumentation) {
141 let (analysis, position) = analysis_and_position(fixture); 141 let (analysis, position) = analysis_and_position(ra_fixture);
142 let config = CompletionConfig::default(); 142 let config = CompletionConfig::default();
143 let completions = analysis.completions(&config, position).unwrap().unwrap(); 143 let completions = analysis.completions(&config, position).unwrap().unwrap();
144 for item in completions { 144 for item in completions {
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index 560fb19e6..ef22ea54d 100644
--- a/crates/ra_ide/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
@@ -213,7 +213,7 @@ impl<'a> CompletionContext<'a> {
213 } 213 }
214 } 214 }
215 215
216 pub(crate) fn scope(&self) -> SemanticsScope<'_, RootDatabase> { 216 pub(crate) fn scope(&self) -> SemanticsScope<'_> {
217 self.sema.scope_at_offset(&self.token.parent(), self.offset) 217 self.sema.scope_at_offset(&self.token.parent(), self.offset)
218 } 218 }
219 219
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs
index 05fb799d6..46f8c31c7 100644
--- a/crates/ra_ide/src/diagnostics.rs
+++ b/crates/ra_ide/src/diagnostics.rs
@@ -324,10 +324,10 @@ mod tests {
324 /// * a diagnostic is produced 324 /// * a diagnostic is produced
325 /// * this diagnostic touches the input cursor position 325 /// * this diagnostic touches the input cursor position
326 /// * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied 326 /// * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied
327 fn check_apply_diagnostic_fix_from_position(fixture: &str, after: &str) { 327 fn check_apply_diagnostic_fix_from_position(ra_fixture: &str, after: &str) {
328 let after = trim_indent(after); 328 let after = trim_indent(after);
329 329
330 let (analysis, file_position) = analysis_and_position(fixture); 330 let (analysis, file_position) = analysis_and_position(ra_fixture);
331 let diagnostic = analysis.diagnostics(file_position.file_id).unwrap().pop().unwrap(); 331 let diagnostic = analysis.diagnostics(file_position.file_id).unwrap().pop().unwrap();
332 let mut fix = diagnostic.fix.unwrap(); 332 let mut fix = diagnostic.fix.unwrap();
333 let edit = fix.source_change.source_file_edits.pop().unwrap().edit; 333 let edit = fix.source_change.source_file_edits.pop().unwrap().edit;
@@ -365,14 +365,14 @@ mod tests {
365 365
366 /// Takes a multi-file input fixture with annotated cursor position and checks that no diagnostics 366 /// Takes a multi-file input fixture with annotated cursor position and checks that no diagnostics
367 /// apply to the file containing the cursor. 367 /// apply to the file containing the cursor.
368 fn check_no_diagnostic_for_target_file(fixture: &str) { 368 fn check_no_diagnostic_for_target_file(ra_fixture: &str) {
369 let (analysis, file_position) = analysis_and_position(fixture); 369 let (analysis, file_position) = analysis_and_position(ra_fixture);
370 let diagnostics = analysis.diagnostics(file_position.file_id).unwrap(); 370 let diagnostics = analysis.diagnostics(file_position.file_id).unwrap();
371 assert_eq!(diagnostics.len(), 0); 371 assert_eq!(diagnostics.len(), 0);
372 } 372 }
373 373
374 fn check_no_diagnostic(content: &str) { 374 fn check_no_diagnostic(ra_fixture: &str) {
375 let (analysis, file_id) = single_file(content); 375 let (analysis, file_id) = single_file(ra_fixture);
376 let diagnostics = analysis.diagnostics(file_id).unwrap(); 376 let diagnostics = analysis.diagnostics(file_id).unwrap();
377 assert_eq!(diagnostics.len(), 0, "expected no diagnostic, found one"); 377 assert_eq!(diagnostics.len(), 0, "expected no diagnostic, found one");
378 } 378 }
@@ -473,7 +473,8 @@ mod tests {
473 473
474 #[test] 474 #[test]
475 fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() { 475 fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() {
476 let content = r#" 476 check_no_diagnostic_for_target_file(
477 r"
477 //- /main.rs 478 //- /main.rs
478 use core::result::Result::{self, Ok, Err}; 479 use core::result::Result::{self, Ok, Err};
479 480
@@ -485,13 +486,14 @@ mod tests {
485 pub mod result { 486 pub mod result {
486 pub enum Result<T, E> { Ok(T), Err(E) } 487 pub enum Result<T, E> { Ok(T), Err(E) }
487 } 488 }
488 "#; 489 ",
489 check_no_diagnostic_for_target_file(content); 490 );
490 } 491 }
491 492
492 #[test] 493 #[test]
493 fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() { 494 fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() {
494 let content = r#" 495 check_no_diagnostic_for_target_file(
496 r"
495 //- /main.rs 497 //- /main.rs
496 use core::result::Result::{self, Ok, Err}; 498 use core::result::Result::{self, Ok, Err};
497 499
@@ -508,8 +510,8 @@ mod tests {
508 pub mod result { 510 pub mod result {
509 pub enum Result<T, E> { Ok(T), Err(E) } 511 pub enum Result<T, E> { Ok(T), Err(E) }
510 } 512 }
511 "#; 513 ",
512 check_no_diagnostic_for_target_file(content); 514 );
513 } 515 }
514 516
515 #[test] 517 #[test]
@@ -618,7 +620,8 @@ mod tests {
618 620
619 #[test] 621 #[test]
620 fn test_fill_struct_fields_no_diagnostic() { 622 fn test_fill_struct_fields_no_diagnostic() {
621 let content = r" 623 check_no_diagnostic(
624 r"
622 struct TestStruct { 625 struct TestStruct {
623 one: i32, 626 one: i32,
624 two: i64, 627 two: i64,
@@ -628,14 +631,14 @@ mod tests {
628 let one = 1; 631 let one = 1;
629 let s = TestStruct{ one, two: 2 }; 632 let s = TestStruct{ one, two: 2 };
630 } 633 }
631 "; 634 ",
632 635 );
633 check_no_diagnostic(content);
634 } 636 }
635 637
636 #[test] 638 #[test]
637 fn test_fill_struct_fields_no_diagnostic_on_spread() { 639 fn test_fill_struct_fields_no_diagnostic_on_spread() {
638 let content = r" 640 check_no_diagnostic(
641 r"
639 struct TestStruct { 642 struct TestStruct {
640 one: i32, 643 one: i32,
641 two: i64, 644 two: i64,
@@ -645,9 +648,8 @@ mod tests {
645 let one = 1; 648 let one = 1;
646 let s = TestStruct{ ..a }; 649 let s = TestStruct{ ..a };
647 } 650 }
648 "; 651 ",
649 652 );
650 check_no_diagnostic(content);
651 } 653 }
652 654
653 #[test] 655 #[test]
diff --git a/crates/ra_ide/src/display/structure.rs b/crates/ra_ide/src/display/structure.rs
index aad5a8e4d..c22a5d17b 100644
--- a/crates/ra_ide/src/display/structure.rs
+++ b/crates/ra_ide/src/display/structure.rs
@@ -173,12 +173,19 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
173 173
174#[cfg(test)] 174#[cfg(test)]
175mod tests { 175mod tests {
176 use expect::{expect, Expect};
177
176 use super::*; 178 use super::*;
177 use insta::assert_debug_snapshot; 179
180 fn check(ra_fixture: &str, expect: Expect) {
181 let file = SourceFile::parse(ra_fixture).ok().unwrap();
182 let structure = file_structure(&file);
183 expect.assert_debug_eq(&structure)
184 }
178 185
179 #[test] 186 #[test]
180 fn test_file_structure() { 187 fn test_file_structure() {
181 let file = SourceFile::parse( 188 check(
182 r#" 189 r#"
183struct Foo { 190struct Foo {
184 x: i32 191 x: i32
@@ -223,216 +230,211 @@ fn obsolete() {}
223#[deprecated(note = "for awhile")] 230#[deprecated(note = "for awhile")]
224fn very_obsolete() {} 231fn very_obsolete() {}
225"#, 232"#,
226 ) 233 expect![[r#"
227 .ok() 234 [
228 .unwrap(); 235 StructureNode {
229 let structure = file_structure(&file); 236 parent: None,
230 assert_debug_snapshot!(structure, 237 label: "Foo",
231 @r###" 238 navigation_range: 8..11,
232 [ 239 node_range: 1..26,
233 StructureNode { 240 kind: STRUCT_DEF,
234 parent: None, 241 detail: None,
235 label: "Foo", 242 deprecated: false,
236 navigation_range: 8..11, 243 },
237 node_range: 1..26, 244 StructureNode {
238 kind: STRUCT_DEF, 245 parent: Some(
239 detail: None, 246 0,
240 deprecated: false, 247 ),
241 }, 248 label: "x",
242 StructureNode { 249 navigation_range: 18..19,
243 parent: Some( 250 node_range: 18..24,
244 0, 251 kind: RECORD_FIELD_DEF,
245 ), 252 detail: Some(
246 label: "x", 253 "i32",
247 navigation_range: 18..19, 254 ),
248 node_range: 18..24, 255 deprecated: false,
249 kind: RECORD_FIELD_DEF, 256 },
250 detail: Some( 257 StructureNode {
251 "i32", 258 parent: None,
252 ), 259 label: "m",
253 deprecated: false, 260 navigation_range: 32..33,
254 }, 261 node_range: 28..158,
255 StructureNode { 262 kind: MODULE,
256 parent: None, 263 detail: None,
257 label: "m", 264 deprecated: false,
258 navigation_range: 32..33, 265 },
259 node_range: 28..158, 266 StructureNode {
260 kind: MODULE, 267 parent: Some(
261 detail: None, 268 2,
262 deprecated: false, 269 ),
263 }, 270 label: "bar1",
264 StructureNode { 271 navigation_range: 43..47,
265 parent: Some( 272 node_range: 40..52,
266 2, 273 kind: FN_DEF,
267 ), 274 detail: Some(
268 label: "bar1", 275 "fn()",
269 navigation_range: 43..47, 276 ),
270 node_range: 40..52, 277 deprecated: false,
271 kind: FN_DEF, 278 },
272 detail: Some( 279 StructureNode {
273 "fn()", 280 parent: Some(
274 ), 281 2,
275 deprecated: false, 282 ),
276 }, 283 label: "bar2",
277 StructureNode { 284 navigation_range: 60..64,
278 parent: Some( 285 node_range: 57..81,
279 2, 286 kind: FN_DEF,
280 ), 287 detail: Some(
281 label: "bar2", 288 "fn<T>(t: T) -> T",
282 navigation_range: 60..64, 289 ),
283 node_range: 57..81, 290 deprecated: false,
284 kind: FN_DEF, 291 },
285 detail: Some( 292 StructureNode {
286 "fn<T>(t: T) -> T", 293 parent: Some(
287 ), 294 2,
288 deprecated: false, 295 ),
289 }, 296 label: "bar3",
290 StructureNode { 297 navigation_range: 89..93,
291 parent: Some( 298 node_range: 86..156,
292 2, 299 kind: FN_DEF,
293 ), 300 detail: Some(
294 label: "bar3", 301 "fn<A, B>(a: A, b: B) -> Vec< u32 >",
295 navigation_range: 89..93, 302 ),
296 node_range: 86..156, 303 deprecated: false,
297 kind: FN_DEF, 304 },
298 detail: Some( 305 StructureNode {
299 "fn<A, B>(a: A, b: B) -> Vec< u32 >", 306 parent: None,
300 ), 307 label: "E",
301 deprecated: false, 308 navigation_range: 165..166,
302 }, 309 node_range: 160..180,
303 StructureNode { 310 kind: ENUM_DEF,
304 parent: None, 311 detail: None,
305 label: "E", 312 deprecated: false,
306 navigation_range: 165..166, 313 },
307 node_range: 160..180, 314 StructureNode {
308 kind: ENUM_DEF, 315 parent: Some(
309 detail: None, 316 6,
310 deprecated: false, 317 ),
311 }, 318 label: "X",
312 StructureNode { 319 navigation_range: 169..170,
313 parent: Some( 320 node_range: 169..170,
314 6, 321 kind: ENUM_VARIANT,
315 ), 322 detail: None,
316 label: "X", 323 deprecated: false,
317 navigation_range: 169..170, 324 },
318 node_range: 169..170, 325 StructureNode {
319 kind: ENUM_VARIANT, 326 parent: Some(
320 detail: None, 327 6,
321 deprecated: false, 328 ),
322 }, 329 label: "Y",
323 StructureNode { 330 navigation_range: 172..173,
324 parent: Some( 331 node_range: 172..178,
325 6, 332 kind: ENUM_VARIANT,
326 ), 333 detail: None,
327 label: "Y", 334 deprecated: false,
328 navigation_range: 172..173, 335 },
329 node_range: 172..178, 336 StructureNode {
330 kind: ENUM_VARIANT, 337 parent: None,
331 detail: None, 338 label: "T",
332 deprecated: false, 339 navigation_range: 186..187,
333 }, 340 node_range: 181..193,
334 StructureNode { 341 kind: TYPE_ALIAS_DEF,
335 parent: None, 342 detail: Some(
336 label: "T", 343 "()",
337 navigation_range: 186..187, 344 ),
338 node_range: 181..193, 345 deprecated: false,
339 kind: TYPE_ALIAS_DEF, 346 },
340 detail: Some( 347 StructureNode {
341 "()", 348 parent: None,
342 ), 349 label: "S",
343 deprecated: false, 350 navigation_range: 201..202,
344 }, 351 node_range: 194..213,
345 StructureNode { 352 kind: STATIC_DEF,
346 parent: None, 353 detail: Some(
347 label: "S", 354 "i32",
348 navigation_range: 201..202, 355 ),
349 node_range: 194..213, 356 deprecated: false,
350 kind: STATIC_DEF, 357 },
351 detail: Some( 358 StructureNode {
352 "i32", 359 parent: None,
353 ), 360 label: "C",
354 deprecated: false, 361 navigation_range: 220..221,
355 }, 362 node_range: 214..232,
356 StructureNode { 363 kind: CONST_DEF,
357 parent: None, 364 detail: Some(
358 label: "C", 365 "i32",
359 navigation_range: 220..221, 366 ),
360 node_range: 214..232, 367 deprecated: false,
361 kind: CONST_DEF, 368 },
362 detail: Some( 369 StructureNode {
363 "i32", 370 parent: None,
364 ), 371 label: "impl E",
365 deprecated: false, 372 navigation_range: 239..240,
366 }, 373 node_range: 234..243,
367 StructureNode { 374 kind: IMPL_DEF,
368 parent: None, 375 detail: None,
369 label: "impl E", 376 deprecated: false,
370 navigation_range: 239..240, 377 },
371 node_range: 234..243, 378 StructureNode {
372 kind: IMPL_DEF, 379 parent: None,
373 detail: None, 380 label: "impl fmt::Debug for E",
374 deprecated: false, 381 navigation_range: 265..266,
375 }, 382 node_range: 245..269,
376 StructureNode { 383 kind: IMPL_DEF,
377 parent: None, 384 detail: None,
378 label: "impl fmt::Debug for E", 385 deprecated: false,
379 navigation_range: 265..266, 386 },
380 node_range: 245..269, 387 StructureNode {
381 kind: IMPL_DEF, 388 parent: None,
382 detail: None, 389 label: "mc",
383 deprecated: false, 390 navigation_range: 284..286,
384 }, 391 node_range: 271..303,
385 StructureNode { 392 kind: MACRO_CALL,
386 parent: None, 393 detail: None,
387 label: "mc", 394 deprecated: false,
388 navigation_range: 284..286, 395 },
389 node_range: 271..303, 396 StructureNode {
390 kind: MACRO_CALL, 397 parent: None,
391 detail: None, 398 label: "mcexp",
392 deprecated: false, 399 navigation_range: 334..339,
393 }, 400 node_range: 305..356,
394 StructureNode { 401 kind: MACRO_CALL,
395 parent: None, 402 detail: None,
396 label: "mcexp", 403 deprecated: false,
397 navigation_range: 334..339, 404 },
398 node_range: 305..356, 405 StructureNode {
399 kind: MACRO_CALL, 406 parent: None,
400 detail: None, 407 label: "mcexp",
401 deprecated: false, 408 navigation_range: 387..392,
402 }, 409 node_range: 358..409,
403 StructureNode { 410 kind: MACRO_CALL,
404 parent: None, 411 detail: None,
405 label: "mcexp", 412 deprecated: false,
406 navigation_range: 387..392, 413 },
407 node_range: 358..409, 414 StructureNode {
408 kind: MACRO_CALL, 415 parent: None,
409 detail: None, 416 label: "obsolete",
410 deprecated: false, 417 navigation_range: 428..436,
411 }, 418 node_range: 411..441,
412 StructureNode { 419 kind: FN_DEF,
413 parent: None, 420 detail: Some(
414 label: "obsolete", 421 "fn()",
415 navigation_range: 428..436, 422 ),
416 node_range: 411..441, 423 deprecated: true,
417 kind: FN_DEF, 424 },
418 detail: Some( 425 StructureNode {
419 "fn()", 426 parent: None,
420 ), 427 label: "very_obsolete",
421 deprecated: true, 428 navigation_range: 481..494,
422 }, 429 node_range: 443..499,
423 StructureNode { 430 kind: FN_DEF,
424 parent: None, 431 detail: Some(
425 label: "very_obsolete", 432 "fn()",
426 navigation_range: 481..494, 433 ),
427 node_range: 443..499, 434 deprecated: true,
428 kind: FN_DEF, 435 },
429 detail: Some( 436 ]
430 "fn()", 437 "#]],
431 ), 438 );
432 deprecated: true,
433 },
434 ]
435 "###
436 );
437 } 439 }
438} 440}
diff --git a/crates/ra_ide/src/expand_macro.rs b/crates/ra_ide/src/expand_macro.rs
index 54a47aac0..043515f54 100644
--- a/crates/ra_ide/src/expand_macro.rs
+++ b/crates/ra_ide/src/expand_macro.rs
@@ -2,7 +2,9 @@ use hir::Semantics;
2use ra_ide_db::RootDatabase; 2use ra_ide_db::RootDatabase;
3use ra_syntax::{ 3use ra_syntax::{
4 algo::{find_node_at_offset, SyntaxRewriter}, 4 algo::{find_node_at_offset, SyntaxRewriter},
5 ast, AstNode, NodeOrToken, SyntaxKind, SyntaxNode, WalkEvent, T, 5 ast, AstNode, NodeOrToken, SyntaxKind,
6 SyntaxKind::*,
7 SyntaxNode, WalkEvent, T,
6}; 8};
7 9
8use crate::FilePosition; 10use crate::FilePosition;
@@ -65,8 +67,6 @@ fn expand_macro_recur(
65// FIXME: It would also be cool to share logic here and in the mbe tests, 67// FIXME: It would also be cool to share logic here and in the mbe tests,
66// which are pretty unreadable at the moment. 68// which are pretty unreadable at the moment.
67fn insert_whitespaces(syn: SyntaxNode) -> String { 69fn insert_whitespaces(syn: SyntaxNode) -> String {
68 use SyntaxKind::*;
69
70 let mut res = String::new(); 70 let mut res = String::new();
71 let mut token_iter = syn 71 let mut token_iter = syn
72 .preorder_with_tokens() 72 .preorder_with_tokens()
@@ -120,175 +120,164 @@ fn insert_whitespaces(syn: SyntaxNode) -> String {
120 120
121#[cfg(test)] 121#[cfg(test)]
122mod tests { 122mod tests {
123 use insta::assert_snapshot; 123 use expect::{expect, Expect};
124 124
125 use crate::mock_analysis::analysis_and_position; 125 use crate::mock_analysis::analysis_and_position;
126 126
127 use super::*; 127 fn check(ra_fixture: &str, expect: Expect) {
128 128 let (analysis, pos) = analysis_and_position(ra_fixture);
129 fn check_expand_macro(fixture: &str) -> ExpandedMacro { 129 let expansion = analysis.expand_macro(pos).unwrap().unwrap();
130 let (analysis, pos) = analysis_and_position(fixture); 130 let actual = format!("{}\n{}", expansion.name, expansion.expansion);
131 analysis.expand_macro(pos).unwrap().unwrap() 131 expect.assert_eq(&actual);
132 } 132 }
133 133
134 #[test] 134 #[test]
135 fn macro_expand_recursive_expansion() { 135 fn macro_expand_recursive_expansion() {
136 let res = check_expand_macro( 136 check(
137 r#" 137 r#"
138 //- /lib.rs 138macro_rules! bar {
139 macro_rules! bar { 139 () => { fn b() {} }
140 () => { fn b() {} } 140}
141 } 141macro_rules! foo {
142 macro_rules! foo { 142 () => { bar!(); }
143 () => { bar!(); } 143}
144 } 144macro_rules! baz {
145 macro_rules! baz { 145 () => { foo!(); }
146 () => { foo!(); } 146}
147 } 147f<|>oo!();
148 f<|>oo!(); 148"#,
149 "#, 149 expect![[r#"
150 foo
151 fn b(){}
152 "#]],
150 ); 153 );
151
152 assert_eq!(res.name, "foo");
153 assert_snapshot!(res.expansion, @r###"
154fn b(){}
155"###);
156 } 154 }
157 155
158 #[test] 156 #[test]
159 fn macro_expand_multiple_lines() { 157 fn macro_expand_multiple_lines() {
160 let res = check_expand_macro( 158 check(
161 r#" 159 r#"
162 //- /lib.rs 160macro_rules! foo {
163 macro_rules! foo { 161 () => {
164 () => { 162 fn some_thing() -> u32 {
165 fn some_thing() -> u32 { 163 let a = 0;
166 let a = 0; 164 a + 10
167 a + 10
168 }
169 }
170 } 165 }
171 f<|>oo!(); 166 }
167}
168f<|>oo!();
172 "#, 169 "#,
170 expect![[r#"
171 foo
172 fn some_thing() -> u32 {
173 let a = 0;
174 a+10
175 }"#]],
173 ); 176 );
174
175 assert_eq!(res.name, "foo");
176 assert_snapshot!(res.expansion, @r###"
177fn some_thing() -> u32 {
178 let a = 0;
179 a+10
180}
181"###);
182 } 177 }
183 178
184 #[test] 179 #[test]
185 fn macro_expand_match_ast() { 180 fn macro_expand_match_ast() {
186 let res = check_expand_macro( 181 check(
187 r#" 182 r#"
188 //- /lib.rs 183macro_rules! match_ast {
189 macro_rules! match_ast { 184 (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
190 (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) }; 185 (match ($node:expr) {
186 $( ast::$ast:ident($it:ident) => $res:block, )*
187 _ => $catch_all:expr $(,)?
188 }) => {{
189 $( if let Some($it) = ast::$ast::cast($node.clone()) $res else )*
190 { $catch_all }
191 }};
192}
191 193
192 (match ($node:expr) { 194fn main() {
193 $( ast::$ast:ident($it:ident) => $res:block, )* 195 mat<|>ch_ast! {
194 _ => $catch_all:expr $(,)? 196 match container {
195 }) => {{ 197 ast::TraitDef(it) => {},
196 $( if let Some($it) = ast::$ast::cast($node.clone()) $res else )* 198 ast::ImplDef(it) => {},
197 { $catch_all } 199 _ => { continue },
198 }};
199 } 200 }
200
201 fn main() {
202 mat<|>ch_ast! {
203 match container {
204 ast::TraitDef(it) => {},
205 ast::ImplDef(it) => {},
206 _ => { continue },
207 }
208 }
209 }
210 "#,
211 );
212
213 assert_eq!(res.name, "match_ast");
214 assert_snapshot!(res.expansion, @r###"
215{
216 if let Some(it) = ast::TraitDef::cast(container.clone()){}
217 else if let Some(it) = ast::ImplDef::cast(container.clone()){}
218 else {
219 {
220 continue
221 } 201 }
222 }
223} 202}
224"###); 203"#,
204 expect![[r#"
205 match_ast
206 {
207 if let Some(it) = ast::TraitDef::cast(container.clone()){}
208 else if let Some(it) = ast::ImplDef::cast(container.clone()){}
209 else {
210 {
211 continue
212 }
213 }
214 }"#]],
215 );
225 } 216 }
226 217
227 #[test] 218 #[test]
228 fn macro_expand_match_ast_inside_let_statement() { 219 fn macro_expand_match_ast_inside_let_statement() {
229 let res = check_expand_macro( 220 check(
230 r#" 221 r#"
231 //- /lib.rs 222macro_rules! match_ast {
232 macro_rules! match_ast { 223 (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
233 (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) }; 224 (match ($node:expr) {}) => {{}};
234 (match ($node:expr) {}) => {{}}; 225}
235 }
236 226
237 fn main() { 227fn main() {
238 let p = f(|it| { 228 let p = f(|it| {
239 let res = mat<|>ch_ast! { match c {}}; 229 let res = mat<|>ch_ast! { match c {}};
240 Some(res) 230 Some(res)
241 })?; 231 })?;
242 } 232}
243 "#, 233"#,
234 expect![[r#"
235 match_ast
236 {}
237 "#]],
244 ); 238 );
245
246 assert_eq!(res.name, "match_ast");
247 assert_snapshot!(res.expansion, @r###"{}"###);
248 } 239 }
249 240
250 #[test] 241 #[test]
251 fn macro_expand_inner_macro_fail_to_expand() { 242 fn macro_expand_inner_macro_fail_to_expand() {
252 let res = check_expand_macro( 243 check(
253 r#" 244 r#"
254 //- /lib.rs 245macro_rules! bar {
255 macro_rules! bar { 246 (BAD) => {};
256 (BAD) => {}; 247}
257 } 248macro_rules! foo {
258 macro_rules! foo { 249 () => {bar!()};
259 () => {bar!()}; 250}
260 }
261 251
262 fn main() { 252fn main() {
263 let res = fo<|>o!(); 253 let res = fo<|>o!();
264 } 254}
265 "#, 255"#,
256 expect![[r#"
257 foo
258 "#]],
266 ); 259 );
267
268 assert_eq!(res.name, "foo");
269 assert_snapshot!(res.expansion, @r###""###);
270 } 260 }
271 261
272 #[test] 262 #[test]
273 fn macro_expand_with_dollar_crate() { 263 fn macro_expand_with_dollar_crate() {
274 let res = check_expand_macro( 264 check(
275 r#" 265 r#"
276 //- /lib.rs 266#[macro_export]
277 #[macro_export] 267macro_rules! bar {
278 macro_rules! bar { 268 () => {0};
279 () => {0}; 269}
280 } 270macro_rules! foo {
281 macro_rules! foo { 271 () => {$crate::bar!()};
282 () => {$crate::bar!()}; 272}
283 }
284 273
285 fn main() { 274fn main() {
286 let res = fo<|>o!(); 275 let res = fo<|>o!();
287 } 276}
288 "#, 277"#,
278 expect![[r#"
279 foo
280 0 "#]],
289 ); 281 );
290
291 assert_eq!(res.name, "foo");
292 assert_snapshot!(res.expansion, @r###"0"###);
293 } 282 }
294} 283}
diff --git a/crates/ra_ide/src/folding_ranges.rs b/crates/ra_ide/src/folding_ranges.rs
index 8657377de..5cec689f8 100644
--- a/crates/ra_ide/src/folding_ranges.rs
+++ b/crates/ra_ide/src/folding_ranges.rs
@@ -15,6 +15,7 @@ pub enum FoldKind {
15 Imports, 15 Imports,
16 Mods, 16 Mods,
17 Block, 17 Block,
18 ArgList,
18} 19}
19 20
20#[derive(Debug)] 21#[derive(Debug)]
@@ -83,6 +84,7 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
83 match kind { 84 match kind {
84 COMMENT => Some(FoldKind::Comment), 85 COMMENT => Some(FoldKind::Comment),
85 USE_ITEM => Some(FoldKind::Imports), 86 USE_ITEM => Some(FoldKind::Imports),
87 ARG_LIST => Some(FoldKind::ArgList),
86 RECORD_FIELD_DEF_LIST 88 RECORD_FIELD_DEF_LIST
87 | RECORD_FIELD_PAT_LIST 89 | RECORD_FIELD_PAT_LIST
88 | ITEM_LIST 90 | ITEM_LIST
@@ -196,89 +198,85 @@ fn contiguous_range_for_comment(
196 198
197#[cfg(test)] 199#[cfg(test)]
198mod tests { 200mod tests {
201 use test_utils::extract_tags;
202
199 use super::*; 203 use super::*;
200 use test_utils::extract_ranges;
201 204
202 fn do_check(text: &str, fold_kinds: &[FoldKind]) { 205 fn check(ra_fixture: &str) {
203 let (ranges, text) = extract_ranges(text, "fold"); 206 let (ranges, text) = extract_tags(ra_fixture, "fold");
207
204 let parse = SourceFile::parse(&text); 208 let parse = SourceFile::parse(&text);
205 let folds = folding_ranges(&parse.tree()); 209 let folds = folding_ranges(&parse.tree());
206
207 assert_eq!( 210 assert_eq!(
208 folds.len(), 211 folds.len(),
209 ranges.len(), 212 ranges.len(),
210 "The amount of folds is different than the expected amount" 213 "The amount of folds is different than the expected amount"
211 ); 214 );
212 assert_eq!( 215
213 folds.len(), 216 for (fold, (range, attr)) in folds.iter().zip(ranges.into_iter()) {
214 fold_kinds.len(),
215 "The amount of fold kinds is different than the expected amount"
216 );
217 for ((fold, range), fold_kind) in
218 folds.iter().zip(ranges.into_iter()).zip(fold_kinds.iter())
219 {
220 assert_eq!(fold.range.start(), range.start()); 217 assert_eq!(fold.range.start(), range.start());
221 assert_eq!(fold.range.end(), range.end()); 218 assert_eq!(fold.range.end(), range.end());
222 assert_eq!(&fold.kind, fold_kind); 219
220 let kind = match fold.kind {
221 FoldKind::Comment => "comment",
222 FoldKind::Imports => "imports",
223 FoldKind::Mods => "mods",
224 FoldKind::Block => "block",
225 FoldKind::ArgList => "arglist",
226 };
227 assert_eq!(kind, &attr.unwrap());
223 } 228 }
224 } 229 }
225 230
226 #[test] 231 #[test]
227 fn test_fold_comments() { 232 fn test_fold_comments() {
228 let text = r#" 233 check(
229<fold>// Hello 234 r#"
235<fold comment>// Hello
230// this is a multiline 236// this is a multiline
231// comment 237// comment
232//</fold> 238//</fold>
233 239
234// But this is not 240// But this is not
235 241
236fn main() <fold>{ 242fn main() <fold block>{
237 <fold>// We should 243 <fold comment>// We should
238 // also 244 // also
239 // fold 245 // fold
240 // this one.</fold> 246 // this one.</fold>
241 <fold>//! But this one is different 247 <fold comment>//! But this one is different
242 //! because it has another flavor</fold> 248 //! because it has another flavor</fold>
243 <fold>/* As does this 249 <fold comment>/* As does this
244 multiline comment */</fold> 250 multiline comment */</fold>
245}</fold>"#; 251}</fold>"#,
246 252 );
247 let fold_kinds = &[
248 FoldKind::Comment,
249 FoldKind::Block,
250 FoldKind::Comment,
251 FoldKind::Comment,
252 FoldKind::Comment,
253 ];
254 do_check(text, fold_kinds);
255 } 253 }
256 254
257 #[test] 255 #[test]
258 fn test_fold_imports() { 256 fn test_fold_imports() {
259 let text = r#" 257 check(
260<fold>use std::<fold>{ 258 r#"
259<fold imports>use std::<fold block>{
261 str, 260 str,
262 vec, 261 vec,
263 io as iop 262 io as iop
264}</fold>;</fold> 263}</fold>;</fold>
265 264
266fn main() <fold>{ 265fn main() <fold block>{
267}</fold>"#; 266}</fold>"#,
268 267 );
269 let folds = &[FoldKind::Imports, FoldKind::Block, FoldKind::Block];
270 do_check(text, folds);
271 } 268 }
272 269
273 #[test] 270 #[test]
274 fn test_fold_mods() { 271 fn test_fold_mods() {
275 let text = r#" 272 check(
273 r#"
276 274
277pub mod foo; 275pub mod foo;
278<fold>mod after_pub; 276<fold mods>mod after_pub;
279mod after_pub_next;</fold> 277mod after_pub_next;</fold>
280 278
281<fold>mod before_pub; 279<fold mods>mod before_pub;
282mod before_pub_next;</fold> 280mod before_pub_next;</fold>
283pub mod bar; 281pub mod bar;
284 282
@@ -286,90 +284,93 @@ mod not_folding_single;
286pub mod foobar; 284pub mod foobar;
287pub not_folding_single_next; 285pub not_folding_single_next;
288 286
289<fold>#[cfg(test)] 287<fold mods>#[cfg(test)]
290mod with_attribute; 288mod with_attribute;
291mod with_attribute_next;</fold> 289mod with_attribute_next;</fold>
292 290
293fn main() <fold>{ 291fn main() <fold block>{
294}</fold>"#; 292}</fold>"#,
295 293 );
296 let folds = &[FoldKind::Mods, FoldKind::Mods, FoldKind::Mods, FoldKind::Block];
297 do_check(text, folds);
298 } 294 }
299 295
300 #[test] 296 #[test]
301 fn test_fold_import_groups() { 297 fn test_fold_import_groups() {
302 let text = r#" 298 check(
303<fold>use std::str; 299 r#"
300<fold imports>use std::str;
304use std::vec; 301use std::vec;
305use std::io as iop;</fold> 302use std::io as iop;</fold>
306 303
307<fold>use std::mem; 304<fold imports>use std::mem;
308use std::f64;</fold> 305use std::f64;</fold>
309 306
310use std::collections::HashMap; 307use std::collections::HashMap;
311// Some random comment 308// Some random comment
312use std::collections::VecDeque; 309use std::collections::VecDeque;
313 310
314fn main() <fold>{ 311fn main() <fold block>{
315}</fold>"#; 312}</fold>"#,
316 313 );
317 let folds = &[FoldKind::Imports, FoldKind::Imports, FoldKind::Block];
318 do_check(text, folds);
319 } 314 }
320 315
321 #[test] 316 #[test]
322 fn test_fold_import_and_groups() { 317 fn test_fold_import_and_groups() {
323 let text = r#" 318 check(
324<fold>use std::str; 319 r#"
320<fold imports>use std::str;
325use std::vec; 321use std::vec;
326use std::io as iop;</fold> 322use std::io as iop;</fold>
327 323
328<fold>use std::mem; 324<fold imports>use std::mem;
329use std::f64;</fold> 325use std::f64;</fold>
330 326
331<fold>use std::collections::<fold>{ 327<fold imports>use std::collections::<fold block>{
332 HashMap, 328 HashMap,
333 VecDeque, 329 VecDeque,
334}</fold>;</fold> 330}</fold>;</fold>
335// Some random comment 331// Some random comment
336 332
337fn main() <fold>{ 333fn main() <fold block>{
338}</fold>"#; 334}</fold>"#,
339 335 );
340 let folds = &[
341 FoldKind::Imports,
342 FoldKind::Imports,
343 FoldKind::Imports,
344 FoldKind::Block,
345 FoldKind::Block,
346 ];
347 do_check(text, folds);
348 } 336 }
349 337
350 #[test] 338 #[test]
351 fn test_folds_macros() { 339 fn test_folds_macros() {
352 let text = r#" 340 check(
353macro_rules! foo <fold>{ 341 r#"
342macro_rules! foo <fold block>{
354 ($($tt:tt)*) => { $($tt)* } 343 ($($tt:tt)*) => { $($tt)* }
355}</fold> 344}</fold>
356"#; 345"#,
357 346 );
358 let folds = &[FoldKind::Block];
359 do_check(text, folds);
360 } 347 }
361 348
362 #[test] 349 #[test]
363 fn test_fold_match_arms() { 350 fn test_fold_match_arms() {
364 let text = r#" 351 check(
365fn main() <fold>{ 352 r#"
366 match 0 <fold>{ 353fn main() <fold block>{
354 match 0 <fold block>{
367 0 => 0, 355 0 => 0,
368 _ => 1, 356 _ => 1,
369 }</fold> 357 }</fold>
370}</fold>"#; 358}</fold>"#,
359 );
360 }
371 361
372 let folds = &[FoldKind::Block, FoldKind::Block]; 362 #[test]
373 do_check(text, folds); 363 fn fold_big_calls() {
364 check(
365 r#"
366fn main() <fold block>{
367 frobnicate<fold arglist>(
368 1,
369 2,
370 3,
371 )</fold>
372}</fold>
373 "#,
374 )
374 } 375 }
375} 376}
diff --git a/crates/ra_ide/src/goto_implementation.rs b/crates/ra_ide/src/goto_implementation.rs
index 99a7022a4..9acc960fc 100644
--- a/crates/ra_ide/src/goto_implementation.rs
+++ b/crates/ra_ide/src/goto_implementation.rs
@@ -219,6 +219,10 @@ impl T for &Foo {}
219 #[derive(Copy)] 219 #[derive(Copy)]
220//^^^^^^^^^^^^^^^ 220//^^^^^^^^^^^^^^^
221struct Foo<|>; 221struct Foo<|>;
222
223mod marker {
224 trait Copy {}
225}
222"#, 226"#,
223 ); 227 );
224 } 228 }
diff --git a/crates/ra_ide/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs
index 91a3097fb..7eb40d637 100644
--- a/crates/ra_ide/src/goto_type_definition.rs
+++ b/crates/ra_ide/src/goto_type_definition.rs
@@ -55,8 +55,8 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
55mod tests { 55mod tests {
56 use crate::mock_analysis::analysis_and_position; 56 use crate::mock_analysis::analysis_and_position;
57 57
58 fn check_goto(fixture: &str, expected: &str) { 58 fn check_goto(ra_fixture: &str, expected: &str) {
59 let (analysis, pos) = analysis_and_position(fixture); 59 let (analysis, pos) = analysis_and_position(ra_fixture);
60 60
61 let mut navs = analysis.goto_type_definition(pos).unwrap().unwrap().info; 61 let mut navs = analysis.goto_type_definition(pos).unwrap().unwrap().info;
62 assert_eq!(navs.len(), 1); 62 assert_eq!(navs.len(), 1);
@@ -67,7 +67,7 @@ mod tests {
67 #[test] 67 #[test]
68 fn goto_type_definition_works_simple() { 68 fn goto_type_definition_works_simple() {
69 check_goto( 69 check_goto(
70 " 70 r"
71 //- /lib.rs 71 //- /lib.rs
72 struct Foo; 72 struct Foo;
73 fn foo() { 73 fn foo() {
@@ -82,7 +82,7 @@ mod tests {
82 #[test] 82 #[test]
83 fn goto_type_definition_works_simple_ref() { 83 fn goto_type_definition_works_simple_ref() {
84 check_goto( 84 check_goto(
85 " 85 r"
86 //- /lib.rs 86 //- /lib.rs
87 struct Foo; 87 struct Foo;
88 fn foo() { 88 fn foo() {
@@ -97,7 +97,7 @@ mod tests {
97 #[test] 97 #[test]
98 fn goto_type_definition_works_through_macro() { 98 fn goto_type_definition_works_through_macro() {
99 check_goto( 99 check_goto(
100 " 100 r"
101 //- /lib.rs 101 //- /lib.rs
102 macro_rules! id { 102 macro_rules! id {
103 ($($tt:tt)*) => { $($tt)* } 103 ($($tt:tt)*) => { $($tt)* }
@@ -116,7 +116,7 @@ mod tests {
116 #[test] 116 #[test]
117 fn goto_type_definition_for_param() { 117 fn goto_type_definition_for_param() {
118 check_goto( 118 check_goto(
119 " 119 r"
120 //- /lib.rs 120 //- /lib.rs
121 struct Foo; 121 struct Foo;
122 fn foo(<|>f: Foo) {} 122 fn foo(<|>f: Foo) {}
@@ -128,7 +128,7 @@ mod tests {
128 #[test] 128 #[test]
129 fn goto_type_definition_for_tuple_field() { 129 fn goto_type_definition_for_tuple_field() {
130 check_goto( 130 check_goto(
131 " 131 r"
132 //- /lib.rs 132 //- /lib.rs
133 struct Foo; 133 struct Foo;
134 struct Bar(Foo); 134 struct Bar(Foo);
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index c3e36a387..eaba2b61e 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -417,8 +417,8 @@ mod tests {
417 assert_eq!(offset, position.into()); 417 assert_eq!(offset, position.into());
418 } 418 }
419 419
420 fn check_hover_result(fixture: &str, expected: &[&str]) -> (String, Vec<HoverAction>) { 420 fn check_hover_result(ra_fixture: &str, expected: &[&str]) -> (String, Vec<HoverAction>) {
421 let (analysis, position) = analysis_and_position(fixture); 421 let (analysis, position) = analysis_and_position(ra_fixture);
422 let hover = analysis.hover(position).unwrap().unwrap(); 422 let hover = analysis.hover(position).unwrap().unwrap();
423 let mut results = Vec::from(hover.info.results()); 423 let mut results = Vec::from(hover.info.results());
424 results.sort(); 424 results.sort();
@@ -435,8 +435,8 @@ mod tests {
435 (content[hover.range].to_string(), hover.info.actions().to_vec()) 435 (content[hover.range].to_string(), hover.info.actions().to_vec())
436 } 436 }
437 437
438 fn check_hover_no_result(fixture: &str) { 438 fn check_hover_no_result(ra_fixture: &str) {
439 let (analysis, position) = analysis_and_position(fixture); 439 let (analysis, position) = analysis_and_position(ra_fixture);
440 assert!(analysis.hover(position).unwrap().is_none()); 440 assert!(analysis.hover(position).unwrap().is_none());
441 } 441 }
442 442
@@ -923,7 +923,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
923 #[test] 923 #[test]
924 fn test_hover_through_macro() { 924 fn test_hover_through_macro() {
925 let (hover_on, _) = check_hover_result( 925 let (hover_on, _) = check_hover_result(
926 " 926 r"
927 //- /lib.rs 927 //- /lib.rs
928 macro_rules! id { 928 macro_rules! id {
929 ($($tt:tt)*) => { $($tt)* } 929 ($($tt:tt)*) => { $($tt)* }
@@ -944,7 +944,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
944 #[test] 944 #[test]
945 fn test_hover_through_expr_in_macro() { 945 fn test_hover_through_expr_in_macro() {
946 let (hover_on, _) = check_hover_result( 946 let (hover_on, _) = check_hover_result(
947 " 947 r"
948 //- /lib.rs 948 //- /lib.rs
949 macro_rules! id { 949 macro_rules! id {
950 ($($tt:tt)*) => { $($tt)* } 950 ($($tt:tt)*) => { $($tt)* }
@@ -962,7 +962,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
962 #[test] 962 #[test]
963 fn test_hover_through_expr_in_macro_recursive() { 963 fn test_hover_through_expr_in_macro_recursive() {
964 let (hover_on, _) = check_hover_result( 964 let (hover_on, _) = check_hover_result(
965 " 965 r"
966 //- /lib.rs 966 //- /lib.rs
967 macro_rules! id_deep { 967 macro_rules! id_deep {
968 ($($tt:tt)*) => { $($tt)* } 968 ($($tt:tt)*) => { $($tt)* }
@@ -983,7 +983,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
983 #[test] 983 #[test]
984 fn test_hover_through_func_in_macro_recursive() { 984 fn test_hover_through_func_in_macro_recursive() {
985 let (hover_on, _) = check_hover_result( 985 let (hover_on, _) = check_hover_result(
986 " 986 r"
987 //- /lib.rs 987 //- /lib.rs
988 macro_rules! id_deep { 988 macro_rules! id_deep {
989 ($($tt:tt)*) => { $($tt)* } 989 ($($tt:tt)*) => { $($tt)* }
@@ -1026,7 +1026,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1026 #[test] 1026 #[test]
1027 fn test_hover_through_assert_macro() { 1027 fn test_hover_through_assert_macro() {
1028 let (hover_on, _) = check_hover_result( 1028 let (hover_on, _) = check_hover_result(
1029 r#" 1029 r"
1030 //- /lib.rs 1030 //- /lib.rs
1031 #[rustc_builtin_macro] 1031 #[rustc_builtin_macro]
1032 macro_rules! assert {} 1032 macro_rules! assert {}
@@ -1035,7 +1035,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1035 fn foo() { 1035 fn foo() {
1036 assert!(ba<|>r()); 1036 assert!(ba<|>r());
1037 } 1037 }
1038 "#, 1038 ",
1039 &["fn bar() -> bool"], 1039 &["fn bar() -> bool"],
1040 ); 1040 );
1041 1041
@@ -1077,14 +1077,14 @@ fn func(foo: i32) { if true { <|>foo; }; }
1077 #[test] 1077 #[test]
1078 fn test_hover_function_show_qualifiers() { 1078 fn test_hover_function_show_qualifiers() {
1079 check_hover_result( 1079 check_hover_result(
1080 " 1080 r"
1081 //- /lib.rs 1081 //- /lib.rs
1082 async fn foo<|>() {} 1082 async fn foo<|>() {}
1083 ", 1083 ",
1084 &["async fn foo()"], 1084 &["async fn foo()"],
1085 ); 1085 );
1086 check_hover_result( 1086 check_hover_result(
1087 " 1087 r"
1088 //- /lib.rs 1088 //- /lib.rs
1089 pub const unsafe fn foo<|>() {} 1089 pub const unsafe fn foo<|>() {}
1090 ", 1090 ",
@@ -1102,7 +1102,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1102 #[test] 1102 #[test]
1103 fn test_hover_trait_show_qualifiers() { 1103 fn test_hover_trait_show_qualifiers() {
1104 let (_, actions) = check_hover_result( 1104 let (_, actions) = check_hover_result(
1105 " 1105 r"
1106 //- /lib.rs 1106 //- /lib.rs
1107 unsafe trait foo<|>() {} 1107 unsafe trait foo<|>() {}
1108 ", 1108 ",
@@ -1114,7 +1114,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1114 #[test] 1114 #[test]
1115 fn test_hover_mod_with_same_name_as_function() { 1115 fn test_hover_mod_with_same_name_as_function() {
1116 check_hover_result( 1116 check_hover_result(
1117 " 1117 r"
1118 //- /lib.rs 1118 //- /lib.rs
1119 use self::m<|>y::Bar; 1119 use self::m<|>y::Bar;
1120 1120
@@ -1237,7 +1237,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1237 #[test] 1237 #[test]
1238 fn test_hover_trait_has_impl_action() { 1238 fn test_hover_trait_has_impl_action() {
1239 let (_, actions) = check_hover_result( 1239 let (_, actions) = check_hover_result(
1240 " 1240 r"
1241 //- /lib.rs 1241 //- /lib.rs
1242 trait foo<|>() {} 1242 trait foo<|>() {}
1243 ", 1243 ",
@@ -1249,7 +1249,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1249 #[test] 1249 #[test]
1250 fn test_hover_struct_has_impl_action() { 1250 fn test_hover_struct_has_impl_action() {
1251 let (_, actions) = check_hover_result( 1251 let (_, actions) = check_hover_result(
1252 " 1252 r"
1253 //- /lib.rs 1253 //- /lib.rs
1254 struct foo<|>() {} 1254 struct foo<|>() {}
1255 ", 1255 ",
@@ -1261,7 +1261,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1261 #[test] 1261 #[test]
1262 fn test_hover_union_has_impl_action() { 1262 fn test_hover_union_has_impl_action() {
1263 let (_, actions) = check_hover_result( 1263 let (_, actions) = check_hover_result(
1264 " 1264 r"
1265 //- /lib.rs 1265 //- /lib.rs
1266 union foo<|>() {} 1266 union foo<|>() {}
1267 ", 1267 ",
@@ -1273,7 +1273,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1273 #[test] 1273 #[test]
1274 fn test_hover_enum_has_impl_action() { 1274 fn test_hover_enum_has_impl_action() {
1275 let (_, actions) = check_hover_result( 1275 let (_, actions) = check_hover_result(
1276 " 1276 r"
1277 //- /lib.rs 1277 //- /lib.rs
1278 enum foo<|>() { 1278 enum foo<|>() {
1279 A, 1279 A,
@@ -1288,7 +1288,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1288 #[test] 1288 #[test]
1289 fn test_hover_test_has_action() { 1289 fn test_hover_test_has_action() {
1290 let (_, actions) = check_hover_result( 1290 let (_, actions) = check_hover_result(
1291 " 1291 r"
1292 //- /lib.rs 1292 //- /lib.rs
1293 #[test] 1293 #[test]
1294 fn foo_<|>test() {} 1294 fn foo_<|>test() {}
@@ -1332,7 +1332,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1332 #[test] 1332 #[test]
1333 fn test_hover_test_mod_has_action() { 1333 fn test_hover_test_mod_has_action() {
1334 let (_, actions) = check_hover_result( 1334 let (_, actions) = check_hover_result(
1335 " 1335 r"
1336 //- /lib.rs 1336 //- /lib.rs
1337 mod tests<|> { 1337 mod tests<|> {
1338 #[test] 1338 #[test]
@@ -1373,7 +1373,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1373 #[test] 1373 #[test]
1374 fn test_hover_struct_has_goto_type_action() { 1374 fn test_hover_struct_has_goto_type_action() {
1375 let (_, actions) = check_hover_result( 1375 let (_, actions) = check_hover_result(
1376 " 1376 r"
1377 //- /main.rs 1377 //- /main.rs
1378 struct S{ f1: u32 } 1378 struct S{ f1: u32 }
1379 1379
@@ -1416,7 +1416,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1416 #[test] 1416 #[test]
1417 fn test_hover_generic_struct_has_goto_type_actions() { 1417 fn test_hover_generic_struct_has_goto_type_actions() {
1418 let (_, actions) = check_hover_result( 1418 let (_, actions) = check_hover_result(
1419 " 1419 r"
1420 //- /main.rs 1420 //- /main.rs
1421 struct Arg(u32); 1421 struct Arg(u32);
1422 struct S<T>{ f1: T } 1422 struct S<T>{ f1: T }
@@ -1479,7 +1479,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1479 #[test] 1479 #[test]
1480 fn test_hover_generic_struct_has_flattened_goto_type_actions() { 1480 fn test_hover_generic_struct_has_flattened_goto_type_actions() {
1481 let (_, actions) = check_hover_result( 1481 let (_, actions) = check_hover_result(
1482 " 1482 r"
1483 //- /main.rs 1483 //- /main.rs
1484 struct Arg(u32); 1484 struct Arg(u32);
1485 struct S<T>{ f1: T } 1485 struct S<T>{ f1: T }
@@ -1542,7 +1542,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1542 #[test] 1542 #[test]
1543 fn test_hover_tuple_has_goto_type_actions() { 1543 fn test_hover_tuple_has_goto_type_actions() {
1544 let (_, actions) = check_hover_result( 1544 let (_, actions) = check_hover_result(
1545 " 1545 r"
1546 //- /main.rs 1546 //- /main.rs
1547 struct A(u32); 1547 struct A(u32);
1548 struct B(u32); 1548 struct B(u32);
@@ -1627,7 +1627,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1627 #[test] 1627 #[test]
1628 fn test_hover_return_impl_trait_has_goto_type_action() { 1628 fn test_hover_return_impl_trait_has_goto_type_action() {
1629 let (_, actions) = check_hover_result( 1629 let (_, actions) = check_hover_result(
1630 " 1630 r"
1631 //- /main.rs 1631 //- /main.rs
1632 trait Foo {} 1632 trait Foo {}
1633 1633
@@ -1672,7 +1672,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1672 #[test] 1672 #[test]
1673 fn test_hover_generic_return_impl_trait_has_goto_type_action() { 1673 fn test_hover_generic_return_impl_trait_has_goto_type_action() {
1674 let (_, actions) = check_hover_result( 1674 let (_, actions) = check_hover_result(
1675 " 1675 r"
1676 //- /main.rs 1676 //- /main.rs
1677 trait Foo<T> {} 1677 trait Foo<T> {}
1678 struct S; 1678 struct S;
@@ -1737,7 +1737,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1737 #[test] 1737 #[test]
1738 fn test_hover_return_impl_traits_has_goto_type_action() { 1738 fn test_hover_return_impl_traits_has_goto_type_action() {
1739 let (_, actions) = check_hover_result( 1739 let (_, actions) = check_hover_result(
1740 " 1740 r"
1741 //- /main.rs 1741 //- /main.rs
1742 trait Foo {} 1742 trait Foo {}
1743 trait Bar {} 1743 trait Bar {}
@@ -1802,7 +1802,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1802 #[test] 1802 #[test]
1803 fn test_hover_generic_return_impl_traits_has_goto_type_action() { 1803 fn test_hover_generic_return_impl_traits_has_goto_type_action() {
1804 let (_, actions) = check_hover_result( 1804 let (_, actions) = check_hover_result(
1805 " 1805 r"
1806 //- /main.rs 1806 //- /main.rs
1807 trait Foo<T> {} 1807 trait Foo<T> {}
1808 trait Bar<T> {} 1808 trait Bar<T> {}
@@ -1907,7 +1907,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1907 #[test] 1907 #[test]
1908 fn test_hover_arg_impl_trait_has_goto_type_action() { 1908 fn test_hover_arg_impl_trait_has_goto_type_action() {
1909 let (_, actions) = check_hover_result( 1909 let (_, actions) = check_hover_result(
1910 " 1910 r"
1911 //- /lib.rs 1911 //- /lib.rs
1912 trait Foo {} 1912 trait Foo {}
1913 fn foo(ar<|>g: &impl Foo) {} 1913 fn foo(ar<|>g: &impl Foo) {}
@@ -1947,7 +1947,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
1947 #[test] 1947 #[test]
1948 fn test_hover_arg_impl_traits_has_goto_type_action() { 1948 fn test_hover_arg_impl_traits_has_goto_type_action() {
1949 let (_, actions) = check_hover_result( 1949 let (_, actions) = check_hover_result(
1950 " 1950 r"
1951 //- /lib.rs 1951 //- /lib.rs
1952 trait Foo {} 1952 trait Foo {}
1953 trait Bar<T> {} 1953 trait Bar<T> {}
@@ -2028,7 +2028,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
2028 #[test] 2028 #[test]
2029 fn test_hover_arg_generic_impl_trait_has_goto_type_action() { 2029 fn test_hover_arg_generic_impl_trait_has_goto_type_action() {
2030 let (_, actions) = check_hover_result( 2030 let (_, actions) = check_hover_result(
2031 " 2031 r"
2032 //- /lib.rs 2032 //- /lib.rs
2033 trait Foo<T> {} 2033 trait Foo<T> {}
2034 struct S {} 2034 struct S {}
@@ -2088,7 +2088,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
2088 #[test] 2088 #[test]
2089 fn test_hover_dyn_return_has_goto_type_action() { 2089 fn test_hover_dyn_return_has_goto_type_action() {
2090 let (_, actions) = check_hover_result( 2090 let (_, actions) = check_hover_result(
2091 " 2091 r"
2092 //- /main.rs 2092 //- /main.rs
2093 trait Foo {} 2093 trait Foo {}
2094 struct S; 2094 struct S;
@@ -2156,7 +2156,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
2156 #[test] 2156 #[test]
2157 fn test_hover_dyn_arg_has_goto_type_action() { 2157 fn test_hover_dyn_arg_has_goto_type_action() {
2158 let (_, actions) = check_hover_result( 2158 let (_, actions) = check_hover_result(
2159 " 2159 r"
2160 //- /lib.rs 2160 //- /lib.rs
2161 trait Foo {} 2161 trait Foo {}
2162 fn foo(ar<|>g: &dyn Foo) {} 2162 fn foo(ar<|>g: &dyn Foo) {}
@@ -2196,7 +2196,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
2196 #[test] 2196 #[test]
2197 fn test_hover_generic_dyn_arg_has_goto_type_action() { 2197 fn test_hover_generic_dyn_arg_has_goto_type_action() {
2198 let (_, actions) = check_hover_result( 2198 let (_, actions) = check_hover_result(
2199 " 2199 r"
2200 //- /lib.rs 2200 //- /lib.rs
2201 trait Foo<T> {} 2201 trait Foo<T> {}
2202 struct S {} 2202 struct S {}
@@ -2256,7 +2256,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
2256 #[test] 2256 #[test]
2257 fn test_hover_goto_type_action_links_order() { 2257 fn test_hover_goto_type_action_links_order() {
2258 let (_, actions) = check_hover_result( 2258 let (_, actions) = check_hover_result(
2259 " 2259 r"
2260 //- /lib.rs 2260 //- /lib.rs
2261 trait ImplTrait<T> {} 2261 trait ImplTrait<T> {}
2262 trait DynTrait<T> {} 2262 trait DynTrait<T> {}
@@ -2357,7 +2357,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
2357 #[test] 2357 #[test]
2358 fn test_hover_associated_type_has_goto_type_action() { 2358 fn test_hover_associated_type_has_goto_type_action() {
2359 let (_, actions) = check_hover_result( 2359 let (_, actions) = check_hover_result(
2360 " 2360 r"
2361 //- /main.rs 2361 //- /main.rs
2362 trait Foo { 2362 trait Foo {
2363 type Item; 2363 type Item;
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs
index 64980a832..62d364bfa 100644
--- a/crates/ra_ide/src/inlay_hints.rs
+++ b/crates/ra_ide/src/inlay_hints.rs
@@ -345,7 +345,7 @@ fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<
345 345
346#[cfg(test)] 346#[cfg(test)]
347mod tests { 347mod tests {
348 use insta::assert_debug_snapshot; 348 use expect::{expect, Expect};
349 use test_utils::extract_annotations; 349 use test_utils::extract_annotations;
350 350
351 use crate::{inlay_hints::InlayHintsConfig, mock_analysis::single_file}; 351 use crate::{inlay_hints::InlayHintsConfig, mock_analysis::single_file};
@@ -363,6 +363,12 @@ mod tests {
363 assert_eq!(expected, actual); 363 assert_eq!(expected, actual);
364 } 364 }
365 365
366 fn check_expect(ra_fixture: &str, config: InlayHintsConfig, expect: Expect) {
367 let (analysis, file_id) = single_file(ra_fixture);
368 let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap();
369 expect.assert_debug_eq(&inlay_hints)
370 }
371
366 #[test] 372 #[test]
367 fn param_hints_only() { 373 fn param_hints_only() {
368 check_with_config( 374 check_with_config(
@@ -772,34 +778,41 @@ fn main() {
772 778
773 #[test] 779 #[test]
774 fn chaining_hints_ignore_comments() { 780 fn chaining_hints_ignore_comments() {
775 let (analysis, file_id) = single_file( 781 check_expect(
776 r#" 782 r#"
777 struct A(B); 783struct A(B);
778 impl A { fn into_b(self) -> B { self.0 } } 784impl A { fn into_b(self) -> B { self.0 } }
779 struct B(C); 785struct B(C);
780 impl B { fn into_c(self) -> C { self.0 } } 786impl B { fn into_c(self) -> C { self.0 } }
781 struct C; 787struct C;
782 788
783 fn main() { 789fn main() {
784 let c = A(B(C)) 790 let c = A(B(C))
785 .into_b() // This is a comment 791 .into_b() // This is a comment
786 .into_c(); 792 .into_c();
787 }"#, 793}
788 ); 794"#,
789 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###" 795 InlayHintsConfig {
790 [ 796 parameter_hints: false,
791 InlayHint { 797 type_hints: false,
792 range: 147..172, 798 chaining_hints: true,
793 kind: ChainingHint, 799 max_length: None,
794 label: "B",
795 },
796 InlayHint {
797 range: 147..154,
798 kind: ChainingHint,
799 label: "A",
800 }, 800 },
801 ] 801 expect![[r#"
802 "###); 802 [
803 InlayHint {
804 range: 147..172,
805 kind: ChainingHint,
806 label: "B",
807 },
808 InlayHint {
809 range: 147..154,
810 kind: ChainingHint,
811 label: "A",
812 },
813 ]
814 "#]],
815 );
803 } 816 }
804 817
805 #[test] 818 #[test]
@@ -826,7 +839,7 @@ fn main() {
826 839
827 #[test] 840 #[test]
828 fn struct_access_chaining_hints() { 841 fn struct_access_chaining_hints() {
829 let (analysis, file_id) = single_file( 842 check_expect(
830 r#" 843 r#"
831struct A { pub b: B } 844struct A { pub b: B }
832struct B { pub c: C } 845struct B { pub c: C }
@@ -845,58 +858,71 @@ fn main() {
845 let x = D 858 let x = D
846 .foo(); 859 .foo();
847}"#, 860}"#,
848 ); 861 InlayHintsConfig {
849 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###" 862 parameter_hints: false,
850 [ 863 type_hints: false,
851 InlayHint { 864 chaining_hints: true,
852 range: 143..190, 865 max_length: None,
853 kind: ChainingHint,
854 label: "C",
855 },
856 InlayHint {
857 range: 143..179,
858 kind: ChainingHint,
859 label: "B",
860 }, 866 },
861 ] 867 expect![[r#"
862 "###); 868 [
869 InlayHint {
870 range: 143..190,
871 kind: ChainingHint,
872 label: "C",
873 },
874 InlayHint {
875 range: 143..179,
876 kind: ChainingHint,
877 label: "B",
878 },
879 ]
880 "#]],
881 );
863 } 882 }
864 883
865 #[test] 884 #[test]
866 fn generic_chaining_hints() { 885 fn generic_chaining_hints() {
867 let (analysis, file_id) = single_file( 886 check_expect(
868 r#" 887 r#"
869 struct A<T>(T); 888struct A<T>(T);
870 struct B<T>(T); 889struct B<T>(T);
871 struct C<T>(T); 890struct C<T>(T);
872 struct X<T,R>(T, R); 891struct X<T,R>(T, R);
873 892
874 impl<T> A<T> { 893impl<T> A<T> {
875 fn new(t: T) -> Self { A(t) } 894 fn new(t: T) -> Self { A(t) }
876 fn into_b(self) -> B<T> { B(self.0) } 895 fn into_b(self) -> B<T> { B(self.0) }
877 } 896}
878 impl<T> B<T> { 897impl<T> B<T> {
879 fn into_c(self) -> C<T> { C(self.0) } 898 fn into_c(self) -> C<T> { C(self.0) }
880 } 899}
881 fn main() { 900fn main() {
882 let c = A::new(X(42, true)) 901 let c = A::new(X(42, true))
883 .into_b() 902 .into_b()
884 .into_c(); 903 .into_c();
885 }"#, 904}
886 ); 905"#,
887 assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsConfig{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###" 906 InlayHintsConfig {
888 [ 907 parameter_hints: false,
889 InlayHint { 908 type_hints: false,
890 range: 246..283, 909 chaining_hints: true,
891 kind: ChainingHint, 910 max_length: None,
892 label: "B<X<i32, bool>>",
893 },
894 InlayHint {
895 range: 246..265,
896 kind: ChainingHint,
897 label: "A<X<i32, bool>>",
898 }, 911 },
899 ] 912 expect![[r#"
900 "###); 913 [
914 InlayHint {
915 range: 246..283,
916 kind: ChainingHint,
917 label: "B<X<i32, bool>>",
918 },
919 InlayHint {
920 range: 246..265,
921 kind: ChainingHint,
922 label: "A<X<i32, bool>>",
923 },
924 ]
925 "#]],
926 );
901 } 927 }
902} 928}
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index ecac5134e..8660278f1 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -75,7 +75,7 @@ pub use crate::{
75 }, 75 },
76}; 76};
77 77
78pub use hir::Documentation; 78pub use hir::{Documentation, Semantics};
79pub use ra_assists::{Assist, AssistConfig, AssistId, ResolvedAssist}; 79pub use ra_assists::{Assist, AssistConfig, AssistId, ResolvedAssist};
80pub use ra_db::{ 80pub use ra_db::{
81 Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot, 81 Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot,
@@ -385,7 +385,9 @@ impl Analysis {
385 position: FilePosition, 385 position: FilePosition,
386 search_scope: Option<SearchScope>, 386 search_scope: Option<SearchScope>,
387 ) -> Cancelable<Option<ReferenceSearchResult>> { 387 ) -> Cancelable<Option<ReferenceSearchResult>> {
388 self.with_db(|db| references::find_all_refs(db, position, search_scope).map(|it| it.info)) 388 self.with_db(|db| {
389 references::find_all_refs(&Semantics::new(db), position, search_scope).map(|it| it.info)
390 })
389 } 391 }
390 392
391 /// Returns a short text describing element at position. 393 /// Returns a short text describing element at position.
diff --git a/crates/ra_ide/src/mock_analysis.rs b/crates/ra_ide/src/mock_analysis.rs
index db6d50694..a393d3dba 100644
--- a/crates/ra_ide/src/mock_analysis.rs
+++ b/crates/ra_ide/src/mock_analysis.rs
@@ -130,7 +130,7 @@ impl MockAnalysis {
130 let other_crate = crate_graph.add_crate_root( 130 let other_crate = crate_graph.add_crate_root(
131 file_id, 131 file_id,
132 edition, 132 edition,
133 Some(CrateName::new(crate_name).unwrap()), 133 Some(crate_name.to_string()),
134 cfg, 134 cfg,
135 env, 135 env,
136 Default::default(), 136 Default::default(),
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs
index 3433fdae3..c2b0d5efe 100644
--- a/crates/ra_ide/src/references.rs
+++ b/crates/ra_ide/src/references.rs
@@ -86,12 +86,11 @@ impl IntoIterator for ReferenceSearchResult {
86} 86}
87 87
88pub(crate) fn find_all_refs( 88pub(crate) fn find_all_refs(
89 db: &RootDatabase, 89 sema: &Semantics<RootDatabase>,
90 position: FilePosition, 90 position: FilePosition,
91 search_scope: Option<SearchScope>, 91 search_scope: Option<SearchScope>,
92) -> Option<RangeInfo<ReferenceSearchResult>> { 92) -> Option<RangeInfo<ReferenceSearchResult>> {
93 let _p = profile("find_all_refs"); 93 let _p = profile("find_all_refs");
94 let sema = Semantics::new(db);
95 let syntax = sema.parse(position.file_id).syntax().clone(); 94 let syntax = sema.parse(position.file_id).syntax().clone();
96 95
97 let (opt_name, search_kind) = if let Some(name) = 96 let (opt_name, search_kind) = if let Some(name) =
@@ -108,15 +107,15 @@ pub(crate) fn find_all_refs(
108 let RangeInfo { range, info: def } = find_name(&sema, &syntax, position, opt_name)?; 107 let RangeInfo { range, info: def } = find_name(&sema, &syntax, position, opt_name)?;
109 108
110 let references = def 109 let references = def
111 .find_usages(db, search_scope) 110 .find_usages(sema, search_scope)
112 .into_iter() 111 .into_iter()
113 .filter(|r| search_kind == ReferenceKind::Other || search_kind == r.kind) 112 .filter(|r| search_kind == ReferenceKind::Other || search_kind == r.kind)
114 .collect(); 113 .collect();
115 114
116 let decl_range = def.try_to_nav(db)?.range(); 115 let decl_range = def.try_to_nav(sema.db)?.range();
117 116
118 let declaration = Declaration { 117 let declaration = Declaration {
119 nav: def.try_to_nav(db)?, 118 nav: def.try_to_nav(sema.db)?,
120 kind: ReferenceKind::Other, 119 kind: ReferenceKind::Other,
121 access: decl_access(&def, &syntax, decl_range), 120 access: decl_access(&def, &syntax, decl_range),
122 }; 121 };
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs
index 7ebc0adcf..b6a2266b4 100644
--- a/crates/ra_ide/src/references/rename.rs
+++ b/crates/ra_ide/src/references/rename.rs
@@ -24,23 +24,24 @@ pub(crate) fn rename(
24 position: FilePosition, 24 position: FilePosition,
25 new_name: &str, 25 new_name: &str,
26) -> Option<RangeInfo<SourceChange>> { 26) -> Option<RangeInfo<SourceChange>> {
27 let sema = Semantics::new(db);
28
27 match lex_single_valid_syntax_kind(new_name)? { 29 match lex_single_valid_syntax_kind(new_name)? {
28 SyntaxKind::IDENT | SyntaxKind::UNDERSCORE => (), 30 SyntaxKind::IDENT | SyntaxKind::UNDERSCORE => (),
29 SyntaxKind::SELF_KW => return rename_to_self(db, position), 31 SyntaxKind::SELF_KW => return rename_to_self(&sema, position),
30 _ => return None, 32 _ => return None,
31 } 33 }
32 34
33 let sema = Semantics::new(db);
34 let source_file = sema.parse(position.file_id); 35 let source_file = sema.parse(position.file_id);
35 let syntax = source_file.syntax(); 36 let syntax = source_file.syntax();
36 if let Some(module) = find_module_at_offset(&sema, position, syntax) { 37 if let Some(module) = find_module_at_offset(&sema, position, syntax) {
37 rename_mod(db, position, module, new_name) 38 rename_mod(&sema, position, module, new_name)
38 } else if let Some(self_token) = 39 } else if let Some(self_token) =
39 syntax.token_at_offset(position.offset).find(|t| t.kind() == SyntaxKind::SELF_KW) 40 syntax.token_at_offset(position.offset).find(|t| t.kind() == SyntaxKind::SELF_KW)
40 { 41 {
41 rename_self_to_param(db, position, self_token, new_name) 42 rename_self_to_param(&sema, position, self_token, new_name)
42 } else { 43 } else {
43 rename_reference(sema.db, position, new_name) 44 rename_reference(&sema, position, new_name)
44 } 45 }
45} 46}
46 47
@@ -97,7 +98,7 @@ fn source_edit_from_reference(reference: Reference, new_name: &str) -> SourceFil
97} 98}
98 99
99fn rename_mod( 100fn rename_mod(
100 db: &RootDatabase, 101 sema: &Semantics<RootDatabase>,
101 position: FilePosition, 102 position: FilePosition,
102 module: Module, 103 module: Module,
103 new_name: &str, 104 new_name: &str,
@@ -105,12 +106,12 @@ fn rename_mod(
105 let mut source_file_edits = Vec::new(); 106 let mut source_file_edits = Vec::new();
106 let mut file_system_edits = Vec::new(); 107 let mut file_system_edits = Vec::new();
107 108
108 let src = module.definition_source(db); 109 let src = module.definition_source(sema.db);
109 let file_id = src.file_id.original_file(db); 110 let file_id = src.file_id.original_file(sema.db);
110 match src.value { 111 match src.value {
111 ModuleSource::SourceFile(..) => { 112 ModuleSource::SourceFile(..) => {
112 // mod is defined in path/to/dir/mod.rs 113 // mod is defined in path/to/dir/mod.rs
113 let dst = if module.is_mod_rs(db) { 114 let dst = if module.is_mod_rs(sema.db) {
114 format!("../{}/mod.rs", new_name) 115 format!("../{}/mod.rs", new_name)
115 } else { 116 } else {
116 format!("{}.rs", new_name) 117 format!("{}.rs", new_name)
@@ -122,17 +123,17 @@ fn rename_mod(
122 ModuleSource::Module(..) => {} 123 ModuleSource::Module(..) => {}
123 } 124 }
124 125
125 if let Some(src) = module.declaration_source(db) { 126 if let Some(src) = module.declaration_source(sema.db) {
126 let file_id = src.file_id.original_file(db); 127 let file_id = src.file_id.original_file(sema.db);
127 let name = src.value.name()?; 128 let name = src.value.name()?;
128 let edit = SourceFileEdit { 129 let edit = SourceFileEdit {
129 file_id: file_id, 130 file_id,
130 edit: TextEdit::replace(name.syntax().text_range(), new_name.into()), 131 edit: TextEdit::replace(name.syntax().text_range(), new_name.into()),
131 }; 132 };
132 source_file_edits.push(edit); 133 source_file_edits.push(edit);
133 } 134 }
134 135
135 let RangeInfo { range, info: refs } = find_all_refs(db, position, None)?; 136 let RangeInfo { range, info: refs } = find_all_refs(sema, position, None)?;
136 let ref_edits = refs 137 let ref_edits = refs
137 .references 138 .references
138 .into_iter() 139 .into_iter()
@@ -142,8 +143,10 @@ fn rename_mod(
142 Some(RangeInfo::new(range, SourceChange::from_edits(source_file_edits, file_system_edits))) 143 Some(RangeInfo::new(range, SourceChange::from_edits(source_file_edits, file_system_edits)))
143} 144}
144 145
145fn rename_to_self(db: &RootDatabase, position: FilePosition) -> Option<RangeInfo<SourceChange>> { 146fn rename_to_self(
146 let sema = Semantics::new(db); 147 sema: &Semantics<RootDatabase>,
148 position: FilePosition,
149) -> Option<RangeInfo<SourceChange>> {
147 let source_file = sema.parse(position.file_id); 150 let source_file = sema.parse(position.file_id);
148 let syn = source_file.syntax(); 151 let syn = source_file.syntax();
149 152
@@ -158,7 +161,7 @@ fn rename_to_self(db: &RootDatabase, position: FilePosition) -> Option<RangeInfo
158 _ => return None, // not renaming other types 161 _ => return None, // not renaming other types
159 }; 162 };
160 163
161 let RangeInfo { range, info: refs } = find_all_refs(db, position, None)?; 164 let RangeInfo { range, info: refs } = find_all_refs(sema, position, None)?;
162 165
163 let param_range = first_param.syntax().text_range(); 166 let param_range = first_param.syntax().text_range();
164 let (param_ref, usages): (Vec<Reference>, Vec<Reference>) = refs 167 let (param_ref, usages): (Vec<Reference>, Vec<Reference>) = refs
@@ -210,16 +213,15 @@ fn text_edit_from_self_param(
210} 213}
211 214
212fn rename_self_to_param( 215fn rename_self_to_param(
213 db: &RootDatabase, 216 sema: &Semantics<RootDatabase>,
214 position: FilePosition, 217 position: FilePosition,
215 self_token: SyntaxToken, 218 self_token: SyntaxToken,
216 new_name: &str, 219 new_name: &str,
217) -> Option<RangeInfo<SourceChange>> { 220) -> Option<RangeInfo<SourceChange>> {
218 let sema = Semantics::new(db);
219 let source_file = sema.parse(position.file_id); 221 let source_file = sema.parse(position.file_id);
220 let syn = source_file.syntax(); 222 let syn = source_file.syntax();
221 223
222 let text = db.file_text(position.file_id); 224 let text = sema.db.file_text(position.file_id);
223 let fn_def = find_node_at_offset::<ast::FnDef>(syn, position.offset)?; 225 let fn_def = find_node_at_offset::<ast::FnDef>(syn, position.offset)?;
224 let search_range = fn_def.syntax().text_range(); 226 let search_range = fn_def.syntax().text_range();
225 227
@@ -249,11 +251,11 @@ fn rename_self_to_param(
249} 251}
250 252
251fn rename_reference( 253fn rename_reference(
252 db: &RootDatabase, 254 sema: &Semantics<RootDatabase>,
253 position: FilePosition, 255 position: FilePosition,
254 new_name: &str, 256 new_name: &str,
255) -> Option<RangeInfo<SourceChange>> { 257) -> Option<RangeInfo<SourceChange>> {
256 let RangeInfo { range, info: refs } = find_all_refs(db, position, None)?; 258 let RangeInfo { range, info: refs } = find_all_refs(sema, position, None)?;
257 259
258 let edit = refs 260 let edit = refs
259 .into_iter() 261 .into_iter()
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs
index b7fad9719..aa7c887d6 100644
--- a/crates/ra_ide/src/syntax_highlighting/tests.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tests.rs
@@ -1,6 +1,7 @@
1use std::fs; 1use std::fs;
2 2
3use test_utils::{assert_eq_text, project_dir, read_text}; 3use expect::{expect_file, ExpectFile};
4use test_utils::project_dir;
4 5
5use crate::{mock_analysis::single_file, FileRange, TextRange}; 6use crate::{mock_analysis::single_file, FileRange, TextRange};
6 7
@@ -91,7 +92,7 @@ impl<T> Option<T> {
91} 92}
92"# 93"#
93 .trim(), 94 .trim(),
94 "crates/ra_ide/src/snapshots/highlighting.html", 95 expect_file!["crates/ra_ide/test_data/highlighting.html"],
95 false, 96 false,
96 ); 97 );
97} 98}
@@ -114,7 +115,7 @@ fn bar() {
114} 115}
115"# 116"#
116 .trim(), 117 .trim(),
117 "crates/ra_ide/src/snapshots/rainbow_highlighting.html", 118 expect_file!["crates/ra_ide/test_data/rainbow_highlighting.html"],
118 true, 119 true,
119 ); 120 );
120} 121}
@@ -167,7 +168,7 @@ fn main() {
167 ); 168 );
168}"## 169}"##
169 .trim(), 170 .trim(),
170 "crates/ra_ide/src/snapshots/highlight_injection.html", 171 expect_file!["crates/ra_ide/test_data/highlight_injection.html"],
171 false, 172 false,
172 ); 173 );
173} 174}
@@ -250,7 +251,7 @@ fn main() {
250 println!("{ничоси}", ничоси = 92); 251 println!("{ничоси}", ничоси = 92);
251}"# 252}"#
252 .trim(), 253 .trim(),
253 "crates/ra_ide/src/snapshots/highlight_strings.html", 254 expect_file!["crates/ra_ide/test_data/highlight_strings.html"],
254 false, 255 false,
255 ); 256 );
256} 257}
@@ -278,7 +279,7 @@ fn main() {
278} 279}
279"# 280"#
280 .trim(), 281 .trim(),
281 "crates/ra_ide/src/snapshots/highlight_unsafe.html", 282 expect_file!["crates/ra_ide/test_data/highlight_unsafe.html"],
282 false, 283 false,
283 ); 284 );
284} 285}
@@ -354,7 +355,7 @@ macro_rules! noop {
354} 355}
355"# 356"#
356 .trim(), 357 .trim(),
357 "crates/ra_ide/src/snapshots/highlight_doctest.html", 358 expect_file!["crates/ra_ide/test_data/highlight_doctest.html"],
358 false, 359 false,
359 ); 360 );
360} 361}
@@ -362,11 +363,8 @@ macro_rules! noop {
362/// Highlights the code given by the `ra_fixture` argument, renders the 363/// Highlights the code given by the `ra_fixture` argument, renders the
363/// result as HTML, and compares it with the HTML file given as `snapshot`. 364/// result as HTML, and compares it with the HTML file given as `snapshot`.
364/// Note that the `snapshot` file is overwritten by the rendered HTML. 365/// Note that the `snapshot` file is overwritten by the rendered HTML.
365fn check_highlighting(ra_fixture: &str, snapshot: &str, rainbow: bool) { 366fn check_highlighting(ra_fixture: &str, expect: ExpectFile, rainbow: bool) {
366 let (analysis, file_id) = single_file(ra_fixture); 367 let (analysis, file_id) = single_file(ra_fixture);
367 let dst_file = project_dir().join(snapshot);
368 let actual_html = &analysis.highlight_as_html(file_id, rainbow).unwrap(); 368 let actual_html = &analysis.highlight_as_html(file_id, rainbow).unwrap();
369 let expected_html = &read_text(&dst_file); 369 expect.assert_eq(actual_html)
370 fs::write(dst_file, &actual_html).unwrap();
371 assert_eq_text!(expected_html, actual_html);
372} 370}
diff --git a/crates/ra_ide/src/snapshots/highlight_doctest.html b/crates/ra_ide/test_data/highlight_doctest.html
index e8155def7..e8155def7 100644
--- a/crates/ra_ide/src/snapshots/highlight_doctest.html
+++ b/crates/ra_ide/test_data/highlight_doctest.html
diff --git a/crates/ra_ide/src/snapshots/highlight_injection.html b/crates/ra_ide/test_data/highlight_injection.html
index 1b0349bae..1b0349bae 100644
--- a/crates/ra_ide/src/snapshots/highlight_injection.html
+++ b/crates/ra_ide/test_data/highlight_injection.html
diff --git a/crates/ra_ide/src/snapshots/highlight_strings.html b/crates/ra_ide/test_data/highlight_strings.html
index d184b5691..d184b5691 100644
--- a/crates/ra_ide/src/snapshots/highlight_strings.html
+++ b/crates/ra_ide/test_data/highlight_strings.html
diff --git a/crates/ra_ide/src/snapshots/highlight_unsafe.html b/crates/ra_ide/test_data/highlight_unsafe.html
index 6936e949f..6936e949f 100644
--- a/crates/ra_ide/src/snapshots/highlight_unsafe.html
+++ b/crates/ra_ide/test_data/highlight_unsafe.html
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/test_data/highlighting.html
index 8d0b38f95..8d0b38f95 100644
--- a/crates/ra_ide/src/snapshots/highlighting.html
+++ b/crates/ra_ide/test_data/highlighting.html
diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/test_data/rainbow_highlighting.html
index 9516c7441..9516c7441 100644
--- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html
+++ b/crates/ra_ide/test_data/rainbow_highlighting.html