diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs index 3fd7613678..9d8127a3d4 100644 --- a/crates/ra_syntax/src/ast/generated/nodes.rs +++ b/crates/ra_syntax/src/ast/generated/nodes.rs @@ -268,6 +268,36 @@ pub struct Rename { impl ast::NameOwner for Rename {} impl Rename { pub fn as_token(&self) -> Option { support::token(&self.syntax, T![as]) } + pub fn underscore_token(&self) -> Option { support::token(&self.syntax, T![_]) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct UseTree { + pub(crate) syntax: SyntaxNode, +} +impl UseTree { + pub fn path(&self) -> Option { support::child(&self.syntax) } + pub fn coloncolon_token(&self) -> Option { support::token(&self.syntax, T![::]) } + pub fn star_token(&self) -> Option { support::token(&self.syntax, T![*]) } + pub fn use_tree_list(&self) -> Option { support::child(&self.syntax) } + pub fn rename(&self) -> Option { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Path { + pub(crate) syntax: SyntaxNode, +} +impl Path { + pub fn qualifier(&self) -> Option { support::child(&self.syntax) } + pub fn coloncolon_token(&self) -> Option { support::token(&self.syntax, T![::]) } + pub fn segment(&self) -> Option { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct UseTreeList { + pub(crate) syntax: SyntaxNode, +} +impl UseTreeList { + pub fn l_curly_token(&self) -> Option { support::token(&self.syntax, T!['{']) } + pub fn use_trees(&self) -> AstChildren { support::children(&self.syntax) } + pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Abi { @@ -433,15 +463,6 @@ impl PathType { pub fn path(&self) -> Option { support::child(&self.syntax) } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Path { - pub(crate) syntax: SyntaxNode, -} -impl Path { - pub fn qualifier(&self) -> Option { support::child(&self.syntax) } - pub fn coloncolon_token(&self) -> Option { support::token(&self.syntax, T![::]) } - pub fn segment(&self) -> Option { support::child(&self.syntax) } -} -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct PointerType { pub(crate) syntax: SyntaxNode, } @@ -1178,26 +1199,6 @@ impl Param { pub fn dotdotdot_token(&self) -> Option { support::token(&self.syntax, T![...]) } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct UseTree { - pub(crate) syntax: SyntaxNode, -} -impl UseTree { - pub fn path(&self) -> Option { support::child(&self.syntax) } - pub fn coloncolon_token(&self) -> Option { support::token(&self.syntax, T![::]) } - pub fn star_token(&self) -> Option { support::token(&self.syntax, T![*]) } - pub fn use_tree_list(&self) -> Option { support::child(&self.syntax) } - pub fn rename(&self) -> Option { support::child(&self.syntax) } -} -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct UseTreeList { - pub(crate) syntax: SyntaxNode, -} -impl UseTreeList { - pub fn l_curly_token(&self) -> Option { support::token(&self.syntax, T!['{']) } - pub fn use_trees(&self) -> AstChildren { support::children(&self.syntax) } - pub fn r_curly_token(&self) -> Option { support::token(&self.syntax, T!['}']) } -} -#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct PathSegment { pub(crate) syntax: SyntaxNode, } @@ -1627,6 +1628,39 @@ impl AstNode for Rename { } fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl AstNode for UseTree { + fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for Path { + fn can_cast(kind: SyntaxKind) -> bool { kind == PATH } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for UseTreeList { + fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE_LIST } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} impl AstNode for Abi { fn can_cast(kind: SyntaxKind) -> bool { kind == ABI } fn cast(syntax: SyntaxNode) -> Option { @@ -1825,17 +1859,6 @@ impl AstNode for PathType { } fn syntax(&self) -> &SyntaxNode { &self.syntax } } -impl AstNode for Path { - fn can_cast(kind: SyntaxKind) -> bool { kind == PATH } - fn cast(syntax: SyntaxNode) -> Option { - if Self::can_cast(syntax.kind()) { - Some(Self { syntax }) - } else { - None - } - } - fn syntax(&self) -> &SyntaxNode { &self.syntax } -} impl AstNode for PointerType { fn can_cast(kind: SyntaxKind) -> bool { kind == POINTER_TYPE } fn cast(syntax: SyntaxNode) -> Option { @@ -2672,28 +2695,6 @@ impl AstNode for Param { } fn syntax(&self) -> &SyntaxNode { &self.syntax } } -impl AstNode for UseTree { - fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE } - fn cast(syntax: SyntaxNode) -> Option { - if Self::can_cast(syntax.kind()) { - Some(Self { syntax }) - } else { - None - } - } - fn syntax(&self) -> &SyntaxNode { &self.syntax } -} -impl AstNode for UseTreeList { - fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE_LIST } - fn cast(syntax: SyntaxNode) -> Option { - if Self::can_cast(syntax.kind()) { - Some(Self { syntax }) - } else { - None - } - } - fn syntax(&self) -> &SyntaxNode { &self.syntax } -} impl AstNode for PathSegment { fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_SEGMENT } fn cast(syntax: SyntaxNode) -> Option { @@ -3560,6 +3561,21 @@ impl std::fmt::Display for Rename { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for UseTree { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for Path { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for UseTreeList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for Abi { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -3650,11 +3666,6 @@ impl std::fmt::Display for PathType { std::fmt::Display::fmt(self.syntax(), f) } } -impl std::fmt::Display for Path { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - std::fmt::Display::fmt(self.syntax(), f) - } -} impl std::fmt::Display for PointerType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -4035,16 +4046,6 @@ impl std::fmt::Display for Param { std::fmt::Display::fmt(self.syntax(), f) } } -impl std::fmt::Display for UseTree { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - std::fmt::Display::fmt(self.syntax(), f) - } -} -impl std::fmt::Display for UseTreeList { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - std::fmt::Display::fmt(self.syntax(), f) - } -} impl std::fmt::Display for PathSegment { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 9b49712c13..c77fc8a8d0 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -543,6 +543,10 @@ fn lower_enum(grammar: &Grammar, rule: &Rule) -> Option> { } fn lower_rule(acc: &mut Vec, grammar: &Grammar, rule: &Rule) { + if lower_comma_list(acc, grammar, rule) { + return; + } + match rule { Rule::Node(node) => { let field = Field::Node { name: grammar[*node].name.clone(), src: FieldSrc::Shorthand }; @@ -595,6 +599,37 @@ fn lower_rule(acc: &mut Vec, grammar: &Grammar, rule: &Rule) { } } +// (T (',' T)* ','?)? +fn lower_comma_list(acc: &mut Vec, grammar: &Grammar, rule: &Rule) -> bool { + let rule = match rule { + Rule::Opt(it) => it, + _ => return false, + }; + let rule = match &**rule { + Rule::Seq(it) => it, + _ => return false, + }; + let (node, repeat, trailing_comma) = match rule.as_slice() { + [Rule::Node(node), Rule::Rep(repeat), Rule::Opt(trailing_comma)] => { + (node, repeat, trailing_comma) + } + _ => return false, + }; + let repeat = match &**repeat { + Rule::Seq(it) => it, + _ => return false, + }; + match repeat.as_slice() { + [comma, Rule::Node(n)] if comma == &**trailing_comma && n == node => (), + _ => return false, + } + let name = grammar[*node].name.clone(); + let label = pluralize(&to_lower_snake_case(&name)); + let field = Field::Node { name: label.clone(), src: FieldSrc::Many(name) }; + acc.push(field); + true +} + fn deduplicate_fields(ast: &mut AstSrc) { for node in &mut ast.nodes { let mut i = 0; diff --git a/xtask/src/codegen/rust.ungram b/xtask/src/codegen/rust.ungram index e6e7c7518f..2ba68457fd 100644 --- a/xtask/src/codegen/rust.ungram +++ b/xtask/src/codegen/rust.ungram @@ -29,6 +29,19 @@ ItemList = ExternCrate = Attr* Visibility? 'extern' 'crate' (NameRef | 'self') Rename? ';' +Rename = + 'as' (Name | '_') + +UseItem = + Attr* Visibility? 'use' UseTree ';' + +UseTree = + (Path? '::')? ('*' | UseTreeList ) +| Path Rename? + +UseTreeList = + '{' (UseTree (',' UseTree)* ','?)? '}' + FnDef = Attr* Visibility? Abi? 'const' 'default' 'async' 'unsafe' 'fn' Name TypeParamList? ParamList RetType? @@ -395,18 +408,6 @@ Param = Attr* Pat (':' ascribed_type:TypeRef) | '...' -UseItem = - Attr* Visibility? 'use' UseTree ';' - -UseTree = - Path ('::' ('*' | UseTreeList)) Rename? - -UseTreeList = - '{' UseTree* '}' - -Rename = - 'as' Name - Path = (qualifier:Path '::')? segment:PathSegment