]> git.lizzy.rs Git - rust.git/commitdiff
Kill RAW_ literals
authorAleksey Kladov <aleksey.kladov@gmail.com>
Fri, 6 Nov 2020 21:21:56 +0000 (22:21 +0100)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Fri, 6 Nov 2020 21:23:14 +0000 (22:23 +0100)
Syntactically, they are indistinguishable from non-raw versions, so it
doesn't make sense to separate then *at the syntax* level.

53 files changed:
crates/assists/src/assist_context.rs
crates/assists/src/handlers/add_turbo_fish.rs
crates/assists/src/handlers/expand_glob_import.rs
crates/assists/src/handlers/flip_comma.rs
crates/assists/src/handlers/flip_trait_bound.rs
crates/assists/src/handlers/introduce_named_lifetime.rs
crates/assists/src/handlers/invert_if.rs
crates/assists/src/handlers/raw_string.rs
crates/assists/src/handlers/remove_mut.rs
crates/assists/src/handlers/replace_let_with_if_let.rs
crates/assists/src/handlers/replace_string_with_char.rs
crates/assists/src/handlers/split_import.rs
crates/assists/src/handlers/unwrap_block.rs
crates/ide/src/extend_selection.rs
crates/ide/src/syntax_highlighting.rs
crates/ide/src/syntax_highlighting/format.rs
crates/ide/src/syntax_highlighting/injection.rs
crates/ide/src/syntax_tree.rs
crates/parser/src/grammar.rs
crates/parser/src/grammar/expressions/atom.rs
crates/parser/src/grammar/items.rs
crates/parser/src/syntax_kind/generated.rs
crates/syntax/src/ast/expr_ext.rs
crates/syntax/src/ast/generated/tokens.rs
crates/syntax/src/ast/node_ext.rs
crates/syntax/src/ast/token_ext.rs
crates/syntax/src/parsing/lexer.rs
crates/syntax/src/parsing/reparsing.rs
crates/syntax/src/validation.rs
crates/syntax/test_data/lexer/err/0033_unclosed_raw_string_at_eof.txt
crates/syntax/test_data/lexer/err/0034_unclosed_raw_string_with_ferris.txt
crates/syntax/test_data/lexer/err/0035_unclosed_raw_string_with_ascii_escape.txt
crates/syntax/test_data/lexer/err/0036_unclosed_raw_string_with_unicode_escape.txt
crates/syntax/test_data/lexer/err/0037_unclosed_raw_string_with_space.txt
crates/syntax/test_data/lexer/err/0038_unclosed_raw_string_with_slash.txt
crates/syntax/test_data/lexer/err/0039_unclosed_raw_string_with_slash_n.txt
crates/syntax/test_data/lexer/err/0040_unclosed_raw_byte_string_at_eof.txt
crates/syntax/test_data/lexer/err/0041_unclosed_raw_byte_string_with_ferris.txt
crates/syntax/test_data/lexer/err/0042_unclosed_raw_byte_string_with_ascii_escape.txt
crates/syntax/test_data/lexer/err/0043_unclosed_raw_byte_string_with_unicode_escape.txt
crates/syntax/test_data/lexer/err/0044_unclosed_raw_byte_string_with_space.txt
crates/syntax/test_data/lexer/err/0045_unclosed_raw_byte_string_with_slash.txt
crates/syntax/test_data/lexer/err/0046_unclosed_raw_byte_string_with_slash_n.txt
crates/syntax/test_data/lexer/err/0047_unstarted_raw_string_at_eof.txt
crates/syntax/test_data/lexer/err/0048_unstarted_raw_byte_string_at_eof.txt
crates/syntax/test_data/lexer/err/0049_unstarted_raw_string_with_ascii.txt
crates/syntax/test_data/lexer/err/0050_unstarted_raw_byte_string_with_ascii.txt
crates/syntax/test_data/lexer/ok/0008_byte_strings.txt
crates/syntax/test_data/lexer/ok/0009_strings.txt
crates/syntax/test_data/lexer/ok/0013_raw_strings.txt
crates/syntax/test_data/parser/inline/ok/0085_expr_literals.rast
xtask/src/ast_src.rs
xtask/src/codegen/gen_syntax.rs

index d11fee196a374bbc541596d89d3c5062ddd7949f..fcfe2d6ee4aec924393c863c6a7cbf8ab60f5cef 100644 (file)
@@ -12,7 +12,7 @@
 };
 use syntax::{
     algo::{self, find_node_at_offset, SyntaxRewriter},
-    AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxToken, TextRange, TextSize,
+    AstNode, AstToken, SourceFile, SyntaxElement, SyntaxKind, SyntaxToken, TextRange, TextSize,
     TokenAtOffset,
 };
 use text_edit::{TextEdit, TextEditBuilder};
