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

Option to rename source of TS trait #274

Merged
merged 11 commits into from
Mar 20, 2024
17 changes: 13 additions & 4 deletions macros/src/attr/enum.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use std::collections::HashMap;

use proc_macro2::TokenStream;
use syn::{Attribute, Ident, Result, Type, WherePredicate};

use super::{parse_assign_from_str, parse_bound};
use crate::{
attr::{parse_assign_inflection, parse_assign_str, parse_concrete, Inflection},
utils::{parse_attrs, parse_docs},
};

use super::parse_bound;

#[derive(Default)]
pub struct EnumAttr {
pub crate_rename: Option<TokenStream>,
escritorio-gustavo marked this conversation as resolved.
Show resolved Hide resolved
pub rename_all: Option<Inflection>,
pub rename_all_fields: Option<Inflection>,
pub rename: Option<String>,
Expand Down Expand Up @@ -64,6 +65,7 @@ impl EnumAttr {
fn merge(
&mut self,
EnumAttr {
crate_rename,
rename_all,
rename_all_fields,
rename,
Expand All @@ -77,6 +79,7 @@ impl EnumAttr {
bound,
}: EnumAttr,
) {
self.crate_rename = self.crate_rename.take().or(crate_rename);
self.rename = self.rename.take().or(rename);
self.rename_all = self.rename_all.take().or(rename_all);
self.rename_all_fields = self.rename_all_fields.take().or(rename_all_fields);
Expand All @@ -87,15 +90,21 @@ impl EnumAttr {
self.export_to = self.export_to.take().or(export_to);
self.docs = docs;
self.concrete.extend(concrete);
self.bound = self.bound
self.bound = self
.bound
.take()
.map(|b| b.into_iter().chain(bound.clone().unwrap_or_default()).collect())
.map(|b| {
b.into_iter()
.chain(bound.clone().unwrap_or_default())
.collect()
})
.or(bound);
}
}

impl_parse! {
EnumAttr(input, out) {
"crate_rename" => out.crate_rename = Some(parse_assign_from_str(input)?),
"rename" => out.rename = Some(parse_assign_str(input)?),
"rename_all" => out.rename_all = Some(parse_assign_inflection(input)?),
"rename_all_fields" => out.rename_all_fields = Some(parse_assign_inflection(input)?),
Expand Down
5 changes: 3 additions & 2 deletions macros/src/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ pub use r#enum::*;
pub use r#struct::*;
use syn::{
parse::{Parse, ParseStream},
Error, Lit, Result, Token, WherePredicate, punctuated::Punctuated,
punctuated::Punctuated,
Error, Lit, Result, Token, WherePredicate,
};
pub use variant::*;

Expand Down Expand Up @@ -136,7 +137,7 @@ fn parse_bound(input: ParseStream) -> Result<Vec<WherePredicate>> {
let parser = Punctuated::<WherePredicate, Token![,]>::parse_terminated;

Ok(string.parse_with(parser)?.into_iter().collect())
},
}
other => Err(Error::new(other.span(), "expected string")),
}
}
17 changes: 13 additions & 4 deletions macros/src/attr/struct.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use std::{collections::HashMap, convert::TryFrom};

use proc_macro2::TokenStream;
use syn::{Attribute, Ident, Result, Type, WherePredicate};

use super::{parse_assign_from_str, parse_bound};
use crate::{
attr::{parse_assign_str, parse_concrete, Inflection, VariantAttr},
utils::{parse_attrs, parse_docs},
};

use super::parse_bound;

#[derive(Default, Clone)]
pub struct StructAttr {
pub crate_rename: Option<TokenStream>,
escritorio-gustavo marked this conversation as resolved.
Show resolved Hide resolved
pub rename_all: Option<Inflection>,
pub rename: Option<String>,
pub export_to: Option<String>,
Expand Down Expand Up @@ -41,6 +42,7 @@ impl StructAttr {
fn merge(
&mut self,
StructAttr {
crate_rename,
rename_all,
rename,
export,
Expand All @@ -51,16 +53,22 @@ impl StructAttr {
bound,
}: StructAttr,
) {
self.crate_rename = self.crate_rename.take().or(crate_rename);
self.rename = self.rename.take().or(rename);
self.rename_all = self.rename_all.take().or(rename_all);
self.export_to = self.export_to.take().or(export_to);
self.export = self.export || export;
self.tag = self.tag.take().or(tag);
self.docs = docs;
self.concrete.extend(concrete);
self.bound = self.bound
self.bound = self
.bound
.take()
.map(|b| b.into_iter().chain(bound.clone().unwrap_or_default()).collect())
.map(|b| {
b.into_iter()
.chain(bound.clone().unwrap_or_default())
.collect()
})
.or(bound);
}
}
Expand All @@ -82,6 +90,7 @@ impl From<VariantAttr> for StructAttr {

impl_parse! {
StructAttr(input, out) {
"crate_rename" => out.crate_rename = Some(parse_assign_from_str(input)?),
"rename" => out.rename = Some(parse_assign_str(input)?),
"rename_all" => out.rename_all = Some(parse_assign_str(input).and_then(Inflection::try_from)?),
"tag" => out.tag = Some(parse_assign_str(input)?),
Expand Down
10 changes: 9 additions & 1 deletion macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mod deps;
mod types;

struct DerivedTS {
crate_rename: Option<TokenStream>,
ts_name: String,
docs: String,
inline: TokenStream,
Expand Down Expand Up @@ -59,8 +60,14 @@ impl DerivedTS {
docs => Some(quote!(const DOCS: Option<&'static str> = Some(#docs);)),
};

let crate_rename = self
.crate_rename
.clone()
.unwrap_or_else(|| quote! { ::ts_rs });

let ident = self.ts_name.clone();
let impl_start = generate_impl_block_header(
&crate_rename,
&rust_ty,
&generics,
self.bound.as_deref(),
Expand Down Expand Up @@ -299,6 +306,7 @@ fn generate_assoc_type(

// generate start of the `impl TS for #ty` block, up to (excluding) the open brace
fn generate_impl_block_header(
crate_rename: &TokenStream,
ty: &Ident,
generics: &Generics,
bounds: Option<&[WherePredicate]>,
Expand Down Expand Up @@ -340,7 +348,7 @@ fn generate_impl_block_header(
}
};

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

fn generate_where_clause(generics: &Generics, dependencies: &Dependencies) -> WhereClause {
Expand Down
3 changes: 3 additions & 0 deletions macros/src/types/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub(crate) fn r#enum_def(s: &ItemEnum) -> syn::Result<DerivedTS> {

if s.variants.is_empty() {
return Ok(DerivedTS {
crate_rename: enum_attr.crate_rename,
ts_name: name,
docs: enum_attr.docs,
inline: quote!("never".to_owned()),
Expand All @@ -46,6 +47,7 @@ pub(crate) fn r#enum_def(s: &ItemEnum) -> syn::Result<DerivedTS> {
}

Ok(DerivedTS {
crate_rename: enum_attr.crate_rename,
inline: quote!([#(#formatted_variants),*].join(" | ")),
inline_flattened: Some(quote!(
format!("({})", [#(#formatted_variants),*].join(" | "))
Expand Down Expand Up @@ -199,6 +201,7 @@ fn format_variant(
fn empty_enum(name: impl Into<String>, enum_attr: EnumAttr) -> DerivedTS {
let name = name.into();
DerivedTS {
crate_rename: enum_attr.crate_rename,
inline: quote!("never".to_owned()),
docs: enum_attr.docs,
inline_flattened: None,
Expand Down
3 changes: 2 additions & 1 deletion macros/src/types/named.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use proc_macro2::TokenStream;
use quote::{quote};
use quote::quote;
use syn::{spanned::Spanned, Field, FieldsNamed, GenericArgument, PathArguments, Result, Type};

use crate::{
Expand Down Expand Up @@ -43,6 +43,7 @@ pub(crate) fn named(attr: &StructAttr, name: &str, fields: &FieldsNamed) -> Resu
};

Ok(DerivedTS {
crate_rename: attr.crate_rename.clone(),
// the `replace` combines `{ ... } & { ... }` into just one `{ ... }`. Not necessary, but it
// results in simpler type definitions.
inline: quote!(#inline.replace(" } & { ", " ")),
Expand Down
3 changes: 2 additions & 1 deletion macros/src/types/newtype.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use quote::{quote};
use quote::quote;
use syn::{FieldsUnnamed, Result};

use crate::{
Expand Down Expand Up @@ -59,6 +59,7 @@ pub(crate) fn newtype(attr: &StructAttr, name: &str, fields: &FieldsUnnamed) ->
};

Ok(DerivedTS {
crate_rename: attr.crate_rename.clone(),
inline: inline_def,
inline_flattened: None,
docs: attr.docs.clone(),
Expand Down
3 changes: 2 additions & 1 deletion macros/src/types/tuple.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use proc_macro2::TokenStream;
use quote::{quote};
use quote::quote;
use syn::{Field, FieldsUnnamed, Result};

use crate::{
Expand All @@ -23,6 +23,7 @@ pub(crate) fn tuple(attr: &StructAttr, name: &str, fields: &FieldsUnnamed) -> Re
}

Ok(DerivedTS {
crate_rename: attr.crate_rename.clone(),
inline: quote! {
format!(
"[{}]",
Expand Down
3 changes: 3 additions & 0 deletions macros/src/types/unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub(crate) fn empty_object(attr: &StructAttr, name: &str) -> Result<DerivedTS> {
check_attributes(attr)?;

Ok(DerivedTS {
crate_rename: attr.crate_rename.clone(),
inline: quote!("Record<string, never>".to_owned()),
inline_flattened: None,
docs: attr.docs.clone(),
Expand All @@ -23,6 +24,7 @@ pub(crate) fn empty_array(attr: &StructAttr, name: &str) -> Result<DerivedTS> {
check_attributes(attr)?;

Ok(DerivedTS {
crate_rename: attr.crate_rename.clone(),
inline: quote!("never[]".to_owned()),
inline_flattened: None,
docs: attr.docs.clone(),
Expand All @@ -39,6 +41,7 @@ pub(crate) fn null(attr: &StructAttr, name: &str) -> Result<DerivedTS> {
check_attributes(attr)?;

Ok(DerivedTS {
crate_rename: attr.crate_rename.clone(),
inline: quote!("null".to_owned()),
inline_flattened: None,
docs: attr.docs.clone(),
Expand Down
16 changes: 16 additions & 0 deletions ts-rs/tests/crate_rename.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#![allow(dead_code)]

use ts_rs as reexport;

#[derive(ts_rs::TS)]
#[ts(crate_rename = "reexport")]
struct TestStruct {
hello: String,
world: i32,
}

#[test]
fn reexported_impl_works() {
let ts = <TestStruct as reexport::TS>::decl();
assert_eq!(ts, "type TestStruct = { hello: string, world: number, };");
}
Loading