mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 21:35:20 +00:00
Add ast for plain and raw string literals
This commit is contained in:
parent
42604c673d
commit
5b54a93fe7
4 changed files with 98 additions and 58 deletions
|
@ -2,8 +2,8 @@
|
|||
|
||||
use crate::{
|
||||
ast::AstToken,
|
||||
SyntaxKind::{COMMENT, WHITESPACE},
|
||||
SyntaxToken,
|
||||
SyntaxKind::{COMMENT, RAW_STRING, STRING, WHITESPACE},
|
||||
SyntaxToken, TextRange, TextUnit,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
|
@ -11,10 +11,9 @@ pub struct Comment(SyntaxToken);
|
|||
|
||||
impl AstToken for Comment {
|
||||
fn cast(token: SyntaxToken) -> Option<Self> {
|
||||
if token.kind() == COMMENT {
|
||||
Some(Comment(token))
|
||||
} else {
|
||||
None
|
||||
match token.kind() {
|
||||
COMMENT => Some(Comment(token)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxToken {
|
||||
|
@ -94,10 +93,9 @@ pub struct Whitespace(SyntaxToken);
|
|||
|
||||
impl AstToken for Whitespace {
|
||||
fn cast(token: SyntaxToken) -> Option<Self> {
|
||||
if token.kind() == WHITESPACE {
|
||||
Some(Whitespace(token))
|
||||
} else {
|
||||
None
|
||||
match token.kind() {
|
||||
WHITESPACE => Some(Whitespace(token)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxToken {
|
||||
|
@ -111,3 +109,80 @@ impl Whitespace {
|
|||
text.find('\n').map_or(false, |idx| text[idx + 1..].contains('\n'))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct String(SyntaxToken);
|
||||
|
||||
impl AstToken for String {
|
||||
fn cast(token: SyntaxToken) -> Option<Self> {
|
||||
match token.kind() {
|
||||
STRING => Some(String(token)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxToken {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl String {
|
||||
pub fn value(&self) -> Option<std::string::String> {
|
||||
let text = self.text().as_str();
|
||||
let usual_string_range = find_usual_string_range(text)?;
|
||||
let start_of_inside = usual_string_range.start().to_usize() + 1;
|
||||
let end_of_inside = usual_string_range.end().to_usize();
|
||||
let inside_str = &text[start_of_inside..end_of_inside];
|
||||
|
||||
let mut buf = std::string::String::with_capacity(inside_str.len());
|
||||
let mut has_error = false;
|
||||
rustc_lexer::unescape::unescape_str(inside_str, &mut |_, unescaped_char| {
|
||||
match unescaped_char {
|
||||
Ok(c) => buf.push(c),
|
||||
Err(_) => has_error = true,
|
||||
}
|
||||
});
|
||||
|
||||
if has_error {
|
||||
return None;
|
||||
}
|
||||
Some(buf)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RawString(SyntaxToken);
|
||||
|
||||
impl AstToken for RawString {
|
||||
fn cast(token: SyntaxToken) -> Option<Self> {
|
||||
match token.kind() {
|
||||
RAW_STRING => Some(RawString(token)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxToken {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl RawString {
|
||||
pub fn value(&self) -> Option<std::string::String> {
|
||||
let text = self.text().as_str();
|
||||
let usual_string_range = find_usual_string_range(text)?;
|
||||
let start_of_inside = usual_string_range.start().to_usize() + 1;
|
||||
let end_of_inside = usual_string_range.end().to_usize();
|
||||
let inside_str = &text[start_of_inside..end_of_inside];
|
||||
Some(inside_str.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
fn find_usual_string_range(s: &str) -> Option<TextRange> {
|
||||
let left_quote = s.find('"')?;
|
||||
let right_quote = s.rfind('"')?;
|
||||
if left_quote == right_quote {
|
||||
// `s` only contains one quote
|
||||
None
|
||||
} else {
|
||||
Some(TextRange::from_to(
|
||||
TextUnit::from(left_quote as u32),
|
||||
TextUnit::from(right_quote as u32),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue