mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
Parse and validate attributes in blocks
This commit is contained in:
parent
137b1ccb71
commit
00e6b5d26c
10 changed files with 352 additions and 0 deletions
|
@ -272,6 +272,7 @@ impl ToOwned for Block {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl ast::AttrsOwner for Block {}
|
||||||
impl Block {
|
impl Block {
|
||||||
pub fn statements(&self) -> impl Iterator<Item = &Stmt> {
|
pub fn statements(&self) -> impl Iterator<Item = &Stmt> {
|
||||||
super::children(self)
|
super::children(self)
|
||||||
|
|
|
@ -571,6 +571,9 @@ Grammar(
|
||||||
options: [ "Expr" ],
|
options: [ "Expr" ],
|
||||||
collections: [
|
collections: [
|
||||||
["statements", "Stmt"],
|
["statements", "Stmt"],
|
||||||
|
],
|
||||||
|
traits: [
|
||||||
|
"AttrsOwner",
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
"ParamList": (
|
"ParamList": (
|
||||||
|
|
|
@ -42,6 +42,8 @@ pub(crate) fn block(p: &mut Parser) {
|
||||||
}
|
}
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
p.bump();
|
p.bump();
|
||||||
|
// This is checked by a validator
|
||||||
|
attributes::inner_attributes(p);
|
||||||
|
|
||||||
while !p.at(EOF) && !p.at(R_CURLY) {
|
while !p.at(EOF) && !p.at(R_CURLY) {
|
||||||
match p.current() {
|
match p.current() {
|
||||||
|
|
|
@ -2,6 +2,7 @@ mod byte;
|
||||||
mod byte_string;
|
mod byte_string;
|
||||||
mod char;
|
mod char;
|
||||||
mod string;
|
mod string;
|
||||||
|
mod block;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
SourceFile, yellow::SyntaxError, AstNode,
|
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::ByteString, _>(self::byte_string::validate_byte_string_node)
|
||||||
.visit::<ast::Char, _>(self::char::validate_char_node)
|
.visit::<ast::Char, _>(self::char::validate_char_node)
|
||||||
.visit::<ast::String, _>(self::string::validate_string_node)
|
.visit::<ast::String, _>(self::string::validate_string_node)
|
||||||
|
.visit::<ast::Block, _>(self::block::validate_block_node)
|
||||||
.accept(node);
|
.accept(node);
|
||||||
}
|
}
|
||||||
errors
|
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,
|
UnicodeEscapeOutOfRange,
|
||||||
UnclosedString,
|
UnclosedString,
|
||||||
InvalidSuffix,
|
InvalidSuffix,
|
||||||
|
InvalidBlockAttr,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[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"),
|
UnicodeEscapeOutOfRange => write!(f, "Unicode escape code should be at most 0x10FFFF"),
|
||||||
UnclosedString => write!(f, "Unclosed string literal"),
|
UnclosedString => write!(f, "Unclosed string literal"),
|
||||||
InvalidSuffix => write!(f, "Invalid literal suffix"),
|
InvalidSuffix => write!(f, "Invalid literal suffix"),
|
||||||
|
InvalidBlockAttr => {
|
||||||
|
write!(f, "A block in this position cannot accept inner attributes")
|
||||||
|
}
|
||||||
ParseError(msg) => write!(f, "{}", msg.0),
|
ParseError(msg) => write!(f, "{}", msg.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
fn block() {
|
||||||
|
let inner = {
|
||||||
|
#![doc("Inner attributes not allowed here")]
|
||||||
|
//! Nor are ModuleDoc comments
|
||||||
|
};
|
||||||
|
if true {
|
||||||
|
#![doc("Nor here")]
|
||||||
|
#![doc("We error on each attr")]
|
||||||
|
//! Nor are ModuleDoc comments
|
||||||
|
}
|
||||||
|
while true {
|
||||||
|
#![doc("Nor here")]
|
||||||
|
//! Nor are ModuleDoc comments
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
SOURCE_FILE@[0; 350)
|
||||||
|
FN_DEF@[0; 349)
|
||||||
|
FN_KW@[0; 2)
|
||||||
|
WHITESPACE@[2; 3)
|
||||||
|
NAME@[3; 8)
|
||||||
|
IDENT@[3; 8) "block"
|
||||||
|
PARAM_LIST@[8; 10)
|
||||||
|
L_PAREN@[8; 9)
|
||||||
|
R_PAREN@[9; 10)
|
||||||
|
WHITESPACE@[10; 11)
|
||||||
|
BLOCK@[11; 349)
|
||||||
|
L_CURLY@[11; 12)
|
||||||
|
WHITESPACE@[12; 17)
|
||||||
|
LET_STMT@[17; 129)
|
||||||
|
LET_KW@[17; 20)
|
||||||
|
WHITESPACE@[20; 21)
|
||||||
|
BIND_PAT@[21; 26)
|
||||||
|
NAME@[21; 26)
|
||||||
|
IDENT@[21; 26) "inner"
|
||||||
|
WHITESPACE@[26; 27)
|
||||||
|
EQ@[27; 28)
|
||||||
|
WHITESPACE@[28; 29)
|
||||||
|
BLOCK_EXPR@[29; 128)
|
||||||
|
BLOCK@[29; 128)
|
||||||
|
L_CURLY@[29; 30)
|
||||||
|
WHITESPACE@[30; 39)
|
||||||
|
err: `A block in this position cannot accept inner attributes`
|
||||||
|
ATTR@[39; 83)
|
||||||
|
POUND@[39; 40)
|
||||||
|
EXCL@[40; 41)
|
||||||
|
TOKEN_TREE@[41; 83)
|
||||||
|
L_BRACK@[41; 42)
|
||||||
|
IDENT@[42; 45) "doc"
|
||||||
|
TOKEN_TREE@[45; 82)
|
||||||
|
L_PAREN@[45; 46)
|
||||||
|
STRING@[46; 81)
|
||||||
|
R_PAREN@[81; 82)
|
||||||
|
R_BRACK@[82; 83)
|
||||||
|
WHITESPACE@[83; 92)
|
||||||
|
COMMENT@[92; 122)
|
||||||
|
WHITESPACE@[122; 127)
|
||||||
|
R_CURLY@[127; 128)
|
||||||
|
SEMI@[128; 129)
|
||||||
|
WHITESPACE@[129; 134)
|
||||||
|
EXPR_STMT@[134; 257)
|
||||||
|
IF_EXPR@[134; 257)
|
||||||
|
IF_KW@[134; 136)
|
||||||
|
WHITESPACE@[136; 137)
|
||||||
|
CONDITION@[137; 141)
|
||||||
|
LITERAL@[137; 141)
|
||||||
|
TRUE_KW@[137; 141)
|
||||||
|
WHITESPACE@[141; 142)
|
||||||
|
BLOCK@[142; 257)
|
||||||
|
L_CURLY@[142; 143)
|
||||||
|
WHITESPACE@[143; 152)
|
||||||
|
err: `A block in this position cannot accept inner attributes`
|
||||||
|
ATTR@[152; 171)
|
||||||
|
POUND@[152; 153)
|
||||||
|
EXCL@[153; 154)
|
||||||
|
TOKEN_TREE@[154; 171)
|
||||||
|
L_BRACK@[154; 155)
|
||||||
|
IDENT@[155; 158) "doc"
|
||||||
|
TOKEN_TREE@[158; 170)
|
||||||
|
L_PAREN@[158; 159)
|
||||||
|
STRING@[159; 169)
|
||||||
|
R_PAREN@[169; 170)
|
||||||
|
R_BRACK@[170; 171)
|
||||||
|
WHITESPACE@[171; 180)
|
||||||
|
err: `A block in this position cannot accept inner attributes`
|
||||||
|
ATTR@[180; 212)
|
||||||
|
POUND@[180; 181)
|
||||||
|
EXCL@[181; 182)
|
||||||
|
TOKEN_TREE@[182; 212)
|
||||||
|
L_BRACK@[182; 183)
|
||||||
|
IDENT@[183; 186) "doc"
|
||||||
|
TOKEN_TREE@[186; 211)
|
||||||
|
L_PAREN@[186; 187)
|
||||||
|
STRING@[187; 210)
|
||||||
|
R_PAREN@[210; 211)
|
||||||
|
R_BRACK@[211; 212)
|
||||||
|
WHITESPACE@[212; 221)
|
||||||
|
COMMENT@[221; 251)
|
||||||
|
WHITESPACE@[251; 256)
|
||||||
|
R_CURLY@[256; 257)
|
||||||
|
WHITESPACE@[257; 262)
|
||||||
|
WHILE_EXPR@[262; 347)
|
||||||
|
WHILE_KW@[262; 267)
|
||||||
|
WHITESPACE@[267; 268)
|
||||||
|
CONDITION@[268; 272)
|
||||||
|
LITERAL@[268; 272)
|
||||||
|
TRUE_KW@[268; 272)
|
||||||
|
WHITESPACE@[272; 273)
|
||||||
|
BLOCK@[273; 347)
|
||||||
|
L_CURLY@[273; 274)
|
||||||
|
WHITESPACE@[274; 283)
|
||||||
|
err: `A block in this position cannot accept inner attributes`
|
||||||
|
ATTR@[283; 302)
|
||||||
|
POUND@[283; 284)
|
||||||
|
EXCL@[284; 285)
|
||||||
|
TOKEN_TREE@[285; 302)
|
||||||
|
L_BRACK@[285; 286)
|
||||||
|
IDENT@[286; 289) "doc"
|
||||||
|
TOKEN_TREE@[289; 301)
|
||||||
|
L_PAREN@[289; 290)
|
||||||
|
STRING@[290; 300)
|
||||||
|
R_PAREN@[300; 301)
|
||||||
|
R_BRACK@[301; 302)
|
||||||
|
WHITESPACE@[302; 311)
|
||||||
|
COMMENT@[311; 341)
|
||||||
|
WHITESPACE@[341; 346)
|
||||||
|
R_CURLY@[346; 347)
|
||||||
|
WHITESPACE@[347; 348)
|
||||||
|
R_CURLY@[348; 349)
|
||||||
|
WHITESPACE@[349; 350)
|
|
@ -0,0 +1,20 @@
|
||||||
|
fn block() {
|
||||||
|
#![doc("Inner attributes allowed here")]
|
||||||
|
//! As are ModuleDoc style comments
|
||||||
|
{
|
||||||
|
#![doc("Inner attributes are allowed in blocks used as statements")]
|
||||||
|
#![doc("Being validated is not affected by duplcates")]
|
||||||
|
//! As are ModuleDoc style comments
|
||||||
|
};
|
||||||
|
{
|
||||||
|
#![doc("Inner attributes are allowed in blocks when they are the last statement of another block")]
|
||||||
|
//! As are ModuleDoc style comments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/rust-analyzer/rust-analyzer/issues/689
|
||||||
|
impl Whatever {
|
||||||
|
fn salsa_event(&self, event_fn: impl Fn() -> Event<Self>) {
|
||||||
|
#![allow(unused_variables)] // this is `inner_attr` of the block
|
||||||
|
}
|
||||||
|
}
|
167
crates/ra_syntax/tests/data/parser/ok/0045_block_inner_attrs.txt
Normal file
167
crates/ra_syntax/tests/data/parser/ok/0045_block_inner_attrs.txt
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
SOURCE_FILE@[0; 686)
|
||||||
|
FN_DEF@[0; 461)
|
||||||
|
FN_KW@[0; 2)
|
||||||
|
WHITESPACE@[2; 3)
|
||||||
|
NAME@[3; 8)
|
||||||
|
IDENT@[3; 8) "block"
|
||||||
|
PARAM_LIST@[8; 10)
|
||||||
|
L_PAREN@[8; 9)
|
||||||
|
R_PAREN@[9; 10)
|
||||||
|
WHITESPACE@[10; 11)
|
||||||
|
BLOCK@[11; 461)
|
||||||
|
L_CURLY@[11; 12)
|
||||||
|
WHITESPACE@[12; 17)
|
||||||
|
ATTR@[17; 57)
|
||||||
|
POUND@[17; 18)
|
||||||
|
EXCL@[18; 19)
|
||||||
|
TOKEN_TREE@[19; 57)
|
||||||
|
L_BRACK@[19; 20)
|
||||||
|
IDENT@[20; 23) "doc"
|
||||||
|
TOKEN_TREE@[23; 56)
|
||||||
|
L_PAREN@[23; 24)
|
||||||
|
STRING@[24; 55)
|
||||||
|
R_PAREN@[55; 56)
|
||||||
|
R_BRACK@[56; 57)
|
||||||
|
WHITESPACE@[57; 62)
|
||||||
|
COMMENT@[62; 97)
|
||||||
|
WHITESPACE@[97; 102)
|
||||||
|
EXPR_STMT@[102; 295)
|
||||||
|
BLOCK_EXPR@[102; 294)
|
||||||
|
BLOCK@[102; 294)
|
||||||
|
L_CURLY@[102; 103)
|
||||||
|
WHITESPACE@[103; 112)
|
||||||
|
ATTR@[112; 180)
|
||||||
|
POUND@[112; 113)
|
||||||
|
EXCL@[113; 114)
|
||||||
|
TOKEN_TREE@[114; 180)
|
||||||
|
L_BRACK@[114; 115)
|
||||||
|
IDENT@[115; 118) "doc"
|
||||||
|
TOKEN_TREE@[118; 179)
|
||||||
|
L_PAREN@[118; 119)
|
||||||
|
STRING@[119; 178)
|
||||||
|
R_PAREN@[178; 179)
|
||||||
|
R_BRACK@[179; 180)
|
||||||
|
WHITESPACE@[180; 189)
|
||||||
|
ATTR@[189; 244)
|
||||||
|
POUND@[189; 190)
|
||||||
|
EXCL@[190; 191)
|
||||||
|
TOKEN_TREE@[191; 244)
|
||||||
|
L_BRACK@[191; 192)
|
||||||
|
IDENT@[192; 195) "doc"
|
||||||
|
TOKEN_TREE@[195; 243)
|
||||||
|
L_PAREN@[195; 196)
|
||||||
|
STRING@[196; 242)
|
||||||
|
R_PAREN@[242; 243)
|
||||||
|
R_BRACK@[243; 244)
|
||||||
|
WHITESPACE@[244; 253)
|
||||||
|
COMMENT@[253; 288)
|
||||||
|
WHITESPACE@[288; 293)
|
||||||
|
R_CURLY@[293; 294)
|
||||||
|
SEMI@[294; 295)
|
||||||
|
WHITESPACE@[295; 300)
|
||||||
|
BLOCK_EXPR@[300; 459)
|
||||||
|
BLOCK@[300; 459)
|
||||||
|
L_CURLY@[300; 301)
|
||||||
|
WHITESPACE@[301; 310)
|
||||||
|
ATTR@[310; 409)
|
||||||
|
POUND@[310; 311)
|
||||||
|
EXCL@[311; 312)
|
||||||
|
TOKEN_TREE@[312; 409)
|
||||||
|
L_BRACK@[312; 313)
|
||||||
|
IDENT@[313; 316) "doc"
|
||||||
|
TOKEN_TREE@[316; 408)
|
||||||
|
L_PAREN@[316; 317)
|
||||||
|
STRING@[317; 407)
|
||||||
|
R_PAREN@[407; 408)
|
||||||
|
R_BRACK@[408; 409)
|
||||||
|
WHITESPACE@[409; 418)
|
||||||
|
COMMENT@[418; 453)
|
||||||
|
WHITESPACE@[453; 458)
|
||||||
|
R_CURLY@[458; 459)
|
||||||
|
WHITESPACE@[459; 460)
|
||||||
|
R_CURLY@[460; 461)
|
||||||
|
WHITESPACE@[461; 463)
|
||||||
|
COMMENT@[463; 523)
|
||||||
|
WHITESPACE@[523; 524)
|
||||||
|
IMPL_BLOCK@[524; 685)
|
||||||
|
IMPL_KW@[524; 528)
|
||||||
|
WHITESPACE@[528; 529)
|
||||||
|
PATH_TYPE@[529; 537)
|
||||||
|
PATH@[529; 537)
|
||||||
|
PATH_SEGMENT@[529; 537)
|
||||||
|
NAME_REF@[529; 537)
|
||||||
|
IDENT@[529; 537) "Whatever"
|
||||||
|
WHITESPACE@[537; 538)
|
||||||
|
ITEM_LIST@[538; 685)
|
||||||
|
L_CURLY@[538; 539)
|
||||||
|
WHITESPACE@[539; 544)
|
||||||
|
FN_DEF@[544; 683)
|
||||||
|
FN_KW@[544; 546)
|
||||||
|
WHITESPACE@[546; 547)
|
||||||
|
NAME@[547; 558)
|
||||||
|
IDENT@[547; 558) "salsa_event"
|
||||||
|
PARAM_LIST@[558; 601)
|
||||||
|
L_PAREN@[558; 559)
|
||||||
|
SELF_PARAM@[559; 564)
|
||||||
|
AMP@[559; 560)
|
||||||
|
SELF_KW@[560; 564)
|
||||||
|
COMMA@[564; 565)
|
||||||
|
WHITESPACE@[565; 566)
|
||||||
|
PARAM@[566; 600)
|
||||||
|
BIND_PAT@[566; 574)
|
||||||
|
NAME@[566; 574)
|
||||||
|
IDENT@[566; 574) "event_fn"
|
||||||
|
COLON@[574; 575)
|
||||||
|
WHITESPACE@[575; 576)
|
||||||
|
IMPL_TRAIT_TYPE@[576; 600)
|
||||||
|
IMPL_KW@[576; 580)
|
||||||
|
WHITESPACE@[580; 581)
|
||||||
|
PATH_TYPE@[581; 600)
|
||||||
|
PATH@[581; 600)
|
||||||
|
PATH_SEGMENT@[581; 600)
|
||||||
|
NAME_REF@[581; 583)
|
||||||
|
IDENT@[581; 583) "Fn"
|
||||||
|
PARAM_LIST@[583; 585)
|
||||||
|
L_PAREN@[583; 584)
|
||||||
|
R_PAREN@[584; 585)
|
||||||
|
WHITESPACE@[585; 586)
|
||||||
|
RET_TYPE@[586; 600)
|
||||||
|
THIN_ARROW@[586; 588)
|
||||||
|
WHITESPACE@[588; 589)
|
||||||
|
PATH_TYPE@[589; 600)
|
||||||
|
PATH@[589; 600)
|
||||||
|
PATH_SEGMENT@[589; 600)
|
||||||
|
NAME_REF@[589; 594)
|
||||||
|
IDENT@[589; 594) "Event"
|
||||||
|
TYPE_ARG_LIST@[594; 600)
|
||||||
|
L_ANGLE@[594; 595)
|
||||||
|
TYPE_ARG@[595; 599)
|
||||||
|
PATH_TYPE@[595; 599)
|
||||||
|
PATH@[595; 599)
|
||||||
|
PATH_SEGMENT@[595; 599)
|
||||||
|
NAME_REF@[595; 599)
|
||||||
|
IDENT@[595; 599) "Self"
|
||||||
|
R_ANGLE@[599; 600)
|
||||||
|
R_PAREN@[600; 601)
|
||||||
|
WHITESPACE@[601; 602)
|
||||||
|
BLOCK@[602; 683)
|
||||||
|
L_CURLY@[602; 603)
|
||||||
|
WHITESPACE@[603; 612)
|
||||||
|
ATTR@[612; 639)
|
||||||
|
POUND@[612; 613)
|
||||||
|
EXCL@[613; 614)
|
||||||
|
TOKEN_TREE@[614; 639)
|
||||||
|
L_BRACK@[614; 615)
|
||||||
|
IDENT@[615; 620) "allow"
|
||||||
|
TOKEN_TREE@[620; 638)
|
||||||
|
L_PAREN@[620; 621)
|
||||||
|
IDENT@[621; 637) "unused_variables"
|
||||||
|
R_PAREN@[637; 638)
|
||||||
|
R_BRACK@[638; 639)
|
||||||
|
WHITESPACE@[639; 640)
|
||||||
|
COMMENT@[640; 677)
|
||||||
|
WHITESPACE@[677; 682)
|
||||||
|
R_CURLY@[682; 683)
|
||||||
|
WHITESPACE@[683; 684)
|
||||||
|
R_CURLY@[684; 685)
|
||||||
|
WHITESPACE@[685; 686)
|
Loading…
Add table
Add a link
Reference in a new issue