From 27c05443c31bf4ae67ceb0056b17ba304804217a Mon Sep 17 00:00:00 2001 From: Kevin Amado Date: Tue, 2 Apr 2024 15:50:22 -0600 Subject: [PATCH] dedup dependencies --- macros/src/deps.rs | 58 ++++++++++++++----- .../tests/enum_with_repeated_dependencies.rs | 28 +++++++++ 2 files changed, 71 insertions(+), 15 deletions(-) create mode 100644 ts-rs/tests/enum_with_repeated_dependencies.rs diff --git a/macros/src/deps.rs b/macros/src/deps.rs index 67305394..34c8de96 100644 --- a/macros/src/deps.rs +++ b/macros/src/deps.rs @@ -1,54 +1,82 @@ +use std::collections::HashSet; + use proc_macro2::TokenStream; use quote::{quote, ToTokens}; use syn::{Path, Type}; pub struct Dependencies { - dependencies: Vec, crate_rename: Path, + dependencies: HashSet, pub types: Vec, } +#[derive(Hash, Eq, PartialEq)] +enum Dependency { + DependencyTypes { crate_rename: Path, ty: Type }, + Generics { crate_rename: Path, ty: Type }, + Type(Type), +} + impl Dependencies { pub fn new(crate_rename: Path) -> Self { Self { - dependencies: Vec::default(), + dependencies: HashSet::default(), crate_rename, types: Vec::default(), } } + /// Adds all dependencies from the given type pub fn append_from(&mut self, ty: &Type) { - let crate_rename = &self.crate_rename; - self.dependencies - .push(quote![.extend(<#ty as #crate_rename::TS>::dependency_types())]); + self.dependencies.insert(Dependency::DependencyTypes { + crate_rename: self.crate_rename.clone(), + ty: ty.clone(), + }); + self.types.push(ty.clone()); } /// Adds the given type. pub fn push(&mut self, ty: &Type) { - let crate_rename = &self.crate_rename; - self.dependencies.push(quote![.push::<#ty>()]); - self.dependencies.push(quote![ - .extend(<#ty as #crate_rename::TS>::generics()) - ]); + self.dependencies.insert(Dependency::Type(ty.clone())); + self.dependencies.insert(Dependency::Generics { + crate_rename: self.crate_rename.clone(), + ty: ty.clone(), + }); self.types.push(ty.clone()); } pub fn append(&mut self, mut other: Dependencies) { - if !other.dependencies.is_empty() { - self.dependencies.push(quote![.extend(#other)]); + self.dependencies.extend(other.dependencies); + + if !other.types.is_empty() { + self.types.append(&mut other.types); } - self.types.append(&mut other.types); } } impl ToTokens for Dependencies { fn to_tokens(&self, tokens: &mut TokenStream) { let crate_rename = &self.crate_rename; - let lines = &self.dependencies; + let lines = self.dependencies.iter(); + tokens.extend(quote![{ use #crate_rename::typelist::TypeList; ()#(#lines)* - }]) + }]); + } +} + +impl ToTokens for Dependency { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + Dependency::DependencyTypes { crate_rename, ty } => { + quote![.extend(<#ty as #crate_rename::TS>::dependency_types())] + } + Dependency::Generics { crate_rename, ty } => { + quote![.extend(<#ty as #crate_rename::TS>::generics())] + } + Dependency::Type(ty) => quote![.push::<#ty>()], + }); } } diff --git a/ts-rs/tests/enum_with_repeated_dependencies.rs b/ts-rs/tests/enum_with_repeated_dependencies.rs new file mode 100644 index 00000000..08d4b0cb --- /dev/null +++ b/ts-rs/tests/enum_with_repeated_dependencies.rs @@ -0,0 +1,28 @@ +use ts_rs::{ + typelist::{TypeList, TypeVisitor}, + TS, +}; + +#[derive(Debug, ts_rs::TS)] +#[ts(export)] +pub enum EnumWith1Dependency { + V001(String), + V002(String), +} + +struct DependencyCounter(usize); + +impl TypeVisitor for DependencyCounter { + fn visit(&mut self) { + self.0 += 1; + } +} + +#[test] +fn dedup_deps() { + let mut dependency_counter = DependencyCounter(0); + + EnumWith1Dependency::dependency_types().for_each(&mut dependency_counter); + + assert_eq!(dependency_counter.0, 1); +}