aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide')
-rw-r--r--crates/ra_ide/Cargo.toml1
-rw-r--r--crates/ra_ide/src/call_info.rs467
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs5
-rw-r--r--crates/ra_ide/src/completion/presentation.rs35
-rw-r--r--crates/ra_ide/src/diagnostics.rs4
-rw-r--r--crates/ra_ide/src/goto_definition.rs18
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs28
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tags.rs2
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tests.rs10
-rw-r--r--crates/ra_ide/test_data/highlight_doctest.html62
-rw-r--r--crates/ra_ide/test_data/highlight_injection.html20
-rw-r--r--crates/ra_ide/test_data/highlight_strings.html104
-rw-r--r--crates/ra_ide/test_data/highlight_unsafe.html28
-rw-r--r--crates/ra_ide/test_data/highlighting.html150
-rw-r--r--crates/ra_ide/test_data/rainbow_highlighting.html20
15 files changed, 534 insertions, 420 deletions
diff --git a/crates/ra_ide/Cargo.toml b/crates/ra_ide/Cargo.toml
index df2fad520..6f8107491 100644
--- a/crates/ra_ide/Cargo.toml
+++ b/crates/ra_ide/Cargo.toml
@@ -3,6 +3,7 @@ edition = "2018"
3name = "ra_ide" 3name = "ra_ide"
4version = "0.1.0" 4version = "0.1.0"
5authors = ["rust-analyzer developers"] 5authors = ["rust-analyzer developers"]
6license = "MIT OR Apache-2.0"
6 7
7[lib] 8[lib]
8doctest = false 9doctest = false
diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs
index a6bdf1c9d..e1d6efb2a 100644
--- a/crates/ra_ide/src/call_info.rs
+++ b/crates/ra_ide/src/call_info.rs
@@ -93,7 +93,7 @@ fn call_info_for_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Op
93 arg_list 93 arg_list
94 .args() 94 .args()
95 .take_while(|arg| { 95 .take_while(|arg| {
96 arg.syntax().text_range().end() < token.text_range().start() 96 arg.syntax().text_range().end() <= token.text_range().start()
97 }) 97 })
98 .count(), 98 .count(),
99 ); 99 );
@@ -213,169 +213,187 @@ impl CallInfo {
213 213
214#[cfg(test)] 214#[cfg(test)]
215mod tests { 215mod tests {
216 use expect::{expect, Expect};
216 use test_utils::mark; 217 use test_utils::mark;
217 218
218 use crate::mock_analysis::analysis_and_position; 219 use crate::mock_analysis::analysis_and_position;
219 220
220 use super::*; 221 fn check(ra_fixture: &str, expect: Expect) {
221 222 let (analysis, position) = analysis_and_position(ra_fixture);
222 // These are only used when testing 223 let call_info = analysis.call_info(position).unwrap();
223 impl CallInfo { 224 let actual = match call_info {
224 fn doc(&self) -> Option<hir::Documentation> { 225 Some(call_info) => {
225 self.signature.doc.clone() 226 let docs = match &call_info.signature.doc {
226 } 227 None => "".to_string(),
227 228 Some(docs) => format!("{}\n------\n", docs.as_str()),
228 fn label(&self) -> String { 229 };
229 self.signature.to_string() 230 let params = call_info
230 } 231 .parameters()
231 } 232 .iter()
232 233 .enumerate()
233 fn call_info_helper(text: &str) -> Option<CallInfo> { 234 .map(|(i, param)| {
234 let (analysis, position) = analysis_and_position(text); 235 if Some(i) == call_info.active_parameter {
235 analysis.call_info(position).unwrap() 236 format!("<{}>", param)
236 } 237 } else {
237 238 param.clone()
238 fn call_info(text: &str) -> CallInfo { 239 }
239 let info = call_info_helper(text); 240 })
240 assert!(info.is_some()); 241 .collect::<Vec<_>>()
241 info.unwrap() 242 .join(", ");
242 } 243 format!("{}{}\n({})\n", docs, call_info.signature, params)
243 244 }
244 fn no_call_info(text: &str) { 245 None => String::new(),
245 let info = call_info_helper(text); 246 };
246 assert!(info.is_none()); 247 expect.assert_eq(&actual);
247 } 248 }
248 249
249 #[test] 250 #[test]
250 fn test_fn_signature_two_args_firstx() { 251 fn test_fn_signature_two_args() {
251 let info = call_info( 252 check(
252 r#"fn foo(x: u32, y: u32) -> u32 {x + y} 253 r#"
253fn bar() { foo(<|>3, ); }"#, 254fn foo(x: u32, y: u32) -> u32 {x + y}
255fn bar() { foo(<|>3, ); }
256"#,
257 expect![[r#"
258 fn foo(x: u32, y: u32) -> u32
259 (<x: u32>, y: u32)
260 "#]],
254 ); 261 );
255 262 check(
256 assert_eq!(info.parameters(), ["x: u32", "y: u32"]); 263 r#"
257 assert_eq!(info.active_parameter, Some(0)); 264fn foo(x: u32, y: u32) -> u32 {x + y}
258 } 265fn bar() { foo(3<|>, ); }
259 266"#,
260 #[test] 267 expect![[r#"
261 fn test_fn_signature_two_args_second() { 268 fn foo(x: u32, y: u32) -> u32
262 let info = call_info( 269 (<x: u32>, y: u32)
263 r#"fn foo(x: u32, y: u32) -> u32 {x + y} 270 "#]],
264fn bar() { foo(3, <|>); }"#, 271 );
272 check(
273 r#"
274fn foo(x: u32, y: u32) -> u32 {x + y}
275fn bar() { foo(3,<|> ); }
276"#,
277 expect![[r#"
278 fn foo(x: u32, y: u32) -> u32
279 (x: u32, <y: u32>)
280 "#]],
281 );
282 check(
283 r#"
284fn foo(x: u32, y: u32) -> u32 {x + y}
285fn bar() { foo(3, <|>); }
286"#,
287 expect![[r#"
288 fn foo(x: u32, y: u32) -> u32
289 (x: u32, <y: u32>)
290 "#]],
265 ); 291 );
266
267 assert_eq!(info.parameters(), ["x: u32", "y: u32"]);
268 assert_eq!(info.active_parameter, Some(1));
269 } 292 }
270 293
271 #[test] 294 #[test]
272 fn test_fn_signature_two_args_empty() { 295 fn test_fn_signature_two_args_empty() {
273 let info = call_info( 296 check(
274 r#"fn foo(x: u32, y: u32) -> u32 {x + y} 297 r#"
275fn bar() { foo(<|>); }"#, 298fn foo(x: u32, y: u32) -> u32 {x + y}
299fn bar() { foo(<|>); }
300"#,
301 expect![[r#"
302 fn foo(x: u32, y: u32) -> u32
303 (<x: u32>, y: u32)
304 "#]],
276 ); 305 );
277
278 assert_eq!(info.parameters(), ["x: u32", "y: u32"]);
279 assert_eq!(info.active_parameter, Some(0));
280 } 306 }
281 307
282 #[test] 308 #[test]
283 fn test_fn_signature_two_args_first_generics() { 309 fn test_fn_signature_two_args_first_generics() {
284 let info = call_info( 310 check(
285 r#"fn foo<T, U: Copy + Display>(x: T, y: U) -> u32 where T: Copy + Display, U: Debug {x + y}
286fn bar() { foo(<|>3, ); }"#,
287 );
288
289 assert_eq!(info.parameters(), ["x: T", "y: U"]);
290 assert_eq!(
291 info.label(),
292 r#" 311 r#"
293fn foo<T, U: Copy + Display>(x: T, y: U) -> u32 312fn foo<T, U: Copy + Display>(x: T, y: U) -> u32
294where T: Copy + Display, 313 where T: Copy + Display, U: Debug
295 U: Debug 314{ x + y }
296 "# 315
297 .trim() 316fn bar() { foo(<|>3, ); }
317"#,
318 expect![[r#"
319 fn foo<T, U: Copy + Display>(x: T, y: U) -> u32
320 where T: Copy + Display,
321 U: Debug
322 (<x: T>, y: U)
323 "#]],
298 ); 324 );
299 assert_eq!(info.active_parameter, Some(0));
300 } 325 }
301 326
302 #[test] 327 #[test]
303 fn test_fn_signature_no_params() { 328 fn test_fn_signature_no_params() {
304 let info = call_info( 329 check(
305 r#"fn foo<T>() -> T where T: Copy + Display {}
306fn bar() { foo(<|>); }"#,
307 );
308
309 assert!(info.parameters().is_empty());
310 assert_eq!(
311 info.label(),
312 r#" 330 r#"
313fn foo<T>() -> T 331fn foo<T>() -> T where T: Copy + Display {}
314where T: Copy + Display 332fn bar() { foo(<|>); }
315 "# 333"#,
316 .trim() 334 expect![[r#"
335 fn foo<T>() -> T
336 where T: Copy + Display
337 ()
338 "#]],
317 ); 339 );
318 assert!(info.active_parameter.is_none());
319 } 340 }
320 341
321 #[test] 342 #[test]
322 fn test_fn_signature_for_impl() { 343 fn test_fn_signature_for_impl() {
323 let info = call_info( 344 check(
324 r#"struct F; impl F { pub fn new() { F{}} } 345 r#"
325fn bar() {let _ : F = F::new(<|>);}"#, 346struct F; impl F { pub fn new() { F{}} }
347fn bar() {let _ : F = F::new(<|>);}
348"#,
349 expect![[r#"
350 pub fn new()
351 ()
352 "#]],
326 ); 353 );
327
328 assert!(info.parameters().is_empty());
329 assert_eq!(info.active_parameter, None);
330 } 354 }
331 355
332 #[test] 356 #[test]
333 fn test_fn_signature_for_method_self() { 357 fn test_fn_signature_for_method_self() {
334 let info = call_info( 358 check(
335 r#"struct F; 359 r#"
336impl F { 360struct S;
337 pub fn new() -> F{ 361impl S { pub fn do_it(&self) {} }
338 F{}
339 }
340
341 pub fn do_it(&self) {}
342}
343 362
344fn bar() { 363fn bar() {
345 let f : F = F::new(); 364 let s: S = S;
346 f.do_it(<|>); 365 s.do_it(<|>);
347}"#, 366}
367"#,
368 expect![[r#"
369 pub fn do_it(&self)
370 (&self)
371 "#]],
348 ); 372 );
349
350 assert_eq!(info.parameters(), ["&self"]);
351 assert_eq!(info.active_parameter, None);
352 } 373 }
353 374
354 #[test] 375 #[test]
355 fn test_fn_signature_for_method_with_arg() { 376 fn test_fn_signature_for_method_with_arg() {
356 let info = call_info( 377 check(
357 r#"struct F; 378 r#"
358impl F { 379struct S;
359 pub fn new() -> F{ 380impl S { pub fn do_it(&self, x: i32) {} }
360 F{}
361 }
362
363 pub fn do_it(&self, x: i32) {}
364}
365 381
366fn bar() { 382fn bar() {
367 let f : F = F::new(); 383 let s: S = S;
368 f.do_it(<|>); 384 s.do_it(<|>);
369}"#, 385}
386"#,
387 expect![[r#"
388 pub fn do_it(&self, x: i32)
389 (&self, <x: i32>)
390 "#]],
370 ); 391 );
371
372 assert_eq!(info.parameters(), ["&self", "x: i32"]);
373 assert_eq!(info.active_parameter, Some(1));
374 } 392 }
375 393
376 #[test] 394 #[test]
377 fn test_fn_signature_with_docs_simple() { 395 fn test_fn_signature_with_docs_simple() {
378 let info = call_info( 396 check(
379 r#" 397 r#"
380/// test 398/// test
381// non-doc-comment 399// non-doc-comment
@@ -387,17 +405,18 @@ fn bar() {
387 let _ = foo(<|>); 405 let _ = foo(<|>);
388} 406}
389"#, 407"#,
408 expect![[r#"
409 test
410 ------
411 fn foo(j: u32) -> u32
412 (<j: u32>)
413 "#]],
390 ); 414 );
391
392 assert_eq!(info.parameters(), ["j: u32"]);
393 assert_eq!(info.active_parameter, Some(0));
394 assert_eq!(info.label(), "fn foo(j: u32) -> u32");
395 assert_eq!(info.doc().map(|it| it.into()), Some("test".to_string()));
396 } 415 }
397 416
398 #[test] 417 #[test]
399 fn test_fn_signature_with_docs() { 418 fn test_fn_signature_with_docs() {
400 let info = call_info( 419 check(
401 r#" 420 r#"
402/// Adds one to the number given. 421/// Adds one to the number given.
403/// 422///
@@ -415,31 +434,26 @@ pub fn add_one(x: i32) -> i32 {
415pub fn do() { 434pub fn do() {
416 add_one(<|> 435 add_one(<|>
417}"#, 436}"#,
418 ); 437 expect![[r##"
419 438 Adds one to the number given.
420 assert_eq!(info.parameters(), ["x: i32"]);
421 assert_eq!(info.active_parameter, Some(0));
422 assert_eq!(info.label(), "pub fn add_one(x: i32) -> i32");
423 assert_eq!(
424 info.doc().map(|it| it.into()),
425 Some(
426 r#"Adds one to the number given.
427 439
428# Examples 440 # Examples
429 441
430``` 442 ```
431let five = 5; 443 let five = 5;
432 444
433assert_eq!(6, my_crate::add_one(5)); 445 assert_eq!(6, my_crate::add_one(5));
434```"# 446 ```
435 .to_string() 447 ------
436 ) 448 pub fn add_one(x: i32) -> i32
449 (<x: i32>)
450 "##]],
437 ); 451 );
438 } 452 }
439 453
440 #[test] 454 #[test]
441 fn test_fn_signature_with_docs_impl() { 455 fn test_fn_signature_with_docs_impl() {
442 let info = call_info( 456 check(
443 r#" 457 r#"
444struct addr; 458struct addr;
445impl addr { 459impl addr {
@@ -460,32 +474,28 @@ impl addr {
460pub fn do_it() { 474pub fn do_it() {
461 addr {}; 475 addr {};
462 addr::add_one(<|>); 476 addr::add_one(<|>);
463}"#, 477}
464 ); 478"#,
465 479 expect![[r##"
466 assert_eq!(info.parameters(), ["x: i32"]); 480 Adds one to the number given.
467 assert_eq!(info.active_parameter, Some(0));
468 assert_eq!(info.label(), "pub fn add_one(x: i32) -> i32");
469 assert_eq!(
470 info.doc().map(|it| it.into()),
471 Some(
472 r#"Adds one to the number given.
473 481
474# Examples 482 # Examples
475 483
476``` 484 ```
477let five = 5; 485 let five = 5;
478 486
479assert_eq!(6, my_crate::add_one(5)); 487 assert_eq!(6, my_crate::add_one(5));
480```"# 488 ```
481 .to_string() 489 ------
482 ) 490 pub fn add_one(x: i32) -> i32
491 (<x: i32>)
492 "##]],
483 ); 493 );
484 } 494 }
485 495
486 #[test] 496 #[test]
487 fn test_fn_signature_with_docs_from_actix() { 497 fn test_fn_signature_with_docs_from_actix() {
488 let info = call_info( 498 check(
489 r#" 499 r#"
490struct WriteHandler<E>; 500struct WriteHandler<E>;
491 501
@@ -509,101 +519,102 @@ impl<E> WriteHandler<E> {
509pub fn foo(mut r: WriteHandler<()>) { 519pub fn foo(mut r: WriteHandler<()>) {
510 r.finished(<|>); 520 r.finished(<|>);
511} 521}
512
513"#, 522"#,
514 ); 523 expect![[r#"
515 524 Method is called when writer finishes.
516 assert_eq!(info.label(), "fn finished(&mut self, ctx: &mut Self::Context)".to_string()); 525
517 assert_eq!(info.parameters(), ["&mut self", "ctx: &mut Self::Context"]); 526 By default this method stops actor's `Context`.
518 assert_eq!(info.active_parameter, Some(1)); 527 ------
519 assert_eq!( 528 fn finished(&mut self, ctx: &mut Self::Context)
520 info.doc().map(|it| it.into()), 529 (&mut self, <ctx: &mut Self::Context>)
521 Some( 530 "#]],
522 r#"Method is called when writer finishes.
523
524By default this method stops actor's `Context`."#
525 .to_string()
526 )
527 ); 531 );
528 } 532 }
529 533
530 #[test] 534 #[test]
531 fn call_info_bad_offset() { 535 fn call_info_bad_offset() {
532 mark::check!(call_info_bad_offset); 536 mark::check!(call_info_bad_offset);
533 let (analysis, position) = analysis_and_position( 537 check(
534 r#"fn foo(x: u32, y: u32) -> u32 {x + y} 538 r#"
535 fn bar() { foo <|> (3, ); }"#, 539fn foo(x: u32, y: u32) -> u32 {x + y}
540fn bar() { foo <|> (3, ); }
541"#,
542 expect![[""]],
536 ); 543 );
537 let call_info = analysis.call_info(position).unwrap();
538 assert!(call_info.is_none());
539 } 544 }
540 545
541 #[test] 546 #[test]
542 fn test_nested_method_in_lamba() { 547 fn test_nested_method_in_lambda() {
543 let info = call_info( 548 check(
544 r#"struct Foo; 549 r#"
545 550struct Foo;
546impl Foo { 551impl Foo { fn bar(&self, _: u32) { } }
547 fn bar(&self, _: u32) { }
548}
549 552
550fn bar(_: u32) { } 553fn bar(_: u32) { }
551 554
552fn main() { 555fn main() {
553 let foo = Foo; 556 let foo = Foo;
554 std::thread::spawn(move || foo.bar(<|>)); 557 std::thread::spawn(move || foo.bar(<|>));
555}"#, 558}
559"#,
560 expect![[r#"
561 fn bar(&self, _: u32)
562 (&self, <_: u32>)
563 "#]],
556 ); 564 );
557
558 assert_eq!(info.parameters(), ["&self", "_: u32"]);
559 assert_eq!(info.active_parameter, Some(1));
560 assert_eq!(info.label(), "fn bar(&self, _: u32)");
561 } 565 }
562 566
563 #[test] 567 #[test]
564 fn works_for_tuple_structs() { 568 fn works_for_tuple_structs() {
565 let info = call_info( 569 check(
566 r#" 570 r#"
567/// A cool tuple struct 571/// A cool tuple struct
568struct TS(u32, i32); 572struct TS(u32, i32);
569fn main() { 573fn main() {
570 let s = TS(0, <|>); 574 let s = TS(0, <|>);
571}"#, 575}
576"#,
577 expect![[r#"
578 A cool tuple struct
579 ------
580 struct TS(u32, i32) -> TS
581 (u32, <i32>)
582 "#]],
572 ); 583 );
573
574 assert_eq!(info.label(), "struct TS(u32, i32) -> TS");
575 assert_eq!(info.doc().map(|it| it.into()), Some("A cool tuple struct".to_string()));
576 assert_eq!(info.active_parameter, Some(1));
577 } 584 }
578 585
579 #[test] 586 #[test]
580 fn generic_struct() { 587 fn generic_struct() {
581 let info = call_info( 588 check(
582 r#" 589 r#"
583struct TS<T>(T); 590struct TS<T>(T);
584fn main() { 591fn main() {
585 let s = TS(<|>); 592 let s = TS(<|>);
586}"#, 593}
594"#,
595 expect![[r#"
596 struct TS<T>(T) -> TS
597 (<T>)
598 "#]],
587 ); 599 );
588
589 assert_eq!(info.label(), "struct TS<T>(T) -> TS");
590 assert_eq!(info.active_parameter, Some(0));
591 } 600 }
592 601
593 #[test] 602 #[test]
594 fn cant_call_named_structs() { 603 fn cant_call_named_structs() {
595 no_call_info( 604 check(
596 r#" 605 r#"
597struct TS { x: u32, y: i32 } 606struct TS { x: u32, y: i32 }
598fn main() { 607fn main() {
599 let s = TS(<|>); 608 let s = TS(<|>);
600}"#, 609}
610"#,
611 expect![[""]],
601 ); 612 );
602 } 613 }
603 614
604 #[test] 615 #[test]
605 fn works_for_enum_variants() { 616 fn works_for_enum_variants() {
606 let info = call_info( 617 check(
607 r#" 618 r#"
608enum E { 619enum E {
609 /// A Variant 620 /// A Variant
@@ -617,17 +628,19 @@ enum E {
617fn main() { 628fn main() {
618 let a = E::A(<|>); 629 let a = E::A(<|>);
619} 630}
620 "#, 631"#,
632 expect![[r#"
633 A Variant
634 ------
635 E::A(0: i32)
636 (<0: i32>)
637 "#]],
621 ); 638 );
622
623 assert_eq!(info.label(), "E::A(0: i32)");
624 assert_eq!(info.doc().map(|it| it.into()), Some("A Variant".to_string()));
625 assert_eq!(info.active_parameter, Some(0));
626 } 639 }
627 640
628 #[test] 641 #[test]
629 fn cant_call_enum_records() { 642 fn cant_call_enum_records() {
630 no_call_info( 643 check(
631 r#" 644 r#"
632enum E { 645enum E {
633 /// A Variant 646 /// A Variant
@@ -641,13 +654,14 @@ enum E {
641fn main() { 654fn main() {
642 let a = E::C(<|>); 655 let a = E::C(<|>);
643} 656}
644 "#, 657"#,
658 expect![[""]],
645 ); 659 );
646 } 660 }
647 661
648 #[test] 662 #[test]
649 fn fn_signature_for_macro() { 663 fn fn_signature_for_macro() {
650 let info = call_info( 664 check(
651 r#" 665 r#"
652/// empty macro 666/// empty macro
653macro_rules! foo { 667macro_rules! foo {
@@ -657,31 +671,30 @@ macro_rules! foo {
657fn f() { 671fn f() {
658 foo!(<|>); 672 foo!(<|>);
659} 673}
660 "#, 674"#,
675 expect![[r#"
676 empty macro
677 ------
678 foo!()
679 ()
680 "#]],
661 ); 681 );
662
663 assert_eq!(info.label(), "foo!()");
664 assert_eq!(info.doc().map(|it| it.into()), Some("empty macro".to_string()));
665 } 682 }
666 683
667 #[test] 684 #[test]
668 fn fn_signature_for_call_in_macro() { 685 fn fn_signature_for_call_in_macro() {
669 let info = call_info( 686 check(
670 r#" 687 r#"
671 macro_rules! id { 688macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
672 ($($tt:tt)*) => { $($tt)* } 689fn foo() { }
673 } 690id! {
674 fn foo() { 691 fn bar() { foo(<|>); }
675 692}
676 } 693"#,
677 id! { 694 expect![[r#"
678 fn bar() { 695 fn foo()
679 foo(<|>); 696 ()
680 } 697 "#]],
681 }
682 "#,
683 ); 698 );
684
685 assert_eq!(info.label(), "fn foo()");
686 } 699 }
687} 700}
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index 3d93f7067..9e82d6854 100644
--- a/crates/ra_ide/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
@@ -63,6 +63,8 @@ pub(crate) struct CompletionContext<'a> {
63 pub(super) dot_receiver_is_ambiguous_float_literal: bool, 63 pub(super) dot_receiver_is_ambiguous_float_literal: bool,
64 /// If this is a call (method or function) in particular, i.e. the () are already there. 64 /// If this is a call (method or function) in particular, i.e. the () are already there.
65 pub(super) is_call: bool, 65 pub(super) is_call: bool,
66 /// Like `is_call`, but for tuple patterns.
67 pub(super) is_pattern_call: bool,
66 /// If this is a macro call, i.e. the () are already there. 68 /// If this is a macro call, i.e. the () are already there.
67 pub(super) is_macro_call: bool, 69 pub(super) is_macro_call: bool,
68 pub(super) is_path_type: bool, 70 pub(super) is_path_type: bool,
@@ -136,6 +138,7 @@ impl<'a> CompletionContext<'a> {
136 is_new_item: false, 138 is_new_item: false,
137 dot_receiver: None, 139 dot_receiver: None,
138 is_call: false, 140 is_call: false,
141 is_pattern_call: false,
139 is_macro_call: false, 142 is_macro_call: false,
140 is_path_type: false, 143 is_path_type: false,
141 has_type_args: false, 144 has_type_args: false,
@@ -370,6 +373,8 @@ impl<'a> CompletionContext<'a> {
370 .and_then(|it| it.syntax().parent().and_then(ast::CallExpr::cast)) 373 .and_then(|it| it.syntax().parent().and_then(ast::CallExpr::cast))
371 .is_some(); 374 .is_some();
372 self.is_macro_call = path.syntax().parent().and_then(ast::MacroCall::cast).is_some(); 375 self.is_macro_call = path.syntax().parent().and_then(ast::MacroCall::cast).is_some();
376 self.is_pattern_call =
377 path.syntax().parent().and_then(ast::TupleStructPat::cast).is_some();
373 378
374 self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); 379 self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some();
375 self.has_type_args = segment.type_arg_list().is_some(); 380 self.has_type_args = segment.type_arg_list().is_some();
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 48afee5fb..64349dcb8 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -315,6 +315,7 @@ impl Completions {
315 } 315 }
316 316
317 if variant_kind == StructKind::Tuple { 317 if variant_kind == StructKind::Tuple {
318 mark::hit!(inserts_parens_for_tuple_enums);
318 let params = Params::Anonymous(variant.fields(ctx.db).len()); 319 let params = Params::Anonymous(variant.fields(ctx.db).len());
319 res = res.add_call_parens(ctx, qualified_name, params) 320 res = res.add_call_parens(ctx, qualified_name, params)
320 } 321 }
@@ -383,10 +384,17 @@ impl Builder {
383 if !ctx.config.add_call_parenthesis { 384 if !ctx.config.add_call_parenthesis {
384 return self; 385 return self;
385 } 386 }
386 if ctx.use_item_syntax.is_some() || ctx.is_call { 387 if ctx.use_item_syntax.is_some() {
387 mark::hit!(no_parens_in_use_item); 388 mark::hit!(no_parens_in_use_item);
388 return self; 389 return self;
389 } 390 }
391 if ctx.is_pattern_call {
392 mark::hit!(dont_duplicate_pattern_parens);
393 return self;
394 }
395 if ctx.is_call {
396 return self;
397 }
390 398
391 // Don't add parentheses if the expected type is some function reference. 399 // Don't add parentheses if the expected type is some function reference.
392 if let Some(ty) = &ctx.expected_type { 400 if let Some(ty) = &ctx.expected_type {
@@ -865,6 +873,7 @@ fn main() { foo(${1:foo}, ${2:bar}, ${3:ho_ge_})$0 }
865 873
866 #[test] 874 #[test]
867 fn inserts_parens_for_tuple_enums() { 875 fn inserts_parens_for_tuple_enums() {
876 mark::check!(inserts_parens_for_tuple_enums);
868 check_edit( 877 check_edit(
869 "Some", 878 "Some",
870 r#" 879 r#"
@@ -906,6 +915,30 @@ fn main(value: Option<i32>) {
906 } 915 }
907 916
908 #[test] 917 #[test]
918 fn dont_duplicate_pattern_parens() {
919 mark::check!(dont_duplicate_pattern_parens);
920 check_edit(
921 "Var",
922 r#"
923enum E { Var(i32) }
924fn main() {
925 match E::Var(92) {
926 E::<|>(92) => (),
927 }
928}
929"#,
930 r#"
931enum E { Var(i32) }
932fn main() {
933 match E::Var(92) {
934 E::Var(92) => (),
935 }
936}
937"#,
938 );
939 }
940
941 #[test]
909 fn no_call_parens_if_fn_ptr_needed() { 942 fn no_call_parens_if_fn_ptr_needed() {
910 mark::check!(no_call_parens_if_fn_ptr_needed); 943 mark::check!(no_call_parens_if_fn_ptr_needed);
911 check_edit( 944 check_edit(
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs
index 3afe5381a..fe75f4b2c 100644
--- a/crates/ra_ide/src/diagnostics.rs
+++ b/crates/ra_ide/src/diagnostics.rs
@@ -35,8 +35,8 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
35 let parse = db.parse(file_id); 35 let parse = db.parse(file_id);
36 let mut res = Vec::new(); 36 let mut res = Vec::new();
37 37
38 // [#34344] Only take first 500 errors to prevent slowing down editor/ide, the number 500 is chosen arbitrarily. 38 // [#34344] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily.
39 res.extend(parse.errors().iter().take(500).map(|err| Diagnostic { 39 res.extend(parse.errors().iter().take(128).map(|err| Diagnostic {
40 range: err.range(), 40 range: err.range(),
41 message: format!("Syntax Error: {}", err), 41 message: format!("Syntax Error: {}", err),
42 severity: Severity::Error, 42 severity: Severity::Error,
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs
index f575d738f..c30b20611 100644
--- a/crates/ra_ide/src/goto_definition.rs
+++ b/crates/ra_ide/src/goto_definition.rs
@@ -866,4 +866,22 @@ type Alias<T> = T<|>;
866"#, 866"#,
867 ) 867 )
868 } 868 }
869
870 #[test]
871 fn goto_def_for_macro_container() {
872 check(
873 r#"
874//- /lib.rs
875foo::module<|>::mac!();
876
877//- /foo/lib.rs
878pub mod module {
879 //^^^^^^
880 #[macro_export]
881 macro_rules! _mac { () => { () } }
882 pub use crate::_mac as mac;
883}
884"#,
885 );
886 }
869} 887}
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index 5bb6f9642..6ac44c2c0 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -553,6 +553,7 @@ fn highlight_element(
553 T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { 553 T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => {
554 Highlight::new(HighlightTag::Macro) 554 Highlight::new(HighlightTag::Macro)
555 } 555 }
556 p if p.is_punct() => HighlightTag::Punctuation.into(),
556 557
557 k if k.is_keyword() => { 558 k if k.is_keyword() => {
558 let h = Highlight::new(HighlightTag::Keyword); 559 let h = Highlight::new(HighlightTag::Keyword);
@@ -566,10 +567,31 @@ fn highlight_element(
566 | T![return] 567 | T![return]
567 | T![while] 568 | T![while]
568 | T![in] => h | HighlightModifier::ControlFlow, 569 | T![in] => h | HighlightModifier::ControlFlow,
569 T![for] if !is_child_of_impl(element) => h | HighlightModifier::ControlFlow, 570 T![for] if !is_child_of_impl(&element) => h | HighlightModifier::ControlFlow,
570 T![unsafe] => h | HighlightModifier::Unsafe, 571 T![unsafe] => h | HighlightModifier::Unsafe,
571 T![true] | T![false] => HighlightTag::BoolLiteral.into(), 572 T![true] | T![false] => HighlightTag::BoolLiteral.into(),
572 T![self] => HighlightTag::SelfKeyword.into(), 573 T![self] => {
574 let self_param_is_mut = element
575 .parent()
576 .and_then(ast::SelfParam::cast)
577 .and_then(|p| p.mut_token())
578 .is_some();
579 // closure to enforce lazyness
580 let self_path = || {
581 sema.resolve_path(&element.parent()?.parent().and_then(ast::Path::cast)?)
582 };
583 if self_param_is_mut
584 || matches!(self_path(),
585 Some(hir::PathResolution::Local(local))
586 if local.is_self(db)
587 && (local.is_mut(db) || local.ty(db).is_mutable_reference())
588 )
589 {
590 HighlightTag::SelfKeyword | HighlightModifier::Mutable
591 } else {
592 HighlightTag::SelfKeyword.into()
593 }
594 }
573 _ => h, 595 _ => h,
574 } 596 }
575 } 597 }
@@ -592,7 +614,7 @@ fn highlight_element(
592 } 614 }
593} 615}
594 616
595fn is_child_of_impl(element: SyntaxElement) -> bool { 617fn is_child_of_impl(element: &SyntaxElement) -> bool {
596 match element.parent() { 618 match element.parent() {
597 Some(e) => e.kind() == IMPL_DEF, 619 Some(e) => e.kind() == IMPL_DEF,
598 _ => false, 620 _ => false,
diff --git a/crates/ra_ide/src/syntax_highlighting/tags.rs b/crates/ra_ide/src/syntax_highlighting/tags.rs
index 719c6ed3c..49ec94bdc 100644
--- a/crates/ra_ide/src/syntax_highlighting/tags.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tags.rs
@@ -32,6 +32,7 @@ pub enum HighlightTag {
32 Macro, 32 Macro,
33 Module, 33 Module,
34 NumericLiteral, 34 NumericLiteral,
35 Punctuation,
35 SelfKeyword, 36 SelfKeyword,
36 SelfType, 37 SelfType,
37 Static, 38 Static,
@@ -83,6 +84,7 @@ impl HighlightTag {
83 HighlightTag::Generic => "generic", 84 HighlightTag::Generic => "generic",
84 HighlightTag::Keyword => "keyword", 85 HighlightTag::Keyword => "keyword",
85 HighlightTag::Lifetime => "lifetime", 86 HighlightTag::Lifetime => "lifetime",
87 HighlightTag::Punctuation => "punctuation",
86 HighlightTag::Macro => "macro", 88 HighlightTag::Macro => "macro",
87 HighlightTag::Module => "module", 89 HighlightTag::Module => "module",
88 HighlightTag::NumericLiteral => "numeric_literal", 90 HighlightTag::NumericLiteral => "numeric_literal",
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs
index aa7c887d6..87a6e2523 100644
--- a/crates/ra_ide/src/syntax_highlighting/tests.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tests.rs
@@ -25,6 +25,16 @@ impl Bar for Foo {
25 } 25 }
26} 26}
27 27
28impl Foo {
29 fn baz(mut self) -> i32 {
30 self.x
31 }
32
33 fn qux(&mut self) {
34 self.x = 0;
35 }
36}
37
28static mut STATIC_MUT: i32 = 0; 38static mut STATIC_MUT: i32 = 0;
29 39
30fn foo<'a, T>() -> T { 40fn foo<'a, T>() -> T {
diff --git a/crates/ra_ide/test_data/highlight_doctest.html b/crates/ra_ide/test_data/highlight_doctest.html
index a77fabb68..1cc17d6d0 100644
--- a/crates/ra_ide/test_data/highlight_doctest.html
+++ b/crates/ra_ide/test_data/highlight_doctest.html
@@ -36,67 +36,67 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
36.unresolved_reference { color: #FC5555; text-decoration: wavy underline; } 36.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
37</style> 37</style>
38<pre><code><span class="comment documentation">/// ```</span> 38<pre><code><span class="comment documentation">/// ```</span>
39<span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> _ = </span><span class="string_literal injected">"early doctests should not go boom"</span><span class="generic injected">;</span> 39<span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="punctuation injected">_</span><span class="generic injected"> </span><span class="punctuation injected">=</span><span class="generic injected"> </span><span class="string_literal injected">"early doctests should not go boom"</span><span class="punctuation injected">;</span><span class="punctuation injected">
40<span class="comment documentation">/// ```</span> 40</span><span class="comment documentation">/// ```</span>
41<span class="keyword">struct</span> <span class="struct declaration">Foo</span> { 41<span class="keyword">struct</span> <span class="struct declaration">Foo</span> <span class="punctuation">{</span>
42 <span class="field declaration">bar</span>: <span class="builtin_type">bool</span>, 42 <span class="field declaration">bar</span><span class="punctuation">:</span> <span class="builtin_type">bool</span><span class="punctuation">,</span>
43} 43<span class="punctuation">}</span>
44 44
45<span class="keyword">impl</span> <span class="struct">Foo</span> { 45<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
46 <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>; 46 <span class="keyword">pub</span> <span class="keyword">const</span> <span class="constant declaration">bar</span><span class="punctuation">:</span> <span class="builtin_type">bool</span> <span class="punctuation">=</span> <span class="bool_literal">true</span><span class="punctuation">;</span>
47 47
48 <span class="comment documentation">/// Constructs a new `Foo`.</span> 48 <span class="comment documentation">/// Constructs a new `Foo`.</span>
49 <span class="comment documentation">///</span> 49 <span class="comment documentation">///</span>
50 <span class="comment documentation">/// # Examples</span> 50 <span class="comment documentation">/// # Examples</span>
51 <span class="comment documentation">///</span> 51 <span class="comment documentation">///</span>
52 <span class="comment documentation">/// ```</span> 52 <span class="comment documentation">/// ```</span>
53 <span class="comment documentation">/// #</span><span class="generic injected"> </span><span class="attribute injected">#![</span><span class="function attribute injected">allow</span><span class="attribute injected">(unused_mut)]</span> 53 <span class="comment documentation">/// #</span><span class="generic injected"> </span><span class="punctuation injected">#</span><span class="punctuation injected">!</span><span class="punctuation injected">[</span><span class="function attribute injected">allow</span><span class="punctuation injected">(</span><span class="attribute injected">unused_mut</span><span class="punctuation injected">)</span><span class="punctuation injected">]</span>
54 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="keyword injected">mut</span><span class="generic injected"> </span><span class="variable declaration injected mutable">foo</span><span class="generic injected">: </span><span class="struct injected">Foo</span><span class="generic injected"> = </span><span class="struct injected">Foo</span><span class="generic injected">::</span><span class="function injected">new</span><span class="generic injected">();</span> 54 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="keyword injected">mut</span><span class="generic injected"> </span><span class="variable declaration injected mutable">foo</span><span class="punctuation injected">:</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="generic injected"> </span><span class="punctuation injected">=</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="punctuation injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected">
55 <span class="comment documentation">/// ```</span> 55</span> <span class="comment documentation">/// ```</span>
56 <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration">new</span>() -&gt; <span class="struct">Foo</span> { 56 <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration">new</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">-&gt;</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
57 <span class="struct">Foo</span> { <span class="field">bar</span>: <span class="bool_literal">true</span> } 57 <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">bar</span><span class="punctuation">:</span> <span class="bool_literal">true</span> <span class="punctuation">}</span>
58 } 58 <span class="punctuation">}</span>
59 59
60 <span class="comment documentation">/// `bar` method on `Foo`.</span> 60 <span class="comment documentation">/// `bar` method on `Foo`.</span>
61 <span class="comment documentation">///</span> 61 <span class="comment documentation">///</span>
62 <span class="comment documentation">/// # Examples</span> 62 <span class="comment documentation">/// # Examples</span>
63 <span class="comment documentation">///</span> 63 <span class="comment documentation">///</span>
64 <span class="comment documentation">/// ```</span> 64 <span class="comment documentation">/// ```</span>
65 <span class="comment documentation">/// </span><span class="keyword injected">use</span><span class="generic injected"> </span><span class="module injected">x</span><span class="generic injected">::</span><span class="module injected">y</span><span class="generic injected">;</span> 65 <span class="comment documentation">/// </span><span class="keyword injected">use</span><span class="generic injected"> </span><span class="module injected">x</span><span class="punctuation injected">::</span><span class="module injected">y</span><span class="punctuation injected">;</span>
66 <span class="comment documentation">///</span> 66 <span class="comment documentation">///</span>
67 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">foo</span><span class="generic injected"> = </span><span class="struct injected">Foo</span><span class="generic injected">::</span><span class="function injected">new</span><span class="generic injected">();</span> 67 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">foo</span><span class="generic injected"> </span><span class="punctuation injected">=</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="punctuation injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span>
68 <span class="comment documentation">///</span> 68 <span class="comment documentation">///</span>
69 <span class="comment documentation">/// </span><span class="comment injected">// calls bar on foo</span> 69 <span class="comment documentation">/// </span><span class="comment injected">// calls bar on foo</span>
70 <span class="comment documentation">/// </span><span class="macro injected">assert!</span><span class="generic injected">(foo.bar());</span> 70 <span class="comment documentation">/// </span><span class="macro injected">assert!</span><span class="punctuation injected">(</span><span class="generic injected">foo</span><span class="punctuation injected">.</span><span class="generic injected">bar</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span>
71 <span class="comment documentation">///</span> 71 <span class="comment documentation">///</span>
72 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">bar</span><span class="generic injected"> = </span><span class="variable injected">foo</span><span class="generic injected">.</span><span class="field injected">bar</span><span class="generic injected"> || </span><span class="struct injected">Foo</span><span class="generic injected">::</span><span class="constant injected">bar</span><span class="generic injected">;</span> 72 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">bar</span><span class="generic injected"> </span><span class="punctuation injected">=</span><span class="generic injected"> </span><span class="variable injected">foo</span><span class="punctuation injected">.</span><span class="field injected">bar</span><span class="generic injected"> </span><span class="punctuation injected">||</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="punctuation injected">::</span><span class="constant injected">bar</span><span class="punctuation injected">;</span>
73 <span class="comment documentation">///</span> 73 <span class="comment documentation">///</span>
74 <span class="comment documentation">/// </span><span class="comment injected">/* multi-line 74 <span class="comment documentation">/// </span><span class="comment injected">/* multi-line
75 </span><span class="comment documentation">/// </span><span class="comment injected"> comment */</span> 75 </span><span class="comment documentation">/// </span><span class="comment injected"> comment */</span>
76 <span class="comment documentation">///</span> 76 <span class="comment documentation">///</span>
77 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">multi_line_string</span><span class="generic injected"> = </span><span class="string_literal injected">"Foo 77 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">multi_line_string</span><span class="generic injected"> </span><span class="punctuation injected">=</span><span class="generic injected"> </span><span class="string_literal injected">"Foo
78 </span><span class="comment documentation">/// </span><span class="string_literal injected"> bar 78 </span><span class="comment documentation">/// </span><span class="string_literal injected"> bar
79 </span><span class="comment documentation">/// </span><span class="string_literal injected"> "</span><span class="generic injected">;</span> 79 </span><span class="comment documentation">/// </span><span class="string_literal injected"> "</span><span class="punctuation injected">;</span>
80 <span class="comment documentation">///</span> 80 <span class="comment documentation">///</span>
81 <span class="comment documentation">/// ```</span> 81 <span class="comment documentation">/// ```</span>
82 <span class="comment documentation">///</span> 82 <span class="comment documentation">///</span>
83 <span class="comment documentation">/// ```rust,no_run</span> 83 <span class="comment documentation">/// ```rust,no_run</span>
84 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">foobar</span><span class="generic injected"> = </span><span class="struct injected">Foo</span><span class="generic injected">::</span><span class="function injected">new</span><span class="generic injected">().</span><span class="function injected">bar</span><span class="generic injected">();</span> 84 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">foobar</span><span class="generic injected"> </span><span class="punctuation injected">=</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="punctuation injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">.</span><span class="function injected">bar</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected">
85 <span class="comment documentation">/// ```</span> 85</span> <span class="comment documentation">/// ```</span>
86 <span class="comment documentation">///</span> 86 <span class="comment documentation">///</span>
87 <span class="comment documentation">/// ```sh</span> 87 <span class="comment documentation">/// ```sh</span>
88 <span class="comment documentation">/// echo 1</span> 88 <span class="comment documentation">/// echo 1</span>
89 <span class="comment documentation">/// ```</span> 89 <span class="comment documentation">/// ```</span>
90 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">foo</span>(&<span class="self_keyword">self</span>) -&gt; <span class="builtin_type">bool</span> { 90 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">foo</span><span class="punctuation">(</span><span class="punctuation">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">-&gt;</span> <span class="builtin_type">bool</span> <span class="punctuation">{</span>
91 <span class="bool_literal">true</span> 91 <span class="bool_literal">true</span>
92 } 92 <span class="punctuation">}</span>
93} 93<span class="punctuation">}</span>
94 94
95<span class="comment documentation">/// ```</span> 95<span class="comment documentation">/// ```</span>
96<span class="comment documentation">/// </span><span class="macro injected">noop!</span><span class="generic injected">(</span><span class="numeric_literal injected">1</span><span class="generic injected">);</span> 96<span class="comment documentation">/// </span><span class="macro injected">noop!</span><span class="punctuation injected">(</span><span class="numeric_literal injected">1</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected">
97<span class="comment documentation">/// ```</span> 97</span><span class="comment documentation">/// ```</span>
98<span class="macro">macro_rules!</span> <span class="macro declaration">noop</span> { 98<span class="macro">macro_rules!</span> <span class="macro declaration">noop</span> <span class="punctuation">{</span>
99 ($expr:expr) =&gt; { 99 <span class="punctuation">(</span><span class="punctuation">$</span>expr<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="punctuation">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span>
100 $expr 100 <span class="punctuation">$</span>expr
101 } 101 <span class="punctuation">}</span>
102}</code></pre> \ No newline at end of file 102<span class="punctuation">}</span></code></pre> \ No newline at end of file
diff --git a/crates/ra_ide/test_data/highlight_injection.html b/crates/ra_ide/test_data/highlight_injection.html
index e15234936..461cfc437 100644
--- a/crates/ra_ide/test_data/highlight_injection.html
+++ b/crates/ra_ide/test_data/highlight_injection.html
@@ -35,14 +35,14 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
35 35
36.unresolved_reference { color: #FC5555; text-decoration: wavy underline; } 36.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
37</style> 37</style>
38<pre><code><span class="keyword">fn</span> <span class="function declaration">fixture</span>(<span class="value_param declaration">ra_fixture</span>: &<span class="builtin_type">str</span>) {} 38<pre><code><span class="keyword">fn</span> <span class="function declaration">fixture</span><span class="punctuation">(</span><span class="value_param declaration">ra_fixture</span><span class="punctuation">:</span> <span class="punctuation">&</span><span class="builtin_type">str</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
39 39
40<span class="keyword">fn</span> <span class="function declaration">main</span>() { 40<span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
41 <span class="function">fixture</span>(<span class="string_literal">r#"</span> 41 <span class="function">fixture</span><span class="punctuation">(</span><span class="string_literal">r#"</span>
42 <span class="keyword">trait</span> <span class="trait declaration">Foo</span> { 42 <span class="keyword">trait</span> <span class="trait declaration">Foo</span> <span class="punctuation">{</span>
43 <span class="keyword">fn</span> <span class="function declaration">foo</span>() { 43 <span class="keyword">fn</span> <span class="function declaration">foo</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
44 <span class="macro">println!</span>(<span class="string_literal">"2 + 2 = {}"</span>, <span class="numeric_literal">4</span>); 44 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"2 + 2 = {}"</span><span class="punctuation">,</span> <span class="numeric_literal">4</span><span class="punctuation">)</span><span class="punctuation">;</span>
45 } 45 <span class="punctuation">}</span>
46 }<span class="string_literal">"#</span> 46 <span class="punctuation">}</span><span class="string_literal">"#</span>
47 ); 47 <span class="punctuation">)</span><span class="punctuation">;</span>
48}</code></pre> \ No newline at end of file 48<span class="punctuation">}</span></code></pre> \ No newline at end of file
diff --git a/crates/ra_ide/test_data/highlight_strings.html b/crates/ra_ide/test_data/highlight_strings.html
index 423813366..9f98e73e7 100644
--- a/crates/ra_ide/test_data/highlight_strings.html
+++ b/crates/ra_ide/test_data/highlight_strings.html
@@ -35,62 +35,62 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
35 35
36.unresolved_reference { color: #FC5555; text-decoration: wavy underline; } 36.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
37</style> 37</style>
38<pre><code><span class="macro">macro_rules!</span> <span class="macro declaration">println</span> { 38<pre><code><span class="macro">macro_rules!</span> <span class="macro declaration">println</span> <span class="punctuation">{</span>
39 ($($arg:tt)*) =&gt; ({ 39 <span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>arg<span class="punctuation">:</span>tt<span class="punctuation">)</span>*<span class="punctuation">)</span> <span class="punctuation">=</span><span class="punctuation">&gt;</span> <span class="punctuation">(</span><span class="punctuation">{</span>
40 $<span class="keyword">crate</span>::io::_print($<span class="keyword">crate</span>::format_args_nl!($($arg)*)); 40 <span class="punctuation">$</span><span class="keyword">crate</span><span class="punctuation">:</span><span class="punctuation">:</span>io<span class="punctuation">:</span><span class="punctuation">:</span>_print<span class="punctuation">(</span><span class="punctuation">$</span><span class="keyword">crate</span><span class="punctuation">:</span><span class="punctuation">:</span>format_args_nl<span class="punctuation">!</span><span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>arg<span class="punctuation">)</span>*<span class="punctuation">)</span><span class="punctuation">)</span><span class="punctuation">;</span>
41 }) 41 <span class="punctuation">}</span><span class="punctuation">)</span>
42} 42<span class="punctuation">}</span>
43#[rustc_builtin_macro] 43#[rustc_builtin_macro]
44<span class="macro">macro_rules!</span> <span class="macro declaration">format_args_nl</span> { 44<span class="macro">macro_rules!</span> <span class="macro declaration">format_args_nl</span> <span class="punctuation">{</span>
45 ($fmt:expr) =&gt; {{ <span class="comment">/* compiler built-in */</span> }}; 45 <span class="punctuation">(</span><span class="punctuation">$</span>fmt<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="punctuation">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">{</span> <span class="comment">/* compiler built-in */</span> <span class="punctuation">}</span><span class="punctuation">}</span><span class="punctuation">;</span>
46 ($fmt:expr, $($args:tt)*) =&gt; {{ <span class="comment">/* compiler built-in */</span> }}; 46 <span class="punctuation">(</span><span class="punctuation">$</span>fmt<span class="punctuation">:</span>expr<span class="punctuation">,</span> <span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>args<span class="punctuation">:</span>tt<span class="punctuation">)</span>*<span class="punctuation">)</span> <span class="punctuation">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">{</span> <span class="comment">/* compiler built-in */</span> <span class="punctuation">}</span><span class="punctuation">}</span><span class="punctuation">;</span>
47} 47<span class="punctuation">}</span>
48 48
49<span class="keyword">fn</span> <span class="function declaration">main</span>() { 49<span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
50 <span class="comment">// from https://doc.rust-lang.org/std/fmt/index.html</span> 50 <span class="comment">// from https://doc.rust-lang.org/std/fmt/index.html</span>
51 <span class="macro">println!</span>(<span class="string_literal">"Hello"</span>); <span class="comment">// =&gt; "Hello"</span> 51 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello"</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// =&gt; "Hello"</span>
52 <span class="macro">println!</span>(<span class="string_literal">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"world"</span>); <span class="comment">// =&gt; "Hello, world!"</span> 52 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"world"</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// =&gt; "Hello, world!"</span>
53 <span class="macro">println!</span>(<span class="string_literal">"The number is </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="numeric_literal">1</span>); <span class="comment">// =&gt; "The number is 1"</span> 53 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"The number is </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="numeric_literal">1</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// =&gt; "The number is 1"</span>
54 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal">"</span>, (<span class="numeric_literal">3</span>, <span class="numeric_literal">4</span>)); <span class="comment">// =&gt; "(3, 4)"</span> 54 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="punctuation">(</span><span class="numeric_literal">3</span><span class="punctuation">,</span> <span class="numeric_literal">4</span><span class="punctuation">)</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// =&gt; "(3, 4)"</span>
55 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">value</span><span class="format_specifier">}</span><span class="string_literal">"</span>, value=<span class="numeric_literal">4</span>); <span class="comment">// =&gt; "4"</span> 55 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">value</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> value<span class="punctuation">=</span><span class="numeric_literal">4</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// =&gt; "4"</span>
56 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="numeric_literal">1</span>, <span class="numeric_literal">2</span>); <span class="comment">// =&gt; "1 2"</span> 56 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="numeric_literal">1</span><span class="punctuation">,</span> <span class="numeric_literal">2</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// =&gt; "1 2"</span>
57 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">4</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="numeric_literal">42</span>); <span class="comment">// =&gt; "0042" with leading zerosV</span> 57 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">4</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="numeric_literal">42</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// =&gt; "0042" with leading zerosV</span>
58 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="numeric_literal">1</span>, <span class="numeric_literal">2</span>); <span class="comment">// =&gt; "2 1 1 2"</span> 58 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="numeric_literal">1</span><span class="punctuation">,</span> <span class="numeric_literal">2</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// =&gt; "2 1 1 2"</span>
59 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">argument</span><span class="format_specifier">}</span><span class="string_literal">"</span>, argument = <span class="string_literal">"test"</span>); <span class="comment">// =&gt; "test"</span> 59 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">argument</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> argument <span class="punctuation">=</span> <span class="string_literal">"test"</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// =&gt; "test"</span>
60 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="numeric_literal">1</span>, name = <span class="numeric_literal">2</span>); <span class="comment">// =&gt; "2 1"</span> 60 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="numeric_literal">1</span><span class="punctuation">,</span> name <span class="punctuation">=</span> <span class="numeric_literal">2</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// =&gt; "2 1"</span>
61 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">a</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="variable">c</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="variable">b</span><span class="format_specifier">}</span><span class="string_literal">"</span>, a=<span class="string_literal">"a"</span>, b=<span class="char_literal">'b'</span>, c=<span class="numeric_literal">3</span>); <span class="comment">// =&gt; "a 3 b"</span> 61 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">a</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="variable">c</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="variable">b</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> a<span class="punctuation">=</span><span class="string_literal">"a"</span><span class="punctuation">,</span> b<span class="punctuation">=</span><span class="char_literal">'b'</span><span class="punctuation">,</span> c<span class="punctuation">=</span><span class="numeric_literal">3</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// =&gt; "a 3 b"</span>
62 <span class="macro">println!</span>(<span class="string_literal">"{{</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">}}"</span>, <span class="numeric_literal">2</span>); <span class="comment">// =&gt; "{2}"</span> 62 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"{{</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">}}"</span><span class="punctuation">,</span> <span class="numeric_literal">2</span><span class="punctuation">)</span><span class="punctuation">;</span> <span class="comment">// =&gt; "{2}"</span>
63 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>); 63 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">)</span><span class="punctuation">;</span>
64 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">5</span>); 64 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">,</span> <span class="numeric_literal">5</span><span class="punctuation">)</span><span class="punctuation">;</span>
65 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="numeric_literal">5</span>, <span class="string_literal">"x"</span>); 65 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="numeric_literal">5</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">)</span><span class="punctuation">;</span>
66 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">width</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>, width = <span class="numeric_literal">5</span>); 66 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">width</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">,</span> width <span class="punctuation">=</span> <span class="numeric_literal">5</span><span class="punctuation">)</span><span class="punctuation">;</span>
67 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>); 67 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">)</span><span class="punctuation">;</span>
68 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">-</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>); 68 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">-</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">)</span><span class="punctuation">;</span>
69 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">^</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>); 69 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">^</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">)</span><span class="punctuation">;</span>
70 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>); 70 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">)</span><span class="punctuation">;</span>
71 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">+</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="numeric_literal">5</span>); 71 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">+</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="numeric_literal">5</span><span class="punctuation">)</span><span class="punctuation">;</span>
72 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="numeric_literal">27</span>); 72 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="numeric_literal">27</span><span class="punctuation">)</span><span class="punctuation">;</span>
73 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="numeric_literal">5</span>); 73 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="numeric_literal">5</span><span class="punctuation">)</span><span class="punctuation">;</span>
74 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, -<span class="numeric_literal">5</span>); 74 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="punctuation">-</span><span class="numeric_literal">5</span><span class="punctuation">)</span><span class="punctuation">;</span>
75 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="numeric_literal">0</span><span class="numeric_literal">10</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="numeric_literal">27</span>); 75 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="numeric_literal">0</span><span class="numeric_literal">10</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="numeric_literal">27</span><span class="punctuation">)</span><span class="punctuation">;</span>
76 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">0.01</span>); 76 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">,</span> <span class="numeric_literal">0.01</span><span class="punctuation">)</span><span class="punctuation">;</span>
77 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="numeric_literal">5</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">0.01</span>); 77 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="numeric_literal">5</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">,</span> <span class="numeric_literal">0.01</span><span class="punctuation">)</span><span class="punctuation">;</span>
78 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">5</span>, <span class="numeric_literal">0.01</span>); 78 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">,</span> <span class="numeric_literal">5</span><span class="punctuation">,</span> <span class="numeric_literal">0.01</span><span class="punctuation">)</span><span class="punctuation">;</span>
79 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">5</span>, <span class="numeric_literal">0.01</span>); 79 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">,</span> <span class="numeric_literal">5</span><span class="punctuation">,</span> <span class="numeric_literal">0.01</span><span class="punctuation">)</span><span class="punctuation">;</span>
80 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">5</span>, <span class="numeric_literal">0.01</span>); 80 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">,</span> <span class="numeric_literal">5</span><span class="punctuation">,</span> <span class="numeric_literal">0.01</span><span class="punctuation">)</span><span class="punctuation">;</span>
81 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="variable">number</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="variable">prec</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="string_literal">"x"</span>, prec = <span class="numeric_literal">5</span>, number = <span class="numeric_literal">0.01</span>); 81 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="variable">number</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="variable">prec</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> <span class="string_literal">"x"</span><span class="punctuation">,</span> prec <span class="punctuation">=</span> <span class="numeric_literal">5</span><span class="punctuation">,</span> number <span class="punctuation">=</span> <span class="numeric_literal">0.01</span><span class="punctuation">)</span><span class="punctuation">;</span>
82 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 fractional digits"</span>, <span class="string_literal">"Hello"</span>, <span class="numeric_literal">3</span>, name=<span class="numeric_literal">1234.56</span>); 82 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 fractional digits"</span><span class="punctuation">,</span> <span class="string_literal">"Hello"</span><span class="punctuation">,</span> <span class="numeric_literal">3</span><span class="punctuation">,</span> name<span class="punctuation">=</span><span class="numeric_literal">1234.56</span><span class="punctuation">)</span><span class="punctuation">;</span>
83 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 characters"</span>, <span class="string_literal">"Hello"</span>, <span class="numeric_literal">3</span>, name=<span class="string_literal">"1234.56"</span>); 83 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 characters"</span><span class="punctuation">,</span> <span class="string_literal">"Hello"</span><span class="punctuation">,</span> <span class="numeric_literal">3</span><span class="punctuation">,</span> name<span class="punctuation">=</span><span class="string_literal">"1234.56"</span><span class="punctuation">)</span><span class="punctuation">;</span>
84 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">8</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 right-aligned characters"</span>, <span class="string_literal">"Hello"</span>, <span class="numeric_literal">3</span>, name=<span class="string_literal">"1234.56"</span>); 84 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">8</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 right-aligned characters"</span><span class="punctuation">,</span> <span class="string_literal">"Hello"</span><span class="punctuation">,</span> <span class="numeric_literal">3</span><span class="punctuation">,</span> name<span class="punctuation">=</span><span class="string_literal">"1234.56"</span><span class="punctuation">)</span><span class="punctuation">;</span>
85 <span class="macro">println!</span>(<span class="string_literal">"Hello {{}}"</span>); 85 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello {{}}"</span><span class="punctuation">)</span><span class="punctuation">;</span>
86 <span class="macro">println!</span>(<span class="string_literal">"{{ Hello"</span>); 86 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"{{ Hello"</span><span class="punctuation">)</span><span class="punctuation">;</span>
87 87
88 <span class="macro">println!</span>(<span class="string_literal">r"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"world"</span>); 88 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">r"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="punctuation">,</span> <span class="string_literal">"world"</span><span class="punctuation">)</span><span class="punctuation">;</span>
89 89
90 <span class="comment">// escape sequences</span> 90 <span class="comment">// escape sequences</span>
91 <span class="macro">println!</span>(<span class="string_literal">"Hello</span><span class="escape_sequence">\n</span><span class="string_literal">World"</span>); 91 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello</span><span class="escape_sequence">\n</span><span class="string_literal">World"</span><span class="punctuation">)</span><span class="punctuation">;</span>
92 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="escape_sequence">\u{48}</span><span class="escape_sequence">\x65</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6F</span><span class="string_literal"> World"</span>); 92 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="escape_sequence">\u{48}</span><span class="escape_sequence">\x65</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6F</span><span class="string_literal"> World"</span><span class="punctuation">)</span><span class="punctuation">;</span>
93 93
94 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal">"</span>, A = <span class="numeric_literal">92</span>); 94 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> A <span class="punctuation">=</span> <span class="numeric_literal">92</span><span class="punctuation">)</span><span class="punctuation">;</span>
95 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal">"</span>, ничоси = <span class="numeric_literal">92</span>); 95 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="punctuation">,</span> ничоси <span class="punctuation">=</span> <span class="numeric_literal">92</span><span class="punctuation">)</span><span class="punctuation">;</span>
96}</code></pre> \ No newline at end of file 96<span class="punctuation">}</span></code></pre> \ No newline at end of file
diff --git a/crates/ra_ide/test_data/highlight_unsafe.html b/crates/ra_ide/test_data/highlight_unsafe.html
index 7585fbb42..88ac91f9a 100644
--- a/crates/ra_ide/test_data/highlight_unsafe.html
+++ b/crates/ra_ide/test_data/highlight_unsafe.html
@@ -35,20 +35,20 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
35 35
36.unresolved_reference { color: #FC5555; text-decoration: wavy underline; } 36.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
37</style> 37</style>
38<pre><code><span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_fn</span>() {} 38<pre><code><span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
39 39
40<span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span>; 40<span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="punctuation">;</span>
41 41
42<span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> { 42<span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="punctuation">{</span>
43 <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_method</span>(&<span class="self_keyword">self</span>) {} 43 <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_method</span><span class="punctuation">(</span><span class="punctuation">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
44} 44<span class="punctuation">}</span>
45 45
46<span class="keyword">fn</span> <span class="function declaration">main</span>() { 46<span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
47 <span class="keyword">let</span> <span class="variable declaration">x</span> = &<span class="numeric_literal">5</span> <span class="keyword">as</span> *<span class="keyword">const</span> <span class="builtin_type">usize</span>; 47 <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="punctuation">=</span> <span class="punctuation">&</span><span class="numeric_literal">5</span> <span class="keyword">as</span> *<span class="keyword">const</span> <span class="builtin_type">usize</span><span class="punctuation">;</span>
48 <span class="keyword unsafe">unsafe</span> { 48 <span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span>
49 <span class="function unsafe">unsafe_fn</span>(); 49 <span class="function unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
50 <span class="struct">HasUnsafeFn</span>.<span class="function unsafe">unsafe_method</span>(); 50 <span class="struct">HasUnsafeFn</span><span class="punctuation">.</span><span class="function unsafe">unsafe_method</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
51 <span class="keyword">let</span> <span class="variable declaration">y</span> = <span class="operator unsafe">*</span>(<span class="variable">x</span>); 51 <span class="keyword">let</span> <span class="variable declaration">y</span> <span class="punctuation">=</span> <span class="operator unsafe">*</span><span class="punctuation">(</span><span class="variable">x</span><span class="punctuation">)</span><span class="punctuation">;</span>
52 <span class="keyword">let</span> <span class="variable declaration">z</span> = -<span class="variable">x</span>; 52 <span class="keyword">let</span> <span class="variable declaration">z</span> <span class="punctuation">=</span> <span class="punctuation">-</span><span class="variable">x</span><span class="punctuation">;</span>
53 } 53 <span class="punctuation">}</span>
54}</code></pre> \ No newline at end of file 54<span class="punctuation">}</span></code></pre> \ No newline at end of file
diff --git a/crates/ra_ide/test_data/highlighting.html b/crates/ra_ide/test_data/highlighting.html
index 134743c72..767e82f9d 100644
--- a/crates/ra_ide/test_data/highlighting.html
+++ b/crates/ra_ide/test_data/highlighting.html
@@ -35,84 +35,94 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
35 35
36.unresolved_reference { color: #FC5555; text-decoration: wavy underline; } 36.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
37</style> 37</style>
38<pre><code><span class="attribute">#[</span><span class="function attribute">derive</span><span class="attribute">(Clone, Debug)]</span> 38<pre><code><span class="punctuation">#</span><span class="punctuation">[</span><span class="function attribute">derive</span><span class="punctuation">(</span><span class="attribute">Clone</span><span class="punctuation">,</span><span class="attribute"> Debug</span><span class="punctuation">)</span><span class="punctuation">]</span>
39<span class="keyword">struct</span> <span class="struct declaration">Foo</span> { 39<span class="keyword">struct</span> <span class="struct declaration">Foo</span> <span class="punctuation">{</span>
40 <span class="keyword">pub</span> <span class="field declaration">x</span>: <span class="builtin_type">i32</span>, 40 <span class="keyword">pub</span> <span class="field declaration">x</span><span class="punctuation">:</span> <span class="builtin_type">i32</span><span class="punctuation">,</span>
41 <span class="keyword">pub</span> <span class="field declaration">y</span>: <span class="builtin_type">i32</span>, 41 <span class="keyword">pub</span> <span class="field declaration">y</span><span class="punctuation">:</span> <span class="builtin_type">i32</span><span class="punctuation">,</span>
42} 42<span class="punctuation">}</span>
43 43
44<span class="keyword">trait</span> <span class="trait declaration">Bar</span> { 44<span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="punctuation">{</span>
45 <span class="keyword">fn</span> <span class="function declaration">bar</span>(&<span class="self_keyword">self</span>) -&gt; <span class="builtin_type">i32</span>; 45 <span class="keyword">fn</span> <span class="function declaration">bar</span><span class="punctuation">(</span><span class="punctuation">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">-&gt;</span> <span class="builtin_type">i32</span><span class="punctuation">;</span>
46} 46<span class="punctuation">}</span>
47 47
48<span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> { 48<span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
49 <span class="keyword">fn</span> <span class="function declaration">bar</span>(&<span class="self_keyword">self</span>) -&gt; <span class="builtin_type">i32</span> { 49 <span class="keyword">fn</span> <span class="function declaration">bar</span><span class="punctuation">(</span><span class="punctuation">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">-&gt;</span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
50 <span class="self_keyword">self</span>.<span class="field">x</span> 50 <span class="self_keyword">self</span><span class="punctuation">.</span><span class="field">x</span>
51 } 51 <span class="punctuation">}</span>
52} 52<span class="punctuation">}</span>
53 53
54<span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable">STATIC_MUT</span>: <span class="builtin_type">i32</span> = <span class="numeric_literal">0</span>; 54<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
55 55 <span class="keyword">fn</span> <span class="function declaration">baz</span><span class="punctuation">(</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">-&gt;</span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
56<span class="keyword">fn</span> <span class="function declaration">foo</span>&lt;<span class="lifetime declaration">'a</span>, <span class="type_param declaration">T</span>&gt;() -&gt; <span class="type_param">T</span> { 56 <span class="self_keyword">self</span><span class="punctuation">.</span><span class="field">x</span>
57 <span class="function">foo</span>::&lt;<span class="lifetime">'a</span>, <span class="builtin_type">i32</span>&gt;() 57 <span class="punctuation">}</span>
58} 58
59 59 <span class="keyword">fn</span> <span class="function declaration">qux</span><span class="punctuation">(</span><span class="punctuation">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span>
60<span class="macro">macro_rules!</span> <span class="macro declaration">def_fn</span> { 60 <span class="self_keyword mutable">self</span><span class="punctuation">.</span><span class="field">x</span> <span class="punctuation">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span>
61 ($($tt:tt)*) =&gt; {$($tt)*} 61 <span class="punctuation">}</span>
62} 62<span class="punctuation">}</span>
63 63
64<span class="macro">def_fn!</span> { 64<span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable">STATIC_MUT</span><span class="punctuation">:</span> <span class="builtin_type">i32</span> <span class="punctuation">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span>
65 <span class="keyword">fn</span> <span class="function declaration">bar</span>() -&gt; <span class="builtin_type">u32</span> { 65
66<span class="keyword">fn</span> <span class="function declaration">foo</span><span class="punctuation">&lt;</span><span class="lifetime declaration">'a</span><span class="punctuation">,</span> <span class="type_param declaration">T</span><span class="punctuation">&gt;</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">-&gt;</span> <span class="type_param">T</span> <span class="punctuation">{</span>
67 <span class="function">foo</span><span class="punctuation">::</span><span class="punctuation">&lt;</span><span class="lifetime">'a</span><span class="punctuation">,</span> <span class="builtin_type">i32</span><span class="punctuation">&gt;</span><span class="punctuation">(</span><span class="punctuation">)</span>
68<span class="punctuation">}</span>
69
70<span class="macro">macro_rules!</span> <span class="macro declaration">def_fn</span> <span class="punctuation">{</span>
71 <span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>tt<span class="punctuation">:</span>tt<span class="punctuation">)</span>*<span class="punctuation">)</span> <span class="punctuation">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>tt<span class="punctuation">)</span>*<span class="punctuation">}</span>
72<span class="punctuation">}</span>
73
74<span class="macro">def_fn!</span> <span class="punctuation">{</span>
75 <span class="keyword">fn</span> <span class="function declaration">bar</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">-</span><span class="punctuation">&gt;</span> <span class="builtin_type">u32</span> <span class="punctuation">{</span>
66 <span class="numeric_literal">100</span> 76 <span class="numeric_literal">100</span>
67 } 77 <span class="punctuation">}</span>
68} 78<span class="punctuation">}</span>
69 79
70<span class="macro">macro_rules!</span> <span class="macro declaration">noop</span> { 80<span class="macro">macro_rules!</span> <span class="macro declaration">noop</span> <span class="punctuation">{</span>
71 ($expr:expr) =&gt; { 81 <span class="punctuation">(</span><span class="punctuation">$</span>expr<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="punctuation">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span>
72 $expr 82 <span class="punctuation">$</span>expr
73 } 83 <span class="punctuation">}</span>
74} 84<span class="punctuation">}</span>
75 85
76<span class="comment">// comment</span> 86<span class="comment">// comment</span>
77<span class="keyword">fn</span> <span class="function declaration">main</span>() { 87<span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
78 <span class="macro">println!</span>(<span class="string_literal">"Hello, {}!"</span>, <span class="numeric_literal">92</span>); 88 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello, {}!"</span><span class="punctuation">,</span> <span class="numeric_literal">92</span><span class="punctuation">)</span><span class="punctuation">;</span>
79 89
80 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">vec</span> = <span class="unresolved_reference">Vec</span>::<span class="unresolved_reference">new</span>(); 90 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">vec</span> <span class="punctuation">=</span> <span class="unresolved_reference">Vec</span><span class="punctuation">::</span><span class="unresolved_reference">new</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
81 <span class="keyword control">if</span> <span class="bool_literal">true</span> { 91 <span class="keyword control">if</span> <span class="bool_literal">true</span> <span class="punctuation">{</span>
82 <span class="keyword">let</span> <span class="variable declaration">x</span> = <span class="numeric_literal">92</span>; 92 <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="punctuation">=</span> <span class="numeric_literal">92</span><span class="punctuation">;</span>
83 <span class="variable mutable">vec</span>.<span class="unresolved_reference">push</span>(<span class="struct">Foo</span> { <span class="field">x</span>, <span class="field">y</span>: <span class="numeric_literal">1</span> }); 93 <span class="variable mutable">vec</span><span class="punctuation">.</span><span class="unresolved_reference">push</span><span class="punctuation">(</span><span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">,</span> <span class="field">y</span><span class="punctuation">:</span> <span class="numeric_literal">1</span> <span class="punctuation">}</span><span class="punctuation">)</span><span class="punctuation">;</span>
84 } 94 <span class="punctuation">}</span>
85 <span class="keyword unsafe">unsafe</span> { 95 <span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span>
86 <span class="variable mutable">vec</span>.<span class="unresolved_reference">set_len</span>(<span class="numeric_literal">0</span>); 96 <span class="variable mutable">vec</span><span class="punctuation">.</span><span class="unresolved_reference">set_len</span><span class="punctuation">(</span><span class="numeric_literal">0</span><span class="punctuation">)</span><span class="punctuation">;</span>
87 <span class="static mutable">STATIC_MUT</span> = <span class="numeric_literal">1</span>; 97 <span class="static mutable">STATIC_MUT</span> <span class="punctuation">=</span> <span class="numeric_literal">1</span><span class="punctuation">;</span>
88 } 98 <span class="punctuation">}</span>
89 99
90 <span class="keyword control">for</span> <span class="variable declaration">e</span> <span class="keyword control">in</span> <span class="variable mutable">vec</span> { 100 <span class="keyword control">for</span> <span class="variable declaration">e</span> <span class="keyword control">in</span> <span class="variable mutable">vec</span> <span class="punctuation">{</span>
91 <span class="comment">// Do nothing</span> 101 <span class="comment">// Do nothing</span>
92 } 102 <span class="punctuation">}</span>
93 103
94 <span class="macro">noop!</span>(<span class="macro">noop</span><span class="macro">!</span>(<span class="numeric_literal">1</span>)); 104 <span class="macro">noop!</span><span class="punctuation">(</span><span class="macro">noop</span><span class="macro">!</span><span class="punctuation">(</span><span class="numeric_literal">1</span><span class="punctuation">)</span><span class="punctuation">)</span><span class="punctuation">;</span>
95 105
96 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> = <span class="numeric_literal">42</span>; 106 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> <span class="punctuation">=</span> <span class="numeric_literal">42</span><span class="punctuation">;</span>
97 <span class="keyword">let</span> <span class="variable declaration mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>; 107 <span class="keyword">let</span> <span class="variable declaration mutable">y</span> <span class="punctuation">=</span> <span class="punctuation">&</span><span class="keyword">mut</span> <span class="variable mutable">x</span><span class="punctuation">;</span>
98 <span class="keyword">let</span> <span class="variable declaration">z</span> = &<span class="variable mutable">y</span>; 108 <span class="keyword">let</span> <span class="variable declaration">z</span> <span class="punctuation">=</span> <span class="punctuation">&</span><span class="variable mutable">y</span><span class="punctuation">;</span>
99 109
100 <span class="keyword">let</span> <span class="struct">Foo</span> { <span class="field">x</span>: <span class="variable declaration">z</span>, <span class="field">y</span> } = <span class="struct">Foo</span> { <span class="field">x</span>: <span class="variable">z</span>, <span class="field">y</span> }; 110 <span class="keyword">let</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">:</span> <span class="variable declaration">z</span><span class="punctuation">,</span> <span class="field">y</span> <span class="punctuation">}</span> <span class="punctuation">=</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">:</span> <span class="variable">z</span><span class="punctuation">,</span> <span class="field">y</span> <span class="punctuation">}</span><span class="punctuation">;</span>
101 111
102 <span class="variable">y</span>; 112 <span class="variable">y</span><span class="punctuation">;</span>
103} 113<span class="punctuation">}</span>
104 114
105<span class="keyword">enum</span> <span class="enum declaration">Option</span>&lt;<span class="type_param declaration">T</span>&gt; { 115<span class="keyword">enum</span> <span class="enum declaration">Option</span><span class="punctuation">&lt;</span><span class="type_param declaration">T</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span>
106 <span class="enum_variant declaration">Some</span>(<span class="type_param">T</span>), 116 <span class="enum_variant declaration">Some</span><span class="punctuation">(</span><span class="type_param">T</span><span class="punctuation">)</span><span class="punctuation">,</span>
107 <span class="enum_variant declaration">None</span>, 117 <span class="enum_variant declaration">None</span><span class="punctuation">,</span>
108} 118<span class="punctuation">}</span>
109<span class="keyword">use</span> <span class="enum">Option</span>::*; 119<span class="keyword">use</span> <span class="enum">Option</span><span class="punctuation">::</span>*<span class="punctuation">;</span>
110 120
111<span class="keyword">impl</span>&lt;<span class="type_param declaration">T</span>&gt; <span class="enum">Option</span>&lt;<span class="type_param">T</span>&gt; { 121<span class="keyword">impl</span><span class="punctuation">&lt;</span><span class="type_param declaration">T</span><span class="punctuation">&gt;</span> <span class="enum">Option</span><span class="punctuation">&lt;</span><span class="type_param">T</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span>
112 <span class="keyword">fn</span> <span class="function declaration">and</span>&lt;<span class="type_param declaration">U</span>&gt;(<span class="self_keyword">self</span>, <span class="value_param declaration">other</span>: <span class="enum">Option</span>&lt;<span class="type_param">U</span>&gt;) -&gt; <span class="enum">Option</span>&lt;(<span class="type_param">T</span>, <span class="type_param">U</span>)&gt; { 122 <span class="keyword">fn</span> <span class="function declaration">and</span><span class="punctuation">&lt;</span><span class="type_param declaration">U</span><span class="punctuation">&gt;</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">,</span> <span class="value_param declaration">other</span><span class="punctuation">:</span> <span class="enum">Option</span><span class="punctuation">&lt;</span><span class="type_param">U</span><span class="punctuation">&gt;</span><span class="punctuation">)</span> <span class="punctuation">-&gt;</span> <span class="enum">Option</span><span class="punctuation">&lt;</span><span class="punctuation">(</span><span class="type_param">T</span><span class="punctuation">,</span> <span class="type_param">U</span><span class="punctuation">)</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span>
113 <span class="keyword control">match</span> <span class="value_param">other</span> { 123 <span class="keyword control">match</span> <span class="value_param">other</span> <span class="punctuation">{</span>
114 <span class="enum_variant">None</span> =&gt; <span class="macro">unimplemented!</span>(), 124 <span class="enum_variant">None</span> <span class="punctuation">=&gt;</span> <span class="macro">unimplemented!</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span>
115 <span class="variable declaration">Nope</span> =&gt; <span class="variable">Nope</span>, 125 <span class="variable declaration">Nope</span> <span class="punctuation">=&gt;</span> <span class="variable">Nope</span><span class="punctuation">,</span>
116 } 126 <span class="punctuation">}</span>
117 } 127 <span class="punctuation">}</span>
118}</code></pre> \ No newline at end of file 128<span class="punctuation">}</span></code></pre> \ No newline at end of file
diff --git a/crates/ra_ide/test_data/rainbow_highlighting.html b/crates/ra_ide/test_data/rainbow_highlighting.html
index 84a7686b2..2fed04a44 100644
--- a/crates/ra_ide/test_data/rainbow_highlighting.html
+++ b/crates/ra_ide/test_data/rainbow_highlighting.html
@@ -35,15 +35,15 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
35 35
36.unresolved_reference { color: #FC5555; text-decoration: wavy underline; } 36.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
37</style> 37</style>
38<pre><code><span class="keyword">fn</span> <span class="function declaration">main</span>() { 38<pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
39 <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span> = <span class="string_literal">"hello"</span>; 39 <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span> <span class="punctuation">=</span> <span class="string_literal">"hello"</span><span class="punctuation">;</span>
40 <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="2705725358298919760" style="color: hsl(17,51%,74%);">x</span> = <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span>.<span class="unresolved_reference">to_string</span>(); 40 <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="2705725358298919760" style="color: hsl(17,51%,74%);">x</span> <span class="punctuation">=</span> <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span><span class="punctuation">.</span><span class="unresolved_reference">to_string</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
41 <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="3365759661443752373" style="color: hsl(127,76%,66%);">y</span> = <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span>.<span class="unresolved_reference">to_string</span>(); 41 <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="3365759661443752373" style="color: hsl(127,76%,66%);">y</span> <span class="punctuation">=</span> <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span><span class="punctuation">.</span><span class="unresolved_reference">to_string</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
42 42
43 <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="794745962933817518" style="color: hsl(19,74%,76%);">x</span> = <span class="string_literal">"other color please!"</span>; 43 <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="794745962933817518" style="color: hsl(19,74%,76%);">x</span> <span class="punctuation">=</span> <span class="string_literal">"other color please!"</span><span class="punctuation">;</span>
44 <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="6717528807933952652" style="color: hsl(85,49%,84%);">y</span> = <span class="variable" data-binding-hash="794745962933817518" style="color: hsl(19,74%,76%);">x</span>.<span class="unresolved_reference">to_string</span>(); 44 <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="6717528807933952652" style="color: hsl(85,49%,84%);">y</span> <span class="punctuation">=</span> <span class="variable" data-binding-hash="794745962933817518" style="color: hsl(19,74%,76%);">x</span><span class="punctuation">.</span><span class="unresolved_reference">to_string</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
45} 45<span class="punctuation">}</span>
46 46
47<span class="keyword">fn</span> <span class="function declaration">bar</span>() { 47<span class="keyword">fn</span> <span class="function declaration">bar</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
48 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span> = <span class="string_literal">"hello"</span>; 48 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span> <span class="punctuation">=</span> <span class="string_literal">"hello"</span><span class="punctuation">;</span>
49}</code></pre> \ No newline at end of file 49<span class="punctuation">}</span></code></pre> \ No newline at end of file