Basic support for decl macros 2.0

This commit is contained in:
Jonas Schievink 2020-12-15 18:43:19 +01:00
parent bd4c352831
commit c31c3246a8
15 changed files with 195 additions and 28 deletions

View file

@ -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::*,

View file

@ -286,6 +286,18 @@ impl MacroRules {
pub fn token_tree(&self) -> Option<TokenTree> { 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<SyntaxToken> { support::token(&self.syntax, T![macro]) }
pub fn args(&self) -> Option<TokenTree> { support::child(&self.syntax) }
pub fn body(&self) -> Option<TokenTree> { 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<Self> {
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<Self> {
@ -3086,6 +3110,9 @@ impl From<MacroCall> for Item {
impl From<MacroRules> for Item {
fn from(node: MacroRules) -> Item { Item::MacroRules(node) }
}
impl From<MacroDef> for Item {
fn from(node: MacroDef) -> Item { Item::MacroDef(node) }
}
impl From<Module> 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)

View file

@ -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<ast::MacroRules> for Macro {
fn from(it: ast::MacroRules) -> Self {
Macro::MacroRules(it)
}
}
impl From<ast::MacroDef> 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<Self> {
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<ast::Name> {
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 {}

View file

@ -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
}
}
}