@@ -352,7 +352,7 @@ func fullTypeName(pkgName, typeName string) string {
352
352
return typeName
353
353
}
354
354
355
- func (parser * Parser ) getTypeSchema (typeName string , file * ast.File , field * ast.Field ) (* TypeSchema , error ) {
355
+ func (parser * Parser ) getTypeSchema (typeName string , file * ast.File , field * ast.Field , parentSchema * TypeSchema ) (* TypeSchema , error ) {
356
356
if IsGolangPrimitiveType (typeName ) {
357
357
name := field .Names [0 ].Name
358
358
isOmitempty , fieldName := getFieldName (name , field , "json" )
@@ -367,6 +367,7 @@ func (parser *Parser) getTypeSchema(typeName string, file *ast.File, field *ast.
367
367
Validate : getValidateTagValue (field ),
368
368
Tags : getParameterTags (field ),
369
369
Required : getRequiredTagValue (field ),
370
+ Parent : parentSchema ,
370
371
}, nil
371
372
}
372
373
@@ -376,7 +377,7 @@ func (parser *Parser) getTypeSchema(typeName string, file *ast.File, field *ast.
376
377
}
377
378
fmt .Println ("typeSpecDef" , typeSpecDef .Name ())
378
379
379
- schema , err := parser .ParseDefinition (typeSpecDef , field )
380
+ schema , err := parser .ParseDefinition (typeSpecDef , field , parentSchema )
380
381
if err != nil {
381
382
return nil , err
382
383
}
@@ -407,22 +408,21 @@ func (parser *Parser) clearStructStack() {
407
408
408
409
// ParseDefinition parses given type spec that corresponds to the type under
409
410
// given name and package
410
- func (parser * Parser ) ParseDefinition (typeSpecDef * TypeSpecDef , field * ast.Field ) (* TypeSchema , error ) {
411
+ func (parser * Parser ) ParseDefinition (typeSpecDef * TypeSpecDef , field * ast.Field , parentSchema * TypeSchema ) (* TypeSchema , error ) {
411
412
typeName := typeSpecDef .FullName ()
412
413
refTypeName := TypeDocName (typeName , typeSpecDef .TypeSpec )
413
414
414
- if parser . isInStructStack (typeSpecDef ) {
415
- fmt .Printf ("Skipping '%s', recursion detected." , typeName )
416
- schema := & TypeSchema {
415
+ if parentSchema != nil && parentSchema . isInTypeChain (typeSpecDef ) {
416
+ fmt .Printf ("Skipping '%s', recursion detected.\n " , typeName )
417
+ return & TypeSchema {
417
418
Name : refTypeName ,
418
419
FieldName : refTypeName ,
419
420
FullName : typeName ,
420
421
Type : OBJECT ,
421
422
Example : NULL ,
422
423
PkgPath : typeSpecDef .PkgPath ,
423
- }
424
- parser .clearStructStack ()
425
- return schema , nil
424
+ Parent : parentSchema ,
425
+ }, nil
426
426
}
427
427
428
428
parser .structStack = append (parser .structStack , typeSpecDef )
@@ -434,35 +434,36 @@ func (parser *Parser) ParseDefinition(typeSpecDef *TypeSpecDef, field *ast.Field
434
434
switch expr := typeSpecDef .TypeSpec .Type .(type ) {
435
435
// type Foo struct {...}
436
436
case * ast.StructType :
437
- schema , err := parser .parseStruct (typeSpecDef .File , expr .Fields )
437
+ schema , err := parser .parseStruct (typeSpecDef , typeSpecDef .File , expr .Fields , parentSchema )
438
438
if err != nil {
439
439
return nil , err
440
440
}
441
441
schema .Name = typeSpecDef .Name ()
442
442
schema .FullName = typeSpecDef .FullName ()
443
443
return schema , err
444
444
case * ast.Ident :
445
- return parser .getTypeSchema (expr .Name , typeSpecDef .File , field )
445
+ return parser .getTypeSchema (expr .Name , typeSpecDef .File , field , parentSchema )
446
446
case * ast.MapType :
447
447
if keyIdent , ok := expr .Key .(* ast.Ident ); ok {
448
448
if IsGolangPrimitiveType (keyIdent .Name ) {
449
449
example := getFieldExample (keyIdent .Name , nil )
450
450
if _ , ok := expr .Value .(* ast.InterfaceType ); ok {
451
451
return & TypeSchema {Type : OBJECT , Properties : nil }, nil
452
452
}
453
- schema , err := parser .parseTypeExpr (typeSpecDef .File , field , expr .Value )
453
+ arrSchama := & TypeSchema {
454
+ Name : example ,
455
+ Type : OBJECT ,
456
+ FieldName : example ,
457
+ Parent : parentSchema ,
458
+ Properties : map [string ]* TypeSchema {},
459
+ }
460
+ schema , err := parser .parseTypeExpr (typeSpecDef .File , field , expr .Value , arrSchama )
454
461
if err != nil {
455
462
return nil , err
456
463
}
457
- return & TypeSchema {
458
- Name : example ,
459
- Type : OBJECT ,
460
- FieldName : example ,
461
- FullName : schema .FullName ,
462
- Properties : map [string ]* TypeSchema {
463
- strings .Trim (example , "\" " ): schema ,
464
- },
465
- }, err
464
+ arrSchama .FullName = schema .FullName
465
+ arrSchama .Properties [strings .Trim (example , "\" " )] = schema
466
+ return arrSchama , nil
466
467
}
467
468
}
468
469
@@ -479,39 +480,40 @@ func (parser *Parser) ParseDefinition(typeSpecDef *TypeSpecDef, field *ast.Field
479
480
return & sch , nil
480
481
}
481
482
482
- func (parser * Parser ) parseTypeExpr (file * ast.File , field * ast.Field , typeExpr ast.Expr ) (* TypeSchema , error ) {
483
+ func (parser * Parser ) parseTypeExpr (file * ast.File , field * ast.Field , typeExpr ast.Expr , parentSchama * TypeSchema ) (* TypeSchema , error ) {
483
484
switch expr := typeExpr .(type ) {
484
485
// type Foo interface{}
485
486
case * ast.InterfaceType :
486
487
return & TypeSchema {
487
488
Type : ANY ,
488
489
Example : "null" ,
490
+ Parent : parentSchama ,
489
491
}, nil
490
492
491
493
// type Foo struct {...}
492
494
case * ast.StructType :
493
- return parser .parseStruct (file , expr .Fields )
495
+ return parser .parseStruct (nil , file , expr .Fields , parentSchama )
494
496
495
497
// type Foo Baz
496
498
case * ast.Ident :
497
- return parser .getTypeSchema (expr .Name , file , field )
499
+ return parser .getTypeSchema (expr .Name , file , field , parentSchama )
498
500
499
501
// type Foo *Baz
500
502
case * ast.StarExpr :
501
- return parser .parseTypeExpr (file , field , expr .X )
503
+ return parser .parseTypeExpr (file , field , expr .X , parentSchama )
502
504
503
505
// type Foo pkg.Bar
504
506
case * ast.SelectorExpr :
505
507
if xIdent , ok := expr .X .(* ast.Ident ); ok {
506
- return parser .getTypeSchema (fullTypeName (xIdent .Name , expr .Sel .Name ), file , field )
508
+ return parser .getTypeSchema (fullTypeName (xIdent .Name , expr .Sel .Name ), file , field , parentSchama )
507
509
}
508
510
// type Foo []Baz
509
511
case * ast.ArrayType :
510
- itemSchema , err := parser .parseTypeExpr (file , field , expr .Elt )
512
+ itemSchema , err := parser .parseTypeExpr (file , field , expr .Elt , parentSchama )
511
513
if err != nil {
512
514
return nil , err
513
515
}
514
- return & TypeSchema {Type : "array" , IsArray : true , ArraySchema : itemSchema }, nil
516
+ return & TypeSchema {Type : "array" , IsArray : true , ArraySchema : itemSchema , Parent : parentSchama }, nil
515
517
// type Foo map[string]Bar
516
518
case * ast.MapType :
517
519
if keyIdent , ok := expr .Key .(* ast.Ident ); ok {
@@ -520,7 +522,7 @@ func (parser *Parser) parseTypeExpr(file *ast.File, field *ast.Field, typeExpr a
520
522
if _ , ok := expr .Value .(* ast.InterfaceType ); ok {
521
523
return & TypeSchema {Type : OBJECT , Properties : nil }, nil
522
524
}
523
- schema , err := parser .parseTypeExpr (file , field , expr .Value )
525
+ schema , err := parser .parseTypeExpr (file , field , expr .Value , parentSchama )
524
526
if err != nil {
525
527
return nil , err
526
528
}
@@ -546,37 +548,38 @@ func (parser *Parser) parseTypeExpr(file *ast.File, field *ast.Field, typeExpr a
546
548
return & TypeSchema {Type : OBJECT }, nil
547
549
}
548
550
549
- func (parser * Parser ) parseStruct (file * ast.File , fields * ast.FieldList ) (* TypeSchema , error ) {
550
- properties := make (map [string ]* TypeSchema )
551
- // parser.clearStructStack() //warning
551
+ func (parser * Parser ) parseStruct (typeSpecDef * TypeSpecDef , file * ast.File , fields * ast.FieldList , parentSchama * TypeSchema ) (* TypeSchema , error ) {
552
+ structSchema := & TypeSchema {
553
+ Name : file .Name .Name ,
554
+ Type : OBJECT ,
555
+ typeSpecDef : typeSpecDef ,
556
+ Parent : parentSchama ,
557
+ Properties : map [string ]* TypeSchema {},
558
+ }
552
559
for _ , field := range fields .List {
553
560
if len (field .Names ) != 1 {
554
561
return nil , errors .New ("error len(field.Names) != 1" )
555
562
}
556
563
name := field .Names [0 ].Name
557
- schema , err := parser .parseStructField (file , field )
564
+ schema , err := parser .parseStructField (file , field , structSchema )
558
565
if err != nil {
559
566
return nil , err
560
567
}
561
568
schema .Name = name
562
569
isOmitempty , fieldName := getFieldName (field .Names [0 ].Name , field , "json" )
563
570
schema .FieldName = fieldName
564
571
schema .IsOmitempty = isOmitempty
565
- properties [schema .FieldName ] = schema
572
+ structSchema . Properties [schema .FieldName ] = schema
566
573
}
567
- return & TypeSchema {
568
- Name : file .Name .Name ,
569
- Type : OBJECT ,
570
- Properties : properties ,
571
- }, nil
574
+ return structSchema , nil
572
575
}
573
576
574
- func (parser * Parser ) parseStructField (file * ast.File , field * ast.Field ) (* TypeSchema , error ) {
577
+ func (parser * Parser ) parseStructField (file * ast.File , field * ast.Field , parentSchama * TypeSchema ) (* TypeSchema , error ) {
575
578
name := field .Names [0 ].Name
576
579
if ! ast .IsExported (name ) {
577
580
return nil , nil
578
581
}
579
- return parser .parseTypeExpr (file , field , field .Type )
582
+ return parser .parseTypeExpr (file , field , field .Type , parentSchama )
580
583
// isArray, typeName, err := getFieldType(field.Type)
581
584
// if err != nil {
582
585
// return nil, err
0 commit comments