diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-31 07:06:31 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-31 07:06:31 +0000 |
commit | 97ade899937dafcafa852177c85edb22ce0b80dc (patch) | |
tree | cf5f8bdc5647222c8300c3386c5c8d47283d5116 /crates/ra_syntax/src | |
parent | 777c79ce6bff0e70c8367f429f058f6d87ff3864 (diff) | |
parent | 00e6b5d26c82d5faff066c24418a0eb5741efcd1 (diff) |
Merge #692
692: [WIP] Correctly parse attributes r=matklad a=DJMcNab
Reference - https://doc.rust-lang.org/reference/attributes.html
This fixes/investigates inner attributes for:
- [x] `impl` blocks
- [x] `extern` blocks
- [x] `fn`s (fixes #689)
- [x] `mod`s (already supported)
- [x] 'block expressions' (the long text just describes all 'blocks' used as statements)
This also investigates/fixes outer attributes for:
- [ ] 'most statements' (see also: #685, https://doc.rust-lang.org/reference/expressions.html#expression-attributes)
- [x] Enum variants, Struct and Union fields (Fixed in #507)
- [ ] 'Match expression arms' (@matklad can you provide a test case which explains what this means?)
- [ ] 'Generic lifetime or type parameters'
- [ ] 'Elements of array expressions, tuple expressions, call expressions, tuple-style struct and enum variant expressions'
- [ ] 'The tail expression of block expressions'
Co-authored-by: DJMcNab <[email protected]>
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r-- | crates/ra_syntax/src/ast/generated.rs | 1 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar.ron | 3 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar/expressions.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar/items/traits.rs | 7 | ||||
-rw-r--r-- | crates/ra_syntax/src/validation.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/validation/block.rs | 24 | ||||
-rw-r--r-- | crates/ra_syntax/src/yellow/syntax_error.rs | 4 |
7 files changed, 43 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 4f5a96014..d0561c495 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -272,6 +272,7 @@ impl ToOwned for Block { | |||
272 | } | 272 | } |
273 | 273 | ||
274 | 274 | ||
275 | impl ast::AttrsOwner for Block {} | ||
275 | impl Block { | 276 | impl Block { |
276 | pub fn statements(&self) -> impl Iterator<Item = &Stmt> { | 277 | pub fn statements(&self) -> impl Iterator<Item = &Stmt> { |
277 | super::children(self) | 278 | super::children(self) |
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index e4cad4eb3..d4c863705 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -571,6 +571,9 @@ Grammar( | |||
571 | options: [ "Expr" ], | 571 | options: [ "Expr" ], |
572 | collections: [ | 572 | collections: [ |
573 | ["statements", "Stmt"], | 573 | ["statements", "Stmt"], |
574 | ], | ||
575 | traits: [ | ||
576 | "AttrsOwner", | ||
574 | ] | 577 | ] |
575 | ), | 578 | ), |
576 | "ParamList": ( | 579 | "ParamList": ( |
diff --git a/crates/ra_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs index d27eb8b7e..6b88c5685 100644 --- a/crates/ra_syntax/src/grammar/expressions.rs +++ b/crates/ra_syntax/src/grammar/expressions.rs | |||
@@ -42,6 +42,8 @@ pub(crate) fn block(p: &mut Parser) { | |||
42 | } | 42 | } |
43 | let m = p.start(); | 43 | let m = p.start(); |
44 | p.bump(); | 44 | p.bump(); |
45 | // This is checked by a validator | ||
46 | attributes::inner_attributes(p); | ||
45 | 47 | ||
46 | while !p.at(EOF) && !p.at(R_CURLY) { | 48 | while !p.at(EOF) && !p.at(R_CURLY) { |
47 | match p.current() { | 49 | match p.current() { |
diff --git a/crates/ra_syntax/src/grammar/items/traits.rs b/crates/ra_syntax/src/grammar/items/traits.rs index 0a0621753..d5a8ccd98 100644 --- a/crates/ra_syntax/src/grammar/items/traits.rs +++ b/crates/ra_syntax/src/grammar/items/traits.rs | |||
@@ -78,6 +78,13 @@ pub(crate) fn impl_item_list(p: &mut Parser) { | |||
78 | assert!(p.at(L_CURLY)); | 78 | assert!(p.at(L_CURLY)); |
79 | let m = p.start(); | 79 | let m = p.start(); |
80 | p.bump(); | 80 | p.bump(); |
81 | // test impl_inner_attributes | ||
82 | // enum F{} | ||
83 | // impl F { | ||
84 | // //! This is a doc comment | ||
85 | // #![doc("This is also a doc comment")] | ||
86 | // } | ||
87 | attributes::inner_attributes(p); | ||
81 | 88 | ||
82 | while !p.at(EOF) && !p.at(R_CURLY) { | 89 | while !p.at(EOF) && !p.at(R_CURLY) { |
83 | if p.at(L_CURLY) { | 90 | if p.at(L_CURLY) { |
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index 73e1d20b9..ac6cc3dd6 100644 --- a/crates/ra_syntax/src/validation.rs +++ b/crates/ra_syntax/src/validation.rs | |||
@@ -2,6 +2,7 @@ mod byte; | |||
2 | mod byte_string; | 2 | mod byte_string; |
3 | mod char; | 3 | mod char; |
4 | mod string; | 4 | mod string; |
5 | mod block; | ||
5 | 6 | ||
6 | use crate::{ | 7 | use crate::{ |
7 | SourceFile, yellow::SyntaxError, AstNode, | 8 | SourceFile, yellow::SyntaxError, AstNode, |
@@ -17,6 +18,7 @@ pub(crate) fn validate(file: &SourceFile) -> Vec<SyntaxError> { | |||
17 | .visit::<ast::ByteString, _>(self::byte_string::validate_byte_string_node) | 18 | .visit::<ast::ByteString, _>(self::byte_string::validate_byte_string_node) |
18 | .visit::<ast::Char, _>(self::char::validate_char_node) | 19 | .visit::<ast::Char, _>(self::char::validate_char_node) |
19 | .visit::<ast::String, _>(self::string::validate_string_node) | 20 | .visit::<ast::String, _>(self::string::validate_string_node) |
21 | .visit::<ast::Block, _>(self::block::validate_block_node) | ||
20 | .accept(node); | 22 | .accept(node); |
21 | } | 23 | } |
22 | errors | 24 | errors |
diff --git a/crates/ra_syntax/src/validation/block.rs b/crates/ra_syntax/src/validation/block.rs new file mode 100644 index 000000000..9e1949124 --- /dev/null +++ b/crates/ra_syntax/src/validation/block.rs | |||
@@ -0,0 +1,24 @@ | |||
1 | use crate::{SyntaxKind::*, | ||
2 | ast::{self, AttrsOwner, AstNode}, | ||
3 | yellow::{ | ||
4 | SyntaxError, | ||
5 | SyntaxErrorKind::*, | ||
6 | }, | ||
7 | }; | ||
8 | |||
9 | pub(crate) fn validate_block_node(node: &ast::Block, errors: &mut Vec<SyntaxError>) { | ||
10 | if let Some(parent) = node.syntax().parent() { | ||
11 | match parent.kind() { | ||
12 | FN_DEF => return, | ||
13 | BLOCK_EXPR => match parent.parent().map(|v| v.kind()) { | ||
14 | Some(EXPR_STMT) | Some(BLOCK) => return, | ||
15 | _ => {} | ||
16 | }, | ||
17 | _ => {} | ||
18 | } | ||
19 | } | ||
20 | errors.extend( | ||
21 | node.attrs() | ||
22 | .map(|attr| SyntaxError::new(InvalidBlockAttr, attr.syntax().range())), | ||
23 | ) | ||
24 | } | ||
diff --git a/crates/ra_syntax/src/yellow/syntax_error.rs b/crates/ra_syntax/src/yellow/syntax_error.rs index 534f3511e..c52c44cc3 100644 --- a/crates/ra_syntax/src/yellow/syntax_error.rs +++ b/crates/ra_syntax/src/yellow/syntax_error.rs | |||
@@ -94,6 +94,7 @@ pub enum SyntaxErrorKind { | |||
94 | UnicodeEscapeOutOfRange, | 94 | UnicodeEscapeOutOfRange, |
95 | UnclosedString, | 95 | UnclosedString, |
96 | InvalidSuffix, | 96 | InvalidSuffix, |
97 | InvalidBlockAttr, | ||
97 | } | 98 | } |
98 | 99 | ||
99 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 100 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
@@ -136,6 +137,9 @@ impl fmt::Display for SyntaxErrorKind { | |||
136 | UnicodeEscapeOutOfRange => write!(f, "Unicode escape code should be at most 0x10FFFF"), | 137 | UnicodeEscapeOutOfRange => write!(f, "Unicode escape code should be at most 0x10FFFF"), |
137 | UnclosedString => write!(f, "Unclosed string literal"), | 138 | UnclosedString => write!(f, "Unclosed string literal"), |
138 | InvalidSuffix => write!(f, "Invalid literal suffix"), | 139 | InvalidSuffix => write!(f, "Invalid literal suffix"), |
140 | InvalidBlockAttr => { | ||
141 | write!(f, "A block in this position cannot accept inner attributes") | ||
142 | } | ||
139 | ParseError(msg) => write!(f, "{}", msg.0), | 143 | ParseError(msg) => write!(f, "{}", msg.0), |
140 | } | 144 | } |
141 | } | 145 | } |