Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(macros): Reduce compile time #7132

Merged
merged 11 commits into from Mar 23, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/ast_node/src/enum_deserialize.rs
Expand Up @@ -29,7 +29,7 @@ pub fn expand(
data,
..
}: DeriveInput,
) -> Vec<ItemImpl> {
) -> ItemImpl {
let data = match data {
Data::Enum(data) => data,
_ => unreachable!("expand_enum is called with none-enum item"),
Expand Down Expand Up @@ -438,5 +438,5 @@ pub fn expand(
.with_generics(generics)
};

vec![deserialize]
deserialize
}
39 changes: 5 additions & 34 deletions crates/ast_node/src/lib.rs
Expand Up @@ -16,29 +16,18 @@ mod spanned;
#[proc_macro_derive(Spanned, attributes(span))]
pub fn derive_spanned(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse::<DeriveInput>(input).expect("failed to parse input as DeriveInput");
let name = input.ident.clone();

let item = self::spanned::derive(input);

print_item(
"derive(Spanned)",
&format!("IMPL_SPANNED_FOR_{}", name),
item.dump(),
)
print("derive(Spanned)", item.dump())
}

/// Derives `serde::Deserialize` which is aware of `tag` based deserialization.
#[proc_macro_derive(DeserializeEnum, attributes(tag))]
pub fn derive_deserialize_enum(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse::<DeriveInput>(input).expect("failed to parse input as DeriveInput");

let item =
enum_deserialize::expand(input)
.into_iter()
.fold(TokenStream::new(), |mut t, item| {
item.to_tokens(&mut t);
t
});
let item = enum_deserialize::expand(input);

print("derive(DeserializeEnum)", item.dump())
}
Expand Down Expand Up @@ -143,7 +132,7 @@ pub fn ast_serde(
}
};

print("ast_serde", item)
print("ast_serde", item.into())
}

struct AddAttr;
Expand Down Expand Up @@ -307,31 +296,13 @@ pub fn ast_node(

if let Some(items) = ast_node_impl {
for item in items {
quote = quote.quote_with(smart_quote!(Vars { item }, { item }))
quote.push_tokens(&item);
}
}

quote
}
};

print("ast_node", item)
}

/// Workarounds https://github.com/rust-lang/rust/issues/44925
fn print_item<T: Into<TokenStream>>(
name: &'static str,
const_name: &str,
item: T,
) -> proc_macro::TokenStream {
let item = Quote::new(def_site::<Span>()).quote_with(smart_quote!(
Vars {
item: item.into(),
NAME: Ident::new(const_name, Span::call_site())
},
{
const NAME: () = { item };
}
));
print(name, item)
print("ast_node", item.into())
}
10 changes: 4 additions & 6 deletions crates/from_variant/src/lib.rs
@@ -1,6 +1,6 @@
extern crate proc_macro;

use pmutil::{smart_quote, Quote, ToTokensExt};
use pmutil::{smart_quote, Quote};
use swc_macros_common::prelude::*;
use syn::*;

Expand All @@ -17,7 +17,7 @@ pub fn derive_from_variant(input: proc_macro::TokenStream) -> proc_macro::TokenS
t
});

print("derive(FromVariant)", item.dump())
print("derive(FromVariant)", item)
}

fn derive(
Expand Down Expand Up @@ -62,7 +62,8 @@ fn derive(
}
}
))
.parse();
.parse::<ItemImpl>()
.with_generics(generics.clone());

from_impls.push(from_impl);
}
Expand All @@ -73,7 +74,4 @@ fn derive(
}

from_impls
.into_iter()
.map(|item| item.with_generics(generics.clone()))
.collect()
}
9 changes: 3 additions & 6 deletions crates/swc_macros_common/src/lib.rs
@@ -1,3 +1,5 @@
//! Internal crate for the swc project.

extern crate proc_macro;

#[cfg(procmacro2_semver_exempt)]
Expand Down Expand Up @@ -29,14 +31,9 @@ pub fn def_site<T: FromSpan>() -> T {
}

/// `attr` - tokens inside `#[]`. e.g. `derive(EqIgnoreSpan)`, ast_node
pub fn print<T: Into<proc_macro2::TokenStream>>(
attr: &'static str,
t: T,
) -> proc_macro::TokenStream {
pub fn print(attr: &'static str, tokens: proc_macro2::TokenStream) -> proc_macro::TokenStream {
use std::env;

let tokens = t.into();

match env::var("PRINT_GENERATED") {
Ok(ref s) if s == "1" || attr == s => {}
_ => return tokens.into(),
Expand Down
4 changes: 1 addition & 3 deletions crates/swc_macros_common/src/syn_ext.rs
@@ -1,4 +1,3 @@
use pmutil::ToTokensExt;
use quote::quote;
use syn::{punctuated::Pair, *};

Expand Down Expand Up @@ -71,8 +70,7 @@ impl ItemImplExt for ItemImpl {

}
};
parse(item.dump().into())
.unwrap_or_else(|err| panic!("with_generics failed: {}\n{}", err, item.dump()))
parse(item.into()).unwrap_or_else(|err| panic!("with_generics failed: {}", err))
};

// Handle generics added by proc-macro.
Expand Down
35 changes: 14 additions & 21 deletions crates/testing_macros/src/fixture.rs
Expand Up @@ -6,13 +6,13 @@ use std::{
use anyhow::{Context, Error};
use glob::glob;
use once_cell::sync::Lazy;
use pmutil::q;
use pmutil::{q, Quote};
use proc_macro2::Span;
use regex::Regex;
use relative_path::RelativePath;
use syn::{
parse::{Parse, ParseStream},
Ident, ItemFn, Lit, LitStr, Meta, NestedMeta, Token,
Ident, Lit, LitStr, Meta, NestedMeta, Token,
};

pub struct Config {
Expand Down Expand Up @@ -96,7 +96,7 @@ impl Parse for Config {
}
}

pub fn expand(callee: &Ident, attr: Config) -> Result<Vec<ItemFn>, Error> {
pub fn expand(callee: &Ident, attr: Config) -> Result<Vec<Quote>, Error> {
let base_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect(
"#[fixture] requires CARGO_MANIFEST_DIR because it's relative to cargo manifest directory",
));
Expand Down Expand Up @@ -152,39 +152,32 @@ pub fn expand(callee: &Ident, attr: Config) -> Result<Vec<ItemFn>, Error> {
.replace("___", "__");
let test_ident = Ident::new(&test_name, Span::call_site());

let mut f = q!(
let ignored_attr = if ignored {
q!(Vars {}, { #[ignore] })
} else {
Quote::new_call_site()
};

let f = q!(
Vars {
test_ident,
path_str: &abs_path.to_string_lossy(),
callee
callee,
ignored_attr,
},
{
#[test]
#[inline(never)]
#[ignore]
#[doc(hidden)]
#[allow(non_snake_case)]
ignored_attr
fn test_ident() {
eprintln!("Input: {}", path_str);

callee(::std::path::PathBuf::from(path_str));
}
}
)
.parse::<ItemFn>();

if !ignored {
f.attrs.retain(|attr| {
if let Some(name) = attr.path.get_ident() {
if name == "ignore" {
return false;
}
}

true
});
//
}
);

test_fns.push(f);
}
Expand Down