Skip to content

Commit f06081d

Browse files
committed
Fix refactor
1 parent 0e44da0 commit f06081d

1 file changed

Lines changed: 45 additions & 42 deletions

File tree

crates/vespera_macro/src/schema_macro/circular.rs

Lines changed: 45 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,27 @@ pub fn detect_circular_fields(
2424
source_module_path: &[String],
2525
related_schema_def: &str,
2626
) -> Vec<String> {
27-
let mut circular_fields = Vec::new();
28-
2927
// Parse the related schema definition
3028
let Ok(parsed) = syn::parse_str::<syn::ItemStruct>(related_schema_def) else {
31-
return circular_fields;
29+
return Vec::new();
3230
};
3331

3432
// Get the source module name (e.g., "memo" from ["crate", "models", "memo"])
3533
let source_module = source_module_path.last().map(|s| s.as_str()).unwrap_or("");
3634

37-
if let syn::Fields::Named(fields_named) = &parsed.fields {
38-
for field in &fields_named.named {
39-
let Some(field_ident) = &field.ident else {
40-
continue;
41-
};
35+
let syn::Fields::Named(fields_named) = &parsed.fields else {
36+
return Vec::new();
37+
};
38+
39+
fields_named
40+
.named
41+
.iter()
42+
.filter_map(|field| {
43+
let field_ident = field.ident.as_ref()?;
4244
let field_name = field_ident.to_string();
4345

4446
// Check if this field's type references the source schema
45-
let field_ty = &field.ty;
46-
let ty_str = quote!(#field_ty).to_string();
47+
let ty_str = quote!(#field.ty).to_string();
4748

4849
// Normalize whitespace: quote!() produces "foo :: bar" instead of "foo::bar"
4950
// Remove all whitespace to make pattern matching reliable
@@ -52,7 +53,7 @@ pub fn detect_circular_fields(
5253
// SKIP HasMany relations - they are excluded by default from schemas,
5354
// so they don't create actual circular references in the output
5455
if ty_str_normalized.contains("HasMany<") {
55-
continue;
56+
return None;
5657
}
5758

5859
// Check for BelongsTo/HasOne patterns that reference the source:
@@ -68,13 +69,9 @@ pub fn detect_circular_fields(
6869
|| ty_str_normalized
6970
.contains(&format!("{}Schema", capitalize_first(source_module))));
7071

71-
if is_circular {
72-
circular_fields.push(field_name);
73-
}
74-
}
75-
}
76-
77-
circular_fields
72+
is_circular.then_some(field_name)
73+
})
74+
.collect()
7875
}
7976

8077
/// Check if a Model has any BelongsTo or HasOne relations (FK-based relations).
@@ -112,32 +109,38 @@ pub fn is_circular_relation_required(related_model_def: &str, circular_field_nam
112109
return false;
113110
};
114111

115-
if let syn::Fields::Named(fields_named) = &parsed.fields {
116-
for field in &fields_named.named {
117-
let Some(field_ident) = &field.ident else {
118-
continue;
119-
};
120-
if *field_ident != circular_field_name {
121-
continue;
122-
}
112+
let syn::Fields::Named(fields_named) = &parsed.fields else {
113+
return false;
114+
};
123115

124-
// Check if this is a HasOne/BelongsTo with required FK
125-
let ty_str = quote!(#field.ty).to_string().replace(' ', "");
126-
if ty_str.contains("HasOne<") || ty_str.contains("BelongsTo<") {
127-
// Check FK field optionality
128-
let fk_field = extract_belongs_to_from_field(&field.attrs);
129-
if let Some(fk) = fk_field {
130-
// Find FK field and check if it's Option
131-
for f in &fields_named.named {
132-
if f.ident.as_ref().map(|i| i.to_string()) == Some(fk.clone()) {
133-
return !is_option_type(&f.ty);
134-
}
135-
}
136-
}
137-
}
138-
}
116+
// Find the circular field by name
117+
let Some(field) = fields_named.named.iter().find(|f| {
118+
f.ident
119+
.as_ref()
120+
.map(|i| i == circular_field_name)
121+
.unwrap_or(false)
122+
}) else {
123+
return false;
124+
};
125+
126+
// Check if this is a HasOne/BelongsTo with required FK
127+
let ty_str = quote!(#field.ty).to_string().replace(' ', "");
128+
if !ty_str.contains("HasOne<") && !ty_str.contains("BelongsTo<") {
129+
return false;
139130
}
140-
false
131+
132+
// Check FK field optionality
133+
let Some(fk) = extract_belongs_to_from_field(&field.attrs) else {
134+
return false;
135+
};
136+
137+
// Find FK field and check if it's Option
138+
fields_named
139+
.named
140+
.iter()
141+
.find(|f| f.ident.as_ref().map(|i| i.to_string()) == Some(fk.clone()))
142+
.map(|f| !is_option_type(&f.ty))
143+
.unwrap_or(false)
141144
}
142145

143146
/// Generate a default value for a SeaORM relation field in inline construction.

0 commit comments

Comments
 (0)