ra_syntax: reshape SyntaxError for the sake of removing redundancy

This commit is contained in:
Veetaha 2020-02-06 02:33:18 +02:00
parent 9053003e3b
commit 9fdf984958
55 changed files with 405 additions and 638 deletions

@ -10,7 +10,7 @@ use ra_prof::profile;
use ra_syntax::{
algo,
ast::{self, make, AstNode},
Location, SyntaxNode, TextRange, T,
SyntaxNode, TextRange, T,
};
use ra_text_edit::{TextEdit, TextEditBuilder};
@ -29,7 +29,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
let mut res = Vec::new();
res.extend(parse.errors().iter().map(|err| Diagnostic {
range: location_to_range(err.location()),
range: *err.range(),
message: format!("Syntax Error: {}", err),
severity: Severity::Error,
fix: None,
@ -116,12 +116,6 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
drop(sink);
res.into_inner()
}
fn location_to_range(location: Location) -> TextRange {
match location {
Location::Offset(offset) => TextRange::offset_len(offset, 1.into()),
Location::Range(range) => range,
}
}
fn check_unnecessary_braces_in_use_statement(
acc: &mut Vec<Diagnostic>,

@ -41,11 +41,9 @@ use crate::syntax_node::GreenNode;
pub use crate::{
algo::InsertPosition,
ast::{AstNode, AstToken},
parsing::{
lex_single_syntax_kind, lex_single_valid_syntax_kind, tokenize, Token, TokenizeError,
},
parsing::{lex_single_syntax_kind, lex_single_valid_syntax_kind, tokenize, Token},
ptr::{AstPtr, SyntaxNodePtr},
syntax_error::{Location, SyntaxError, SyntaxErrorKind},
syntax_error::SyntaxError,
syntax_node::{
Direction, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken, SyntaxTreeBuilder,
},
@ -117,7 +115,7 @@ impl Parse<SourceFile> {
pub fn debug_dump(&self) -> String {
let mut buf = format!("{:#?}", self.tree().syntax());
for err in self.errors.iter() {
writeln!(buf, "error {:?}: {}", err.location(), err.kind()).unwrap();
writeln!(buf, "error {:?}: {}", err.range(), err.message()).unwrap();
}
buf
}

@ -2,7 +2,7 @@
//! It is just a bridge to `rustc_lexer`.
use crate::{
SyntaxError, SyntaxErrorKind,
SyntaxError,
SyntaxKind::{self, *},
TextRange, TextUnit,
};
@ -41,13 +41,13 @@ pub fn tokenize(text: &str) -> (Vec<Token>, Vec<SyntaxError>) {
let token_len = TextUnit::from_usize(rustc_token.len);
let token_range = TextRange::offset_len(TextUnit::from_usize(offset), token_len);
let (syntax_kind, error) =
let (syntax_kind, err_message) =
rustc_token_kind_to_syntax_kind(&rustc_token.kind, &text[token_range]);
tokens.push(Token { kind: syntax_kind, len: token_len });
if let Some(error) = error {
errors.push(SyntaxError::new(SyntaxErrorKind::TokenizeError(error), token_range));
if let Some(err_message) = err_message {
errors.push(SyntaxError::new(err_message, token_range));
}
offset += rustc_token.len;
@ -94,61 +94,21 @@ fn lex_first_token(text: &str) -> Option<(Token, Option<SyntaxError>)> {
}
let rustc_token = rustc_lexer::first_token(text);
let (syntax_kind, error) = rustc_token_kind_to_syntax_kind(&rustc_token.kind, text);
let (syntax_kind, err_message) = rustc_token_kind_to_syntax_kind(&rustc_token.kind, text);
let token = Token { kind: syntax_kind, len: TextUnit::from_usize(rustc_token.len) };
let error = error.map(|error| {
SyntaxError::new(
SyntaxErrorKind::TokenizeError(error),
TextRange::from_to(TextUnit::from(0), TextUnit::of_str(text)),
)
let optional_error = err_message.map(|err_message| {
SyntaxError::new(err_message, TextRange::from_to(0.into(), TextUnit::of_str(text)))
});
Some((token, error))
}
// FIXME: simplify TokenizeError to `SyntaxError(String, TextRange)` as per @matklad advice:
// https://github.com/rust-analyzer/rust-analyzer/pull/2911/files#r371175067
/// Describes the values of `SyntaxErrorKind::TokenizeError` enum variant.
/// It describes all the types of errors that may happen during the tokenization
/// of Rust source.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum TokenizeError {
/// Base prefix was provided, but there were no digits
/// after it, e.g. `0x`, `0b`.
EmptyInt,
/// Float exponent lacks digits e.g. `12.34e+`, `12.3E+`, `12e-`, `1_E-`,
EmptyExponent,
/// Block comment lacks trailing delimiter `*/`
UnterminatedBlockComment,
/// Character literal lacks trailing delimiter `'`
UnterminatedChar,
/// Characterish byte literal lacks trailing delimiter `'`
UnterminatedByte,
/// String literal lacks trailing delimiter `"`
UnterminatedString,
/// Byte string literal lacks trailing delimiter `"`
UnterminatedByteString,
/// Raw literal lacks trailing delimiter e.g. `"##`
UnterminatedRawString,
/// Raw byte string literal lacks trailing delimiter e.g. `"##`
UnterminatedRawByteString,
/// Raw string lacks a quote after the pound characters e.g. `r###`
UnstartedRawString,
/// Raw byte string lacks a quote after the pound characters e.g. `br###`
UnstartedRawByteString,
/// Lifetime starts with a number e.g. `'4ever`
LifetimeStartsWithNumber,
Some((token, optional_error))
}
/// Returns `SyntaxKind` and an optional tokenize error message.
fn rustc_token_kind_to_syntax_kind(
rustc_token_kind: &rustc_lexer::TokenKind,
token_text: &str,
) -> (SyntaxKind, Option<TokenizeError>) {
) -> (SyntaxKind, Option<&'static str>) {
// A note on an intended tradeoff:
// We drop some useful infromation here (see patterns with double dots `..`)
// Storing that info in `SyntaxKind` is not possible due to its layout requirements of
@ -156,14 +116,15 @@ fn rustc_token_kind_to_syntax_kind(
let syntax_kind = {
use rustc_lexer::TokenKind as TK;
use TokenizeError as TE;
match rustc_token_kind {
TK::LineComment => COMMENT,
TK::BlockComment { terminated: true } => COMMENT,
TK::BlockComment { terminated: false } => {
return (COMMENT, Some(TE::UnterminatedBlockComment));
return (
COMMENT,
Some("Missing trailing `*/` symbols to terminate the block comment"),
);
}
TK::Whitespace => WHITESPACE,
@ -181,7 +142,7 @@ fn rustc_token_kind_to_syntax_kind(
TK::Lifetime { starts_with_number: false } => LIFETIME,
TK::Lifetime { starts_with_number: true } => {
return (LIFETIME, Some(TE::LifetimeStartsWithNumber))
return (LIFETIME, Some("Lifetime name cannot start with a number"))
}
TK::Semi => SEMI,
@ -217,57 +178,56 @@ fn rustc_token_kind_to_syntax_kind(
return (syntax_kind, None);
fn match_literal_kind(kind: &rustc_lexer::LiteralKind) -> (SyntaxKind, Option<TokenizeError>) {
fn match_literal_kind(kind: &rustc_lexer::LiteralKind) -> (SyntaxKind, Option<&'static str>) {
use rustc_lexer::LiteralKind as LK;
use TokenizeError as TE;
#[rustfmt::skip]
let syntax_kind = match *kind {
LK::Int { empty_int: false, .. } => INT_NUMBER,
LK::Int { empty_int: true, .. } => {
return (INT_NUMBER, Some(TE::EmptyInt))
return (INT_NUMBER, Some("Missing digits after the integer base prefix"))
}
LK::Float { empty_exponent: false, .. } => FLOAT_NUMBER,
LK::Float { empty_exponent: true, .. } => {
return (FLOAT_NUMBER, Some(TE::EmptyExponent))
return (FLOAT_NUMBER, Some("Missing digits after the exponent symbol"))
}
LK::Char { terminated: true } => CHAR,
LK::Char { terminated: false } => {
return (CHAR, Some(TE::UnterminatedChar))
return (CHAR, Some("Missing trailing `'` symbol to terminate the character literal"))
}
LK::Byte { terminated: true } => BYTE,
LK::Byte { terminated: false } => {
return (BYTE, Some(TE::UnterminatedByte))
return (BYTE, Some("Missing trailing `'` symbol to terminate the byte literal"))
}
LK::Str { terminated: true } => STRING,
LK::Str { terminated: false } => {
return (STRING, Some(TE::UnterminatedString))
return (STRING, Some("Missing trailing `\"` symbol to terminate the string literal"))
}
LK::ByteStr { terminated: true } => BYTE_STRING,
LK::ByteStr { terminated: false } => {
return (BYTE_STRING, Some(TE::UnterminatedByteString))
return (BYTE_STRING, Some("Missing trailing `\"` symbol to terminate the byte string literal"))
}
LK::RawStr { started: true, terminated: true, .. } => RAW_STRING,
LK::RawStr { started: true, terminated: false, .. } => {
return (RAW_STRING, Some(TE::UnterminatedRawString))
return (RAW_STRING, Some("Missing trailing `\"` with `#` symbols to terminate the raw string literal"))
}
LK::RawStr { started: false, .. } => {
return (RAW_STRING, Some(TE::UnstartedRawString))
return (RAW_STRING, Some("Missing `\"` symbol after `#` symbols to begin the raw string literal"))
}
LK::RawByteStr { started: true, terminated: true, .. } => RAW_BYTE_STRING,
LK::RawByteStr { started: true, terminated: false, .. } => {
return (RAW_BYTE_STRING, Some(TE::UnterminatedRawByteString))
return (RAW_BYTE_STRING, Some("Missing trailing `\"` with `#` symbols to terminate the raw byte string literal"))
}
LK::RawByteStr { started: false, .. } => {
return (RAW_BYTE_STRING, Some(TE::UnstartedRawByteString))
return (RAW_BYTE_STRING, Some("Missing `\"` symbol after `#` symbols to begin the raw byte string literal"))
}
};

@ -87,7 +87,7 @@ fn reparse_block<'node>(
edit: &AtomTextEdit,
) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
let (node, reparser) = find_reparsable_node(root, edit.delete)?;
let text = get_text_after_edit(node.clone().into(), &edit);
let text = get_text_after_edit(node.clone().into(), edit);
let (tokens, new_lexer_errors) = tokenize(&text);
if !is_balanced(&tokens) {
@ -162,20 +162,27 @@ fn is_balanced(tokens: &[Token]) -> bool {
fn merge_errors(
old_errors: Vec<SyntaxError>,
new_errors: Vec<SyntaxError>,
old_range: TextRange,
range_before_reparse: TextRange,
edit: &AtomTextEdit,
) -> Vec<SyntaxError> {
let mut res = Vec::new();
for e in old_errors {
if e.offset() <= old_range.start() {
res.push(e)
} else if e.offset() >= old_range.end() {
res.push(e.add_offset(TextUnit::of_str(&edit.insert), edit.delete.len()));
for old_err in old_errors {
let old_err_range = *old_err.range();
// FIXME: make sure that .start() was here previously by a mistake
if old_err_range.end() <= range_before_reparse.start() {
res.push(old_err);
} else if old_err_range.start() >= range_before_reparse.end() {
let inserted_len = TextUnit::of_str(&edit.insert);
res.push(old_err.with_range((old_err_range + inserted_len) - edit.delete.len()));
// Note: extra parens are intentional to prevent uint underflow, HWAB (here was a bug)
}
}
for e in new_errors {
res.push(e.add_offset(old_range.start(), 0.into()));
}
res.extend(new_errors.into_iter().map(|new_err| {
// fighting borrow checker with a variable ;)
let offseted_range = *new_err.range() + range_before_reparse.start();
new_err.with_range(offseted_range)
}));
res
}

@ -1,209 +1,47 @@
//! FIXME: write short doc here
//! Module that defines `SyntaxError`.
use std::fmt;
use ra_parser::ParseError;
use crate::{validation::EscapeError, TextRange, TextUnit, TokenizeError};
use crate::{TextRange, TextUnit};
/// Represents the result of unsuccessful tokenization, parsing
/// or semmantical analyzis.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SyntaxError {
kind: SyntaxErrorKind,
location: Location,
}
pub struct SyntaxError(String, TextRange);
// FIXME: Location should be just `Location(TextRange)`
// TextUnit enum member just unnecessarily compicates things,
// we should'n treat it specially, it just as a `TextRange { start: x, end: x + 1 }`
// see `location_to_range()` in ra_ide/src/diagnostics
#[derive(Clone, PartialEq, Eq, Hash)]
pub enum Location {
Offset(TextUnit),
Range(TextRange),
}
impl From<TextUnit> for Location {
fn from(offset: TextUnit) -> Location {
Location::Offset(offset)
}
}
impl From<TextRange> for Location {
fn from(range: TextRange) -> Location {
Location::Range(range)
}
}
impl fmt::Debug for Location {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Location::Offset(it) => fmt::Debug::fmt(it, f),
Location::Range(it) => fmt::Debug::fmt(it, f),
}
}
}
// FIXME: there was an unused SyntaxErrorKind previously (before this enum was removed)
// It was introduced in this PR: https://github.com/rust-analyzer/rust-analyzer/pull/846/files#diff-827da9b03b8f9faa1bade5cdd44d5dafR95
// but it was not removed by a mistake.
//
// So, we need to find a place where to stick validation for attributes in match clauses.
// Code before refactor:
// InvalidMatchInnerAttr => {
// write!(f, "Inner attributes are only allowed directly after the opening brace of the match expression")
// }
impl SyntaxError {
pub fn new<L: Into<Location>>(kind: SyntaxErrorKind, loc: L) -> SyntaxError {
SyntaxError { kind, location: loc.into() }
pub fn new(message: impl Into<String>, range: TextRange) -> Self {
Self(message.into(), range)
}
pub fn new_at_offset(message: impl Into<String>, offset: TextUnit) -> Self {
Self(message.into(), TextRange::offset_len(offset, 1.into()))
}
pub fn kind(&self) -> SyntaxErrorKind {
self.kind.clone()
pub fn message(&self) -> &str {
&self.0
}
pub fn range(&self) -> &TextRange {
&self.1
}
pub fn location(&self) -> Location {
self.location.clone()
}
pub fn offset(&self) -> TextUnit {
match self.location {
Location::Offset(offset) => offset,
Location::Range(range) => range.start(),
}
}
pub fn add_offset(mut self, plus_offset: TextUnit, minus_offset: TextUnit) -> SyntaxError {
self.location = match self.location {
Location::Range(range) => Location::Range(range + plus_offset - minus_offset),
Location::Offset(offset) => Location::Offset(offset + plus_offset - minus_offset),
};
pub fn with_range(mut self, range: TextRange) -> Self {
self.1 = range;
self
}
pub fn debug_dump(&self, acc: &mut impl fmt::Write) {
writeln!(acc, "error {:?}: {}", self.location(), self.kind()).unwrap();
}
}
impl fmt::Display for SyntaxError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.kind.fmt(f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum SyntaxErrorKind {
ParseError(ParseError),
EscapeError(EscapeError),
TokenizeError(TokenizeError),
// FIXME: the obvious pattern of this enum dictates that the following enum variants
// should be wrapped into something like `SemmanticError(SemmanticError)`
// or `ValidateError(ValidateError)` or `SemmanticValidateError(...)`
InvalidBlockAttr,
InvalidMatchInnerAttr,
InvalidTupleIndexFormat,
VisibilityNotAllowed,
InclusiveRangeMissingEnd,
}
impl fmt::Display for SyntaxErrorKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::SyntaxErrorKind::*;
match self {
InvalidBlockAttr => {
write!(f, "A block in this position cannot accept inner attributes")
}
InvalidMatchInnerAttr => {
write!(f, "Inner attributes are only allowed directly after the opening brace of the match expression")
}
InvalidTupleIndexFormat => {
write!(f, "Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix")
}
ParseError(msg) => write!(f, "{}", msg.0),
EscapeError(err) => write!(f, "{}", err),
TokenizeError(err) => write!(f, "{}", err),
VisibilityNotAllowed => {
write!(f, "unnecessary visibility qualifier")
}
InclusiveRangeMissingEnd => {
write!(f, "An inclusive range must have an end expression")
}
}
}
}
impl fmt::Display for TokenizeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[rustfmt::skip]
let msg = match self {
TokenizeError::EmptyInt => {
"Missing digits after the integer base prefix"
}
TokenizeError::EmptyExponent => {
"Missing digits after the exponent symbol"
}
TokenizeError::UnterminatedBlockComment => {
"Missing trailing `*/` symbols to terminate the block comment"
}
TokenizeError::UnterminatedChar => {
"Missing trailing `'` symbol to terminate the character literal"
}
TokenizeError::UnterminatedByte => {
"Missing trailing `'` symbol to terminate the byte literal"
}
TokenizeError::UnterminatedString => {
"Missing trailing `\"` symbol to terminate the string literal"
}
TokenizeError::UnterminatedByteString => {
"Missing trailing `\"` symbol to terminate the byte string literal"
}
TokenizeError::UnterminatedRawString => {
"Missing trailing `\"` with `#` symbols to terminate the raw string literal"
}
TokenizeError::UnterminatedRawByteString => {
"Missing trailing `\"` with `#` symbols to terminate the raw byte string literal"
}
TokenizeError::UnstartedRawString => {
"Missing `\"` symbol after `#` symbols to begin the raw string literal"
}
TokenizeError::UnstartedRawByteString => {
"Missing `\"` symbol after `#` symbols to begin the raw byte string literal"
}
TokenizeError::LifetimeStartsWithNumber => {
"Lifetime name cannot start with a number"
}
};
write!(f, "{}", msg)
}
}
impl fmt::Display for EscapeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let msg = match self {
EscapeError::ZeroChars => "Empty literal",
EscapeError::MoreThanOneChar => "Literal should be one character long",
EscapeError::LoneSlash => "Character must be escaped: '\\'",
EscapeError::InvalidEscape => "Invalid escape sequence",
EscapeError::BareCarriageReturn => "Character must be escaped: '\r'",
EscapeError::EscapeOnlyChar => "Character must be escaped",
EscapeError::TooShortHexEscape => "Escape sequence should have two digits",
EscapeError::InvalidCharInHexEscape => "Escape sequence should be a hexadecimal number",
EscapeError::OutOfRangeHexEscape => "Escape sequence should be ASCII",
EscapeError::NoBraceInUnicodeEscape => "Invalid escape sequence",
EscapeError::InvalidCharInUnicodeEscape => "Invalid escape sequence",
EscapeError::EmptyUnicodeEscape => "Invalid escape sequence",
EscapeError::UnclosedUnicodeEscape => "Missing '}'",
EscapeError::LeadingUnderscoreUnicodeEscape => "Invalid escape sequence",
EscapeError::OverlongUnicodeEscape => {
"Unicode escape sequence should have at most 6 digits"
}
EscapeError::LoneSurrogateUnicodeEscape => {
"Unicode escape code should not be a surrogate"
}
EscapeError::OutOfRangeUnicodeEscape => {
"Unicode escape code should be at most 0x10FFFF"
}
EscapeError::UnicodeEscapeInByte => "Unicode escapes are not allowed in bytes",
EscapeError::NonAsciiCharInByte => "Non ASCII characters are not allowed in bytes",
};
write!(f, "{}", msg)
}
}
impl From<EscapeError> for SyntaxErrorKind {
fn from(err: EscapeError) -> Self {
SyntaxErrorKind::EscapeError(err)
self.0.fmt(f)
}
}

@ -6,15 +6,10 @@
//! The *real* implementation is in the (language-agnostic) `rowan` crate, this
//! module just wraps its API.
use ra_parser::ParseError;
pub(crate) use rowan::{GreenNode, GreenToken};
use rowan::{GreenNodeBuilder, Language};
use crate::{
syntax_error::{SyntaxError, SyntaxErrorKind},
Parse, SmolStr, SyntaxKind, TextUnit,
};
pub(crate) use rowan::{GreenNode, GreenToken};
use crate::{Parse, SmolStr, SyntaxError, SyntaxKind, TextUnit};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum RustLanguage {}
@ -73,8 +68,7 @@ impl SyntaxTreeBuilder {
self.inner.finish_node()
}
pub fn error(&mut self, error: ParseError, text_pos: TextUnit) {
let error = SyntaxError::new(SyntaxErrorKind::ParseError(error), text_pos);
self.errors.push(error)
pub fn error(&mut self, error: ra_parser::ParseError, text_pos: TextUnit) {
self.errors.push(SyntaxError::new_at_offset(error.0, text_pos))
}
}

@ -5,7 +5,7 @@ use std::{
use test_utils::{collect_tests, dir_tests, project_dir, read_text};
use crate::{fuzz, tokenize, Location, SourceFile, SyntaxError, TextRange, Token};
use crate::{fuzz, tokenize, SourceFile, SyntaxError, Token};
#[test]
fn lexer_tests() {
@ -128,25 +128,14 @@ fn dump_tokens_and_errors(tokens: &[Token], errors: &[SyntaxError], text: &str)
writeln!(acc, "{:?} {} {:?}", token.kind, token_len, token_text).unwrap();
}
for err in errors {
let err_range = location_to_range(err.location());
writeln!(
acc,
"> error{:?} token({:?}) msg({})",
err.location(),
&text[err_range],
err.kind()
err.range(),
&text[*err.range()],
err.message()
)
.unwrap();
}
return acc;
// FIXME: copy-pasted this from `ra_ide/src/diagnostics.rs`
// `Location` will be refactored soon in new PR, see todos here:
// https://github.com/rust-analyzer/rust-analyzer/issues/223
fn location_to_range(location: Location) -> TextRange {
match location {
Location::Offset(offset) => TextRange::offset_len(offset, 1.into()),
Location::Range(range) => range,
}
}
acc
}

@ -5,92 +5,76 @@ mod block;
use rustc_lexer::unescape;
use crate::{
ast, match_ast, AstNode, SyntaxError, SyntaxErrorKind,
ast, match_ast, AstNode, SyntaxError,
SyntaxKind::{BYTE, BYTE_STRING, CHAR, CONST_DEF, FN_DEF, INT_NUMBER, STRING, TYPE_ALIAS_DEF},
SyntaxNode, SyntaxToken, TextUnit, T,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum EscapeError {
ZeroChars,
MoreThanOneChar,
LoneSlash,
InvalidEscape,
BareCarriageReturn,
EscapeOnlyChar,
TooShortHexEscape,
InvalidCharInHexEscape,
OutOfRangeHexEscape,
NoBraceInUnicodeEscape,
InvalidCharInUnicodeEscape,
EmptyUnicodeEscape,
UnclosedUnicodeEscape,
LeadingUnderscoreUnicodeEscape,
OverlongUnicodeEscape,
LoneSurrogateUnicodeEscape,
OutOfRangeUnicodeEscape,
UnicodeEscapeInByte,
NonAsciiCharInByte,
}
fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> &'static str {
use unescape::EscapeError as EE;
impl From<rustc_lexer::unescape::EscapeError> for EscapeError {
fn from(err: rustc_lexer::unescape::EscapeError) -> Self {
match err {
rustc_lexer::unescape::EscapeError::ZeroChars => EscapeError::ZeroChars,
rustc_lexer::unescape::EscapeError::MoreThanOneChar => EscapeError::MoreThanOneChar,
rustc_lexer::unescape::EscapeError::LoneSlash => EscapeError::LoneSlash,
rustc_lexer::unescape::EscapeError::InvalidEscape => EscapeError::InvalidEscape,
rustc_lexer::unescape::EscapeError::BareCarriageReturn
| rustc_lexer::unescape::EscapeError::BareCarriageReturnInRawString => {
EscapeError::BareCarriageReturn
}
rustc_lexer::unescape::EscapeError::EscapeOnlyChar => EscapeError::EscapeOnlyChar,
rustc_lexer::unescape::EscapeError::TooShortHexEscape => EscapeError::TooShortHexEscape,
rustc_lexer::unescape::EscapeError::InvalidCharInHexEscape => {
EscapeError::InvalidCharInHexEscape
}
rustc_lexer::unescape::EscapeError::OutOfRangeHexEscape => {
EscapeError::OutOfRangeHexEscape
}
rustc_lexer::unescape::EscapeError::NoBraceInUnicodeEscape => {
EscapeError::NoBraceInUnicodeEscape
}
rustc_lexer::unescape::EscapeError::InvalidCharInUnicodeEscape => {
EscapeError::InvalidCharInUnicodeEscape
}
rustc_lexer::unescape::EscapeError::EmptyUnicodeEscape => {
EscapeError::EmptyUnicodeEscape
}
rustc_lexer::unescape::EscapeError::UnclosedUnicodeEscape => {
EscapeError::UnclosedUnicodeEscape
}
rustc_lexer::unescape::EscapeError::LeadingUnderscoreUnicodeEscape => {
EscapeError::LeadingUnderscoreUnicodeEscape
}
rustc_lexer::unescape::EscapeError::OverlongUnicodeEscape => {
EscapeError::OverlongUnicodeEscape
}
rustc_lexer::unescape::EscapeError::LoneSurrogateUnicodeEscape => {
EscapeError::LoneSurrogateUnicodeEscape
}
rustc_lexer::unescape::EscapeError::OutOfRangeUnicodeEscape => {
EscapeError::OutOfRangeUnicodeEscape
}
rustc_lexer::unescape::EscapeError::UnicodeEscapeInByte => {
EscapeError::UnicodeEscapeInByte
}
rustc_lexer::unescape::EscapeError::NonAsciiCharInByte
| rustc_lexer::unescape::EscapeError::NonAsciiCharInByteString => {
EscapeError::NonAsciiCharInByte
}
#[rustfmt::skip]
let err_message = match err {
EE::ZeroChars => {
"Literal must not be empty"
}
}
}
EE::MoreThanOneChar => {
"Literal must be one character long"
}
EE::LoneSlash => {
"Character must be escaped: `\\`"
}
EE::InvalidEscape => {
"Invalid escape"
}
EE::BareCarriageReturn | EE::BareCarriageReturnInRawString => {
"Character must be escaped: `\r`"
}
EE::EscapeOnlyChar => {
"Escape character `\\` must be escaped itself"
}
EE::TooShortHexEscape => {
"ASCII hex escape code must have exactly two digits"
}
EE::InvalidCharInHexEscape => {
"ASCII hex escape code must contain only hex characters"
}
EE::OutOfRangeHexEscape => {
"ASCII hex escape code must be at most 0x7F"
}
EE::NoBraceInUnicodeEscape => {
"Missing `{` to begin the unicode escape"
}
EE::InvalidCharInUnicodeEscape => {
"Unicode escape must contain only hex characters and underscores"
}
EE::EmptyUnicodeEscape => {
"Unicode escape must not be empty"
}
EE::UnclosedUnicodeEscape => {
"Missing '}' to terminate the unicode escape"
}
EE::LeadingUnderscoreUnicodeEscape => {
"Unicode escape code must not begin with an underscore"
}
EE::OverlongUnicodeEscape => {
"Unicode escape code must have at most 6 digits"
}
EE::LoneSurrogateUnicodeEscape => {
"Unicode escape code must not be a surrogate"
}
EE::OutOfRangeUnicodeEscape => {
"Unicode escape code must be at most 0x10FFFF"
}
EE::UnicodeEscapeInByte => {
"Byte literals must not contain unicode escapes"
}
EE::NonAsciiCharInByte | EE::NonAsciiCharInByteString => {
"Byte literals must not contain non-ASCII characters"
}
};
impl From<rustc_lexer::unescape::EscapeError> for SyntaxErrorKind {
fn from(err: rustc_lexer::unescape::EscapeError) -> Self {
SyntaxErrorKind::EscapeError(err.into())
}
err_message
}
pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
@ -118,6 +102,7 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
}
fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
// FIXME: move this function to outer scope (https://github.com/rust-analyzer/rust-analyzer/pull/2834#discussion_r366196658)
fn unquote(text: &str, prefix_len: usize, end_delimiter: char) -> Option<&str> {
text.rfind(end_delimiter).and_then(|end| text.get(prefix_len..end))
}
@ -125,9 +110,10 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
let token = literal.token();
let text = token.text().as_str();
// FIXME: lift this lambda refactor to `fn` (https://github.com/rust-analyzer/rust-analyzer/pull/2834#discussion_r366199205)
let mut push_err = |prefix_len, (off, err): (usize, unescape::EscapeError)| {
let off = token.text_range().start() + TextUnit::from_usize(off + prefix_len);
acc.push(SyntaxError::new(err.into(), off));
acc.push(SyntaxError::new_at_offset(rustc_unescape_error_to_string(err), off));
};
match token.kind() {
@ -195,7 +181,8 @@ fn validate_numeric_name(name_ref: Option<ast::NameRef>, errors: &mut Vec<Syntax
if let Some(int_token) = int_token(name_ref) {
if int_token.text().chars().any(|c| !c.is_digit(10)) {
errors.push(SyntaxError::new(
SyntaxErrorKind::InvalidTupleIndexFormat,
"Tuple (struct) field access is only allowed through \
decimal integers with no underscores or suffix",
int_token.text_range(),
));
}
@ -215,21 +202,21 @@ fn validate_visibility(vis: ast::Visibility, errors: &mut Vec<SyntaxError>) {
FN_DEF | CONST_DEF | TYPE_ALIAS_DEF => (),
_ => return,
}
let impl_block = match parent.parent().and_then(|it| it.parent()).and_then(ast::ImplBlock::cast)
{
Some(it) => it,
None => return,
};
if impl_block.target_trait().is_some() {
errors
.push(SyntaxError::new(SyntaxErrorKind::VisibilityNotAllowed, vis.syntax.text_range()))
errors.push(SyntaxError::new("Unnecessary visibility qualifier", vis.syntax.text_range()));
}
}
fn validate_range_expr(expr: ast::RangeExpr, errors: &mut Vec<SyntaxError>) {
if expr.op_kind() == Some(ast::RangeOp::Inclusive) && expr.end().is_none() {
errors.push(SyntaxError::new(
SyntaxErrorKind::InclusiveRangeMissingEnd,
"An inclusive range must have an end expression",
expr.syntax().text_range(),
));
}

@ -1,9 +1,8 @@
//! FIXME: write short doc here
//! Logic for validating block expressions i.e. `ast::BlockExpr`.
use crate::{
ast::{self, AstNode, AttrsOwner},
SyntaxError,
SyntaxErrorKind::*,
SyntaxKind::*,
};
@ -15,10 +14,11 @@ pub(crate) fn validate_block_expr(expr: ast::BlockExpr, errors: &mut Vec<SyntaxE
}
}
if let Some(block) = expr.block() {
errors.extend(
block
.attrs()
.map(|attr| SyntaxError::new(InvalidBlockAttr, attr.syntax().text_range())),
)
errors.extend(block.attrs().map(|attr| {
SyntaxError::new(
"A block in this position cannot accept inner attributes",
attr.syntax().text_range(),
)
}))
}
}

@ -31,4 +31,4 @@ SOURCE_FILE@[0; 34)
IDENT@[29; 32) "u32"
WHITESPACE@[32; 33) "\n"
R_CURLY@[33; 34) "}"
error 21: expected COMMA
error [21; 22): expected COMMA

@ -14,5 +14,5 @@ SOURCE_FILE@[0; 21)
RECORD_FIELD_DEF_LIST@[19; 21)
L_CURLY@[19; 20) "{"
R_CURLY@[20; 21) "}"
error 0: expected an item
error 3: expected an item
error [0; 1): expected an item
error [3; 4): expected an item

@ -26,14 +26,14 @@ SOURCE_FILE@[0; 42)
NAME@[36; 41)
IDENT@[36; 41) "rusti"
WHITESPACE@[41; 42) "\n"
error 23: expected `[`
error 23: expected an item
error 27: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
error 28: expected SEMI
error 31: expected EXCL
error 31: expected `{`, `[`, `(`
error 31: expected SEMI
error 31: expected an item
error 35: expected EXCL
error 41: expected `{`, `[`, `(`
error 41: expected SEMI
error [23; 24): expected `[`
error [23; 24): expected an item
error [27; 28): expected one of `*`, `::`, `{`, `self`, `super` or an identifier
error [28; 29): expected SEMI
error [31; 32): expected EXCL
error [31; 32): expected `{`, `[`, `(`
error [31; 32): expected SEMI
error [31; 32): expected an item
error [35; 36): expected EXCL
error [41; 42): expected `{`, `[`, `(`
error [41; 42): expected SEMI

@ -35,5 +35,5 @@ SOURCE_FILE@[0; 40)
R_CURLY@[38; 39) "}"
ERROR@[39; 40)
SEMI@[39; 40) ";"
error 39: expected item, found `;`
error [39; 40): expected item, found `;`
consider removing this semicolon

@ -13,4 +13,4 @@ SOURCE_FILE@[0; 12)
ERROR@[9; 11)
INT_NUMBER@[9; 11) "92"
SEMI@[11; 12) ";"
error 9: expected identifier
error [9; 10): expected identifier

@ -55,6 +55,6 @@ SOURCE_FILE@[0; 54)
WHITESPACE@[51; 52) "\n"
R_CURLY@[52; 53) "}"
WHITESPACE@[53; 54) "\n"
error 53: expected R_PAREN
error 53: expected `]`
error 53: expected an item
error [53; 54): expected R_PAREN
error [53; 54): expected `]`
error [53; 54): expected an item

@ -64,11 +64,11 @@ SOURCE_FILE@[0; 74)
WHITESPACE@[71; 72) "\n"
R_CURLY@[72; 73) "}"
WHITESPACE@[73; 74) "\n"
error 31: expected field declaration
error 33: expected COMMA
error 38: expected field declaration
error 39: expected COMMA
error 40: expected field declaration
error 41: expected COMMA
error 42: expected field declaration
error 43: expected COMMA
error [31; 32): expected field declaration
error [33; 34): expected COMMA
error [38; 39): expected field declaration
error [39; 40): expected COMMA
error [40; 41): expected field declaration
error [41; 42): expected COMMA
error [42; 43): expected field declaration
error [43; 44): expected COMMA

@ -28,6 +28,6 @@ SOURCE_FILE@[0; 31)
ERROR@[29; 30)
R_CURLY@[29; 30) "}"
WHITESPACE@[30; 31) "\n"
error 0: unmatched `}`
error 14: unmatched `}`
error 29: unmatched `}`
error [0; 1): unmatched `}`
error [14; 15): unmatched `}`
error [29; 30): unmatched `}`

@ -76,6 +76,6 @@ SOURCE_FILE@[0; 95)
WHITESPACE@[92; 93) "\n"
R_CURLY@[93; 94) "}"
WHITESPACE@[94; 95) "\n"
error 17: expected EXCL
error 19: expected SEMI
error 20: expected an item
error [17; 18): expected EXCL
error [19; 20): expected SEMI
error [20; 21): expected an item

@ -45,14 +45,14 @@ SOURCE_FILE@[0; 43)
IDENT@[40; 41) "T"
SEMI@[41; 42) ";"
WHITESPACE@[42; 43) "\n"
error 9: expected type parameter
error 11: expected COMMA
error 11: expected R_ANGLE
error 11: expected `;`, `{`, or `(`
error 12: expected an item
error 14: expected an item
error 15: expected an item
error 17: expected an item
error 24: expected SEMI
error 24: expected expression
error 25: expected SEMI
error [9; 10): expected type parameter
error [11; 12): expected COMMA
error [11; 12): expected R_ANGLE
error [11; 12): expected `;`, `{`, or `(`
error [12; 13): expected an item
error [14; 15): expected an item
error [15; 16): expected an item
error [17; 18): expected an item
error [24; 25): expected SEMI
error [24; 25): expected expression
error [25; 26): expected SEMI

@ -40,4 +40,4 @@ SOURCE_FILE@[0; 42)
WHITESPACE@[39; 40) "\n"
R_CURLY@[40; 41) "}"
WHITESPACE@[41; 42) "\n"
error 24: expected `{`
error [24; 25): expected `{`

@ -10,4 +10,4 @@ SOURCE_FILE@[0; 19)
IDENT@[14; 17) "Foo"
SEMI@[17; 18) ";"
WHITESPACE@[18; 19) "\n"
error 6: expected existential, fn, trait or impl
error [6; 7): expected existential, fn, trait or impl

@ -69,21 +69,21 @@ SOURCE_FILE@[0; 86)
ERROR@[83; 84)
SEMI@[83; 84) ";"
WHITESPACE@[84; 86) "\n\n"
error 67: expected type
error 68: expected COMMA
error 68: expected R_ANGLE
error 68: expected COMMA
error 68: expected R_ANGLE
error 68: expected COMMA
error 68: expected R_ANGLE
error 68: expected COMMA
error 72: expected COMMA
error 72: expected a type
error 72: expected R_PAREN
error 72: expected SEMI
error 72: expected an item
error 73: expected an item
error 79: expected an item
error 80: expected an item
error 82: expected an item
error 83: expected an item
error [67; 68): expected type
error [68; 69): expected COMMA
error [68; 69): expected R_ANGLE
error [68; 69): expected COMMA
error [68; 69): expected R_ANGLE
error [68; 69): expected COMMA
error [68; 69): expected R_ANGLE
error [68; 69): expected COMMA
error [72; 73): expected COMMA
error [72; 73): expected a type
error [72; 73): expected R_PAREN
error [72; 73): expected SEMI
error [72; 73): expected an item
error [73; 74): expected an item
error [79; 80): expected an item
error [80; 81): expected an item
error [82; 83): expected an item
error [83; 84): expected an item

@ -29,4 +29,4 @@ SOURCE_FILE@[0; 23)
L_CURLY@[20; 21) "{"
R_CURLY@[21; 22) "}"
WHITESPACE@[22; 23) "\n"
error 19: expected colon
error [19; 20): expected colon

@ -16,9 +16,9 @@ SOURCE_FILE@[0; 14)
WHITESPACE@[11; 12) "\n"
R_CURLY@[12; 13) "}"
WHITESPACE@[13; 14) "\n"
error 7: expected value parameter
error 7: expected R_PAREN
error 7: expected a block
error 7: unmatched `}`
error 8: expected an item
error 10: expected an item
error [7; 8): expected value parameter
error [7; 8): expected R_PAREN
error [7; 8): expected a block
error [7; 8): unmatched `}`
error [8; 9): expected an item
error [10; 11): expected an item

@ -41,4 +41,4 @@ SOURCE_FILE@[0; 56)
WHITESPACE@[53; 54) "\n"
R_CURLY@[54; 55) "}"
WHITESPACE@[55; 56) "\n"
error 38: expected SEMI
error [38; 39): expected SEMI

@ -44,4 +44,4 @@ SOURCE_FILE@[0; 47)
WHITESPACE@[44; 45) "\n"
R_CURLY@[45; 46) "}"
WHITESPACE@[46; 47) "\n"
error 44: expected expression
error [44; 45): expected expression

@ -125,8 +125,8 @@ SOURCE_FILE@[0; 183)
WHITESPACE@[180; 181) "\n"
R_CURLY@[181; 182) "}"
WHITESPACE@[182; 183) "\n"
error 34: expected pattern
error 34: expected COLON
error 34: expected type
error 180: expected function arguments
error 180: expected a block
error [34; 35): expected pattern
error [34; 35): expected COLON
error [34; 35): expected type
error [180; 181): expected function arguments
error [180; 181): expected a block

@ -95,13 +95,13 @@ SOURCE_FILE@[0; 139)
WHITESPACE@[136; 137) "\n"
R_CURLY@[137; 138) "}"
WHITESPACE@[138; 139) "\n"
error 24: expected expression
error 24: expected SEMI
error 49: expected pattern
error 49: expected SEMI
error 75: expected pattern
error 75: expected SEMI
error 98: expected pattern
error 98: expected SEMI
error 124: expected pattern
error 124: expected SEMI
error [24; 25): expected expression
error [24; 25): expected SEMI
error [49; 50): expected pattern
error [49; 50): expected SEMI
error [75; 76): expected pattern
error [75; 76): expected SEMI
error [98; 99): expected pattern
error [98; 99): expected SEMI
error [124; 125): expected pattern
error [124; 125): expected SEMI

@ -16,6 +16,6 @@ SOURCE_FILE@[0; 16)
L_CURLY@[13; 14) "{"
R_CURLY@[14; 15) "}"
WHITESPACE@[15; 16) "\n"
error 2: expected a name
error 2: expected function arguments
error 2: expected a block
error [2; 3): expected a name
error [2; 3): expected function arguments
error [2; 3): expected a block

@ -31,5 +31,5 @@ SOURCE_FILE@[0; 22)
WHITESPACE@[19; 20) "\n"
R_CURLY@[20; 21) "}"
WHITESPACE@[21; 22) "\n"
error 16: expected COLON
error 16: expected type
error [16; 17): expected COLON
error [16; 17): expected type

@ -148,36 +148,36 @@ SOURCE_FILE@[0; 112)
WHITESPACE@[109; 110) " "
R_CURLY@[110; 111) "}"
WHITESPACE@[111; 112) "\n"
error 16: expected expression
error 17: expected R_BRACK
error 17: expected SEMI
error 17: expected expression
error 18: expected SEMI
error 25: expected a name
error 26: expected `;`, `{`, or `(`
error 30: expected pattern
error 31: expected SEMI
error 53: expected expression
error 54: expected SEMI
error 54: expected expression
error 55: expected SEMI
error 60: expected type
error 60: expected `{`
error 60: expected expression
error 61: expected SEMI
error 65: expected pattern
error 65: expected SEMI
error 65: expected expression
error 92: expected expression
error 93: expected SEMI
error 93: expected expression
error 94: expected SEMI
error 95: expected expression
error 96: expected SEMI
error 96: expected expression
error 97: expected SEMI
error 103: expected a name
error 104: expected `{`
error 108: expected pattern
error 108: expected SEMI
error 108: expected expression
error [16; 17): expected expression
error [17; 18): expected R_BRACK
error [17; 18): expected SEMI
error [17; 18): expected expression
error [18; 19): expected SEMI
error [25; 26): expected a name
error [26; 27): expected `;`, `{`, or `(`
error [30; 31): expected pattern
error [31; 32): expected SEMI
error [53; 54): expected expression
error [54; 55): expected SEMI
error [54; 55): expected expression
error [55; 56): expected SEMI
error [60; 61): expected type
error [60; 61): expected `{`
error [60; 61): expected expression
error [61; 62): expected SEMI
error [65; 66): expected pattern
error [65; 66): expected SEMI
error [65; 66): expected expression
error [92; 93): expected expression
error [93; 94): expected SEMI
error [93; 94): expected expression
error [94; 95): expected SEMI
error [95; 96): expected expression
error [96; 97): expected SEMI
error [96; 97): expected expression
error [97; 98): expected SEMI
error [103; 104): expected a name
error [104; 105): expected `{`
error [108; 109): expected pattern
error [108; 109): expected SEMI
error [108; 109): expected expression

@ -40,5 +40,5 @@ SOURCE_FILE@[0; 94)
ERROR@[92; 93)
R_CURLY@[92; 93) "}"
WHITESPACE@[93; 94) "\n"
error 49: unmatched `}`
error 92: unmatched `}`
error [49; 50): unmatched `}`
error [92; 93): unmatched `}`

@ -290,32 +290,32 @@ SOURCE_FILE@[0; 240)
WHITESPACE@[237; 238) "\n"
R_CURLY@[238; 239) "}"
WHITESPACE@[239; 240) "\n"
error 88: expected COMMA
error 88: expected R_ANGLE
error 121: expected SEMI
error 121: expected expression
error 140: expected type
error 141: expected R_PAREN
error 141: expected COMMA
error 141: expected R_ANGLE
error 141: expected SEMI
error 146: expected SEMI
error 146: expected expression
error 147: expected SEMI
error 148: expected expression
error 149: expected SEMI
error 154: expected pattern
error 155: expected IN_KW
error 155: expected expression
error 157: expected a block
error 165: expected expression
error 168: expected expression
error 179: expected expression
error 180: expected COMMA
error 180: expected expression
error 180: expected R_PAREN
error 180: expected SEMI
error 215: expected COMMA
error 215: expected R_ANGLE
error 235: expected SEMI
error 235: expected expression
error [88; 89): expected COMMA
error [88; 89): expected R_ANGLE
error [121; 122): expected SEMI
error [121; 122): expected expression
error [140; 141): expected type
error [141; 142): expected R_PAREN
error [141; 142): expected COMMA
error [141; 142): expected R_ANGLE
error [141; 142): expected SEMI
error [146; 147): expected SEMI
error [146; 147): expected expression
error [147; 148): expected SEMI
error [148; 149): expected expression
error [149; 150): expected SEMI
error [154; 155): expected pattern
error [155; 156): expected IN_KW
error [155; 156): expected expression
error [157; 158): expected a block
error [165; 166): expected expression
error [168; 169): expected expression
error [179; 180): expected expression
error [180; 181): expected COMMA
error [180; 181): expected expression
error [180; 181): expected R_PAREN
error [180; 181): expected SEMI
error [215; 216): expected COMMA
error [215; 216): expected R_ANGLE
error [235; 236): expected SEMI
error [235; 236): expected expression

@ -191,14 +191,14 @@ SOURCE_FILE@[0; 575)
WHITESPACE@[572; 573) "\n"
R_CURLY@[573; 574) "}"
WHITESPACE@[574; 575) "\n"
error 95: expected type
error 95: expected COMMA
error 96: expected field
error 98: expected field declaration
error 371: expected COMMA
error 372: expected a type
error 372: expected R_PAREN
error 372: expected COMMA
error 372: expected enum variant
error 374: expected enum variant
error 508: expected expression
error [95; 96): expected type
error [95; 96): expected COMMA
error [96; 97): expected field
error [98; 99): expected field declaration
error [371; 372): expected COMMA
error [372; 373): expected a type
error [372; 373): expected R_PAREN
error [372; 373): expected COMMA
error [372; 373): expected enum variant
error [374; 375): expected enum variant
error [508; 509): expected expression

@ -45,5 +45,5 @@ SOURCE_FILE@[0; 38)
L_CURLY@[35; 36) "{"
R_CURLY@[36; 37) "}"
WHITESPACE@[37; 38) "\n"
error 14: expected trait or type
error 14: expected `{`
error [14; 15): expected trait or type
error [14; 15): expected `{`

@ -25,5 +25,5 @@ SOURCE_FILE@[0; 30)
L_CURLY@[27; 28) "{"
R_CURLY@[28; 29) "}"
WHITESPACE@[29; 30) "\n"
error 26: expected a path
error 26: expected colon
error [26; 27): expected a path
error [26; 27): expected colon

@ -33,4 +33,4 @@ SOURCE_FILE@[0; 24)
WHITESPACE@[21; 22) "\n"
R_CURLY@[22; 23) "}"
WHITESPACE@[23; 24) "\n"
error 21: expected field name or number
error [21; 22): expected field name or number

@ -191,14 +191,14 @@ SOURCE_FILE@[0; 293)
WHITESPACE@[290; 291) "\n"
R_CURLY@[291; 292) "}"
WHITESPACE@[292; 293) "\n"
error 52: expected `[`
error 52: expected pattern
error 53: expected FAT_ARROW
error 78: expected COMMA
error 161: expected `[`
error 161: expected pattern
error 162: expected FAT_ARROW
error 232: expected `[`
error 232: expected pattern
error 233: expected FAT_ARROW
error 250: expected COMMA
error [52; 53): expected `[`
error [52; 53): expected pattern
error [53; 54): expected FAT_ARROW
error [78; 79): expected COMMA
error [161; 162): expected `[`
error [161; 162): expected pattern
error [162; 163): expected FAT_ARROW
error [232; 233): expected `[`
error [232; 233): expected pattern
error [233; 234): expected FAT_ARROW
error [250; 251): expected COMMA

@ -62,6 +62,6 @@ SOURCE_FILE@[0; 89)
WHITESPACE@[86; 87) "\n"
R_CURLY@[87; 88) "}"
WHITESPACE@[88; 89) "\n"
error 80: expected pattern
error 80: expected FAT_ARROW
error 80: expected expression
error [80; 81): expected pattern
error [80; 81): expected FAT_ARROW
error [80; 81): expected expression

@ -88,9 +88,9 @@ SOURCE_FILE@[0; 91)
WHITESPACE@[87; 88) "\n"
R_CURLY@[88; 89) "}"
WHITESPACE@[89; 91) "\n\n"
error 24: expected a name
error 27: expected SEMI
error 48: expected a name
error 51: expected SEMI
error 76: expected a name
error 79: expected SEMI
error [24; 25): expected a name
error [27; 28): expected SEMI
error [48; 49): expected a name
error [51; 52): expected SEMI
error [76; 77): expected a name
error [79; 80): expected SEMI

@ -48,7 +48,7 @@ SOURCE_FILE@[0; 48)
L_CURLY@[45; 46) "{"
R_CURLY@[46; 47) "}"
WHITESPACE@[47; 48) "\n"
error 17: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
error 17: expected SEMI
error 37: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
error 37: expected SEMI
error [17; 18): expected one of `*`, `::`, `{`, `self`, `super` or an identifier
error [17; 18): expected SEMI
error [37; 38): expected one of `*`, `::`, `{`, `self`, `super` or an identifier
error [37; 38): expected SEMI

@ -39,13 +39,13 @@ SOURCE_FILE@[0; 37)
ERROR@[35; 36)
SEMI@[35; 36) ";"
WHITESPACE@[36; 37) "\n"
error 22: expected COMMA
error 22: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
error 23: expected COMMA
error 24: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
error 27: expected COMMA
error 35: expected COMMA
error 35: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
error 36: expected COMMA
error 36: expected R_CURLY
error 36: expected SEMI
error [22; 23): expected COMMA
error [22; 23): expected one of `*`, `::`, `{`, `self`, `super` or an identifier
error [23; 24): expected COMMA
error [24; 25): expected one of `*`, `::`, `{`, `self`, `super` or an identifier
error [27; 28): expected COMMA
error [35; 36): expected COMMA
error [35; 36): expected one of `*`, `::`, `{`, `self`, `super` or an identifier
error [36; 37): expected COMMA
error [36; 37): expected R_CURLY
error [36; 37): expected SEMI

@ -94,6 +94,6 @@ SOURCE_FILE@[0; 118)
WHITESPACE@[115; 116) "\n"
R_CURLY@[116; 117) "}"
WHITESPACE@[117; 118) "\n"
error [36; 39): unnecessary visibility qualifier
error [56; 66): unnecessary visibility qualifier
error [86; 96): unnecessary visibility qualifier
error [36; 39): Unnecessary visibility qualifier
error [56; 66): Unnecessary visibility qualifier
error [86; 96): Unnecessary visibility qualifier

@ -80,4 +80,4 @@ SOURCE_FILE@[0; 83)
WHITESPACE@[80; 81) "\n"
R_CURLY@[81; 82) "}"
WHITESPACE@[82; 83) "\n"
error 56: expected expression
error [56; 57): expected expression

@ -20,8 +20,8 @@ SOURCE_FILE@[0; 18)
ERROR@[16; 17)
SEMI@[16; 17) ";"
WHITESPACE@[17; 18) "\n"
error 12: expected `;` or `]`
error 12: expected SEMI
error 13: expected an item
error 15: expected an item
error 16: expected an item
error [12; 13): expected `;` or `]`
error [12; 13): expected SEMI
error [13; 14): expected an item
error [15; 16): expected an item
error [16; 17): expected an item

@ -23,7 +23,7 @@ SOURCE_FILE@[0; 30)
WHITESPACE@[27; 28) "\n"
R_CURLY@[28; 29) "}"
WHITESPACE@[29; 30) "\n"
error 22: expected a loop
error 22: expected SEMI
error 27: expected type
error 27: expected `{`
error [22; 23): expected a loop
error [22; 23): expected SEMI
error [27; 28): expected type
error [27; 28): expected `{`

@ -14,4 +14,4 @@ SOURCE_FILE@[0; 14)
R_PAREN@[11; 12) ")"
SEMI@[12; 13) ";"
WHITESPACE@[13; 14) "\n"
error 10: expected mut or const in raw pointer type (use `*mut T` or `*const T` as appropriate)
error [10; 11): expected mut or const in raw pointer type (use `*mut T` or `*const T` as appropriate)

@ -73,7 +73,7 @@ SOURCE_FILE@[0; 87)
L_CURLY@[84; 85) "{"
R_CURLY@[85; 86) "}"
WHITESPACE@[86; 87) "\n"
error 38: expected trait or type
error 38: expected `{`
error 70: expected trait or type
error 70: expected `{`
error [38; 39): expected trait or type
error [38; 39): expected `{`
error [70; 71): expected trait or type
error [70; 71): expected `{`

@ -16,8 +16,8 @@ SOURCE_FILE@[0; 20)
ERROR@[18; 19)
SEMI@[18; 19) ";"
WHITESPACE@[19; 20) "\n"
error 15: expected `fn`
error 15: expected SEMI
error 16: expected an item
error 17: expected an item
error 18: expected an item
error [15; 16): expected `fn`
error [15; 16): expected SEMI
error [16; 17): expected an item
error [17; 18): expected an item
error [18; 19): expected an item

@ -33,5 +33,5 @@ SOURCE_FILE@[0; 33)
L_CURLY@[30; 31) "{"
R_CURLY@[31; 32) "}"
WHITESPACE@[32; 33) "\n"
error 11: expected an item
error 18: expected an item
error [11; 12): expected an item
error [18; 19): expected an item

@ -29,4 +29,4 @@ SOURCE_FILE@[0; 30)
WHITESPACE@[27; 28) " "
R_CURLY@[28; 29) "}"
WHITESPACE@[29; 30) "\n"
error 27: expected SEMI
error [27; 28): expected SEMI

@ -23,4 +23,4 @@ SOURCE_FILE@[0; 21)
WHITESPACE@[18; 19) " "
R_CURLY@[19; 20) "}"
WHITESPACE@[20; 21) "\n"
error 14: expected an item
error [14; 15): expected an item

@ -57,5 +57,5 @@ SOURCE_FILE@[0; 48)
WHITESPACE@[45; 46) "\n"
R_CURLY@[46; 47) "}"
WHITESPACE@[47; 48) "\n"
error 24: attributes are not allowed on BIN_EXPR
error 44: attributes are not allowed on IF_EXPR
error [24; 25): attributes are not allowed on BIN_EXPR
error [44; 45): attributes are not allowed on IF_EXPR

@ -18,4 +18,4 @@ SOURCE_FILE@[0; 19)
INT_NUMBER@[16; 17) "5"
SEMI@[17; 18) ";"
WHITESPACE@[18; 19) "\n"
error 7: expected a name
error [7; 8): expected a name

@ -51,9 +51,9 @@ SOURCE_FILE@[0; 62)
WHITESPACE@[59; 60) "\n"
R_CURLY@[60; 61) "}"
WHITESPACE@[61; 62) "\n"
error 21: expected EXCL
error 21: expected `{`, `[`, `(`
error 21: expected SEMI
error 47: expected EXCL
error 47: expected `{`, `[`, `(`
error 47: expected SEMI
error [21; 22): expected EXCL
error [21; 22): expected `{`, `[`, `(`
error [21; 22): expected SEMI
error [47; 48): expected EXCL
error [47; 48): expected `{`, `[`, `(`
error [47; 48): expected SEMI