@@ -57,6 +57,9 @@ type applyFirstMarker interface {
57
57
ApplyFirst ()
58
58
}
59
59
60
+ // schemaFetcher is a function that fetches a schema for a given type.
61
+ type schemaFetcher func (TypeIdent ) * apiext.JSONSchemaProps
62
+
60
63
// schemaRequester knows how to marker that another schema (e.g. via an external reference) is necessary.
61
64
type schemaRequester interface {
62
65
NeedSchemaFor (typ TypeIdent )
@@ -68,6 +71,7 @@ type schemaContext struct {
68
71
info * markers.TypeInfo
69
72
70
73
schemaRequester schemaRequester
74
+ schemaFetcher schemaFetcher
71
75
PackageMarkers markers.MarkerValues
72
76
73
77
allowDangerousTypes bool
@@ -76,11 +80,12 @@ type schemaContext struct {
76
80
77
81
// newSchemaContext constructs a new schemaContext for the given package and schema requester.
78
82
// It must have type info added before use via ForInfo.
79
- func newSchemaContext (pkg * loader.Package , req schemaRequester , allowDangerousTypes , ignoreUnexportedFields bool ) * schemaContext {
83
+ func newSchemaContext (pkg * loader.Package , req schemaRequester , fetcher schemaFetcher , allowDangerousTypes , ignoreUnexportedFields bool ) * schemaContext {
80
84
pkg .NeedTypesInfo ()
81
85
return & schemaContext {
82
86
pkg : pkg ,
83
87
schemaRequester : req ,
88
+ schemaFetcher : fetcher ,
84
89
allowDangerousTypes : allowDangerousTypes ,
85
90
ignoreUnexportedFields : ignoreUnexportedFields ,
86
91
}
@@ -93,6 +98,7 @@ func (c *schemaContext) ForInfo(info *markers.TypeInfo) *schemaContext {
93
98
pkg : c .pkg ,
94
99
info : info ,
95
100
schemaRequester : c .schemaRequester ,
101
+ schemaFetcher : c .schemaFetcher ,
96
102
allowDangerousTypes : c .allowDangerousTypes ,
97
103
ignoreUnexportedFields : c .ignoreUnexportedFields ,
98
104
}
@@ -234,7 +240,9 @@ func typeToSchema(ctx *schemaContext, rawType ast.Expr) *apiext.JSONSchemaProps
234
240
return & apiext.JSONSchemaProps {}
235
241
}
236
242
237
- props .Description = ctx .info .Doc
243
+ if ctx .info .Doc != "" {
244
+ props .Description = ctx .info .Doc
245
+ }
238
246
239
247
applyMarkers (ctx , ctx .info .Markers , props , rawType )
240
248
@@ -270,6 +278,7 @@ func localNamedToSchema(ctx *schemaContext, ident *ast.Ident) *apiext.JSONSchema
270
278
if aliasInfo , isAlias := typeInfo .(* types.Alias ); isAlias {
271
279
typeInfo = aliasInfo .Rhs ()
272
280
}
281
+
273
282
if basicInfo , isBasic := typeInfo .(* types.Basic ); isBasic {
274
283
typ , fmt , err := builtinToType (basicInfo , ctx .allowDangerousTypes )
275
284
if err != nil {
@@ -281,32 +290,21 @@ func localNamedToSchema(ctx *schemaContext, ident *ast.Ident) *apiext.JSONSchema
281
290
// > Otherwise, the alias information is only in the type name, which
282
291
// > points directly to the actual (aliased) type.
283
292
if basicInfo .Name () != ident .Name {
284
- ctx .requestSchema ("" , ident .Name )
285
- link := TypeRefLink ("" , ident .Name )
286
- return & apiext.JSONSchemaProps {
287
- Type : typ ,
288
- Format : fmt ,
289
- Ref : & link ,
290
- }
293
+ return ctx .schemaFetcher (TypeIdent {
294
+ Package : ctx .pkg ,
295
+ Name : ident .Name ,
296
+ })
291
297
}
292
298
return & apiext.JSONSchemaProps {
293
299
Type : typ ,
294
300
Format : fmt ,
295
301
}
296
302
}
297
- // NB(directxman12): if there are dot imports, this might be an external reference,
298
- // so use typechecking info to get the actual object
299
- typeNameInfo := typeInfo .(interface { Obj () * types.TypeName }).Obj ()
300
- pkg := typeNameInfo .Pkg ()
301
- pkgPath := loader .NonVendorPath (pkg .Path ())
302
- if pkg == ctx .pkg .Types {
303
- pkgPath = ""
304
- }
305
- ctx .requestSchema (pkgPath , typeNameInfo .Name ())
306
- link := TypeRefLink (pkgPath , typeNameInfo .Name ())
307
- return & apiext.JSONSchemaProps {
308
- Ref : & link ,
309
- }
303
+
304
+ return ctx .schemaFetcher (TypeIdent {
305
+ Package : ctx .pkg ,
306
+ Name : ident .Name ,
307
+ })
310
308
}
311
309
312
310
// namedSchema creates a schema (ref) for an explicitly external type reference.
@@ -501,7 +499,9 @@ func structToSchema(ctx *schemaContext, structType *ast.StructType) *apiext.JSON
501
499
} else {
502
500
propSchema = typeToSchema (ctx .ForInfo (& markers.TypeInfo {}), field .RawField .Type )
503
501
}
504
- propSchema .Description = field .Doc
502
+ if field .Doc != "" {
503
+ propSchema .Description = field .Doc
504
+ }
505
505
506
506
applyMarkers (ctx , field .Markers , propSchema , field .RawField )
507
507
@@ -513,6 +513,9 @@ func structToSchema(ctx *schemaContext, structType *ast.StructType) *apiext.JSON
513
513
props .Properties [fieldName ] = * propSchema
514
514
}
515
515
516
+ // Ensure the required fields are always listed alphabetically.
517
+ sort .Strings (props .Required )
518
+
516
519
return props
517
520
}
518
521
0 commit comments