Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion macros/src/deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::{Path, Type};

#[derive(Clone, Debug)]
pub struct Dependencies {
crate_rename: Rc<Path>,
dependencies: HashSet<Dependency>,
types: HashSet<Rc<Type>>,
}

#[derive(Hash, Eq, PartialEq)]
#[derive(Clone, Hash, Eq, PartialEq, Debug)]
enum Dependency {
// A dependency on all dependencies of `ty`.
// This does not include a dependency on `ty` itself - only its dependencies!
Expand Down
58 changes: 41 additions & 17 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ struct DerivedTS {
inline: TokenStream,
inline_flattened: Option<TokenStream>,
dependencies: Dependencies,
flattened_dependencies: Dependencies,
concrete: HashMap<Ident, Type>,
bound: Option<Vec<WherePredicate>>,
ts_enum: Option<Repr>,
Expand Down Expand Up @@ -77,13 +78,15 @@ impl DerivedTS {
};

let ident = self.ts_name.clone();
let impl_start = generate_impl_block_header(
let (impl_start, bounds) = generate_impl_block_header(
&crate_rename,
&rust_ty,
&generics,
self.bound.as_deref(),
&self.dependencies,
&self.flattened_dependencies,
);

let assoc_type = generate_assoc_type(&rust_ty, &crate_rename, &generics, &self.concrete);
let name = self.generate_name_fn(&generics);
let is_enum = self.is_enum.clone();
Expand All @@ -92,9 +95,20 @@ impl DerivedTS {
let dependencies = &self.dependencies;
let generics_fn = self.generate_generics_fn(&generics);

let inline_flattened = self.inline_flattened.clone().map(|x| {
quote! {
#[automatically_derived]
#impl_start #crate_rename::Flattenable #bounds {
fn inline_flattened(cfg: &#crate_rename::Config) -> String {
#x
}
}
}
});

quote! {
#[automatically_derived]
#impl_start {
#impl_start #crate_rename::TS #bounds {
#assoc_type
type OptionInnerType = Self;

Expand All @@ -119,6 +133,8 @@ impl DerivedTS {
}
}

#inline_flattened

#export
}
}
Expand Down Expand Up @@ -178,10 +194,12 @@ impl DerivedTS {
type OptionInnerType = Self;
fn name(cfg: &#crate_rename::Config) -> String { stringify!(#generics).to_owned() }
fn inline(cfg: &#crate_rename::Config) -> String { panic!("{} cannot be inlined", #name) }
fn inline_flattened(cfg: &#crate_rename::Config) -> String { stringify!(#generics).to_owned() }
fn decl(cfg: &#crate_rename::Config) -> String { panic!("{} cannot be declared", #name) }
fn decl_concrete(cfg: &#crate_rename::Config) -> String { panic!("{} cannot be declared", #name) }
}
impl #crate_rename::Flattenable for #generics {
fn inline_flattened(cfg: &#crate_rename::Config) -> String { stringify!(#generics).to_owned() }
}
)*
}
}
Expand Down Expand Up @@ -245,12 +263,6 @@ impl DerivedTS {
let inline = &self.inline;
let crate_rename = &self.crate_rename;

let inline_flattened = self.inline_flattened.clone().unwrap_or_else(|| {
quote! {
panic!("{} cannot be flattened", <Self as #crate_rename::TS>::name(cfg))
}
});

let inline = match self.ts_enum {
Some(Repr::Int) => quote! {
let variants = #inline.replace(|x: char| !x.is_numeric() && x != ',', "");
Expand Down Expand Up @@ -301,10 +313,6 @@ impl DerivedTS {
fn inline(cfg: &#crate_rename::Config) -> String {
#inline
}

fn inline_flattened(cfg: &#crate_rename::Config) -> String {
#inline_flattened
}
}
}

Expand Down Expand Up @@ -394,7 +402,8 @@ fn generate_impl_block_header(
generics: &Generics,
bounds: Option<&[WherePredicate]>,
dependencies: &Dependencies,
) -> TokenStream {
flattened_dependencies: &Dependencies,
) -> (TokenStream, TokenStream) {
use GenericParam as G;

let params = generics.params.iter().map(|param| match param {
Expand Down Expand Up @@ -426,18 +435,23 @@ fn generate_impl_block_header(
let where_bound = match bounds {
Some(bounds) => quote! { where #(#bounds),* },
None => {
let bounds = generate_where_clause(crate_rename, generics, dependencies);
let bounds =
generate_where_clause(crate_rename, generics, dependencies, flattened_dependencies);
quote! { #bounds }
}
};

quote!(impl <#(#params),*> #crate_rename::TS for #ty <#(#type_args),*> #where_bound)
(
quote!(impl <#(#params),*>),
quote!(for #ty <#(#type_args),*> #where_bound),
)
}

fn generate_where_clause(
crate_rename: &Path,
generics: &Generics,
dependencies: &Dependencies,
flattened_dependencies: &Dependencies,
) -> WhereClause {
let used_types = {
let is_type_param = |id: &Ident| generics.type_params().any(|p| &p.ident == id);
Expand All @@ -449,9 +463,19 @@ fn generate_where_clause(
used_types.into_iter()
};

let flattened_used_types = {
let is_type_param = |id: &Ident| generics.type_params().any(|p| &p.ident == id);

let mut flattened_used_types = HashSet::new();
for ty in flattened_dependencies.used_types() {
used_type_params(&mut flattened_used_types, ty, is_type_param);
}
flattened_used_types.into_iter()
};

let existing = generics.where_clause.iter().flat_map(|w| &w.predicates);
parse_quote! {
where #(#existing,)* #(#used_types: #crate_rename::TS),*
where #(#existing,)* #(#used_types: #crate_rename::TS),* #(, #flattened_used_types: #crate_rename::Flattenable)*
}
}

Expand Down
9 changes: 8 additions & 1 deletion macros/src/types/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ pub(crate) fn r#enum_def(s: &ItemEnum) -> syn::Result<DerivedTS> {

let mut formatted_variants = Vec::new();
let mut dependencies = Dependencies::new(crate_rename.clone());
let mut flattened_dependencies = Dependencies::new(crate_rename.clone());

for variant in &s.variants {
format_variant(
&mut formatted_variants,
&mut dependencies,
&mut flattened_dependencies,
&enum_attr,
variant,
)?;
Expand All @@ -58,6 +60,7 @@ pub(crate) fn r#enum_def(s: &ItemEnum) -> syn::Result<DerivedTS> {
format!("({})", [#(#formatted_variants),*].join(" | "))
)),
dependencies,
flattened_dependencies,
docs: enum_attr.docs,
export: enum_attr.export,
export_to: enum_attr.export_to,
Expand All @@ -72,6 +75,7 @@ pub(crate) fn r#enum_def(s: &ItemEnum) -> syn::Result<DerivedTS> {
fn format_variant(
formatted_variants: &mut Vec<TokenStream>,
dependencies: &mut Dependencies,
flattened_dependencies: &mut Dependencies,
enum_attr: &EnumAttr,
variant: &Variant,
) -> syn::Result<()> {
Expand Down Expand Up @@ -123,6 +127,7 @@ fn format_variant(
)?;

let variant_dependencies = variant_type.dependencies;
let variant_flattened_dependencies = variant_type.flattened_dependencies;
let inline_type = variant_type.inline;

let parsed_ty = match (&variant_attr.type_as, &variant_attr.type_override) {
Expand All @@ -134,6 +139,7 @@ fn format_variant(
(None, Some(ty)) => quote!(#ty.to_owned()),
(None, None) => {
dependencies.append(variant_dependencies);
flattened_dependencies.append(variant_flattened_dependencies);
inline_type
}
};
Expand Down Expand Up @@ -228,7 +234,8 @@ fn empty_enum(ts_name: Expr, enum_attr: EnumAttr) -> DerivedTS {
inline: quote!("never".to_owned()),
docs: enum_attr.docs,
inline_flattened: None,
dependencies: Dependencies::new(crate_rename),
dependencies: Dependencies::new(crate_rename.clone()),
flattened_dependencies: Dependencies::new(crate_rename),
export: enum_attr.export,
export_to: enum_attr.export_to,
ts_name,
Expand Down
7 changes: 6 additions & 1 deletion macros/src/types/named.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub(crate) fn named(attr: &StructAttr, ts_name: Expr, fields: &FieldsNamed) -> R
let mut formatted_fields = Vec::new();
let mut flattened_fields = Vec::new();
let mut dependencies = Dependencies::new(crate_rename.clone());
let mut flattened_dependencies = Dependencies::new(crate_rename.clone());

if let Some(tag) = &attr.tag {
formatted_fields.push(quote! {
Expand All @@ -29,6 +30,7 @@ pub(crate) fn named(attr: &StructAttr, ts_name: Expr, fields: &FieldsNamed) -> R
&mut formatted_fields,
&mut flattened_fields,
&mut dependencies,
&mut flattened_dependencies,
field,
&attr.rename_all,
attr.optional_fields,
Expand Down Expand Up @@ -67,6 +69,7 @@ pub(crate) fn named(attr: &StructAttr, ts_name: Expr, fields: &FieldsNamed) -> R
inline_flattened: Some(quote!(#inline_flattened.replace(" } & { ", " "))),
docs: attr.docs.clone(),
dependencies,
flattened_dependencies,
export: attr.export,
export_to: attr.export_to.clone(),
ts_name,
Expand All @@ -92,6 +95,7 @@ fn format_field(
formatted_fields: &mut Vec<TokenStream>,
flattened_fields: &mut Vec<TokenStream>,
dependencies: &mut Dependencies,
flattened_dependencies: &mut Dependencies,
field: &Field,
rename_all: &Option<Inflection>,
struct_optional: Optional,
Expand Down Expand Up @@ -124,7 +128,8 @@ fn format_field(
}

if field_attr.flatten {
flattened_fields.push(quote!(<#ty as #crate_rename::TS>::inline_flattened(cfg)));
flattened_fields.push(quote!(<#ty as #crate_rename::Flattenable>::inline_flattened(cfg)));
flattened_dependencies.append_from(&ty);
return Ok(());
}

Expand Down
1 change: 1 addition & 0 deletions macros/src/types/newtype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub(crate) fn newtype(
inline_flattened: None,
docs: attr.docs.clone(),
dependencies,
flattened_dependencies: Dependencies::new(crate_rename.clone()),
export: attr.export,
export_to: attr.export_to.clone(),
ts_name,
Expand Down
3 changes: 2 additions & 1 deletion macros/src/types/tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub(crate) fn tuple(attr: &StructAttr, ts_name: Expr, fields: &FieldsUnnamed) ->
}

Ok(DerivedTS {
crate_rename,
crate_rename: crate_rename.clone(),
inline: quote! {
format!(
"[{}]",
Expand All @@ -34,6 +34,7 @@ pub(crate) fn tuple(attr: &StructAttr, ts_name: Expr, fields: &FieldsUnnamed) ->
inline_flattened: None,
docs: attr.docs.clone(),
dependencies,
flattened_dependencies: Dependencies::new(crate_rename),
export: attr.export,
export_to: attr.export_to.clone(),
ts_name,
Expand Down
6 changes: 6 additions & 0 deletions macros/src/types/type_as.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ pub(crate) fn type_as_struct(
let mut dependencies = Dependencies::new(crate_rename.clone());
dependencies.append_from(type_as);

let flattened_dependencies = Dependencies::new(crate_rename.clone());

Ok(DerivedTS {
crate_rename: crate_rename.clone(),
inline: quote!(<#type_as as #crate_rename::TS>::inline(cfg)),
inline_flattened: None,
docs: attr.docs.clone(),
dependencies,
flattened_dependencies,
export: attr.export,
export_to: attr.export_to.clone(),
ts_name,
Expand All @@ -39,12 +42,15 @@ pub(crate) fn type_as_enum(attr: &EnumAttr, ts_name: Expr, type_as: &Type) -> Re
let mut dependencies = Dependencies::new(crate_rename.clone());
dependencies.append_from(type_as);

let flattened_dependencies = Dependencies::new(crate_rename.clone());

Ok(DerivedTS {
crate_rename: crate_rename.clone(),
inline: quote!(<#type_as as #crate_rename::TS>::inline(cfg)),
inline_flattened: None,
docs: attr.docs.clone(),
dependencies,
flattened_dependencies,
export: attr.export,
export_to: attr.export_to.clone(),
ts_name,
Expand Down
6 changes: 4 additions & 2 deletions macros/src/types/type_override.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ pub(crate) fn type_override_struct(
inline: quote!(#type_override.to_owned()),
inline_flattened: None,
docs: attr.docs.clone(),
dependencies: Dependencies::new(crate_rename),
dependencies: Dependencies::new(crate_rename.clone()),
flattened_dependencies: Dependencies::new(crate_rename),
export: attr.export,
export_to: attr.export_to.clone(),
ts_name,
Expand All @@ -42,7 +43,8 @@ pub(crate) fn type_override_enum(
inline: quote!(#type_override.to_owned()),
inline_flattened: None,
docs: attr.docs.clone(),
dependencies: Dependencies::new(crate_rename),
dependencies: Dependencies::new(crate_rename.clone()),
flattened_dependencies: Dependencies::new(crate_rename),
export: attr.export,
export_to: attr.export_to.clone(),
ts_name,
Expand Down
9 changes: 6 additions & 3 deletions macros/src/types/unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ pub(crate) fn empty_object(attr: &StructAttr, ts_name: Expr) -> DerivedTS {
inline: quote!("Record<symbol, never>".to_owned()),
inline_flattened: None,
docs: attr.docs.clone(),
dependencies: Dependencies::new(crate_rename),
dependencies: Dependencies::new(crate_rename.clone()),
flattened_dependencies: Dependencies::new(crate_rename),
export: attr.export,
export_to: attr.export_to.clone(),
ts_name,
Expand All @@ -34,7 +35,8 @@ pub(crate) fn empty_array(attr: &StructAttr, ts_name: Expr) -> DerivedTS {
inline: quote!("never[]".to_owned()),
inline_flattened: None,
docs: attr.docs.clone(),
dependencies: Dependencies::new(crate_rename),
dependencies: Dependencies::new(crate_rename.clone()),
flattened_dependencies: Dependencies::new(crate_rename),
export: attr.export,
export_to: attr.export_to.clone(),
ts_name,
Expand All @@ -53,7 +55,8 @@ pub(crate) fn null(attr: &StructAttr, ts_name: Expr) -> DerivedTS {
inline: quote!("null".to_owned()),
inline_flattened: None,
docs: attr.docs.clone(),
dependencies: Dependencies::new(crate_rename),
dependencies: Dependencies::new(crate_rename.clone()),
flattened_dependencies: Dependencies::new(crate_rename),
export: attr.export,
export_to: attr.export_to.clone(),
ts_name,
Expand Down
Loading