Skip to content

Commit

Permalink
Add support for #[serde(rename_all_fields = "...")] attribute (#225)
Browse files Browse the repository at this point in the history
* Add support for #[serde(rename_all_fields = ...)] attribute
* Change VariantAttr constructor
* Document the new attribute
* Update CHANGELOG.md
* Update tests
* Run cargo +nightly fmt
  • Loading branch information
escritorio-gustavo authored Feb 8, 2024
1 parent be74ebb commit dd32308
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- Add `import-esm` cargo feature to import files with a `.js` extension ([#192](https://github.com/Aleph-Alpha/ts-rs/pull/192))
- Implement `#[ts(...)]` equivalents for `#[serde(tag = "...")]`, `#[serde(tag = "...", content = "...")]` and `#[serde(untagged)]` ([#227](https://github.com/Aleph-Alpha/ts-rs/pull/227))
- Support `#[serde(untagged)]` on individual enum variants ((#226)[https://github.com/Aleph-Alpha/ts-rs/pull/226])
- Support for `#[serde(rename_all_fields = "...")]` ([#225](https://github.com/Aleph-Alpha/ts-rs/pull/225))

### Fixes
- `rename_all` with `camelCase` produces wrong names if fields were already in camelCase ([#198](https://github.com/Aleph-Alpha/ts-rs/pull/198))
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ With the `serde-compat` feature (enabled by default), serde attributes can be pa
Supported serde attributes:
- `rename`
- `rename-all`
- `rename-all-fields`
- `tag`
- `content`
- `untagged`
Expand Down
5 changes: 5 additions & 0 deletions macros/src/attr/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{
#[derive(Default)]
pub struct EnumAttr {
pub rename_all: Option<Inflection>,
pub rename_all_fields: Option<Inflection>,
pub rename: Option<String>,
pub export_to: Option<String>,
pub export: bool,
Expand Down Expand Up @@ -53,6 +54,7 @@ impl EnumAttr {
&mut self,
EnumAttr {
rename_all,
rename_all_fields,
rename,
tag,
content,
Expand All @@ -63,6 +65,7 @@ impl EnumAttr {
) {
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);
self.tag = self.tag.take().or(tag);
self.untagged = self.untagged || untagged;
self.content = self.content.take().or(content);
Expand All @@ -75,6 +78,7 @@ impl_parse! {
EnumAttr(input, out) {
"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)?),
"export_to" => out.export_to = Some(parse_assign_str(input)?),
"export" => out.export = true,
"tag" => out.tag = Some(parse_assign_str(input)?),
Expand All @@ -88,6 +92,7 @@ impl_parse! {
SerdeEnumAttr(input, out) {
"rename" => out.0.rename = Some(parse_assign_str(input)?),
"rename_all" => out.0.rename_all = Some(parse_assign_inflection(input)?),
"rename_all_fields" => out.0.rename_all_fields = Some(parse_assign_inflection(input)?),
"tag" => out.0.tag = Some(parse_assign_str(input)?),
"content" => out.0.content = Some(parse_assign_str(input)?),
"untagged" => out.0.untagged = true
Expand Down
4 changes: 3 additions & 1 deletion macros/src/attr/variant.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use syn::{Attribute, Ident, Result};

use super::EnumAttr;
use crate::{
attr::{parse_assign_inflection, parse_assign_str, Inflection},
utils::parse_attrs,
Expand All @@ -19,9 +20,10 @@ pub struct VariantAttr {
pub struct SerdeVariantAttr(VariantAttr);

impl VariantAttr {
pub fn from_attrs(attrs: &[Attribute]) -> Result<Self> {
pub fn new(attrs: &[Attribute], enum_attr: &EnumAttr) -> Result<Self> {
let mut result = Self::default();
parse_attrs(attrs)?.for_each(|a| result.merge(a));
result.rename_all = result.rename_all.or(enum_attr.rename_all_fields);
#[cfg(feature = "serde-compat")]
if !result.skip {
crate::utils::parse_serde_attrs::<SerdeVariantAttr>(attrs)
Expand Down
2 changes: 1 addition & 1 deletion macros/src/types/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ fn format_variant(
variant: &Variant,
generics: &Generics,
) -> syn::Result<()> {
let variant_attr = VariantAttr::from_attrs(&variant.attrs)?;
let variant_attr = VariantAttr::new(&variant.attrs, enum_attr)?;

if variant_attr.skip {
return Ok(());
Expand Down
5 changes: 5 additions & 0 deletions ts-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
//! Supported serde attributes:
//! - `rename`
//! - `rename-all`
//! - `rename-all-fields`
//! - `tag`
//! - `content`
//! - `untagged`
Expand Down Expand Up @@ -254,6 +255,10 @@ pub mod typelist;
/// - `#[ts(rename_all = "..")]`:
/// Rename all variants of this enum.
/// Valid values are `lowercase`, `UPPERCASE`, `camelCase`, `snake_case`, `PascalCase`, `SCREAMING_SNAKE_CASE`, "kebab-case"
///
/// - `#[ts(rename_all_fieds = "..")]`
/// Renames the fields of all the struct variants of this enum.
/// Valid values are `lowercase`, `UPPERCASE`, `camelCase`, `snake_case`, `PascalCase`, `SCREAMING_SNAKE_CASE`, "kebab-case"
///
/// ### enum variant attributes
///
Expand Down
25 changes: 25 additions & 0 deletions ts-rs/tests/enum_struct_rename_all.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,28 @@ pub fn enum_struct_rename_all() {
r#"{ "running": { startedTime: string, } } | { "terminated": { status: number, stdout: string, stderr: string, } }"#
)
}

#[cfg_attr(feature = "serde-compat", derive(Serialize))]
#[derive(TS, Clone)]
#[ts(export)]
#[cfg_attr(feature = "serde-compat", serde(rename_all_fields = "kebab-case"))]
#[cfg_attr(not(feature = "serde-compat"), ts(rename_all_fields = "kebab-case"))]
pub enum TaskStatus2 {
Running {
started_time: String,
},

Terminated {
status: i32,
stdout: String,
stderr: String,
},
}

#[test]
pub fn enum_struct_rename_all_fields() {
assert_eq!(
TaskStatus2::inline(),
r#"{ "Running": { "started-time": string, } } | { "Terminated": { status: number, stdout: string, stderr: string, } }"#
)
}

0 comments on commit dd32308

Please sign in to comment.