diff --git a/Cargo.lock b/Cargo.lock index 26976bd..0c8483c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1438,9 +1438,9 @@ dependencies = [ [[package]] name = "serde_tokenstream" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd80de2b23fd8f323001816f6db55b64b87302043519a45548708620ae6c71ef" +checksum = "2794f0ba0179a8ca422c30d9975d86faf8306be0164bfc3b0b1ca4f060ac639d" dependencies = [ "proc-macro2", "serde", @@ -1849,9 +1849,8 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "typify" -version = "0.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e8486352f3c946e69f983558cfc09b295250b01e01b381ec67a05a812d01d63" +version = "0.0.11-dev" +source = "git+https://github.com/oxidecomputer/typify#6f20ad934a8da5aa3a94d25d2ab3cca1e60f53d9" dependencies = [ "typify-impl", "typify-macro", @@ -1859,9 +1858,8 @@ dependencies = [ [[package]] name = "typify-impl" -version = "0.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7624d0b911df6e2bbf34a236f76281f93b294cdde1d4df1dbdb748e5a7fefa5" +version = "0.0.11-dev" +source = "git+https://github.com/oxidecomputer/typify#6f20ad934a8da5aa3a94d25d2ab3cca1e60f53d9" dependencies = [ "heck", "log", @@ -1878,9 +1876,8 @@ dependencies = [ [[package]] name = "typify-macro" -version = "0.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c42802aa033cee7650a4e1509ba7d5848a56f84be7c4b31e4385ee12445e942" +version = "0.0.11-dev" +source = "git+https://github.com/oxidecomputer/typify#6f20ad934a8da5aa3a94d25d2ab3cca1e60f53d9" dependencies = [ "proc-macro2", "quote", diff --git a/progenitor-impl/Cargo.toml b/progenitor-impl/Cargo.toml index 3291687..1ed3c59 100644 --- a/progenitor-impl/Cargo.toml +++ b/progenitor-impl/Cargo.toml @@ -21,8 +21,8 @@ serde_json = "1.0" syn = { version = "1.0", features = ["parsing"] } thiserror = "1.0" # To publish, use a numbered version -typify = "0.0.10" -#typify = { git = "https://github.com/oxidecomputer/typify" } +#typify = "0.0.10" +typify = { git = "https://github.com/oxidecomputer/typify" } unicode-ident = "1.0.5" [dev-dependencies] diff --git a/progenitor-impl/src/lib.rs b/progenitor-impl/src/lib.rs index 10d7f9e..e7e24f5 100644 --- a/progenitor-impl/src/lib.rs +++ b/progenitor-impl/src/lib.rs @@ -1,6 +1,6 @@ // Copyright 2022 Oxide Computer Company -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use openapiv3::OpenAPI; use proc_macro2::TokenStream; @@ -11,6 +11,8 @@ use typify::{TypeSpace, TypeSpaceSettings}; use crate::to_schema::ToSchema; +pub use typify::TypeSpacePatch as TypePatch; + mod method; mod template; mod to_schema; @@ -49,6 +51,7 @@ pub struct GenerationSettings { pre_hook: Option, post_hook: Option, extra_derives: Vec, + patch: HashMap, } #[derive(Clone, Deserialize, PartialEq, Eq)] @@ -109,6 +112,16 @@ impl GenerationSettings { self.extra_derives.push(derive.to_string()); self } + + pub fn with_patch>( + &mut self, + type_name: S, + patch: &TypePatch, + ) -> &mut Self { + self.patch + .insert(type_name.as_ref().to_string(), patch.clone()); + self + } } impl Default for Generator { @@ -133,6 +146,9 @@ impl Generator { settings.extra_derives.iter().for_each(|derive| { let _ = type_settings.with_derive(derive.clone()); }); + settings.patch.iter().for_each(|(type_name, patch)| { + type_settings.with_patch(type_name, patch); + }); Self { type_space: TypeSpace::new(&type_settings), settings: settings.clone(), diff --git a/progenitor-impl/tests/output/nexus-builder.out b/progenitor-impl/tests/output/nexus-builder.out index d601a94..70bb832 100644 --- a/progenitor-impl/tests/output/nexus-builder.out +++ b/progenitor-impl/tests/output/nexus-builder.out @@ -1724,7 +1724,7 @@ pub mod types { ///Names must begin with a lower case ASCII letter, be composed exclusively /// of lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end /// with a '-'. Names cannot be a UUID though they may contain a UUID. - #[derive(Clone, Debug, Serialize, JsonSchema)] + #[derive(Clone, Debug, Serialize, Hash, JsonSchema)] pub struct Name(String); impl std::ops::Deref for Name { type Target = String; diff --git a/progenitor-impl/tests/test_output.rs b/progenitor-impl/tests/test_output.rs index 1a4d798..8bd129a 100644 --- a/progenitor-impl/tests/test_output.rs +++ b/progenitor-impl/tests/test_output.rs @@ -3,7 +3,7 @@ use std::{fs::File, path::PathBuf}; use progenitor_impl::{ - GenerationSettings, Generator, InterfaceStyle, TagStyle, + GenerationSettings, Generator, InterfaceStyle, TagStyle, TypePatch, }; #[track_caller] @@ -25,7 +25,8 @@ fn verify_apis(openapi_file: &str) { GenerationSettings::default() .with_interface(InterfaceStyle::Builder) .with_tag(TagStyle::Merged) - .with_derive("JsonSchema"), + .with_derive("JsonSchema") + .with_patch("Name", TypePatch::default().with_derive("Hash")), ); let output = generator.generate_text_normalize_comments(&spec).unwrap(); expectorate::assert_contents( diff --git a/progenitor-macro/src/lib.rs b/progenitor-macro/src/lib.rs index 7ae3fa1..6693c10 100644 --- a/progenitor-macro/src/lib.rs +++ b/progenitor-macro/src/lib.rs @@ -1,11 +1,11 @@ // Copyright 2022 Oxide Computer Company -use std::path::Path; +use std::{collections::HashMap, path::Path}; use openapiv3::OpenAPI; use proc_macro::TokenStream; use progenitor_impl::{ - GenerationSettings, Generator, InterfaceStyle, TagStyle, + GenerationSettings, Generator, InterfaceStyle, TagStyle, TypePatch, }; use quote::{quote, ToTokens}; use serde::Deserialize; @@ -80,6 +80,29 @@ struct MacroSettings { post_hook: Option>, #[serde(default)] derives: Vec>, + #[serde(default)] + patch: HashMap, MacroPatch>, +} + +#[derive(Deserialize)] +struct MacroPatch { + #[serde(default)] + rename: Option, + #[serde(default)] + derives: Vec>, +} + +impl From for TypePatch { + fn from(a: MacroPatch) -> Self { + let mut s = Self::default(); + a.rename.iter().for_each(|rename| { + s.with_rename(rename); + }); + a.derives.iter().for_each(|derive| { + s.with_derive(derive.to_token_stream().to_string()); + }); + s + } } #[derive(Deserialize)] @@ -129,6 +152,7 @@ fn do_generate_api(item: TokenStream) -> Result { pre_hook, post_hook, derives, + patch, } = serde_tokenstream::from_tokenstream(&item.into())?; let mut settings = GenerationSettings::default(); settings.with_interface(interface); @@ -144,6 +168,12 @@ fn do_generate_api(item: TokenStream) -> Result { derives.into_iter().for_each(|derive| { settings.with_derive(derive.to_token_stream()); }); + patch.into_iter().for_each(|(type_name, patch)| { + settings.with_patch( + type_name.to_token_stream().to_string(), + &patch.into(), + ); + }); (spec.into_inner(), settings) }; diff --git a/progenitor/src/lib.rs b/progenitor/src/lib.rs index d7a7632..0220d75 100644 --- a/progenitor/src/lib.rs +++ b/progenitor/src/lib.rs @@ -16,4 +16,5 @@ pub use progenitor_impl::GenerationSettings; pub use progenitor_impl::Generator; pub use progenitor_impl::InterfaceStyle; pub use progenitor_impl::TagStyle; +pub use progenitor_impl::TypePatch; pub use progenitor_macro::generate_api; diff --git a/progenitor/tests/build_nexus.rs b/progenitor/tests/build_nexus.rs index a612d32..0245323 100644 --- a/progenitor/tests/build_nexus.rs +++ b/progenitor/tests/build_nexus.rs @@ -1,4 +1,4 @@ -// Copyright 2021 Oxide Computer Company +// Copyright 2022 Oxide Computer Company mod positional { use futures::StreamExt; @@ -31,6 +31,11 @@ mod builder_untagged { spec = "../sample_openapi/nexus.json", interface = Builder, tags = Merged, + patch = { + Name = { + derives = [Hash], + } + } ); }