diff options
Diffstat (limited to 'crates/ra_ide')
-rw-r--r-- | crates/ra_ide/src/completion/completion_context.rs | 1 | ||||
-rw-r--r-- | crates/ra_ide/src/diagnostics.rs | 20 | ||||
-rw-r--r-- | crates/ra_ide/src/lib.rs | 8 | ||||
-rw-r--r-- | crates/ra_ide/src/prime_caches.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/references/rename.rs | 91 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/highlight_doctest.html | 28 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/highlight_injection.html | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/highlight_strings.html | 8 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/highlight_unsafe.html | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/highlighting.html | 10 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/rainbow_highlighting.html | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/ssr.rs | 74 | ||||
-rw-r--r-- | crates/ra_ide/src/status.rs | 15 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 122 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/html.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/injection.rs | 16 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/tags.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/tests.rs | 32 |
18 files changed, 277 insertions, 162 deletions
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index 9f4c582d0..560fb19e6 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs | |||
@@ -381,6 +381,7 @@ impl<'a> CompletionContext<'a> { | |||
381 | self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); | 381 | self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); |
382 | self.has_type_args = segment.type_arg_list().is_some(); | 382 | self.has_type_args = segment.type_arg_list().is_some(); |
383 | 383 | ||
384 | #[allow(deprecated)] | ||
384 | if let Some(path) = hir::Path::from_ast(path.clone()) { | 385 | if let Some(path) = hir::Path::from_ast(path.clone()) { |
385 | if let Some(path_prefix) = path.qualifier() { | 386 | if let Some(path_prefix) = path.qualifier() { |
386 | self.path_prefix = Some(path_prefix); | 387 | self.path_prefix = Some(path_prefix); |
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index e1bfd72f9..fd9abb55b 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs | |||
@@ -11,7 +11,7 @@ use hir::{ | |||
11 | Semantics, | 11 | Semantics, |
12 | }; | 12 | }; |
13 | use itertools::Itertools; | 13 | use itertools::Itertools; |
14 | use ra_db::{RelativePath, SourceDatabase, SourceDatabaseExt}; | 14 | use ra_db::SourceDatabase; |
15 | use ra_ide_db::RootDatabase; | 15 | use ra_ide_db::RootDatabase; |
16 | use ra_prof::profile; | 16 | use ra_prof::profile; |
17 | use ra_syntax::{ | 17 | use ra_syntax::{ |
@@ -57,14 +57,10 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> | |||
57 | }) | 57 | }) |
58 | .on::<hir::diagnostics::UnresolvedModule, _>(|d| { | 58 | .on::<hir::diagnostics::UnresolvedModule, _>(|d| { |
59 | let original_file = d.source().file_id.original_file(db); | 59 | let original_file = d.source().file_id.original_file(db); |
60 | let source_root = db.file_source_root(original_file); | 60 | let fix = Fix::new( |
61 | let path = db | 61 | "Create module", |
62 | .file_relative_path(original_file) | 62 | FileSystemEdit::CreateFile { anchor: original_file, dst: d.candidate.clone() }.into(), |
63 | .parent() | 63 | ); |
64 | .unwrap_or_else(|| RelativePath::new("")) | ||
65 | .join(&d.candidate); | ||
66 | let fix = | ||
67 | Fix::new("Create module", FileSystemEdit::CreateFile { source_root, path }.into()); | ||
68 | res.borrow_mut().push(Diagnostic { | 64 | res.borrow_mut().push(Diagnostic { |
69 | range: sema.diagnostics_range(d).range, | 65 | range: sema.diagnostics_range(d).range, |
70 | message: d.message(), | 66 | message: d.message(), |
@@ -612,10 +608,10 @@ mod tests { | |||
612 | source_file_edits: [], | 608 | source_file_edits: [], |
613 | file_system_edits: [ | 609 | file_system_edits: [ |
614 | CreateFile { | 610 | CreateFile { |
615 | source_root: SourceRootId( | 611 | anchor: FileId( |
616 | 0, | 612 | 1, |
617 | ), | 613 | ), |
618 | path: "foo.rs", | 614 | dst: "foo.rs", |
619 | }, | 615 | }, |
620 | ], | 616 | ], |
621 | is_snippet: false, | 617 | is_snippet: false, |
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 28f686767..51dc1f041 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -82,7 +82,7 @@ pub use ra_db::{ | |||
82 | Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRootId, | 82 | Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRootId, |
83 | }; | 83 | }; |
84 | pub use ra_ide_db::{ | 84 | pub use ra_ide_db::{ |
85 | change::{AnalysisChange, LibraryData}, | 85 | change::AnalysisChange, |
86 | line_index::{LineCol, LineIndex}, | 86 | line_index::{LineCol, LineIndex}, |
87 | search::SearchScope, | 87 | search::SearchScope, |
88 | source_change::{FileSystemEdit, SourceChange, SourceFileEdit}, | 88 | source_change::{FileSystemEdit, SourceChange, SourceFileEdit}, |
@@ -440,12 +440,14 @@ impl Analysis { | |||
440 | 440 | ||
441 | /// Computes syntax highlighting for the given file | 441 | /// Computes syntax highlighting for the given file |
442 | pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> { | 442 | pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> { |
443 | self.with_db(|db| syntax_highlighting::highlight(db, file_id, None)) | 443 | self.with_db(|db| syntax_highlighting::highlight(db, file_id, None, false)) |
444 | } | 444 | } |
445 | 445 | ||
446 | /// Computes syntax highlighting for the given file range. | 446 | /// Computes syntax highlighting for the given file range. |
447 | pub fn highlight_range(&self, frange: FileRange) -> Cancelable<Vec<HighlightedRange>> { | 447 | pub fn highlight_range(&self, frange: FileRange) -> Cancelable<Vec<HighlightedRange>> { |
448 | self.with_db(|db| syntax_highlighting::highlight(db, frange.file_id, Some(frange.range))) | 448 | self.with_db(|db| { |
449 | syntax_highlighting::highlight(db, frange.file_id, Some(frange.range), false) | ||
450 | }) | ||
449 | } | 451 | } |
450 | 452 | ||
451 | /// Computes syntax highlighting for the given file. | 453 | /// Computes syntax highlighting for the given file. |
diff --git a/crates/ra_ide/src/prime_caches.rs b/crates/ra_ide/src/prime_caches.rs index 90bf7d25f..c5ab5a1d8 100644 --- a/crates/ra_ide/src/prime_caches.rs +++ b/crates/ra_ide/src/prime_caches.rs | |||
@@ -7,6 +7,6 @@ use crate::{FileId, RootDatabase}; | |||
7 | 7 | ||
8 | pub(crate) fn prime_caches(db: &RootDatabase, files: Vec<FileId>) { | 8 | pub(crate) fn prime_caches(db: &RootDatabase, files: Vec<FileId>) { |
9 | for file in files { | 9 | for file in files { |
10 | let _ = crate::syntax_highlighting::highlight(db, file, None); | 10 | let _ = crate::syntax_highlighting::highlight(db, file, None, false); |
11 | } | 11 | } |
12 | } | 12 | } |
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index 915d4f4d3..c4f07f905 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::{ModuleSource, Semantics}; | 3 | use hir::{ModuleSource, Semantics}; |
4 | use ra_db::{RelativePath, RelativePathBuf, SourceDatabaseExt}; | 4 | use ra_db::{RelativePathBuf, SourceDatabaseExt}; |
5 | use ra_ide_db::RootDatabase; | 5 | use ra_ide_db::RootDatabase; |
6 | use ra_syntax::{ | 6 | use ra_syntax::{ |
7 | algo::find_node_at_offset, ast, ast::TypeAscriptionOwner, lex_single_valid_syntax_kind, | 7 | algo::find_node_at_offset, ast, ast::TypeAscriptionOwner, lex_single_valid_syntax_kind, |
@@ -92,23 +92,14 @@ fn rename_mod( | |||
92 | ModuleSource::SourceFile(..) => { | 92 | ModuleSource::SourceFile(..) => { |
93 | let mod_path: RelativePathBuf = sema.db.file_relative_path(file_id); | 93 | let mod_path: RelativePathBuf = sema.db.file_relative_path(file_id); |
94 | // mod is defined in path/to/dir/mod.rs | 94 | // mod is defined in path/to/dir/mod.rs |
95 | let dst_path = if mod_path.file_stem() == Some("mod") { | 95 | let dst = if mod_path.file_stem() == Some("mod") { |
96 | mod_path | 96 | format!("../{}/mod.rs", new_name) |
97 | .parent() | ||
98 | .and_then(|p| p.parent()) | ||
99 | .or_else(|| Some(RelativePath::new(""))) | ||
100 | .map(|p| p.join(new_name).join("mod.rs")) | ||
101 | } else { | 97 | } else { |
102 | Some(mod_path.with_file_name(new_name).with_extension("rs")) | 98 | format!("{}.rs", new_name) |
103 | }; | 99 | }; |
104 | if let Some(path) = dst_path { | 100 | let move_file = |
105 | let move_file = FileSystemEdit::MoveFile { | 101 | FileSystemEdit::MoveFile { src: file_id, anchor: position.file_id, dst }; |
106 | src: file_id, | 102 | file_system_edits.push(move_file); |
107 | dst_source_root: sema.db.file_source_root(position.file_id), | ||
108 | dst_path: path, | ||
109 | }; | ||
110 | file_system_edits.push(move_file); | ||
111 | } | ||
112 | } | 103 | } |
113 | ModuleSource::Module(..) => {} | 104 | ModuleSource::Module(..) => {} |
114 | } | 105 | } |
@@ -623,16 +614,16 @@ mod tests { | |||
623 | #[test] | 614 | #[test] |
624 | fn test_rename_mod() { | 615 | fn test_rename_mod() { |
625 | let (analysis, position) = analysis_and_position( | 616 | let (analysis, position) = analysis_and_position( |
626 | " | 617 | r#" |
627 | //- /lib.rs | 618 | //- /lib.rs |
628 | mod bar; | 619 | mod bar; |
629 | 620 | ||
630 | //- /bar.rs | 621 | //- /bar.rs |
631 | mod foo<|>; | 622 | mod foo<|>; |
632 | 623 | ||
633 | //- /bar/foo.rs | 624 | //- /bar/foo.rs |
634 | // emtpy | 625 | // emtpy |
635 | ", | 626 | "#, |
636 | ); | 627 | ); |
637 | let new_name = "foo2"; | 628 | let new_name = "foo2"; |
638 | let source_change = analysis.rename(position, new_name).unwrap(); | 629 | let source_change = analysis.rename(position, new_name).unwrap(); |
@@ -662,10 +653,10 @@ mod tests { | |||
662 | src: FileId( | 653 | src: FileId( |
663 | 3, | 654 | 3, |
664 | ), | 655 | ), |
665 | dst_source_root: SourceRootId( | 656 | anchor: FileId( |
666 | 0, | 657 | 2, |
667 | ), | 658 | ), |
668 | dst_path: "bar/foo2.rs", | 659 | dst: "foo2.rs", |
669 | }, | 660 | }, |
670 | ], | 661 | ], |
671 | is_snippet: false, | 662 | is_snippet: false, |
@@ -678,12 +669,12 @@ mod tests { | |||
678 | #[test] | 669 | #[test] |
679 | fn test_rename_mod_in_dir() { | 670 | fn test_rename_mod_in_dir() { |
680 | let (analysis, position) = analysis_and_position( | 671 | let (analysis, position) = analysis_and_position( |
681 | " | 672 | r#" |
682 | //- /lib.rs | 673 | //- /lib.rs |
683 | mod fo<|>o; | 674 | mod fo<|>o; |
684 | //- /foo/mod.rs | 675 | //- /foo/mod.rs |
685 | // emtpy | 676 | // emtpy |
686 | ", | 677 | "#, |
687 | ); | 678 | ); |
688 | let new_name = "foo2"; | 679 | let new_name = "foo2"; |
689 | let source_change = analysis.rename(position, new_name).unwrap(); | 680 | let source_change = analysis.rename(position, new_name).unwrap(); |
@@ -713,10 +704,10 @@ mod tests { | |||
713 | src: FileId( | 704 | src: FileId( |
714 | 2, | 705 | 2, |
715 | ), | 706 | ), |
716 | dst_source_root: SourceRootId( | 707 | anchor: FileId( |
717 | 0, | 708 | 1, |
718 | ), | 709 | ), |
719 | dst_path: "foo2/mod.rs", | 710 | dst: "../foo2/mod.rs", |
720 | }, | 711 | }, |
721 | ], | 712 | ], |
722 | is_snippet: false, | 713 | is_snippet: false, |
@@ -753,19 +744,19 @@ mod tests { | |||
753 | #[test] | 744 | #[test] |
754 | fn test_rename_mod_filename_and_path() { | 745 | fn test_rename_mod_filename_and_path() { |
755 | let (analysis, position) = analysis_and_position( | 746 | let (analysis, position) = analysis_and_position( |
756 | " | 747 | r#" |
757 | //- /lib.rs | 748 | //- /lib.rs |
758 | mod bar; | 749 | mod bar; |
759 | fn f() { | 750 | fn f() { |
760 | bar::foo::fun() | 751 | bar::foo::fun() |
761 | } | 752 | } |
762 | 753 | ||
763 | //- /bar.rs | 754 | //- /bar.rs |
764 | pub mod foo<|>; | 755 | pub mod foo<|>; |
765 | 756 | ||
766 | //- /bar/foo.rs | 757 | //- /bar/foo.rs |
767 | // pub fn fun() {} | 758 | // pub fn fun() {} |
768 | ", | 759 | "#, |
769 | ); | 760 | ); |
770 | let new_name = "foo2"; | 761 | let new_name = "foo2"; |
771 | let source_change = analysis.rename(position, new_name).unwrap(); | 762 | let source_change = analysis.rename(position, new_name).unwrap(); |
@@ -808,10 +799,10 @@ mod tests { | |||
808 | src: FileId( | 799 | src: FileId( |
809 | 3, | 800 | 3, |
810 | ), | 801 | ), |
811 | dst_source_root: SourceRootId( | 802 | anchor: FileId( |
812 | 0, | 803 | 2, |
813 | ), | 804 | ), |
814 | dst_path: "bar/foo2.rs", | 805 | dst: "foo2.rs", |
815 | }, | 806 | }, |
816 | ], | 807 | ], |
817 | is_snippet: false, | 808 | is_snippet: false, |
diff --git a/crates/ra_ide/src/snapshots/highlight_doctest.html b/crates/ra_ide/src/snapshots/highlight_doctest.html index 0ae8c7efc..f92a0aba5 100644 --- a/crates/ra_ide/src/snapshots/highlight_doctest.html +++ b/crates/ra_ide/src/snapshots/highlight_doctest.html | |||
@@ -25,22 +25,30 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
25 | .variable { color: #DCDCCC; } | 25 | .variable { color: #DCDCCC; } |
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | ||
29 | .escape_sequence { color: #94BFF3; } | ||
28 | 30 | ||
29 | .keyword { color: #F0DFAF; font-weight: bold; } | 31 | .keyword { color: #F0DFAF; font-weight: bold; } |
30 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 32 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
31 | .control { font-style: italic; } | 33 | .control { font-style: italic; } |
32 | </style> | 34 | </style> |
33 | <pre><code><span class="keyword">impl</span> <span class="unresolved_reference">Foo</span> { | 35 | <pre><code><span class="keyword">struct</span> <span class="struct declaration">Foo</span> { |
36 | <span class="field declaration">bar</span>: <span class="builtin_type">bool</span>, | ||
37 | } | ||
38 | |||
39 | <span class="keyword">impl</span> <span class="struct">Foo</span> { | ||
40 | <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>; | ||
41 | |||
34 | <span class="comment">/// Constructs a new `Foo`.</span> | 42 | <span class="comment">/// Constructs a new `Foo`.</span> |
35 | <span class="comment">///</span> | 43 | <span class="comment">///</span> |
36 | <span class="comment">/// # Examples</span> | 44 | <span class="comment">/// # Examples</span> |
37 | <span class="comment">///</span> | 45 | <span class="comment">///</span> |
38 | <span class="comment">/// ```</span> | 46 | <span class="comment">/// ```</span> |
39 | <span class="comment">/// #</span> <span class="attribute">#![</span><span class="function attribute">allow</span><span class="attribute">(unused_mut)]</span> | 47 | <span class="comment">/// #</span> <span class="attribute">#![</span><span class="function attribute">allow</span><span class="attribute">(unused_mut)]</span> |
40 | <span class="comment">/// </span><span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span>: <span class="unresolved_reference">Foo</span> = <span class="unresolved_reference">Foo</span>::<span class="unresolved_reference">new</span>(); | 48 | <span class="comment">/// </span><span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span>: <span class="struct">Foo</span> = <span class="struct">Foo</span>::<span class="function">new</span>(); |
41 | <span class="comment">/// ```</span> | 49 | <span class="comment">/// ```</span> |
42 | <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration">new</span>() -> <span class="unresolved_reference">Foo</span> { | 50 | <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration">new</span>() -> <span class="struct">Foo</span> { |
43 | <span class="unresolved_reference">Foo</span> { } | 51 | <span class="struct">Foo</span> { <span class="field">bar</span>: <span class="bool_literal">true</span> } |
44 | } | 52 | } |
45 | 53 | ||
46 | <span class="comment">/// `bar` method on `Foo`.</span> | 54 | <span class="comment">/// `bar` method on `Foo`.</span> |
@@ -48,11 +56,15 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
48 | <span class="comment">/// # Examples</span> | 56 | <span class="comment">/// # Examples</span> |
49 | <span class="comment">///</span> | 57 | <span class="comment">///</span> |
50 | <span class="comment">/// ```</span> | 58 | <span class="comment">/// ```</span> |
51 | <span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">foo</span> = <span class="unresolved_reference">Foo</span>::<span class="unresolved_reference">new</span>(); | 59 | <span class="comment">/// </span><span class="keyword">use</span> <span class="module">x</span>::<span class="module">y</span>; |
60 | <span class="comment">///</span> | ||
61 | <span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">foo</span> = <span class="struct">Foo</span>::<span class="function">new</span>(); | ||
52 | <span class="comment">///</span> | 62 | <span class="comment">///</span> |
53 | <span class="comment">/// </span><span class="comment">// calls bar on foo</span> | 63 | <span class="comment">/// </span><span class="comment">// calls bar on foo</span> |
54 | <span class="comment">/// </span><span class="macro">assert!</span>(foo.bar()); | 64 | <span class="comment">/// </span><span class="macro">assert!</span>(foo.bar()); |
55 | <span class="comment">///</span> | 65 | <span class="comment">///</span> |
66 | <span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">bar</span> = <span class="variable">foo</span>.<span class="field">bar</span> || <span class="struct">Foo</span>::<span class="constant">bar</span>; | ||
67 | <span class="comment">///</span> | ||
56 | <span class="comment">/// </span><span class="comment">/* multi-line | 68 | <span class="comment">/// </span><span class="comment">/* multi-line |
57 | </span><span class="comment">/// </span><span class="comment"> comment */</span> | 69 | </span><span class="comment">/// </span><span class="comment"> comment */</span> |
58 | <span class="comment">///</span> | 70 | <span class="comment">///</span> |
@@ -62,8 +74,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
62 | <span class="comment">///</span> | 74 | <span class="comment">///</span> |
63 | <span class="comment">/// ```</span> | 75 | <span class="comment">/// ```</span> |
64 | <span class="comment">///</span> | 76 | <span class="comment">///</span> |
77 | <span class="comment">/// ```rust,no_run</span> | ||
78 | <span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">foobar</span> = <span class="struct">Foo</span>::<span class="function">new</span>().<span class="function">bar</span>(); | ||
65 | <span class="comment">/// ```</span> | 79 | <span class="comment">/// ```</span> |
66 | <span class="comment">/// </span><span class="keyword">let</span> <span class="variable declaration">foobar</span> = <span class="unresolved_reference">Foo</span>::<span class="unresolved_reference">new</span>().<span class="unresolved_reference">bar</span>(); | 80 | <span class="comment">///</span> |
81 | <span class="comment">/// ```sh</span> | ||
82 | <span class="comment">/// echo 1</span> | ||
67 | <span class="comment">/// ```</span> | 83 | <span class="comment">/// ```</span> |
68 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">foo</span>(&<span class="self_keyword">self</span>) -> <span class="builtin_type">bool</span> { | 84 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">foo</span>(&<span class="self_keyword">self</span>) -> <span class="builtin_type">bool</span> { |
69 | <span class="bool_literal">true</span> | 85 | <span class="bool_literal">true</span> |
diff --git a/crates/ra_ide/src/snapshots/highlight_injection.html b/crates/ra_ide/src/snapshots/highlight_injection.html index dec06eb51..47dbd7bc8 100644 --- a/crates/ra_ide/src/snapshots/highlight_injection.html +++ b/crates/ra_ide/src/snapshots/highlight_injection.html | |||
@@ -25,6 +25,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
25 | .variable { color: #DCDCCC; } | 25 | .variable { color: #DCDCCC; } |
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | ||
29 | .escape_sequence { color: #94BFF3; } | ||
28 | 30 | ||
29 | .keyword { color: #F0DFAF; font-weight: bold; } | 31 | .keyword { color: #F0DFAF; font-weight: bold; } |
30 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 32 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
diff --git a/crates/ra_ide/src/snapshots/highlight_strings.html b/crates/ra_ide/src/snapshots/highlight_strings.html index 849eb3b73..b46fa44c6 100644 --- a/crates/ra_ide/src/snapshots/highlight_strings.html +++ b/crates/ra_ide/src/snapshots/highlight_strings.html | |||
@@ -25,6 +25,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
25 | .variable { color: #DCDCCC; } | 25 | .variable { color: #DCDCCC; } |
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | ||
29 | .escape_sequence { color: #94BFF3; } | ||
28 | 30 | ||
29 | .keyword { color: #F0DFAF; font-weight: bold; } | 31 | .keyword { color: #F0DFAF; font-weight: bold; } |
30 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 32 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
@@ -82,6 +84,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
82 | 84 | ||
83 | <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>); | 85 | <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>); |
84 | 86 | ||
85 | <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">\x41</span><span class="format_specifier">}</span><span class="string_literal">"</span>, A = <span class="numeric_literal">92</span>); | 87 | <span class="comment">// escape sequences</span> |
88 | <span class="macro">println!</span>(<span class="string_literal">"Hello</span><span class="escape_sequence">\n</span><span class="string_literal">World"</span>); | ||
89 | <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>); | ||
90 | |||
91 | <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>); | ||
86 | <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>); | 92 | <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>); |
87 | }</code></pre> \ No newline at end of file | 93 | }</code></pre> \ No newline at end of file |
diff --git a/crates/ra_ide/src/snapshots/highlight_unsafe.html b/crates/ra_ide/src/snapshots/highlight_unsafe.html index bd24e6e38..73438fbb4 100644 --- a/crates/ra_ide/src/snapshots/highlight_unsafe.html +++ b/crates/ra_ide/src/snapshots/highlight_unsafe.html | |||
@@ -25,6 +25,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
25 | .variable { color: #DCDCCC; } | 25 | .variable { color: #DCDCCC; } |
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | ||
29 | .escape_sequence { color: #94BFF3; } | ||
28 | 30 | ||
29 | .keyword { color: #F0DFAF; font-weight: bold; } | 31 | .keyword { color: #F0DFAF; font-weight: bold; } |
30 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 32 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html index 33548d43c..0c4f0a018 100644 --- a/crates/ra_ide/src/snapshots/highlighting.html +++ b/crates/ra_ide/src/snapshots/highlighting.html | |||
@@ -25,6 +25,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
25 | .variable { color: #DCDCCC; } | 25 | .variable { color: #DCDCCC; } |
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | ||
29 | .escape_sequence { color: #94BFF3; } | ||
28 | 30 | ||
29 | .keyword { color: #F0DFAF; font-weight: bold; } | 31 | .keyword { color: #F0DFAF; font-weight: bold; } |
30 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 32 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
@@ -62,6 +64,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
62 | } | 64 | } |
63 | } | 65 | } |
64 | 66 | ||
67 | <span class="macro">macro_rules!</span> <span class="macro declaration">noop</span> { | ||
68 | ($expr:expr) => { | ||
69 | $expr | ||
70 | } | ||
71 | } | ||
72 | |||
65 | <span class="comment">// comment</span> | 73 | <span class="comment">// comment</span> |
66 | <span class="keyword">fn</span> <span class="function declaration">main</span>() { | 74 | <span class="keyword">fn</span> <span class="function declaration">main</span>() { |
67 | <span class="macro">println!</span>(<span class="string_literal">"Hello, {}!"</span>, <span class="numeric_literal">92</span>); | 75 | <span class="macro">println!</span>(<span class="string_literal">"Hello, {}!"</span>, <span class="numeric_literal">92</span>); |
@@ -80,6 +88,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
80 | <span class="comment">// Do nothing</span> | 88 | <span class="comment">// Do nothing</span> |
81 | } | 89 | } |
82 | 90 | ||
91 | <span class="macro">noop!</span>(<span class="macro">noop</span><span class="macro">!</span>(<span class="numeric_literal">1</span>)); | ||
92 | |||
83 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> = <span class="numeric_literal">42</span>; | 93 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> = <span class="numeric_literal">42</span>; |
84 | <span class="keyword">let</span> <span class="variable declaration mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>; | 94 | <span class="keyword">let</span> <span class="variable declaration mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>; |
85 | <span class="keyword">let</span> <span class="variable declaration">z</span> = &<span class="variable mutable">y</span>; | 95 | <span class="keyword">let</span> <span class="variable declaration">z</span> = &<span class="variable mutable">y</span>; |
diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html index 1ab06182c..a74a70069 100644 --- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html +++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html | |||
@@ -25,6 +25,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
25 | .variable { color: #DCDCCC; } | 25 | .variable { color: #DCDCCC; } |
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | ||
29 | .escape_sequence { color: #94BFF3; } | ||
28 | 30 | ||
29 | .keyword { color: #F0DFAF; font-weight: bold; } | 31 | .keyword { color: #F0DFAF; font-weight: bold; } |
30 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 32 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
diff --git a/crates/ra_ide/src/ssr.rs b/crates/ra_ide/src/ssr.rs index 93e9aee1d..762aab962 100644 --- a/crates/ra_ide/src/ssr.rs +++ b/crates/ra_ide/src/ssr.rs | |||
@@ -27,11 +27,11 @@ impl std::error::Error for SsrError {} | |||
27 | // | 27 | // |
28 | // Search and replace with named wildcards that will match any expression. | 28 | // Search and replace with named wildcards that will match any expression. |
29 | // The syntax for a structural search replace command is `<search_pattern> ==>> <replace_pattern>`. | 29 | // The syntax for a structural search replace command is `<search_pattern> ==>> <replace_pattern>`. |
30 | // A `$<name>:expr` placeholder in the search pattern will match any expression and `$<name>` will reference it in the replacement. | 30 | // A `$<name>` placeholder in the search pattern will match any AST node and `$<name>` will reference it in the replacement. |
31 | // Available via the command `rust-analyzer.ssr`. | 31 | // Available via the command `rust-analyzer.ssr`. |
32 | // | 32 | // |
33 | // ```rust | 33 | // ```rust |
34 | // // Using structural search replace command [foo($a:expr, $b:expr) ==>> ($a).foo($b)] | 34 | // // Using structural search replace command [foo($a, $b) ==>> ($a).foo($b)] |
35 | // | 35 | // |
36 | // // BEFORE | 36 | // // BEFORE |
37 | // String::from(foo(y + 5, z)) | 37 | // String::from(foo(y + 5, z)) |
@@ -79,7 +79,7 @@ struct SsrPattern { | |||
79 | vars: Vec<Var>, | 79 | vars: Vec<Var>, |
80 | } | 80 | } |
81 | 81 | ||
82 | /// represents an `$var` in an SSR query | 82 | /// Represents a `$var` in an SSR query. |
83 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 83 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
84 | struct Var(String); | 84 | struct Var(String); |
85 | 85 | ||
@@ -122,8 +122,7 @@ impl FromStr for SsrQuery { | |||
122 | let mut pattern = it.next().expect("something").to_string(); | 122 | let mut pattern = it.next().expect("something").to_string(); |
123 | 123 | ||
124 | for part in it.map(split_by_var) { | 124 | for part in it.map(split_by_var) { |
125 | let (var, var_type, remainder) = part?; | 125 | let (var, remainder) = part?; |
126 | is_expr(var_type)?; | ||
127 | let new_var = create_name(var, &mut vars)?; | 126 | let new_var = create_name(var, &mut vars)?; |
128 | pattern.push_str(new_var); | 127 | pattern.push_str(new_var); |
129 | pattern.push_str(remainder); | 128 | pattern.push_str(remainder); |
@@ -166,15 +165,11 @@ fn traverse(node: &SyntaxNode, go: &mut impl FnMut(&SyntaxNode) -> bool) { | |||
166 | } | 165 | } |
167 | } | 166 | } |
168 | 167 | ||
169 | fn split_by_var(s: &str) -> Result<(&str, &str, &str), SsrError> { | 168 | fn split_by_var(s: &str) -> Result<(&str, &str), SsrError> { |
170 | let end_of_name = s.find(':').ok_or_else(|| SsrError("Use $<name>:expr".into()))?; | 169 | let end_of_name = s.find(|c| !char::is_ascii_alphanumeric(&c)).unwrap_or_else(|| s.len()); |
171 | let name = &s[0..end_of_name]; | 170 | let name = &s[..end_of_name]; |
172 | is_name(name)?; | 171 | is_name(name)?; |
173 | let type_begin = end_of_name + 1; | 172 | Ok((name, &s[end_of_name..])) |
174 | let type_length = | ||
175 | s[type_begin..].find(|c| !char::is_ascii_alphanumeric(&c)).unwrap_or_else(|| s.len()); | ||
176 | let type_name = &s[type_begin..type_begin + type_length]; | ||
177 | Ok((name, type_name, &s[type_begin + type_length..])) | ||
178 | } | 173 | } |
179 | 174 | ||
180 | fn is_name(s: &str) -> Result<(), SsrError> { | 175 | fn is_name(s: &str) -> Result<(), SsrError> { |
@@ -185,14 +180,6 @@ fn is_name(s: &str) -> Result<(), SsrError> { | |||
185 | } | 180 | } |
186 | } | 181 | } |
187 | 182 | ||
188 | fn is_expr(s: &str) -> Result<(), SsrError> { | ||
189 | if s == "expr" { | ||
190 | Ok(()) | ||
191 | } else { | ||
192 | Err(SsrError("Only $<name>:expr is supported".into())) | ||
193 | } | ||
194 | } | ||
195 | |||
196 | fn replace_in_template(template: String, var: &str, new_var: &str) -> String { | 183 | fn replace_in_template(template: String, var: &str, new_var: &str) -> String { |
197 | let name = format!("${}", var); | 184 | let name = format!("${}", var); |
198 | template.replace(&name, new_var) | 185 | template.replace(&name, new_var) |
@@ -450,7 +437,7 @@ mod tests { | |||
450 | 437 | ||
451 | #[test] | 438 | #[test] |
452 | fn parser_happy_case() { | 439 | fn parser_happy_case() { |
453 | let result: SsrQuery = "foo($a:expr, $b:expr) ==>> bar($b, $a)".parse().unwrap(); | 440 | let result: SsrQuery = "foo($a, $b) ==>> bar($b, $a)".parse().unwrap(); |
454 | assert_eq!(&result.pattern.pattern.text(), "foo(__search_pattern_a, __search_pattern_b)"); | 441 | assert_eq!(&result.pattern.pattern.text(), "foo(__search_pattern_a, __search_pattern_b)"); |
455 | assert_eq!(result.pattern.vars.len(), 2); | 442 | assert_eq!(result.pattern.vars.len(), 2); |
456 | assert_eq!(result.pattern.vars[0].0, "__search_pattern_a"); | 443 | assert_eq!(result.pattern.vars[0].0, "__search_pattern_a"); |
@@ -477,30 +464,9 @@ mod tests { | |||
477 | } | 464 | } |
478 | 465 | ||
479 | #[test] | 466 | #[test] |
480 | fn parser_no_pattern_type() { | ||
481 | assert_eq!(parse_error_text("foo($a) ==>>"), "Parse error: Use $<name>:expr"); | ||
482 | } | ||
483 | |||
484 | #[test] | ||
485 | fn parser_invalid_name() { | ||
486 | assert_eq!( | ||
487 | parse_error_text("foo($a+:expr) ==>>"), | ||
488 | "Parse error: Name can contain only alphanumerics and _" | ||
489 | ); | ||
490 | } | ||
491 | |||
492 | #[test] | ||
493 | fn parser_invalid_type() { | ||
494 | assert_eq!( | ||
495 | parse_error_text("foo($a:ident) ==>>"), | ||
496 | "Parse error: Only $<name>:expr is supported" | ||
497 | ); | ||
498 | } | ||
499 | |||
500 | #[test] | ||
501 | fn parser_repeated_name() { | 467 | fn parser_repeated_name() { |
502 | assert_eq!( | 468 | assert_eq!( |
503 | parse_error_text("foo($a:expr, $a:expr) ==>>"), | 469 | parse_error_text("foo($a, $a) ==>>"), |
504 | "Parse error: Name `a` repeats more than once" | 470 | "Parse error: Name `a` repeats more than once" |
505 | ); | 471 | ); |
506 | } | 472 | } |
@@ -517,7 +483,7 @@ mod tests { | |||
517 | 483 | ||
518 | #[test] | 484 | #[test] |
519 | fn parse_match_replace() { | 485 | fn parse_match_replace() { |
520 | let query: SsrQuery = "foo($x:expr) ==>> bar($x)".parse().unwrap(); | 486 | let query: SsrQuery = "foo($x) ==>> bar($x)".parse().unwrap(); |
521 | let input = "fn main() { foo(1+2); }"; | 487 | let input = "fn main() { foo(1+2); }"; |
522 | 488 | ||
523 | let code = SourceFile::parse(input).tree(); | 489 | let code = SourceFile::parse(input).tree(); |
@@ -549,7 +515,7 @@ mod tests { | |||
549 | #[test] | 515 | #[test] |
550 | fn ssr_function_to_method() { | 516 | fn ssr_function_to_method() { |
551 | assert_ssr_transform( | 517 | assert_ssr_transform( |
552 | "my_function($a:expr, $b:expr) ==>> ($a).my_method($b)", | 518 | "my_function($a, $b) ==>> ($a).my_method($b)", |
553 | "loop { my_function( other_func(x, y), z + w) }", | 519 | "loop { my_function( other_func(x, y), z + w) }", |
554 | "loop { (other_func(x, y)).my_method(z + w) }", | 520 | "loop { (other_func(x, y)).my_method(z + w) }", |
555 | ) | 521 | ) |
@@ -558,7 +524,7 @@ mod tests { | |||
558 | #[test] | 524 | #[test] |
559 | fn ssr_nested_function() { | 525 | fn ssr_nested_function() { |
560 | assert_ssr_transform( | 526 | assert_ssr_transform( |
561 | "foo($a:expr, $b:expr, $c:expr) ==>> bar($c, baz($a, $b))", | 527 | "foo($a, $b, $c) ==>> bar($c, baz($a, $b))", |
562 | "fn main { foo (x + value.method(b), x+y-z, true && false) }", | 528 | "fn main { foo (x + value.method(b), x+y-z, true && false) }", |
563 | "fn main { bar(true && false, baz(x + value.method(b), x+y-z)) }", | 529 | "fn main { bar(true && false, baz(x + value.method(b), x+y-z)) }", |
564 | ) | 530 | ) |
@@ -567,7 +533,7 @@ mod tests { | |||
567 | #[test] | 533 | #[test] |
568 | fn ssr_expected_spacing() { | 534 | fn ssr_expected_spacing() { |
569 | assert_ssr_transform( | 535 | assert_ssr_transform( |
570 | "foo($x:expr) + bar() ==>> bar($x)", | 536 | "foo($x) + bar() ==>> bar($x)", |
571 | "fn main() { foo(5) + bar() }", | 537 | "fn main() { foo(5) + bar() }", |
572 | "fn main() { bar(5) }", | 538 | "fn main() { bar(5) }", |
573 | ); | 539 | ); |
@@ -576,7 +542,7 @@ mod tests { | |||
576 | #[test] | 542 | #[test] |
577 | fn ssr_with_extra_space() { | 543 | fn ssr_with_extra_space() { |
578 | assert_ssr_transform( | 544 | assert_ssr_transform( |
579 | "foo($x:expr ) + bar() ==>> bar($x)", | 545 | "foo($x ) + bar() ==>> bar($x)", |
580 | "fn main() { foo( 5 ) +bar( ) }", | 546 | "fn main() { foo( 5 ) +bar( ) }", |
581 | "fn main() { bar(5) }", | 547 | "fn main() { bar(5) }", |
582 | ); | 548 | ); |
@@ -585,7 +551,7 @@ mod tests { | |||
585 | #[test] | 551 | #[test] |
586 | fn ssr_keeps_nested_comment() { | 552 | fn ssr_keeps_nested_comment() { |
587 | assert_ssr_transform( | 553 | assert_ssr_transform( |
588 | "foo($x:expr) ==>> bar($x)", | 554 | "foo($x) ==>> bar($x)", |
589 | "fn main() { foo(other(5 /* using 5 */)) }", | 555 | "fn main() { foo(other(5 /* using 5 */)) }", |
590 | "fn main() { bar(other(5 /* using 5 */)) }", | 556 | "fn main() { bar(other(5 /* using 5 */)) }", |
591 | ) | 557 | ) |
@@ -594,7 +560,7 @@ mod tests { | |||
594 | #[test] | 560 | #[test] |
595 | fn ssr_keeps_comment() { | 561 | fn ssr_keeps_comment() { |
596 | assert_ssr_transform( | 562 | assert_ssr_transform( |
597 | "foo($x:expr) ==>> bar($x)", | 563 | "foo($x) ==>> bar($x)", |
598 | "fn main() { foo(5 /* using 5 */) }", | 564 | "fn main() { foo(5 /* using 5 */) }", |
599 | "fn main() { bar(5)/* using 5 */ }", | 565 | "fn main() { bar(5)/* using 5 */ }", |
600 | ) | 566 | ) |
@@ -603,7 +569,7 @@ mod tests { | |||
603 | #[test] | 569 | #[test] |
604 | fn ssr_struct_lit() { | 570 | fn ssr_struct_lit() { |
605 | assert_ssr_transform( | 571 | assert_ssr_transform( |
606 | "foo{a: $a:expr, b: $b:expr} ==>> foo::new($a, $b)", | 572 | "foo{a: $a, b: $b} ==>> foo::new($a, $b)", |
607 | "fn main() { foo{b:2, a:1} }", | 573 | "fn main() { foo{b:2, a:1} }", |
608 | "fn main() { foo::new(1, 2) }", | 574 | "fn main() { foo::new(1, 2) }", |
609 | ) | 575 | ) |
@@ -612,7 +578,7 @@ mod tests { | |||
612 | #[test] | 578 | #[test] |
613 | fn ssr_call_and_method_call() { | 579 | fn ssr_call_and_method_call() { |
614 | assert_ssr_transform( | 580 | assert_ssr_transform( |
615 | "foo::<'a>($a:expr, $b:expr)) ==>> foo2($a, $b)", | 581 | "foo::<'a>($a, $b)) ==>> foo2($a, $b)", |
616 | "fn main() { get().bar.foo::<'a>(1); }", | 582 | "fn main() { get().bar.foo::<'a>(1); }", |
617 | "fn main() { foo2(get().bar, 1); }", | 583 | "fn main() { foo2(get().bar, 1); }", |
618 | ) | 584 | ) |
@@ -621,7 +587,7 @@ mod tests { | |||
621 | #[test] | 587 | #[test] |
622 | fn ssr_method_call_and_call() { | 588 | fn ssr_method_call_and_call() { |
623 | assert_ssr_transform( | 589 | assert_ssr_transform( |
624 | "$o:expr.foo::<i32>($a:expr)) ==>> $o.foo2($a)", | 590 | "$o.foo::<i32>($a)) ==>> $o.foo2($a)", |
625 | "fn main() { X::foo::<i32>(x, 1); }", | 591 | "fn main() { X::foo::<i32>(x, 1); }", |
626 | "fn main() { x.foo2(1); }", | 592 | "fn main() { x.foo2(1); }", |
627 | ) | 593 | ) |
diff --git a/crates/ra_ide/src/status.rs b/crates/ra_ide/src/status.rs index 5b7992920..45411b357 100644 --- a/crates/ra_ide/src/status.rs +++ b/crates/ra_ide/src/status.rs | |||
@@ -16,6 +16,7 @@ use ra_prof::{memory_usage, Bytes}; | |||
16 | use ra_syntax::{ast, Parse, SyntaxNode}; | 16 | use ra_syntax::{ast, Parse, SyntaxNode}; |
17 | 17 | ||
18 | use crate::FileId; | 18 | use crate::FileId; |
19 | use rustc_hash::FxHashMap; | ||
19 | 20 | ||
20 | fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats { | 21 | fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats { |
21 | db.query(ra_db::ParseQuery).entries::<SyntaxTreeStats>() | 22 | db.query(ra_db::ParseQuery).entries::<SyntaxTreeStats>() |
@@ -123,20 +124,24 @@ struct LibrarySymbolsStats { | |||
123 | 124 | ||
124 | impl fmt::Display for LibrarySymbolsStats { | 125 | impl fmt::Display for LibrarySymbolsStats { |
125 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | 126 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
126 | write!(fmt, "{} ({}) symbols", self.total, self.size,) | 127 | write!(fmt, "{} ({}) symbols", self.total, self.size) |
127 | } | 128 | } |
128 | } | 129 | } |
129 | 130 | ||
130 | impl FromIterator<TableEntry<SourceRootId, Arc<SymbolIndex>>> for LibrarySymbolsStats { | 131 | impl FromIterator<TableEntry<(), Arc<FxHashMap<SourceRootId, SymbolIndex>>>> |
132 | for LibrarySymbolsStats | ||
133 | { | ||
131 | fn from_iter<T>(iter: T) -> LibrarySymbolsStats | 134 | fn from_iter<T>(iter: T) -> LibrarySymbolsStats |
132 | where | 135 | where |
133 | T: IntoIterator<Item = TableEntry<SourceRootId, Arc<SymbolIndex>>>, | 136 | T: IntoIterator<Item = TableEntry<(), Arc<FxHashMap<SourceRootId, SymbolIndex>>>>, |
134 | { | 137 | { |
135 | let mut res = LibrarySymbolsStats::default(); | 138 | let mut res = LibrarySymbolsStats::default(); |
136 | for entry in iter { | 139 | for entry in iter { |
137 | let value = entry.value.unwrap(); | 140 | let value = entry.value.unwrap(); |
138 | res.total += value.len(); | 141 | for symbols in value.values() { |
139 | res.size += value.memory_size(); | 142 | res.total += symbols.len(); |
143 | res.size += symbols.memory_size(); | ||
144 | } | ||
140 | } | 145 | } |
141 | res | 146 | res |
142 | } | 147 | } |
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index ab45c364a..854b6cc6d 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -44,6 +44,7 @@ pub(crate) fn highlight( | |||
44 | db: &RootDatabase, | 44 | db: &RootDatabase, |
45 | file_id: FileId, | 45 | file_id: FileId, |
46 | range_to_highlight: Option<TextRange>, | 46 | range_to_highlight: Option<TextRange>, |
47 | syntactic_name_ref_highlighting: bool, | ||
47 | ) -> Vec<HighlightedRange> { | 48 | ) -> Vec<HighlightedRange> { |
48 | let _p = profile("highlight"); | 49 | let _p = profile("highlight"); |
49 | let sema = Semantics::new(db); | 50 | let sema = Semantics::new(db); |
@@ -104,6 +105,7 @@ pub(crate) fn highlight( | |||
104 | if let Some((highlight, binding_hash)) = highlight_element( | 105 | if let Some((highlight, binding_hash)) = highlight_element( |
105 | &sema, | 106 | &sema, |
106 | &mut bindings_shadow_count, | 107 | &mut bindings_shadow_count, |
108 | syntactic_name_ref_highlighting, | ||
107 | name.syntax().clone().into(), | 109 | name.syntax().clone().into(), |
108 | ) { | 110 | ) { |
109 | stack.add(HighlightedRange { | 111 | stack.add(HighlightedRange { |
@@ -160,23 +162,25 @@ pub(crate) fn highlight( | |||
160 | // Check if macro takes a format string and remember it for highlighting later. | 162 | // Check if macro takes a format string and remember it for highlighting later. |
161 | // The macros that accept a format string expand to a compiler builtin macros | 163 | // The macros that accept a format string expand to a compiler builtin macros |
162 | // `format_args` and `format_args_nl`. | 164 | // `format_args` and `format_args_nl`. |
163 | if let Some(fmt_macro_call) = parent.parent().and_then(ast::MacroCall::cast) { | 165 | if let Some(name) = parent |
164 | if let Some(name) = | 166 | .parent() |
165 | fmt_macro_call.path().and_then(|p| p.segment()).and_then(|s| s.name_ref()) | 167 | .and_then(ast::MacroCall::cast) |
166 | { | 168 | .and_then(|mc| mc.path()) |
167 | match name.text().as_str() { | 169 | .and_then(|p| p.segment()) |
168 | "format_args" | "format_args_nl" => { | 170 | .and_then(|s| s.name_ref()) |
169 | format_string = parent | 171 | { |
170 | .children_with_tokens() | 172 | match name.text().as_str() { |
171 | .filter(|t| t.kind() != WHITESPACE) | 173 | "format_args" | "format_args_nl" => { |
172 | .nth(1) | 174 | format_string = parent |
173 | .filter(|e| { | 175 | .children_with_tokens() |
174 | ast::String::can_cast(e.kind()) | 176 | .filter(|t| t.kind() != WHITESPACE) |
175 | || ast::RawString::can_cast(e.kind()) | 177 | .nth(1) |
176 | }) | 178 | .filter(|e| { |
177 | } | 179 | ast::String::can_cast(e.kind()) |
178 | _ => {} | 180 | || ast::RawString::can_cast(e.kind()) |
181 | }) | ||
179 | } | 182 | } |
183 | _ => {} | ||
180 | } | 184 | } |
181 | } | 185 | } |
182 | 186 | ||
@@ -198,15 +202,18 @@ pub(crate) fn highlight( | |||
198 | 202 | ||
199 | let is_format_string = format_string.as_ref() == Some(&element_to_highlight); | 203 | let is_format_string = format_string.as_ref() == Some(&element_to_highlight); |
200 | 204 | ||
201 | if let Some((highlight, binding_hash)) = | 205 | if let Some((highlight, binding_hash)) = highlight_element( |
202 | highlight_element(&sema, &mut bindings_shadow_count, element_to_highlight.clone()) | 206 | &sema, |
203 | { | 207 | &mut bindings_shadow_count, |
208 | syntactic_name_ref_highlighting, | ||
209 | element_to_highlight.clone(), | ||
210 | ) { | ||
204 | stack.add(HighlightedRange { range, highlight, binding_hash }); | 211 | stack.add(HighlightedRange { range, highlight, binding_hash }); |
205 | if let Some(string) = | 212 | if let Some(string) = |
206 | element_to_highlight.as_token().cloned().and_then(ast::String::cast) | 213 | element_to_highlight.as_token().cloned().and_then(ast::String::cast) |
207 | { | 214 | { |
208 | stack.push(); | ||
209 | if is_format_string { | 215 | if is_format_string { |
216 | stack.push(); | ||
210 | string.lex_format_specifier(|piece_range, kind| { | 217 | string.lex_format_specifier(|piece_range, kind| { |
211 | if let Some(highlight) = highlight_format_specifier(kind) { | 218 | if let Some(highlight) = highlight_format_specifier(kind) { |
212 | stack.add(HighlightedRange { | 219 | stack.add(HighlightedRange { |
@@ -216,13 +223,27 @@ pub(crate) fn highlight( | |||
216 | }); | 223 | }); |
217 | } | 224 | } |
218 | }); | 225 | }); |
226 | stack.pop(); | ||
227 | } | ||
228 | // Highlight escape sequences | ||
229 | if let Some(char_ranges) = string.char_ranges() { | ||
230 | stack.push(); | ||
231 | for (piece_range, _) in char_ranges.iter().filter(|(_, char)| char.is_ok()) { | ||
232 | if string.text()[piece_range.start().into()..].starts_with('\\') { | ||
233 | stack.add(HighlightedRange { | ||
234 | range: piece_range + range.start(), | ||
235 | highlight: HighlightTag::EscapeSequence.into(), | ||
236 | binding_hash: None, | ||
237 | }); | ||
238 | } | ||
239 | } | ||
240 | stack.pop_and_inject(false); | ||
219 | } | 241 | } |
220 | stack.pop(); | ||
221 | } else if let Some(string) = | 242 | } else if let Some(string) = |
222 | element_to_highlight.as_token().cloned().and_then(ast::RawString::cast) | 243 | element_to_highlight.as_token().cloned().and_then(ast::RawString::cast) |
223 | { | 244 | { |
224 | stack.push(); | ||
225 | if is_format_string { | 245 | if is_format_string { |
246 | stack.push(); | ||
226 | string.lex_format_specifier(|piece_range, kind| { | 247 | string.lex_format_specifier(|piece_range, kind| { |
227 | if let Some(highlight) = highlight_format_specifier(kind) { | 248 | if let Some(highlight) = highlight_format_specifier(kind) { |
228 | stack.add(HighlightedRange { | 249 | stack.add(HighlightedRange { |
@@ -232,8 +253,8 @@ pub(crate) fn highlight( | |||
232 | }); | 253 | }); |
233 | } | 254 | } |
234 | }); | 255 | }); |
256 | stack.pop(); | ||
235 | } | 257 | } |
236 | stack.pop(); | ||
237 | } | 258 | } |
238 | } | 259 | } |
239 | } | 260 | } |
@@ -408,6 +429,7 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> { | |||
408 | fn highlight_element( | 429 | fn highlight_element( |
409 | sema: &Semantics<RootDatabase>, | 430 | sema: &Semantics<RootDatabase>, |
410 | bindings_shadow_count: &mut FxHashMap<Name, u32>, | 431 | bindings_shadow_count: &mut FxHashMap<Name, u32>, |
432 | syntactic_name_ref_highlighting: bool, | ||
411 | element: SyntaxElement, | 433 | element: SyntaxElement, |
412 | ) -> Option<(Highlight, Option<u64>)> { | 434 | ) -> Option<(Highlight, Option<u64>)> { |
413 | let db = sema.db; | 435 | let db = sema.db; |
@@ -461,6 +483,7 @@ fn highlight_element( | |||
461 | } | 483 | } |
462 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), | 484 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), |
463 | }, | 485 | }, |
486 | None if syntactic_name_ref_highlighting => highlight_name_ref_by_syntax(name_ref), | ||
464 | None => HighlightTag::UnresolvedReference.into(), | 487 | None => HighlightTag::UnresolvedReference.into(), |
465 | } | 488 | } |
466 | } | 489 | } |
@@ -493,6 +516,9 @@ fn highlight_element( | |||
493 | h |= HighlightModifier::Unsafe; | 516 | h |= HighlightModifier::Unsafe; |
494 | h | 517 | h |
495 | } | 518 | } |
519 | T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { | ||
520 | Highlight::new(HighlightTag::Macro) | ||
521 | } | ||
496 | 522 | ||
497 | k if k.is_keyword() => { | 523 | k if k.is_keyword() => { |
498 | let h = Highlight::new(HighlightTag::Keyword); | 524 | let h = Highlight::new(HighlightTag::Keyword); |
@@ -609,3 +635,53 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight { | |||
609 | 635 | ||
610 | tag.into() | 636 | tag.into() |
611 | } | 637 | } |
638 | |||
639 | fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight { | ||
640 | let default = HighlightTag::UnresolvedReference; | ||
641 | |||
642 | let parent = match name.syntax().parent() { | ||
643 | Some(it) => it, | ||
644 | _ => return default.into(), | ||
645 | }; | ||
646 | |||
647 | let tag = match parent.kind() { | ||
648 | METHOD_CALL_EXPR => HighlightTag::Function, | ||
649 | FIELD_EXPR => HighlightTag::Field, | ||
650 | PATH_SEGMENT => { | ||
651 | let path = match parent.parent().and_then(ast::Path::cast) { | ||
652 | Some(it) => it, | ||
653 | _ => return default.into(), | ||
654 | }; | ||
655 | let expr = match path.syntax().parent().and_then(ast::PathExpr::cast) { | ||
656 | Some(it) => it, | ||
657 | _ => { | ||
658 | // within path, decide whether it is module or adt by checking for uppercase name | ||
659 | return if name.text().chars().next().unwrap_or_default().is_uppercase() { | ||
660 | HighlightTag::Struct | ||
661 | } else { | ||
662 | HighlightTag::Module | ||
663 | } | ||
664 | .into(); | ||
665 | } | ||
666 | }; | ||
667 | let parent = match expr.syntax().parent() { | ||
668 | Some(it) => it, | ||
669 | None => return default.into(), | ||
670 | }; | ||
671 | |||
672 | match parent.kind() { | ||
673 | CALL_EXPR => HighlightTag::Function, | ||
674 | _ => { | ||
675 | if name.text().chars().next().unwrap_or_default().is_uppercase() { | ||
676 | HighlightTag::Struct | ||
677 | } else { | ||
678 | HighlightTag::Constant | ||
679 | } | ||
680 | } | ||
681 | } | ||
682 | } | ||
683 | _ => default, | ||
684 | }; | ||
685 | |||
686 | tag.into() | ||
687 | } | ||
diff --git a/crates/ra_ide/src/syntax_highlighting/html.rs b/crates/ra_ide/src/syntax_highlighting/html.rs index 5bada6252..99b6b25ab 100644 --- a/crates/ra_ide/src/syntax_highlighting/html.rs +++ b/crates/ra_ide/src/syntax_highlighting/html.rs | |||
@@ -19,7 +19,7 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo | |||
19 | ) | 19 | ) |
20 | } | 20 | } |
21 | 21 | ||
22 | let ranges = highlight(db, file_id, None); | 22 | let ranges = highlight(db, file_id, None, false); |
23 | let text = parse.tree().syntax().to_string(); | 23 | let text = parse.tree().syntax().to_string(); |
24 | let mut prev_pos = TextSize::from(0); | 24 | let mut prev_pos = TextSize::from(0); |
25 | let mut buf = String::new(); | 25 | let mut buf = String::new(); |
@@ -84,6 +84,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
84 | .variable { color: #DCDCCC; } | 84 | .variable { color: #DCDCCC; } |
85 | .format_specifier { color: #CC696B; } | 85 | .format_specifier { color: #CC696B; } |
86 | .mutable { text-decoration: underline; } | 86 | .mutable { text-decoration: underline; } |
87 | .unresolved_reference { color: #FC5555; } | ||
88 | .escape_sequence { color: #94BFF3; } | ||
87 | 89 | ||
88 | .keyword { color: #F0DFAF; font-weight: bold; } | 90 | .keyword { color: #F0DFAF; font-weight: bold; } |
89 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 91 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
diff --git a/crates/ra_ide/src/syntax_highlighting/injection.rs b/crates/ra_ide/src/syntax_highlighting/injection.rs index 3575a0fc6..929a5cc5c 100644 --- a/crates/ra_ide/src/syntax_highlighting/injection.rs +++ b/crates/ra_ide/src/syntax_highlighting/injection.rs | |||
@@ -53,6 +53,10 @@ pub(super) fn highlight_injection( | |||
53 | /// Mapping from extracted documentation code to original code | 53 | /// Mapping from extracted documentation code to original code |
54 | type RangesMap = BTreeMap<TextSize, TextSize>; | 54 | type RangesMap = BTreeMap<TextSize, TextSize>; |
55 | 55 | ||
56 | const RUSTDOC_FENCE: &'static str = "```"; | ||
57 | const RUSTDOC_FENCE_TOKENS: &[&'static str] = | ||
58 | &["", "rust", "should_panic", "ignore", "no_run", "compile_fail", "edition2015", "edition2018"]; | ||
59 | |||
56 | /// Extracts Rust code from documentation comments as well as a mapping from | 60 | /// Extracts Rust code from documentation comments as well as a mapping from |
57 | /// the extracted source code back to the original source ranges. | 61 | /// the extracted source code back to the original source ranges. |
58 | /// Lastly, a vector of new comment highlight ranges (spanning only the | 62 | /// Lastly, a vector of new comment highlight ranges (spanning only the |
@@ -67,6 +71,7 @@ pub(super) fn extract_doc_comments( | |||
67 | // Mapping from extracted documentation code to original code | 71 | // Mapping from extracted documentation code to original code |
68 | let mut range_mapping: RangesMap = BTreeMap::new(); | 72 | let mut range_mapping: RangesMap = BTreeMap::new(); |
69 | let mut line_start = TextSize::try_from(prefix.len()).unwrap(); | 73 | let mut line_start = TextSize::try_from(prefix.len()).unwrap(); |
74 | let mut is_codeblock = false; | ||
70 | let mut is_doctest = false; | 75 | let mut is_doctest = false; |
71 | // Replace the original, line-spanning comment ranges by new, only comment-prefix | 76 | // Replace the original, line-spanning comment ranges by new, only comment-prefix |
72 | // spanning comment ranges. | 77 | // spanning comment ranges. |
@@ -76,8 +81,13 @@ pub(super) fn extract_doc_comments( | |||
76 | .filter_map(|el| el.into_token().and_then(ast::Comment::cast)) | 81 | .filter_map(|el| el.into_token().and_then(ast::Comment::cast)) |
77 | .filter(|comment| comment.kind().doc.is_some()) | 82 | .filter(|comment| comment.kind().doc.is_some()) |
78 | .filter(|comment| { | 83 | .filter(|comment| { |
79 | if comment.text().contains("```") { | 84 | if let Some(idx) = comment.text().find(RUSTDOC_FENCE) { |
80 | is_doctest = !is_doctest; | 85 | is_codeblock = !is_codeblock; |
86 | // Check whether code is rust by inspecting fence guards | ||
87 | let guards = &comment.text()[idx + RUSTDOC_FENCE.len()..]; | ||
88 | let is_rust = | ||
89 | guards.split(',').all(|sub| RUSTDOC_FENCE_TOKENS.contains(&sub.trim())); | ||
90 | is_doctest = is_codeblock && is_rust; | ||
81 | false | 91 | false |
82 | } else { | 92 | } else { |
83 | is_doctest | 93 | is_doctest |
@@ -137,7 +147,7 @@ pub(super) fn highlight_doc_comment( | |||
137 | let (analysis, tmp_file_id) = Analysis::from_single_file(text); | 147 | let (analysis, tmp_file_id) = Analysis::from_single_file(text); |
138 | 148 | ||
139 | stack.push(); | 149 | stack.push(); |
140 | for mut h in analysis.highlight(tmp_file_id).unwrap() { | 150 | for mut h in analysis.with_db(|db| super::highlight(db, tmp_file_id, None, true)).unwrap() { |
141 | // Determine start offset and end offset in case of multi-line ranges | 151 | // Determine start offset and end offset in case of multi-line ranges |
142 | let mut start_offset = None; | 152 | let mut start_offset = None; |
143 | let mut end_offset = None; | 153 | let mut end_offset = None; |
diff --git a/crates/ra_ide/src/syntax_highlighting/tags.rs b/crates/ra_ide/src/syntax_highlighting/tags.rs index 94f466966..400d22fb6 100644 --- a/crates/ra_ide/src/syntax_highlighting/tags.rs +++ b/crates/ra_ide/src/syntax_highlighting/tags.rs | |||
@@ -23,6 +23,7 @@ pub enum HighlightTag { | |||
23 | Constant, | 23 | Constant, |
24 | Enum, | 24 | Enum, |
25 | EnumVariant, | 25 | EnumVariant, |
26 | EscapeSequence, | ||
26 | Field, | 27 | Field, |
27 | FormatSpecifier, | 28 | FormatSpecifier, |
28 | Function, | 29 | Function, |
@@ -71,6 +72,7 @@ impl HighlightTag { | |||
71 | HighlightTag::Constant => "constant", | 72 | HighlightTag::Constant => "constant", |
72 | HighlightTag::Enum => "enum", | 73 | HighlightTag::Enum => "enum", |
73 | HighlightTag::EnumVariant => "enum_variant", | 74 | HighlightTag::EnumVariant => "enum_variant", |
75 | HighlightTag::EscapeSequence => "escape_sequence", | ||
74 | HighlightTag::Field => "field", | 76 | HighlightTag::Field => "field", |
75 | HighlightTag::FormatSpecifier => "format_specifier", | 77 | HighlightTag::FormatSpecifier => "format_specifier", |
76 | HighlightTag::Function => "function", | 78 | HighlightTag::Function => "function", |
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs index 949bf59a0..b4d56a7a0 100644 --- a/crates/ra_ide/src/syntax_highlighting/tests.rs +++ b/crates/ra_ide/src/syntax_highlighting/tests.rs | |||
@@ -43,6 +43,12 @@ def_fn! { | |||
43 | } | 43 | } |
44 | } | 44 | } |
45 | 45 | ||
46 | macro_rules! noop { | ||
47 | ($expr:expr) => { | ||
48 | $expr | ||
49 | } | ||
50 | } | ||
51 | |||
46 | // comment | 52 | // comment |
47 | fn main() { | 53 | fn main() { |
48 | println!("Hello, {}!", 92); | 54 | println!("Hello, {}!", 92); |
@@ -61,6 +67,8 @@ fn main() { | |||
61 | // Do nothing | 67 | // Do nothing |
62 | } | 68 | } |
63 | 69 | ||
70 | noop!(noop!(1)); | ||
71 | |||
64 | let mut x = 42; | 72 | let mut x = 42; |
65 | let y = &mut x; | 73 | let y = &mut x; |
66 | let z = &y; | 74 | let z = &y; |
@@ -238,6 +246,10 @@ fn main() { | |||
238 | 246 | ||
239 | println!(r"Hello, {}!", "world"); | 247 | println!(r"Hello, {}!", "world"); |
240 | 248 | ||
249 | // escape sequences | ||
250 | println!("Hello\nWorld"); | ||
251 | println!("\u{48}\x65\x6C\x6C\x6F World"); | ||
252 | |||
241 | println!("{\x41}", A = 92); | 253 | println!("{\x41}", A = 92); |
242 | println!("{ничоси}", ничоси = 92); | 254 | println!("{ничоси}", ничоси = 92); |
243 | }"# | 255 | }"# |
@@ -279,7 +291,13 @@ fn main() { | |||
279 | fn test_highlight_doctest() { | 291 | fn test_highlight_doctest() { |
280 | check_highlighting( | 292 | check_highlighting( |
281 | r#" | 293 | r#" |
294 | struct Foo { | ||
295 | bar: bool, | ||
296 | } | ||
297 | |||
282 | impl Foo { | 298 | impl Foo { |
299 | pub const bar: bool = true; | ||
300 | |||
283 | /// Constructs a new `Foo`. | 301 | /// Constructs a new `Foo`. |
284 | /// | 302 | /// |
285 | /// # Examples | 303 | /// # Examples |
@@ -289,7 +307,7 @@ impl Foo { | |||
289 | /// let mut foo: Foo = Foo::new(); | 307 | /// let mut foo: Foo = Foo::new(); |
290 | /// ``` | 308 | /// ``` |
291 | pub const fn new() -> Foo { | 309 | pub const fn new() -> Foo { |
292 | Foo { } | 310 | Foo { bar: true } |
293 | } | 311 | } |
294 | 312 | ||
295 | /// `bar` method on `Foo`. | 313 | /// `bar` method on `Foo`. |
@@ -297,11 +315,15 @@ impl Foo { | |||
297 | /// # Examples | 315 | /// # Examples |
298 | /// | 316 | /// |
299 | /// ``` | 317 | /// ``` |
318 | /// use x::y; | ||
319 | /// | ||
300 | /// let foo = Foo::new(); | 320 | /// let foo = Foo::new(); |
301 | /// | 321 | /// |
302 | /// // calls bar on foo | 322 | /// // calls bar on foo |
303 | /// assert!(foo.bar()); | 323 | /// assert!(foo.bar()); |
304 | /// | 324 | /// |
325 | /// let bar = foo.bar || Foo::bar; | ||
326 | /// | ||
305 | /// /* multi-line | 327 | /// /* multi-line |
306 | /// comment */ | 328 | /// comment */ |
307 | /// | 329 | /// |
@@ -311,9 +333,13 @@ impl Foo { | |||
311 | /// | 333 | /// |
312 | /// ``` | 334 | /// ``` |
313 | /// | 335 | /// |
314 | /// ``` | 336 | /// ```rust,no_run |
315 | /// let foobar = Foo::new().bar(); | 337 | /// let foobar = Foo::new().bar(); |
316 | /// ``` | 338 | /// ``` |
339 | /// | ||
340 | /// ```sh | ||
341 | /// echo 1 | ||
342 | /// ``` | ||
317 | pub fn foo(&self) -> bool { | 343 | pub fn foo(&self) -> bool { |
318 | true | 344 | true |
319 | } | 345 | } |
@@ -322,7 +348,7 @@ impl Foo { | |||
322 | .trim(), | 348 | .trim(), |
323 | "crates/ra_ide/src/snapshots/highlight_doctest.html", | 349 | "crates/ra_ide/src/snapshots/highlight_doctest.html", |
324 | false, | 350 | false, |
325 | ) | 351 | ); |
326 | } | 352 | } |
327 | 353 | ||
328 | /// Highlights the code given by the `ra_fixture` argument, renders the | 354 | /// Highlights the code given by the `ra_fixture` argument, renders the |