Parse and validate attributes in blocks
This commit is contained in:
@@ -272,6 +272,7 @@ impl ToOwned for Block {
|
||||
}
|
||||
|
||||
|
||||
impl ast::AttrsOwner for Block {}
|
||||
impl Block {
|
||||
pub fn statements(&self) -> impl Iterator<Item = &Stmt> {
|
||||
super::children(self)
|
||||
|
||||
@@ -571,6 +571,9 @@ Grammar(
|
||||
options: [ "Expr" ],
|
||||
collections: [
|
||||
["statements", "Stmt"],
|
||||
],
|
||||
traits: [
|
||||
"AttrsOwner",
|
||||
]
|
||||
),
|
||||
"ParamList": (
|
||||
|
||||
@@ -42,6 +42,8 @@ pub(crate) fn block(p: &mut Parser) {
|
||||
}
|
||||
let m = p.start();
|
||||
p.bump();
|
||||
// This is checked by a validator
|
||||
attributes::inner_attributes(p);
|
||||
|
||||
while !p.at(EOF) && !p.at(R_CURLY) {
|
||||
match p.current() {
|
||||
|
||||
@@ -2,6 +2,7 @@ mod byte;
|
||||
mod byte_string;
|
||||
mod char;
|
||||
mod string;
|
||||
mod block;
|
||||
|
||||
use crate::{
|
||||
SourceFile, yellow::SyntaxError, AstNode,
|
||||
@@ -17,6 +18,7 @@ pub(crate) fn validate(file: &SourceFile) -> Vec<SyntaxError> {
|
||||
.visit::<ast::ByteString, _>(self::byte_string::validate_byte_string_node)
|
||||
.visit::<ast::Char, _>(self::char::validate_char_node)
|
||||
.visit::<ast::String, _>(self::string::validate_string_node)
|
||||
.visit::<ast::Block, _>(self::block::validate_block_node)
|
||||
.accept(node);
|
||||
}
|
||||
errors
|
||||
|
||||
24
crates/ra_syntax/src/validation/block.rs
Normal file
24
crates/ra_syntax/src/validation/block.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::{SyntaxKind::*,
|
||||
ast::{self, AttrsOwner, AstNode},
|
||||
yellow::{
|
||||
SyntaxError,
|
||||
SyntaxErrorKind::*,
|
||||
},
|
||||
};
|
||||
|
||||
pub(crate) fn validate_block_node(node: &ast::Block, errors: &mut Vec<SyntaxError>) {
|
||||
if let Some(parent) = node.syntax().parent() {
|
||||
match parent.kind() {
|
||||
FN_DEF => return,
|
||||
BLOCK_EXPR => match parent.parent().map(|v| v.kind()) {
|
||||
Some(EXPR_STMT) | Some(BLOCK) => return,
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
errors.extend(
|
||||
node.attrs()
|
||||
.map(|attr| SyntaxError::new(InvalidBlockAttr, attr.syntax().range())),
|
||||
)
|
||||
}
|
||||
@@ -94,6 +94,7 @@ pub enum SyntaxErrorKind {
|
||||
UnicodeEscapeOutOfRange,
|
||||
UnclosedString,
|
||||
InvalidSuffix,
|
||||
InvalidBlockAttr,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
@@ -136,6 +137,9 @@ impl fmt::Display for SyntaxErrorKind {
|
||||
UnicodeEscapeOutOfRange => write!(f, "Unicode escape code should be at most 0x10FFFF"),
|
||||
UnclosedString => write!(f, "Unclosed string literal"),
|
||||
InvalidSuffix => write!(f, "Invalid literal suffix"),
|
||||
InvalidBlockAttr => {
|
||||
write!(f, "A block in this position cannot accept inner attributes")
|
||||
}
|
||||
ParseError(msg) => write!(f, "{}", msg.0),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user