From 60f4d7bd8c0ecb9f23557464e824140a2be8f41a Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Fri, 3 Apr 2020 21:12:09 +0200 Subject: Provide more complete AST accessors to support usage in rustc --- xtask/src/ast_src.rs | 383 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 292 insertions(+), 91 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index d9f51ec39..3200acc86 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs @@ -70,7 +70,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { "match", "mod", "move", "mut", "pub", "ref", "return", "self", "static", "struct", "super", "trait", "true", "try", "type", "unsafe", "use", "where", "while", ], - contextual_keywords: &["auto", "default", "existential", "union"], + contextual_keywords: &["auto", "default", "existential", "union", "raw"], literals: &[ "INT_NUMBER", "FLOAT_NUMBER", @@ -297,235 +297,311 @@ macro_rules! ast_enums { pub(crate) const AST_SRC: AstSrc = AstSrc { nodes: &ast_nodes! { - struct SourceFile: ModuleItemOwner, FnDefOwner { + struct SourceFile: ModuleItemOwner, FnDefOwner, AttrsOwner { modules: [Module], } struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner { + Abi, + ConstKw, + DefaultKw, + AsyncKw, + UnsafeKw, + FnKw, ParamList, RetType, body: BlockExpr, + Semi } - struct RetType { TypeRef } + struct RetType { ThinArrow, TypeRef } struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { + StructKw, + FieldDefList, + Semi } struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { + UnionKw, RecordFieldDefList, } - struct RecordFieldDefList { fields: [RecordFieldDef] } + struct RecordFieldDefList { LCurly, fields: [RecordFieldDef], RCurly } struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { } - struct TupleFieldDefList { fields: [TupleFieldDef] } + struct TupleFieldDefList { LParen, fields: [TupleFieldDef], RParen } struct TupleFieldDef: VisibilityOwner, AttrsOwner { TypeRef, } struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { + EnumKw, variant_list: EnumVariantList, } struct EnumVariantList { + LCurly, variants: [EnumVariant], + RCurly } - struct EnumVariant: NameOwner, DocCommentsOwner, AttrsOwner { + struct EnumVariant: VisibilityOwner, NameOwner, DocCommentsOwner, AttrsOwner { + FieldDefList, + Eq, Expr } struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner { + UnsafeKw, + AutoKw, + TraitKw, ItemList, } struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner { + ModKw, ItemList, + Semi } struct ItemList: FnDefOwner, ModuleItemOwner { + LCurly, impl_items: [ImplItem], + RCurly } struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { + DefaultKw, + ConstKw, + Eq, body: Expr, + Semi } struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { + StaticKw, + MutKw, + Eq, body: Expr, + Semi } struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner { + DefaultKw, + TypeKw, + Eq, TypeRef, + Semi } struct ImplDef: TypeParamsOwner, AttrsOwner { + DefaultKw, + ConstKw, + UnsafeKw, + ImplKw, + Excl, + ForKw, ItemList, } - struct ParenType { TypeRef } - struct TupleType { fields: [TypeRef] } - struct NeverType { } + struct ParenType { LParen, TypeRef, RParen } + struct TupleType { LParen, fields: [TypeRef], RParen } + struct NeverType { Excl } struct PathType { Path } - struct PointerType { TypeRef } - struct ArrayType { TypeRef, Expr } - struct SliceType { TypeRef } - struct ReferenceType { TypeRef } - struct PlaceholderType { } - struct FnPointerType { ParamList, RetType } - struct ForType { TypeRef } - struct ImplTraitType: TypeBoundsOwner {} - struct DynTraitType: TypeBoundsOwner {} - - struct TupleExpr { exprs: [Expr] } - struct ArrayExpr { exprs: [Expr] } - struct ParenExpr { Expr } + struct PointerType { Star, ConstKw, TypeRef } + struct ArrayType { LBrack, TypeRef, Semi, Expr, RBrack } + struct SliceType { LBrack, TypeRef, RBrack } + struct ReferenceType { Amp, Lifetime, MutKw, TypeRef } + struct PlaceholderType { Underscore } + struct FnPointerType { Abi, UnsafeKw, FnKw, ParamList, RetType } + struct ForType { ForKw, TypeParamList, TypeRef } + struct ImplTraitType: TypeBoundsOwner { ImplKw } + struct DynTraitType: TypeBoundsOwner { DynKw } + + struct TupleExpr: AttrsOwner { LParen, exprs: [Expr], RParen } + struct ArrayExpr: AttrsOwner { LBrack, exprs: [Expr], Semi, RBrack } + struct ParenExpr: AttrsOwner { LParen, Expr, RParen } struct PathExpr { Path } - struct LambdaExpr { + struct LambdaExpr: AttrsOwner { + StaticKw, + AsyncKw, + MoveKw, ParamList, RetType, body: Expr, } - struct IfExpr { Condition } - struct LoopExpr: LoopBodyOwner { } - struct TryBlockExpr { body: BlockExpr } - struct ForExpr: LoopBodyOwner { + struct IfExpr: AttrsOwner { IfKw, Condition } + struct LoopExpr: AttrsOwner, LoopBodyOwner { LoopKw } + struct TryBlockExpr: AttrsOwner { TryKw, body: BlockExpr } + struct ForExpr: AttrsOwner, LoopBodyOwner { + ForKw, Pat, + InKw, iterable: Expr, } - struct WhileExpr: LoopBodyOwner { Condition } - struct ContinueExpr {} - struct BreakExpr { Expr } - struct Label {} - struct BlockExpr { Block } - struct ReturnExpr { Expr } + struct WhileExpr: AttrsOwner, LoopBodyOwner { WhileKw, Condition } + struct ContinueExpr: AttrsOwner { ContinueKw, Lifetime } + struct BreakExpr: AttrsOwner { BreakKw, Lifetime, Expr } + struct Label { Lifetime } + struct BlockExpr: AttrsOwner { Label, UnsafeKw, Block } + struct ReturnExpr: AttrsOwner { Expr } struct CallExpr: ArgListOwner { Expr } - struct MethodCallExpr: ArgListOwner { - Expr, NameRef, TypeArgList, - } - struct IndexExpr {} - struct FieldExpr { Expr, NameRef } - struct AwaitExpr { Expr } - struct TryExpr { Expr } - struct CastExpr { Expr, TypeRef } - struct RefExpr { Expr } - struct PrefixExpr { Expr } - struct BoxExpr { Expr } - struct RangeExpr {} - struct BinExpr {} - struct Literal {} - - struct MatchExpr { Expr, MatchArmList } - struct MatchArmList: AttrsOwner { arms: [MatchArm] } + struct MethodCallExpr: AttrsOwner, ArgListOwner { + Expr, Dot, NameRef, TypeArgList, + } + struct IndexExpr: AttrsOwner { LBrack, RBrack } + struct FieldExpr: AttrsOwner { Expr, Dot, NameRef } + struct AwaitExpr: AttrsOwner { Expr, Dot, AwaitKw } + struct TryExpr: AttrsOwner { TryKw, Expr } + struct CastExpr: AttrsOwner { Expr, AsKw, TypeRef } + struct RefExpr: AttrsOwner { Amp, RawKw, MutKw, Expr } + struct PrefixExpr: AttrsOwner { PrefixOp, Expr } + struct BoxExpr: AttrsOwner { BoxKw, Expr } + struct RangeExpr: AttrsOwner { RangeOp } + struct BinExpr: AttrsOwner { BinOp } + struct Literal { LiteralToken } + + struct MatchExpr: AttrsOwner { MatchKw, Expr, MatchArmList } + struct MatchArmList: AttrsOwner { LCurly, arms: [MatchArm], RCurly } struct MatchArm: AttrsOwner { pat: Pat, guard: MatchGuard, + FatArrow, Expr, } - struct MatchGuard { Expr } + struct MatchGuard { IfKw, Expr } - struct RecordLit { Path, RecordFieldList } + struct RecordLit { Path, RecordFieldList} struct RecordFieldList { + LCurly, fields: [RecordField], + Dotdot, spread: Expr, + RCurly } - struct RecordField { NameRef, Expr } + struct RecordField: AttrsOwner { NameRef, Colon, Expr } struct OrPat { pats: [Pat] } - struct ParenPat { Pat } - struct RefPat { Pat } - struct BoxPat { Pat } - struct BindPat: NameOwner { Pat } - struct PlaceholderPat { } - struct DotDotPat { } + struct ParenPat { LParen, Pat, RParen } + struct RefPat { Amp, MutKw, Pat } + struct BoxPat { BoxKw, Pat } + struct BindPat: AttrsOwner, NameOwner { RefKw, MutKw, Pat } + struct PlaceholderPat { Underscore } + struct DotDotPat { Dotdot } struct PathPat { Path } - struct SlicePat { args: [Pat] } - struct RangePat {} + struct SlicePat { LBrack, args: [Pat], RBrack } + struct RangePat { RangeSeparator } struct LiteralPat { Literal } struct MacroPat { MacroCall } struct RecordPat { RecordFieldPatList, Path } struct RecordFieldPatList { + LCurly, + pats: [RecordInnerPat], record_field_pats: [RecordFieldPat], bind_pats: [BindPat], + Dotdot, + RCurly } - struct RecordFieldPat: NameOwner { Pat } + struct RecordFieldPat: AttrsOwner, NameOwner { Colon, Pat } - struct TupleStructPat { Path, args: [Pat] } - struct TuplePat { args: [Pat] } + struct TupleStructPat { Path, LParen, args: [Pat], RParen } + struct TuplePat { LParen, args: [Pat], RParen } - struct Visibility {} - struct Name {} - struct NameRef {} + struct Visibility { PubKw, SuperKw, SelfKw, CrateKw } + struct Name { Ident } + struct NameRef { NameRefToken } struct MacroCall: NameOwner, AttrsOwner,DocCommentsOwner { - TokenTree, Path + Path, Excl, TokenTree, Semi } - struct Attr { Path, input: AttrInput } + struct Attr { Pound, Excl, LBrack, Path, Eq, input: AttrInput, RBrack } struct TokenTree {} struct TypeParamList { + LAngle, + generic_params: [GenericParam], type_params: [TypeParam], lifetime_params: [LifetimeParam], + const_params: [ConstParam], + RAngle } struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner { + Eq, default_type: TypeRef, } struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner { + Eq, default_val: Expr, } - struct LifetimeParam: AttrsOwner { } - struct TypeBound { TypeRef} + struct LifetimeParam: AttrsOwner { Lifetime} + struct TypeBound { Lifetime, /* Question, */ ConstKw, /* Question, */ TypeRef} struct TypeBoundList { bounds: [TypeBound] } - struct WherePred: TypeBoundsOwner { TypeRef } - struct WhereClause { predicates: [WherePred] } - struct ExprStmt { Expr } - struct LetStmt: TypeAscriptionOwner { + struct WherePred: TypeBoundsOwner { Lifetime, TypeRef } + struct WhereClause { WhereKw, predicates: [WherePred] } + struct Abi { String } + struct ExprStmt: AttrsOwner { Expr, Semi } + struct LetStmt: AttrsOwner, TypeAscriptionOwner { + LetKw, Pat, + Eq, initializer: Expr, } - struct Condition { Pat, Expr } + struct Condition { LetKw, Pat, Eq, Expr } struct Block: AttrsOwner, ModuleItemOwner { + LCurly, statements: [Stmt], + statements_or_semi: [StmtOrSemi], Expr, + RCurly, } struct ParamList { + LParen, SelfParam, params: [Param], + RParen } - struct SelfParam: TypeAscriptionOwner, AttrsOwner { } + struct SelfParam: TypeAscriptionOwner, AttrsOwner { Amp, Lifetime, SelfKw } struct Param: TypeAscriptionOwner, AttrsOwner { Pat, + Dotdotdot } struct UseItem: AttrsOwner, VisibilityOwner { + UseKw, UseTree, } struct UseTree { - Path, UseTreeList, Alias + Path, Star, UseTreeList, Alias } - struct Alias: NameOwner { } - struct UseTreeList { use_trees: [UseTree] } + struct Alias: NameOwner { AsKw } + struct UseTreeList { LCurly, use_trees: [UseTree], RCurly } struct ExternCrateItem: AttrsOwner, VisibilityOwner { - NameRef, Alias, + ExternKw, CrateKw, NameRef, Alias, } struct ArgList { + LParen, args: [Expr], + RParen } struct Path { segment: PathSegment, qualifier: Path, } struct PathSegment { - NameRef, TypeArgList, ParamList, RetType, PathType, + Coloncolon, LAngle, NameRef, TypeArgList, ParamList, RetType, PathType, RAngle } struct TypeArgList { + Coloncolon, + LAngle, + generic_args: [GenericArg], type_args: [TypeArg], lifetime_args: [LifetimeArg], assoc_type_args: [AssocTypeArg], - const_arg: [ConstArg], + const_args: [ConstArg], + RAngle } struct TypeArg { TypeRef } - struct AssocTypeArg { NameRef, TypeRef } - struct LifetimeArg {} - struct ConstArg { Literal, BlockExpr } + struct AssocTypeArg : TypeBoundsOwner { NameRef, Eq, TypeRef } + struct LifetimeArg { Lifetime } + struct ConstArg { Literal, Eq, BlockExpr } struct MacroItems: ModuleItemOwner, FnDefOwner { } @@ -533,12 +609,44 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { statements: [Stmt], Expr, } + + struct ExternItemList: FnDefOwner, ModuleItemOwner { + LCurly, + extern_items: [ExternItem], + RCurly + } + + struct ExternBlock { + Abi, + ExternItemList + } + + struct MetaItem { + Path, Eq, AttrInput, nested_meta_items: [MetaItem] + } + + struct MacroDef { + Name, TokenTree + } }, enums: &ast_enums! { enum NominalDef: NameOwner, TypeParamsOwner, AttrsOwner { StructDef, EnumDef, UnionDef, } + enum GenericParam { + LifetimeParam, + TypeParam, + ConstParam + } + + enum GenericArg { + LifetimeArg, + TypeArg, + ConstArg, + AssocTypeArg + } + enum TypeRef { ParenType, TupleType, @@ -555,7 +663,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { DynTraitType, } - enum ModuleItem: AttrsOwner, VisibilityOwner { + enum ModuleItem: NameOwner, AttrsOwner, VisibilityOwner { StructDef, UnionDef, EnumDef, @@ -569,13 +677,20 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { StaticDef, Module, MacroCall, + ExternBlock } - enum ImplItem: AttrsOwner { - FnDef, TypeAliasDef, ConstDef, + /* impl blocks can also contain MacroCall */ + enum ImplItem: NameOwner, AttrsOwner { + FnDef, TypeAliasDef, ConstDef } - enum Expr { + /* extern blocks can also contain MacroCall */ + enum ExternItem: NameOwner, AttrsOwner, VisibilityOwner { + FnDef, StaticDef + } + + enum Expr: AttrsOwner { TupleExpr, ArrayExpr, ParenExpr, @@ -627,7 +742,93 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { MacroPat, } + enum RecordInnerPat { + RecordFieldPat, + BindPat + } + enum AttrInput { Literal, TokenTree } - enum Stmt { ExprStmt, LetStmt } + enum Stmt { + ModuleItem, + LetStmt, + ExprStmt, + // macro calls are parsed as expression statements */ + } + enum StmtOrSemi {Stmt, Semi} + + enum LeftDelimiter { LParen, LBrack, LCurly } + enum RightDelimiter { RParen, RBrack, RCurly } + enum RangeSeparator { Dotdot, Dotdotdot, Dotdoteq} + + enum BinOp { + Pipepipe, + Ampamp, + Eqeq, + Neq, + Lteq, + Gteq, + LAngle, + RAngle, + Plus, + Star, + Minus, + Slash, + Percent, + Shl, + Shr, + Caret, + Pipe, + Amp, + Eq, + Pluseq, + Slasheq, + Stareq, + Percenteq, + Shreq, + Shleq, + Minuseq, + Pipeeq, + Ampeq, + Careteq, + } + + enum PrefixOp { + Minus, + Excl, + Star + } + + enum RangeOp { + Dotdot, + Dotdoteq + } + + enum LiteralToken { + IntNumber, + FloatNumber, + String, + RawString, + TrueKw, + FalseKw, + ByteString, + RawByteString, + Char, + Byte + } + + enum NameRefToken { + Ident, + IntNumber + } + + enum FieldDefList { + RecordFieldDefList, + TupleFieldDefList, + } + + enum AttrOrComment { + Attr, + Comment + } }, }; -- cgit v1.2.3 From 689661c95968cb438f8bd1f10ce0ee096287741b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 9 Apr 2020 13:00:09 +0200 Subject: Scale back to only two traits --- xtask/src/ast_src.rs | 8 ---- xtask/src/codegen/gen_syntax.rs | 87 +++++++++++++++++++++++++++-------------- 2 files changed, 58 insertions(+), 37 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index 3200acc86..5fed777ac 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs @@ -549,7 +549,6 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { struct Block: AttrsOwner, ModuleItemOwner { LCurly, statements: [Stmt], - statements_or_semi: [StmtOrSemi], Expr, RCurly, } @@ -749,12 +748,10 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { enum AttrInput { Literal, TokenTree } enum Stmt { - ModuleItem, LetStmt, ExprStmt, // macro calls are parsed as expression statements */ } - enum StmtOrSemi {Stmt, Semi} enum LeftDelimiter { LParen, LBrack, LCurly } enum RightDelimiter { RParen, RBrack, RCurly } @@ -825,10 +822,5 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { RecordFieldDefList, TupleFieldDefList, } - - enum AttrOrComment { - Attr, - Comment - } }, }; diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 2dfb68371..6dae93aa2 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -146,14 +146,23 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { FieldSrc::Many(_) => { quote! { pub fn #method_name(&self) -> AstChildren<#ty> { - AstChildren::new(&self.syntax) + support::children(&self.syntax) } } } FieldSrc::Optional(_) | FieldSrc::Shorthand => { - quote! { - pub fn #method_name(&self) -> Option<#ty> { - AstChildren::new(&self.syntax).next() + let is_token = element_kinds_map[&ty.to_string()].has_tokens; + if is_token { + quote! { + pub fn #method_name(&self) -> Option<#ty> { + support::token(&self.syntax) + } + } + } else { + quote! { + pub fn #method_name(&self) -> Option<#ty> { + support::child(&self.syntax) + } } } } @@ -205,6 +214,48 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { quote!(impl ast::#trait_name for #name {}) }); + let element_kinds = &element_kinds_map[&en.name.to_string()]; + assert!( + element_kinds.has_nodes ^ element_kinds.has_tokens, + "{}: {:#?}", + name, + element_kinds + ); + let specific_ast_trait = { + let (ast_trait, syntax_type) = if element_kinds.has_tokens { + (quote!(AstToken), quote!(SyntaxToken)) + } else { + (quote!(AstNode), quote!(SyntaxNode)) + }; + + quote! { + impl #ast_trait for #name { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + #(#kinds)|* => true, + _ => false, + } + } + fn cast(syntax: #syntax_type) -> Option { + let res = match syntax.kind() { + #( + #kinds => #name::#variants(#variants { syntax }), + )* + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &#syntax_type { + match self { + #( + #name::#variants(it) => &it.syntax, + )* + } + } + } + } + }; + quote! { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum #name { @@ -225,30 +276,8 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { } } - impl AstNode for #name { - fn can_cast(kind: SyntaxKind) -> bool { - match kind { - #(#kinds)|* => true, - _ => false, - } - } - fn cast(syntax: SyntaxNode) -> Option { - let res = match syntax.kind() { - #( - #kinds => #name::#variants(#variants { syntax }), - )* - _ => return None, - }; - Some(res) - } - fn syntax(&self) -> &SyntaxNode { - match self { - #( - #name::#variants(it) => &it.syntax, - )* - } - } - } + #specific_ast_trait + #(#traits)* } }); @@ -268,7 +297,7 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { #[allow(unused_imports)] use crate::{ SyntaxNode, SyntaxToken, SyntaxElement, NodeOrToken, SyntaxKind::{self, *}, - ast::{self, AstNode, AstToken, AstChildren}, + ast::{self, AstNode, AstToken, AstChildren, support}, }; #(#tokens)* -- cgit v1.2.3 From 6379061e21dffd0faf6225484a1550a0ecc523cf Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 9 Apr 2020 15:47:48 +0200 Subject: Cleanup import --- xtask/src/codegen/gen_syntax.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 6dae93aa2..af7d4ffac 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -3,10 +3,13 @@ //! Specifically, it generates the `SyntaxKind` enum and a number of newtype //! wrappers around `SyntaxNode` which implement `ra_syntax::AstNode`. +use std::{ + borrow::Cow, + collections::{BTreeSet, HashMap, HashSet}, +}; + use proc_macro2::{Punct, Spacing}; use quote::{format_ident, quote}; -use std::borrow::Cow; -use std::collections::{BTreeSet, HashMap, HashSet}; use crate::{ ast_src::{AstSrc, FieldSrc, KindsSrc, AST_SRC, KINDS_SRC}, -- cgit v1.2.3 From 0fc8c5cca01501b3b6b708b0ba9ba94c0a81f69e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 9 Apr 2020 15:49:17 +0200 Subject: Reduce visibility --- xtask/src/codegen.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index a53d57335..104399f7f 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -22,8 +22,8 @@ const GRAMMAR_DIR: &str = "crates/ra_parser/src/grammar"; const OK_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/ok"; const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/err"; -pub const SYNTAX_KINDS: &str = "crates/ra_parser/src/syntax_kind/generated.rs"; -pub const AST: &str = "crates/ra_syntax/src/ast/generated.rs"; +const SYNTAX_KINDS: &str = "crates/ra_parser/src/syntax_kind/generated.rs"; +const AST: &str = "crates/ra_syntax/src/ast/generated.rs"; const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers"; const ASSISTS_TESTS: &str = "crates/ra_assists/src/doc_tests/generated.rs"; -- cgit v1.2.3 From d61932ef7e74f3d9f7863c33c6647c2c52538ed5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 9 Apr 2020 16:17:18 +0200 Subject: Prepare for spliting generated into tokens and nodes --- xtask/src/codegen.rs | 2 +- xtask/src/codegen/gen_syntax.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index 104399f7f..e6ba2009c 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -23,7 +23,7 @@ const OK_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/ok"; const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/err"; const SYNTAX_KINDS: &str = "crates/ra_parser/src/syntax_kind/generated.rs"; -const AST: &str = "crates/ra_syntax/src/ast/generated.rs"; +const AST_NODES: &str = "crates/ra_syntax/src/ast/generated/nodes.rs"; const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers"; const ASSISTS_TESTS: &str = "crates/ra_assists/src/doc_tests/generated.rs"; diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index af7d4ffac..c2734d638 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -22,7 +22,7 @@ pub fn generate_syntax(mode: Mode) -> Result<()> { let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?; update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; - let ast_file = project_root().join(codegen::AST); + let ast_file = project_root().join(codegen::AST_NODES); let ast = generate_ast(KINDS_SRC, AST_SRC)?; update(ast_file.as_path(), &ast, mode)?; -- cgit v1.2.3 From 59b6b2278b7f7d2089b5caf6fcfd57528d9aafd0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 9 Apr 2020 16:25:06 +0200 Subject: Start ast/generated/tokens --- xtask/src/codegen.rs | 1 + xtask/src/codegen/gen_syntax.rs | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index e6ba2009c..678b40133 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -24,6 +24,7 @@ const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/err const SYNTAX_KINDS: &str = "crates/ra_parser/src/syntax_kind/generated.rs"; const AST_NODES: &str = "crates/ra_syntax/src/ast/generated/nodes.rs"; +const AST_TOKENS: &str = "crates/ra_syntax/src/ast/generated/tokens.rs"; const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers"; const ASSISTS_TESTS: &str = "crates/ra_assists/src/doc_tests/generated.rs"; diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index c2734d638..75bcd1973 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -22,9 +22,13 @@ pub fn generate_syntax(mode: Mode) -> Result<()> { let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?; update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; - let ast_file = project_root().join(codegen::AST_NODES); - let ast = generate_ast(KINDS_SRC, AST_SRC)?; - update(ast_file.as_path(), &ast, mode)?; + let ast_nodes_file = project_root().join(codegen::AST_NODES); + let contents = generate_ast(KINDS_SRC, AST_SRC)?; + update(ast_nodes_file.as_path(), &contents, mode)?; + + let ast_tokens_file = project_root().join(codegen::AST_TOKENS); + let contents = "//! Generated file, do not edit by hand, see `xtask/src/codegen`"; + update(ast_tokens_file.as_path(), &contents, mode)?; Ok(()) } -- cgit v1.2.3 From c80795e27491527487f97368be54b4467eb8b41e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 9 Apr 2020 17:47:46 +0200 Subject: Move generated tokens to a separate file --- xtask/src/codegen/gen_syntax.rs | 98 +++++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 37 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 75bcd1973..683901a0a 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -23,11 +23,11 @@ pub fn generate_syntax(mode: Mode) -> Result<()> { update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; let ast_nodes_file = project_root().join(codegen::AST_NODES); - let contents = generate_ast(KINDS_SRC, AST_SRC)?; + let contents = generate_nodes(KINDS_SRC, AST_SRC)?; update(ast_nodes_file.as_path(), &contents, mode)?; let ast_tokens_file = project_root().join(codegen::AST_TOKENS); - let contents = "//! Generated file, do not edit by hand, see `xtask/src/codegen`"; + let contents = generate_tokens(KINDS_SRC, AST_SRC)?; update(ast_tokens_file.as_path(), &contents, mode)?; Ok(()) @@ -40,7 +40,62 @@ struct ElementKinds { has_tokens: bool, } -fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { +fn generate_tokens(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { + let all_token_kinds: Vec<_> = kinds + .punct + .into_iter() + .map(|(_, kind)| kind) + .copied() + .map(|x| x.into()) + .chain( + kinds + .keywords + .into_iter() + .chain(kinds.contextual_keywords.into_iter()) + .map(|name| Cow::Owned(format!("{}_KW", to_upper_snake_case(&name)))), + ) + .chain(kinds.literals.into_iter().copied().map(|x| x.into())) + .chain(kinds.tokens.into_iter().copied().map(|x| x.into())) + .collect(); + let tokens = all_token_kinds.iter().map(|kind_str| { + let kind_str = &**kind_str; + let kind = format_ident!("{}", kind_str); + let name = format_ident!("{}", to_pascal_case(kind_str)); + quote! { + #[derive(Debug, Clone, PartialEq, Eq, Hash)] + pub struct #name { + pub(crate) syntax: SyntaxToken, + } + + impl std::fmt::Display for #name { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.syntax, f) + } + } + + impl AstToken for #name { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + #kind => true, + _ => false, + } + } + fn cast(syntax: SyntaxToken) -> Option { + if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } + } + fn syntax(&self) -> &SyntaxToken { &self.syntax } + } + } + }); + + crate::reformat(quote! { + use crate::{SyntaxToken, SyntaxKind::{self, *}, ast::AstToken}; + + #(#tokens)* + }) +} + +fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { let all_token_kinds: Vec<_> = kinds .punct .into_iter() @@ -98,37 +153,6 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { element_kinds_map.insert(en.name.to_string(), element_kinds); } - let tokens = all_token_kinds.iter().map(|kind_str| { - let kind_str = &**kind_str; - let kind = format_ident!("{}", kind_str); - let name = format_ident!("{}", to_pascal_case(kind_str)); - quote! { - #[derive(Debug, Clone, PartialEq, Eq, Hash)] - pub struct #name { - pub(crate) syntax: SyntaxToken, - } - - impl std::fmt::Display for #name { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(&self.syntax, f) - } - } - - impl AstToken for #name { - fn can_cast(kind: SyntaxKind) -> bool { - match kind { - #kind => true, - _ => false, - } - } - fn cast(syntax: SyntaxToken) -> Option { - if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } - } - fn syntax(&self) -> &SyntaxToken { &self.syntax } - } - } - }); - let nodes = grammar.nodes.iter().map(|node| { let name = format_ident!("{}", node.name); let kind = format_ident!("{}", to_upper_snake_case(&name.to_string())); @@ -301,13 +325,13 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { } let ast = quote! { - #[allow(unused_imports)] use crate::{ - SyntaxNode, SyntaxToken, SyntaxElement, NodeOrToken, SyntaxKind::{self, *}, + SyntaxNode, SyntaxToken, SyntaxKind::{self, *}, ast::{self, AstNode, AstToken, AstChildren, support}, }; - #(#tokens)* + use super::tokens::*; + #(#nodes)* #(#enums)* }; -- cgit v1.2.3 From 4a063e651f0ec0da852ce1f87589d5c0a893c59d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 9 Apr 2020 17:58:15 +0200 Subject: Move the rest of the tokens to generated/tokens --- xtask/src/ast_src.rs | 13 +-- xtask/src/codegen/gen_syntax.rs | 170 +++++++++++++++++++++------------------- 2 files changed, 98 insertions(+), 85 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index 5fed777ac..eba66ff4d 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs @@ -227,6 +227,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { pub(crate) struct AstSrc<'a> { pub(crate) nodes: &'a [AstNodeSrc<'a>], pub(crate) enums: &'a [AstEnumSrc<'a>], + pub(crate) token_enums: &'a [AstEnumSrc<'a>], } pub(crate) struct AstNodeSrc<'a> { @@ -753,6 +754,13 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { // macro calls are parsed as expression statements */ } + enum FieldDefList { + RecordFieldDefList, + TupleFieldDefList, + } + }, + + token_enums: &ast_enums! { enum LeftDelimiter { LParen, LBrack, LCurly } enum RightDelimiter { RParen, RBrack, RCurly } enum RangeSeparator { Dotdot, Dotdotdot, Dotdoteq} @@ -817,10 +825,5 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { Ident, IntNumber } - - enum FieldDefList { - RecordFieldDefList, - TupleFieldDefList, - } }, }; diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 683901a0a..9801a3dba 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -5,7 +5,7 @@ use std::{ borrow::Cow, - collections::{BTreeSet, HashMap, HashSet}, + collections::{BTreeSet, HashSet}, }; use proc_macro2::{Punct, Spacing}; @@ -57,6 +57,7 @@ fn generate_tokens(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { .chain(kinds.literals.into_iter().copied().map(|x| x.into())) .chain(kinds.tokens.into_iter().copied().map(|x| x.into())) .collect(); + let tokens = all_token_kinds.iter().map(|kind_str| { let kind_str = &**kind_str; let kind = format_ident!("{}", kind_str); @@ -88,10 +89,67 @@ fn generate_tokens(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { } }); + let enums = grammar.token_enums.iter().map(|en| { + let variants = en.variants.iter().map(|var| format_ident!("{}", var)).collect::>(); + let name = format_ident!("{}", en.name); + let kinds = variants + .iter() + .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string()))) + .collect::>(); + assert!(en.traits.is_empty()); + + quote! { + #[derive(Debug, Clone, PartialEq, Eq, Hash)] + pub enum #name { + #(#variants(#variants),)* + } + + #( + impl From<#variants> for #name { + fn from(node: #variants) -> #name { + #name::#variants(node) + } + } + )* + + impl std::fmt::Display for #name { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } + } + + impl AstToken for #name { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + #(#kinds)|* => true, + _ => false, + } + } + fn cast(syntax: SyntaxToken) -> Option { + let res = match syntax.kind() { + #( + #kinds => #name::#variants(#variants { syntax }), + )* + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxToken { + match self { + #( + #name::#variants(it) => &it.syntax, + )* + } + } + } + } + }); + crate::reformat(quote! { use crate::{SyntaxToken, SyntaxKind::{self, *}, ast::AstToken}; #(#tokens)* + #(#enums)* }) } @@ -113,44 +171,15 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { .chain(kinds.tokens.into_iter().copied().map(|x| x.into())) .collect(); - let mut element_kinds_map = HashMap::new(); + let mut token_kinds = HashSet::new(); for kind in &all_token_kinds { let kind = &**kind; let name = to_pascal_case(kind); - element_kinds_map.insert( - name, - ElementKinds { - kinds: Some(format_ident!("{}", kind)).into_iter().collect(), - has_nodes: false, - has_tokens: true, - }, - ); + token_kinds.insert(name); } - for kind in kinds.nodes { - let name = to_pascal_case(kind); - element_kinds_map.insert( - name, - ElementKinds { - kinds: Some(format_ident!("{}", *kind)).into_iter().collect(), - has_nodes: true, - has_tokens: false, - }, - ); - } - - for en in grammar.enums { - let mut element_kinds: ElementKinds = Default::default(); - for variant in en.variants { - if let Some(variant_element_kinds) = element_kinds_map.get(*variant) { - element_kinds.kinds.extend(variant_element_kinds.kinds.iter().cloned()); - element_kinds.has_tokens |= variant_element_kinds.has_tokens; - element_kinds.has_nodes |= variant_element_kinds.has_nodes; - } else { - panic!("Enum variant has type that does not exist or was not declared before the enum: {}", *variant); - } - } - element_kinds_map.insert(en.name.to_string(), element_kinds); + for en in grammar.token_enums { + token_kinds.insert(en.name.to_string()); } let nodes = grammar.nodes.iter().map(|node| { @@ -182,7 +211,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { } } FieldSrc::Optional(_) | FieldSrc::Shorthand => { - let is_token = element_kinds_map[&ty.to_string()].has_tokens; + let is_token = token_kinds.contains(&ty.to_string()); if is_token { quote! { pub fn #method_name(&self) -> Option<#ty> { @@ -245,48 +274,6 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { quote!(impl ast::#trait_name for #name {}) }); - let element_kinds = &element_kinds_map[&en.name.to_string()]; - assert!( - element_kinds.has_nodes ^ element_kinds.has_tokens, - "{}: {:#?}", - name, - element_kinds - ); - let specific_ast_trait = { - let (ast_trait, syntax_type) = if element_kinds.has_tokens { - (quote!(AstToken), quote!(SyntaxToken)) - } else { - (quote!(AstNode), quote!(SyntaxNode)) - }; - - quote! { - impl #ast_trait for #name { - fn can_cast(kind: SyntaxKind) -> bool { - match kind { - #(#kinds)|* => true, - _ => false, - } - } - fn cast(syntax: #syntax_type) -> Option { - let res = match syntax.kind() { - #( - #kinds => #name::#variants(#variants { syntax }), - )* - _ => return None, - }; - Some(res) - } - fn syntax(&self) -> &#syntax_type { - match self { - #( - #name::#variants(it) => &it.syntax, - )* - } - } - } - } - }; - quote! { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum #name { @@ -307,7 +294,30 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { } } - #specific_ast_trait + impl AstNode for #name { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + #(#kinds)|* => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option { + let res = match syntax.kind() { + #( + #kinds => #name::#variants(#variants { syntax }), + )* + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + #( + #name::#variants(it) => &it.syntax, + )* + } + } + } #(#traits)* } @@ -326,8 +336,8 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { let ast = quote! { use crate::{ - SyntaxNode, SyntaxToken, SyntaxKind::{self, *}, - ast::{self, AstNode, AstToken, AstChildren, support}, + SyntaxNode, SyntaxKind::{self, *}, + ast::{self, AstNode, AstChildren, support}, }; use super::tokens::*; -- cgit v1.2.3 From 6fd2a1249589c0c732b04177e3e7484ac6440fd8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 9 Apr 2020 18:03:03 +0200 Subject: More compact generated code --- xtask/src/lib.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'xtask/src') diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 9d087daa2..ec824a518 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -67,6 +67,7 @@ fn reformat(text: impl std::fmt::Display) -> Result { let mut rustfmt = Command::new("rustup") .args(&["run", TOOLCHAIN, "--", "rustfmt", "--config-path"]) .arg(project_root().join("rustfmt.toml")) + .args(&["--config", "fn_single_line=true"]) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn()?; -- cgit v1.2.3 From 9285cbffb66e1c497469fedc5c181b7f295742fd Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 9 Apr 2020 18:08:54 +0200 Subject: More compact --- xtask/src/codegen/gen_syntax.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 9801a3dba..f9a50c5b9 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -75,12 +75,7 @@ fn generate_tokens(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { } impl AstToken for #name { - fn can_cast(kind: SyntaxKind) -> bool { - match kind { - #kind => true, - _ => false, - } - } + fn can_cast(kind: SyntaxKind) -> bool { kind == #kind } fn cast(syntax: SyntaxToken) -> Option { if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } } @@ -243,10 +238,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { impl AstNode for #name { fn can_cast(kind: SyntaxKind) -> bool { - match kind { - #kind => true, - _ => false, - } + kind == #kind } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } -- cgit v1.2.3 From 56c8581b901427ee3e63052c531f3ba3b1ec112d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 9 Apr 2020 18:11:16 +0200 Subject: Put displays at the end --- xtask/src/codegen/gen_syntax.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'xtask/src') diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index f9a50c5b9..6657c9fc5 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -230,12 +230,6 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { pub(crate) syntax: SyntaxNode, } - impl std::fmt::Display for #name { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(self.syntax(), f) - } - } - impl AstNode for #name { fn can_cast(kind: SyntaxKind) -> bool { kind == #kind @@ -280,12 +274,6 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { } )* - impl std::fmt::Display for #name { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(self.syntax(), f) - } - } - impl AstNode for #name { fn can_cast(kind: SyntaxKind) -> bool { match kind { @@ -315,6 +303,21 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { } }); + let displays = grammar + .enums + .iter() + .map(|it| format_ident!("{}", it.name)) + .chain(grammar.nodes.iter().map(|it| format_ident!("{}", it.name))) + .map(|name| { + quote! { + impl std::fmt::Display for #name { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } + } + } + }); + let defined_nodes: HashSet<_> = grammar.nodes.iter().map(|node| node.name).collect(); for node in kinds @@ -336,6 +339,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { #(#nodes)* #(#enums)* + #(#displays)* }; let pretty = crate::reformat(ast)?; -- cgit v1.2.3