@@ -162,6 +162,43 @@ func parseMetadataComments(path string) (*Meta, error) {
162162 // build param-name → type alias map
163163 aliasMap := buildAliasMap (allParams )
164164
165+ seen := map [fieldKey ]struct {}{}
166+ addField := func (parent , name , typ , desc string ) {
167+ if parent == "" || name == "" {
168+ return
169+ }
170+ if real , ok := aliasMap [parent ]; ok {
171+ parent = real
172+ }
173+ k := fieldKey {parent : parent , name : name }
174+ if _ , dup := seen [k ]; dup {
175+ return
176+ }
177+ typeFields [parent ] = append (typeFields [parent ], FieldMeta {
178+ ParentTypeName : parent ,
179+ Name : name ,
180+ Type : typ ,
181+ Description : desc ,
182+ })
183+ seen [k ] = struct {}{}
184+ }
185+
186+ // collect from raw lines
187+ for _ , line := range lines {
188+ if m := fieldRe .FindStringSubmatch (strings .TrimSpace (line )); m != nil {
189+ qual := m [1 ]
190+ typ := m [2 ]
191+ desc := m [3 ]
192+
193+ rootType , field := qual , ""
194+ if strings .Contains (qual , "." ) {
195+ parts := strings .SplitN (qual , "." , 2 )
196+ rootType , field = parts [0 ], parts [1 ]
197+ }
198+ addField (rootType , field , typ , desc )
199+ }
200+ }
201+
165202 // ───────────── second pass: traverse YAML & @field ─────────────
166203 var walk func (node * yaml.Node , path []string )
167204 walk = func (node * yaml.Node , path []string ) {
@@ -406,9 +443,22 @@ func normalizeType(t string) string {
406443 t = t [:idx ]
407444 }
408445
409- // if underlying base is primitive, preserve it verbatim
446+ // normalize emptyobject for display
447+ if t == aliasEmptyObject {
448+ return "object"
449+ }
450+ if t == "*" + aliasEmptyObject {
451+ return "*object"
452+ }
453+
454+ // if underlying base is primitive, preserve it verbatim (after emptyobject normalization above)
410455 base := deriveTypeName (t )
411456 if isPrimitive (base ) {
457+ // show emptyobject as object in composite forms too
458+ if base == aliasEmptyObject {
459+ // handle map/array already below; for bare it's handled above
460+ return strings .ReplaceAll (t , aliasEmptyObject , "object" )
461+ }
412462 return t
413463 }
414464
@@ -418,11 +468,19 @@ func normalizeType(t string) string {
418468 if ! isPrimitive (base ) {
419469 return "[]object"
420470 }
471+ // []emptyobject -> []object
472+ if base == aliasEmptyObject {
473+ return "[]object"
474+ }
421475 return "[]" + base
422476 }
423477
424478 // Handle map types
425479 if strings .HasPrefix (t , "map[" ) {
480+ // map[string]emptyobject -> map[string]object
481+ if deriveTypeName (t ) == aliasEmptyObject {
482+ return "map[string]object"
483+ }
426484 return "map[string]object"
427485 }
428486
@@ -431,13 +489,13 @@ func normalizeType(t string) string {
431489 if ! isPrimitive (base ) && ! strings .HasPrefix (base , "[]" ) && ! strings .HasPrefix (base , "map[" ) {
432490 return "*object"
433491 }
492+ // *emptyobject already handled above
434493 return t
435494 }
436495
437496 if ! isPrimitive (t ) && ! strings .HasPrefix (t , "[]" ) && ! strings .HasPrefix (t , "map[" ) {
438497 return "object"
439498 }
440-
441499 return t
442500}
443501
@@ -485,6 +543,11 @@ func valueString(raw interface{}, exists bool, t string) string {
485543 }
486544}
487545
546+ type fieldKey struct {
547+ parent string
548+ name string
549+ }
550+
488551func isPrimitive (t string ) bool {
489552 base := strings .TrimPrefix (t , "*" )
490553 if isStringFormat (base ) {
@@ -493,7 +556,7 @@ func isPrimitive(t string) bool {
493556 switch base {
494557 case "string" , "bool" , "int" , "int32" , "int64" ,
495558 "float32" , "float64" ,
496- aliasQuantity , aliasDuration , aliasTime , aliasObject :
559+ aliasQuantity , aliasDuration , aliasTime , aliasObject , aliasEmptyObject :
497560 return true
498561 default :
499562 return false
0 commit comments