From 1c97c1ac11459d45f7bfc57dc72428d2b294520c Mon Sep 17 00:00:00 2001 From: Ville Penttinen Date: Sun, 17 Feb 2019 19:08:34 +0200 Subject: Enable parsing of attributes inside a match block We allow invalid inner attributes to be parsed, e.g. inner attributes that are not directly after the opening brace of the match block. Instead we run validation on `MatchArmList` to allow better reporting of errors. --- crates/ra_syntax/src/ast.rs | 14 ++ crates/ra_syntax/src/ast/generated.rs | 2 + crates/ra_syntax/src/grammar.ron | 4 +- crates/ra_syntax/src/grammar/attributes.rs | 10 ++ crates/ra_syntax/src/grammar/expressions/atom.rs | 33 ++++ crates/ra_syntax/src/syntax_node/syntax_error.rs | 4 + crates/ra_syntax/src/validation.rs | 2 + crates/ra_syntax/src/validation/match_armlist.rs | 28 ++++ .../data/parser/err/0032_match_arms_inner_attrs.rs | 20 +++ .../parser/err/0032_match_arms_inner_attrs.txt | 173 +++++++++++++++++++++ .../data/parser/err/0033_match_arms_outer_attrs.rs | 7 + .../parser/err/0033_match_arms_outer_attrs.txt | 64 ++++++++ .../inline/ok/0120_match_arms_inner_attribute.rs | 8 + .../inline/ok/0120_match_arms_inner_attribute.txt | 74 +++++++++ .../inline/ok/0121_match_arms_outer_attributes.rs | 12 ++ .../inline/ok/0121_match_arms_outer_attributes.txt | 135 ++++++++++++++++ 16 files changed, 589 insertions(+), 1 deletion(-) create mode 100644 crates/ra_syntax/src/validation/match_armlist.rs create mode 100644 crates/ra_syntax/tests/data/parser/err/0032_match_arms_inner_attrs.rs create mode 100644 crates/ra_syntax/tests/data/parser/err/0032_match_arms_inner_attrs.txt create mode 100644 crates/ra_syntax/tests/data/parser/err/0033_match_arms_outer_attrs.rs create mode 100644 crates/ra_syntax/tests/data/parser/err/0033_match_arms_outer_attrs.txt create mode 100644 crates/ra_syntax/tests/data/parser/inline/ok/0120_match_arms_inner_attribute.rs create mode 100644 crates/ra_syntax/tests/data/parser/inline/ok/0120_match_arms_inner_attribute.txt create mode 100644 crates/ra_syntax/tests/data/parser/inline/ok/0121_match_arms_outer_attributes.rs create mode 100644 crates/ra_syntax/tests/data/parser/inline/ok/0121_match_arms_outer_attributes.txt diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 22105d6c9..350f01f33 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs @@ -153,6 +153,20 @@ impl FnDef { } impl Attr { + pub fn is_inner(&self) -> bool { + let tt = match self.value() { + None => return false, + Some(tt) => tt, + }; + + let prev = match tt.syntax().prev_sibling() { + None => return false, + Some(prev) => prev, + }; + + prev.kind() == EXCL + } + pub fn as_atom(&self) -> Option { let tt = self.value()?; let (_bra, attr, _ket) = tt.syntax().children().collect_tuple()?; diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index dd91b5063..c7aaccc95 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -1946,6 +1946,7 @@ impl ToOwned for MatchArm { } +impl ast::AttrsOwner for MatchArm {} impl MatchArm { pub fn pats(&self) -> impl Iterator { super::children(self) @@ -1986,6 +1987,7 @@ impl ToOwned for MatchArmList { } +impl ast::AttrsOwner for MatchArmList {} impl MatchArmList { pub fn arms(&self) -> impl Iterator { super::children(self) diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 27a123681..193b563aa 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -413,13 +413,15 @@ Grammar( ), "MatchArmList": ( collections: [ ["arms", "MatchArm"] ], + traits: [ "AttrsOwner" ] ), "MatchArm": ( options: [ [ "guard", "MatchGuard" ], "Expr", ], - collections: [ [ "pats", "Pat" ] ] + collections: [ [ "pats", "Pat" ] ], + traits: [ "AttrsOwner" ] ), "MatchGuard": (options: ["Expr"]), "StructLit": (options: ["Path", "NamedFieldList", ["spread", "Expr"]]), diff --git a/crates/ra_syntax/src/grammar/attributes.rs b/crates/ra_syntax/src/grammar/attributes.rs index cd30e8a45..2624d2e16 100644 --- a/crates/ra_syntax/src/grammar/attributes.rs +++ b/crates/ra_syntax/src/grammar/attributes.rs @@ -1,5 +1,15 @@ use super::*; +/// Parses both inner & outer attributes. +/// +/// Allowing to run validation for reporting errors +/// regarding attributes +pub(super) fn all_attributes(p: &mut Parser) { + while p.at(POUND) { + attribute(p, p.nth(1) == EXCL) + } +} + pub(super) fn inner_attributes(p: &mut Parser) { while p.current() == POUND && p.nth(1) == EXCL { attribute(p, true) diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs index 27ba87657..67cd7e6b0 100644 --- a/crates/ra_syntax/src/grammar/expressions/atom.rs +++ b/crates/ra_syntax/src/grammar/expressions/atom.rs @@ -313,11 +313,44 @@ pub(crate) fn match_arm_list(p: &mut Parser) { assert!(p.at(L_CURLY)); let m = p.start(); p.eat(L_CURLY); + + // test match_arms_inner_attribute + // fn foo() { + // match () { + // #![doc("Inner attribute")] + // #![doc("Can be")] + // #![doc("Stacked")] + // _ => (), + // } + // } + attributes::inner_attributes(p); + while !p.at(EOF) && !p.at(R_CURLY) { if p.at(L_CURLY) { error_block(p, "expected match arm"); continue; } + + // This may result in invalid attributes + // if there are inner attributes mixed in together + // with the outer attributes, but we allow parsing + // those so we can run validation and report better errors + + // test match_arms_outer_attributes + // fn foo() { + // match () { + // #[cfg(feature = "some")] + // _ => (), + // #[cfg(feature = "other")] + // _ => (), + // #[cfg(feature = "many")] + // #[cfg(feature = "attributes")] + // #[cfg(feature = "before")] + // _ => (), + // } + // } + attributes::all_attributes(p); + // test match_arms_commas // fn foo() { // match () { diff --git a/crates/ra_syntax/src/syntax_node/syntax_error.rs b/crates/ra_syntax/src/syntax_node/syntax_error.rs index 412cf82cc..4ff998090 100644 --- a/crates/ra_syntax/src/syntax_node/syntax_error.rs +++ b/crates/ra_syntax/src/syntax_node/syntax_error.rs @@ -92,6 +92,7 @@ pub enum SyntaxErrorKind { UnclosedString, InvalidSuffix, InvalidBlockAttr, + InvalidMatchInnerAttr, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -136,6 +137,9 @@ impl fmt::Display for SyntaxErrorKind { 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") + } ParseError(msg) => write!(f, "{}", msg.0), } } diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index 10672d6bf..27a465a78 100644 --- a/crates/ra_syntax/src/validation.rs +++ b/crates/ra_syntax/src/validation.rs @@ -3,6 +3,7 @@ mod byte_string; mod char; mod string; mod block; +mod match_armlist; use crate::{ SourceFile, syntax_node::SyntaxError, AstNode, @@ -19,6 +20,7 @@ pub(crate) fn validate(file: &SourceFile) -> Vec { .visit::(self::char::validate_char_node) .visit::(self::string::validate_string_node) .visit::(self::block::validate_block_node) + .visit::(self::match_armlist::validate_match_armlist) .accept(node); } errors diff --git a/crates/ra_syntax/src/validation/match_armlist.rs b/crates/ra_syntax/src/validation/match_armlist.rs new file mode 100644 index 000000000..c43ed7092 --- /dev/null +++ b/crates/ra_syntax/src/validation/match_armlist.rs @@ -0,0 +1,28 @@ +use crate::{ + ast::{self, AttrsOwner, AstNode}, + syntax_node::{ + SyntaxError, + SyntaxErrorKind::*, + Direction, + }, +}; + +pub(crate) fn validate_match_armlist(node: &ast::MatchArmList, errors: &mut Vec) { + // Report errors for any inner attribute + // which has a preceding matcharm or an outer attribute + for inner_attr in node.attrs().filter(|s| s.is_inner()) { + let any_errors = inner_attr.syntax().siblings(Direction::Prev).any(|s| { + match (ast::MatchArm::cast(s), ast::Attr::cast(s)) { + (Some(_), _) => true, + // Outer attributes which preceed an inner attribute are not allowed + (_, Some(a)) if !a.is_inner() => true, + (_, Some(_)) => false, + (None, None) => false, + } + }); + + if any_errors { + errors.push(SyntaxError::new(InvalidMatchInnerAttr, inner_attr.syntax().range())); + } + } +} diff --git a/crates/ra_syntax/tests/data/parser/err/0032_match_arms_inner_attrs.rs b/crates/ra_syntax/tests/data/parser/err/0032_match_arms_inner_attrs.rs new file mode 100644 index 000000000..06aa47770 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/err/0032_match_arms_inner_attrs.rs @@ -0,0 +1,20 @@ +fn foo() { + match () { + _ => (), + #![doc("Not allowed here")] + _ => (), + } + + match () { + _ => (), + _ => (), + #![doc("Nor here")] + } + + match () { + #[cfg(test)] + #![doc("Nor here")] + _ => (), + _ => (), + } +} diff --git a/crates/ra_syntax/tests/data/parser/err/0032_match_arms_inner_attrs.txt b/crates/ra_syntax/tests/data/parser/err/0032_match_arms_inner_attrs.txt new file mode 100644 index 000000000..b3ff36364 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/err/0032_match_arms_inner_attrs.txt @@ -0,0 +1,173 @@ +SOURCE_FILE@[0; 293) + FN_DEF@[0; 292) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 6) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 8) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK@[9; 292) + L_CURLY@[9; 10) + WHITESPACE@[10; 15) + EXPR_STMT@[15; 101) + MATCH_EXPR@[15; 101) + MATCH_KW@[15; 20) + WHITESPACE@[20; 21) + TUPLE_EXPR@[21; 23) + L_PAREN@[21; 22) + R_PAREN@[22; 23) + WHITESPACE@[23; 24) + MATCH_ARM_LIST@[24; 101) + L_CURLY@[24; 25) + WHITESPACE@[25; 34) + MATCH_ARM@[34; 41) + PLACEHOLDER_PAT@[34; 35) + UNDERSCORE@[34; 35) + WHITESPACE@[35; 36) + FAT_ARROW@[36; 38) + WHITESPACE@[38; 39) + TUPLE_EXPR@[39; 41) + L_PAREN@[39; 40) + R_PAREN@[40; 41) + COMMA@[41; 42) + WHITESPACE@[42; 51) + err: `Inner attributes are only allowed directly after the opening brace of the match expression` + ATTR@[51; 78) + POUND@[51; 52) + EXCL@[52; 53) + TOKEN_TREE@[53; 78) + L_BRACK@[53; 54) + IDENT@[54; 57) "doc" + TOKEN_TREE@[57; 77) + L_PAREN@[57; 58) + STRING@[58; 76) + R_PAREN@[76; 77) + R_BRACK@[77; 78) + WHITESPACE@[78; 87) + MATCH_ARM@[87; 94) + PLACEHOLDER_PAT@[87; 88) + UNDERSCORE@[87; 88) + WHITESPACE@[88; 89) + FAT_ARROW@[89; 91) + WHITESPACE@[91; 92) + TUPLE_EXPR@[92; 94) + L_PAREN@[92; 93) + R_PAREN@[93; 94) + COMMA@[94; 95) + WHITESPACE@[95; 100) + R_CURLY@[100; 101) + WHITESPACE@[101; 107) + EXPR_STMT@[107; 185) + MATCH_EXPR@[107; 185) + MATCH_KW@[107; 112) + WHITESPACE@[112; 113) + TUPLE_EXPR@[113; 115) + L_PAREN@[113; 114) + R_PAREN@[114; 115) + WHITESPACE@[115; 116) + MATCH_ARM_LIST@[116; 185) + L_CURLY@[116; 117) + WHITESPACE@[117; 126) + MATCH_ARM@[126; 133) + PLACEHOLDER_PAT@[126; 127) + UNDERSCORE@[126; 127) + WHITESPACE@[127; 128) + FAT_ARROW@[128; 130) + WHITESPACE@[130; 131) + TUPLE_EXPR@[131; 133) + L_PAREN@[131; 132) + R_PAREN@[132; 133) + COMMA@[133; 134) + WHITESPACE@[134; 143) + MATCH_ARM@[143; 150) + PLACEHOLDER_PAT@[143; 144) + UNDERSCORE@[143; 144) + WHITESPACE@[144; 145) + FAT_ARROW@[145; 147) + WHITESPACE@[147; 148) + TUPLE_EXPR@[148; 150) + L_PAREN@[148; 149) + R_PAREN@[149; 150) + COMMA@[150; 151) + WHITESPACE@[151; 160) + err: `Inner attributes are only allowed directly after the opening brace of the match expression` + ATTR@[160; 179) + POUND@[160; 161) + EXCL@[161; 162) + TOKEN_TREE@[162; 179) + L_BRACK@[162; 163) + IDENT@[163; 166) "doc" + TOKEN_TREE@[166; 178) + L_PAREN@[166; 167) + STRING@[167; 177) + R_PAREN@[177; 178) + R_BRACK@[178; 179) + WHITESPACE@[179; 184) + err: `expected pattern` + err: `expected FAT_ARROW` + err: `expected expression` + MATCH_ARM@[184; 184) + R_CURLY@[184; 185) + WHITESPACE@[185; 191) + MATCH_EXPR@[191; 290) + MATCH_KW@[191; 196) + WHITESPACE@[196; 197) + TUPLE_EXPR@[197; 199) + L_PAREN@[197; 198) + R_PAREN@[198; 199) + WHITESPACE@[199; 200) + MATCH_ARM_LIST@[200; 290) + L_CURLY@[200; 201) + WHITESPACE@[201; 210) + ATTR@[210; 222) + POUND@[210; 211) + TOKEN_TREE@[211; 222) + L_BRACK@[211; 212) + IDENT@[212; 215) "cfg" + TOKEN_TREE@[215; 221) + L_PAREN@[215; 216) + IDENT@[216; 220) "test" + R_PAREN@[220; 221) + R_BRACK@[221; 222) + WHITESPACE@[222; 231) + err: `Inner attributes are only allowed directly after the opening brace of the match expression` + ATTR@[231; 250) + POUND@[231; 232) + EXCL@[232; 233) + TOKEN_TREE@[233; 250) + L_BRACK@[233; 234) + IDENT@[234; 237) "doc" + TOKEN_TREE@[237; 249) + L_PAREN@[237; 238) + STRING@[238; 248) + R_PAREN@[248; 249) + R_BRACK@[249; 250) + WHITESPACE@[250; 259) + MATCH_ARM@[259; 266) + PLACEHOLDER_PAT@[259; 260) + UNDERSCORE@[259; 260) + WHITESPACE@[260; 261) + FAT_ARROW@[261; 263) + WHITESPACE@[263; 264) + TUPLE_EXPR@[264; 266) + L_PAREN@[264; 265) + R_PAREN@[265; 266) + COMMA@[266; 267) + WHITESPACE@[267; 276) + MATCH_ARM@[276; 283) + PLACEHOLDER_PAT@[276; 277) + UNDERSCORE@[276; 277) + WHITESPACE@[277; 278) + FAT_ARROW@[278; 280) + WHITESPACE@[280; 281) + TUPLE_EXPR@[281; 283) + L_PAREN@[281; 282) + R_PAREN@[282; 283) + COMMA@[283; 284) + WHITESPACE@[284; 289) + R_CURLY@[289; 290) + WHITESPACE@[290; 291) + R_CURLY@[291; 292) + WHITESPACE@[292; 293) diff --git a/crates/ra_syntax/tests/data/parser/err/0033_match_arms_outer_attrs.rs b/crates/ra_syntax/tests/data/parser/err/0033_match_arms_outer_attrs.rs new file mode 100644 index 000000000..4635222da --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/err/0033_match_arms_outer_attrs.rs @@ -0,0 +1,7 @@ +fn foo() { + match () { + _ => (), + _ => (), + #[cfg(test)] + } +} diff --git a/crates/ra_syntax/tests/data/parser/err/0033_match_arms_outer_attrs.txt b/crates/ra_syntax/tests/data/parser/err/0033_match_arms_outer_attrs.txt new file mode 100644 index 000000000..7f8767001 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/err/0033_match_arms_outer_attrs.txt @@ -0,0 +1,64 @@ +SOURCE_FILE@[0; 89) + FN_DEF@[0; 88) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 6) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 8) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK@[9; 88) + L_CURLY@[9; 10) + WHITESPACE@[10; 15) + MATCH_EXPR@[15; 86) + MATCH_KW@[15; 20) + WHITESPACE@[20; 21) + TUPLE_EXPR@[21; 23) + L_PAREN@[21; 22) + R_PAREN@[22; 23) + WHITESPACE@[23; 24) + MATCH_ARM_LIST@[24; 86) + L_CURLY@[24; 25) + WHITESPACE@[25; 34) + MATCH_ARM@[34; 41) + PLACEHOLDER_PAT@[34; 35) + UNDERSCORE@[34; 35) + WHITESPACE@[35; 36) + FAT_ARROW@[36; 38) + WHITESPACE@[38; 39) + TUPLE_EXPR@[39; 41) + L_PAREN@[39; 40) + R_PAREN@[40; 41) + COMMA@[41; 42) + WHITESPACE@[42; 51) + MATCH_ARM@[51; 58) + PLACEHOLDER_PAT@[51; 52) + UNDERSCORE@[51; 52) + WHITESPACE@[52; 53) + FAT_ARROW@[53; 55) + WHITESPACE@[55; 56) + TUPLE_EXPR@[56; 58) + L_PAREN@[56; 57) + R_PAREN@[57; 58) + COMMA@[58; 59) + WHITESPACE@[59; 68) + ATTR@[68; 80) + POUND@[68; 69) + TOKEN_TREE@[69; 80) + L_BRACK@[69; 70) + IDENT@[70; 73) "cfg" + TOKEN_TREE@[73; 79) + L_PAREN@[73; 74) + IDENT@[74; 78) "test" + R_PAREN@[78; 79) + R_BRACK@[79; 80) + WHITESPACE@[80; 85) + err: `expected pattern` + err: `expected FAT_ARROW` + err: `expected expression` + MATCH_ARM@[85; 85) + R_CURLY@[85; 86) + WHITESPACE@[86; 87) + R_CURLY@[87; 88) + WHITESPACE@[88; 89) diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0120_match_arms_inner_attribute.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0120_match_arms_inner_attribute.rs new file mode 100644 index 000000000..54a67c9d7 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0120_match_arms_inner_attribute.rs @@ -0,0 +1,8 @@ +fn foo() { + match () { + #![doc("Inner attribute")] + #![doc("Can be")] + #![doc("Stacked")] + _ => (), + } +} diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0120_match_arms_inner_attribute.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0120_match_arms_inner_attribute.txt new file mode 100644 index 000000000..b39a217bd --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0120_match_arms_inner_attribute.txt @@ -0,0 +1,74 @@ +SOURCE_FILE@[0; 139) + FN_DEF@[0; 138) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 6) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 8) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK@[9; 138) + L_CURLY@[9; 10) + WHITESPACE@[10; 15) + MATCH_EXPR@[15; 136) + MATCH_KW@[15; 20) + WHITESPACE@[20; 21) + TUPLE_EXPR@[21; 23) + L_PAREN@[21; 22) + R_PAREN@[22; 23) + WHITESPACE@[23; 24) + MATCH_ARM_LIST@[24; 136) + L_CURLY@[24; 25) + WHITESPACE@[25; 34) + ATTR@[34; 60) + POUND@[34; 35) + EXCL@[35; 36) + TOKEN_TREE@[36; 60) + L_BRACK@[36; 37) + IDENT@[37; 40) "doc" + TOKEN_TREE@[40; 59) + L_PAREN@[40; 41) + STRING@[41; 58) + R_PAREN@[58; 59) + R_BRACK@[59; 60) + WHITESPACE@[60; 69) + ATTR@[69; 86) + POUND@[69; 70) + EXCL@[70; 71) + TOKEN_TREE@[71; 86) + L_BRACK@[71; 72) + IDENT@[72; 75) "doc" + TOKEN_TREE@[75; 85) + L_PAREN@[75; 76) + STRING@[76; 84) + R_PAREN@[84; 85) + R_BRACK@[85; 86) + WHITESPACE@[86; 95) + ATTR@[95; 113) + POUND@[95; 96) + EXCL@[96; 97) + TOKEN_TREE@[97; 113) + L_BRACK@[97; 98) + IDENT@[98; 101) "doc" + TOKEN_TREE@[101; 112) + L_PAREN@[101; 102) + STRING@[102; 111) + R_PAREN@[111; 112) + R_BRACK@[112; 113) + WHITESPACE@[113; 122) + MATCH_ARM@[122; 129) + PLACEHOLDER_PAT@[122; 123) + UNDERSCORE@[122; 123) + WHITESPACE@[123; 124) + FAT_ARROW@[124; 126) + WHITESPACE@[126; 127) + TUPLE_EXPR@[127; 129) + L_PAREN@[127; 128) + R_PAREN@[128; 129) + COMMA@[129; 130) + WHITESPACE@[130; 135) + R_CURLY@[135; 136) + WHITESPACE@[136; 137) + R_CURLY@[137; 138) + WHITESPACE@[138; 139) diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0121_match_arms_outer_attributes.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0121_match_arms_outer_attributes.rs new file mode 100644 index 000000000..676db42d1 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0121_match_arms_outer_attributes.rs @@ -0,0 +1,12 @@ +fn foo() { + match () { + #[cfg(feature = "some")] + _ => (), + #[cfg(feature = "other")] + _ => (), + #[cfg(feature = "many")] + #[cfg(feature = "attributes")] + #[cfg(feature = "before")] + _ => (), + } +} diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0121_match_arms_outer_attributes.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0121_match_arms_outer_attributes.txt new file mode 100644 index 000000000..c888fb8f0 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0121_match_arms_outer_attributes.txt @@ -0,0 +1,135 @@ +SOURCE_FILE@[0; 259) + FN_DEF@[0; 258) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 6) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 8) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK@[9; 258) + L_CURLY@[9; 10) + WHITESPACE@[10; 15) + MATCH_EXPR@[15; 256) + MATCH_KW@[15; 20) + WHITESPACE@[20; 21) + TUPLE_EXPR@[21; 23) + L_PAREN@[21; 22) + R_PAREN@[22; 23) + WHITESPACE@[23; 24) + MATCH_ARM_LIST@[24; 256) + L_CURLY@[24; 25) + WHITESPACE@[25; 34) + ATTR@[34; 58) + POUND@[34; 35) + TOKEN_TREE@[35; 58) + L_BRACK@[35; 36) + IDENT@[36; 39) "cfg" + TOKEN_TREE@[39; 57) + L_PAREN@[39; 40) + IDENT@[40; 47) "feature" + WHITESPACE@[47; 48) + EQ@[48; 49) + WHITESPACE@[49; 50) + STRING@[50; 56) + R_PAREN@[56; 57) + R_BRACK@[57; 58) + WHITESPACE@[58; 67) + MATCH_ARM@[67; 74) + PLACEHOLDER_PAT@[67; 68) + UNDERSCORE@[67; 68) + WHITESPACE@[68; 69) + FAT_ARROW@[69; 71) + WHITESPACE@[71; 72) + TUPLE_EXPR@[72; 74) + L_PAREN@[72; 73) + R_PAREN@[73; 74) + COMMA@[74; 75) + WHITESPACE@[75; 84) + ATTR@[84; 109) + POUND@[84; 85) + TOKEN_TREE@[85; 109) + L_BRACK@[85; 86) + IDENT@[86; 89) "cfg" + TOKEN_TREE@[89; 108) + L_PAREN@[89; 90) + IDENT@[90; 97) "feature" + WHITESPACE@[97; 98) + EQ@[98; 99) + WHITESPACE@[99; 100) + STRING@[100; 107) + R_PAREN@[107; 108) + R_BRACK@[108; 109) + WHITESPACE@[109; 118) + MATCH_ARM@[118; 125) + PLACEHOLDER_PAT@[118; 119) + UNDERSCORE@[118; 119) + WHITESPACE@[119; 120) + FAT_ARROW@[120; 122) + WHITESPACE@[122; 123) + TUPLE_EXPR@[123; 125) + L_PAREN@[123; 124) + R_PAREN@[124; 125) + COMMA@[125; 126) + WHITESPACE@[126; 135) + ATTR@[135; 159) + POUND@[135; 136) + TOKEN_TREE@[136; 159) + L_BRACK@[136; 137) + IDENT@[137; 140) "cfg" + TOKEN_TREE@[140; 158) + L_PAREN@[140; 141) + IDENT@[141; 148) "feature" + WHITESPACE@[148; 149) + EQ@[149; 150) + WHITESPACE@[150; 151) + STRING@[151; 157) + R_PAREN@[157; 158) + R_BRACK@[158; 159) + WHITESPACE@[159; 168) + ATTR@[168; 198) + POUND@[168; 169) + TOKEN_TREE@[169; 198) + L_BRACK@[169; 170) + IDENT@[170; 173) "cfg" + TOKEN_TREE@[173; 197) + L_PAREN@[173; 174) + IDENT@[174; 181) "feature" + WHITESPACE@[181; 182) + EQ@[182; 183) + WHITESPACE@[183; 184) + STRING@[184; 196) + R_PAREN@[196; 197) + R_BRACK@[197; 198) + WHITESPACE@[198; 207) + ATTR@[207; 233) + POUND@[207; 208) + TOKEN_TREE@[208; 233) + L_BRACK@[208; 209) + IDENT@[209; 212) "cfg" + TOKEN_TREE@[212; 232) + L_PAREN@[212; 213) + IDENT@[213; 220) "feature" + WHITESPACE@[220; 221) + EQ@[221; 222) + WHITESPACE@[222; 223) + STRING@[223; 231) + R_PAREN@[231; 232) + R_BRACK@[232; 233) + WHITESPACE@[233; 242) + MATCH_ARM@[242; 249) + PLACEHOLDER_PAT@[242; 243) + UNDERSCORE@[242; 243) + WHITESPACE@[243; 244) + FAT_ARROW@[244; 246) + WHITESPACE@[246; 247) + TUPLE_EXPR@[247; 249) + L_PAREN@[247; 248) + R_PAREN@[248; 249) + COMMA@[249; 250) + WHITESPACE@[250; 255) + R_CURLY@[255; 256) + WHITESPACE@[256; 257) + R_CURLY@[257; 258) + WHITESPACE@[258; 259) -- cgit v1.2.3 From 96e3ac389fbc3709cc6e7e8dbe25619daeb61f4b Mon Sep 17 00:00:00 2001 From: Ville Penttinen Date: Sun, 17 Feb 2019 19:48:08 +0200 Subject: Parse only outer_attributes for match arms for now --- crates/ra_syntax/src/grammar/attributes.rs | 10 --- crates/ra_syntax/src/grammar/expressions/atom.rs | 7 +- .../parser/err/0032_match_arms_inner_attrs.txt | 90 ++++++++++++++-------- 3 files changed, 60 insertions(+), 47 deletions(-) diff --git a/crates/ra_syntax/src/grammar/attributes.rs b/crates/ra_syntax/src/grammar/attributes.rs index 2624d2e16..cd30e8a45 100644 --- a/crates/ra_syntax/src/grammar/attributes.rs +++ b/crates/ra_syntax/src/grammar/attributes.rs @@ -1,15 +1,5 @@ use super::*; -/// Parses both inner & outer attributes. -/// -/// Allowing to run validation for reporting errors -/// regarding attributes -pub(super) fn all_attributes(p: &mut Parser) { - while p.at(POUND) { - attribute(p, p.nth(1) == EXCL) - } -} - pub(super) fn inner_attributes(p: &mut Parser) { while p.current() == POUND && p.nth(1) == EXCL { attribute(p, true) diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs index 67cd7e6b0..e74305b6a 100644 --- a/crates/ra_syntax/src/grammar/expressions/atom.rs +++ b/crates/ra_syntax/src/grammar/expressions/atom.rs @@ -331,11 +331,6 @@ pub(crate) fn match_arm_list(p: &mut Parser) { continue; } - // This may result in invalid attributes - // if there are inner attributes mixed in together - // with the outer attributes, but we allow parsing - // those so we can run validation and report better errors - // test match_arms_outer_attributes // fn foo() { // match () { @@ -349,7 +344,7 @@ pub(crate) fn match_arm_list(p: &mut Parser) { // _ => (), // } // } - attributes::all_attributes(p); + attributes::outer_attributes(p); // test match_arms_commas // fn foo() { diff --git a/crates/ra_syntax/tests/data/parser/err/0032_match_arms_inner_attrs.txt b/crates/ra_syntax/tests/data/parser/err/0032_match_arms_inner_attrs.txt index b3ff36364..b7543abc9 100644 --- a/crates/ra_syntax/tests/data/parser/err/0032_match_arms_inner_attrs.txt +++ b/crates/ra_syntax/tests/data/parser/err/0032_match_arms_inner_attrs.txt @@ -33,18 +33,29 @@ SOURCE_FILE@[0; 293) R_PAREN@[40; 41) COMMA@[41; 42) WHITESPACE@[42; 51) - err: `Inner attributes are only allowed directly after the opening brace of the match expression` - ATTR@[51; 78) + ATTR@[51; 52) POUND@[51; 52) - EXCL@[52; 53) - TOKEN_TREE@[53; 78) + err: `expected `[`` + err: `expected pattern` + MATCH_ARM@[52; 78) + ERROR@[52; 53) + EXCL@[52; 53) + err: `expected FAT_ARROW` + ARRAY_EXPR@[53; 78) L_BRACK@[53; 54) - IDENT@[54; 57) "doc" - TOKEN_TREE@[57; 77) - L_PAREN@[57; 58) - STRING@[58; 76) - R_PAREN@[76; 77) + CALL_EXPR@[54; 77) + PATH_EXPR@[54; 57) + PATH@[54; 57) + PATH_SEGMENT@[54; 57) + NAME_REF@[54; 57) + IDENT@[54; 57) "doc" + ARG_LIST@[57; 77) + L_PAREN@[57; 58) + LITERAL@[58; 76) + STRING@[58; 76) + R_PAREN@[76; 77) R_BRACK@[77; 78) + err: `expected COMMA` WHITESPACE@[78; 87) MATCH_ARM@[87; 94) PLACEHOLDER_PAT@[87; 88) @@ -92,23 +103,29 @@ SOURCE_FILE@[0; 293) R_PAREN@[149; 150) COMMA@[150; 151) WHITESPACE@[151; 160) - err: `Inner attributes are only allowed directly after the opening brace of the match expression` - ATTR@[160; 179) + ATTR@[160; 161) POUND@[160; 161) - EXCL@[161; 162) - TOKEN_TREE@[162; 179) + err: `expected `[`` + err: `expected pattern` + MATCH_ARM@[161; 179) + ERROR@[161; 162) + EXCL@[161; 162) + err: `expected FAT_ARROW` + ARRAY_EXPR@[162; 179) L_BRACK@[162; 163) - IDENT@[163; 166) "doc" - TOKEN_TREE@[166; 178) - L_PAREN@[166; 167) - STRING@[167; 177) - R_PAREN@[177; 178) + CALL_EXPR@[163; 178) + PATH_EXPR@[163; 166) + PATH@[163; 166) + PATH_SEGMENT@[163; 166) + NAME_REF@[163; 166) + IDENT@[163; 166) "doc" + ARG_LIST@[166; 178) + L_PAREN@[166; 167) + LITERAL@[167; 177) + STRING@[167; 177) + R_PAREN@[177; 178) R_BRACK@[178; 179) WHITESPACE@[179; 184) - err: `expected pattern` - err: `expected FAT_ARROW` - err: `expected expression` - MATCH_ARM@[184; 184) R_CURLY@[184; 185) WHITESPACE@[185; 191) MATCH_EXPR@[191; 290) @@ -132,18 +149,29 @@ SOURCE_FILE@[0; 293) R_PAREN@[220; 221) R_BRACK@[221; 222) WHITESPACE@[222; 231) - err: `Inner attributes are only allowed directly after the opening brace of the match expression` - ATTR@[231; 250) + ATTR@[231; 232) POUND@[231; 232) - EXCL@[232; 233) - TOKEN_TREE@[233; 250) + err: `expected `[`` + err: `expected pattern` + MATCH_ARM@[232; 250) + ERROR@[232; 233) + EXCL@[232; 233) + err: `expected FAT_ARROW` + ARRAY_EXPR@[233; 250) L_BRACK@[233; 234) - IDENT@[234; 237) "doc" - TOKEN_TREE@[237; 249) - L_PAREN@[237; 238) - STRING@[238; 248) - R_PAREN@[248; 249) + CALL_EXPR@[234; 249) + PATH_EXPR@[234; 237) + PATH@[234; 237) + PATH_SEGMENT@[234; 237) + NAME_REF@[234; 237) + IDENT@[234; 237) "doc" + ARG_LIST@[237; 249) + L_PAREN@[237; 238) + LITERAL@[238; 248) + STRING@[238; 248) + R_PAREN@[248; 249) R_BRACK@[249; 250) + err: `expected COMMA` WHITESPACE@[250; 259) MATCH_ARM@[259; 266) PLACEHOLDER_PAT@[259; 260) -- cgit v1.2.3 From bb259587056faa3a76eed6e7dae487e1848d841a Mon Sep 17 00:00:00 2001 From: Ville Penttinen Date: Sun, 17 Feb 2019 20:32:10 +0200 Subject: Remove match_armlist validator --- crates/ra_syntax/src/validation.rs | 2 -- crates/ra_syntax/src/validation/match_armlist.rs | 28 ------------------------ 2 files changed, 30 deletions(-) delete mode 100644 crates/ra_syntax/src/validation/match_armlist.rs diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index 27a465a78..10672d6bf 100644 --- a/crates/ra_syntax/src/validation.rs +++ b/crates/ra_syntax/src/validation.rs @@ -3,7 +3,6 @@ mod byte_string; mod char; mod string; mod block; -mod match_armlist; use crate::{ SourceFile, syntax_node::SyntaxError, AstNode, @@ -20,7 +19,6 @@ pub(crate) fn validate(file: &SourceFile) -> Vec { .visit::(self::char::validate_char_node) .visit::(self::string::validate_string_node) .visit::(self::block::validate_block_node) - .visit::(self::match_armlist::validate_match_armlist) .accept(node); } errors diff --git a/crates/ra_syntax/src/validation/match_armlist.rs b/crates/ra_syntax/src/validation/match_armlist.rs deleted file mode 100644 index c43ed7092..000000000 --- a/crates/ra_syntax/src/validation/match_armlist.rs +++ /dev/null @@ -1,28 +0,0 @@ -use crate::{ - ast::{self, AttrsOwner, AstNode}, - syntax_node::{ - SyntaxError, - SyntaxErrorKind::*, - Direction, - }, -}; - -pub(crate) fn validate_match_armlist(node: &ast::MatchArmList, errors: &mut Vec) { - // Report errors for any inner attribute - // which has a preceding matcharm or an outer attribute - for inner_attr in node.attrs().filter(|s| s.is_inner()) { - let any_errors = inner_attr.syntax().siblings(Direction::Prev).any(|s| { - match (ast::MatchArm::cast(s), ast::Attr::cast(s)) { - (Some(_), _) => true, - // Outer attributes which preceed an inner attribute are not allowed - (_, Some(a)) if !a.is_inner() => true, - (_, Some(_)) => false, - (None, None) => false, - } - }); - - if any_errors { - errors.push(SyntaxError::new(InvalidMatchInnerAttr, inner_attr.syntax().range())); - } - } -} -- cgit v1.2.3