From c31c3246a8c87a3639623c30b692a57e728bb046 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 15 Dec 2020 18:43:19 +0100 Subject: Basic support for decl macros 2.0 --- crates/syntax/src/ast.rs | 4 +-- crates/syntax/src/ast/generated/nodes.rs | 36 ++++++++++++++++++++- crates/syntax/src/ast/node_ext.rs | 54 ++++++++++++++++++++++++++++++++ crates/syntax/src/display.rs | 18 +++++++++-- 4 files changed, 106 insertions(+), 6 deletions(-) (limited to 'crates/syntax') diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs index 7844f9ed6..70c568ea1 100644 --- a/crates/syntax/src/ast.rs +++ b/crates/syntax/src/ast.rs @@ -19,8 +19,8 @@ pub use self::{ expr_ext::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind, PrefixOp, RangeOp}, generated::{nodes::*, tokens::*}, node_ext::{ - AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents, - StructKind, TypeBoundKind, VisibilityKind, + AttrKind, FieldKind, Macro, NameOrNameRef, PathSegmentKind, SelfParamKind, + SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind, }, token_ext::*, traits::*, diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 0ad75214f..6eae323f4 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -286,6 +286,18 @@ impl MacroRules { pub fn token_tree(&self) -> Option { support::child(&self.syntax) } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct MacroDef { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for MacroDef {} +impl ast::NameOwner for MacroDef {} +impl ast::VisibilityOwner for MacroDef {} +impl MacroDef { + pub fn macro_token(&self) -> Option { support::token(&self.syntax, T![macro]) } + pub fn args(&self) -> Option { support::child(&self.syntax) } + pub fn body(&self) -> Option { support::child(&self.syntax) } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Module { pub(crate) syntax: SyntaxNode, } @@ -1332,6 +1344,7 @@ pub enum Item { Impl(Impl), MacroCall(MacroCall), MacroRules(MacroRules), + MacroDef(MacroDef), Module(Module), Static(Static), Struct(Struct), @@ -1689,6 +1702,17 @@ impl AstNode for MacroRules { } fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl AstNode for MacroDef { + fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_DEF } + 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 Module { fn can_cast(kind: SyntaxKind) -> bool { kind == MODULE } fn cast(syntax: SyntaxNode) -> Option { @@ -3086,6 +3110,9 @@ impl From for Item { impl From for Item { fn from(node: MacroRules) -> Item { Item::MacroRules(node) } } +impl From for Item { + fn from(node: MacroDef) -> Item { Item::MacroDef(node) } +} impl From for Item { fn from(node: Module) -> Item { Item::Module(node) } } @@ -3111,7 +3138,7 @@ impl AstNode for Item { fn can_cast(kind: SyntaxKind) -> bool { match kind { CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE | FN | IMPL | MACRO_CALL | MACRO_RULES - | MODULE | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION | USE => true, + | MACRO_DEF | MODULE | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION | USE => true, _ => false, } } @@ -3125,6 +3152,7 @@ impl AstNode for Item { IMPL => Item::Impl(Impl { syntax }), MACRO_CALL => Item::MacroCall(MacroCall { syntax }), MACRO_RULES => Item::MacroRules(MacroRules { syntax }), + MACRO_DEF => Item::MacroDef(MacroDef { syntax }), MODULE => Item::Module(Module { syntax }), STATIC => Item::Static(Static { syntax }), STRUCT => Item::Struct(Struct { syntax }), @@ -3146,6 +3174,7 @@ impl AstNode for Item { Item::Impl(it) => &it.syntax, Item::MacroCall(it) => &it.syntax, Item::MacroRules(it) => &it.syntax, + Item::MacroDef(it) => &it.syntax, Item::Module(it) => &it.syntax, Item::Static(it) => &it.syntax, Item::Struct(it) => &it.syntax, @@ -3615,6 +3644,11 @@ impl std::fmt::Display for MacroRules { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for MacroDef { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for Module { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index c59a29eab..40dec3c7f 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -3,6 +3,7 @@ use std::fmt; +use ast::AttrsOwner; use itertools::Itertools; use parser::SyntaxKind; @@ -31,6 +32,57 @@ fn text_of_first_token(node: &SyntaxNode) -> &SmolStr { node.green().children().next().and_then(|it| it.into_token()).unwrap().text() } +pub enum Macro { + MacroRules(ast::MacroRules), + MacroDef(ast::MacroDef), +} + +impl From for Macro { + fn from(it: ast::MacroRules) -> Self { + Macro::MacroRules(it) + } +} + +impl From for Macro { + fn from(it: ast::MacroDef) -> Self { + Macro::MacroDef(it) + } +} + +impl AstNode for Macro { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + SyntaxKind::MACRO_RULES | SyntaxKind::MACRO_DEF => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option { + let res = match syntax.kind() { + SyntaxKind::MACRO_RULES => Macro::MacroRules(ast::MacroRules { syntax }), + SyntaxKind::MACRO_DEF => Macro::MacroDef(ast::MacroDef { syntax }), + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + Macro::MacroRules(it) => it.syntax(), + Macro::MacroDef(it) => it.syntax(), + } + } +} + +impl NameOwner for Macro { + fn name(&self) -> Option { + match self { + Macro::MacroRules(mac) => mac.name(), + Macro::MacroDef(mac) => mac.name(), + } + } +} + +impl AttrsOwner for Macro {} + #[derive(Debug, Clone, PartialEq, Eq)] pub enum AttrKind { Inner, @@ -462,4 +514,6 @@ impl ast::DocCommentsOwner for ast::Const {} impl ast::DocCommentsOwner for ast::TypeAlias {} impl ast::DocCommentsOwner for ast::Impl {} impl ast::DocCommentsOwner for ast::MacroRules {} +impl ast::DocCommentsOwner for ast::MacroDef {} +impl ast::DocCommentsOwner for ast::Macro {} impl ast::DocCommentsOwner for ast::Use {} diff --git a/crates/syntax/src/display.rs b/crates/syntax/src/display.rs index d33bde30c..391647fc6 100644 --- a/crates/syntax/src/display.rs +++ b/crates/syntax/src/display.rs @@ -76,8 +76,20 @@ pub fn type_label(node: &ast::TypeAlias) -> String { label.trim().to_owned() } -pub fn macro_label(node: &ast::MacroRules) -> String { +pub fn macro_label(node: &ast::Macro) -> String { let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default(); - let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" }; - format!("{}macro_rules! {}", vis, name) + match node { + ast::Macro::MacroRules(node) => { + let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" }; + format!("{}macro_rules! {}", vis, name) + } + ast::Macro::MacroDef(node) => { + let mut s = String::new(); + if let Some(vis) = node.visibility() { + format_to!(s, "{} ", vis); + } + format_to!(s, "macro {}", name); + s + } + } } -- cgit v1.2.3