⬆️ rust-analyzer

This commit is contained in:
Laurențiu Nicola 2022-11-23 17:24:03 +02:00
parent 61c744d4fd
commit a2a1d99545
126 changed files with 2098 additions and 904 deletions

View file

@ -5,7 +5,7 @@ description = "Comment and whitespace preserving parser for the Rust language"
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-lang/rust-analyzer"
edition = "2021"
rust-version = "1.57"
rust-version = "1.65"
[lib]
doctest = false

View file

@ -4,7 +4,7 @@ name = "syntax-fuzz"
version = "0.0.1"
publish = false
edition = "2021"
rust-version = "1.57"
rust-version = "1.65"
[package.metadata]
cargo-fuzz = true

View file

@ -239,8 +239,11 @@ Static =
Trait =
Attr* Visibility?
'unsafe'? 'auto'?
'trait' Name GenericParamList? (':' TypeBoundList?)? WhereClause?
AssocItemList
'trait' Name GenericParamList?
(
(':' TypeBoundList?)? WhereClause? AssocItemList
| '=' TypeBoundList? WhereClause? ';'
)
AssocItemList =
'{' Attr* AssocItem* '}'

View file

@ -407,6 +407,8 @@ impl Trait {
pub fn auto_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![auto]) }
pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) }
pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) }
pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]

View file

@ -209,17 +209,19 @@ impl ast::String {
let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
let mut buf = String::new();
let mut text_iter = text.chars();
let mut prev_end = 0;
let mut has_error = false;
unescape_literal(text, Mode::Str, &mut |char_range, unescaped_char| match (
unescaped_char,
buf.capacity() == 0,
) {
(Ok(c), false) => buf.push(c),
(Ok(c), true) if char_range.len() == 1 && Some(c) == text_iter.next() => (),
(Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
prev_end = char_range.end
}
(Ok(c), true) => {
buf.reserve_exact(text.len());
buf.push_str(&text[..char_range.start]);
buf.push_str(&text[..prev_end]);
buf.push(c);
}
(Err(_), _) => has_error = true,
@ -252,17 +254,19 @@ impl ast::ByteString {
let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
let mut buf: Vec<u8> = Vec::new();
let mut text_iter = text.chars();
let mut prev_end = 0;
let mut has_error = false;
unescape_literal(text, Mode::ByteStr, &mut |char_range, unescaped_char| match (
unescaped_char,
buf.capacity() == 0,
) {
(Ok(c), false) => buf.push(c as u8),
(Ok(c), true) if char_range.len() == 1 && Some(c) == text_iter.next() => (),
(Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
prev_end = char_range.end
}
(Ok(c), true) => {
buf.reserve_exact(text.len());
buf.extend_from_slice(text[..char_range.start].as_bytes());
buf.extend_from_slice(text[..prev_end].as_bytes());
buf.push(c as u8);
}
(Err(_), _) => has_error = true,
@ -445,6 +449,36 @@ mod tests {
check_string_value(r"\foobar", None);
check_string_value(r"\nfoobar", "\nfoobar");
check_string_value(r"C:\\Windows\\System32\\", "C:\\Windows\\System32\\");
check_string_value(r"\x61bcde", "abcde");
check_string_value(
r"a\
bcde", "abcde",
);
}
fn check_byte_string_value<'a, const N: usize>(
lit: &str,
expected: impl Into<Option<&'a [u8; N]>>,
) {
assert_eq!(
ast::ByteString { syntax: make::tokens::literal(&format!("b\"{}\"", lit)) }
.value()
.as_deref(),
expected.into().map(|value| &value[..])
);
}
#[test]
fn test_byte_string_escape() {
check_byte_string_value(r"foobar", b"foobar");
check_byte_string_value(r"\foobar", None::<&[u8; 0]>);
check_byte_string_value(r"\nfoobar", b"\nfoobar");
check_byte_string_value(r"C:\\Windows\\System32\\", b"C:\\Windows\\System32\\");
check_byte_string_value(r"\x61bcde", b"abcde");
check_byte_string_value(
r"a\
bcde", b"abcde",
);
}
#[test]

View file

@ -86,7 +86,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
.traits
.iter()
.filter(|trait_name| {
// Loops have two expressions so this might collide, therefor manual impl it
// Loops have two expressions so this might collide, therefore manual impl it
node.name != "ForExpr" && node.name != "WhileExpr"
|| trait_name.as_str() != "HasLoopBody"
})