Skip to content

Commit

Permalink
dedup dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
kamadorueda committed Apr 2, 2024
1 parent 22d03fc commit 27c0544
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 15 deletions.
58 changes: 43 additions & 15 deletions macros/src/deps.rs
Original file line number Diff line number Diff line change
@@ -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<TokenStream>,
crate_rename: Path,
dependencies: HashSet<Dependency>,
pub types: Vec<Type>,
}

#[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>()],
});
}
}
28 changes: 28 additions & 0 deletions ts-rs/tests/enum_with_repeated_dependencies.rs
Original file line number Diff line number Diff line change
@@ -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<T: TS + 'static + ?Sized>(&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);
}

0 comments on commit 27c0544

Please sign in to comment.