Skip to content

Commit a5ee896

Browse files
committed
use inferred union variant names in more places
1 parent 27d15d9 commit a5ee896

File tree

8 files changed

+8069
-8005
lines changed

8 files changed

+8069
-8005
lines changed

typify-impl/src/enums.rs

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright 2025 Oxide Computer Company
22

3-
use std::collections::{BTreeMap, BTreeSet, HashSet};
3+
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
44

55
use heck::{ToKebabCase, ToPascalCase};
66
use proc_macro2::TokenStream;
@@ -609,33 +609,52 @@ impl TypeSpace {
609609
// account for types such as Uuid whose names come from outside of
610610
// the schema... but you can't win them all.
611611
.map(schema_is_named)
612-
.collect::<Option<Vec<_>>>()
613-
// Prune the common prefixes from all variant names. If this
614-
// results in any of them being empty, we don't use these names.
615-
.and_then(|variant_names| {
616-
let common_prefix = variant_names
617-
.iter()
618-
.cloned()
619-
.reduce(|a, b| get_common_prefix(&a, &b))
620-
.unwrap();
621-
variant_names
622-
.into_iter()
623-
.map(|var_name| {
624-
let var_name = &var_name[common_prefix.len()..];
625-
if var_name.is_empty() {
626-
None
627-
} else {
628-
Some(var_name.to_string())
629-
}
630-
})
631-
.collect::<Option<Vec<_>>>()
612+
.collect::<Vec<_>>();
613+
614+
let common_prefix = variant_names
615+
.iter()
616+
.cloned()
617+
.flatten()
618+
.reduce(|a, b| get_common_prefix(&a, &b))
619+
.unwrap_or_else(String::new);
620+
621+
// Store seen, un-stripped names here. Any item for which their
622+
// name appears more than once, ALL the items with that clashing
623+
// name will be converted to the `VariantN` scheme.
624+
let duplicate_names = variant_names
625+
.iter()
626+
.cloned()
627+
.flatten()
628+
.fold(HashMap::new(), |mut counter: HashMap<_, u8>, name| {
629+
*counter.entry(name).or_default() += 1;
630+
counter
632631
})
633-
// Fall back to `VariantN` naming.
634-
.unwrap_or_else(|| {
635-
(0..subschemas.len())
636-
.map(|idx| format!("Variant{}", idx))
637-
.collect()
638-
});
632+
.into_iter()
633+
.filter_map(|(name, count)| if count > 1 { Some(name) } else { None })
634+
.collect::<HashSet<_>>();
635+
636+
// Prune the common prefixes from all variant names. If this
637+
// results in any of them being empty, we don't use these names.
638+
//
639+
// Fall back to VariantN if the variant name cannot be derived from
640+
// the schema.
641+
let variant_names = variant_names
642+
.into_iter()
643+
.enumerate()
644+
.map(|(idx, var_name)| {
645+
match var_name {
646+
None => None,
647+
var_name => {
648+
var_name.filter(|var_name| !duplicate_names.contains(var_name.as_str()))
649+
}
650+
}
651+
.map(|var_name| var_name[common_prefix.len()..].to_string())
652+
.filter(|var_name| !var_name.is_empty())
653+
.map(|var_name| var_name.to_string())
654+
// Fall back to `VariantN` naming.
655+
.unwrap_or_else(|| format!("Variant{}", idx))
656+
})
657+
.collect::<Vec<_>>();
639658

640659
// Gather the variant details along with its name.
641660
let variant_details = subschemas

typify-impl/src/util.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,20 @@ pub(crate) fn schema_is_named(schema: &Schema) -> Option<String> {
622622
extensions: _,
623623
}) => singleton_subschema(subschemas).and_then(schema_is_named),
624624

625+
// Best-effort fallback for things with raw types that can be easily inferred
626+
Schema::Object(SchemaObject {
627+
instance_type: Some(SingleOrVec::Single(single)),
628+
..
629+
}) => match **single {
630+
InstanceType::Boolean => Some("Boolean".to_string()),
631+
InstanceType::Integer => Some("Integer".to_string()),
632+
InstanceType::Number => Some("Number".to_string()),
633+
InstanceType::String => Some("String".to_string()),
634+
InstanceType::Array => Some("Array".to_string()),
635+
InstanceType::Object => Some("Object".to_string()),
636+
InstanceType::Null => Some("Null".to_string()),
637+
},
638+
625639
_ => None,
626640
}?;
627641

typify-impl/src/value.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,7 +1089,7 @@ mod tests {
10891089
.map(|x| x.to_string()),
10901090
Some(
10911091
quote! {
1092-
super::Test::Variant0
1092+
super::Test::Null
10931093
}
10941094
.to_string()
10951095
)
@@ -1100,7 +1100,7 @@ mod tests {
11001100
.map(|x| x.to_string()),
11011101
Some(
11021102
quote! {
1103-
super::Test::Variant1("xx".to_string(), "yy".to_string())
1103+
super::Test::Array("xx".to_string(), "yy".to_string())
11041104
}
11051105
.to_string()
11061106
)
@@ -1117,7 +1117,7 @@ mod tests {
11171117
.map(|x| x.to_string()),
11181118
Some(
11191119
quote! {
1120-
super::Test::Variant2 {
1120+
super::Test::Object {
11211121
cc: "xx".to_string(),
11221122
dd: "yy".to_string()
11231123
}
@@ -1147,7 +1147,7 @@ mod tests {
11471147
.map(|x| x.to_string()),
11481148
Some(
11491149
quote! {
1150-
Test::Variant0
1150+
Test::Null
11511151
}
11521152
.to_string()
11531153
)
@@ -1158,7 +1158,7 @@ mod tests {
11581158
.map(|x| x.to_string()),
11591159
Some(
11601160
quote! {
1161-
Test::Variant1("xx".to_string(), "yy".to_string())
1161+
Test::Array("xx".to_string(), "yy".to_string())
11621162
}
11631163
.to_string()
11641164
)
@@ -1175,7 +1175,7 @@ mod tests {
11751175
.map(|x| x.to_string()),
11761176
Some(
11771177
quote! {
1178-
Test::Variant2 {
1178+
Test::Object {
11791179
cc: "xx".to_string(),
11801180
dd: "yy".to_string()
11811181
}

0 commit comments

Comments
 (0)