about summary refs log tree commit diff
diff options
context:
space:
mode:
authoryipinliu <ypliu18@gmail.com>2022-03-12 19:00:17 +0800
committeryipinliu <ypliu18@gmail.com>2022-03-12 19:03:14 +0800
commit581e1bf0d7b05cafdc60c1f132ba99c5ca338bc6 (patch)
tree957ba29947bca5ada74d7d83083bbf3ac8c5da29
parent36e87fdb985c65dcc36a794e7004f1f79e8977d8 (diff)
downloadrust-581e1bf0d7b05cafdc60c1f132ba99c5ca338bc6.tar.gz
rust-581e1bf0d7b05cafdc60c1f132ba99c5ca338bc6.zip
Highlight escape sequences in byte strings
-rw-r--r--crates/ide/src/syntax_highlighting.rs29
-rw-r--r--crates/ide/src/syntax_highlighting/escape.rs25
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_byte_string.html47
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs14
4 files changed, 97 insertions, 18 deletions
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 0119ba5cb77..1bd95c4c437 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -7,6 +7,7 @@ mod highlight;
 mod format;
 mod macro_;
 mod inject;
+mod escape;
 
 mod html;
 #[cfg(test)]
@@ -16,7 +17,7 @@ use hir::{InFile, Name, Semantics};
 use ide_db::RootDatabase;
 use rustc_hash::FxHashMap;
 use syntax::{
-    ast::{self, IsString},
+    ast::{self},
     AstNode, AstToken, NodeOrToken,
     SyntaxKind::*,
     SyntaxNode, TextRange, WalkEvent, T,
@@ -30,6 +31,7 @@ use crate::{
     FileId, HlMod, HlTag,
 };
 
+use crate::syntax_highlighting::escape::highlight_escape_string;
 pub(crate) use html::highlight_as_html;
 
 #[derive(Debug, Clone, Copy)]
@@ -371,29 +373,20 @@ fn traverse(
         // string highlight injections, note this does not use the descended element as proc-macros
         // can rewrite string literals which invalidates our indices
         if let (Some(token), Some(descended_token)) = (token, descended_element.as_token()) {
-            let string = ast::String::cast(token);
-            let string_to_highlight = ast::String::cast(descended_token.clone());
-            if let Some((string, expanded_string)) = string.zip(string_to_highlight) {
+            if ast::String::can_cast(token.kind()) && ast::String::can_cast(descended_token.kind())
+            {
+                let string = ast::String::cast(token).unwrap();
+                let expanded_string = ast::String::cast(descended_token.clone()).unwrap();
                 if string.is_raw() {
                     if inject::ra_fixture(hl, sema, &string, &expanded_string).is_some() {
                         continue;
                     }
                 }
                 highlight_format_string(hl, &string, &expanded_string, range);
-                // Highlight escape sequences
-                string.escaped_char_ranges(&mut |piece_range, char| {
-                    if char.is_err() {
-                        return;
-                    }
-
-                    if string.text()[piece_range.start().into()..].starts_with('\\') {
-                        hl.add(HlRange {
-                            range: piece_range + range.start(),
-                            highlight: HlTag::EscapeSequence.into(),
-                            binding_hash: None,
-                        });
-                    }
-                });
+                highlight_escape_string(hl, &string, range.start());
+            } else if ast::ByteString::can_cast(token.kind()) {
+                let byte_string = ast::ByteString::cast(token).unwrap();
+                highlight_escape_string(hl, &byte_string, range.start());
             }
         }
 
diff --git a/crates/ide/src/syntax_highlighting/escape.rs b/crates/ide/src/syntax_highlighting/escape.rs
new file mode 100644
index 00000000000..1b53edb7dc4
--- /dev/null
+++ b/crates/ide/src/syntax_highlighting/escape.rs
@@ -0,0 +1,25 @@
+use crate::syntax_highlighting::highlights::Highlights;
+use crate::{HlRange, HlTag};
+use syntax::ast::IsString;
+use syntax::TextSize;
+
+/// Highlight escape sequences
+pub(super) fn highlight_escape_string<T: IsString>(
+    stack: &mut Highlights,
+    string: &T,
+    start: TextSize,
+) {
+    string.escaped_char_ranges(&mut |piece_range, char| {
+        if char.is_err() {
+            return;
+        }
+
+        if string.text()[piece_range.start().into()..].starts_with('\\') {
+            stack.add(HlRange {
+                range: piece_range + start,
+                highlight: HlTag::EscapeSequence.into(),
+                binding_hash: None,
+            });
+        }
+    });
+}
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_byte_string.html b/crates/ide/src/syntax_highlighting/test_data/highlight_byte_string.html
new file mode 100644
index 00000000000..113b73af0c4
--- /dev/null
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_byte_string.html
@@ -0,0 +1,47 @@
+
+<style>
+body                { margin: 0; }
+pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
+
+.lifetime           { color: #DFAF8F; font-style: italic; }
+.label              { color: #DFAF8F; font-style: italic; }
+.comment            { color: #7F9F7F; }
+.documentation      { color: #629755; }
+.intra_doc_link     { font-style: italic; }
+.injected           { opacity: 0.65 ; }
+.struct, .enum      { color: #7CB8BB; }
+.enum_variant       { color: #BDE0F3; }
+.string_literal     { color: #CC9393; }
+.field              { color: #94BFF3; }
+.function           { color: #93E0E3; }
+.function.unsafe    { color: #BC8383; }
+.trait.unsafe       { color: #BC8383; }
+.operator.unsafe    { color: #BC8383; }
+.mutable.unsafe     { color: #BC8383; text-decoration: underline; }
+.keyword.unsafe     { color: #BC8383; font-weight: bold; }
+.parameter          { color: #94BFF3; }
+.text               { color: #DCDCCC; }
+.type               { color: #7CB8BB; }
+.builtin_type       { color: #8CD0D3; }
+.type_param         { color: #DFAF8F; }
+.attribute          { color: #94BFF3; }
+.numeric_literal    { color: #BFEBBF; }
+.bool_literal       { color: #BFE6EB; }
+.macro              { color: #94BFF3; }
+.derive             { color: #94BFF3; font-style: italic; }
+.module             { color: #AFD8AF; }
+.value_param        { color: #DCDCCC; }
+.variable           { color: #DCDCCC; }
+.format_specifier   { color: #CC696B; }
+.mutable            { text-decoration: underline; }
+.escape_sequence    { color: #94BFF3; }
+.keyword            { color: #F0DFAF; font-weight: bold; }
+.control            { font-style: italic; }
+.reference          { font-style: italic; font-weight: bold; }
+
+.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+</style>
+<pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
+    <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x00</span><span class="escape_sequence">\x63</span><span class="escape_sequence">\n</span><span class="string_literal">"</span><span class="semicolon">;</span>
+    <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">b"</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x00</span><span class="escape_sequence">\x63</span><span class="escape_sequence">\n</span><span class="string_literal">"</span><span class="semicolon">;</span>
+<span class="brace">}</span></code></pre>
\ No newline at end of file
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index efd03c28237..f9c2404c358 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -477,6 +477,20 @@ fn main() {
 }
 
 #[test]
+fn test_byte_string_highlight() {
+    check_highlighting(
+        r#"
+fn main() {
+    let _ = "\x28\x28\x00\x63\n";
+    let _ = b"\x28\x28\x00\x63\n";
+}
+"#,
+        expect_file!["./test_data/highlight_byte_string.html"],
+        false,
+    );
+}
+
+#[test]
 fn test_unsafe_highlighting() {
     check_highlighting(
         r#"