@@ -57,6 +57,9 @@ type applyFirstMarker interface {
5757ApplyFirst ()
5858}
5959
60+ // schemaFetcher is a function that fetches a schema for a given type.
61+ type schemaFetcher func (TypeIdent ) * apiext.JSONSchemaProps
62+
6063// schemaRequester knows how to marker that another schema (e.g. via an external reference) is necessary.
6164type schemaRequester interface {
6265NeedSchemaFor (typ TypeIdent )
@@ -68,6 +71,7 @@ type schemaContext struct {
6871info * markers.TypeInfo
6972
7073schemaRequester schemaRequester
74+ schemaFetcher schemaFetcher
7175PackageMarkers markers.MarkerValues
7276
7377allowDangerousTypes bool
@@ -76,11 +80,12 @@ type schemaContext struct {
7680
7781// newSchemaContext constructs a new schemaContext for the given package and schema requester.
7882// 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 {
8084pkg .NeedTypesInfo ()
8185return & schemaContext {
8286pkg : pkg ,
8387schemaRequester : req ,
88+ schemaFetcher : fetcher ,
8489allowDangerousTypes : allowDangerousTypes ,
8590ignoreUnexportedFields : ignoreUnexportedFields ,
8691}
@@ -93,6 +98,7 @@ func (c *schemaContext) ForInfo(info *markers.TypeInfo) *schemaContext {
9398pkg : c .pkg ,
9499info : info ,
95100schemaRequester : c .schemaRequester ,
101+ schemaFetcher : c .schemaFetcher ,
96102allowDangerousTypes : c .allowDangerousTypes ,
97103ignoreUnexportedFields : c .ignoreUnexportedFields ,
98104}
@@ -234,7 +240,9 @@ func typeToSchema(ctx *schemaContext, rawType ast.Expr) *apiext.JSONSchemaProps
234240return & apiext.JSONSchemaProps {}
235241}
236242
237- props .Description = ctx .info .Doc
243+ if ctx .info .Doc != "" {
244+ props .Description = ctx .info .Doc
245+ }
238246
239247applyMarkers (ctx , ctx .info .Markers , props , rawType )
240248
@@ -270,6 +278,7 @@ func localNamedToSchema(ctx *schemaContext, ident *ast.Ident) *apiext.JSONSchema
270278if aliasInfo , isAlias := typeInfo .(* types.Alias ); isAlias {
271279typeInfo = aliasInfo .Rhs ()
272280}
281+
273282if basicInfo , isBasic := typeInfo .(* types.Basic ); isBasic {
274283typ , fmt , err := builtinToType (basicInfo , ctx .allowDangerousTypes )
275284if err != nil {
@@ -281,32 +290,21 @@ func localNamedToSchema(ctx *schemaContext, ident *ast.Ident) *apiext.JSONSchema
281290// > Otherwise, the alias information is only in the type name, which
282291// > points directly to the actual (aliased) type.
283292if 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+ })
291297}
292298return & apiext.JSONSchemaProps {
293299Type : typ ,
294300Format : fmt ,
295301}
296302}
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+ })
310308}
311309
312310// namedSchema creates a schema (ref) for an explicitly external type reference.
@@ -501,7 +499,9 @@ func structToSchema(ctx *schemaContext, structType *ast.StructType) *apiext.JSON
501499} else {
502500propSchema = typeToSchema (ctx .ForInfo (& markers.TypeInfo {}), field .RawField .Type )
503501}
504- propSchema .Description = field .Doc
502+ if field .Doc != "" {
503+ propSchema .Description = field .Doc
504+ }
505505
506506applyMarkers (ctx , field .Markers , propSchema , field .RawField )
507507
@@ -513,6 +513,9 @@ func structToSchema(ctx *schemaContext, structType *ast.StructType) *apiext.JSON
513513props .Properties [fieldName ] = * propSchema
514514}
515515
516+ // Ensure the required fields are always listed alphabetically.
517+ sort .Strings (props .Required )
518+
516519return props
517520}
518521
0 commit comments