diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-06-17 16:08:17 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-06-17 16:08:17 +0100 |
commit | f061b2daeb8639b5d24db8d73fa1e21d18196aa4 (patch) | |
tree | 2b1931cadd7400a09e6d10f0cb9ae4cc6646e93d | |
parent | 931f3173992df6ac6b728fa9fa9a94d15781027e (diff) | |
parent | 2145e2d878fb3b8ffcaa4ab0858cab3a7a4324e0 (diff) |
Merge #4925
4925: Syntax highlighting for escape sequences in strings r=matklad a=ltentrup
I have added a new semantic token type `ESCAPE_SEQUENCE` as the LSP specification does not seem to have an appropriate token type. This may actually be a regression for some users, as the TextMate Rust grammar has a scope `constant.character.escape.rust` which highlights escape sequences (which caused problems with semantic highlighting, see #4138).
Fixes #2604.
Co-authored-by: Leander Tentrup <[email protected]>
-rw-r--r-- | crates/ra_ide/src/snapshots/highlight_doctest.html | 1 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/highlight_injection.html | 1 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/highlight_strings.html | 7 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/highlight_unsafe.html | 1 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/highlighting.html | 1 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/rainbow_highlighting.html | 1 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 22 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/html.rs | 1 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/tags.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/tests.rs | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/semantic_tokens.rs | 1 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 1 |
12 files changed, 38 insertions, 5 deletions
diff --git a/crates/ra_ide/src/snapshots/highlight_doctest.html b/crates/ra_ide/src/snapshots/highlight_doctest.html index 13a5d1b12..f92a0aba5 100644 --- a/crates/ra_ide/src/snapshots/highlight_doctest.html +++ b/crates/ra_ide/src/snapshots/highlight_doctest.html | |||
@@ -26,6 +26,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | 28 | .unresolved_reference { color: #FC5555; } |
29 | .escape_sequence { color: #94BFF3; } | ||
29 | 30 | ||
30 | .keyword { color: #F0DFAF; font-weight: bold; } | 31 | .keyword { color: #F0DFAF; font-weight: bold; } |
31 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 32 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
diff --git a/crates/ra_ide/src/snapshots/highlight_injection.html b/crates/ra_ide/src/snapshots/highlight_injection.html index e1c9d3523..47dbd7bc8 100644 --- a/crates/ra_ide/src/snapshots/highlight_injection.html +++ b/crates/ra_ide/src/snapshots/highlight_injection.html | |||
@@ -26,6 +26,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | 28 | .unresolved_reference { color: #FC5555; } |
29 | .escape_sequence { color: #94BFF3; } | ||
29 | 30 | ||
30 | .keyword { color: #F0DFAF; font-weight: bold; } | 31 | .keyword { color: #F0DFAF; font-weight: bold; } |
31 | .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 666b48fd0..b46fa44c6 100644 --- a/crates/ra_ide/src/snapshots/highlight_strings.html +++ b/crates/ra_ide/src/snapshots/highlight_strings.html | |||
@@ -26,6 +26,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | 28 | .unresolved_reference { color: #FC5555; } |
29 | .escape_sequence { color: #94BFF3; } | ||
29 | 30 | ||
30 | .keyword { color: #F0DFAF; font-weight: bold; } | 31 | .keyword { color: #F0DFAF; font-weight: bold; } |
31 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 32 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
@@ -83,6 +84,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
83 | 84 | ||
84 | <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>); |
85 | 86 | ||
86 | <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>); | ||
87 | <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>); |
88 | }</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 e1540499b..73438fbb4 100644 --- a/crates/ra_ide/src/snapshots/highlight_unsafe.html +++ b/crates/ra_ide/src/snapshots/highlight_unsafe.html | |||
@@ -26,6 +26,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | 28 | .unresolved_reference { color: #FC5555; } |
29 | .escape_sequence { color: #94BFF3; } | ||
29 | 30 | ||
30 | .keyword { color: #F0DFAF; font-weight: bold; } | 31 | .keyword { color: #F0DFAF; font-weight: bold; } |
31 | .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 52912dc93..0c4f0a018 100644 --- a/crates/ra_ide/src/snapshots/highlighting.html +++ b/crates/ra_ide/src/snapshots/highlighting.html | |||
@@ -26,6 +26,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | 28 | .unresolved_reference { color: #FC5555; } |
29 | .escape_sequence { color: #94BFF3; } | ||
29 | 30 | ||
30 | .keyword { color: #F0DFAF; font-weight: bold; } | 31 | .keyword { color: #F0DFAF; font-weight: bold; } |
31 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 32 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html index 1d7f04882..a74a70069 100644 --- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html +++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html | |||
@@ -26,6 +26,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
26 | .format_specifier { color: #CC696B; } | 26 | .format_specifier { color: #CC696B; } |
27 | .mutable { text-decoration: underline; } | 27 | .mutable { text-decoration: underline; } |
28 | .unresolved_reference { color: #FC5555; } | 28 | .unresolved_reference { color: #FC5555; } |
29 | .escape_sequence { color: #94BFF3; } | ||
29 | 30 | ||
30 | .keyword { color: #F0DFAF; font-weight: bold; } | 31 | .keyword { color: #F0DFAF; font-weight: bold; } |
31 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 32 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 5a4de450c..854b6cc6d 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -212,8 +212,8 @@ pub(crate) fn highlight( | |||
212 | if let Some(string) = | 212 | if let Some(string) = |
213 | element_to_highlight.as_token().cloned().and_then(ast::String::cast) | 213 | element_to_highlight.as_token().cloned().and_then(ast::String::cast) |
214 | { | 214 | { |
215 | stack.push(); | ||
216 | if is_format_string { | 215 | if is_format_string { |
216 | stack.push(); | ||
217 | string.lex_format_specifier(|piece_range, kind| { | 217 | string.lex_format_specifier(|piece_range, kind| { |
218 | if let Some(highlight) = highlight_format_specifier(kind) { | 218 | if let Some(highlight) = highlight_format_specifier(kind) { |
219 | stack.add(HighlightedRange { | 219 | stack.add(HighlightedRange { |
@@ -223,13 +223,27 @@ pub(crate) fn highlight( | |||
223 | }); | 223 | }); |
224 | } | 224 | } |
225 | }); | 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); | ||
226 | } | 241 | } |
227 | stack.pop(); | ||
228 | } else if let Some(string) = | 242 | } else if let Some(string) = |
229 | element_to_highlight.as_token().cloned().and_then(ast::RawString::cast) | 243 | element_to_highlight.as_token().cloned().and_then(ast::RawString::cast) |
230 | { | 244 | { |
231 | stack.push(); | ||
232 | if is_format_string { | 245 | if is_format_string { |
246 | stack.push(); | ||
233 | string.lex_format_specifier(|piece_range, kind| { | 247 | string.lex_format_specifier(|piece_range, kind| { |
234 | if let Some(highlight) = highlight_format_specifier(kind) { | 248 | if let Some(highlight) = highlight_format_specifier(kind) { |
235 | stack.add(HighlightedRange { | 249 | stack.add(HighlightedRange { |
@@ -239,8 +253,8 @@ pub(crate) fn highlight( | |||
239 | }); | 253 | }); |
240 | } | 254 | } |
241 | }); | 255 | }); |
256 | stack.pop(); | ||
242 | } | 257 | } |
243 | stack.pop(); | ||
244 | } | 258 | } |
245 | } | 259 | } |
246 | } | 260 | } |
diff --git a/crates/ra_ide/src/syntax_highlighting/html.rs b/crates/ra_ide/src/syntax_highlighting/html.rs index 853b4a20f..99b6b25ab 100644 --- a/crates/ra_ide/src/syntax_highlighting/html.rs +++ b/crates/ra_ide/src/syntax_highlighting/html.rs | |||
@@ -85,6 +85,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
85 | .format_specifier { color: #CC696B; } | 85 | .format_specifier { color: #CC696B; } |
86 | .mutable { text-decoration: underline; } | 86 | .mutable { text-decoration: underline; } |
87 | .unresolved_reference { color: #FC5555; } | 87 | .unresolved_reference { color: #FC5555; } |
88 | .escape_sequence { color: #94BFF3; } | ||
88 | 89 | ||
89 | .keyword { color: #F0DFAF; font-weight: bold; } | 90 | .keyword { color: #F0DFAF; font-weight: bold; } |
90 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | 91 | .keyword.unsafe { color: #BC8383; font-weight: bold; } |
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 ebf5b50ac..b4d56a7a0 100644 --- a/crates/ra_ide/src/syntax_highlighting/tests.rs +++ b/crates/ra_ide/src/syntax_highlighting/tests.rs | |||
@@ -246,6 +246,10 @@ fn main() { | |||
246 | 246 | ||
247 | println!(r"Hello, {}!", "world"); | 247 | println!(r"Hello, {}!", "world"); |
248 | 248 | ||
249 | // escape sequences | ||
250 | println!("Hello\nWorld"); | ||
251 | println!("\u{48}\x65\x6C\x6C\x6F World"); | ||
252 | |||
249 | println!("{\x41}", A = 92); | 253 | println!("{\x41}", A = 92); |
250 | println!("{ничоси}", ничоси = 92); | 254 | println!("{ничоси}", ничоси = 92); |
251 | }"# | 255 | }"# |
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs index 6f125c37c..2ea63d33b 100644 --- a/crates/rust-analyzer/src/semantic_tokens.rs +++ b/crates/rust-analyzer/src/semantic_tokens.rs | |||
@@ -45,6 +45,7 @@ define_semantic_token_types![ | |||
45 | (UNION, "union"), | 45 | (UNION, "union"), |
46 | (UNRESOLVED_REFERENCE, "unresolvedReference"), | 46 | (UNRESOLVED_REFERENCE, "unresolvedReference"), |
47 | (FORMAT_SPECIFIER, "formatSpecifier"), | 47 | (FORMAT_SPECIFIER, "formatSpecifier"), |
48 | (ESCAPE_SEQUENCE, "escapeSequence"), | ||
48 | ]; | 49 | ]; |
49 | 50 | ||
50 | macro_rules! define_semantic_token_modifiers { | 51 | macro_rules! define_semantic_token_modifiers { |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 2851b4d31..055c97455 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -324,6 +324,7 @@ fn semantic_token_type_and_modifiers( | |||
324 | HighlightTag::UnresolvedReference => semantic_tokens::UNRESOLVED_REFERENCE, | 324 | HighlightTag::UnresolvedReference => semantic_tokens::UNRESOLVED_REFERENCE, |
325 | HighlightTag::FormatSpecifier => semantic_tokens::FORMAT_SPECIFIER, | 325 | HighlightTag::FormatSpecifier => semantic_tokens::FORMAT_SPECIFIER, |
326 | HighlightTag::Operator => lsp_types::SemanticTokenType::OPERATOR, | 326 | HighlightTag::Operator => lsp_types::SemanticTokenType::OPERATOR, |
327 | HighlightTag::EscapeSequence => semantic_tokens::ESCAPE_SEQUENCE, | ||
327 | }; | 328 | }; |
328 | 329 | ||
329 | for modifier in highlight.modifiers.iter() { | 330 | for modifier in highlight.modifiers.iter() { |