diff --git a/.changepacks/changepack_log_ikN3nuiD4ptMqueTJBAjI.json b/.changepacks/changepack_log_ikN3nuiD4ptMqueTJBAjI.json new file mode 100644 index 0000000..38b69ff --- /dev/null +++ b/.changepacks/changepack_log_ikN3nuiD4ptMqueTJBAjI.json @@ -0,0 +1 @@ +{"changes":{"Cargo.toml":"Patch"},"note":"Fix description issue","date":"2026-04-07T09:36:28.999142800Z"} \ No newline at end of file diff --git a/crates/vespera_macro/src/parser/schema/serde_attrs.rs b/crates/vespera_macro/src/parser/schema/serde_attrs.rs index d254d9b..3750bb7 100644 --- a/crates/vespera_macro/src/parser/schema/serde_attrs.rs +++ b/crates/vespera_macro/src/parser/schema/serde_attrs.rs @@ -17,13 +17,14 @@ pub fn extract_doc_comment(attrs: &[syn::Attribute]) -> Option { }) = &meta_nv.value { let line = lit_str.value(); - // Trim leading space that rustdoc adds. - // Also handle `" / "` prefix that can appear when doc-comment - // markers leak through TokenStream → string → parse roundtrips. + // Strip `" / "` or `"/ "` prefixes that can appear when doc-comment + // markers leak through TokenStream → string → parse roundtrips, + // then trim any remaining whitespace. let trimmed = line .strip_prefix(" / ") - .or_else(|| line.strip_prefix(' ')) - .unwrap_or(&line); + .or_else(|| line.strip_prefix("/ ")) + .unwrap_or(&line) + .trim(); doc_lines.push(trimmed.to_string()); } } diff --git a/crates/vespera_macro/src/parser/schema/struct_schema.rs b/crates/vespera_macro/src/parser/schema/struct_schema.rs index 2bee2c6..bb34eab 100644 --- a/crates/vespera_macro/src/parser/schema/struct_schema.rs +++ b/crates/vespera_macro/src/parser/schema/struct_schema.rs @@ -349,6 +349,31 @@ mod tests { } } + #[test] + fn test_parse_struct_to_schema_description_strips_slash_prefix() { + // When doc attributes have "/ " prefix (without leading space), descriptions should be clean. + // This can happen in certain TokenStream roundtrip scenarios. + let struct_item: syn::ItemStruct = syn::parse_str( + r#" + #[doc = "/ Struct description"] + struct Admin { + #[doc = "/ Field description"] + id: i32, + } + "#, + ) + .unwrap(); + let schema = parse_struct_to_schema(&struct_item, &HashSet::new(), &HashMap::new()); + assert_eq!( + schema.description, + Some("Struct description".to_string()) + ); + let props = schema.properties.unwrap(); + if let SchemaRef::Inline(id_schema) = props.get("id").unwrap() { + assert_eq!(id_schema.description, Some("Field description".to_string())); + } + } + #[test] fn test_parse_struct_to_schema_with_flatten() { let struct_item: syn::ItemStruct = syn::parse_str( diff --git a/crates/vespera_macro/src/route/utils.rs b/crates/vespera_macro/src/route/utils.rs index 06bb8b4..da2c736 100644 --- a/crates/vespera_macro/src/route/utils.rs +++ b/crates/vespera_macro/src/route/utils.rs @@ -14,13 +14,14 @@ pub fn extract_doc_comment(attrs: &[syn::Attribute]) -> Option { }) = &meta_nv.value { let line = lit_str.value(); - // Trim leading space that rustdoc adds. - // Also handle `" / "` prefix that can appear when doc-comment - // markers leak through TokenStream → string → parse roundtrips. + // Strip `" / "` or `"/ "` prefixes that can appear when doc-comment + // markers leak through TokenStream → string → parse roundtrips, + // then trim any remaining whitespace. let trimmed = line .strip_prefix(" / ") - .or_else(|| line.strip_prefix(' ')) - .unwrap_or(&line); + .or_else(|| line.strip_prefix("/ ")) + .unwrap_or(&line) + .trim(); doc_lines.push(trimmed.to_string()); } }