diff options
Diffstat (limited to 'crates/ide/src/syntax_highlighting/injection.rs')
-rw-r--r-- | crates/ide/src/syntax_highlighting/injection.rs | 105 |
1 files changed, 39 insertions, 66 deletions
diff --git a/crates/ide/src/syntax_highlighting/injection.rs b/crates/ide/src/syntax_highlighting/injection.rs index 98ee03e0d..008d5ce24 100644 --- a/crates/ide/src/syntax_highlighting/injection.rs +++ b/crates/ide/src/syntax_highlighting/injection.rs | |||
@@ -7,12 +7,12 @@ use ide_db::call_info::ActiveParameter; | |||
7 | use itertools::Itertools; | 7 | use itertools::Itertools; |
8 | use syntax::{ast, AstToken, SyntaxNode, SyntaxToken, TextRange, TextSize}; | 8 | use syntax::{ast, AstToken, SyntaxNode, SyntaxToken, TextRange, TextSize}; |
9 | 9 | ||
10 | use crate::{Analysis, HighlightModifier, HighlightTag, HighlightedRange, RootDatabase}; | 10 | use crate::{Analysis, HlMod, HlRange, HlTag, RootDatabase}; |
11 | 11 | ||
12 | use super::{highlights::Highlights, injector::Injector}; | 12 | use super::{highlights::Highlights, injector::Injector}; |
13 | 13 | ||
14 | pub(super) fn highlight_injection( | 14 | pub(super) fn highlight_injection( |
15 | acc: &mut Highlights, | 15 | hl: &mut Highlights, |
16 | sema: &Semantics<RootDatabase>, | 16 | sema: &Semantics<RootDatabase>, |
17 | literal: ast::String, | 17 | literal: ast::String, |
18 | expanded: SyntaxToken, | 18 | expanded: SyntaxToken, |
@@ -22,80 +22,53 @@ pub(super) fn highlight_injection( | |||
22 | return None; | 22 | return None; |
23 | } | 23 | } |
24 | let value = literal.value()?; | 24 | let value = literal.value()?; |
25 | let marker_info = MarkerInfo::new(&*value); | ||
26 | let (analysis, tmp_file_id) = Analysis::from_single_file(marker_info.cleaned_text.clone()); | ||
27 | 25 | ||
28 | if let Some(range) = literal.open_quote_text_range() { | 26 | if let Some(range) = literal.open_quote_text_range() { |
29 | acc.add(HighlightedRange { | 27 | hl.add(HlRange { range, highlight: HlTag::StringLiteral.into(), binding_hash: None }) |
30 | range, | ||
31 | highlight: HighlightTag::StringLiteral.into(), | ||
32 | binding_hash: None, | ||
33 | }) | ||
34 | } | 28 | } |
35 | 29 | ||
36 | for mut h in analysis.highlight(tmp_file_id).unwrap() { | 30 | let mut inj = Injector::default(); |
37 | let range = marker_info.map_range_up(h.range); | ||
38 | if let Some(range) = literal.map_range_up(range) { | ||
39 | h.range = range; | ||
40 | acc.add(h); | ||
41 | } | ||
42 | } | ||
43 | 31 | ||
44 | if let Some(range) = literal.close_quote_text_range() { | 32 | let mut text = &*value; |
45 | acc.add(HighlightedRange { | 33 | let mut offset: TextSize = 0.into(); |
46 | range, | ||
47 | highlight: HighlightTag::StringLiteral.into(), | ||
48 | binding_hash: None, | ||
49 | }) | ||
50 | } | ||
51 | 34 | ||
52 | Some(()) | 35 | while !text.is_empty() { |
53 | } | 36 | let marker = "$0"; |
37 | let idx = text.find(marker).unwrap_or(text.len()); | ||
38 | let (chunk, next) = text.split_at(idx); | ||
39 | inj.add(chunk, TextRange::at(offset, TextSize::of(chunk))); | ||
54 | 40 | ||
55 | /// Data to remove `$0` from string and map ranges | 41 | text = next; |
56 | #[derive(Default, Debug)] | 42 | offset += TextSize::of(chunk); |
57 | struct MarkerInfo { | ||
58 | cleaned_text: String, | ||
59 | markers: Vec<TextRange>, | ||
60 | } | ||
61 | 43 | ||
62 | impl MarkerInfo { | 44 | if let Some(next) = text.strip_prefix(marker) { |
63 | fn new(mut text: &str) -> Self { | 45 | if let Some(range) = literal.map_range_up(TextRange::at(offset, TextSize::of(marker))) { |
64 | let marker = "$0"; | 46 | hl.add(HlRange { range, highlight: HlTag::Keyword.into(), binding_hash: None }); |
47 | } | ||
65 | 48 | ||
66 | let mut res = MarkerInfo::default(); | ||
67 | let mut offset: TextSize = 0.into(); | ||
68 | while !text.is_empty() { | ||
69 | let idx = text.find(marker).unwrap_or(text.len()); | ||
70 | let (chunk, next) = text.split_at(idx); | ||
71 | text = next; | 49 | text = next; |
72 | res.cleaned_text.push_str(chunk); | ||
73 | offset += TextSize::of(chunk); | ||
74 | |||
75 | if let Some(next) = text.strip_prefix(marker) { | ||
76 | text = next; | ||
77 | 50 | ||
78 | let marker_len = TextSize::of(marker); | 51 | let marker_len = TextSize::of(marker); |
79 | res.markers.push(TextRange::at(offset, marker_len)); | 52 | offset += marker_len; |
80 | offset += marker_len; | ||
81 | } | ||
82 | } | 53 | } |
83 | res | ||
84 | } | 54 | } |
85 | fn map_range_up(&self, range: TextRange) -> TextRange { | 55 | |
86 | TextRange::new( | 56 | let (analysis, tmp_file_id) = Analysis::from_single_file(inj.text().to_string()); |
87 | self.map_offset_up(range.start(), true), | 57 | |
88 | self.map_offset_up(range.end(), false), | 58 | for mut hl_range in analysis.highlight(tmp_file_id).unwrap() { |
89 | ) | 59 | for range in inj.map_range_up(hl_range.range) { |
90 | } | 60 | if let Some(range) = literal.map_range_up(range) { |
91 | fn map_offset_up(&self, mut offset: TextSize, start: bool) -> TextSize { | 61 | hl_range.range = range; |
92 | for r in &self.markers { | 62 | hl.add(hl_range.clone()); |
93 | if r.start() < offset || (start && r.start() == offset) { | ||
94 | offset += r.len() | ||
95 | } | 63 | } |
96 | } | 64 | } |
97 | offset | ||
98 | } | 65 | } |
66 | |||
67 | if let Some(range) = literal.close_quote_text_range() { | ||
68 | hl.add(HlRange { range, highlight: HlTag::StringLiteral.into(), binding_hash: None }) | ||
69 | } | ||
70 | |||
71 | Some(()) | ||
99 | } | 72 | } |
100 | 73 | ||
101 | const RUSTDOC_FENCE: &'static str = "```"; | 74 | const RUSTDOC_FENCE: &'static str = "```"; |
@@ -116,7 +89,7 @@ const RUSTDOC_FENCE_TOKENS: &[&'static str] = &[ | |||
116 | /// Lastly, a vector of new comment highlight ranges (spanning only the | 89 | /// Lastly, a vector of new comment highlight ranges (spanning only the |
117 | /// comment prefix) is returned which is used in the syntax highlighting | 90 | /// comment prefix) is returned which is used in the syntax highlighting |
118 | /// injection to replace the previous (line-spanning) comment ranges. | 91 | /// injection to replace the previous (line-spanning) comment ranges. |
119 | pub(super) fn extract_doc_comments(node: &SyntaxNode) -> Option<(Vec<HighlightedRange>, Injector)> { | 92 | pub(super) fn extract_doc_comments(node: &SyntaxNode) -> Option<(Vec<HlRange>, Injector)> { |
120 | let mut inj = Injector::default(); | 93 | let mut inj = Injector::default(); |
121 | // wrap the doctest into function body to get correct syntax highlighting | 94 | // wrap the doctest into function body to get correct syntax highlighting |
122 | let prefix = "fn doctest() {\n"; | 95 | let prefix = "fn doctest() {\n"; |
@@ -166,12 +139,12 @@ pub(super) fn extract_doc_comments(node: &SyntaxNode) -> Option<(Vec<Highlighted | |||
166 | pos | 139 | pos |
167 | }; | 140 | }; |
168 | 141 | ||
169 | new_comments.push(HighlightedRange { | 142 | new_comments.push(HlRange { |
170 | range: TextRange::new( | 143 | range: TextRange::new( |
171 | range.start(), | 144 | range.start(), |
172 | range.start() + TextSize::try_from(pos).unwrap(), | 145 | range.start() + TextSize::try_from(pos).unwrap(), |
173 | ), | 146 | ), |
174 | highlight: HighlightTag::Comment | HighlightModifier::Documentation, | 147 | highlight: HlTag::Comment | HlMod::Documentation, |
175 | binding_hash: None, | 148 | binding_hash: None, |
176 | }); | 149 | }); |
177 | line_start += range.len() - TextSize::try_from(pos).unwrap(); | 150 | line_start += range.len() - TextSize::try_from(pos).unwrap(); |
@@ -196,7 +169,7 @@ pub(super) fn extract_doc_comments(node: &SyntaxNode) -> Option<(Vec<Highlighted | |||
196 | 169 | ||
197 | /// Injection of syntax highlighting of doctests. | 170 | /// Injection of syntax highlighting of doctests. |
198 | pub(super) fn highlight_doc_comment( | 171 | pub(super) fn highlight_doc_comment( |
199 | new_comments: Vec<HighlightedRange>, | 172 | new_comments: Vec<HlRange>, |
200 | inj: Injector, | 173 | inj: Injector, |
201 | stack: &mut Highlights, | 174 | stack: &mut Highlights, |
202 | ) { | 175 | ) { |
@@ -207,9 +180,9 @@ pub(super) fn highlight_doc_comment( | |||
207 | 180 | ||
208 | for h in analysis.with_db(|db| super::highlight(db, tmp_file_id, None, true)).unwrap() { | 181 | for h in analysis.with_db(|db| super::highlight(db, tmp_file_id, None, true)).unwrap() { |
209 | for r in inj.map_range_up(h.range) { | 182 | for r in inj.map_range_up(h.range) { |
210 | stack.add(HighlightedRange { | 183 | stack.add(HlRange { |
211 | range: r, | 184 | range: r, |
212 | highlight: h.highlight | HighlightModifier::Injected, | 185 | highlight: h.highlight | HlMod::Injected, |
213 | binding_hash: h.binding_hash, | 186 | binding_hash: h.binding_hash, |
214 | }); | 187 | }); |
215 | } | 188 | } |