Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into better-typeid
Browse files Browse the repository at this point in the history
  • Loading branch information
oscartbeaumont committed Dec 25, 2023
2 parents 38eeb2c + ac331ca commit d6259a7
Show file tree
Hide file tree
Showing 15 changed files with 167 additions and 101 deletions.
5 changes: 3 additions & 2 deletions macros/src/type/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub fn parse_enum(
container_attrs: &ContainerAttr,
generics: &Generics,
crate_ref: &TokenStream,
sid: &TokenStream,
data: &DataEnum,
) -> syn::Result<(TokenStream, TokenStream, bool)> {
if container_attrs.transparent {
Expand Down Expand Up @@ -232,12 +233,12 @@ pub fn parse_enum(
let skip_bigint_checs = enum_attrs.unstable_skip_bigint_checks;

Ok((
quote!(#crate_ref::DataType::Enum(#crate_ref::internal::construct::r#enum(#name.into(), SID, #repr, #skip_bigint_checs, vec![#(#definition_generics),*], vec![#(#variant_types),*]))),
quote!(#crate_ref::DataType::Enum(#crate_ref::internal::construct::r#enum(#name.into(), #sid, #repr, #skip_bigint_checs, vec![#(#definition_generics),*], vec![#(#variant_types),*]))),
quote!({
let generics = vec![#(#reference_generics),*];
#crate_ref::reference::reference::<Self>(type_map, #crate_ref::internal::construct::data_type_reference(
#name.into(),
SID,
#sid,
generics
))
}),
Expand Down
37 changes: 29 additions & 8 deletions macros/src/type/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,29 @@ pub fn add_type_to_where_clause(ty: &TokenStream, generics: &Generics) -> Option
}
}

type DtGenericFn = fn(&TokenStream, TokenStream) -> TokenStream;
fn dt_generic_fn(f: DtGenericFn) -> DtGenericFn {
f
}

pub fn construct_datatype(
var_ident: Ident,
ty: &Type,
generic_idents: &[(usize, &Ident)],
crate_ref: &TokenStream,
inline: bool,
) -> syn::Result<TokenStream> {
let (method, transform) = match inline {
true => (quote!(inline), quote!()),
false => (quote!(reference), quote!(.inner)),
let (method, transform, generics) = match inline {
true => (
quote!(inline),
quote!(),
dt_generic_fn(|crate_ref, tokens| quote!(#crate_ref::Generics::Provided(#tokens))),
),
false => (
quote!(reference),
quote!(.inner),
dt_generic_fn(|_, tokens| tokens),
),
};

let path = match ty {
Expand All @@ -115,10 +128,11 @@ pub fn construct_datatype(
.enumerate()
.map(|(i, _)| format_ident!("{}_{}", &var_ident, i));

let generics = generics(&crate_ref, quote!(&[#(#generic_var_idents),*]));
return Ok(quote! {
#(#elems)*

let #var_ident = <#ty as #crate_ref::Type>::#method(type_map, &[#(#generic_var_idents),*])#transform;
let #var_ident = <#ty as #crate_ref::Type>::#method(type_map, #generics)#transform;
});
}
Type::Paren(p) => {
Expand All @@ -134,10 +148,11 @@ pub fn construct_datatype(
inline,
)?;

let generics = generics(&crate_ref, quote!(&[#elem_var_ident]));
return Ok(quote! {
#elem

let #var_ident = <#ty as #crate_ref::Type>::#method(type_map, &[#elem_var_ident])#transform;
let #var_ident = <#ty as #crate_ref::Type>::#method(type_map, #generics)#transform;
});
}
Type::Ptr(TypePtr { elem, .. }) | Type::Reference(TypeReference { elem, .. }) => {
Expand All @@ -151,8 +166,9 @@ pub fn construct_datatype(
));
}
Type::Macro(m) => {
let generics = generics(&crate_ref, quote!(&[]));
return Ok(quote! {
let #var_ident = <#m as #crate_ref::Type>::#method(type_map, &[])#transform;
let #var_ident = <#m as #crate_ref::Type>::#method(type_map, #generics)#transform;
});
}
ty => {
Expand All @@ -172,10 +188,14 @@ pub fn construct_datatype(
.find(|(_, ident)| ident == &type_ident)
{
let type_ident = type_ident.to_string();
let generics = generics(
&crate_ref,
quote!(&[#crate_ref::DataType::Generic(std::borrow::Cow::Borrowed(#type_ident).into())]),
);
return Ok(quote! {
let #var_ident = generics.get(#i).cloned().unwrap_or_else(
|| {
<#generic_ident as #crate_ref::Type>::#method(type_map, &[#crate_ref::DataType::Generic(std::borrow::Cow::Borrowed(#type_ident).into())])#transform
<#generic_ident as #crate_ref::Type>::#method(type_map, #generics)#transform
},
);
});
Expand Down Expand Up @@ -218,9 +238,10 @@ pub fn construct_datatype(
.iter()
.map(|(i, _)| format_ident!("{}_{}", &var_ident, i));

let generics = generics(&crate_ref, quote!(&[#(#generic_var_idents),*]));
Ok(quote! {
#(#generic_vars)*

let #var_ident = <#ty as #crate_ref::Type>::#method(type_map, &[#(#generic_var_idents),*])#transform;
let #var_ident = <#ty as #crate_ref::Type>::#method(type_map, #generics)#transform;
})
}
35 changes: 18 additions & 17 deletions macros/src/type/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,18 @@ pub fn derive(input: proc_macro::TokenStream) -> syn::Result<proc_macro::TokenSt
unraw_raw_ident(&format_ident!("{}", raw_ident.to_string())).to_token_stream()
});

let sid = quote!(#crate_ref::internal::construct::sid(#name, concat!("::", module_path!(), ":", line!(), ":", column!())));
let (inlines, reference, can_flatten) = match data {
Data::Struct(data) => parse_struct(&name, &container_attrs, generics, &crate_ref, data),
Data::Struct(data) => {
parse_struct(&name, &container_attrs, generics, &crate_ref, &sid, data)
}
Data::Enum(data) => parse_enum(
&name,
&EnumAttr::from_attrs(&container_attrs, &mut attrs)?,
&container_attrs,
generics,
&crate_ref,
&sid,
data,
),
Data::Union(data) => Err(syn::Error::new_spanned(
Expand Down Expand Up @@ -123,26 +127,22 @@ pub fn derive(input: proc_macro::TokenStream) -> syn::Result<proc_macro::TokenSt
let comments = &container_attrs.common.doc;
let deprecated = container_attrs.common.deprecated_as_tokens(&crate_ref);

let sid = quote!(#crate_ref::internal::construct::sid(#name, concat!("::", module_path!(), ":", line!(), ":", column!())));
let impl_location = quote!(#crate_ref::internal::construct::impl_location(concat!(file!(), ":", line!(), ":", column!())));

Ok(quote! {
const _: () = {
const SID: #crate_ref::SpectaID = #sid;
const IMPL_LOCATION: #crate_ref::ImplLocation = #impl_location;
const DEFINITION_GENERICS: &[#crate_ref::DataType] = &[#(#definition_generics),*];

#[automatically_derived]
#type_impl_heading {
fn inline(type_map: &mut #crate_ref::TypeMap, generics: &[#crate_ref::DataType]) -> #crate_ref::DataType {
#inlines
}
fn inline(type_map: &mut #crate_ref::TypeMap, generics: #crate_ref::Generics) -> #crate_ref::DataType {
let generics = match generics {
#crate_ref::Generics::Definition => DEFINITION_GENERICS,
#crate_ref::Generics::Provided(generics) => generics,
};

fn definition(type_map: &mut #crate_ref::TypeMap) -> #crate_ref::DataType {
Self::inline(
type_map,
&DEFINITION_GENERICS
)
#inlines
}

fn reference(type_map: &mut #crate_ref::TypeMap, generics: &[#crate_ref::DataType]) -> #crate_ref::reference::Reference {
Expand All @@ -152,17 +152,18 @@ pub fn derive(input: proc_macro::TokenStream) -> syn::Result<proc_macro::TokenSt

#[automatically_derived]
impl #bounds #crate_ref::NamedType for #ident #type_args #where_bound {
const SID: #crate_ref::SpectaID = SID;
const IMPL_LOCATION: #crate_ref::ImplLocation = IMPL_LOCATION;
fn sid() -> #crate_ref::SpectaID {
#sid
}

fn named_data_type(type_map: &mut #crate_ref::TypeMap, generics: &[#crate_ref::DataType]) -> #crate_ref::NamedDataType {
#crate_ref::internal::construct::named_data_type(
#name.into(),
#comments.into(),
#deprecated,
SID,
#sid,
IMPL_LOCATION,
<Self as #crate_ref::Type>::inline(type_map, generics)
<Self as #crate_ref::Type>::inline(type_map, #crate_ref::Generics::Provided(generics))
)
}

Expand All @@ -171,9 +172,9 @@ pub fn derive(input: proc_macro::TokenStream) -> syn::Result<proc_macro::TokenSt
#name.into(),
#comments.into(),
#deprecated,
SID,
#sid,
IMPL_LOCATION,
<Self as #crate_ref::Type>::definition(type_map)
<Self as #crate_ref::Type>::inline(type_map, #crate_ref::Generics::Definition)
)
}
}
Expand Down
7 changes: 4 additions & 3 deletions macros/src/type/struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub fn parse_struct(
container_attrs: &ContainerAttr,
generics: &Generics,
crate_ref: &TokenStream,
sid: &TokenStream,
data: &DataStruct,
) -> syn::Result<(TokenStream, TokenStream, bool)> {
let generic_idents = generics
Expand Down Expand Up @@ -189,7 +190,7 @@ pub fn parse_struct(
quote! {
fn validate_flatten<T: #crate_ref::Flatten>() {}
validate_flatten::<#field_ty>();
#crate_ref::internal::flatten::<#field_ty>(SID, type_map, &generics)
#crate_ref::internal::flatten::<#field_ty>(#sid, type_map, &generics)
}
} else {
quote! {
Expand Down Expand Up @@ -265,7 +266,7 @@ pub fn parse_struct(
Fields::Unit => quote!(#crate_ref::internal::construct::struct_unit()),
};

quote!(#crate_ref::DataType::Struct(#crate_ref::internal::construct::r#struct(#name.into(), Some(SID), vec![#(#definition_generics),*], #fields)))
quote!(#crate_ref::DataType::Struct(#crate_ref::internal::construct::r#struct(#name.into(), Some(#sid), vec![#(#definition_generics),*], #fields)))
};

let category = if container_attrs.inline {
Expand All @@ -278,7 +279,7 @@ pub fn parse_struct(
#reference_generics
#crate_ref::reference::reference::<Self>(type_map, #crate_ref::internal::construct::data_type_reference(
#name.into(),
SID,
#sid,
vec![#(#reference_generics2),*]
))
})
Expand Down
12 changes: 7 additions & 5 deletions src/datatype/reference.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Helpers for generating [Type::reference] implementations.

use crate::{DataType, DataTypeReference, NamedType, Type, TypeMap};
use crate::{DataType, DataTypeReference, Generics, NamedType, Type, TypeMap};

/// A reference datatype.
///
Expand All @@ -12,15 +12,17 @@ pub struct Reference {

pub fn inline<T: Type + ?Sized>(type_map: &mut TypeMap, generics: &[DataType]) -> Reference {
Reference {
inner: T::inline(type_map, generics),
inner: T::inline(type_map, Generics::Provided(generics)),
}
}

pub fn reference<T: NamedType>(type_map: &mut TypeMap, reference: DataTypeReference) -> Reference {
if type_map.map.get(&T::SID).is_none() {
type_map.map.entry(T::SID).or_insert(None);
let sid = T::sid();

if type_map.map.get(&sid).is_none() {
type_map.map.entry(sid).or_insert(None);
let dt = T::definition_named_data_type(type_map);
type_map.map.insert(T::SID, Some(dt));
type_map.map.insert(sid, Some(dt));
}

Reference {
Expand Down
4 changes: 2 additions & 2 deletions src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub use ctor;
#[cfg(feature = "functions")]
pub use specta_macros::fn_datatype;

use crate::{DataType, DeprecatedType, Field, SpectaID, Type, TypeMap};
use crate::{DataType, DeprecatedType, Field, Generics, SpectaID, Type, TypeMap};

/// Functions used to construct `crate::datatype` types (they have private fields so can't be constructed directly).
/// We intentionally keep their fields private so we can modify them without a major version bump.
Expand Down Expand Up @@ -184,7 +184,7 @@ pub fn flatten<T: Type>(sid: SpectaID, type_map: &mut TypeMap, generics: &[DataT
panic!("Type recursion limit exceeded!");
}

let ty = T::inline(type_map, generics);
let ty = T::inline(type_map, Generics::Provided(generics));

type_map.flatten_stack.pop();

Expand Down
2 changes: 1 addition & 1 deletion src/lang/ts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub fn inline_ref<T: Type>(_: &T, conf: &ExportConfig) -> Output {
/// Eg. `{ demo: string; };`
pub fn inline<T: Type>(conf: &ExportConfig) -> Output {
let mut type_map = TypeMap::default();
let ty = T::inline(&mut type_map, &[]);
let ty = T::inline(&mut type_map, Generics::NONE);
is_valid_ty(&ty, &type_map)?;
let result = datatype(conf, &ty, &type_map);

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ mod static_types;
pub mod r#type;

pub use crate::serde::*;
#[doc(hidden)]
#[doc(hidden)] // TODO: Should we actually do this? I think not
pub use datatype::*;
pub use lang::*;
pub use r#type::*;
Expand Down
6 changes: 3 additions & 3 deletions src/static_types.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::fmt::Debug;

use crate::{DataType, Type, TypeMap};
use crate::{DataType, Generics, Type, TypeMap};

/// Easily convert a non-Specta type into a Specta compatible type.
/// This will be typed as `any` in Typescript.
Expand Down Expand Up @@ -34,7 +34,7 @@ use crate::{DataType, Type, TypeMap};
pub struct Any<T = ()>(T);

impl<T> Type for Any<T> {
fn inline(_: &mut TypeMap, _: &[DataType]) -> DataType {
fn inline(_: &mut TypeMap, _: Generics) -> DataType {
DataType::Any
}
}
Expand Down Expand Up @@ -97,7 +97,7 @@ impl<T: serde::Serialize> serde::Serialize for Any<T> {
pub struct Unknown<T = ()>(T);

impl<T> Type for Unknown<T> {
fn inline(_: &mut TypeMap, _: &[DataType]) -> DataType {
fn inline(_: &mut TypeMap, _: Generics) -> DataType {
DataType::Unknown
}
}
Expand Down
Loading

0 comments on commit d6259a7

Please sign in to comment.