9fe4437bda
* Use vendored go-swagger * vendor go-swagger * revert un wanteed change * remove un-needed GO111MODULE * Update Makefile Co-Authored-By: techknowlogick <matti@mdranta.net>
232 lines
4.8 KiB
Go
232 lines
4.8 KiB
Go
package codescan
|
|
|
|
import (
|
|
"github.com/go-openapi/spec"
|
|
)
|
|
|
|
func newSpecBuilder(input *spec.Swagger, sc *scanCtx, scanModels bool) *specBuilder {
|
|
if input == nil {
|
|
input = new(spec.Swagger)
|
|
input.Swagger = "2.0"
|
|
}
|
|
|
|
if input.Paths == nil {
|
|
input.Paths = new(spec.Paths)
|
|
}
|
|
if input.Definitions == nil {
|
|
input.Definitions = make(map[string]spec.Schema)
|
|
}
|
|
if input.Responses == nil {
|
|
input.Responses = make(map[string]spec.Response)
|
|
}
|
|
if input.Extensions == nil {
|
|
input.Extensions = make(spec.Extensions)
|
|
}
|
|
|
|
return &specBuilder{
|
|
ctx: sc,
|
|
input: input,
|
|
scanModels: scanModels,
|
|
operations: collectOperationsFromInput(input),
|
|
definitions: input.Definitions,
|
|
responses: input.Responses,
|
|
}
|
|
}
|
|
|
|
type specBuilder struct {
|
|
scanModels bool
|
|
input *spec.Swagger
|
|
ctx *scanCtx
|
|
discovered []*entityDecl
|
|
definitions map[string]spec.Schema
|
|
responses map[string]spec.Response
|
|
operations map[string]*spec.Operation
|
|
}
|
|
|
|
func (s *specBuilder) Build() (*spec.Swagger, error) {
|
|
if err := s.buildModels(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := s.buildParameters(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := s.buildRespones(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// build definitions dictionary
|
|
if err := s.buildDiscovered(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := s.buildRoutes(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := s.buildOperations(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := s.buildMeta(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if s.input.Swagger == "" {
|
|
s.input.Swagger = "2.0"
|
|
}
|
|
|
|
return s.input, nil
|
|
}
|
|
|
|
func (s *specBuilder) buildDiscovered() error {
|
|
// loop over discovered until all the items are in definitions
|
|
keepGoing := len(s.discovered) > 0
|
|
for keepGoing {
|
|
var queue []*entityDecl
|
|
for _, d := range s.discovered {
|
|
nm, _ := d.Names()
|
|
if _, ok := s.definitions[nm]; !ok {
|
|
queue = append(queue, d)
|
|
}
|
|
}
|
|
s.discovered = nil
|
|
for _, sd := range queue {
|
|
if err := s.buildDiscoveredSchema(sd); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
keepGoing = len(s.discovered) > 0
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *specBuilder) buildDiscoveredSchema(decl *entityDecl) error {
|
|
sb := &schemaBuilder{
|
|
ctx: s.ctx,
|
|
decl: decl,
|
|
discovered: s.discovered,
|
|
}
|
|
if err := sb.Build(s.definitions); err != nil {
|
|
return err
|
|
}
|
|
s.discovered = append(s.discovered, sb.postDecls...)
|
|
return nil
|
|
}
|
|
|
|
func (s *specBuilder) buildMeta() error {
|
|
// build swagger object
|
|
for _, decl := range s.ctx.app.Meta {
|
|
if err := newMetaParser(s.input).Parse(decl.Comments); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *specBuilder) buildOperations() error {
|
|
for _, pp := range s.ctx.app.Operations {
|
|
ob := &operationsBuilder{
|
|
operations: s.operations,
|
|
ctx: s.ctx,
|
|
path: pp,
|
|
}
|
|
if err := ob.Build(s.input.Paths); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *specBuilder) buildRoutes() error {
|
|
// build paths dictionary
|
|
for _, pp := range s.ctx.app.Routes {
|
|
rb := &routesBuilder{
|
|
ctx: s.ctx,
|
|
route: pp,
|
|
responses: s.responses,
|
|
operations: s.operations,
|
|
definitions: s.definitions,
|
|
}
|
|
if err := rb.Build(s.input.Paths); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *specBuilder) buildRespones() error {
|
|
// build responses dictionary
|
|
for _, decl := range s.ctx.app.Responses {
|
|
rb := &responseBuilder{
|
|
ctx: s.ctx,
|
|
decl: decl,
|
|
}
|
|
if err := rb.Build(s.responses); err != nil {
|
|
return err
|
|
}
|
|
s.discovered = append(s.discovered, rb.postDecls...)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *specBuilder) buildParameters() error {
|
|
// build parameters dictionary
|
|
for _, decl := range s.ctx.app.Parameters {
|
|
pb := ¶meterBuilder{
|
|
ctx: s.ctx,
|
|
decl: decl,
|
|
}
|
|
if err := pb.Build(s.operations); err != nil {
|
|
return err
|
|
}
|
|
s.discovered = append(s.discovered, pb.postDecls...)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *specBuilder) buildModels() error {
|
|
// build models dictionary
|
|
if !s.scanModels {
|
|
return nil
|
|
}
|
|
for _, decl := range s.ctx.app.Models {
|
|
if err := s.buildDiscoveredSchema(decl); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func collectOperationsFromInput(input *spec.Swagger) map[string]*spec.Operation {
|
|
operations := make(map[string]*spec.Operation)
|
|
if input != nil && input.Paths != nil {
|
|
for _, pth := range input.Paths.Paths {
|
|
if pth.Get != nil {
|
|
operations[pth.Get.ID] = pth.Get
|
|
}
|
|
if pth.Post != nil {
|
|
operations[pth.Post.ID] = pth.Post
|
|
}
|
|
if pth.Put != nil {
|
|
operations[pth.Put.ID] = pth.Put
|
|
}
|
|
if pth.Patch != nil {
|
|
operations[pth.Patch.ID] = pth.Patch
|
|
}
|
|
if pth.Delete != nil {
|
|
operations[pth.Delete.ID] = pth.Delete
|
|
}
|
|
if pth.Head != nil {
|
|
operations[pth.Head.ID] = pth.Head
|
|
}
|
|
if pth.Options != nil {
|
|
operations[pth.Options.ID] = pth.Options
|
|
}
|
|
}
|
|
}
|
|
return operations
|
|
}
|