mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 21:54:36 +03:00
implement #[span]
This commit is contained in:
parent
3321ca590d
commit
077e0c551f
@ -29,4 +29,8 @@ features = [ "suggestions", "color" ]
|
|||||||
|
|
||||||
|
|
||||||
[profile.bench]
|
[profile.bench]
|
||||||
debug = true
|
debug = true
|
||||||
|
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
darling = { git = "https://github.com/kdy1/darling", branch = "proc-macro2-nightly" }
|
@ -12,13 +12,14 @@ pub enum Decl {
|
|||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct FnDecl {
|
pub struct FnDecl {
|
||||||
pub ident: Ident,
|
pub ident: Ident,
|
||||||
|
#[span]
|
||||||
pub function: Function,
|
pub function: Function,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct ClassDecl {
|
pub struct ClassDecl {
|
||||||
pub ident: Ident,
|
pub ident: Ident,
|
||||||
|
#[span]
|
||||||
pub class: Class,
|
pub class: Class,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::{AssignOp, BinaryOp, BlockStmt, Class, Function, Ident, Lit, Pat, Prop, UnaryOp,
|
use super::{AssignOp, BinaryOp, BlockStmt, Class, Function, Ident, Lit, Pat, Prop, UnaryOp,
|
||||||
UpdateOp};
|
UpdateOp};
|
||||||
use swc_common::Span;
|
use swc_common::{Span, Spanned};
|
||||||
use swc_macros::ast_node;
|
use swc_macros::ast_node;
|
||||||
|
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
@ -114,7 +114,7 @@ pub struct BinExpr {
|
|||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct FnExpr {
|
pub struct FnExpr {
|
||||||
pub ident: Option<Ident>,
|
pub ident: Option<Ident>,
|
||||||
|
#[span]
|
||||||
pub function: Function,
|
pub function: Function,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ pub struct FnExpr {
|
|||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct ClassExpr {
|
pub struct ClassExpr {
|
||||||
pub ident: Option<Ident>,
|
pub ident: Option<Ident>,
|
||||||
|
#[span]
|
||||||
pub class: Class,
|
pub class: Class,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,34 +136,42 @@ pub struct AssignExpr {
|
|||||||
|
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct MemberExpr {
|
pub struct MemberExpr {
|
||||||
|
pub span: Span,
|
||||||
pub obj: ExprOrSuper,
|
pub obj: ExprOrSuper,
|
||||||
pub prop: Box<Expr>,
|
pub prop: Box<Expr>,
|
||||||
pub computed: bool,
|
pub computed: bool,
|
||||||
}
|
}
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct CondExpr {
|
pub struct CondExpr {
|
||||||
|
#[span(lo)]
|
||||||
pub test: Box<Expr>,
|
pub test: Box<Expr>,
|
||||||
pub cons: Box<Expr>,
|
pub cons: Box<Expr>,
|
||||||
|
#[span(hi)]
|
||||||
pub alt: Box<Expr>,
|
pub alt: Box<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct CallExpr {
|
pub struct CallExpr {
|
||||||
|
pub span: Span,
|
||||||
pub callee: ExprOrSuper,
|
pub callee: ExprOrSuper,
|
||||||
pub args: Vec<ExprOrSpread>,
|
pub args: Vec<ExprOrSpread>,
|
||||||
}
|
}
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct NewExpr {
|
pub struct NewExpr {
|
||||||
|
pub span: Span,
|
||||||
pub callee: Box<Expr>,
|
pub callee: Box<Expr>,
|
||||||
// #[code = "$( $( $args ),* )?"]
|
|
||||||
pub args: Option<(Vec<ExprOrSpread>)>,
|
pub args: Option<(Vec<ExprOrSpread>)>,
|
||||||
}
|
}
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct SeqExpr {
|
pub struct SeqExpr {
|
||||||
|
/// TODO: Calculate
|
||||||
|
pub span: Span,
|
||||||
pub exprs: Vec<(Box<Expr>)>,
|
pub exprs: Vec<(Box<Expr>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct ArrowExpr {
|
pub struct ArrowExpr {
|
||||||
|
pub span: Span,
|
||||||
pub params: Vec<Pat>,
|
pub params: Vec<Pat>,
|
||||||
|
|
||||||
pub body: BlockStmtOrExpr,
|
pub body: BlockStmtOrExpr,
|
||||||
@ -173,21 +181,26 @@ pub struct ArrowExpr {
|
|||||||
|
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct YieldExpr {
|
pub struct YieldExpr {
|
||||||
|
pub span: Span,
|
||||||
pub arg: Option<(Box<Expr>)>,
|
pub arg: Option<(Box<Expr>)>,
|
||||||
pub delegate: bool,
|
pub delegate: bool,
|
||||||
}
|
}
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct MetaPropExpr {
|
pub struct MetaPropExpr {
|
||||||
|
#[span(lo)]
|
||||||
pub meta: Ident,
|
pub meta: Ident,
|
||||||
|
#[span(hi)]
|
||||||
pub prop: Ident,
|
pub prop: Ident,
|
||||||
}
|
}
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct AwaitExpr {
|
pub struct AwaitExpr {
|
||||||
|
pub span: Span,
|
||||||
pub arg: Box<Expr>,
|
pub arg: Box<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct TplLit {
|
pub struct TplLit {
|
||||||
|
pub span: Span,
|
||||||
pub tag: Option<(Box<Expr>)>,
|
pub tag: Option<(Box<Expr>)>,
|
||||||
|
|
||||||
pub exprs: Vec<(Box<Expr>)>,
|
pub exprs: Vec<(Box<Expr>)>,
|
||||||
@ -197,6 +210,7 @@ pub struct TplLit {
|
|||||||
|
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct TplElement {
|
pub struct TplElement {
|
||||||
|
pub span: Span,
|
||||||
pub tail: bool,
|
pub tail: bool,
|
||||||
pub cooked: bool,
|
pub cooked: bool,
|
||||||
pub raw: String,
|
pub raw: String,
|
||||||
@ -214,11 +228,20 @@ pub enum ExprOrSuper {
|
|||||||
Expr(Box<Expr>),
|
Expr(Box<Expr>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ast_node]
|
#[derive(Fold, Clone, Debug, PartialEq)]
|
||||||
pub struct ExprOrSpread {
|
pub struct ExprOrSpread {
|
||||||
pub spread: Option<Span>,
|
pub spread: Option<Span>,
|
||||||
pub expr: Box<Expr>,
|
pub expr: Box<Expr>,
|
||||||
}
|
}
|
||||||
|
impl Spanned for ExprOrSpread {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
let expr = self.expr.span();
|
||||||
|
match self.spread {
|
||||||
|
Some(spread) => expr.with_lo(spread.lo()),
|
||||||
|
None => expr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub enum BlockStmtOrExpr {
|
pub enum BlockStmtOrExpr {
|
||||||
|
@ -12,15 +12,18 @@ pub use self::class::{Class, ClassMethod, ClassMethodKind};
|
|||||||
pub use self::decl::{ClassDecl, Decl, FnDecl, VarDecl, VarDeclKind, VarDeclarator};
|
pub use self::decl::{ClassDecl, Decl, FnDecl, VarDecl, VarDeclKind, VarDeclarator};
|
||||||
pub use self::expr::{ArrayLit, ArrowExpr, AssignExpr, AwaitExpr, BinExpr, BlockStmtOrExpr,
|
pub use self::expr::{ArrayLit, ArrowExpr, AssignExpr, AwaitExpr, BinExpr, BlockStmtOrExpr,
|
||||||
CallExpr, ClassExpr, CondExpr, Expr, ExprOrSpread, ExprOrSuper, FnExpr,
|
CallExpr, ClassExpr, CondExpr, Expr, ExprOrSpread, ExprOrSuper, FnExpr,
|
||||||
MemberExpr, MetaPropExpr, NewExpr, ObjectLit, PatOrExpr, SeqExpr, TplElement,
|
MemberExpr, MetaPropExpr, NewExpr, ObjectLit, ParenExpr, PatOrExpr, SeqExpr,
|
||||||
TplLit, UnaryExpr, UpdateExpr, YieldExpr};
|
ThisExpr, TplElement, TplLit, UnaryExpr, UpdateExpr, YieldExpr};
|
||||||
pub use self::function::Function;
|
pub use self::function::Function;
|
||||||
pub use self::lit::{Bool, Lit, Null, Number, Regex, RegexFlags, Str};
|
pub use self::lit::{Bool, Lit, Null, Number, Regex, RegexFlags, Str};
|
||||||
pub use self::module::{Module, ModuleItem};
|
pub use self::module::{Module, ModuleItem};
|
||||||
pub use self::module_decl::{ExportDefaultDecl, ExportSpecifier, ImportSpecifier, ModuleDecl};
|
pub use self::module_decl::{ExportAll, ExportDefaultDecl, ExportSpecifier, ImportDecl,
|
||||||
|
ImportDefault, ImportSpecific, ImportSpecifier, ImportStarAs,
|
||||||
|
ModuleDecl, NamedExport};
|
||||||
pub use self::operators::{AssignOp, BinaryOp, UnaryOp, UpdateOp};
|
pub use self::operators::{AssignOp, BinaryOp, UnaryOp, UpdateOp};
|
||||||
pub use self::pat::{ObjectPatProp, Pat};
|
pub use self::pat::{ArrayPat, AssignPat, AssignPatProp, KeyValuePatProp, ObjectPat, ObjectPatProp,
|
||||||
pub use self::prop::{Prop, PropName};
|
Pat};
|
||||||
|
pub use self::prop::{AssignProp, GetterProp, KeyValueProp, MethodProp, Prop, PropName, SetterProp};
|
||||||
pub use self::stmt::{BlockStmt, BreakStmt, CatchClause, ContinueStmt, DebuggerStmt, DoWhileStmt,
|
pub use self::stmt::{BlockStmt, BreakStmt, CatchClause, ContinueStmt, DebuggerStmt, DoWhileStmt,
|
||||||
EmptyStmt, ForInStmt, ForOfStmt, ForStmt, IfStmt, LabeledStmt, ReturnStmt,
|
EmptyStmt, ForInStmt, ForOfStmt, ForStmt, IfStmt, LabeledStmt, ReturnStmt,
|
||||||
Stmt, SwitchCase, SwitchStmt, ThrowStmt, TryStmt, VarDeclOrExpr,
|
Stmt, SwitchCase, SwitchStmt, ThrowStmt, TryStmt, VarDeclOrExpr,
|
||||||
|
@ -78,6 +78,7 @@ pub struct ImportSpecific {
|
|||||||
|
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct ExportSpecifier {
|
pub struct ExportSpecifier {
|
||||||
|
pub span: Span,
|
||||||
/// `foo` in `export { foo as bar }`
|
/// `foo` in `export { foo as bar }`
|
||||||
pub orig: Ident,
|
pub orig: Ident,
|
||||||
/// `Some(bar)` in `export { foo as bar }`
|
/// `Some(bar)` in `export { foo as bar }`
|
||||||
|
@ -10,7 +10,7 @@ pub enum Pat {
|
|||||||
|
|
||||||
Rest(Box<Pat>),
|
Rest(Box<Pat>),
|
||||||
|
|
||||||
Object(Vec<ObjectPatProp>),
|
Object(ObjectPat),
|
||||||
|
|
||||||
Assign(AssignPat),
|
Assign(AssignPat),
|
||||||
|
|
||||||
@ -24,6 +24,12 @@ pub struct ArrayPat {
|
|||||||
pub elems: Vec<(Option<Pat>)>,
|
pub elems: Vec<(Option<Pat>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[ast_node]
|
||||||
|
pub struct ObjectPat {
|
||||||
|
pub span: Span,
|
||||||
|
pub props: Vec<ObjectPatProp>,
|
||||||
|
}
|
||||||
|
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct AssignPat {
|
pub struct AssignPat {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -40,12 +46,15 @@ pub enum ObjectPatProp {
|
|||||||
/// `{key: value}`
|
/// `{key: value}`
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct KeyValuePatProp {
|
pub struct KeyValuePatProp {
|
||||||
|
#[span(lo)]
|
||||||
pub key: PropName,
|
pub key: PropName,
|
||||||
|
#[span(hi)]
|
||||||
pub value: Box<Pat>,
|
pub value: Box<Pat>,
|
||||||
}
|
}
|
||||||
/// `{key}` or `{key = value}`
|
/// `{key}` or `{key = value}`
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct AssignPatProp {
|
pub struct AssignPatProp {
|
||||||
|
pub span: Span,
|
||||||
pub key: Ident,
|
pub key: Ident,
|
||||||
|
|
||||||
pub value: Option<(Box<Expr>)>,
|
pub value: Option<(Box<Expr>)>,
|
||||||
|
@ -18,18 +18,18 @@ pub enum Prop {
|
|||||||
|
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct KeyValueProp {
|
pub struct KeyValueProp {
|
||||||
// #[span(lo)]
|
#[span(lo)]
|
||||||
pub key: PropName,
|
pub key: PropName,
|
||||||
|
|
||||||
// #[span(hi)]
|
#[span(hi)]
|
||||||
pub value: Box<Expr>,
|
pub value: Box<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct AssignProp {
|
pub struct AssignProp {
|
||||||
// #[span(lo)]
|
#[span(lo)]
|
||||||
key: Ident,
|
key: Ident,
|
||||||
// #[span(hi)]
|
#[span(hi)]
|
||||||
value: Box<Expr>,
|
value: Box<Expr>,
|
||||||
}
|
}
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
@ -47,9 +47,9 @@ pub struct SetterProp {
|
|||||||
}
|
}
|
||||||
#[ast_node]
|
#[ast_node]
|
||||||
pub struct MethodProp {
|
pub struct MethodProp {
|
||||||
// #[span(lo)]
|
#[span(lo)]
|
||||||
key: PropName,
|
key: PropName,
|
||||||
// #[span(hi)]
|
#[span(hi)]
|
||||||
function: Function,
|
function: Function,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ swc_macros_common = { path = "../common" }
|
|||||||
pmutil = "0.1"
|
pmutil = "0.1"
|
||||||
proc-macro2 = { version = "0.2", features = ["nightly"] }
|
proc-macro2 = { version = "0.2", features = ["nightly"] }
|
||||||
quote = "0.4"
|
quote = "0.4"
|
||||||
|
darling = "0.3"
|
||||||
|
|
||||||
[dependencies.syn]
|
[dependencies.syn]
|
||||||
version = "0.12"
|
version = "0.12"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#![feature(box_syntax, proc_macro)]
|
#![feature(box_syntax, proc_macro)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate darling;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate pmutil;
|
extern crate pmutil;
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
@ -1,5 +1,22 @@
|
|||||||
|
use darling::FromField;
|
||||||
use swc_macros_common::prelude::*;
|
use swc_macros_common::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Debug, FromField)]
|
||||||
|
#[darling(attributes(span))]
|
||||||
|
struct MyField {
|
||||||
|
/// Name of the field.
|
||||||
|
pub ident: Option<Ident>,
|
||||||
|
/// Type of the field.
|
||||||
|
pub ty: Type,
|
||||||
|
|
||||||
|
/// `#[span(lo)]`
|
||||||
|
#[darling(default)]
|
||||||
|
pub lo: bool,
|
||||||
|
/// `#[span(hi)]`
|
||||||
|
#[darling(default)]
|
||||||
|
pub hi: bool,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn derive(input: DeriveInput) -> ItemImpl {
|
pub fn derive(input: DeriveInput) -> ItemImpl {
|
||||||
let arms = Binder::new_from(&input)
|
let arms = Binder::new_from(&input)
|
||||||
.variants()
|
.variants()
|
||||||
@ -53,6 +70,15 @@ pub fn derive(input: DeriveInput) -> ItemImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn make_body_for_variant(v: &VariantBinder, bindings: Vec<BindedField>) -> Box<Expr> {
|
fn make_body_for_variant(v: &VariantBinder, bindings: Vec<BindedField>) -> Box<Expr> {
|
||||||
|
/// `swc_common::Spanned::span(#field)`
|
||||||
|
fn simple_field(field: &ToTokens) -> Box<Expr> {
|
||||||
|
box Quote::new(Span::def_site())
|
||||||
|
.quote_with(smart_quote!(Vars { field }, {
|
||||||
|
swc_common::Spanned::span(field)
|
||||||
|
}))
|
||||||
|
.parse()
|
||||||
|
}
|
||||||
|
|
||||||
if bindings.len() == 0 {
|
if bindings.len() == 0 {
|
||||||
panic!("#[derive(Spanned)] requires a field to get span from")
|
panic!("#[derive(Spanned)] requires a field to get span from")
|
||||||
}
|
}
|
||||||
@ -61,35 +87,75 @@ fn make_body_for_variant(v: &VariantBinder, bindings: Vec<BindedField>) -> Box<E
|
|||||||
match *v.data() {
|
match *v.data() {
|
||||||
Fields::Unnamed(..) => {
|
Fields::Unnamed(..) => {
|
||||||
// Call self.0.span()
|
// Call self.0.span()
|
||||||
return box Quote::new(Span::def_site())
|
return simple_field(&bindings[0]);
|
||||||
.quote_with(smart_quote!(
|
|
||||||
Vars {
|
|
||||||
field: &bindings[0],
|
|
||||||
},
|
|
||||||
{ swc_common::Spanned::span(field) }
|
|
||||||
))
|
|
||||||
.parse();
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Handle #[span] attribute.
|
// Handle #[span] attribute.
|
||||||
|
if let Some(f) = bindings
|
||||||
let span_field = bindings
|
|
||||||
.iter()
|
.iter()
|
||||||
.find(|b| {
|
.find(|b| has_empty_span_attr(&b.field().attrs))
|
||||||
let s = b.field().ident.as_ref().map(|ident| ident.as_ref());
|
{
|
||||||
Some("span") == s
|
//TODO: Verify that there's no more #[span]
|
||||||
})
|
return simple_field(f);
|
||||||
.unwrap_or_else(|| {
|
}
|
||||||
panic!(
|
|
||||||
"#[derive(Spanned)]: cannot determine span field to use for {}",
|
|
||||||
v.qual_path().dump()
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
box Quote::new(Span::def_site())
|
// If all fields do not have `#[span(..)]`, check for field named `span`.
|
||||||
.quote_with(smart_quote!(Vars { span_field }, { span_field }))
|
let has_any_span_attr = bindings
|
||||||
.parse()
|
.iter()
|
||||||
|
.map(|b| {
|
||||||
|
b.field()
|
||||||
|
.attrs
|
||||||
|
.iter()
|
||||||
|
.any(|attr| is_attr_name(attr, "span"))
|
||||||
|
})
|
||||||
|
.any(|b| b);
|
||||||
|
if !has_any_span_attr {
|
||||||
|
let span_field = bindings
|
||||||
|
.iter()
|
||||||
|
.find(|b| Some("span") == b.field().ident.as_ref().map(|ident| ident.as_ref()))
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
panic!(
|
||||||
|
"#[derive(Spanned)]: cannot determine span field to use for {}",
|
||||||
|
v.qual_path().dump()
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
return simple_field(span_field);
|
||||||
|
}
|
||||||
|
|
||||||
|
let fields: Vec<_> = bindings
|
||||||
|
.iter()
|
||||||
|
.map(|b| (b, MyField::from_field(b.field()).unwrap()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// TODO: Only one field should be `#[span(lo)]`.
|
||||||
|
let lo = fields.iter().find(|&&(_, ref f)| f.lo);
|
||||||
|
let hi = fields.iter().find(|&&(_, ref f)| f.hi);
|
||||||
|
|
||||||
|
match (lo, hi) {
|
||||||
|
(Some(&(ref lo_field, _)), Some(&(ref hi_field, _))) => {
|
||||||
|
// Create a new span from lo_field.lo(), hi_field.hi()
|
||||||
|
box Quote::new(Span::def_site())
|
||||||
|
.quote_with(smart_quote!(Vars { lo_field, hi_field }, {
|
||||||
|
swc_common::Spanned::span(lo_field)
|
||||||
|
.with_hi(swc_common::Spanned::span(hi_field).hi())
|
||||||
|
}))
|
||||||
|
.parse()
|
||||||
|
}
|
||||||
|
_ => panic!("#[derive(Spanned)]: #[span(lo)] and #[span(hi)] is required"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Search for `#[span]`
|
||||||
|
fn has_empty_span_attr(attrs: &[Attribute]) -> bool {
|
||||||
|
attrs.iter().any(|attr| {
|
||||||
|
if !is_attr_name(attr, "span") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr.tts.is_empty()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
24
macros/ast_node/tests/attr_interop.rs
Normal file
24
macros/ast_node/tests/attr_interop.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
//! Test that `#[span]` and `#[fold]` can be used at same time.
|
||||||
|
#![feature(proc_macro)]
|
||||||
|
|
||||||
|
extern crate swc_common;
|
||||||
|
extern crate swc_macros;
|
||||||
|
use swc_common::{Fold, Span, Spanned};
|
||||||
|
use swc_macros::ast_node;
|
||||||
|
|
||||||
|
#[ast_node]
|
||||||
|
// See https://github.com/rust-lang/rust/issues/44925
|
||||||
|
pub struct Class {
|
||||||
|
#[span]
|
||||||
|
pub has_span: HasSpan,
|
||||||
|
#[fold(ignore)]
|
||||||
|
pub s: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[ast_node]
|
||||||
|
pub struct Tuple(#[span] HasSpan, #[fold(ignore)] usize, usize);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Fold, Spanned)]
|
||||||
|
pub struct HasSpan {
|
||||||
|
pub span: Span,
|
||||||
|
}
|
@ -1,15 +0,0 @@
|
|||||||
#![feature(specialization, proc_macro)]
|
|
||||||
|
|
||||||
extern crate swc_common;
|
|
||||||
extern crate swc_macros;
|
|
||||||
use swc_macros::ast_node;
|
|
||||||
|
|
||||||
#[ast_node]
|
|
||||||
// See https://github.com/rust-lang/rust/issues/44925
|
|
||||||
pub struct Class {
|
|
||||||
#[fold(ignore)]
|
|
||||||
pub s: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[ast_node]
|
|
||||||
pub struct Tuple(usize, usize);
|
|
@ -1,12 +1,12 @@
|
|||||||
#![feature(specialization, proc_macro)]
|
#![feature(proc_macro)]
|
||||||
|
|
||||||
|
extern crate ast_node;
|
||||||
extern crate swc_common;
|
extern crate swc_common;
|
||||||
extern crate swc_macros;
|
use ast_node::*;
|
||||||
use swc_macros::ast_node;
|
|
||||||
|
|
||||||
#[ast_node]
|
#[derive(Debug, Fold)]
|
||||||
pub struct Struct {}
|
pub struct Struct {}
|
||||||
|
|
||||||
#[ast_node]
|
#[derive(Debug, FromVariant, Fold)]
|
||||||
pub enum Enum {
|
pub enum Enum {
|
||||||
}
|
}
|
||||||
|
@ -1,30 +1,29 @@
|
|||||||
//! Ensures that #[derive(AstNode)] works with generic types.
|
//! Ensures that #[derive(Fold)] works with generic types.
|
||||||
|
|
||||||
#![feature(specialization, proc_macro)]
|
#![feature(specialization, proc_macro)]
|
||||||
|
|
||||||
extern crate swc_common;
|
extern crate swc_common;
|
||||||
extern crate swc_macros;
|
extern crate swc_macros;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use swc_common::AstNode;
|
use swc_common::{AstNode, Fold};
|
||||||
use swc_macros::ast_node;
|
|
||||||
|
|
||||||
pub trait Ast: Copy + Eq + Debug {
|
pub trait Ast: Copy + Eq + Debug {
|
||||||
type CustomExpr: AstNode;
|
type CustomExpr: AstNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ast_node]
|
#[derive(Fold)]
|
||||||
pub struct Stmt<A: Ast> {
|
pub struct Stmt<A: Ast> {
|
||||||
#[fold(bound)]
|
#[fold(bound)]
|
||||||
pub expr: Expr<A>,
|
pub expr: Expr<A>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ast_node]
|
#[derive(Fold)]
|
||||||
pub struct Expr<A: Ast> {
|
pub struct Expr<A: Ast> {
|
||||||
#[fold(bound)]
|
#[fold(bound)]
|
||||||
pub node: ExprKind<A>,
|
pub node: ExprKind<A>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ast_node]
|
#[derive(Fold)]
|
||||||
pub enum ExprKind<A: Ast> {
|
pub enum ExprKind<A: Ast> {
|
||||||
Custom(#[fold(bound)] A::CustomExpr),
|
Custom(#[fold(bound)] A::CustomExpr),
|
||||||
/// Recursive
|
/// Recursive
|
@ -2,15 +2,14 @@
|
|||||||
|
|
||||||
extern crate swc_common;
|
extern crate swc_common;
|
||||||
extern crate swc_macros;
|
extern crate swc_macros;
|
||||||
use swc_common::{FoldWith, Folder};
|
use swc_common::{Fold, FoldWith};
|
||||||
use swc_macros::ast_node;
|
|
||||||
|
|
||||||
pub trait AssertFolder<T>: Folder<T> {}
|
pub trait AssertFolder<T>: Fold<T> {}
|
||||||
|
|
||||||
// check for trait bound
|
// check for trait bound
|
||||||
|
|
||||||
pub struct LitFolder;
|
pub struct LitFolder;
|
||||||
impl Folder<Lit> for LitFolder {
|
impl Fold<Lit> for LitFolder {
|
||||||
fn fold(&mut self, _: Lit) -> Lit {
|
fn fold(&mut self, _: Lit) -> Lit {
|
||||||
Lit::A
|
Lit::A
|
||||||
}
|
}
|
||||||
@ -18,7 +17,7 @@ impl Folder<Lit> for LitFolder {
|
|||||||
impl AssertFolder<Expr> for LitFolder {}
|
impl AssertFolder<Expr> for LitFolder {}
|
||||||
impl AssertFolder<ExprKind> for LitFolder {}
|
impl AssertFolder<ExprKind> for LitFolder {}
|
||||||
|
|
||||||
#[ast_node]
|
#[derive(Debug, Fold, PartialEq, Eq)]
|
||||||
pub struct Expr {
|
pub struct Expr {
|
||||||
pub node: ExprKind,
|
pub node: ExprKind,
|
||||||
/// This field should be skipped.
|
/// This field should be skipped.
|
||||||
@ -40,7 +39,7 @@ impl<F> FoldWith<F> for PanicOnFold {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ast_node]
|
#[derive(Debug, Fold, PartialEq, Eq)]
|
||||||
pub enum ExprKind {
|
pub enum ExprKind {
|
||||||
RecursiveBoud(Box<Expr>),
|
RecursiveBoud(Box<Expr>),
|
||||||
Rec2(Vec<Option<Box<Expr>>>),
|
Rec2(Vec<Option<Box<Expr>>>),
|
||||||
@ -48,7 +47,7 @@ pub enum ExprKind {
|
|||||||
Lit(Lit),
|
Lit(Lit),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ast_node]
|
#[derive(Debug, Fold, PartialEq, Eq)]
|
||||||
pub enum Lit {
|
pub enum Lit {
|
||||||
A,
|
A,
|
||||||
B,
|
B,
|
22
macros/ast_node/tests/spanned_attr.rs
Normal file
22
macros/ast_node/tests/spanned_attr.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#![feature(proc_macro)]
|
||||||
|
|
||||||
|
extern crate swc_common;
|
||||||
|
use swc_common::{BytePos, Span, Spanned};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lo_hi() {
|
||||||
|
#[derive(Spanned)]
|
||||||
|
struct LoHi {
|
||||||
|
#[span(lo)]
|
||||||
|
pub lo: BytePos,
|
||||||
|
#[span(hi)]
|
||||||
|
pub hi: BytePos,
|
||||||
|
}
|
||||||
|
|
||||||
|
let lo = BytePos(0);
|
||||||
|
let hi = BytePos(5);
|
||||||
|
assert_eq!(
|
||||||
|
LoHi { lo, hi }.span(),
|
||||||
|
Span::new(lo, hi, Default::default())
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user