From 2154a3f117d9ea7cc2f12856d6e7f2b33a255d26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Thu, 23 Mar 2023 18:16:50 +0900 Subject: [PATCH] refactor(macros): Reduce compile time (#7132) **Description:** - Reduce usage of generics in proc-macros. - Remove needless operations like parsing tokens as an AST node. --- crates/ast_node/src/enum_deserialize.rs | 4 +-- crates/ast_node/src/lib.rs | 39 +++------------------- crates/from_variant/src/lib.rs | 10 +++--- crates/swc_macros_common/src/lib.rs | 9 ++---- crates/swc_macros_common/src/syn_ext.rs | 43 ++++++------------------- crates/testing_macros/src/fixture.rs | 35 ++++++++------------ 6 files changed, 38 insertions(+), 102 deletions(-) diff --git a/crates/ast_node/src/enum_deserialize.rs b/crates/ast_node/src/enum_deserialize.rs index def6f8706aca..ca37bf03fceb 100644 --- a/crates/ast_node/src/enum_deserialize.rs +++ b/crates/ast_node/src/enum_deserialize.rs @@ -29,7 +29,7 @@ pub fn expand( data, .. }: DeriveInput, -) -> Vec { +) -> ItemImpl { let data = match data { Data::Enum(data) => data, _ => unreachable!("expand_enum is called with none-enum item"), @@ -438,5 +438,5 @@ pub fn expand( .with_generics(generics) }; - vec![deserialize] + deserialize } diff --git a/crates/ast_node/src/lib.rs b/crates/ast_node/src/lib.rs index 4c2c45b50bea..b27e1554c620 100644 --- a/crates/ast_node/src/lib.rs +++ b/crates/ast_node/src/lib.rs @@ -16,15 +16,10 @@ mod spanned; #[proc_macro_derive(Spanned, attributes(span))] pub fn derive_spanned(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input = parse::(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. @@ -32,13 +27,7 @@ pub fn derive_spanned(input: proc_macro::TokenStream) -> proc_macro::TokenStream pub fn derive_deserialize_enum(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input = parse::(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()) } @@ -143,7 +132,7 @@ pub fn ast_serde( } }; - print("ast_serde", item) + print("ast_serde", item.into()) } struct AddAttr; @@ -307,7 +296,7 @@ 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); } } @@ -315,23 +304,5 @@ pub fn ast_node( } }; - print("ast_node", item) -} - -/// Workarounds https://github.com/rust-lang/rust/issues/44925 -fn print_item>( - name: &'static str, - const_name: &str, - item: T, -) -> proc_macro::TokenStream { - let item = Quote::new(def_site::()).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()) } diff --git a/crates/from_variant/src/lib.rs b/crates/from_variant/src/lib.rs index 908290820154..5041ac97601f 100644 --- a/crates/from_variant/src/lib.rs +++ b/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::*; @@ -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( @@ -62,7 +62,8 @@ fn derive( } } )) - .parse(); + .parse::() + .with_generics(generics.clone()); from_impls.push(from_impl); } @@ -73,7 +74,4 @@ fn derive( } from_impls - .into_iter() - .map(|item| item.with_generics(generics.clone())) - .collect() } diff --git a/crates/swc_macros_common/src/lib.rs b/crates/swc_macros_common/src/lib.rs index 09c6104b2ec2..b2b2a994c716 100644 --- a/crates/swc_macros_common/src/lib.rs +++ b/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)] @@ -29,14 +31,9 @@ pub fn def_site() -> T { } /// `attr` - tokens inside `#[]`. e.g. `derive(EqIgnoreSpan)`, ast_node -pub fn print>( - 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(), diff --git a/crates/swc_macros_common/src/syn_ext.rs b/crates/swc_macros_common/src/syn_ext.rs index 493baddd770d..384575c7ec5f 100644 --- a/crates/swc_macros_common/src/syn_ext.rs +++ b/crates/swc_macros_common/src/syn_ext.rs @@ -1,4 +1,3 @@ -use pmutil::ToTokensExt; use quote::quote; use syn::{punctuated::Pair, *}; @@ -60,46 +59,24 @@ impl ItemImplExt for ItemImpl { // Handle generics defined on struct, enum, or union. let mut item: ItemImpl = { - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); - let item = if let Some((ref polarity, ref path, ref for_token)) = self.trait_ { - quote! { - impl #impl_generics #polarity #path #for_token #ty #ty_generics #where_clause {} - } - } else { - quote! { - impl #impl_generics #ty #ty_generics #where_clause {} - - } + let (_, ty_generics, _) = generics.split_for_impl(); + let item = quote! { + #ty #ty_generics }; - parse(item.dump().into()) - .unwrap_or_else(|err| panic!("with_generics failed: {}\n{}", err, item.dump())) + + ItemImpl { + generics, + self_ty: parse2(item).unwrap(), + ..self + } }; // Handle generics added by proc-macro. item.generics .params .extend(self.generics.params.into_pairs()); - match self.generics.where_clause { - Some(WhereClause { - ref mut predicates, .. - }) => predicates.extend( - generics - .where_clause - .into_iter() - .flat_map(|wc| wc.predicates.into_pairs()), - ), - ref mut opt @ None => *opt = generics.where_clause, - } - ItemImpl { - attrs: self.attrs, - defaultness: self.defaultness, - unsafety: self.unsafety, - impl_token: self.impl_token, - brace_token: self.brace_token, - items: self.items, - ..item - } + item } } diff --git a/crates/testing_macros/src/fixture.rs b/crates/testing_macros/src/fixture.rs index ccd768bb05ee..36ba62b813f3 100644 --- a/crates/testing_macros/src/fixture.rs +++ b/crates/testing_macros/src/fixture.rs @@ -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 { @@ -96,7 +96,7 @@ impl Parse for Config { } } -pub fn expand(callee: &Ident, attr: Config) -> Result, Error> { +pub fn expand(callee: &Ident, attr: Config) -> Result, 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", )); @@ -152,39 +152,32 @@ pub fn expand(callee: &Ident, attr: Config) -> Result, 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::(); - - if !ignored { - f.attrs.retain(|attr| { - if let Some(name) = attr.path.get_ident() { - if name == "ignore" { - return false; - } - } - - true - }); - // - } + ); test_fns.push(f); }