@@ -81,9 +81,12 @@ pub(crate) fn offset(&self) -> TextSize {
     pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken> {
         self.source_file.syntax().token_at_offset(self.offset())
     }
-    pub(crate) fn find_token_at_offset(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
+    pub(crate) fn find_token_syntax_at_offset(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
         self.token_at_offset().find(|it| it.kind() == kind)
     }
+    pub(crate) fn find_token_at_offset<T: AstToken>(&self) -> Option<T> {
+        self.token_at_offset().find_map(T::cast)
+    }
     pub(crate) fn find_node_at_offset<N: AstNode>(&self) -> Option<N> {
         find_node_at_offset(self.source_file.syntax(), self.offset())
     }
index e3d84d6986afcaced592137f95c8edd17477352f..1f486c013c8f3c3065e0617a660a4caed42bb704 100644 (file)
@@ -25,7 +25,7 @@
 // }
 // ```
 pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let ident = ctx.find_token_at_offset(SyntaxKind::IDENT).or_else(|| {
+    let ident = ctx.find_token_syntax_at_offset(SyntaxKind::IDENT).or_else(|| {
         let arg_list = ctx.find_node_at_offset::<ast::ArgList>()?;
         if arg_list.args().count() > 0 {
             return None;
index 316a58d883adf37b4216edbb3c36001493b581d4..853266395daea7fef1e6bed833a7928366b1e993 100644 (file)
@@ -41,7 +41,7 @@
 // fn qux(bar: Bar, baz: Baz) {}
 // ```
 pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let star = ctx.find_token_at_offset(T![*])?;
+    let star = ctx.find_token_syntax_at_offset(T![*])?;
     let (parent, mod_path) = find_parent_and_path(&star)?;
     let target_module = match ctx.sema.resolve_path(&mod_path)? {
         PathResolution::Def(ModuleDef::Module(it)) => it,
index 5c69db53e564af28d329c3cbdab3aaf0db46302b..64b4b1a76a50916e3697c839a7f712993d8dd01e 100644 (file)
@@ -18,7 +18,7 @@
 // }
 // ```
 pub(crate) fn flip_comma(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let comma = ctx.find_token_at_offset(T![,])?;
+    let comma = ctx.find_token_syntax_at_offset(T![,])?;
     let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?;
     let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?;
 
index 347e79b1dadedaae3b10184964f28e68db4fb3b7..92ee4218104c8f7853eb6be5f4a00183bbb1564b 100644 (file)
@@ -20,7 +20,7 @@
 pub(crate) fn flip_trait_bound(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
     // We want to replicate the behavior of `flip_binexpr` by only suggesting
     // the assist when the cursor is on a `+`
-    let plus = ctx.find_token_at_offset(T![+])?;
+    let plus = ctx.find_token_syntax_at_offset(T![+])?;
 
     // Make sure we're in a `TypeBoundList`
     if ast::TypeBoundList::cast(plus.parent()).is_none() {
index 5f623e5f7add2db2ce8c413b2e68e3674a981a78..4cc8dae65026fbb7b9c67c1ad4aa88771446e6f3 100644 (file)
@@ -36,7 +36,7 @@
 // FIXME: should also add support for the case fun(f: &Foo) -> &<|>Foo
 pub(crate) fn introduce_named_lifetime(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
     let lifetime_token = ctx
-        .find_token_at_offset(SyntaxKind::LIFETIME)
+        .find_token_syntax_at_offset(SyntaxKind::LIFETIME)
         .filter(|lifetime| lifetime.text() == "'_")?;
     if let Some(fn_def) = lifetime_token.ancestors().find_map(ast::Fn::cast) {
         generate_fn_def_assist(acc, &fn_def, lifetime_token.text_range())
index 461fcf8626b6458b40394defaec877d7863ead4e..ea722b91b2da65bd1878c93549fe92cd247f933f 100644 (file)
@@ -29,7 +29,7 @@
 // ```
 
 pub(crate) fn invert_if(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let if_keyword = ctx.find_token_at_offset(T![if])?;
+    let if_keyword = ctx.find_token_syntax_at_offset(T![if])?;
     let expr = ast::IfExpr::cast(if_keyword.parent())?;
     let if_range = if_keyword.text_range();
     let cursor_in_range = if_range.contains_range(ctx.frange.range);
index 9ddd116e015567ae58a2f67d47dca2c79236c934..7f9f01c9cd2d7c480d1d2ab00850e75e83ea9557 100644 (file)
@@ -2,9 +2,7 @@
 
 use syntax::{
     ast::{self, HasQuotes, HasStringValue},
-    AstToken,
-    SyntaxKind::{RAW_STRING, STRING},
-    TextRange, TextSize,
+    AstToken, TextRange, TextSize,
 };
 use test_utils::mark;
 
 // }
 // ```
 pub(crate) fn make_raw_string(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let token = ctx.find_token_at_offset(STRING).and_then(ast::String::cast)?;
+    let token = ctx.find_token_at_offset::<ast::String>()?;
+    if token.is_raw() {
+        return None;
+    }
     let value = token.value()?;
     let target = token.syntax().text_range();
     acc.add(
@@ -65,7 +66,10 @@ pub(crate) fn make_raw_string(acc: &mut Assists, ctx: &AssistContext) -> Option<
 // }
 // ```
 pub(crate) fn make_usual_string(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let token = ctx.find_token_at_offset(RAW_STRING).and_then(ast::RawString::cast)?;
+    let token = ctx.find_token_at_offset::<ast::String>()?;
+    if !token.is_raw() {
+        return None;
+    }
     let value = token.value()?;
     let target = token.syntax().text_range();
     acc.add(
@@ -104,11 +108,15 @@ pub(crate) fn make_usual_string(acc: &mut Assists, ctx: &AssistContext) -> Optio
 // }
 // ```
 pub(crate) fn add_hash(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let token = ctx.find_token_at_offset(RAW_STRING)?;
-    let target = token.text_range();
+    let token = ctx.find_token_at_offset::<ast::String>()?;
+    if !token.is_raw() {
+        return None;
+    }
+    let text_range = token.syntax().text_range();
+    let target = text_range;
     acc.add(AssistId("add_hash", AssistKind::Refactor), "Add #", target, |edit| {
-        edit.insert(token.text_range().start() + TextSize::of('r'), "#");
-        edit.insert(token.text_range().end(), "#");
+        edit.insert(text_range.start() + TextSize::of('r'), "#");
+        edit.insert(text_range.end(), "#");
     })
 }
 
@@ -128,7 +136,10 @@ pub(crate) fn add_hash(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
 // }
 // ```
 pub(crate) fn remove_hash(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let token = ctx.find_token_at_offset(RAW_STRING).and_then(ast::RawString::cast)?;
+    let token = ctx.find_token_at_offset::<ast::String>()?;
+    if !token.is_raw() {
+        return None;
+    }
 
     let text = token.text().as_str();
     if !text.starts_with("r#") && text.ends_with('#') {
index 44f41daa92d772bf93fa476043546728f82928d3..575b271f71d273bed2faaa6ad3533ac040b7bb52 100644 (file)
@@ -18,7 +18,7 @@
 // }
 // ```
 pub(crate) fn remove_mut(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let mut_token = ctx.find_token_at_offset(T![mut])?;
+    let mut_token = ctx.find_token_syntax_at_offset(T![mut])?;
     let delete_from = mut_token.text_range().start();
     let delete_to = match mut_token.next_token() {
         Some(it) if it.kind() == SyntaxKind::WHITESPACE => it.text_range().end(),
index a5bcbda24e1d1aab64ebae8cc4ee2ec06a191041..69d3b08d36cb7065fb225cc410b636554703e0e1 100644 (file)
@@ -37,7 +37,7 @@
 // fn compute() -> Option<i32> { None }
 // ```
 pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let let_kw = ctx.find_token_at_offset(T![let])?;
+    let let_kw = ctx.find_token_syntax_at_offset(T![let])?;
     let let_stmt = let_kw.ancestors().find_map(ast::LetStmt::cast)?;
     let init = let_stmt.initializer()?;
     let original_pat = let_stmt.pat()?;
index 4ca87a8ecc0e3485145c2e97ac8f8d6bb31f7cd2..6d227e8831dcd3a087a0e2d4894ea9db5e1b5a8a 100644 (file)
@@ -22,7 +22,7 @@
 // }
 // ```
 pub(crate) fn replace_string_with_char(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let token = ctx.find_token_at_offset(STRING).and_then(ast::String::cast)?;
+    let token = ctx.find_token_syntax_at_offset(STRING).and_then(ast::String::cast)?;
     let value = token.value()?;
     let target = token.syntax().text_range();
 
index 15e67eaa19f8f0ee8d09006be9ee102d74f185fb..ef1f6b8a1aaa78c47efccfe1554750c98c69f670 100644 (file)
@@ -16,7 +16,7 @@
 // use std::{collections::HashMap};
 // ```
 pub(crate) fn split_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let colon_colon = ctx.find_token_at_offset(T![::])?;
+    let colon_colon = ctx.find_token_syntax_at_offset(T![::])?;
     let path = ast::Path::cast(colon_colon.parent())?.qualifier()?;
     let top_path = successors(Some(path.clone()), |it| it.parent_path()).last()?;
 
index 3851aeb3e7459fc0a8c101293588fb24ec1a3006..36ef871b9385ddbec56af702c2ea4dccdf7098b1 100644 (file)
@@ -29,7 +29,7 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
     let assist_id = AssistId("unwrap_block", AssistKind::RefactorRewrite);
     let assist_label = "Unwrap block";
 
-    let l_curly_token = ctx.find_token_at_offset(T!['{'])?;
+    let l_curly_token = ctx.find_token_syntax_at_offset(T!['{'])?;
     let mut block = ast::BlockExpr::cast(l_curly_token.parent())?;
     let mut parent = block.syntax().parent()?;
     if ast::MatchArm::can_cast(parent.kind()) {
index 3ee0af8ad430a02d89e33a410447a35d3b311e53..0971f7701536884001736e3cdcc58cb9df3a74be 100644 (file)
@@ -35,7 +35,7 @@ fn try_extend_selection(
 ) -> Option<TextRange> {
     let range = frange.range;
 
-    let string_kinds = [COMMENT, STRING, RAW_STRING, BYTE_STRING, RAW_BYTE_STRING];
+    let string_kinds = [COMMENT, STRING, BYTE_STRING];
     let list_kinds = [
         RECORD_PAT_FIELD_LIST,
         MATCH_ARM_LIST,
index efcc8ecfe6b03d42e180826a5ccdb726e846aad7..05bafe9c89dd344f9ce37423e4bc221b67349196 100644 (file)
@@ -179,10 +179,12 @@ pub(crate) fn highlight(
             element.clone()
         };
 
-        if let Some(token) = element.as_token().cloned().and_then(ast::RawString::cast) {
-            let expanded = element_to_highlight.as_token().unwrap().clone();
-            if injection::highlight_injection(&mut stack, &sema, token, expanded).is_some() {
-                continue;
+        if let Some(token) = element.as_token().cloned().and_then(ast::String::cast) {
+            if token.is_raw() {
+                let expanded = element_to_highlight.as_token().unwrap().clone();
+                if injection::highlight_injection(&mut stack, &sema, token, expanded).is_some() {
+                    continue;
+                }
             }
         }
 
@@ -214,10 +216,6 @@ pub(crate) fn highlight(
                     }
                     stack.pop_and_inject(None);
                 }
-            } else if let Some(string) =
-                element_to_highlight.as_token().cloned().and_then(ast::RawString::cast)
-            {
-                format_string_highlighter.highlight_format_string(&mut stack, &string, range);
             }
         }
     }
@@ -532,7 +530,7 @@ fn highlight_element(
                 None => h.into(),
             }
         }
-        STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => HighlightTag::StringLiteral.into(),
+        STRING | BYTE_STRING => HighlightTag::StringLiteral.into(),
         ATTR => HighlightTag::Attribute.into(),
         INT_NUMBER | FLOAT_NUMBER => HighlightTag::NumericLiteral.into(),
         BYTE => HighlightTag::ByteLiteral.into(),
index 71bde24f08929c04f4603acf6c920e0cb5167946..42f27df5d9be7cc1371ba07a24ab55e532a2a391 100644 (file)
@@ -29,9 +29,7 @@ pub(super) fn check_for_format_string(&mut self, parent: &SyntaxNode) {
                         .children_with_tokens()
                         .filter(|t| t.kind() != SyntaxKind::WHITESPACE)
                         .nth(1)
-                        .filter(|e| {
-                            ast::String::can_cast(e.kind()) || ast::RawString::can_cast(e.kind())
-                        })
+                        .filter(|e| ast::String::can_cast(e.kind()))
                 }
                 _ => {}
             }
index 59a74bc02e5f2cb5683a988156ee47e1aeb322ac..79f6b5359913aee41481d5b1bb27d09ddb1db085 100644 (file)
@@ -15,7 +15,7 @@
 pub(super) fn highlight_injection(
     acc: &mut HighlightedRangeStack,
     sema: &Semantics<RootDatabase>,
-    literal: ast::RawString,
+    literal: ast::String,
     expanded: SyntaxToken,
 ) -> Option<()> {
     let active_parameter = ActiveParameter::at_token(&sema, expanded)?;
index 7941610d6b04e9558af6f4e05f37eb0a629fd46e..6dd05c05de45ce2d171b22279d3573cf06d4bc44 100644 (file)
@@ -1,9 +1,7 @@
 use ide_db::base_db::{FileId, SourceDatabase};
 use ide_db::RootDatabase;
 use syntax::{
-    algo, AstNode, NodeOrToken, SourceFile,
-    SyntaxKind::{RAW_STRING, STRING},
-    SyntaxToken, TextRange, TextSize,
+    algo, AstNode, NodeOrToken, SourceFile, SyntaxKind::STRING, SyntaxToken, TextRange, TextSize,
 };
 
 // Feature: Show Syntax Tree
@@ -46,7 +44,7 @@ fn syntax_tree_for_string(token: &SyntaxToken, text_range: TextRange) -> Option<
     // we'll attempt parsing it as rust syntax
     // to provide the syntax tree of the contents of the string
     match token.kind() {
-        STRING | RAW_STRING => syntax_tree_for_token(token, text_range),
+        STRING => syntax_tree_for_token(token, text_range),
         _ => None,
     }
 }
index 4ab206a838e5c8dc46ec9441ff177ec611a09e9c..116b991a82020165c0c1e33ac887bf4224da4987 100644 (file)
@@ -236,10 +236,7 @@ fn abi(p: &mut Parser) {
     assert!(p.at(T![extern]));
     let abi = p.start();
     p.bump(T![extern]);
-    match p.current() {
-        STRING | RAW_STRING => p.bump_any(),
-        _ => (),
-    }
+    p.eat(STRING);
     abi.complete(p, ABI);
 }
 
index 66a92a4e11132926d5e29357ea2196c1e2565ea8..31f42f16185d7017d7400469a931117f618ec8f3 100644 (file)
 //     let _ = b"e";
 //     let _ = br"f";
 // }
-pub(crate) const LITERAL_FIRST: TokenSet = TokenSet::new(&[
-    TRUE_KW,
-    FALSE_KW,
-    INT_NUMBER,
-    FLOAT_NUMBER,
-    BYTE,
-    CHAR,
-    STRING,
-    RAW_STRING,
-    BYTE_STRING,
-    RAW_BYTE_STRING,
-]);
+pub(crate) const LITERAL_FIRST: TokenSet =
+    TokenSet::new(&[TRUE_KW, FALSE_KW, INT_NUMBER, FLOAT_NUMBER, BYTE, CHAR, STRING, BYTE_STRING]);
 
 pub(crate) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
     if !p.at_ts(LITERAL_FIRST) {
index 22810e6fb88ab0b2e4ede93b9c2c56b6587a1a7e..780bc470a432b638b5d083c20b9eae39eb4e2fe0 100644 (file)
@@ -239,9 +239,7 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
         T![static] => consts::static_(p, m),
         // test extern_block
         // extern {}
-        T![extern]
-            if la == T!['{'] || ((la == STRING || la == RAW_STRING) && p.nth(2) == T!['{']) =>
-        {
+        T![extern] if la == T!['{'] || (la == STRING && p.nth(2) == T!['{']) => {
             abi(p);
             extern_item_list(p);
             m.complete(p, EXTERN_BLOCK);
index 935bd2c5e93fab980b0cda7640154a051bdd4442..8bc6688f3cc61b481c9ec21922fe122c64156212 100644 (file)
@@ -111,9 +111,7 @@ pub enum SyntaxKind {
     CHAR,
     BYTE,
     STRING,
-    RAW_STRING,
     BYTE_STRING,
-    RAW_BYTE_STRING,
     ERROR,
     IDENT,
     WHITESPACE,
@@ -277,8 +275,7 @@ pub fn is_punct(self) -> bool {
     }
     pub fn is_literal(self) -> bool {
         match self {
-            INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE | STRING | RAW_STRING | BYTE_STRING
-            | RAW_BYTE_STRING => true,
+            INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE | STRING | BYTE_STRING => true,
             _ => false,
         }
     }
index 3d33cd1cf7955cb5928c182c4a784bf1cffbac99..eb44bb2ab17031bff26ebea689c4b6d9f5a07a73 100644 (file)
@@ -320,6 +320,13 @@ pub fn as_int_number(&self) -> Option<ast::IntNumber> {
         ast::IntNumber::cast(self.token())
     }
 
+    pub fn as_string(&self) -> Option<ast::String> {
+        ast::String::cast(self.token())
+    }
+    pub fn as_byte_string(&self) -> Option<ast::ByteString> {
+        ast::ByteString::cast(self.token())
+    }
+
     fn find_suffix(text: &str, possible_suffixes: &[&str]) -> Option<SmolStr> {
         possible_suffixes
             .iter()
@@ -351,10 +358,10 @@ pub fn kind(&self) -> LiteralKind {
                     suffix: Self::find_suffix(&text, &ast::FloatNumber::SUFFIXES),
                 }
             }
-            STRING | RAW_STRING => LiteralKind::String,
+            STRING => LiteralKind::String,
             T![true] => LiteralKind::Bool(true),
             T![false] => LiteralKind::Bool(false),
-            BYTE_STRING | RAW_BYTE_STRING => LiteralKind::ByteString,
+            BYTE_STRING => LiteralKind::ByteString,
             CHAR => LiteralKind::Char,
             BYTE => LiteralKind::Byte,
             _ => unreachable!(),
index 1b8449221d31abdf5078bd7e94ef0630f4b21a9b..728b72cd77e2ab0f81ef09ce3abccd301ce5871f 100644 (file)
@@ -70,16 +70,16 @@ fn syntax(&self) -> &SyntaxToken { &self.syntax }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RawString {
+pub struct ByteString {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for RawString {
+impl std::fmt::Display for ByteString {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for RawString {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == RAW_STRING }
+impl AstToken for ByteString {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == BYTE_STRING }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
index c5cd1c504da1eb87f02f68b83351fa68d837b0cd..5579f72b978f28e89487b09163c0ba969d5a6a6e 100644 (file)
@@ -55,13 +55,7 @@ pub fn as_simple_key_value(&self) -> Option<(SmolStr, SmolStr)> {
         let key = self.simple_name()?;
         let value_token = lit.syntax().first_token()?;
 
-        let value: SmolStr = if let Some(s) = ast::String::cast(value_token.clone()) {
-            s.value()?.into()
-        } else if let Some(s) = ast::RawString::cast(value_token) {
-            s.value()?.into()
-        } else {
-            return None;
-        };
+        let value: SmolStr = ast::String::cast(value_token.clone())?.value()?.into();
 
         Some((key, value))
     }
index 8d3fad5a6c6f6f42896109f3ef9885aa9244ee35..6cd20b6a60766f5da813e0cb3a1ebf8c7dfee834 100644 (file)
@@ -139,14 +139,31 @@ fn text_range_between_quotes(&self) -> Option<TextRange> {
 }
 
 impl HasQuotes for ast::String {}
-impl HasQuotes for ast::RawString {}
 
 pub trait HasStringValue: HasQuotes {
     fn value(&self) -> Option<Cow<'_, str>>;
 }
 
+impl ast::String {
+    pub fn is_raw(&self) -> bool {
+        self.text().starts_with('r')
+    }
+    pub fn map_range_up(&self, range: TextRange) -> Option<TextRange> {
+        let contents_range = self.text_range_between_quotes()?;
+        assert!(TextRange::up_to(contents_range.len()).contains_range(range));
+        Some(range + contents_range.start())
+    }
+}
+
 impl HasStringValue for ast::String {
     fn value(&self) -> Option<Cow<'_, str>> {
+        if self.is_raw() {
+            let text = self.text().as_str();
+            let text =
+                &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
+            return Some(Cow::Borrowed(text));
+        }
+
         let text = self.text().as_str();
         let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
 
@@ -166,20 +183,9 @@ fn value(&self) -> Option<Cow<'_, str>> {
     }
 }
 
-// FIXME: merge `ast::RawString` and `ast::String`.
-impl HasStringValue for ast::RawString {
-    fn value(&self) -> Option<Cow<'_, str>> {
-        let text = self.text().as_str();
-        let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
-        Some(Cow::Borrowed(text))
-    }
-}
-
-impl ast::RawString {
-    pub fn map_range_up(&self, range: TextRange) -> Option<TextRange> {
-        let contents_range = self.text_range_between_quotes()?;
-        assert!(TextRange::up_to(contents_range.len()).contains_range(range));
-        Some(range + contents_range.start())
+impl ast::ByteString {
+    pub fn is_raw(&self) -> bool {
+        self.text().starts_with("br")
     }
 }
 
@@ -522,22 +528,6 @@ fn char_ranges(
     }
 }
 
-impl HasFormatSpecifier for ast::RawString {
-    fn char_ranges(
-        &self,
-    ) -> Option<Vec<(TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>> {
-        let text = self.text().as_str();
-        let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
-        let offset = self.text_range_between_quotes()?.start() - self.syntax().text_range().start();
-
-        let mut res = Vec::with_capacity(text.len());
-        for (idx, c) in text.char_indices() {
-            res.push((TextRange::at(idx.try_into().unwrap(), TextSize::of(c)) + offset, Ok(c)));
-        }
-        Some(res)
-    }
-}
-
 impl ast::IntNumber {
     #[rustfmt::skip]
     pub(crate) const SUFFIXES: &'static [&'static str] = &[
index 5674ecb84db7df3fcdb6e8dc5f78a637648e57cb..8afd7e53bc5eaf8f3a181d6715bb2ada4fcdb52e 100644 (file)
@@ -235,7 +235,7 @@ fn match_literal_kind(kind: &rustc_lexer::LiteralKind) -> (SyntaxKind, Option<&'
                         RawStrError::TooManyDelimiters { .. } => "Too many `#` symbols: raw strings may be delimited by up to 65535 `#` symbols",
                     };
                 };
-                RAW_STRING
+                STRING
             }
             rustc_lexer::LiteralKind::RawByteStr { err: raw_str_err, .. } => {
                 if let Some(raw_str_err) = raw_str_err {
@@ -250,7 +250,7 @@ fn match_literal_kind(kind: &rustc_lexer::LiteralKind) -> (SyntaxKind, Option<&'
                     };
                 };
 
-                RAW_BYTE_STRING
+                BYTE_STRING
             }
         };
 
index 4149f856a83d30afa145eeece1dd1b3622f65daf..190f5f67a45c8dad3c0479516cd985679fdd131f 100644 (file)
@@ -44,7 +44,7 @@ fn reparse_token<'node>(
     let prev_token = algo::find_covering_element(root, edit.delete).as_token()?.clone();
     let prev_token_kind = prev_token.kind();
     match prev_token_kind {
-        WHITESPACE | COMMENT | IDENT | STRING | RAW_STRING => {
+        WHITESPACE | COMMENT | IDENT | STRING => {
             if prev_token_kind == WHITESPACE || prev_token_kind == COMMENT {
                 // removing a new line may extends previous token
                 let deleted_range = edit.delete - prev_token.text_range().start();
index 0f9a5e8ae7edee379d01d626f67372316a744720..62a37c50a156342056de54d92d7dbdca847680e8 100644 (file)
@@ -4,7 +4,7 @@
 
 use crate::{
     algo, ast, match_ast, AstNode, SyntaxError,
-    SyntaxKind::{BYTE, BYTE_STRING, CHAR, CONST, FN, INT_NUMBER, STRING, TYPE_ALIAS},
+    SyntaxKind::{BYTE, CHAR, CONST, FN, INT_NUMBER, TYPE_ALIAS},
     SyntaxNode, SyntaxToken, TextSize, T,
 };
 use rowan::Direction;
@@ -121,18 +121,19 @@ fn unquote(text: &str, prefix_len: usize, end_delimiter: char) -> Option<&str> {
         acc.push(SyntaxError::new_at_offset(rustc_unescape_error_to_string(err), off));
     };
 
-    match token.kind() {
-        BYTE => {
-            if let Some(Err(e)) = unquote(text, 2, '\'').map(unescape_byte) {
-                push_err(2, e);
-            }
-        }
-        CHAR => {
-            if let Some(Err(e)) = unquote(text, 1, '\'').map(unescape_char) {
-                push_err(1, e);
+    if let Some(s) = literal.as_string() {
+        if !s.is_raw() {
+            if let Some(without_quotes) = unquote(text, 1, '"') {
+                unescape_literal(without_quotes, Mode::Str, &mut |range, char| {
+                    if let Err(err) = char {
+                        push_err(1, (range.start, err));
+                    }
+                })
             }
         }
-        BYTE_STRING => {
+    }
+    if let Some(s) = literal.as_byte_string() {
+        if !s.is_raw() {
             if let Some(without_quotes) = unquote(text, 2, '"') {
                 unescape_byte_literal(without_quotes, Mode::ByteStr, &mut |range, char| {
                     if let Err(err) = char {
@@ -141,13 +142,17 @@ fn unquote(text: &str, prefix_len: usize, end_delimiter: char) -> Option<&str> {
                 })
             }
         }
-        STRING => {
-            if let Some(without_quotes) = unquote(text, 1, '"') {
-                unescape_literal(without_quotes, Mode::Str, &mut |range, char| {
-                    if let Err(err) = char {
-                        push_err(1, (range.start, err));
-                    }
-                })
+    }
+
+    match token.kind() {
+        BYTE => {
+            if let Some(Err(e)) = unquote(text, 2, '\'').map(unescape_byte) {
+                push_err(2, e);
+            }
+        }
+        CHAR => {
+            if let Some(Err(e)) = unquote(text, 1, '\'').map(unescape_char) {
+                push_err(1, e);
             }
         }
         _ => (),
index 6fd59ccc0279ca73f5c2ee7b80485e634eb6c1b0..54e707b73674a178868d5292274516181a1eeb72 100644 (file)
@@ -1,2 +1,2 @@
-RAW_STRING 4 "r##\""
+STRING 4 "r##\""
 > error0..4 token("r##\"") msg(Missing trailing `"` with `#` symbols to terminate the raw string literal)
index 8d9ca0e8f12ca35e794bb6cd9594689fd7e17829..1f9889775f5e5ce73bcd642ef29a67d7d8fb3c2f 100644 (file)
@@ -1,2 +1,2 @@
-RAW_STRING 8 "r##\"🦀"
+STRING 8 "r##\"🦀"
 > error0..8 token("r##\"🦀") msg(Missing trailing `"` with `#` symbols to terminate the raw string literal)
index a906380c718a0dbfbe10d0a1a2010a205ce19699..93f6f72ae603e8c9677e2ca31423d4566ede5278 100644 (file)
@@ -1,2 +1,2 @@
-RAW_STRING 8 "r##\"\\x7f"
+STRING 8 "r##\"\\x7f"
 > error0..8 token("r##\"\\x7f") msg(Missing trailing `"` with `#` symbols to terminate the raw string literal)
index 5667c614995147e7175e0f23e974644acebf6d89..1d2ebc60fdf9cdf6b7751baab387c2814aed27c7 100644 (file)
@@ -1,2 +1,2 @@
-RAW_STRING 12 "r##\"\\u{20AA}"
+STRING 12 "r##\"\\u{20AA}"
 > error0..12 token("r##\"\\u{20AA}") msg(Missing trailing `"` with `#` symbols to terminate the raw string literal)
index 141c8268e8040d20bbb18c3ba888c5a621cc70a1..c567ab7e28210306d3382f2217b708fddd0f80ed 100644 (file)
@@ -1,2 +1,2 @@
-RAW_STRING 5 "r##\" "
+STRING 5 "r##\" "
 > error0..5 token("r##\" ") msg(Missing trailing `"` with `#` symbols to terminate the raw string literal)
index f61d4cc915e52838d5d0aec060d35b9f1df7035a..343b20323a1785c963d0ec69046d57b50d103df3 100644 (file)
@@ -1,2 +1,2 @@
-RAW_STRING 5 "r##\"\\"
+STRING 5 "r##\"\\"
 > error0..5 token("r##\"\\") msg(Missing trailing `"` with `#` symbols to terminate the raw string literal)
index 12e2c0fc038a8d7e96cf1cfd7455bd32eed414d2..041a42737580c6b44bfec9b77b10a09703572e89 100644 (file)
@@ -1,2 +1,2 @@
-RAW_STRING 6 "r##\"\\n"
+STRING 6 "r##\"\\n"
 > error0..6 token("r##\"\\n") msg(Missing trailing `"` with `#` symbols to terminate the raw string literal)
index fe12cb5fc6da14cda53c264e28b48436c3b975a0..efaa1cafd93e4f51b210a885f7c5181ee00e367e 100644 (file)
@@ -1,2 +1,2 @@
-RAW_BYTE_STRING 5 "br##\""
+BYTE_STRING 5 "br##\""
 > error0..5 token("br##\"") msg(Missing trailing `"` with `#` symbols to terminate the raw byte string literal)
index 5be2a7861b4a3a341a3585fe04bf9928475b6da1..b6c938f94e9c3a2cc76a5cbe31caae849fa3722e 100644 (file)
@@ -1,2 +1,2 @@
-RAW_BYTE_STRING 9 "br##\"🦀"
+BYTE_STRING 9 "br##\"🦀"
 > error0..9 token("br##\"🦀") msg(Missing trailing `"` with `#` symbols to terminate the raw byte string literal)
index 6cbe08d07ed94aa9807a0e90733407517a6934b2..f82efe49acc70101a1a70f84fae4ca94ff9dddf2 100644 (file)
@@ -1,2 +1,2 @@
-RAW_BYTE_STRING 9 "br##\"\\x7f"
+BYTE_STRING 9 "br##\"\\x7f"
 > error0..9 token("br##\"\\x7f") msg(Missing trailing `"` with `#` symbols to terminate the raw byte string literal)
index f56a4f98480d2db7f66210152fcc0bc7157d46b3..4e4a576961a19c85b43eba7647058b1b405b71d8 100644 (file)
@@ -1,2 +1,2 @@
-RAW_BYTE_STRING 13 "br##\"\\u{20AA}"
+BYTE_STRING 13 "br##\"\\u{20AA}"
 > error0..13 token("br##\"\\u{20AA}") msg(Missing trailing `"` with `#` symbols to terminate the raw byte string literal)
index 3d32ce34ea56315edfbbd3ce1992ebc599bb2c45..0018c8623c2eaee4987f8a982b9484a2aafd671b 100644 (file)
@@ -1,2 +1,2 @@
-RAW_BYTE_STRING 6 "br##\" "
+BYTE_STRING 6 "br##\" "
 > error0..6 token("br##\" ") msg(Missing trailing `"` with `#` symbols to terminate the raw byte string literal)
index 320fea17700e3ed769858798c2693d3ffb584855..c3ba4ae82b8a75cdb5a62df6753495f9aba8cbe2 100644 (file)
@@ -1,2 +1,2 @@
-RAW_BYTE_STRING 6 "br##\"\\"
+BYTE_STRING 6 "br##\"\\"
 > error0..6 token("br##\"\\") msg(Missing trailing `"` with `#` symbols to terminate the raw byte string literal)
index b3a56380cbd03a1d2f98ff5223672720f03efb66..7bda72276fe7679c5668a7dca65e38e5526c29c5 100644 (file)
@@ -1,2 +1,2 @@
-RAW_BYTE_STRING 7 "br##\"\\n"
+BYTE_STRING 7 "br##\"\\n"
 > error0..7 token("br##\"\\n") msg(Missing trailing `"` with `#` symbols to terminate the raw byte string literal)
index 5af1e2d97ffdc9e37922e5d3b96d9b5e8bd26275..ce92d2ff75b6358df3e9149c952220f4a4197c27 100644 (file)
@@ -1,2 +1,2 @@
-RAW_STRING 3 "r##"
+STRING 3 "r##"
 > error0..3 token("r##") msg(Missing `"` symbol after `#` symbols to begin the raw string literal)
index aec7afd92785a8706d6c394e461b51a9b295dac4..a75d9030c4dbd5609a7bb51cb74e97f0395af84d 100644 (file)
@@ -1,2 +1,2 @@
-RAW_BYTE_STRING 4 "br##"
+BYTE_STRING 4 "br##"
 > error0..4 token("br##") msg(Missing `"` symbol after `#` symbols to begin the raw byte string literal)
index e22fe5374f09075d1881cf1ffdfc11b030005f00..516e0b78ed03f6de4e44442c1dff4c483d3576ba 100644 (file)
@@ -1,4 +1,4 @@
-RAW_STRING 4 "r## "
+STRING 4 "r## "
 IDENT 1 "I"
 WHITESPACE 1 " "
 IDENT 4 "lack"
index d74ea4c2796b12ae1b68fe391c288deda159cf4c..2f8a6f5f29fd7b3c481d2db2154e3a303527e128 100644 (file)
@@ -1,4 +1,4 @@
-RAW_BYTE_STRING 5 "br## "
+BYTE_STRING 5 "br## "
 IDENT 1 "I"
 WHITESPACE 1 " "
 IDENT 4 "lack"
index bc03b51a8ab8e5df68ff2a0d8c5f8d10ab47acd5..e61ad99bef5fd008f6e6cf5a2111ed3f6f3ae042 100644 (file)
@@ -4,13 +4,13 @@ BYTE 4 "b\'x\'"
 WHITESPACE 1 " "
 BYTE_STRING 6 "b\"foo\""
 WHITESPACE 1 " "
-RAW_BYTE_STRING 4 "br\"\""
+BYTE_STRING 4 "br\"\""
 WHITESPACE 1 "\n"
 BYTE 6 "b\'\'suf"
 WHITESPACE 1 " "
 BYTE_STRING 5 "b\"\"ix"
 WHITESPACE 1 " "
-RAW_BYTE_STRING 6 "br\"\"br"
+BYTE_STRING 6 "br\"\"br"
 WHITESPACE 1 "\n"
 BYTE 5 "b\'\\n\'"
 WHITESPACE 1 " "
index 4cb4d711d6783beff2738cd74d1c78257ebe4513..988a8877bd7265ec691ba6fb1e000c46d46dfaf5 100644 (file)
@@ -1,6 +1,6 @@
 STRING 7 "\"hello\""
 WHITESPACE 1 " "
-RAW_STRING 8 "r\"world\""
+STRING 8 "r\"world\""
 WHITESPACE 1 " "
 STRING 17 "\"\\n\\\"\\\\no escape\""
 WHITESPACE 1 " "
index 9cf0957d1e69932d371c0cf9518b7e76bdf7993d..db0d5ffd1435fc56f2bef058bfb909cd8d6b8a24 100644 (file)
@@ -1,2 +1,2 @@
-RAW_STRING 36 "r###\"this is a r##\"raw\"## string\"###"
+STRING 36 "r###\"this is a r##\"raw\"## string\"###"
 WHITESPACE 1 "\n"
index 9a87b5b936de1a3c921fad0a948d659d9aa197e6..ae838105d05e915635f79bed38dbb3882ca43d39 100644 (file)
@@ -104,7 +104,7 @@ SOURCE_FILE@0..189
         EQ@142..143 "="
         WHITESPACE@143..144 " "
         LITERAL@144..148
-          RAW_STRING@144..148 "r\"d\""
+          STRING@144..148 "r\"d\""
         SEMICOLON@148..149 ";"
       WHITESPACE@149..154 "\n    "
       LET_STMT@154..167
@@ -128,7 +128,7 @@ SOURCE_FILE@0..189
         EQ@178..179 "="
         WHITESPACE@179..180 " "
         LITERAL@180..185
-          RAW_BYTE_STRING@180..185 "br\"f\""
+          BYTE_STRING@180..185 "br\"f\""
         SEMICOLON@185..186 ";"
       WHITESPACE@186..187 "\n"
       R_CURLY@187..188 "}"
index adc191254d823af63ff21c72740defadb472adc1..8ceaaf60eb40ee54ad4912f2b9034b00c8382d56 100644 (file)
@@ -71,16 +71,7 @@ pub(crate) struct KindsSrc<'a> {
         "trait", "true", "try", "type", "unsafe", "use", "where", "while",
     ],
     contextual_keywords: &["auto", "default", "existential", "union", "raw"],
-    literals: &[
-        "INT_NUMBER",
-        "FLOAT_NUMBER",
-        "CHAR",
-        "BYTE",
-        "STRING",
-        "RAW_STRING",
-        "BYTE_STRING",
-        "RAW_BYTE_STRING",
-    ],
+    literals: &["INT_NUMBER", "FLOAT_NUMBER", "CHAR", "BYTE", "STRING", "BYTE_STRING"],
     tokens: &[
         "ERROR",
         "IDENT",
index 87c934e66763d3efcb9d32a3f4a786df718e424d..44460effa83f1300a2444137f5810b6225eb6c04 100644 (file)
@@ -505,7 +505,7 @@ fn ty(&self) -> proc_macro2::Ident {
 fn lower(grammar: &Grammar) -> AstSrc {
     let mut res = AstSrc::default();
 
-    res.tokens = "Whitespace Comment String RawString IntNumber FloatNumber"
+    res.tokens = "Whitespace Comment String ByteString IntNumber FloatNumber"
         .split_ascii_whitespace()
         .map(|it| it.to_string())
         .collect::<Vec<_>>();