Skip to content

Commit 324dffa

Browse files
fix: bad name on shared types (#955)
Since types can be shared, prefixing the name with the first function/path encountered would be confusing for the other types that also refers to it. This patch disables prefixing for types with more than one referrer. #### Migration notes None - [ ] The change comes with new or modified tests - [ ] Hard-to-understand functions have explanatory comments - [ ] End-user documentation is updated to reflect the change <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit Based on the comprehensive summary of changes across multiple files, here are the updated release notes: - **Type System Refinement** - Standardized type naming conventions across multiple languages. - Replaced specific type aliases with more generic scalar types. - Updated function signatures to use simplified type definitions. - **Version Updates** - Incremented metatype version from "0.5.0-rc.8" to "0.5.0-rc.9". - **Upload Functionality** - Modified file upload method return types to return boolean instead of complex output. - Updated argument types for upload-related functions. - **Performance and Naming Improvements** - Enhanced reference counting for type naming processor. - Refined type generation logic with more consistent naming strategies. These changes primarily focus on improving type system consistency and simplifying type definitions across different runtime environments. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 445bb5d commit 324dffa

File tree

20 files changed

+471
-381
lines changed

20 files changed

+471
-381
lines changed

examples/typegraphs/metagen/rs/fdk.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl Router {
109109
}
110110

111111
pub fn init(&self, args: InitArgs) -> Result<InitResponse, InitError> {
112-
static MT_VERSION: &str = "0.5.0-rc.8";
112+
static MT_VERSION: &str = "0.5.0-rc.9";
113113
if args.metatype_version != MT_VERSION {
114114
return Err(InitError::VersionMismatch(MT_VERSION.into()));
115115
}

src/typegate/src/typegraphs/typegate.json

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
},
8484
{
8585
"type": "object",
86-
"title": "root_typegraphs_fn_input",
86+
"title": "struct_542d7",
8787
"properties": {},
8888
"id": [],
8989
"required": []
@@ -109,7 +109,7 @@
109109
},
110110
{
111111
"type": "string",
112-
"title": "Typegraph_name_string"
112+
"title": "string_5d176"
113113
},
114114
{
115115
"type": "string",
@@ -198,7 +198,7 @@
198198
},
199199
{
200200
"type": "string",
201-
"title": "root_addTypegraph_fn_input_fromString_string_json",
201+
"title": "string_json_df54e",
202202
"format": "json"
203203
},
204204
{
@@ -268,7 +268,7 @@
268268
},
269269
{
270270
"type": "optional",
271-
"title": "root_addTypegraph_fn_output_failure_root_addTypegraph_fn_input_fromString_string_json_optional",
271+
"title": "root_addTypegraph_fn_output_failure_string_json_df54e_optional",
272272
"item": 14,
273273
"default_value": null
274274
},
@@ -296,12 +296,12 @@
296296
},
297297
{
298298
"type": "list",
299-
"title": "root_removeTypegraphs_fn_input_names_Typegraph_name_string_list",
299+
"title": "string_5d176_list_691ee",
300300
"items": 5
301301
},
302302
{
303303
"type": "boolean",
304-
"title": "root_removeTypegraphs_fn_output"
304+
"title": "boolean_a56cd"
305305
},
306306
{
307307
"type": "function",
@@ -333,7 +333,7 @@
333333
},
334334
{
335335
"type": "list",
336-
"title": "root_argInfoByPath_fn_input_argPaths_root_removeTypegraphs_fn_input_names_Typegraph_name_string_list_list",
336+
"title": "root_argInfoByPath_fn_input_argPaths_string_5d176_list_691ee_list",
337337
"items": 24
338338
},
339339
{
@@ -369,18 +369,18 @@
369369
},
370370
{
371371
"type": "optional",
372-
"title": "TypeInfo_enum_TypeInfo_enum_root_addTypegraph_fn_input_fromString_string_json_list_optional",
372+
"title": "TypeInfo_enum_TypeInfo_enum_string_json_df54e_list_optional",
373373
"item": 32,
374374
"default_value": null
375375
},
376376
{
377377
"type": "list",
378-
"title": "TypeInfo_enum_root_addTypegraph_fn_input_fromString_string_json_list",
378+
"title": "TypeInfo_enum_string_json_df54e_list",
379379
"items": 14
380380
},
381381
{
382382
"type": "optional",
383-
"title": "TypeInfo_format_Typegraph_name_string_optional",
383+
"title": "TypeInfo_format_string_5d176_optional",
384384
"item": 5,
385385
"default_value": null
386386
},
@@ -440,7 +440,7 @@
440440
},
441441
{
442442
"type": "object",
443-
"title": "root_findAvailableOperations_fn_input",
443+
"title": "struct_8f8a3",
444444
"properties": {
445445
"typegraph": 5
446446
},
@@ -596,7 +596,7 @@
596596
},
597597
{
598598
"type": "object",
599-
"title": "root_execRawPrismaRead_fn_input",
599+
"title": "struct_5fa3d",
600600
"properties": {
601601
"typegraph": 5,
602602
"runtime": 5,
@@ -777,7 +777,7 @@
777777
},
778778
{
779779
"type": "integer",
780-
"title": "root_queryPrismaModel_fn_input_offset_integer"
780+
"title": "integer_e116e"
781781
},
782782
{
783783
"type": "object",

src/typegraph/core/src/snapshots/typegraph_core__tests__successful_serialization.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ expression: typegraph.0
4747
},
4848
{
4949
"type": "integer",
50-
"title": "root_one_fn_input_two_integer",
50+
"title": "integer_f0e37",
5151
"minimum": 12,
5252
"maximum": 44
5353
},

src/typegraph/core/src/utils/postprocess/naming.rs

Lines changed: 133 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use common::typegraph::{
1010
visitor::{Edge, PathSegment},
1111
StringFormat, TypeNode, Typegraph,
1212
};
13+
use indexmap::IndexSet;
14+
use sha2::{Digest, Sha256};
1315

1416
use crate::errors::TgError;
1517

@@ -25,17 +27,27 @@ impl super::PostProcessor for NamingProcessor {
2527
tg,
2628
user_named: self.user_named,
2729
};
28-
let mut acc = VisitCollector {
29-
named_types: Default::default(),
30-
path: vec![],
31-
};
3230

3331
let TypeNode::Object {
3432
data: root_data, ..
3533
} = &tg.types[0]
3634
else {
3735
panic!("first item must be root object")
3836
};
37+
38+
let mut ref_counters = TypeRefCount {
39+
counts: Default::default(),
40+
};
41+
for (_, &ty_id) in &root_data.properties {
42+
collect_ref_info(&cx, &mut ref_counters, ty_id, &mut HashSet::new())?;
43+
}
44+
45+
let mut acc = VisitCollector {
46+
named_types: Default::default(),
47+
path: vec![],
48+
// ref related
49+
counts: ref_counters.counts,
50+
};
3951
for (key, &ty_id) in &root_data.properties {
4052
acc.path.push((
4153
PathSegment {
@@ -62,6 +74,41 @@ struct VisitContext<'a> {
6274
struct VisitCollector {
6375
named_types: HashMap<u32, Rc<str>>,
6476
path: Vec<(PathSegment, Rc<str>)>,
77+
// ref related
78+
counts: HashMap<u32, IndexSet<u32>>,
79+
}
80+
81+
struct TypeRefCount {
82+
pub counts: HashMap<u32, IndexSet<u32>>,
83+
}
84+
85+
impl TypeRefCount {
86+
pub fn new_hit(&mut self, id: u32, referrer: u32) {
87+
self.counts
88+
.entry(id)
89+
.and_modify(|counter| {
90+
counter.insert(referrer);
91+
})
92+
.or_insert(IndexSet::from([referrer]));
93+
}
94+
}
95+
96+
impl VisitCollector {
97+
pub fn has_more_than_one_referrer(&self, id: u32) -> bool {
98+
if let Some(referrers) = self.counts.get(&id) {
99+
return referrers.len() > 1;
100+
}
101+
102+
false
103+
}
104+
105+
pub fn next_name(&mut self, name: String, hash_input: String) -> String {
106+
let mut sha256 = Sha256::new();
107+
sha256.update(hash_input.bytes().collect::<Vec<_>>());
108+
let hash = format!("{:x}", sha256.finalize());
109+
110+
format!("{name}_{}", hash.chars().take(5).collect::<String>())
111+
}
65112
}
66113

67114
fn visit_type(cx: &VisitContext, acc: &mut VisitCollector, id: u32) -> anyhow::Result<Rc<str>> {
@@ -215,14 +262,89 @@ fn visit_type(cx: &VisitContext, acc: &mut VisitCollector, id: u32) -> anyhow::R
215262
};
216263

217264
acc.named_types.insert(id, name.clone());
265+
218266
Ok(name)
219267
}
220268

269+
fn collect_ref_info(
270+
cx: &VisitContext,
271+
acc: &mut TypeRefCount,
272+
id: u32,
273+
visited: &mut HashSet<u32>,
274+
) -> anyhow::Result<()> {
275+
if cx.user_named.contains(&id) || visited.contains(&id) {
276+
return Ok(());
277+
}
278+
279+
visited.insert(id);
280+
281+
let node = &cx.tg.types[id as usize];
282+
match node {
283+
TypeNode::Boolean { .. }
284+
| TypeNode::Float { .. }
285+
| TypeNode::Integer { .. }
286+
| TypeNode::String { .. }
287+
| TypeNode::File { .. }
288+
| TypeNode::Any { .. } => {
289+
// base case
290+
}
291+
TypeNode::Optional { data, .. } => {
292+
acc.new_hit(data.item, id);
293+
collect_ref_info(cx, acc, data.item, visited)?;
294+
}
295+
TypeNode::Object { data, .. } => {
296+
for (_, key_id) in &data.properties {
297+
acc.new_hit(*key_id, id);
298+
collect_ref_info(cx, acc, *key_id, visited)?;
299+
}
300+
}
301+
TypeNode::Function { data, .. } => {
302+
acc.new_hit(data.input, id);
303+
acc.new_hit(data.output, id);
304+
305+
collect_ref_info(cx, acc, data.input, visited)?;
306+
collect_ref_info(cx, acc, data.output, visited)?;
307+
}
308+
TypeNode::List { data, .. } => {
309+
acc.new_hit(data.items, id);
310+
collect_ref_info(cx, acc, data.items, visited)?;
311+
}
312+
TypeNode::Union { data, .. } => {
313+
for variant in &data.any_of {
314+
acc.new_hit(*variant, id);
315+
collect_ref_info(cx, acc, *variant, visited)?;
316+
}
317+
}
318+
TypeNode::Either { data, .. } => {
319+
for variant in &data.one_of {
320+
acc.new_hit(*variant, id);
321+
collect_ref_info(cx, acc, *variant, visited)?;
322+
}
323+
}
324+
};
325+
326+
visited.remove(&id);
327+
328+
Ok(())
329+
}
330+
221331
fn gen_name(cx: &VisitContext, acc: &mut VisitCollector, id: u32, ty_name: &str) -> Rc<str> {
332+
let node = &cx.tg.types[id as usize];
222333
let name: Rc<str> = if cx.user_named.contains(&id) {
223-
let node = &cx.tg.types[id as usize];
224334
node.base().title.clone().into()
225335
} else {
336+
macro_rules! join_if_ok {
337+
($prefix:expr, $default:expr) => {
338+
if acc.has_more_than_one_referrer(id) {
339+
// Cannot be opinionated on the prefix path if shared (confusing)
340+
let hash_input = $prefix;
341+
acc.next_name(ty_name.to_string(), hash_input)
342+
} else {
343+
format!("{}_{}", $prefix, $default)
344+
}
345+
};
346+
}
347+
226348
let title;
227349
let mut last = acc.path.len();
228350
loop {
@@ -232,11 +354,13 @@ fn gen_name(cx: &VisitContext, acc: &mut VisitCollector, id: u32, ty_name: &str)
232354
// we don't include optional and list nodes in
233355
// generated names (useless but also, they might be placeholders)
234356
Edge::OptionalItem | Edge::ArrayItem => continue,
235-
Edge::FunctionInput => format!("{last_name}_input"),
236-
Edge::FunctionOutput => format!("{last_name}_output"),
237-
Edge::ObjectProp(key) => format!("{last_name}_{key}_{ty_name}"),
357+
Edge::FunctionInput => join_if_ok!(last_name.to_string(), "input"),
358+
Edge::FunctionOutput => join_if_ok!(last_name.to_string(), "output"),
359+
Edge::ObjectProp(key) => {
360+
join_if_ok!(format!("{last_name}_{key}"), ty_name)
361+
}
238362
Edge::EitherVariant(idx) | Edge::UnionVariant(idx) => {
239-
format!("{last_name}_t{idx}_{ty_name}")
363+
join_if_ok!(format!("{last_name}_t{idx}"), ty_name)
240364
}
241365
};
242366
break;

0 commit comments

Comments
 (0)