[Vendor] update go-swagger v0.21.0 -> v0.25.0 (#12670)
* Update go-swagger * vendor
This commit is contained in:
parent
66843f2237
commit
3270e7a443
350 changed files with 26353 additions and 5552 deletions
101
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff.go
generated
vendored
101
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff.go
generated
vendored
|
@ -2,11 +2,14 @@ package commands
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"errors"
|
||||
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-swagger/go-swagger/cmd/swagger/commands/diff"
|
||||
)
|
||||
|
@ -22,32 +25,46 @@ type DiffCommand struct {
|
|||
Format string `long:"format" short:"f" description:"When present, writes output as json" default:"txt" choice:"txt" choice:"json"`
|
||||
IgnoreFile string `long:"ignore" short:"i" description:"Exception file of diffs to ignore (copy output from json diff format)" default:"none specified"`
|
||||
Destination string `long:"dest" short:"d" description:"Output destination file or stdout" default:"stdout"`
|
||||
Args struct {
|
||||
OldSpec string `positional-arg-name:"{old spec}"`
|
||||
NewSpec string `positional-arg-name:"{new spec}"`
|
||||
} `required:"2" positional-args:"specs" description:"Input specs to be diff-ed"`
|
||||
}
|
||||
|
||||
// Execute diffs the two specs provided
|
||||
func (c *DiffCommand) Execute(args []string) error {
|
||||
if len(args) != 2 {
|
||||
msg := `missing arguments for diff command (use --help for more info)`
|
||||
return errors.New(msg)
|
||||
func (c *DiffCommand) Execute(_ []string) error {
|
||||
if c.Args.OldSpec == "" || c.Args.NewSpec == "" {
|
||||
return errors.New(`missing arguments for diff command (use --help for more info)`)
|
||||
}
|
||||
|
||||
log.Println("Run Config:")
|
||||
log.Printf("Spec1: %s", args[0])
|
||||
log.Printf("Spec2: %s", args[1])
|
||||
log.Printf("ReportOnlyBreakingChanges (-c) :%v", c.OnlyBreakingChanges)
|
||||
log.Printf("OutputFormat (-f) :%s", c.Format)
|
||||
log.Printf("IgnoreFile (-i) :%s", c.IgnoreFile)
|
||||
log.Printf("Diff Report Destination (-d) :%s", c.Destination)
|
||||
c.printInfo()
|
||||
|
||||
diffs, err := getDiffs(args[0], args[1])
|
||||
var (
|
||||
output io.WriteCloser
|
||||
err error
|
||||
)
|
||||
if c.Destination != "" {
|
||||
output, err = os.OpenFile(c.Destination, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", c.Destination, err)
|
||||
}
|
||||
defer func() {
|
||||
_ = output.Close()
|
||||
}()
|
||||
} else {
|
||||
output = os.Stdout
|
||||
}
|
||||
|
||||
diffs, err := c.getDiffs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ignores, err := readIgnores(c.IgnoreFile)
|
||||
ignores, err := c.readIgnores()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
diffs = diffs.FilterIgnores(ignores)
|
||||
if len(ignores) > 0 {
|
||||
log.Printf("Diff Report Ignored Items from IgnoreFile")
|
||||
|
@ -56,40 +73,44 @@ func (c *DiffCommand) Execute(args []string) error {
|
|||
}
|
||||
}
|
||||
|
||||
if c.Format == JSONFormat {
|
||||
err = diffs.ReportAllDiffs(true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var (
|
||||
input io.Reader
|
||||
warn error
|
||||
)
|
||||
if c.Format != JSONFormat && c.OnlyBreakingChanges {
|
||||
input, err, warn = diffs.ReportCompatibility()
|
||||
} else {
|
||||
if c.OnlyBreakingChanges {
|
||||
err = diffs.ReportCompatibility()
|
||||
} else {
|
||||
err = diffs.ReportAllDiffs(false)
|
||||
}
|
||||
input, err, warn = diffs.ReportAllDiffs(c.Format == JSONFormat)
|
||||
}
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.Copy(output, input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return warn
|
||||
}
|
||||
|
||||
func readIgnores(ignoreFile string) (diff.SpecDifferences, error) {
|
||||
func (c *DiffCommand) readIgnores() (diff.SpecDifferences, error) {
|
||||
ignoreFile := c.IgnoreFile
|
||||
ignoreDiffs := diff.SpecDifferences{}
|
||||
|
||||
if ignoreFile == "none specified" {
|
||||
if ignoreFile == "none specified" || ignoreFile == "" {
|
||||
return ignoreDiffs, nil
|
||||
}
|
||||
// Open our jsonFile
|
||||
jsonFile, err := os.Open(ignoreFile)
|
||||
// if we os.Open returns an error then handle it
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("%s: %w", ignoreFile, err)
|
||||
}
|
||||
// defer the closing of our jsonFile so that we can parse it later on
|
||||
defer jsonFile.Close()
|
||||
defer func() {
|
||||
_ = jsonFile.Close()
|
||||
}()
|
||||
byteValue, err := ioutil.ReadAll(jsonFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("reading %s: %w", ignoreFile, err)
|
||||
}
|
||||
// def
|
||||
err = json.Unmarshal(byteValue, &ignoreDiffs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -97,10 +118,10 @@ func readIgnores(ignoreFile string) (diff.SpecDifferences, error) {
|
|||
return ignoreDiffs, nil
|
||||
}
|
||||
|
||||
func getDiffs(oldSpecPath, newSpecPath string) (diff.SpecDifferences, error) {
|
||||
func (c *DiffCommand) getDiffs() (diff.SpecDifferences, error) {
|
||||
oldSpecPath, newSpecPath := c.Args.OldSpec, c.Args.NewSpec
|
||||
swaggerDoc1 := oldSpecPath
|
||||
specDoc1, err := loads.Spec(swaggerDoc1)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -113,3 +134,13 @@ func getDiffs(oldSpecPath, newSpecPath string) (diff.SpecDifferences, error) {
|
|||
|
||||
return diff.Compare(specDoc1.Spec(), specDoc2.Spec())
|
||||
}
|
||||
|
||||
func (c *DiffCommand) printInfo() {
|
||||
log.Println("Run Config:")
|
||||
log.Printf("Spec1: %s", c.Args.OldSpec)
|
||||
log.Printf("Spec2: %s", c.Args.NewSpec)
|
||||
log.Printf("ReportOnlyBreakingChanges (-c) :%v", c.OnlyBreakingChanges)
|
||||
log.Printf("OutputFormat (-f) :%s", c.Format)
|
||||
log.Printf("IgnoreFile (-i) :%s", c.IgnoreFile)
|
||||
log.Printf("Diff Report Destination (-d) :%s", c.Destination)
|
||||
}
|
||||
|
|
35
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/array_diff.go
generated
vendored
35
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/array_diff.go
generated
vendored
|
@ -2,22 +2,29 @@ package diff
|
|||
|
||||
// This is a simple DSL for diffing arrays
|
||||
|
||||
// FromArrayStruct utility struct to encompass diffing of string arrays
|
||||
type FromArrayStruct struct {
|
||||
// fromArrayStruct utility struct to encompass diffing of string arrays
|
||||
type fromArrayStruct struct {
|
||||
from []string
|
||||
}
|
||||
|
||||
// FromStringArray starts a fluent diff expression
|
||||
func FromStringArray(from []string) FromArrayStruct {
|
||||
return FromArrayStruct{from}
|
||||
// fromStringArray starts a fluent diff expression
|
||||
func fromStringArray(from []string) fromArrayStruct {
|
||||
return fromArrayStruct{from}
|
||||
}
|
||||
|
||||
// DiffsTo completes a fluent dff expression
|
||||
func (f FromArrayStruct) DiffsTo(toArray []string) (added, deleted, common []string) {
|
||||
// DiffsTo completes a fluent diff expression
|
||||
func (f fromArrayStruct) DiffsTo(toArray []string) (added, deleted, common []string) {
|
||||
inFrom := 1
|
||||
inTo := 2
|
||||
|
||||
m := make(map[string]int)
|
||||
if f.from == nil {
|
||||
return toArray, []string{}, []string{}
|
||||
}
|
||||
|
||||
m := make(map[string]int, len(toArray))
|
||||
added = make([]string, 0, len(toArray))
|
||||
deleted = make([]string, 0, len(f.from))
|
||||
common = make([]string, 0, len(f.from))
|
||||
|
||||
for _, item := range f.from {
|
||||
m[item] = inFrom
|
||||
|
@ -43,14 +50,14 @@ func (f FromArrayStruct) DiffsTo(toArray []string) (added, deleted, common []str
|
|||
return
|
||||
}
|
||||
|
||||
// FromMapStruct utility struct to encompass diffing of string arrays
|
||||
type FromMapStruct struct {
|
||||
// fromMapStruct utility struct to encompass diffing of string arrays
|
||||
type fromMapStruct struct {
|
||||
srcMap map[string]interface{}
|
||||
}
|
||||
|
||||
// FromStringMap starts a comparison by declaring a source map
|
||||
func FromStringMap(srcMap map[string]interface{}) FromMapStruct {
|
||||
return FromMapStruct{srcMap}
|
||||
// fromStringMap starts a comparison by declaring a source map
|
||||
func fromStringMap(srcMap map[string]interface{}) fromMapStruct {
|
||||
return fromMapStruct{srcMap}
|
||||
}
|
||||
|
||||
// Pair stores a pair of items which share a key in two maps
|
||||
|
@ -60,7 +67,7 @@ type Pair struct {
|
|||
}
|
||||
|
||||
// DiffsTo - generates diffs for a comparison
|
||||
func (f FromMapStruct) DiffsTo(destMap map[string]interface{}) (added, deleted, common map[string]interface{}) {
|
||||
func (f fromMapStruct) DiffsTo(destMap map[string]interface{}) (added, deleted, common map[string]interface{}) {
|
||||
added = make(map[string]interface{})
|
||||
deleted = make(map[string]interface{})
|
||||
common = make(map[string]interface{})
|
||||
|
|
15
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/difftypes.go
generated
vendored
15
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/difftypes.go
generated
vendored
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
// SpecChangeCode enumerates the various types of diffs from one spec to another
|
||||
|
@ -175,18 +176,18 @@ var toStringSpecChangeCode = map[SpecChangeCode]string{
|
|||
var toIDSpecChangeCode = map[string]SpecChangeCode{}
|
||||
|
||||
// Description returns an english version of this error
|
||||
func (s *SpecChangeCode) Description() (result string) {
|
||||
result, ok := toLongStringSpecChangeCode[*s]
|
||||
func (s SpecChangeCode) Description() (result string) {
|
||||
result, ok := toLongStringSpecChangeCode[s]
|
||||
if !ok {
|
||||
fmt.Printf("WARNING: No description for %v", *s)
|
||||
log.Printf("warning: No description for %v", s)
|
||||
result = "UNDEFINED"
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalJSON marshals the enum as a quoted json string
|
||||
func (s *SpecChangeCode) MarshalJSON() ([]byte, error) {
|
||||
return stringAsQuotedBytes(toStringSpecChangeCode[*s])
|
||||
func (s SpecChangeCode) MarshalJSON() ([]byte, error) {
|
||||
return stringAsQuotedBytes(toStringSpecChangeCode[s])
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmashalls a quoted json string to the enum value
|
||||
|
@ -228,8 +229,8 @@ var toStringCompatibility = map[Compatibility]string{
|
|||
var toIDCompatibility = map[string]Compatibility{}
|
||||
|
||||
// MarshalJSON marshals the enum as a quoted json string
|
||||
func (s *Compatibility) MarshalJSON() ([]byte, error) {
|
||||
return stringAsQuotedBytes(toStringCompatibility[*s])
|
||||
func (s Compatibility) MarshalJSON() ([]byte, error) {
|
||||
return stringAsQuotedBytes(toStringCompatibility[s])
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmashals a quoted json string to the enum value
|
||||
|
|
5
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/reporting.go
generated
vendored
5
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/reporting.go
generated
vendored
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
|
@ -153,10 +154,10 @@ var numberWideness = map[string]int{
|
|||
"integer.int32": 0,
|
||||
}
|
||||
|
||||
func prettyprint(b []byte) ([]byte, error) {
|
||||
func prettyprint(b []byte) (io.ReadWriter, error) {
|
||||
var out bytes.Buffer
|
||||
err := json.Indent(&out, b, "", " ")
|
||||
return out.Bytes(), err
|
||||
return &out, err
|
||||
}
|
||||
|
||||
// JSONMarshal allows the item to be correctly rendered to json
|
||||
|
|
10
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/spec_analyser.go
generated
vendored
10
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/spec_analyser.go
generated
vendored
|
@ -59,7 +59,7 @@ func (sd *SpecAnalyser) Analyse(spec1, spec2 *spec.Swagger) error {
|
|||
|
||||
func (sd *SpecAnalyser) analyseSpecMetadata(spec1, spec2 *spec.Swagger) {
|
||||
// breaking if it no longer consumes any formats
|
||||
added, deleted, _ := FromStringArray(spec1.Consumes).DiffsTo(spec2.Consumes)
|
||||
added, deleted, _ := fromStringArray(spec1.Consumes).DiffsTo(spec2.Consumes)
|
||||
|
||||
node := getNameOnlyDiffNode("Spec")
|
||||
location := DifferenceLocation{Node: node}
|
||||
|
@ -74,7 +74,7 @@ func (sd *SpecAnalyser) analyseSpecMetadata(spec1, spec2 *spec.Swagger) {
|
|||
}
|
||||
|
||||
// // breaking if it no longer produces any formats
|
||||
added, deleted, _ = FromStringArray(spec1.Produces).DiffsTo(spec2.Produces)
|
||||
added, deleted, _ = fromStringArray(spec1.Produces).DiffsTo(spec2.Produces)
|
||||
producesLocation := location.AddNode(getNameOnlyDiffNode("produces"))
|
||||
for _, eachAdded := range added {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: producesLocation, Code: AddedProducesFormat, Compatibility: NonBreaking, DiffInfo: eachAdded})
|
||||
|
@ -84,7 +84,7 @@ func (sd *SpecAnalyser) analyseSpecMetadata(spec1, spec2 *spec.Swagger) {
|
|||
}
|
||||
|
||||
// // breaking if it no longer supports a scheme
|
||||
added, deleted, _ = FromStringArray(spec1.Schemes).DiffsTo(spec2.Schemes)
|
||||
added, deleted, _ = fromStringArray(spec1.Schemes).DiffsTo(spec2.Schemes)
|
||||
schemesLocation := location.AddNode(getNameOnlyDiffNode("schemes"))
|
||||
|
||||
for _, eachAdded := range added {
|
||||
|
@ -120,7 +120,7 @@ func (sd *SpecAnalyser) analyseEndpointData() {
|
|||
|
||||
for URLMethod, op2 := range sd.urlMethods2 {
|
||||
if op1, ok := sd.urlMethods1[URLMethod]; ok {
|
||||
addedTags, deletedTags, _ := FromStringArray(op1.Operation.Tags).DiffsTo(op2.Operation.Tags)
|
||||
addedTags, deletedTags, _ := fromStringArray(op1.Operation.Tags).DiffsTo(op2.Operation.Tags)
|
||||
location := DifferenceLocation{URL: URLMethod.Path, Method: URLMethod.Method}
|
||||
|
||||
for _, eachAddedTag := range addedTags {
|
||||
|
@ -566,7 +566,7 @@ func (sd *SpecAnalyser) compareEnums(left, right []interface{}) []TypeDiff {
|
|||
for _, eachRight := range right {
|
||||
rightStrs = append(rightStrs, fmt.Sprintf("%v", eachRight))
|
||||
}
|
||||
added, deleted, _ := FromStringArray(leftStrs).DiffsTo(rightStrs)
|
||||
added, deleted, _ := fromStringArray(leftStrs).DiffsTo(rightStrs)
|
||||
if len(added) > 0 {
|
||||
typeChange := strings.Join(added, ",")
|
||||
diffs = append(diffs, TypeDiff{Change: AddedEnumValue, Description: typeChange})
|
||||
|
|
53
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/spec_difference.go
generated
vendored
53
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/spec_difference.go
generated
vendored
|
@ -1,8 +1,10 @@
|
|||
package diff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"io"
|
||||
"sort"
|
||||
)
|
||||
|
||||
|
@ -131,19 +133,23 @@ func (sd SpecDifferences) addDiff(diff SpecDifference) SpecDifferences {
|
|||
}
|
||||
|
||||
// ReportCompatibility lists and spec
|
||||
func (sd *SpecDifferences) ReportCompatibility() error {
|
||||
func (sd *SpecDifferences) ReportCompatibility() (io.Reader, error, error) {
|
||||
var out bytes.Buffer
|
||||
breakingCount := sd.BreakingChangeCount()
|
||||
if breakingCount > 0 {
|
||||
fmt.Printf("\nBREAKING CHANGES:\n=================\n")
|
||||
sd.reportChanges(Breaking)
|
||||
return fmt.Errorf("compatibility Test FAILED: %d Breaking changes detected", breakingCount)
|
||||
fmt.Fprintln(&out, "\nBREAKING CHANGES:\n=================")
|
||||
_, _ = out.ReadFrom(sd.reportChanges(Breaking))
|
||||
msg := fmt.Sprintf("compatibility test FAILED: %d breaking changes detected", breakingCount)
|
||||
fmt.Fprintln(&out, msg)
|
||||
return &out, nil, errors.New(msg)
|
||||
}
|
||||
log.Printf("Compatibility test OK. No breaking changes identified.")
|
||||
return nil
|
||||
fmt.Fprintf(&out, "compatibility test OK. No breaking changes identified.")
|
||||
return &out, nil, nil
|
||||
}
|
||||
|
||||
func (sd SpecDifferences) reportChanges(compat Compatibility) {
|
||||
func (sd SpecDifferences) reportChanges(compat Compatibility) io.Reader {
|
||||
toReportList := []string{}
|
||||
var out bytes.Buffer
|
||||
|
||||
for _, diff := range sd {
|
||||
if diff.Compatibility == compat {
|
||||
|
@ -156,35 +162,36 @@ func (sd SpecDifferences) reportChanges(compat Compatibility) {
|
|||
})
|
||||
|
||||
for _, eachDiff := range toReportList {
|
||||
fmt.Println(eachDiff)
|
||||
fmt.Fprintln(&out, eachDiff)
|
||||
}
|
||||
return &out
|
||||
}
|
||||
|
||||
// ReportAllDiffs lists all the diffs between two specs
|
||||
func (sd SpecDifferences) ReportAllDiffs(fmtJSON bool) error {
|
||||
func (sd SpecDifferences) ReportAllDiffs(fmtJSON bool) (io.Reader, error, error) {
|
||||
if fmtJSON {
|
||||
|
||||
b, err := JSONMarshal(sd)
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't print results: %v", err)
|
||||
return nil, fmt.Errorf("couldn't print results: %v", err), nil
|
||||
}
|
||||
pretty, err := prettyprint(b)
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't print results: %v", err)
|
||||
}
|
||||
fmt.Println(string(pretty))
|
||||
return nil
|
||||
out, err := prettyprint(b)
|
||||
return out, err, nil
|
||||
}
|
||||
numDiffs := len(sd)
|
||||
if numDiffs == 0 {
|
||||
fmt.Println("No changes identified")
|
||||
return nil
|
||||
return bytes.NewBuffer([]byte("No changes identified")), nil, nil
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
if numDiffs != sd.BreakingChangeCount() {
|
||||
fmt.Println("NON-BREAKING CHANGES:\n=====================")
|
||||
sd.reportChanges(NonBreaking)
|
||||
fmt.Fprintln(&out, "NON-BREAKING CHANGES:\n=====================")
|
||||
_, _ = out.ReadFrom(sd.reportChanges(NonBreaking))
|
||||
}
|
||||
|
||||
return sd.ReportCompatibility()
|
||||
more, err, warn := sd.ReportCompatibility()
|
||||
if err != nil {
|
||||
return nil, err, warn
|
||||
}
|
||||
_, _ = out.ReadFrom(more)
|
||||
return &out, nil, warn
|
||||
}
|
||||
|
|
2
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/expand.go
generated
vendored
2
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/expand.go
generated
vendored
|
@ -69,5 +69,5 @@ func writeToFile(swspec *spec.Swagger, pretty bool, format string, output string
|
|||
fmt.Println(string(b))
|
||||
return nil
|
||||
}
|
||||
return ioutil.WriteFile(output, b, 0644)
|
||||
return ioutil.WriteFile(output, b, 0644) // #nosec
|
||||
}
|
||||
|
|
77
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/client.go
generated
vendored
77
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/client.go
generated
vendored
|
@ -20,56 +20,51 @@ import (
|
|||
"github.com/go-swagger/go-swagger/generator"
|
||||
)
|
||||
|
||||
type clientOptions struct {
|
||||
ClientPackage string `long:"client-package" short:"c" description:"the package to save the client specific code" default:"client"`
|
||||
}
|
||||
|
||||
func (co clientOptions) apply(opts *generator.GenOpts) {
|
||||
opts.ClientPackage = co.ClientPackage
|
||||
}
|
||||
|
||||
// Client the command to generate a swagger client
|
||||
type Client struct {
|
||||
shared
|
||||
Name string `long:"name" short:"A" description:"the name of the application, defaults to a mangled value of info.title"`
|
||||
Operations []string `long:"operation" short:"O" description:"specify an operation to include, repeat for multiple"`
|
||||
Tags []string `long:"tags" description:"the tags to include, if not specified defaults to all"`
|
||||
Principal string `long:"principal" short:"P" description:"the model to use for the security principal"`
|
||||
Models []string `long:"model" short:"M" description:"specify a model to include, repeat for multiple"`
|
||||
DefaultScheme string `long:"default-scheme" description:"the default scheme for this client" default:"http"`
|
||||
DefaultProduces string `long:"default-produces" description:"the default mime type that API operations produce" default:"application/json"`
|
||||
SkipModels bool `long:"skip-models" description:"no models will be generated when this flag is specified"`
|
||||
SkipOperations bool `long:"skip-operations" description:"no operations will be generated when this flag is specified"`
|
||||
DumpData bool `long:"dump-data" description:"when present dumps the json for the template generator instead of generating files"`
|
||||
SkipValidation bool `long:"skip-validation" description:"skips validation of spec prior to generation"`
|
||||
WithShared
|
||||
WithModels
|
||||
WithOperations
|
||||
|
||||
clientOptions
|
||||
schemeOptions
|
||||
mediaOptions
|
||||
|
||||
SkipModels bool `long:"skip-models" description:"no models will be generated when this flag is specified"`
|
||||
SkipOperations bool `long:"skip-operations" description:"no operations will be generated when this flag is specified"`
|
||||
|
||||
Name string `long:"name" short:"A" description:"the name of the application, defaults to a mangled value of info.title"`
|
||||
}
|
||||
|
||||
func (c *Client) getOpts() (*generator.GenOpts, error) {
|
||||
return &generator.GenOpts{
|
||||
Spec: string(c.Spec),
|
||||
func (c Client) apply(opts *generator.GenOpts) {
|
||||
c.Shared.apply(opts)
|
||||
c.Models.apply(opts)
|
||||
c.Operations.apply(opts)
|
||||
c.clientOptions.apply(opts)
|
||||
c.schemeOptions.apply(opts)
|
||||
c.mediaOptions.apply(opts)
|
||||
|
||||
Target: string(c.Target),
|
||||
APIPackage: c.APIPackage,
|
||||
ModelPackage: c.ModelPackage,
|
||||
ServerPackage: c.ServerPackage,
|
||||
ClientPackage: c.ClientPackage,
|
||||
Principal: c.Principal,
|
||||
DefaultScheme: c.DefaultScheme,
|
||||
DefaultProduces: c.DefaultProduces,
|
||||
IncludeModel: !c.SkipModels,
|
||||
IncludeValidator: !c.SkipModels,
|
||||
IncludeHandler: !c.SkipOperations,
|
||||
IncludeParameters: !c.SkipOperations,
|
||||
IncludeResponses: !c.SkipOperations,
|
||||
ValidateSpec: !c.SkipValidation,
|
||||
Tags: c.Tags,
|
||||
IncludeSupport: true,
|
||||
Template: c.Template,
|
||||
TemplateDir: string(c.TemplateDir),
|
||||
DumpData: c.DumpData,
|
||||
ExistingModels: c.ExistingModels,
|
||||
IsClient: true,
|
||||
}, nil
|
||||
}
|
||||
opts.IncludeModel = !c.SkipModels
|
||||
opts.IncludeValidator = !c.SkipModels
|
||||
opts.IncludeHandler = !c.SkipOperations
|
||||
opts.IncludeParameters = !c.SkipOperations
|
||||
opts.IncludeResponses = !c.SkipOperations
|
||||
opts.Name = c.Name
|
||||
|
||||
func (c *Client) getShared() *shared {
|
||||
return &c.shared
|
||||
opts.IsClient = true
|
||||
opts.IncludeSupport = true
|
||||
}
|
||||
|
||||
func (c *Client) generate(opts *generator.GenOpts) error {
|
||||
return generator.GenerateClient(c.Name, c.Models, c.Operations, opts)
|
||||
return generator.GenerateClient(c.Name, c.Models.Models, c.Operations.Operations, opts)
|
||||
}
|
||||
|
||||
func (c *Client) log(rp string) {
|
||||
|
|
1
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/contrib.go
generated
vendored
1
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/contrib.go
generated
vendored
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
// contribOptionsOverride gives contributed templates the ability to override the options if they need
|
||||
func contribOptionsOverride(opts *generator.GenOpts) {
|
||||
// nolint: gocritic
|
||||
switch opts.Template {
|
||||
case "stratoscale":
|
||||
// Stratoscale template needs to regenerate the configureapi on every run.
|
||||
|
|
86
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/model.go
generated
vendored
86
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/model.go
generated
vendored
|
@ -17,37 +17,83 @@ package generate
|
|||
import (
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
"github.com/go-swagger/go-swagger/generator"
|
||||
)
|
||||
|
||||
// Model the generate model file command
|
||||
type modelOptions struct {
|
||||
ModelPackage string `long:"model-package" short:"m" description:"the package to save the models" default:"models"`
|
||||
Models []string `long:"model" short:"M" description:"specify a model to include in generation, repeat for multiple (defaults to all)"`
|
||||
ExistingModels string `long:"existing-models" description:"use pre-generated models e.g. github.com/foobar/model"`
|
||||
StrictAdditionalProperties bool `long:"strict-additional-properties" description:"disallow extra properties when additionalProperties is set to false"`
|
||||
KeepSpecOrder bool `long:"keep-spec-order" description:"keep schema properties order identical to spec file"`
|
||||
AllDefinitions bool `long:"all-definitions" description:"generate all model definitions regardless of usage in operations" hidden:"deprecated"`
|
||||
StructTags []string `long:"struct-tags" description:"the struct tags to generate, repeat for multiple (defaults to json)"`
|
||||
}
|
||||
|
||||
func (mo modelOptions) apply(opts *generator.GenOpts) {
|
||||
opts.ModelPackage = mo.ModelPackage
|
||||
opts.Models = mo.Models
|
||||
opts.ExistingModels = mo.ExistingModels
|
||||
opts.StrictAdditionalProperties = mo.StrictAdditionalProperties
|
||||
opts.PropertiesSpecOrder = mo.KeepSpecOrder
|
||||
opts.IgnoreOperations = mo.AllDefinitions
|
||||
opts.StructTags = mo.StructTags
|
||||
}
|
||||
|
||||
// WithModels adds the model options group.
|
||||
//
|
||||
// This group is available to all commands that need some model generation.
|
||||
type WithModels struct {
|
||||
Models modelOptions `group:"Options for model generation"`
|
||||
}
|
||||
|
||||
// Model the generate model file command.
|
||||
//
|
||||
// Define the options that are specific to the "swagger generate model" command.
|
||||
type Model struct {
|
||||
shared
|
||||
Name []string `long:"name" short:"n" description:"the model to generate"`
|
||||
NoStruct bool `long:"skip-struct" description:"when present will not generate the model struct"`
|
||||
DumpData bool `long:"dump-data" description:"when present dumps the json for the template generator instead of generating files"`
|
||||
SkipValidation bool `long:"skip-validation" description:"skips validation of spec prior to generation"`
|
||||
WithShared
|
||||
WithModels
|
||||
|
||||
NoStruct bool `long:"skip-struct" description:"when present will not generate the model struct" hidden:"deprecated"`
|
||||
Name []string `long:"name" short:"n" description:"the model to generate, repeat for multiple (defaults to all). Same as --models"`
|
||||
AcceptDefinitionsOnly bool `long:"accept-definitions-only" description:"accepts a partial swagger spec wih only the definitions key"`
|
||||
}
|
||||
|
||||
func (m Model) apply(opts *generator.GenOpts) {
|
||||
m.Shared.apply(opts)
|
||||
m.Models.apply(opts)
|
||||
|
||||
opts.IncludeModel = !m.NoStruct
|
||||
opts.IncludeValidator = !m.NoStruct
|
||||
opts.AcceptDefinitionsOnly = m.AcceptDefinitionsOnly
|
||||
}
|
||||
|
||||
func (m Model) log(rp string) {
|
||||
log.Printf(`Generation completed!
|
||||
|
||||
For this generation to compile you need to have some packages in your GOPATH:
|
||||
|
||||
* github.com/go-openapi/validate
|
||||
* github.com/go-openapi/strfmt
|
||||
|
||||
You can get these now with: go get -u -f %s/...
|
||||
`, rp)
|
||||
}
|
||||
|
||||
func (m *Model) generate(opts *generator.GenOpts) error {
|
||||
return generator.GenerateModels(append(m.Name, m.Models.Models...), opts)
|
||||
}
|
||||
|
||||
// Execute generates a model file
|
||||
func (m *Model) Execute(args []string) error {
|
||||
|
||||
if m.DumpData && len(m.Name) > 1 {
|
||||
if m.Shared.DumpData && len(append(m.Name, m.Models.Models...)) > 1 {
|
||||
return errors.New("only 1 model at a time is supported for dumping data")
|
||||
}
|
||||
|
||||
if m.ExistingModels != "" {
|
||||
if m.Models.ExistingModels != "" {
|
||||
log.Println("warning: Ignoring existing-models flag when generating models.")
|
||||
}
|
||||
s := &Server{
|
||||
shared: m.shared,
|
||||
Models: m.Name,
|
||||
DumpData: m.DumpData,
|
||||
ExcludeMain: true,
|
||||
ExcludeSpec: true,
|
||||
SkipSupport: true,
|
||||
SkipOperations: true,
|
||||
SkipModels: m.NoStruct,
|
||||
SkipValidation: m.SkipValidation,
|
||||
}
|
||||
return s.Execute(args)
|
||||
return createSwagger(m)
|
||||
}
|
||||
|
|
90
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/operation.go
generated
vendored
90
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/operation.go
generated
vendored
|
@ -21,51 +21,69 @@ import (
|
|||
"github.com/go-swagger/go-swagger/generator"
|
||||
)
|
||||
|
||||
type operationOptions struct {
|
||||
Operations []string `long:"operation" short:"O" description:"specify an operation to include, repeat for multiple (defaults to all)"`
|
||||
Tags []string `long:"tags" description:"the tags to include, if not specified defaults to all" group:"operations"`
|
||||
APIPackage string `long:"api-package" short:"a" description:"the package to save the operations" default:"operations"`
|
||||
WithEnumCI bool `long:"with-enum-ci" description:"allow case-insensitive enumerations"`
|
||||
|
||||
// tags handling
|
||||
SkipTagPackages bool `long:"skip-tag-packages" description:"skips the generation of tag-based operation packages, resulting in a flat generation"`
|
||||
}
|
||||
|
||||
func (oo operationOptions) apply(opts *generator.GenOpts) {
|
||||
opts.Operations = oo.Operations
|
||||
opts.Tags = oo.Tags
|
||||
opts.APIPackage = oo.APIPackage
|
||||
opts.AllowEnumCI = oo.WithEnumCI
|
||||
opts.SkipTagPackages = oo.SkipTagPackages
|
||||
}
|
||||
|
||||
// WithOperations adds the operations options group
|
||||
type WithOperations struct {
|
||||
Operations operationOptions `group:"Options for operation generation"`
|
||||
}
|
||||
|
||||
// Operation the generate operation files command
|
||||
type Operation struct {
|
||||
shared
|
||||
Name []string `long:"name" short:"n" required:"true" description:"the operations to generate, repeat for multiple"`
|
||||
Tags []string `long:"tags" description:"the tags to include, if not specified defaults to all"`
|
||||
Principal string `short:"P" long:"principal" description:"the model to use for the security principal"`
|
||||
DefaultScheme string `long:"default-scheme" description:"the default scheme for this API" default:"http"`
|
||||
NoHandler bool `long:"skip-handler" description:"when present will not generate an operation handler"`
|
||||
NoStruct bool `long:"skip-parameters" description:"when present will not generate the parameter model struct"`
|
||||
NoResponses bool `long:"skip-responses" description:"when present will not generate the response model struct"`
|
||||
NoURLBuilder bool `long:"skip-url-builder" description:"when present will not generate a URL builder"`
|
||||
DumpData bool `long:"dump-data" description:"when present dumps the json for the template generator instead of generating files"`
|
||||
SkipValidation bool `long:"skip-validation" description:"skips validation of spec prior to generation"`
|
||||
WithShared
|
||||
WithOperations
|
||||
|
||||
clientOptions
|
||||
serverOptions
|
||||
schemeOptions
|
||||
mediaOptions
|
||||
|
||||
ModelPackage string `long:"model-package" short:"m" description:"the package to save the models" default:"models"`
|
||||
|
||||
NoHandler bool `long:"skip-handler" description:"when present will not generate an operation handler"`
|
||||
NoStruct bool `long:"skip-parameters" description:"when present will not generate the parameter model struct"`
|
||||
NoResponses bool `long:"skip-responses" description:"when present will not generate the response model struct"`
|
||||
NoURLBuilder bool `long:"skip-url-builder" description:"when present will not generate a URL builder"`
|
||||
|
||||
Name []string `long:"name" short:"n" description:"the operations to generate, repeat for multiple (defaults to all). Same as --operations"`
|
||||
}
|
||||
|
||||
func (o *Operation) getOpts() (*generator.GenOpts, error) {
|
||||
return &generator.GenOpts{
|
||||
Spec: string(o.Spec),
|
||||
Target: string(o.Target),
|
||||
APIPackage: o.APIPackage,
|
||||
ModelPackage: o.ModelPackage,
|
||||
ServerPackage: o.ServerPackage,
|
||||
ClientPackage: o.ClientPackage,
|
||||
Principal: o.Principal,
|
||||
DumpData: o.DumpData,
|
||||
DefaultScheme: o.DefaultScheme,
|
||||
TemplateDir: string(o.TemplateDir),
|
||||
IncludeHandler: !o.NoHandler,
|
||||
IncludeResponses: !o.NoResponses,
|
||||
IncludeParameters: !o.NoStruct,
|
||||
IncludeURLBuilder: !o.NoURLBuilder,
|
||||
Tags: o.Tags,
|
||||
ValidateSpec: !o.SkipValidation,
|
||||
}, nil
|
||||
}
|
||||
func (o Operation) apply(opts *generator.GenOpts) {
|
||||
o.Shared.apply(opts)
|
||||
o.Operations.apply(opts)
|
||||
o.clientOptions.apply(opts)
|
||||
o.serverOptions.apply(opts)
|
||||
o.schemeOptions.apply(opts)
|
||||
o.mediaOptions.apply(opts)
|
||||
|
||||
func (o *Operation) getShared() *shared {
|
||||
return &o.shared
|
||||
opts.ModelPackage = o.ModelPackage
|
||||
opts.IncludeHandler = !o.NoHandler
|
||||
opts.IncludeResponses = !o.NoResponses
|
||||
opts.IncludeParameters = !o.NoStruct
|
||||
opts.IncludeURLBuilder = !o.NoURLBuilder
|
||||
}
|
||||
|
||||
func (o *Operation) generate(opts *generator.GenOpts) error {
|
||||
return generator.GenerateServerOperation(o.Name, opts)
|
||||
return generator.GenerateServerOperation(append(o.Name, o.Operations.Operations...), opts)
|
||||
}
|
||||
|
||||
func (o *Operation) log(rp string) {
|
||||
func (o Operation) log(rp string) {
|
||||
|
||||
log.Printf(`Generation completed!
|
||||
|
||||
|
@ -79,7 +97,7 @@ You can get these now with: go get -u -f %s/...
|
|||
|
||||
// Execute generates a model file
|
||||
func (o *Operation) Execute(args []string) error {
|
||||
if o.DumpData && len(o.Name) > 1 {
|
||||
if o.Shared.DumpData && len(append(o.Name, o.Operations.Operations...)) > 1 {
|
||||
return errors.New("only 1 operation at a time is supported for dumping data")
|
||||
}
|
||||
|
||||
|
|
126
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/server.go
generated
vendored
126
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/server.go
generated
vendored
|
@ -21,87 +21,81 @@ import (
|
|||
"github.com/go-swagger/go-swagger/generator"
|
||||
)
|
||||
|
||||
// Server the command to generate an entire server application
|
||||
type Server struct {
|
||||
shared
|
||||
Name string `long:"name" short:"A" description:"the name of the application, defaults to a mangled value of info.title"`
|
||||
Operations []string `long:"operation" short:"O" description:"specify an operation to include, repeat for multiple"`
|
||||
Tags []string `long:"tags" description:"the tags to include, if not specified defaults to all"`
|
||||
Principal string `long:"principal" short:"P" description:"the model to use for the security principal"`
|
||||
DefaultScheme string `long:"default-scheme" description:"the default scheme for this API" default:"http"`
|
||||
Models []string `long:"model" short:"M" description:"specify a model to include, repeat for multiple"`
|
||||
SkipModels bool `long:"skip-models" description:"no models will be generated when this flag is specified"`
|
||||
SkipOperations bool `long:"skip-operations" description:"no operations will be generated when this flag is specified"`
|
||||
SkipSupport bool `long:"skip-support" description:"no supporting files will be generated when this flag is specified"`
|
||||
ExcludeMain bool `long:"exclude-main" description:"exclude main function, so just generate the library"`
|
||||
ExcludeSpec bool `long:"exclude-spec" description:"don't embed the swagger specification"`
|
||||
WithContext bool `long:"with-context" description:"handlers get a context as first arg (deprecated)"`
|
||||
DumpData bool `long:"dump-data" description:"when present dumps the json for the template generator instead of generating files"`
|
||||
FlagStrategy string `long:"flag-strategy" description:"the strategy to provide flags for the server" default:"go-flags" choice:"go-flags" choice:"pflag" choice:"flag"`
|
||||
CompatibilityMode string `long:"compatibility-mode" description:"the compatibility mode for the tls server" default:"modern" choice:"modern" choice:"intermediate"`
|
||||
SkipValidation bool `long:"skip-validation" description:"skips validation of spec prior to generation"`
|
||||
RegenerateConfigureAPI bool `long:"regenerate-configureapi" description:"Force regeneration of configureapi.go"`
|
||||
KeepSpecOrder bool `long:"keep-spec-order" description:"Keep schema properties order identical to spec file"`
|
||||
StrictAdditionalProperties bool `long:"strict-additional-properties" description:"disallow extra properties when additionalProperties is set to false"`
|
||||
type serverOptions struct {
|
||||
ServerPackage string `long:"server-package" short:"s" description:"the package to save the server specific code" default:"restapi"`
|
||||
MainTarget string `long:"main-package" short:"" description:"the location of the generated main. Defaults to cmd/{name}-server" default:""`
|
||||
}
|
||||
|
||||
func (s *Server) getOpts() (*generator.GenOpts, error) {
|
||||
// warning: deprecation
|
||||
func (cs serverOptions) apply(opts *generator.GenOpts) {
|
||||
opts.ServerPackage = cs.ServerPackage
|
||||
}
|
||||
|
||||
// Server the command to generate an entire server application
|
||||
type Server struct {
|
||||
WithShared
|
||||
WithModels
|
||||
WithOperations
|
||||
|
||||
serverOptions
|
||||
schemeOptions
|
||||
mediaOptions
|
||||
|
||||
SkipModels bool `long:"skip-models" description:"no models will be generated when this flag is specified"`
|
||||
SkipOperations bool `long:"skip-operations" description:"no operations will be generated when this flag is specified"`
|
||||
SkipSupport bool `long:"skip-support" description:"no supporting files will be generated when this flag is specified"`
|
||||
ExcludeMain bool `long:"exclude-main" description:"exclude main function, so just generate the library"`
|
||||
ExcludeSpec bool `long:"exclude-spec" description:"don't embed the swagger specification"`
|
||||
FlagStrategy string `long:"flag-strategy" description:"the strategy to provide flags for the server" default:"go-flags" choice:"go-flags" choice:"pflag" choice:"flag"` // nolint: staticcheck
|
||||
CompatibilityMode string `long:"compatibility-mode" description:"the compatibility mode for the tls server" default:"modern" choice:"modern" choice:"intermediate"` // nolint: staticcheck
|
||||
RegenerateConfigureAPI bool `long:"regenerate-configureapi" description:"Force regeneration of configureapi.go"`
|
||||
|
||||
Name string `long:"name" short:"A" description:"the name of the application, defaults to a mangled value of info.title"`
|
||||
// TODO(fredbi): CmdName string `long:"cmd-name" short:"A" description:"the name of the server command, when main is generated (defaults to {name}-server)"`
|
||||
|
||||
//deprecated flags
|
||||
WithContext bool `long:"with-context" description:"handlers get a context as first arg (deprecated)"`
|
||||
}
|
||||
|
||||
func (s Server) apply(opts *generator.GenOpts) {
|
||||
if s.WithContext {
|
||||
log.Printf("warning: deprecated option --with-context is ignored")
|
||||
}
|
||||
|
||||
return &generator.GenOpts{
|
||||
Spec: string(s.Spec),
|
||||
Target: string(s.Target),
|
||||
APIPackage: s.APIPackage,
|
||||
ModelPackage: s.ModelPackage,
|
||||
ServerPackage: s.ServerPackage,
|
||||
ClientPackage: s.ClientPackage,
|
||||
Principal: s.Principal,
|
||||
DefaultScheme: s.DefaultScheme,
|
||||
IncludeModel: !s.SkipModels,
|
||||
IncludeValidator: !s.SkipModels,
|
||||
IncludeHandler: !s.SkipOperations,
|
||||
IncludeParameters: !s.SkipOperations,
|
||||
IncludeResponses: !s.SkipOperations,
|
||||
IncludeURLBuilder: !s.SkipOperations,
|
||||
IncludeMain: !s.ExcludeMain,
|
||||
IncludeSupport: !s.SkipSupport,
|
||||
PropertiesSpecOrder: s.KeepSpecOrder,
|
||||
ValidateSpec: !s.SkipValidation,
|
||||
ExcludeSpec: s.ExcludeSpec,
|
||||
StrictAdditionalProperties: s.StrictAdditionalProperties,
|
||||
Template: s.Template,
|
||||
RegenerateConfigureAPI: s.RegenerateConfigureAPI,
|
||||
TemplateDir: string(s.TemplateDir),
|
||||
DumpData: s.DumpData,
|
||||
Models: s.Models,
|
||||
Operations: s.Operations,
|
||||
Tags: s.Tags,
|
||||
Name: s.Name,
|
||||
FlagStrategy: s.FlagStrategy,
|
||||
CompatibilityMode: s.CompatibilityMode,
|
||||
ExistingModels: s.ExistingModels,
|
||||
AllowTemplateOverride: s.AllowTemplateOverride,
|
||||
}, nil
|
||||
}
|
||||
s.Shared.apply(opts)
|
||||
s.Models.apply(opts)
|
||||
s.Operations.apply(opts)
|
||||
s.serverOptions.apply(opts)
|
||||
s.schemeOptions.apply(opts)
|
||||
s.mediaOptions.apply(opts)
|
||||
|
||||
func (s *Server) getShared() *shared {
|
||||
return &s.shared
|
||||
opts.IncludeModel = !s.SkipModels
|
||||
opts.IncludeValidator = !s.SkipModels
|
||||
opts.IncludeHandler = !s.SkipOperations
|
||||
opts.IncludeParameters = !s.SkipOperations
|
||||
opts.IncludeResponses = !s.SkipOperations
|
||||
opts.IncludeURLBuilder = !s.SkipOperations
|
||||
opts.IncludeSupport = !s.SkipSupport
|
||||
opts.IncludeMain = !s.ExcludeMain
|
||||
opts.FlagStrategy = s.FlagStrategy
|
||||
opts.CompatibilityMode = s.CompatibilityMode
|
||||
opts.RegenerateConfigureAPI = s.RegenerateConfigureAPI
|
||||
|
||||
opts.Name = s.Name
|
||||
opts.MainPackage = s.MainTarget
|
||||
}
|
||||
|
||||
func (s *Server) generate(opts *generator.GenOpts) error {
|
||||
return generator.GenerateServer(s.Name, s.Models, s.Operations, opts)
|
||||
return generator.GenerateServer(s.Name, s.Models.Models, s.Operations.Operations, opts)
|
||||
}
|
||||
|
||||
func (s *Server) log(rp string) {
|
||||
func (s Server) log(rp string) {
|
||||
var flagsPackage string
|
||||
if strings.HasPrefix(s.FlagStrategy, "pflag") {
|
||||
switch {
|
||||
case strings.HasPrefix(s.FlagStrategy, "pflag"):
|
||||
flagsPackage = "github.com/spf13/pflag"
|
||||
} else if strings.HasPrefix(s.FlagStrategy, "flag") {
|
||||
case strings.HasPrefix(s.FlagStrategy, "flag"):
|
||||
flagsPackage = "flag"
|
||||
} else {
|
||||
default:
|
||||
flagsPackage = "github.com/jessevdk/go-flags"
|
||||
}
|
||||
|
||||
|
|
202
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/shared.go
generated
vendored
202
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/shared.go
generated
vendored
|
@ -1,10 +1,12 @@
|
|||
package generate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
"github.com/go-openapi/swag"
|
||||
|
@ -15,8 +17,8 @@ import (
|
|||
|
||||
// FlattenCmdOptions determines options to the flatten spec preprocessing
|
||||
type FlattenCmdOptions struct {
|
||||
WithExpand bool `long:"with-expand" description:"expands all $ref's in spec prior to generation (shorthand to --with-flatten=expand)"`
|
||||
WithFlatten []string `long:"with-flatten" description:"flattens all $ref's in spec prior to generation" choice:"minimal" choice:"full" choice:"expand" choice:"verbose" choice:"noverbose" choice:"remove-unused" default:"minimal" default:"verbose"`
|
||||
WithExpand bool `long:"with-expand" description:"expands all $ref's in spec prior to generation (shorthand to --with-flatten=expand)" group:"shared"`
|
||||
WithFlatten []string `long:"with-flatten" description:"flattens all $ref's in spec prior to generation" choice:"minimal" choice:"full" choice:"expand" choice:"verbose" choice:"noverbose" choice:"remove-unused" default:"minimal" default:"verbose" group:"shared"` // nolint: staticcheck
|
||||
}
|
||||
|
||||
// SetFlattenOptions builds flatten options from command line args
|
||||
|
@ -30,138 +32,159 @@ func (f *FlattenCmdOptions) SetFlattenOptions(dflt *analysis.FlattenOpts) (res *
|
|||
}
|
||||
verboseIsSet := false
|
||||
minimalIsSet := false
|
||||
//removeUnusedIsSet := false
|
||||
expandIsSet := false
|
||||
if f.WithExpand {
|
||||
res.Expand = true
|
||||
expandIsSet = true
|
||||
}
|
||||
for _, opt := range f.WithFlatten {
|
||||
if opt == "verbose" {
|
||||
switch opt {
|
||||
case "verbose":
|
||||
res.Verbose = true
|
||||
verboseIsSet = true
|
||||
}
|
||||
if opt == "noverbose" && !verboseIsSet {
|
||||
// verbose flag takes precedence
|
||||
res.Verbose = false
|
||||
verboseIsSet = true
|
||||
}
|
||||
if opt == "remove-unused" {
|
||||
case "noverbose":
|
||||
if !verboseIsSet {
|
||||
// verbose flag takes precedence
|
||||
res.Verbose = false
|
||||
verboseIsSet = true
|
||||
}
|
||||
case "remove-unused":
|
||||
res.RemoveUnused = true
|
||||
//removeUnusedIsSet = true
|
||||
}
|
||||
if opt == "expand" {
|
||||
case "expand":
|
||||
res.Expand = true
|
||||
expandIsSet = true
|
||||
}
|
||||
if opt == "full" && !minimalIsSet && !expandIsSet {
|
||||
// minimal flag takes precedence
|
||||
res.Minimal = false
|
||||
minimalIsSet = true
|
||||
}
|
||||
if opt == "minimal" && !expandIsSet {
|
||||
// expand flag takes precedence
|
||||
res.Minimal = true
|
||||
minimalIsSet = true
|
||||
case "full":
|
||||
if !minimalIsSet && !expandIsSet {
|
||||
// minimal flag takes precedence
|
||||
res.Minimal = false
|
||||
minimalIsSet = true
|
||||
}
|
||||
case "minimal":
|
||||
if !expandIsSet {
|
||||
// expand flag takes precedence
|
||||
res.Minimal = true
|
||||
minimalIsSet = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type shared struct {
|
||||
Spec flags.Filename `long:"spec" short:"f" description:"the spec file to use (default swagger.{json,yml,yaml})"`
|
||||
APIPackage string `long:"api-package" short:"a" description:"the package to save the operations" default:"operations"`
|
||||
ModelPackage string `long:"model-package" short:"m" description:"the package to save the models" default:"models"`
|
||||
ServerPackage string `long:"server-package" short:"s" description:"the package to save the server specific code" default:"restapi"`
|
||||
ClientPackage string `long:"client-package" short:"c" description:"the package to save the client specific code" default:"client"`
|
||||
Target flags.Filename `long:"target" short:"t" default:"./" description:"the base directory for generating the files"`
|
||||
Template string `long:"template" description:"Load contributed templates" choice:"stratoscale"`
|
||||
TemplateDir flags.Filename `long:"template-dir" short:"T" description:"alternative template override directory"`
|
||||
ConfigFile flags.Filename `long:"config-file" short:"C" description:"configuration file to use for overriding template options"`
|
||||
CopyrightFile flags.Filename `long:"copyright-file" short:"r" description:"copyright file used to add copyright header"`
|
||||
ExistingModels string `long:"existing-models" description:"use pre-generated models e.g. github.com/foobar/model"`
|
||||
AdditionalInitialisms []string `long:"additional-initialism" description:"consecutive capitals that should be considered intialisms"`
|
||||
AllowTemplateOverride bool `long:"allow-template-override" description:"allows overriding protected templates"`
|
||||
FlattenCmdOptions
|
||||
}
|
||||
|
||||
type sharedCommand interface {
|
||||
getOpts() (*generator.GenOpts, error)
|
||||
getShared() *shared
|
||||
getConfigFile() flags.Filename
|
||||
getAdditionalInitialisms() []string
|
||||
apply(*generator.GenOpts)
|
||||
getConfigFile() string
|
||||
generate(*generator.GenOpts) error
|
||||
log(string)
|
||||
}
|
||||
|
||||
func (s *shared) getConfigFile() flags.Filename {
|
||||
return s.ConfigFile
|
||||
type schemeOptions struct {
|
||||
Principal string `short:"P" long:"principal" description:"the model to use for the security principal"`
|
||||
DefaultScheme string `long:"default-scheme" description:"the default scheme for this API" default:"http"`
|
||||
}
|
||||
|
||||
func (s *shared) getAdditionalInitialisms() []string {
|
||||
return s.AdditionalInitialisms
|
||||
func (so schemeOptions) apply(opts *generator.GenOpts) {
|
||||
opts.Principal = so.Principal
|
||||
opts.DefaultScheme = so.DefaultScheme
|
||||
}
|
||||
|
||||
func (s *shared) setCopyright() (string, error) {
|
||||
var copyrightstr string
|
||||
copyrightfile := string(s.CopyrightFile)
|
||||
if copyrightfile != "" {
|
||||
//Read the Copyright from file path in opts
|
||||
bytebuffer, err := ioutil.ReadFile(copyrightfile)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
copyrightstr = string(bytebuffer)
|
||||
} else {
|
||||
copyrightstr = ""
|
||||
type mediaOptions struct {
|
||||
DefaultProduces string `long:"default-produces" description:"the default mime type that API operations produce" default:"application/json"`
|
||||
DefaultConsumes string `long:"default-consumes" description:"the default mime type that API operations consume" default:"application/json"`
|
||||
}
|
||||
|
||||
func (m mediaOptions) apply(opts *generator.GenOpts) {
|
||||
opts.DefaultProduces = m.DefaultProduces
|
||||
opts.DefaultConsumes = m.DefaultConsumes
|
||||
|
||||
const xmlIdentifier = "xml"
|
||||
opts.WithXML = strings.Contains(opts.DefaultProduces, xmlIdentifier) || strings.Contains(opts.DefaultConsumes, xmlIdentifier)
|
||||
}
|
||||
|
||||
// WithShared adds the shared options group
|
||||
type WithShared struct {
|
||||
Shared sharedOptions `group:"Options common to all code generation commands"`
|
||||
}
|
||||
|
||||
func (w WithShared) getConfigFile() string {
|
||||
return string(w.Shared.ConfigFile)
|
||||
}
|
||||
|
||||
type sharedOptions struct {
|
||||
Spec flags.Filename `long:"spec" short:"f" description:"the spec file to use (default swagger.{json,yml,yaml})" group:"shared"`
|
||||
Target flags.Filename `long:"target" short:"t" default:"./" description:"the base directory for generating the files" group:"shared"`
|
||||
Template string `long:"template" description:"load contributed templates" choice:"stratoscale" group:"shared"`
|
||||
TemplateDir flags.Filename `long:"template-dir" short:"T" description:"alternative template override directory" group:"shared"`
|
||||
ConfigFile flags.Filename `long:"config-file" short:"C" description:"configuration file to use for overriding template options" group:"shared"`
|
||||
CopyrightFile flags.Filename `long:"copyright-file" short:"r" description:"copyright file used to add copyright header" group:"shared"`
|
||||
AdditionalInitialisms []string `long:"additional-initialism" description:"consecutive capitals that should be considered intialisms" group:"shared"`
|
||||
AllowTemplateOverride bool `long:"allow-template-override" description:"allows overriding protected templates" group:"shared"`
|
||||
SkipValidation bool `long:"skip-validation" description:"skips validation of spec prior to generation" group:"shared"`
|
||||
DumpData bool `long:"dump-data" description:"when present dumps the json for the template generator instead of generating files" group:"shared"`
|
||||
StrictResponders bool `long:"strict-responders" description:"Use strict type for the handler return value"`
|
||||
FlattenCmdOptions
|
||||
}
|
||||
|
||||
func (s sharedOptions) apply(opts *generator.GenOpts) {
|
||||
opts.Spec = string(s.Spec)
|
||||
opts.Target = string(s.Target)
|
||||
opts.Template = s.Template
|
||||
opts.TemplateDir = string(s.TemplateDir)
|
||||
opts.AllowTemplateOverride = s.AllowTemplateOverride
|
||||
opts.ValidateSpec = !s.SkipValidation
|
||||
opts.DumpData = s.DumpData
|
||||
opts.FlattenOpts = s.FlattenCmdOptions.SetFlattenOptions(opts.FlattenOpts)
|
||||
opts.Copyright = string(s.CopyrightFile)
|
||||
opts.StrictResponders = s.StrictResponders
|
||||
|
||||
swag.AddInitialisms(s.AdditionalInitialisms...)
|
||||
}
|
||||
|
||||
func setCopyright(copyrightFile string) (string, error) {
|
||||
// read the Copyright from file path in opts
|
||||
if copyrightFile == "" {
|
||||
return "", nil
|
||||
}
|
||||
return copyrightstr, nil
|
||||
bytebuffer, err := ioutil.ReadFile(copyrightFile)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(bytebuffer), nil
|
||||
}
|
||||
|
||||
func createSwagger(s sharedCommand) error {
|
||||
cfg, erc := readConfig(string(s.getConfigFile()))
|
||||
if erc != nil {
|
||||
return erc
|
||||
cfg, err := readConfig(s.getConfigFile())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
setDebug(cfg)
|
||||
setDebug(cfg) // viper config Debug
|
||||
|
||||
opts, ero := s.getOpts()
|
||||
if ero != nil {
|
||||
return ero
|
||||
opts := new(generator.GenOpts)
|
||||
s.apply(opts)
|
||||
|
||||
opts.Copyright, err = setCopyright(opts.Copyright)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not load copyright file: %v", err)
|
||||
}
|
||||
|
||||
if opts.Template != "" {
|
||||
contribOptionsOverride(opts)
|
||||
}
|
||||
|
||||
if err := opts.EnsureDefaults(); err != nil {
|
||||
if err = opts.EnsureDefaults(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := configureOptsFromConfig(cfg, opts); err != nil {
|
||||
if err = configureOptsFromConfig(cfg, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
swag.AddInitialisms(s.getAdditionalInitialisms()...)
|
||||
|
||||
if sharedOpts := s.getShared(); sharedOpts != nil {
|
||||
// process shared options
|
||||
opts.FlattenOpts = sharedOpts.FlattenCmdOptions.SetFlattenOptions(opts.FlattenOpts)
|
||||
|
||||
copyrightStr, erc := sharedOpts.setCopyright()
|
||||
if erc != nil {
|
||||
return erc
|
||||
}
|
||||
opts.Copyright = copyrightStr
|
||||
}
|
||||
|
||||
if err := s.generate(opts); err != nil {
|
||||
if err = s.generate(opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
basepath, era := filepath.Abs(".")
|
||||
if era != nil {
|
||||
return era
|
||||
basepath, err := filepath.Abs(".")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
targetAbs, err := filepath.Abs(opts.Target)
|
||||
|
@ -204,11 +227,12 @@ func configureOptsFromConfig(cfg *viper.Viper, opts *generator.GenOpts) error {
|
|||
}
|
||||
|
||||
func setDebug(cfg *viper.Viper) {
|
||||
// viper config debug
|
||||
if os.Getenv("DEBUG") != "" || os.Getenv("SWAGGER_DEBUG") != "" {
|
||||
if cfg != nil {
|
||||
cfg.Debug()
|
||||
} else {
|
||||
log.Println("NO config read")
|
||||
log.Println("No config read")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
2
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/spec_go111.go
generated
vendored
2
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/spec_go111.go
generated
vendored
|
@ -94,7 +94,7 @@ func writeToFile(swspec *spec.Swagger, pretty bool, output string) error {
|
|||
fmt.Println(string(b))
|
||||
return nil
|
||||
}
|
||||
return ioutil.WriteFile(output, b, 0644)
|
||||
return ioutil.WriteFile(output, b, 0644) // #nosec
|
||||
}
|
||||
|
||||
func marshalToJSONFormat(swspec *spec.Swagger, pretty bool) ([]byte, error) {
|
||||
|
|
47
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/support.go
generated
vendored
47
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/support.go
generated
vendored
|
@ -22,40 +22,33 @@ import (
|
|||
|
||||
// Support generates the supporting files
|
||||
type Support struct {
|
||||
shared
|
||||
Name string `long:"name" short:"A" description:"the name of the application, defaults to a mangled value of info.title"`
|
||||
Operations []string `long:"operation" short:"O" description:"specify an operation to include, repeat for multiple"`
|
||||
Principal string `long:"principal" description:"the model to use for the security principal"`
|
||||
Models []string `long:"model" short:"M" description:"specify a model to include, repeat for multiple"`
|
||||
DumpData bool `long:"dump-data" description:"when present dumps the json for the template generator instead of generating files"`
|
||||
DefaultScheme string `long:"default-scheme" description:"the default scheme for this API" default:"http"`
|
||||
WithShared
|
||||
WithModels
|
||||
WithOperations
|
||||
|
||||
clientOptions
|
||||
serverOptions
|
||||
schemeOptions
|
||||
mediaOptions
|
||||
|
||||
Name string `long:"name" short:"A" description:"the name of the application, defaults to a mangled value of info.title"`
|
||||
}
|
||||
|
||||
func (s *Support) getOpts() (*generator.GenOpts, error) {
|
||||
return &generator.GenOpts{
|
||||
Spec: string(s.Spec),
|
||||
Target: string(s.Target),
|
||||
APIPackage: s.APIPackage,
|
||||
ModelPackage: s.ModelPackage,
|
||||
ServerPackage: s.ServerPackage,
|
||||
ClientPackage: s.ClientPackage,
|
||||
Principal: s.Principal,
|
||||
DumpData: s.DumpData,
|
||||
DefaultScheme: s.DefaultScheme,
|
||||
Template: s.Template,
|
||||
TemplateDir: string(s.TemplateDir),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Support) getShared() *shared {
|
||||
return &s.shared
|
||||
func (s *Support) apply(opts *generator.GenOpts) {
|
||||
s.Shared.apply(opts)
|
||||
s.Models.apply(opts)
|
||||
s.Operations.apply(opts)
|
||||
s.clientOptions.apply(opts)
|
||||
s.serverOptions.apply(opts)
|
||||
s.schemeOptions.apply(opts)
|
||||
s.mediaOptions.apply(opts)
|
||||
}
|
||||
|
||||
func (s *Support) generate(opts *generator.GenOpts) error {
|
||||
return generator.GenerateSupport(s.Name, nil, nil, opts)
|
||||
return generator.GenerateSupport(s.Name, s.Models.Models, s.Operations.Operations, opts)
|
||||
}
|
||||
|
||||
func (s *Support) log(rp string) {
|
||||
func (s Support) log(rp string) {
|
||||
|
||||
log.Printf(`Generation completed!
|
||||
|
||||
|
|
2
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/mixin.go
generated
vendored
2
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/mixin.go
generated
vendored
|
@ -16,7 +16,7 @@ import (
|
|||
|
||||
const (
|
||||
// Output messages
|
||||
nothingToDo = "Nothing to do. Need some swagger files to merge.\nUSAGE: swagger mixin [-c <expected#Collisions>] <primary-swagger-file> <mixin-swagger-file>..."
|
||||
nothingToDo = "nothing to do. Need some swagger files to merge.\nUSAGE: swagger mixin [-c <expected#Collisions>] <primary-swagger-file> <mixin-swagger-file...>"
|
||||
)
|
||||
|
||||
// MixinSpec holds command line flag definitions specific to the mixin
|
||||
|
|
21
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/serve.go
generated
vendored
21
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/serve.go
generated
vendored
|
@ -4,16 +4,15 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/go-openapi/spec"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/toqueteos/webbrowser"
|
||||
|
@ -43,7 +42,6 @@ func (s *ServeCmd) Execute(args []string) error {
|
|||
}
|
||||
|
||||
if s.Flatten {
|
||||
var err error
|
||||
specDoc, err = specDoc.Expanded(&spec.ExpandOptions{
|
||||
SkipSchemas: false,
|
||||
ContinueOnError: true,
|
||||
|
@ -88,17 +86,12 @@ func (s *ServeCmd) Execute(args []string) error {
|
|||
}, handler)
|
||||
visit = fmt.Sprintf("http://%s:%d%s", sh, sp, path.Join(basePath, "docs"))
|
||||
} else if visit != "" || s.Flavor == "swagger" {
|
||||
if visit == "" {
|
||||
visit = "http://petstore.swagger.io/"
|
||||
}
|
||||
u, err := url.Parse(visit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
q := u.Query()
|
||||
q.Add("url", fmt.Sprintf("http://%s:%d%s", sh, sp, path.Join(basePath, "swagger.json")))
|
||||
u.RawQuery = q.Encode()
|
||||
visit = u.String()
|
||||
handler = middleware.SwaggerUI(middleware.SwaggerUIOpts{
|
||||
BasePath: basePath,
|
||||
SpecURL: path.Join(basePath, "swagger.json"),
|
||||
Path: "docs",
|
||||
}, handler)
|
||||
visit = fmt.Sprintf("http://%s:%d%s", sh, sp, path.Join(basePath, "docs"))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/validate.go
generated
vendored
2
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/validate.go
generated
vendored
|
@ -26,7 +26,7 @@ import (
|
|||
|
||||
const (
|
||||
// Output messages
|
||||
missingArgMsg = "The validate command requires the swagger document url to be specified"
|
||||
missingArgMsg = "the validate command requires the swagger document url to be specified"
|
||||
validSpecMsg = "\nThe swagger spec at %q is valid against swagger specification %s\n"
|
||||
invalidSpecMsg = "\nThe swagger spec at %q is invalid against swagger specification %s.\nSee errors below:\n"
|
||||
warningSpecMsg = "\nThe swagger spec at %q showed up some valid but possibly unwanted constructs."
|
||||
|
|
5
vendor/github.com/go-swagger/go-swagger/cmd/swagger/swagger.go
generated
vendored
5
vendor/github.com/go-swagger/go-swagger/cmd/swagger/swagger.go
generated
vendored
|
@ -29,11 +29,6 @@ func init() {
|
|||
loads.AddLoader(fmts.YAMLMatcher, fmts.YAMLDoc)
|
||||
}
|
||||
|
||||
var (
|
||||
// Debug is true when the SWAGGER_DEBUG env var is not empty
|
||||
Debug = os.Getenv("SWAGGER_DEBUG") != ""
|
||||
)
|
||||
|
||||
var opts struct {
|
||||
// General options applicable to all commands
|
||||
Quiet func() `long:"quiet" short:"q" description:"silence logs"`
|
||||
|
|
51
vendor/github.com/go-swagger/go-swagger/codescan/application.go
generated
vendored
51
vendor/github.com/go-swagger/go-swagger/codescan/application.go
generated
vendored
|
@ -3,6 +3,7 @@ package codescan
|
|||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
|
@ -290,7 +291,7 @@ func (s *scanCtx) FindModel(pkgPath, name string) (*entityDecl, bool) {
|
|||
}
|
||||
}
|
||||
if decl, found := s.FindDecl(pkgPath, name); found {
|
||||
s.app.Models[decl.Ident] = decl
|
||||
s.app.ExtraModels[decl.Ident] = decl
|
||||
return decl, true
|
||||
}
|
||||
return nil, false
|
||||
|
@ -352,6 +353,36 @@ func (s *scanCtx) FindComments(pkg *packages.Package, name string) (*ast.Comment
|
|||
return nil, false
|
||||
}
|
||||
|
||||
func (s *scanCtx) FindEnumValues(pkg *packages.Package, enumName string) (list []interface{}, _ bool) {
|
||||
for _, f := range pkg.Syntax {
|
||||
for _, d := range f.Decls {
|
||||
gd, ok := d.(*ast.GenDecl)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if gd.Tok != token.CONST {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, s := range gd.Specs {
|
||||
if vs, ok := s.(*ast.ValueSpec); ok {
|
||||
if vsIdent, ok := vs.Type.(*ast.Ident); ok {
|
||||
if vsIdent.Name == enumName {
|
||||
if len(vs.Values) > 0 {
|
||||
if bl, ok := vs.Values[0].(*ast.BasicLit); ok {
|
||||
list = append(list, getEnumBasicLitValue(bl))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list, true
|
||||
}
|
||||
|
||||
func newTypeIndex(pkgs []*packages.Package,
|
||||
excludeDeps bool, includeTags, excludeTags map[string]bool,
|
||||
includePkgs, excludePkgs []string) (*typeIndex, error) {
|
||||
|
@ -359,6 +390,7 @@ func newTypeIndex(pkgs []*packages.Package,
|
|||
ac := &typeIndex{
|
||||
AllPackages: make(map[string]*packages.Package),
|
||||
Models: make(map[*ast.Ident]*entityDecl),
|
||||
ExtraModels: make(map[*ast.Ident]*entityDecl),
|
||||
excludeDeps: excludeDeps,
|
||||
includeTags: includeTags,
|
||||
excludeTags: excludeTags,
|
||||
|
@ -374,6 +406,7 @@ func newTypeIndex(pkgs []*packages.Package,
|
|||
type typeIndex struct {
|
||||
AllPackages map[string]*packages.Package
|
||||
Models map[*ast.Ident]*entityDecl
|
||||
ExtraModels map[*ast.Ident]*entityDecl
|
||||
Meta []metaSection
|
||||
Routes []parsedPathContent
|
||||
Operations []parsedPathContent
|
||||
|
@ -483,12 +516,12 @@ func (a *typeIndex) processDecl(pkg *packages.Package, file *ast.File, n node, g
|
|||
def, ok := pkg.TypesInfo.Defs[ts.Name]
|
||||
if !ok {
|
||||
debugLog("couldn't find type info for %s", ts.Name)
|
||||
//continue
|
||||
continue
|
||||
}
|
||||
nt, isNamed := def.Type().(*types.Named)
|
||||
if !isNamed {
|
||||
debugLog("%s is not a named type but a %T", ts.Name, def.Type())
|
||||
//continue
|
||||
continue
|
||||
}
|
||||
decl := &entityDecl{
|
||||
Comments: gd.Doc,
|
||||
|
@ -516,16 +549,16 @@ func (a *typeIndex) walkImports(pkg *packages.Package) error {
|
|||
if a.excludeDeps {
|
||||
return nil
|
||||
}
|
||||
for k := range pkg.Imports {
|
||||
if _, known := a.AllPackages[k]; known {
|
||||
for _, v := range pkg.Imports {
|
||||
if _, known := a.AllPackages[v.PkgPath]; known {
|
||||
continue
|
||||
}
|
||||
pk := pkg.Imports[k]
|
||||
a.AllPackages[pk.PkgPath] = pk
|
||||
if err := a.processPackage(pk); err != nil {
|
||||
|
||||
a.AllPackages[v.PkgPath] = v
|
||||
if err := a.processPackage(v); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := a.walkImports(pk); err != nil {
|
||||
if err := a.walkImports(v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
23
vendor/github.com/go-swagger/go-swagger/codescan/enum.go
generated
vendored
Normal file
23
vendor/github.com/go-swagger/go-swagger/codescan/enum.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
package codescan
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func getEnumBasicLitValue(basicLit *ast.BasicLit) interface{} {
|
||||
switch basicLit.Kind.String() {
|
||||
case "INT":
|
||||
if result, err := strconv.ParseInt(basicLit.Value, 10, 64); err == nil {
|
||||
return result
|
||||
}
|
||||
case "FLOAT":
|
||||
if result, err := strconv.ParseFloat(basicLit.Value, 64); err == nil {
|
||||
return result
|
||||
}
|
||||
default:
|
||||
return strings.Trim(basicLit.Value, "\"")
|
||||
}
|
||||
return nil
|
||||
}
|
13
vendor/github.com/go-swagger/go-swagger/codescan/meta.go
generated
vendored
13
vendor/github.com/go-swagger/go-swagger/codescan/meta.go
generated
vendored
|
@ -201,9 +201,10 @@ func parseContactInfo(line string) (*spec.ContactInfo, error) {
|
|||
name, email = addr.Name, addr.Address
|
||||
}
|
||||
return &spec.ContactInfo{
|
||||
URL: url,
|
||||
Name: name,
|
||||
Email: email,
|
||||
ContactInfoProps: spec.ContactInfoProps{
|
||||
URL: url,
|
||||
Name: name,
|
||||
Email: email,},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -215,8 +216,10 @@ func setInfoLicense(swspec *spec.Swagger, lines []string) error {
|
|||
line := lines[0]
|
||||
name, url := splitURL(line)
|
||||
info.License = &spec.License{
|
||||
Name: name,
|
||||
URL: url,
|
||||
LicenseProps: spec.LicenseProps{
|
||||
Name: name,
|
||||
URL: url,
|
||||
},
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
13
vendor/github.com/go-swagger/go-swagger/codescan/parameters.go
generated
vendored
13
vendor/github.com/go-swagger/go-swagger/codescan/parameters.go
generated
vendored
|
@ -59,6 +59,10 @@ func (pt paramTypable) AddExtension(key string, value interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
func (pt paramTypable) WithEnum(values ...interface{}) {
|
||||
pt.param.WithEnum(values...)
|
||||
}
|
||||
|
||||
type itemsTypable struct {
|
||||
items *spec.Items
|
||||
level int
|
||||
|
@ -90,6 +94,10 @@ func (pt itemsTypable) AddExtension(key string, value interface{}) {
|
|||
pt.items.AddExtension(key, value)
|
||||
}
|
||||
|
||||
func (pt itemsTypable) WithEnum(values ...interface{}) {
|
||||
pt.items.WithEnum(values...)
|
||||
}
|
||||
|
||||
type paramValidations struct {
|
||||
current *spec.Parameter
|
||||
}
|
||||
|
@ -286,6 +294,11 @@ func (p *parameterBuilder) buildFromStruct(decl *entityDecl, tpe *types.Struct,
|
|||
continue
|
||||
}
|
||||
|
||||
if !fld.Exported() {
|
||||
debugLog("skipping field %s because it's not exported", fld.Name())
|
||||
continue
|
||||
}
|
||||
|
||||
tg := tpe.Tag(i)
|
||||
|
||||
var afld *ast.Field
|
||||
|
|
1
vendor/github.com/go-swagger/go-swagger/codescan/parser.go
generated
vendored
1
vendor/github.com/go-swagger/go-swagger/codescan/parser.go
generated
vendored
|
@ -200,6 +200,7 @@ type swaggerTypable interface {
|
|||
Schema() *spec.Schema
|
||||
Level() int
|
||||
AddExtension(key string, value interface{})
|
||||
WithEnum(...interface{})
|
||||
}
|
||||
|
||||
// Map all Go builtin types that have Json representation to Swagger/Json types.
|
||||
|
|
7
vendor/github.com/go-swagger/go-swagger/codescan/responses.go
generated
vendored
7
vendor/github.com/go-swagger/go-swagger/codescan/responses.go
generated
vendored
|
@ -72,13 +72,19 @@ func (ht responseTypable) Schema() *spec.Schema {
|
|||
func (ht responseTypable) SetSchema(schema *spec.Schema) {
|
||||
ht.response.Schema = schema
|
||||
}
|
||||
|
||||
func (ht responseTypable) CollectionOf(items *spec.Items, format string) {
|
||||
ht.header.CollectionOf(items, format)
|
||||
}
|
||||
|
||||
func (ht responseTypable) AddExtension(key string, value interface{}) {
|
||||
ht.response.AddExtension(key, value)
|
||||
}
|
||||
|
||||
func (ht responseTypable) WithEnum(values ...interface{}) {
|
||||
ht.header.WithEnum(values)
|
||||
}
|
||||
|
||||
type headerValidations struct {
|
||||
current *spec.Header
|
||||
}
|
||||
|
@ -185,6 +191,7 @@ func (r *responseBuilder) buildFromField(fld *types.Var, tpe types.Type, typable
|
|||
if err := sb.buildFromType(ftpe.Elem(), schemaTypable{schema, typable.Level() + 1}); err != nil {
|
||||
return err
|
||||
}
|
||||
r.postDecls = append(r.postDecls, sb.postDecls...)
|
||||
return nil
|
||||
case *types.Named:
|
||||
if decl, found := r.ctx.DeclForType(ftpe.Obj().Type()); found {
|
||||
|
|
53
vendor/github.com/go-swagger/go-swagger/codescan/schema.go
generated
vendored
53
vendor/github.com/go-swagger/go-swagger/codescan/schema.go
generated
vendored
|
@ -65,11 +65,17 @@ func (st schemaTypable) AdditionalProperties() swaggerTypable {
|
|||
st.schema.Typed("object", "")
|
||||
return schemaTypable{st.schema.AdditionalProperties.Schema, st.level + 1}
|
||||
}
|
||||
|
||||
func (st schemaTypable) Level() int { return st.level }
|
||||
|
||||
func (st schemaTypable) AddExtension(key string, value interface{}) {
|
||||
addExtension(&st.schema.VendorExtensible, key, value)
|
||||
}
|
||||
|
||||
func (st schemaTypable) WithEnum(values ...interface{}) {
|
||||
st.schema.WithEnum(values...)
|
||||
}
|
||||
|
||||
type schemaValidations struct {
|
||||
current *spec.Schema
|
||||
}
|
||||
|
@ -182,8 +188,8 @@ func (s *schemaBuilder) buildFromDecl(decl *entityDecl, schema *spec.Schema) err
|
|||
debugLog("map: %v -> [%v]%v", s.decl.Ident.Name, tpe.Key().String(), tpe.Elem().String())
|
||||
case *types.Named:
|
||||
o := tpe.Obj()
|
||||
debugLog("got the named type object: %s.%s | isAlias: %t | exported: %t", o.Pkg().Path(), o.Name(), o.IsAlias(), o.Exported())
|
||||
if o != nil {
|
||||
debugLog("got the named type object: %s.%s | isAlias: %t | exported: %t", o.Pkg().Path(), o.Name(), o.IsAlias(), o.Exported())
|
||||
if o.Pkg().Name() == "time" && o.Name() == "Time" {
|
||||
schema.Typed("string", "date-time")
|
||||
return nil
|
||||
|
@ -263,6 +269,10 @@ func (s *schemaBuilder) buildFromType(tpe types.Type, tgt swaggerTypable) error
|
|||
tgt.Typed("string", "date-time")
|
||||
return nil
|
||||
}
|
||||
if pkg.PkgPath == "encoding/json" && tio.Name() == "RawMessage" {
|
||||
tgt.Typed("object", "")
|
||||
return nil
|
||||
}
|
||||
cmt, hasComments := s.ctx.FindComments(pkg, tio.Name())
|
||||
if !hasComments {
|
||||
cmt = new(ast.CommentGroup)
|
||||
|
@ -298,7 +308,12 @@ func (s *schemaBuilder) buildFromType(tpe types.Type, tgt swaggerTypable) error
|
|||
}
|
||||
|
||||
if enumName, ok := enumName(cmt); ok {
|
||||
debugLog(enumName)
|
||||
enumValues, _ := s.ctx.FindEnumValues(pkg, enumName)
|
||||
if len(enumValues) > 0 {
|
||||
tgt.WithEnum(enumValues...)
|
||||
enumTypeName := reflect.TypeOf(enumValues[0]).String()
|
||||
_ = swaggerSchemaForType(enumTypeName, tgt)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -693,6 +708,11 @@ func (s *schemaBuilder) buildFromStruct(decl *entityDecl, st *types.Struct, sche
|
|||
break
|
||||
}
|
||||
|
||||
if afld == nil {
|
||||
debugLog("can't find source associated with %s", fld.String())
|
||||
continue
|
||||
}
|
||||
|
||||
// if the field is annotated with swagger:ignore, ignore it
|
||||
if ignored(afld.Doc) {
|
||||
continue
|
||||
|
@ -973,6 +993,21 @@ func schemaVendorExtensibleSetter(meta *spec.Schema) func(json.RawMessage) error
|
|||
}
|
||||
}
|
||||
|
||||
type tagOptions []string
|
||||
|
||||
func (t tagOptions) Contain(option string) bool {
|
||||
for i := 1; i < len(t); i++ {
|
||||
if t[i] == option {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (t tagOptions) Name() string {
|
||||
return t[0]
|
||||
}
|
||||
|
||||
func parseJSONTag(field *ast.Field) (name string, ignore bool, isString bool, err error) {
|
||||
if len(field.Names) > 0 {
|
||||
name = field.Names[0].Name
|
||||
|
@ -988,19 +1023,21 @@ func parseJSONTag(field *ast.Field) (name string, ignore bool, isString bool, er
|
|||
|
||||
if strings.TrimSpace(tv) != "" {
|
||||
st := reflect.StructTag(tv)
|
||||
jsonParts := strings.Split(st.Get("json"), ",")
|
||||
jsonName := jsonParts[0]
|
||||
jsonParts := tagOptions(strings.Split(st.Get("json"), ","))
|
||||
|
||||
if len(jsonParts) > 1 && jsonParts[1] == "string" {
|
||||
if jsonParts.Contain("string") {
|
||||
// Need to check if the field type is a scalar. Otherwise, the
|
||||
// ",string" directive doesn't apply.
|
||||
isString = isFieldStringable(field.Type)
|
||||
}
|
||||
|
||||
if jsonName == "-" {
|
||||
switch jsonParts.Name() {
|
||||
case "-":
|
||||
return name, true, isString, nil
|
||||
} else if jsonName != "" {
|
||||
return jsonName, false, isString, nil
|
||||
case "":
|
||||
return name, false, isString, nil
|
||||
default:
|
||||
return jsonParts.Name(), false, isString, nil
|
||||
}
|
||||
}
|
||||
return name, false, false, nil
|
||||
|
|
26
vendor/github.com/go-swagger/go-swagger/codescan/spec.go
generated
vendored
26
vendor/github.com/go-swagger/go-swagger/codescan/spec.go
generated
vendored
|
@ -1,6 +1,8 @@
|
|||
package codescan
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
|
@ -193,11 +195,35 @@ func (s *specBuilder) buildModels() error {
|
|||
if !s.scanModels {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, decl := range s.ctx.app.Models {
|
||||
if err := s.buildDiscoveredSchema(decl); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return s.joinExtraModels()
|
||||
}
|
||||
|
||||
func (s *specBuilder) joinExtraModels() error {
|
||||
tmp := make(map[*ast.Ident]*entityDecl, len(s.ctx.app.ExtraModels))
|
||||
for k, v := range s.ctx.app.ExtraModels {
|
||||
tmp[k] = v
|
||||
s.ctx.app.Models[k] = v
|
||||
delete(s.ctx.app.ExtraModels, k)
|
||||
}
|
||||
|
||||
// process extra models and see if there is any reference to a new extra one
|
||||
for _, decl := range tmp {
|
||||
if err := s.buildDiscoveredSchema(decl); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(s.ctx.app.ExtraModels) > 0 {
|
||||
return s.joinExtraModels()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
627
vendor/github.com/go-swagger/go-swagger/generator/bindata.go
generated
vendored
627
vendor/github.com/go-swagger/go-swagger/generator/bindata.go
generated
vendored
File diff suppressed because one or more lines are too long
130
vendor/github.com/go-swagger/go-swagger/generator/client.go
generated
vendored
130
vendor/github.com/go-swagger/go-swagger/generator/client.go
generated
vendored
|
@ -15,102 +15,54 @@
|
|||
package generator
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// GenerateClient generates a client library for a swagger spec document.
|
||||
func GenerateClient(name string, modelNames, operationIDs []string, opts *GenOpts) error {
|
||||
templates.LoadDefaults()
|
||||
if opts == nil {
|
||||
return errors.New("gen opts are required")
|
||||
}
|
||||
|
||||
if opts.Template != "" {
|
||||
if err := templates.LoadContrib(opts.Template); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
templates.SetAllowOverride(opts.AllowTemplateOverride)
|
||||
|
||||
if opts.TemplateDir != "" {
|
||||
if err := templates.LoadDir(opts.TemplateDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := opts.CheckOpts(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Load the spec
|
||||
_, specDoc, err := loadSpec(opts.Spec)
|
||||
if err != nil {
|
||||
if err := opts.setTemplates(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate and Expand. specDoc is in/out param.
|
||||
specDoc, err = validateAndFlattenSpec(opts, specDoc)
|
||||
specDoc, analyzed, err := opts.analyzeSpec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
analyzed := analysis.New(specDoc.Spec())
|
||||
|
||||
models, err := gatherModels(specDoc, modelNames)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
operations := gatherOperations(analyzed, operationIDs)
|
||||
|
||||
if len(operations) == 0 {
|
||||
return errors.New("no operations were selected")
|
||||
}
|
||||
|
||||
defaultScheme := opts.DefaultScheme
|
||||
if defaultScheme == "" {
|
||||
defaultScheme = sHTTP
|
||||
}
|
||||
|
||||
defaultConsumes := opts.DefaultConsumes
|
||||
if defaultConsumes == "" {
|
||||
defaultConsumes = runtime.JSONMime
|
||||
}
|
||||
|
||||
defaultProduces := opts.DefaultProduces
|
||||
if defaultProduces == "" {
|
||||
defaultProduces = runtime.JSONMime
|
||||
}
|
||||
|
||||
generator := appGenerator{
|
||||
Name: appNameOrDefault(specDoc, name, "rest"),
|
||||
Name: appNameOrDefault(specDoc, name, defaultClientName),
|
||||
SpecDoc: specDoc,
|
||||
Analyzed: analyzed,
|
||||
Models: models,
|
||||
Operations: operations,
|
||||
Target: opts.Target,
|
||||
DumpData: opts.DumpData,
|
||||
Package: opts.LanguageOpts.ManglePackageName(opts.ClientPackage, "client"),
|
||||
APIPackage: opts.LanguageOpts.ManglePackagePath(opts.APIPackage, "api"),
|
||||
ModelsPackage: opts.LanguageOpts.ManglePackagePath(opts.ModelPackage, "definitions"),
|
||||
ServerPackage: opts.LanguageOpts.ManglePackagePath(opts.ServerPackage, "server"),
|
||||
ClientPackage: opts.LanguageOpts.ManglePackagePath(opts.ClientPackage, "client"),
|
||||
OperationsPackage: opts.LanguageOpts.ManglePackagePath(opts.ClientPackage, "client"),
|
||||
Principal: opts.Principal,
|
||||
DefaultScheme: defaultScheme,
|
||||
DefaultProduces: defaultProduces,
|
||||
DefaultConsumes: defaultConsumes,
|
||||
Package: opts.LanguageOpts.ManglePackageName(opts.ClientPackage, defaultClientTarget),
|
||||
APIPackage: opts.LanguageOpts.ManglePackagePath(opts.APIPackage, defaultOperationsTarget),
|
||||
ModelsPackage: opts.LanguageOpts.ManglePackagePath(opts.ModelPackage, defaultModelsTarget),
|
||||
ServerPackage: opts.LanguageOpts.ManglePackagePath(opts.ServerPackage, defaultServerTarget),
|
||||
ClientPackage: opts.LanguageOpts.ManglePackagePath(opts.ClientPackage, defaultClientTarget),
|
||||
OperationsPackage: opts.LanguageOpts.ManglePackagePath(opts.ClientPackage, defaultClientTarget),
|
||||
Principal: opts.PrincipalAlias(),
|
||||
DefaultScheme: opts.DefaultScheme,
|
||||
DefaultProduces: opts.DefaultProduces,
|
||||
DefaultConsumes: opts.DefaultConsumes,
|
||||
GenOpts: opts,
|
||||
}
|
||||
generator.Receiver = "o"
|
||||
|
@ -123,69 +75,33 @@ type clientGenerator struct {
|
|||
|
||||
func (c *clientGenerator) Generate() error {
|
||||
app, err := c.makeCodegenApp()
|
||||
if app.Name == "" {
|
||||
app.Name = "APIClient"
|
||||
}
|
||||
baseImport := c.GenOpts.LanguageOpts.baseImport(c.Target)
|
||||
|
||||
if c.GenOpts.ExistingModels == "" {
|
||||
if app.Imports == nil {
|
||||
app.Imports = make(map[string]string)
|
||||
}
|
||||
pkgAlias := c.GenOpts.LanguageOpts.ManglePackageName(c.ModelsPackage, "models")
|
||||
app.Imports[pkgAlias] = path.Join(
|
||||
filepath.ToSlash(baseImport),
|
||||
c.GenOpts.LanguageOpts.ManglePackagePath(c.GenOpts.ModelPackage, "models"))
|
||||
} else {
|
||||
app.DefaultImports = append(app.DefaultImports, c.GenOpts.LanguageOpts.ManglePackagePath(c.GenOpts.ExistingModels, ""))
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.DumpData {
|
||||
bb, _ := json.MarshalIndent(swag.ToDynamicJSON(app), "", " ")
|
||||
fmt.Fprintln(os.Stdout, string(bb))
|
||||
return nil
|
||||
return dumpData(swag.ToDynamicJSON(app))
|
||||
}
|
||||
|
||||
if c.GenOpts.IncludeModel {
|
||||
for _, mod := range app.Models {
|
||||
modCopy := mod
|
||||
modCopy.IncludeValidator = true
|
||||
if !mod.IsStream {
|
||||
if err := c.GenOpts.renderDefinition(&modCopy); err != nil {
|
||||
return err
|
||||
}
|
||||
if mod.IsStream {
|
||||
continue
|
||||
}
|
||||
if err := c.GenOpts.renderDefinition(&mod); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if c.GenOpts.IncludeHandler {
|
||||
sort.Sort(app.OperationGroups)
|
||||
for i := range app.OperationGroups {
|
||||
opGroup := app.OperationGroups[i]
|
||||
opGroup.DefaultImports = app.DefaultImports
|
||||
opGroup.RootPackage = c.ClientPackage
|
||||
opGroup.GenOpts = c.GenOpts
|
||||
app.OperationGroups[i] = opGroup
|
||||
sort.Sort(opGroup.Operations)
|
||||
for _, op := range opGroup.Operations {
|
||||
opCopy := op
|
||||
if opCopy.Package == "" {
|
||||
opCopy.Package = c.Package
|
||||
}
|
||||
if err := c.GenOpts.renderOperation(&opCopy); err != nil {
|
||||
for _, opg := range app.OperationGroups {
|
||||
for _, op := range opg.Operations {
|
||||
if err := c.GenOpts.renderOperation(&op); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
app.DefaultImports = append(app.DefaultImports,
|
||||
path.Join(
|
||||
filepath.ToSlash(baseImport),
|
||||
c.GenOpts.LanguageOpts.ManglePackagePath(c.ClientPackage, "client"),
|
||||
opGroup.Name))
|
||||
|
||||
if err := c.GenOpts.renderOperationGroup(&opGroup); err != nil {
|
||||
if err := c.GenOpts.renderOperationGroup(&opg); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
4
vendor/github.com/go-swagger/go-swagger/generator/debug.go
generated
vendored
4
vendor/github.com/go-swagger/go-swagger/generator/debug.go
generated
vendored
|
@ -31,10 +31,6 @@ var (
|
|||
generatorLogger *log.Logger
|
||||
)
|
||||
|
||||
func init() {
|
||||
debugOptions()
|
||||
}
|
||||
|
||||
func debugOptions() {
|
||||
generatorLogger = log.New(os.Stdout, "generator:", log.LstdFlags)
|
||||
}
|
||||
|
|
433
vendor/github.com/go-swagger/go-swagger/generator/language.go
generated
vendored
Normal file
433
vendor/github.com/go-swagger/go-swagger/generator/language.go
generated
vendored
Normal file
|
@ -0,0 +1,433 @@
|
|||
package generator
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
goruntime "runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"golang.org/x/tools/imports"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultLanguageFunc defines the default generation language
|
||||
DefaultLanguageFunc func() *LanguageOpts
|
||||
|
||||
moduleRe *regexp.Regexp
|
||||
)
|
||||
|
||||
func initLanguage() {
|
||||
DefaultLanguageFunc = GoLangOpts
|
||||
|
||||
moduleRe = regexp.MustCompile(`module[ \t]+([^\s]+)`)
|
||||
}
|
||||
|
||||
// LanguageOpts to describe a language to the code generator
|
||||
type LanguageOpts struct {
|
||||
ReservedWords []string
|
||||
BaseImportFunc func(string) string `json:"-"`
|
||||
ImportsFunc func(map[string]string) string `json:"-"`
|
||||
ArrayInitializerFunc func(interface{}) (string, error) `json:"-"`
|
||||
reservedWordsSet map[string]struct{}
|
||||
initialized bool
|
||||
formatFunc func(string, []byte) ([]byte, error)
|
||||
fileNameFunc func(string) string // language specific source file naming rules
|
||||
dirNameFunc func(string) string // language specific directory naming rules
|
||||
}
|
||||
|
||||
// Init the language option
|
||||
func (l *LanguageOpts) Init() {
|
||||
if l.initialized {
|
||||
return
|
||||
}
|
||||
l.initialized = true
|
||||
l.reservedWordsSet = make(map[string]struct{})
|
||||
for _, rw := range l.ReservedWords {
|
||||
l.reservedWordsSet[rw] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// MangleName makes sure a reserved word gets a safe name
|
||||
func (l *LanguageOpts) MangleName(name, suffix string) string {
|
||||
if _, ok := l.reservedWordsSet[swag.ToFileName(name)]; !ok {
|
||||
return name
|
||||
}
|
||||
return strings.Join([]string{name, suffix}, "_")
|
||||
}
|
||||
|
||||
// MangleVarName makes sure a reserved word gets a safe name
|
||||
func (l *LanguageOpts) MangleVarName(name string) string {
|
||||
nm := swag.ToVarName(name)
|
||||
if _, ok := l.reservedWordsSet[nm]; !ok {
|
||||
return nm
|
||||
}
|
||||
return nm + "Var"
|
||||
}
|
||||
|
||||
// MangleFileName makes sure a file name gets a safe name
|
||||
func (l *LanguageOpts) MangleFileName(name string) string {
|
||||
if l.fileNameFunc != nil {
|
||||
return l.fileNameFunc(name)
|
||||
}
|
||||
return swag.ToFileName(name)
|
||||
}
|
||||
|
||||
// ManglePackageName makes sure a package gets a safe name.
|
||||
// In case of a file system path (e.g. name contains "/" or "\" on Windows), this return only the last element.
|
||||
func (l *LanguageOpts) ManglePackageName(name, suffix string) string {
|
||||
if name == "" {
|
||||
return suffix
|
||||
}
|
||||
if l.dirNameFunc != nil {
|
||||
name = l.dirNameFunc(name)
|
||||
}
|
||||
pth := filepath.ToSlash(filepath.Clean(name)) // preserve path
|
||||
pkg := importAlias(pth) // drop path
|
||||
return l.MangleName(swag.ToFileName(prefixForName(pkg)+pkg), suffix)
|
||||
}
|
||||
|
||||
// ManglePackagePath makes sure a full package path gets a safe name.
|
||||
// Only the last part of the path is altered.
|
||||
func (l *LanguageOpts) ManglePackagePath(name string, suffix string) string {
|
||||
if name == "" {
|
||||
return suffix
|
||||
}
|
||||
target := filepath.ToSlash(filepath.Clean(name)) // preserve path
|
||||
parts := strings.Split(target, "/")
|
||||
parts[len(parts)-1] = l.ManglePackageName(parts[len(parts)-1], suffix)
|
||||
return strings.Join(parts, "/")
|
||||
}
|
||||
|
||||
// FormatContent formats a file with a language specific formatter
|
||||
func (l *LanguageOpts) FormatContent(name string, content []byte) ([]byte, error) {
|
||||
if l.formatFunc != nil {
|
||||
return l.formatFunc(name, content)
|
||||
}
|
||||
return content, nil
|
||||
}
|
||||
|
||||
// imports generate the code to import some external packages, possibly aliased
|
||||
func (l *LanguageOpts) imports(imports map[string]string) string {
|
||||
if l.ImportsFunc != nil {
|
||||
return l.ImportsFunc(imports)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// arrayInitializer builds a litteral array
|
||||
func (l *LanguageOpts) arrayInitializer(data interface{}) (string, error) {
|
||||
if l.ArrayInitializerFunc != nil {
|
||||
return l.ArrayInitializerFunc(data)
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// baseImport figures out the base path to generate import statements
|
||||
func (l *LanguageOpts) baseImport(tgt string) string {
|
||||
if l.BaseImportFunc != nil {
|
||||
return l.BaseImportFunc(tgt)
|
||||
}
|
||||
debugLog("base import func is nil")
|
||||
return ""
|
||||
}
|
||||
|
||||
// GoLangOpts for rendering items as golang code
|
||||
func GoLangOpts() *LanguageOpts {
|
||||
var goOtherReservedSuffixes = map[string]bool{
|
||||
// see:
|
||||
// https://golang.org/src/go/build/syslist.go
|
||||
// https://golang.org/doc/install/source#environment
|
||||
|
||||
// goos
|
||||
"aix": true,
|
||||
"android": true,
|
||||
"darwin": true,
|
||||
"dragonfly": true,
|
||||
"freebsd": true,
|
||||
"hurd": true,
|
||||
"illumos": true,
|
||||
"js": true,
|
||||
"linux": true,
|
||||
"nacl": true,
|
||||
"netbsd": true,
|
||||
"openbsd": true,
|
||||
"plan9": true,
|
||||
"solaris": true,
|
||||
"windows": true,
|
||||
"zos": true,
|
||||
|
||||
// arch
|
||||
"386": true,
|
||||
"amd64": true,
|
||||
"amd64p32": true,
|
||||
"arm": true,
|
||||
"armbe": true,
|
||||
"arm64": true,
|
||||
"arm64be": true,
|
||||
"mips": true,
|
||||
"mipsle": true,
|
||||
"mips64": true,
|
||||
"mips64le": true,
|
||||
"mips64p32": true,
|
||||
"mips64p32le": true,
|
||||
"ppc": true,
|
||||
"ppc64": true,
|
||||
"ppc64le": true,
|
||||
"riscv": true,
|
||||
"riscv64": true,
|
||||
"s390": true,
|
||||
"s390x": true,
|
||||
"sparc": true,
|
||||
"sparc64": true,
|
||||
"wasm": true,
|
||||
|
||||
// other reserved suffixes
|
||||
"test": true,
|
||||
}
|
||||
|
||||
opts := new(LanguageOpts)
|
||||
opts.ReservedWords = []string{
|
||||
"break", "default", "func", "interface", "select",
|
||||
"case", "defer", "go", "map", "struct",
|
||||
"chan", "else", "goto", "package", "switch",
|
||||
"const", "fallthrough", "if", "range", "type",
|
||||
"continue", "for", "import", "return", "var",
|
||||
}
|
||||
|
||||
opts.formatFunc = func(ffn string, content []byte) ([]byte, error) {
|
||||
opts := new(imports.Options)
|
||||
opts.TabIndent = true
|
||||
opts.TabWidth = 2
|
||||
opts.Fragment = true
|
||||
opts.Comments = true
|
||||
return imports.Process(ffn, content, opts)
|
||||
}
|
||||
|
||||
opts.fileNameFunc = func(name string) string {
|
||||
// whenever a generated file name ends with a suffix
|
||||
// that is meaningful to go build, adds a "swagger"
|
||||
// suffix
|
||||
parts := strings.Split(swag.ToFileName(name), "_")
|
||||
if goOtherReservedSuffixes[parts[len(parts)-1]] {
|
||||
// file name ending with a reserved arch or os name
|
||||
// are appended an innocuous suffix "swagger"
|
||||
parts = append(parts, "swagger")
|
||||
}
|
||||
return strings.Join(parts, "_")
|
||||
}
|
||||
|
||||
opts.dirNameFunc = func(name string) string {
|
||||
// whenever a generated directory name is a special
|
||||
// golang directory, append an innocuous suffix
|
||||
switch name {
|
||||
case "vendor", "internal":
|
||||
return strings.Join([]string{name, "swagger"}, "_")
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
opts.ImportsFunc = func(imports map[string]string) string {
|
||||
if len(imports) == 0 {
|
||||
return ""
|
||||
}
|
||||
result := make([]string, 0, len(imports))
|
||||
for k, v := range imports {
|
||||
_, name := path.Split(v)
|
||||
if name != k {
|
||||
result = append(result, fmt.Sprintf("\t%s %q", k, v))
|
||||
} else {
|
||||
result = append(result, fmt.Sprintf("\t%q", v))
|
||||
}
|
||||
}
|
||||
sort.Strings(result)
|
||||
return strings.Join(result, "\n")
|
||||
}
|
||||
|
||||
opts.ArrayInitializerFunc = func(data interface{}) (string, error) {
|
||||
// ArrayInitializer constructs a Go literal initializer from interface{} literals.
|
||||
// e.g. []interface{}{"a", "b"} is transformed in {"a","b",}
|
||||
// e.g. map[string]interface{}{ "a": "x", "b": "y"} is transformed in {"a":"x","b":"y",}.
|
||||
//
|
||||
// NOTE: this is currently used to construct simple slice intializers for default values.
|
||||
// This allows for nicer slice initializers for slices of primitive types and avoid systematic use for json.Unmarshal().
|
||||
b, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.Replace(strings.Replace(strings.Replace(string(b), "}", ",}", -1), "[", "{", -1), "]", ",}", -1), nil
|
||||
}
|
||||
|
||||
opts.BaseImportFunc = func(tgt string) string {
|
||||
tgt = filepath.Clean(tgt)
|
||||
// On Windows, filepath.Abs("") behaves differently than on Unix.
|
||||
// Windows: yields an error, since Abs() does not know the volume.
|
||||
// UNIX: returns current working directory
|
||||
if tgt == "" {
|
||||
tgt = "."
|
||||
}
|
||||
tgtAbsPath, err := filepath.Abs(tgt)
|
||||
if err != nil {
|
||||
log.Fatalf("could not evaluate base import path with target \"%s\": %v", tgt, err)
|
||||
}
|
||||
|
||||
var tgtAbsPathExtended string
|
||||
tgtAbsPathExtended, err = filepath.EvalSymlinks(tgtAbsPath)
|
||||
if err != nil {
|
||||
log.Fatalf("could not evaluate base import path with target \"%s\" (with symlink resolution): %v", tgtAbsPath, err)
|
||||
}
|
||||
|
||||
gopath := os.Getenv("GOPATH")
|
||||
if gopath == "" {
|
||||
gopath = filepath.Join(os.Getenv("HOME"), "go")
|
||||
}
|
||||
|
||||
var pth string
|
||||
for _, gp := range filepath.SplitList(gopath) {
|
||||
// EvalSymLinks also calls the Clean
|
||||
gopathExtended, er := filepath.EvalSymlinks(gp)
|
||||
if er != nil {
|
||||
log.Fatalln(er)
|
||||
}
|
||||
gopathExtended = filepath.Join(gopathExtended, "src")
|
||||
gp = filepath.Join(gp, "src")
|
||||
|
||||
// At this stage we have expanded and unexpanded target path. GOPATH is fully expanded.
|
||||
// Expanded means symlink free.
|
||||
// We compare both types of targetpath<s> with gopath.
|
||||
// If any one of them coincides with gopath , it is imperative that
|
||||
// target path lies inside gopath. How?
|
||||
// - Case 1: Irrespective of symlinks paths coincide. Both non-expanded paths.
|
||||
// - Case 2: Symlink in target path points to location inside GOPATH. (Expanded Target Path)
|
||||
// - Case 3: Symlink in target path points to directory outside GOPATH (Unexpanded target path)
|
||||
|
||||
// Case 1: - Do nothing case. If non-expanded paths match just generate base import path as if
|
||||
// there are no symlinks.
|
||||
|
||||
// Case 2: - Symlink in target path points to location inside GOPATH. (Expanded Target Path)
|
||||
// First if will fail. Second if will succeed.
|
||||
|
||||
// Case 3: - Symlink in target path points to directory outside GOPATH (Unexpanded target path)
|
||||
// First if will succeed and break.
|
||||
|
||||
// compares non expanded path for both
|
||||
if ok, relativepath := checkPrefixAndFetchRelativePath(tgtAbsPath, gp); ok {
|
||||
pth = relativepath
|
||||
break
|
||||
}
|
||||
|
||||
// Compares non-expanded target path
|
||||
if ok, relativepath := checkPrefixAndFetchRelativePath(tgtAbsPath, gopathExtended); ok {
|
||||
pth = relativepath
|
||||
break
|
||||
}
|
||||
|
||||
// Compares expanded target path.
|
||||
if ok, relativepath := checkPrefixAndFetchRelativePath(tgtAbsPathExtended, gopathExtended); ok {
|
||||
pth = relativepath
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mod, goModuleAbsPath, err := tryResolveModule(tgtAbsPath)
|
||||
switch {
|
||||
case err != nil:
|
||||
log.Fatalf("Failed to resolve module using go.mod file: %s", err)
|
||||
case mod != "":
|
||||
relTgt := relPathToRelGoPath(goModuleAbsPath, tgtAbsPath)
|
||||
if !strings.HasSuffix(mod, relTgt) {
|
||||
return filepath.ToSlash(mod + relTgt)
|
||||
}
|
||||
return filepath.ToSlash(mod)
|
||||
}
|
||||
|
||||
if pth == "" {
|
||||
log.Fatalln("target must reside inside a location in the $GOPATH/src or be a module")
|
||||
}
|
||||
return filepath.ToSlash(pth)
|
||||
}
|
||||
opts.Init()
|
||||
return opts
|
||||
}
|
||||
|
||||
// resolveGoModFile walks up the directory tree starting from 'dir' until it
|
||||
// finds a go.mod file. If go.mod is found it will return the related file
|
||||
// object. If no go.mod file is found it will return an error.
|
||||
func resolveGoModFile(dir string) (*os.File, string, error) {
|
||||
goModPath := filepath.Join(dir, "go.mod")
|
||||
f, err := os.Open(goModPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) && dir != filepath.Dir(dir) {
|
||||
return resolveGoModFile(filepath.Dir(dir))
|
||||
}
|
||||
return nil, "", err
|
||||
}
|
||||
return f, dir, nil
|
||||
}
|
||||
|
||||
// relPathToRelGoPath takes a relative os path and returns the relative go
|
||||
// package path. For unix nothing will change but for windows \ will be
|
||||
// converted to /.
|
||||
func relPathToRelGoPath(modAbsPath, absPath string) string {
|
||||
if absPath == "." {
|
||||
return ""
|
||||
}
|
||||
|
||||
path := strings.TrimPrefix(absPath, modAbsPath)
|
||||
pathItems := strings.Split(path, string(filepath.Separator))
|
||||
return strings.Join(pathItems, "/")
|
||||
}
|
||||
|
||||
func tryResolveModule(baseTargetPath string) (string, string, error) {
|
||||
f, goModAbsPath, err := resolveGoModFile(baseTargetPath)
|
||||
switch {
|
||||
case os.IsNotExist(err):
|
||||
return "", "", nil
|
||||
case err != nil:
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
src, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
match := moduleRe.FindSubmatch(src)
|
||||
if len(match) != 2 {
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
return string(match[1]), goModAbsPath, nil
|
||||
}
|
||||
|
||||
// 1. Checks if the child path and parent path coincide.
|
||||
// 2. If they do return child path relative to parent path.
|
||||
// 3. Everything else return false
|
||||
func checkPrefixAndFetchRelativePath(childpath string, parentpath string) (bool, string) {
|
||||
// Windows (local) file systems - NTFS, as well as FAT and variants
|
||||
// are case insensitive.
|
||||
cp, pp := childpath, parentpath
|
||||
if goruntime.GOOS == "windows" {
|
||||
cp = strings.ToLower(cp)
|
||||
pp = strings.ToLower(pp)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(cp, pp) {
|
||||
pth, err := filepath.Rel(parentpath, childpath)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
return true, pth
|
||||
}
|
||||
|
||||
return false, ""
|
||||
|
||||
}
|
191
vendor/github.com/go-swagger/go-swagger/generator/media.go
generated
vendored
Normal file
191
vendor/github.com/go-swagger/go-swagger/generator/media.go
generated
vendored
Normal file
|
@ -0,0 +1,191 @@
|
|||
package generator
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
const jsonSerializer = "json"
|
||||
|
||||
var mediaTypeNames = map[*regexp.Regexp]string{
|
||||
regexp.MustCompile("application/.*json"): jsonSerializer,
|
||||
regexp.MustCompile("application/.*yaml"): "yaml",
|
||||
regexp.MustCompile("application/.*protobuf"): "protobuf",
|
||||
regexp.MustCompile("application/.*capnproto"): "capnproto",
|
||||
regexp.MustCompile("application/.*thrift"): "thrift",
|
||||
regexp.MustCompile("(?:application|text)/.*xml"): "xml",
|
||||
regexp.MustCompile("text/.*markdown"): "markdown",
|
||||
regexp.MustCompile("text/.*html"): "html",
|
||||
regexp.MustCompile("text/.*csv"): "csv",
|
||||
regexp.MustCompile("text/.*tsv"): "tsv",
|
||||
regexp.MustCompile("text/.*javascript"): "js",
|
||||
regexp.MustCompile("text/.*css"): "css",
|
||||
regexp.MustCompile("text/.*plain"): "txt",
|
||||
regexp.MustCompile("application/.*octet-stream"): "bin",
|
||||
regexp.MustCompile("application/.*tar"): "tar",
|
||||
regexp.MustCompile("application/.*gzip"): "gzip",
|
||||
regexp.MustCompile("application/.*gz"): "gzip",
|
||||
regexp.MustCompile("application/.*raw-stream"): "bin",
|
||||
regexp.MustCompile("application/x-www-form-urlencoded"): "urlform",
|
||||
regexp.MustCompile("application/javascript"): "txt",
|
||||
regexp.MustCompile("multipart/form-data"): "multipartform",
|
||||
regexp.MustCompile("image/.*"): "bin",
|
||||
regexp.MustCompile("audio/.*"): "bin",
|
||||
regexp.MustCompile("application/pdf"): "bin",
|
||||
}
|
||||
|
||||
var knownProducers = map[string]string{
|
||||
jsonSerializer: "runtime.JSONProducer()",
|
||||
"yaml": "yamlpc.YAMLProducer()",
|
||||
"xml": "runtime.XMLProducer()",
|
||||
"txt": "runtime.TextProducer()",
|
||||
"bin": "runtime.ByteStreamProducer()",
|
||||
"urlform": "runtime.DiscardProducer",
|
||||
"multipartform": "runtime.DiscardProducer",
|
||||
}
|
||||
|
||||
var knownConsumers = map[string]string{
|
||||
jsonSerializer: "runtime.JSONConsumer()",
|
||||
"yaml": "yamlpc.YAMLConsumer()",
|
||||
"xml": "runtime.XMLConsumer()",
|
||||
"txt": "runtime.TextConsumer()",
|
||||
"bin": "runtime.ByteStreamConsumer()",
|
||||
"urlform": "runtime.DiscardConsumer",
|
||||
"multipartform": "runtime.DiscardConsumer",
|
||||
}
|
||||
|
||||
func wellKnownMime(tn string) (string, bool) {
|
||||
for k, v := range mediaTypeNames {
|
||||
if k.MatchString(tn) {
|
||||
return v, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func mediaMime(orig string) string {
|
||||
return strings.SplitN(orig, ";", 2)[0]
|
||||
}
|
||||
|
||||
func mediaParameters(orig string) string {
|
||||
parts := strings.SplitN(orig, ";", 2)
|
||||
if len(parts) < 2 {
|
||||
return ""
|
||||
}
|
||||
return parts[1]
|
||||
}
|
||||
|
||||
func (a *appGenerator) makeSerializers(mediaTypes []string, known func(string) (string, bool)) (GenSerGroups, bool) {
|
||||
supportsJSON := false
|
||||
uniqueSerializers := make(map[string]*GenSerializer, len(mediaTypes))
|
||||
uniqueSerializerGroups := make(map[string]*GenSerGroup, len(mediaTypes))
|
||||
|
||||
// build all required serializers
|
||||
for _, media := range mediaTypes {
|
||||
key := mediaMime(media)
|
||||
nm, ok := wellKnownMime(key)
|
||||
if !ok {
|
||||
// keep this serializer named, even though its implementation is empty (cf. #1557)
|
||||
nm = key
|
||||
}
|
||||
name := swag.ToJSONName(nm)
|
||||
impl, _ := known(name)
|
||||
|
||||
ser, ok := uniqueSerializers[key]
|
||||
if !ok {
|
||||
ser = &GenSerializer{
|
||||
AppName: a.Name,
|
||||
ReceiverName: a.Receiver,
|
||||
Name: name,
|
||||
MediaType: key,
|
||||
Implementation: impl,
|
||||
Parameters: []string{},
|
||||
}
|
||||
uniqueSerializers[key] = ser
|
||||
}
|
||||
// provide all known parameters (currently unused by codegen templates)
|
||||
if params := strings.TrimSpace(mediaParameters(media)); params != "" {
|
||||
found := false
|
||||
for _, p := range ser.Parameters {
|
||||
if params == p {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
ser.Parameters = append(ser.Parameters, params)
|
||||
}
|
||||
}
|
||||
|
||||
uniqueSerializerGroups[name] = &GenSerGroup{
|
||||
GenSerializer: GenSerializer{
|
||||
AppName: a.Name,
|
||||
ReceiverName: a.Receiver,
|
||||
Name: name,
|
||||
Implementation: impl,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if len(uniqueSerializers) == 0 {
|
||||
impl, _ := known(jsonSerializer)
|
||||
uniqueSerializers[runtime.JSONMime] = &GenSerializer{
|
||||
AppName: a.Name,
|
||||
ReceiverName: a.Receiver,
|
||||
Name: jsonSerializer,
|
||||
MediaType: runtime.JSONMime,
|
||||
Implementation: impl,
|
||||
Parameters: []string{},
|
||||
}
|
||||
uniqueSerializerGroups[jsonSerializer] = &GenSerGroup{
|
||||
GenSerializer: GenSerializer{
|
||||
AppName: a.Name,
|
||||
ReceiverName: a.Receiver,
|
||||
Name: jsonSerializer,
|
||||
Implementation: impl,
|
||||
},
|
||||
}
|
||||
supportsJSON = true
|
||||
}
|
||||
|
||||
// group serializers by consumer/producer to serve several mime media types
|
||||
serializerGroups := make(GenSerGroups, 0, len(uniqueSerializers))
|
||||
|
||||
for _, group := range uniqueSerializerGroups {
|
||||
if group.Name == jsonSerializer {
|
||||
supportsJSON = true
|
||||
}
|
||||
serializers := make(GenSerializers, 0, len(uniqueSerializers))
|
||||
for _, ser := range uniqueSerializers {
|
||||
if group.Name == ser.Name {
|
||||
sort.Strings(ser.Parameters)
|
||||
serializers = append(serializers, *ser)
|
||||
}
|
||||
}
|
||||
sort.Sort(serializers)
|
||||
group.AllSerializers = serializers // provides the full list of mime media types for this serializer group
|
||||
serializerGroups = append(serializerGroups, *group)
|
||||
}
|
||||
sort.Sort(serializerGroups)
|
||||
return serializerGroups, supportsJSON
|
||||
}
|
||||
|
||||
func (a *appGenerator) makeConsumes() (GenSerGroups, bool) {
|
||||
// builds a codegen struct from all consumes in the spec
|
||||
return a.makeSerializers(a.Analyzed.RequiredConsumes(), func(media string) (string, bool) {
|
||||
c, ok := knownConsumers[media]
|
||||
return c, ok
|
||||
})
|
||||
}
|
||||
|
||||
func (a *appGenerator) makeProduces() (GenSerGroups, bool) {
|
||||
// builds a codegen struct from all produces in the spec
|
||||
return a.makeSerializers(a.Analyzed.RequiredProduces(), func(media string) (string, bool) {
|
||||
p, ok := knownProducers[media]
|
||||
return p, ok
|
||||
})
|
||||
}
|
204
vendor/github.com/go-swagger/go-swagger/generator/model.go
generated
vendored
204
vendor/github.com/go-swagger/go-swagger/generator/model.go
generated
vendored
|
@ -15,11 +15,9 @@
|
|||
package generator
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
@ -49,30 +47,38 @@ Every action that happens tracks the path which is a linked list of refs
|
|||
|
||||
*/
|
||||
|
||||
// GenerateDefinition generates a model file for a schema definition.
|
||||
// GenerateModels generates all model files for some schema definitions
|
||||
func GenerateModels(modelNames []string, opts *GenOpts) error {
|
||||
// overide any default or incompatible options setting
|
||||
opts.IncludeModel = true
|
||||
opts.IgnoreOperations = true
|
||||
opts.ExistingModels = ""
|
||||
opts.IncludeHandler = false
|
||||
opts.IncludeMain = false
|
||||
opts.IncludeSupport = false
|
||||
generator, err := newAppGenerator("", modelNames, nil, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generator.Generate()
|
||||
}
|
||||
|
||||
// GenerateDefinition generates a single model file for some schema definitions
|
||||
func GenerateDefinition(modelNames []string, opts *GenOpts) error {
|
||||
if opts == nil {
|
||||
return errors.New("gen opts are required")
|
||||
}
|
||||
|
||||
templates.SetAllowOverride(opts.AllowTemplateOverride)
|
||||
|
||||
if opts.TemplateDir != "" {
|
||||
if err := templates.LoadDir(opts.TemplateDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := opts.CheckOpts(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Load the spec
|
||||
specPath, specDoc, err := loadSpec(opts.Spec)
|
||||
if err := opts.setTemplates(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
specDoc, _, err := opts.analyzeSpec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
modelNames = pruneEmpty(modelNames)
|
||||
if len(modelNames) == 0 {
|
||||
for k := range specDoc.Spec().Definitions {
|
||||
modelNames = append(modelNames, k)
|
||||
|
@ -83,7 +89,7 @@ func GenerateDefinition(modelNames []string, opts *GenOpts) error {
|
|||
// lookup schema
|
||||
model, ok := specDoc.Spec().Definitions[modelName]
|
||||
if !ok {
|
||||
return fmt.Errorf("model %q not found in definitions given by %q", modelName, specPath)
|
||||
return fmt.Errorf("model %q not found in definitions given by %q", modelName, opts.Spec)
|
||||
}
|
||||
|
||||
// generate files
|
||||
|
@ -121,9 +127,7 @@ func (m *definitionGenerator) Generate() error {
|
|||
}
|
||||
|
||||
if m.opts.DumpData {
|
||||
bb, _ := json.MarshalIndent(swag.ToDynamicJSON(mod), "", " ")
|
||||
fmt.Fprintln(os.Stdout, string(bb))
|
||||
return nil
|
||||
return dumpData(swag.ToDynamicJSON(mod))
|
||||
}
|
||||
|
||||
if m.opts.IncludeModel {
|
||||
|
@ -169,13 +173,17 @@ func shallowValidationLookup(sch GenSchema) bool {
|
|||
// and NeedsValidation (e.g. should have a Validate method with something in it).
|
||||
// The latter was almost not used anyhow.
|
||||
|
||||
if sch.HasAdditionalProperties && sch.AdditionalProperties == nil {
|
||||
log.Printf("warning: schema for additional properties in schema %q is empty. skipped", sch.Name)
|
||||
}
|
||||
|
||||
if sch.IsArray && sch.HasValidations {
|
||||
return true
|
||||
}
|
||||
if sch.IsStream || sch.IsInterface { // these types have no validation - aliased types on those do not implement the Validatable interface
|
||||
return false
|
||||
}
|
||||
if sch.Required || sch.IsCustomFormatter && !sch.IsStream {
|
||||
if sch.Required || hasFormatValidation(sch.resolvedType) {
|
||||
return true
|
||||
}
|
||||
if sch.MaxLength != nil || sch.MinLength != nil || sch.Pattern != "" || sch.MultipleOf != nil || sch.Minimum != nil || sch.Maximum != nil || len(sch.Enum) > 0 || len(sch.ItemsEnum) > 0 {
|
||||
|
@ -196,11 +204,11 @@ func shallowValidationLookup(sch GenSchema) bool {
|
|||
if sch.IsTuple && (sch.AdditionalItems != nil && (sch.AdditionalItems.HasValidations || sch.AdditionalItems.Required)) {
|
||||
return true
|
||||
}
|
||||
if sch.HasAdditionalProperties && (sch.AdditionalProperties.IsInterface || sch.AdditionalProperties.IsStream) {
|
||||
if sch.HasAdditionalProperties && sch.AdditionalProperties != nil && (sch.AdditionalProperties.IsInterface || sch.AdditionalProperties.IsStream) {
|
||||
return false
|
||||
}
|
||||
|
||||
if sch.HasAdditionalProperties && (sch.AdditionalProperties.HasValidations || sch.AdditionalProperties.Required || sch.AdditionalProperties.IsAliased && !(sch.AdditionalProperties.IsInterface || sch.AdditionalProperties.IsStream)) {
|
||||
if sch.HasAdditionalProperties && sch.AdditionalProperties != nil && (sch.AdditionalProperties.HasValidations || sch.AdditionalProperties.Required || sch.AdditionalProperties.IsAliased && !(sch.AdditionalProperties.IsInterface || sch.AdditionalProperties.IsStream)) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -213,10 +221,13 @@ func shallowValidationLookup(sch GenSchema) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func isExternal(schema spec.Schema) bool {
|
||||
extType, ok := hasExternalType(schema.Extensions)
|
||||
return ok && !extType.Embedded
|
||||
}
|
||||
|
||||
func makeGenDefinitionHierarchy(name, pkg, container string, schema spec.Schema, specDoc *loads.Document, opts *GenOpts) (*GenDefinition, error) {
|
||||
// Check if model is imported from external package using x-go-type
|
||||
_, external := schema.Extensions[xGoType]
|
||||
|
||||
receiver := "m"
|
||||
// models are resolved in the current package
|
||||
resolver := newTypeResolver("", specDoc)
|
||||
|
@ -241,6 +252,8 @@ func makeGenDefinitionHierarchy(name, pkg, container string, schema spec.Schema,
|
|||
IncludeValidator: opts.IncludeValidator,
|
||||
IncludeModel: opts.IncludeModel,
|
||||
StrictAdditionalProperties: opts.StrictAdditionalProperties,
|
||||
WithXML: opts.WithXML,
|
||||
StructTags: opts.StructTags,
|
||||
}
|
||||
if err := pg.makeGenSchema(); err != nil {
|
||||
return nil, fmt.Errorf("could not generate schema for %s: %v", name, err)
|
||||
|
@ -282,6 +295,10 @@ func makeGenDefinitionHierarchy(name, pkg, container string, schema spec.Schema,
|
|||
// replace the ref with this new genschema
|
||||
swsp := specDoc.Spec()
|
||||
for i, ss := range schema.AllOf {
|
||||
if pg.GenSchema.AllOf == nil {
|
||||
log.Printf("warning: resolved schema for subtype %q.AllOf[%d] is empty. skipped", name, i)
|
||||
continue
|
||||
}
|
||||
ref := ss.Ref
|
||||
for ref.String() != "" {
|
||||
var rsch *spec.Schema
|
||||
|
@ -290,7 +307,6 @@ func makeGenDefinitionHierarchy(name, pkg, container string, schema spec.Schema,
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ref = rsch.Ref
|
||||
if rsch != nil && rsch.Ref.String() != "" {
|
||||
ref = rsch.Ref
|
||||
continue
|
||||
|
@ -336,17 +352,17 @@ func makeGenDefinitionHierarchy(name, pkg, container string, schema spec.Schema,
|
|||
|
||||
}
|
||||
|
||||
defaultImports := []string{
|
||||
"github.com/go-openapi/errors",
|
||||
"github.com/go-openapi/runtime",
|
||||
"github.com/go-openapi/swag",
|
||||
"github.com/go-openapi/validate",
|
||||
defaultImports := map[string]string{
|
||||
"errors": "github.com/go-openapi/errors",
|
||||
"runtime": "github.com/go-openapi/runtime",
|
||||
"swag": "github.com/go-openapi/swag",
|
||||
"validate": "github.com/go-openapi/validate",
|
||||
}
|
||||
|
||||
return &GenDefinition{
|
||||
GenCommon: GenCommon{
|
||||
Copyright: opts.Copyright,
|
||||
TargetImportPath: filepath.ToSlash(opts.LanguageOpts.baseImport(opts.Target)),
|
||||
TargetImportPath: opts.LanguageOpts.baseImport(opts.Target),
|
||||
},
|
||||
Package: opts.LanguageOpts.ManglePackageName(path.Base(filepath.ToSlash(pkg)), "definitions"),
|
||||
GenSchema: pg.GenSchema,
|
||||
|
@ -354,7 +370,7 @@ func makeGenDefinitionHierarchy(name, pkg, container string, schema spec.Schema,
|
|||
DefaultImports: defaultImports,
|
||||
ExtraSchemas: gatherExtraSchemas(pg.ExtraSchemas),
|
||||
Imports: findImports(&pg.GenSchema),
|
||||
External: external,
|
||||
External: isExternal(schema),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -364,6 +380,11 @@ func findImports(sch *GenSchema) map[string]string {
|
|||
if t.Pkg != "" && t.PkgAlias != "" {
|
||||
imp[t.PkgAlias] = t.Pkg
|
||||
}
|
||||
if t.IsEmbedded && t.ElemType != nil {
|
||||
if t.ElemType.Pkg != "" && t.ElemType.PkgAlias != "" {
|
||||
imp[t.ElemType.PkgAlias] = t.ElemType.Pkg
|
||||
}
|
||||
}
|
||||
if sch.Items != nil {
|
||||
sub := findImports(sch.Items)
|
||||
for k, v := range sub {
|
||||
|
@ -404,6 +425,9 @@ func findImports(sch *GenSchema) map[string]string {
|
|||
}
|
||||
}
|
||||
}
|
||||
for k, v := range sch.ExtraImports {
|
||||
imp[k] = v
|
||||
}
|
||||
return imp
|
||||
}
|
||||
|
||||
|
@ -418,6 +442,7 @@ type schemaGenContext struct {
|
|||
IncludeValidator bool
|
||||
IncludeModel bool
|
||||
StrictAdditionalProperties bool
|
||||
WithXML bool
|
||||
Index int
|
||||
|
||||
Path string
|
||||
|
@ -431,6 +456,7 @@ type schemaGenContext struct {
|
|||
Container string
|
||||
Schema spec.Schema
|
||||
TypeResolver *typeResolver
|
||||
StructTags []string
|
||||
|
||||
GenSchema GenSchema
|
||||
Dependencies []string // NOTE: Dependencies is actually set nowhere
|
||||
|
@ -438,6 +464,9 @@ type schemaGenContext struct {
|
|||
Discriminator *discor
|
||||
Discriminated *discee
|
||||
Discrimination *discInfo
|
||||
|
||||
// force to use container in inlined definitions (for deconflicting)
|
||||
UseContainerInName bool
|
||||
}
|
||||
|
||||
func (sg *schemaGenContext) NewSliceBranch(schema *spec.Schema) *schemaGenContext {
|
||||
|
@ -548,7 +577,7 @@ func (sg *schemaGenContext) shallowClone() *schemaGenContext {
|
|||
if pg.Container == "" {
|
||||
pg.Container = sg.Name
|
||||
}
|
||||
pg.GenSchema = GenSchema{}
|
||||
pg.GenSchema = GenSchema{StructTags: sg.StructTags}
|
||||
pg.Dependencies = nil
|
||||
pg.Named = false
|
||||
pg.Index = 0
|
||||
|
@ -621,6 +650,16 @@ func hasValidations(model *spec.Schema, isRequired bool) (hasValidation bool) {
|
|||
return
|
||||
}
|
||||
|
||||
func hasFormatValidation(tpe resolvedType) bool {
|
||||
if tpe.IsCustomFormatter && !tpe.IsStream && !tpe.IsBase64 {
|
||||
return true
|
||||
}
|
||||
if tpe.IsArray && tpe.ElemType != nil {
|
||||
return hasFormatValidation(*tpe.ElemType)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// handleFormatConflicts handles all conflicting model properties when a format is set
|
||||
func handleFormatConflicts(model *spec.Schema) {
|
||||
switch model.Format {
|
||||
|
@ -690,6 +729,14 @@ func (sg *schemaGenContext) MergeResult(other *schemaGenContext, liftsRequired b
|
|||
if other.GenSchema.IsMapNullOverride {
|
||||
sg.GenSchema.IsMapNullOverride = true
|
||||
}
|
||||
|
||||
// lift extra imports
|
||||
if other.GenSchema.Pkg != "" && other.GenSchema.PkgAlias != "" {
|
||||
sg.GenSchema.ExtraImports[other.GenSchema.PkgAlias] = other.GenSchema.Pkg
|
||||
}
|
||||
for k, v := range other.GenSchema.ExtraImports {
|
||||
sg.GenSchema.ExtraImports[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
func (sg *schemaGenContext) buildProperties() error {
|
||||
|
@ -702,7 +749,7 @@ func (sg *schemaGenContext) buildProperties() error {
|
|||
sg.Name, k, sg.IsTuple, sg.GenSchema.HasValidations)
|
||||
|
||||
// check if this requires de-anonymizing, if so lift this as a new struct and extra schema
|
||||
tpe, err := sg.TypeResolver.ResolveSchema(&v, true, sg.IsTuple || containsString(sg.Schema.Required, k))
|
||||
tpe, err := sg.TypeResolver.ResolveSchema(&v, true, sg.IsTuple || swag.ContainsStrings(sg.Schema.Required, k))
|
||||
if sg.Schema.Discriminator == k {
|
||||
tpe.IsNullable = false
|
||||
}
|
||||
|
@ -714,7 +761,7 @@ func (sg *schemaGenContext) buildProperties() error {
|
|||
var hasValidation bool
|
||||
if tpe.IsComplexObject && tpe.IsAnonymous && len(v.Properties) > 0 {
|
||||
// this is an anonymous complex construct: build a new new type for it
|
||||
pg := sg.makeNewStruct(sg.Name+swag.ToGoName(k), v)
|
||||
pg := sg.makeNewStruct(sg.makeRefName()+swag.ToGoName(k), v)
|
||||
pg.IsTuple = sg.IsTuple
|
||||
if sg.Path != "" {
|
||||
pg.Path = sg.Path + "+ \".\"+" + fmt.Sprintf("%q", k)
|
||||
|
@ -754,7 +801,7 @@ func (sg *schemaGenContext) buildProperties() error {
|
|||
}
|
||||
|
||||
// generates format validation on property
|
||||
emprop.GenSchema.HasValidations = emprop.GenSchema.HasValidations || (tpe.IsCustomFormatter && !tpe.IsStream) || (tpe.IsArray && tpe.ElemType.IsCustomFormatter && !tpe.ElemType.IsStream)
|
||||
emprop.GenSchema.HasValidations = emprop.GenSchema.HasValidations || hasFormatValidation(tpe)
|
||||
|
||||
if emprop.Schema.Ref.String() != "" {
|
||||
// expand the schema of this property, so we take informed decisions about its type
|
||||
|
@ -768,7 +815,9 @@ func (sg *schemaGenContext) buildProperties() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ref = rsch.Ref
|
||||
if rsch == nil {
|
||||
return errors.New("spec.ResolveRef returned nil schema")
|
||||
}
|
||||
if rsch != nil && rsch.Ref.String() != "" {
|
||||
ref = rsch.Ref
|
||||
continue
|
||||
|
@ -804,7 +853,7 @@ func (sg *schemaGenContext) buildProperties() error {
|
|||
hv := hasValidations(sch, false)
|
||||
|
||||
// include format validation, excluding binary
|
||||
hv = hv || (ttpe.IsCustomFormatter && !ttpe.IsStream) || (ttpe.IsArray && ttpe.ElemType.IsCustomFormatter && !ttpe.ElemType.IsStream)
|
||||
hv = hv || hasFormatValidation(ttpe)
|
||||
|
||||
// a base type property is always validated against the base type
|
||||
// exception: for the base type definition itself (see shallowValidationLookup())
|
||||
|
@ -898,7 +947,7 @@ func (sg *schemaGenContext) buildAllOf() error {
|
|||
// - nested allOf: this one is itself a AllOf: build a new type for it
|
||||
// - anonymous simple types for edge cases: array, primitive, interface{}
|
||||
// NOTE: when branches are aliased or anonymous, the nullable property in the branch type is lost.
|
||||
name := swag.ToVarName(goName(&sch, sg.Name+"AllOf"+strconv.Itoa(i)))
|
||||
name := swag.ToVarName(goName(&sch, sg.makeRefName()+"AllOf"+strconv.Itoa(i)))
|
||||
debugLog("building anonymous nested allOf in %s: %s", sg.Name, name)
|
||||
ng := sg.makeNewStruct(name, sch)
|
||||
if err := ng.makeGenSchema(); err != nil {
|
||||
|
@ -991,7 +1040,7 @@ func newMapStack(context *schemaGenContext) (first, last *mapStack, err error) {
|
|||
//reached the end of the rabbit hole
|
||||
if tpe.IsComplexObject && tpe.IsAnonymous {
|
||||
// found an anonymous object: create the struct from a newly created definition
|
||||
nw := l.Context.makeNewStruct(l.Context.Name+" Anon", *l.Type.AdditionalProperties.Schema)
|
||||
nw := l.Context.makeNewStruct(l.Context.makeRefName()+" Anon", *l.Type.AdditionalProperties.Schema)
|
||||
sch := spec.RefProperty("#/definitions/" + nw.Name)
|
||||
l.NewObj = nw
|
||||
|
||||
|
@ -1216,7 +1265,7 @@ func (sg *schemaGenContext) buildAdditionalProperties() error {
|
|||
|
||||
if tpe.IsComplexObject && tpe.IsAnonymous {
|
||||
// if the AdditionalProperties is an anonymous complex object, generate a new type for it
|
||||
pg := sg.makeNewStruct(sg.Name+" Anon", *addp.Schema)
|
||||
pg := sg.makeNewStruct(sg.makeRefName()+" Anon", *addp.Schema)
|
||||
if err := pg.makeGenSchema(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1311,7 +1360,7 @@ func (sg *schemaGenContext) buildAdditionalProperties() error {
|
|||
}
|
||||
|
||||
hasMapNullOverride := sg.GenSchema.IsMapNullOverride
|
||||
sg.GenSchema = GenSchema{}
|
||||
sg.GenSchema = GenSchema{StructTags: sg.StructTags}
|
||||
sg.Schema = *spec.RefProperty("#/definitions/" + newObj.Name)
|
||||
if err := sg.makeGenSchema(); err != nil {
|
||||
return err
|
||||
|
@ -1356,6 +1405,7 @@ func (sg *schemaGenContext) makeNewStruct(name string, schema spec.Schema) *sche
|
|||
IncludeValidator: sg.IncludeValidator,
|
||||
IncludeModel: sg.IncludeModel,
|
||||
StrictAdditionalProperties: sg.StrictAdditionalProperties,
|
||||
StructTags: sg.StructTags,
|
||||
}
|
||||
if schema.Ref.String() == "" {
|
||||
pg.TypeResolver = sg.TypeResolver.NewWithModelName(name)
|
||||
|
@ -1374,7 +1424,7 @@ func (sg *schemaGenContext) buildArray() error {
|
|||
|
||||
// check if the element is a complex object, if so generate a new type for it
|
||||
if tpe.IsComplexObject && tpe.IsAnonymous {
|
||||
pg := sg.makeNewStruct(sg.Name+" items"+strconv.Itoa(sg.Index), *sg.Schema.Items.Schema)
|
||||
pg := sg.makeNewStruct(sg.makeRefName()+" items"+strconv.Itoa(sg.Index), *sg.Schema.Items.Schema)
|
||||
if err := pg.makeGenSchema(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1419,10 +1469,8 @@ func (sg *schemaGenContext) buildArray() error {
|
|||
schemaCopy.Required = false
|
||||
|
||||
// validations of items
|
||||
hv := hasValidations(sg.Schema.Items.Schema, false)
|
||||
|
||||
// include format validation, excluding binary
|
||||
hv = hv || (schemaCopy.IsCustomFormatter && !schemaCopy.IsStream) || (schemaCopy.IsArray && schemaCopy.ElemType.IsCustomFormatter && !schemaCopy.ElemType.IsStream)
|
||||
// include format validation, excluding binary and base64 format validation
|
||||
hv := hasValidations(sg.Schema.Items.Schema, false) || hasFormatValidation(schemaCopy.resolvedType)
|
||||
|
||||
// base types of polymorphic types must be validated
|
||||
// NOTE: IsNullable is not useful to figure out a validation: we use Refed and IsAliased below instead
|
||||
|
@ -1478,7 +1526,7 @@ func (sg *schemaGenContext) buildItems() error {
|
|||
}
|
||||
if tpe.IsComplexObject && tpe.IsAnonymous {
|
||||
// if the tuple element is an anonymous complex object, build a new type for it
|
||||
pg := sg.makeNewStruct(sg.Name+" Items"+strconv.Itoa(i), s)
|
||||
pg := sg.makeNewStruct(sg.makeRefName()+" Items"+strconv.Itoa(i), s)
|
||||
if err := pg.makeGenSchema(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1546,7 +1594,7 @@ func (sg *schemaGenContext) buildAdditionalItems() error {
|
|||
return err
|
||||
}
|
||||
if tpe.IsComplexObject && tpe.IsAnonymous {
|
||||
pg := sg.makeNewStruct(sg.Name+" Items", *sg.Schema.AdditionalItems.Schema)
|
||||
pg := sg.makeNewStruct(sg.makeRefName()+" Items", *sg.Schema.AdditionalItems.Schema)
|
||||
if err := pg.makeGenSchema(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1581,16 +1629,21 @@ func (sg *schemaGenContext) buildAdditionalItems() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (sg *schemaGenContext) buildXMLName() error {
|
||||
if sg.Schema.XML == nil {
|
||||
return nil
|
||||
}
|
||||
sg.GenSchema.XMLName = sg.Name
|
||||
func (sg *schemaGenContext) buildXMLNameWithTags() error {
|
||||
if sg.WithXML || sg.Schema.XML != nil {
|
||||
sg.GenSchema.XMLName = sg.Name
|
||||
|
||||
if sg.Schema.XML.Name != "" {
|
||||
sg.GenSchema.XMLName = sg.Schema.XML.Name
|
||||
if sg.Schema.XML.Attribute {
|
||||
sg.GenSchema.XMLName += ",attr"
|
||||
if sg.Schema.XML != nil {
|
||||
if sg.Schema.XML.Name != "" {
|
||||
sg.GenSchema.XMLName = sg.Schema.XML.Name
|
||||
}
|
||||
if sg.Schema.XML.Attribute {
|
||||
sg.GenSchema.XMLName += ",attr"
|
||||
}
|
||||
}
|
||||
|
||||
if !sg.GenSchema.Required && sg.GenSchema.IsEmptyOmitted {
|
||||
sg.GenSchema.XMLName += ",omitempty"
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -1646,6 +1699,7 @@ func (sg *schemaGenContext) shortCircuitNamedRef() (bool, error) {
|
|||
tpe.IsNullable = tpx.IsNullable // TODO
|
||||
tpe.IsInterface = tpx.IsInterface
|
||||
tpe.IsStream = tpx.IsStream
|
||||
tpe.IsEmbedded = tpx.IsEmbedded
|
||||
|
||||
tpe.SwaggerType = tpx.SwaggerType
|
||||
sch := spec.Schema{}
|
||||
|
@ -1764,6 +1818,15 @@ func (sg *schemaGenContext) buildAliased() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (sg schemaGenContext) makeRefName() string {
|
||||
// figure out a longer name for deconflicting anonymous models.
|
||||
// This is used when makeNewStruct() is followed by the creation of a new ref to definitions
|
||||
if sg.UseContainerInName && sg.Container != sg.Name {
|
||||
return sg.Container + swag.ToGoName(sg.Name)
|
||||
}
|
||||
return sg.Name
|
||||
}
|
||||
|
||||
func (sg *schemaGenContext) GoName() string {
|
||||
return goName(&sg.Schema, sg.Name)
|
||||
}
|
||||
|
@ -1852,6 +1915,8 @@ func (sg *schemaGenContext) makeGenSchema() error {
|
|||
sg.GenSchema.IncludeModel = sg.IncludeModel
|
||||
sg.GenSchema.StrictAdditionalProperties = sg.StrictAdditionalProperties
|
||||
sg.GenSchema.Default = sg.Schema.Default
|
||||
sg.GenSchema.StructTags = sg.StructTags
|
||||
sg.GenSchema.ExtraImports = make(map[string]string)
|
||||
|
||||
var err error
|
||||
returns, err := sg.shortCircuitNamedRef()
|
||||
|
@ -1893,7 +1958,7 @@ func (sg *schemaGenContext) makeGenSchema() error {
|
|||
sg.GenSchema.HasDiscriminator = tpe.HasDiscriminator
|
||||
|
||||
// include format validations, excluding binary
|
||||
sg.GenSchema.HasValidations = sg.GenSchema.HasValidations || (tpe.IsCustomFormatter && !tpe.IsStream) || (tpe.IsArray && tpe.ElemType != nil && tpe.ElemType.IsCustomFormatter && !tpe.ElemType.IsStream)
|
||||
sg.GenSchema.HasValidations = sg.GenSchema.HasValidations || hasFormatValidation(tpe)
|
||||
|
||||
// usage of a polymorphic base type is rendered with getter funcs on private properties.
|
||||
// In the case of aliased types, the value expression remains unchanged to the receiver.
|
||||
|
@ -1940,7 +2005,7 @@ func (sg *schemaGenContext) makeGenSchema() error {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := sg.buildXMLName(); err != nil {
|
||||
if err := sg.buildXMLNameWithTags(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -1958,6 +2023,21 @@ func (sg *schemaGenContext) makeGenSchema() error {
|
|||
|
||||
sg.buildMapOfNullable(nil)
|
||||
|
||||
// extra serializers & interfaces
|
||||
|
||||
// generate MarshalBinary for:
|
||||
// - tuple
|
||||
// - struct
|
||||
// - map
|
||||
// - aliased primitive of a formatter type which is not a stringer
|
||||
//
|
||||
// but not for:
|
||||
// - interface{}
|
||||
// - io.Reader
|
||||
gs := sg.GenSchema
|
||||
sg.GenSchema.WantsMarshalBinary = !(gs.IsInterface || gs.IsStream || gs.IsBaseType) &&
|
||||
(gs.IsTuple || gs.IsComplexObject || gs.IsAdditionalProperties || (gs.IsPrimitive && gs.IsAliased && gs.IsCustomFormatter && !strings.Contains(gs.Zero(), `("`)))
|
||||
|
||||
debugLog("finished gen schema for %q", sg.Name)
|
||||
return nil
|
||||
}
|
||||
|
|
442
vendor/github.com/go-swagger/go-swagger/generator/operation.go
generated
vendored
442
vendor/github.com/go-swagger/go-swagger/generator/operation.go
generated
vendored
|
@ -18,8 +18,6 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
@ -55,86 +53,58 @@ func sortedResponses(input map[int]spec.Response) responses {
|
|||
return res
|
||||
}
|
||||
|
||||
// GenerateServerOperation generates a parameter model, parameter validator, http handler implementations for a given operation
|
||||
// GenerateServerOperation generates a parameter model, parameter validator, http handler implementations for a given operation.
|
||||
//
|
||||
// It also generates an operation handler interface that uses the parameter model for handling a valid request.
|
||||
// Allows for specifying a list of tags to include only certain tags for the generation
|
||||
func GenerateServerOperation(operationNames []string, opts *GenOpts) error {
|
||||
if opts == nil {
|
||||
return errors.New("gen opts are required")
|
||||
}
|
||||
templates.LoadDefaults()
|
||||
|
||||
templates.SetAllowOverride(opts.AllowTemplateOverride)
|
||||
|
||||
if opts.TemplateDir != "" {
|
||||
if err := templates.LoadDir(opts.TemplateDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := opts.CheckOpts(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Load the spec
|
||||
_, specDoc, err := loadSpec(opts.Spec)
|
||||
if err != nil {
|
||||
if err := opts.setTemplates(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate and Expand. specDoc is in/out param.
|
||||
specDoc, err = validateAndFlattenSpec(opts, specDoc)
|
||||
specDoc, analyzed, err := opts.analyzeSpec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
analyzed := analysis.New(specDoc.Spec())
|
||||
|
||||
ops := gatherOperations(analyzed, operationNames)
|
||||
|
||||
if len(ops) == 0 {
|
||||
return errors.New("no operations were selected")
|
||||
}
|
||||
|
||||
for operationName, opRef := range ops {
|
||||
method, path, operation := opRef.Method, opRef.Path, opRef.Op
|
||||
defaultScheme := opts.DefaultScheme
|
||||
if defaultScheme == "" {
|
||||
defaultScheme = sHTTP
|
||||
}
|
||||
defaultProduces := opts.DefaultProduces
|
||||
if defaultProduces == "" {
|
||||
defaultProduces = runtime.JSONMime
|
||||
}
|
||||
defaultConsumes := opts.DefaultConsumes
|
||||
if defaultConsumes == "" {
|
||||
defaultConsumes = runtime.JSONMime
|
||||
}
|
||||
|
||||
serverPackage := opts.LanguageOpts.ManglePackagePath(opts.ServerPackage, "server")
|
||||
serverPackage := opts.LanguageOpts.ManglePackagePath(opts.ServerPackage, defaultServerTarget)
|
||||
generator := operationGenerator{
|
||||
Name: operationName,
|
||||
Method: method,
|
||||
Path: path,
|
||||
BasePath: specDoc.BasePath(),
|
||||
APIPackage: opts.LanguageOpts.ManglePackagePath(opts.APIPackage, "api"),
|
||||
ModelsPackage: opts.LanguageOpts.ManglePackagePath(opts.ModelPackage, "definitions"),
|
||||
ClientPackage: opts.LanguageOpts.ManglePackagePath(opts.ClientPackage, "client"),
|
||||
APIPackage: opts.LanguageOpts.ManglePackagePath(opts.APIPackage, defaultOperationsTarget),
|
||||
ModelsPackage: opts.LanguageOpts.ManglePackagePath(opts.ModelPackage, defaultModelsTarget),
|
||||
ClientPackage: opts.LanguageOpts.ManglePackagePath(opts.ClientPackage, defaultClientTarget),
|
||||
ServerPackage: serverPackage,
|
||||
Operation: *operation,
|
||||
SecurityRequirements: analyzed.SecurityRequirementsFor(operation),
|
||||
SecurityDefinitions: analyzed.SecurityDefinitionsFor(operation),
|
||||
Principal: opts.Principal,
|
||||
Principal: opts.PrincipalAlias(),
|
||||
Target: filepath.Join(opts.Target, filepath.FromSlash(serverPackage)),
|
||||
Base: opts.Target,
|
||||
Tags: opts.Tags,
|
||||
IncludeHandler: opts.IncludeHandler,
|
||||
IncludeParameters: opts.IncludeParameters,
|
||||
IncludeResponses: opts.IncludeResponses,
|
||||
IncludeValidator: true, // we no more support the CLI option to disable validation
|
||||
IncludeValidator: opts.IncludeValidator,
|
||||
DumpData: opts.DumpData,
|
||||
DefaultScheme: defaultScheme,
|
||||
DefaultProduces: defaultProduces,
|
||||
DefaultConsumes: defaultConsumes,
|
||||
DefaultScheme: opts.DefaultScheme,
|
||||
DefaultProduces: opts.DefaultProduces,
|
||||
DefaultConsumes: opts.DefaultConsumes,
|
||||
Doc: specDoc,
|
||||
Analyzed: analyzed,
|
||||
GenOpts: opts,
|
||||
|
@ -177,78 +147,55 @@ type operationGenerator struct {
|
|||
GenOpts *GenOpts
|
||||
}
|
||||
|
||||
func intersectTags(left, right []string) (filtered []string) {
|
||||
if len(right) == 0 {
|
||||
filtered = left
|
||||
return
|
||||
}
|
||||
for _, l := range left {
|
||||
if containsString(right, l) {
|
||||
filtered = append(filtered, l)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Generate a single operation
|
||||
func (o *operationGenerator) Generate() error {
|
||||
// Build a list of codegen operations based on the tags,
|
||||
// the tag decides the actual package for an operation
|
||||
// the user specified package serves as root for generating the directory structure
|
||||
var operations GenOperations
|
||||
authed := len(o.SecurityRequirements) > 0
|
||||
|
||||
var bldr codeGenOpBuilder
|
||||
bldr.Name = o.Name
|
||||
bldr.Method = o.Method
|
||||
bldr.Path = o.Path
|
||||
bldr.BasePath = o.BasePath
|
||||
bldr.ModelsPackage = o.ModelsPackage
|
||||
bldr.Principal = o.Principal
|
||||
bldr.Target = o.Target
|
||||
bldr.Operation = o.Operation
|
||||
bldr.Authed = authed
|
||||
bldr.Security = o.SecurityRequirements
|
||||
bldr.SecurityDefinitions = o.SecurityDefinitions
|
||||
bldr.Doc = o.Doc
|
||||
bldr.Analyzed = o.Analyzed
|
||||
bldr.DefaultScheme = o.DefaultScheme
|
||||
bldr.DefaultProduces = o.DefaultProduces
|
||||
bldr.RootAPIPackage = o.GenOpts.LanguageOpts.ManglePackageName(o.ServerPackage, "server")
|
||||
bldr.GenOpts = o.GenOpts
|
||||
bldr.DefaultConsumes = o.DefaultConsumes
|
||||
bldr.IncludeValidator = o.IncludeValidator
|
||||
defaultImports := o.GenOpts.defaultImports()
|
||||
|
||||
bldr.DefaultImports = []string{o.GenOpts.ExistingModels}
|
||||
if o.GenOpts.ExistingModels == "" {
|
||||
bldr.DefaultImports = []string{
|
||||
path.Join(
|
||||
filepath.ToSlash(o.GenOpts.LanguageOpts.baseImport(o.Base)),
|
||||
o.GenOpts.LanguageOpts.ManglePackagePath(o.ModelsPackage, "")),
|
||||
}
|
||||
apiPackage := o.GenOpts.LanguageOpts.ManglePackagePath(o.GenOpts.APIPackage, defaultOperationsTarget)
|
||||
imports := o.GenOpts.initImports(
|
||||
filepath.Join(o.GenOpts.LanguageOpts.ManglePackagePath(o.GenOpts.ServerPackage, defaultServerTarget), apiPackage))
|
||||
|
||||
bldr := codeGenOpBuilder{
|
||||
ModelsPackage: o.ModelsPackage,
|
||||
Principal: o.GenOpts.PrincipalAlias(),
|
||||
Target: o.Target,
|
||||
DefaultImports: defaultImports,
|
||||
Imports: imports,
|
||||
DefaultScheme: o.DefaultScheme,
|
||||
Doc: o.Doc,
|
||||
Analyzed: o.Analyzed,
|
||||
BasePath: o.BasePath,
|
||||
GenOpts: o.GenOpts,
|
||||
Name: o.Name,
|
||||
Operation: o.Operation,
|
||||
Method: o.Method,
|
||||
Path: o.Path,
|
||||
IncludeValidator: o.IncludeValidator,
|
||||
APIPackage: o.APIPackage, // defaults to main operations package
|
||||
DefaultProduces: o.DefaultProduces,
|
||||
DefaultConsumes: o.DefaultConsumes,
|
||||
Authed: len(o.Analyzed.SecurityRequirementsFor(&o.Operation)) > 0,
|
||||
Security: o.Analyzed.SecurityRequirementsFor(&o.Operation),
|
||||
SecurityDefinitions: o.Analyzed.SecurityDefinitionsFor(&o.Operation),
|
||||
RootAPIPackage: o.GenOpts.LanguageOpts.ManglePackageName(o.ServerPackage, defaultServerTarget),
|
||||
}
|
||||
|
||||
bldr.APIPackage = o.APIPackage
|
||||
st := o.Tags
|
||||
if o.GenOpts != nil {
|
||||
st = o.GenOpts.Tags
|
||||
}
|
||||
intersected := intersectTags(o.Operation.Tags, st)
|
||||
if len(intersected) > 0 {
|
||||
tag := intersected[0]
|
||||
bldr.APIPackage = o.GenOpts.LanguageOpts.ManglePackagePath(tag, o.APIPackage)
|
||||
}
|
||||
_, tags, _ := bldr.analyzeTags()
|
||||
|
||||
op, err := bldr.MakeOperation()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.Tags = intersected
|
||||
|
||||
op.Tags = tags
|
||||
operations := make(GenOperations, 0, 1)
|
||||
operations = append(operations, op)
|
||||
sort.Sort(operations)
|
||||
|
||||
for _, op := range operations {
|
||||
if o.GenOpts.DumpData {
|
||||
bb, _ := json.MarshalIndent(swag.ToDynamicJSON(op), "", " ")
|
||||
fmt.Fprintln(os.Stdout, string(bb))
|
||||
_ = dumpData(swag.ToDynamicJSON(op))
|
||||
continue
|
||||
}
|
||||
if err := o.GenOpts.renderOperation(&op); err != nil {
|
||||
|
@ -268,14 +215,16 @@ type codeGenOpBuilder struct {
|
|||
Path string
|
||||
BasePath string
|
||||
APIPackage string
|
||||
APIPackageAlias string
|
||||
RootAPIPackage string
|
||||
ModelsPackage string
|
||||
Principal string
|
||||
Target string
|
||||
Operation spec.Operation
|
||||
Doc *loads.Document
|
||||
PristineDoc *loads.Document
|
||||
Analyzed *analysis.Spec
|
||||
DefaultImports []string
|
||||
DefaultImports map[string]string
|
||||
Imports map[string]string
|
||||
DefaultScheme string
|
||||
DefaultProduces string
|
||||
|
@ -286,16 +235,57 @@ type codeGenOpBuilder struct {
|
|||
GenOpts *GenOpts
|
||||
}
|
||||
|
||||
// paramMappings yields a map of safe parameter names for an operation
|
||||
func paramMappings(params map[string]spec.Parameter) (map[string]map[string]string, string) {
|
||||
idMapping := map[string]map[string]string{
|
||||
"query": make(map[string]string, len(params)),
|
||||
"path": make(map[string]string, len(params)),
|
||||
"formData": make(map[string]string, len(params)),
|
||||
"header": make(map[string]string, len(params)),
|
||||
"body": make(map[string]string, len(params)),
|
||||
}
|
||||
|
||||
// In order to avoid unstable generation, adopt same naming convention
|
||||
// for all parameters with same name across locations.
|
||||
seenIds := make(map[string]interface{}, len(params))
|
||||
for id, p := range params {
|
||||
if val, ok := seenIds[p.Name]; ok {
|
||||
previous := val.(struct{ id, in string })
|
||||
idMapping[p.In][p.Name] = swag.ToGoName(id)
|
||||
// rewrite the previously found one
|
||||
idMapping[previous.in][p.Name] = swag.ToGoName(previous.id)
|
||||
} else {
|
||||
idMapping[p.In][p.Name] = swag.ToGoName(p.Name)
|
||||
}
|
||||
seenIds[strings.ToLower(idMapping[p.In][p.Name])] = struct{ id, in string }{id: id, in: p.In}
|
||||
}
|
||||
|
||||
// pick a deconflicted private name for timeout for this operation
|
||||
timeoutName := renameTimeout(seenIds, "timeout")
|
||||
|
||||
return idMapping, timeoutName
|
||||
}
|
||||
|
||||
// renameTimeout renames the variable in use by client template to avoid conflicting
|
||||
// with param names.
|
||||
func renameTimeout(seenIds map[string][]string, current string) string {
|
||||
//
|
||||
// NOTE: this merely protects the timeout field in the client parameter struct,
|
||||
// fields "Context" and "HTTPClient" remain exposed to name conflicts.
|
||||
func renameTimeout(seenIds map[string]interface{}, timeoutName string) string {
|
||||
if seenIds == nil {
|
||||
return timeoutName
|
||||
}
|
||||
current := strings.ToLower(timeoutName)
|
||||
if _, ok := seenIds[current]; !ok {
|
||||
return timeoutName
|
||||
}
|
||||
var next string
|
||||
switch strings.ToLower(current) {
|
||||
switch current {
|
||||
case "timeout":
|
||||
next = "requestTimeout"
|
||||
case "requesttimeout":
|
||||
next = "httpRequestTimeout"
|
||||
case "httptrequesttimeout":
|
||||
case "httprequesttimeout":
|
||||
next = "swaggerTimeout"
|
||||
case "swaggertimeout":
|
||||
next = "operationTimeout"
|
||||
|
@ -303,11 +293,10 @@ func renameTimeout(seenIds map[string][]string, current string) string {
|
|||
next = "opTimeout"
|
||||
case "optimeout":
|
||||
next = "operTimeout"
|
||||
default:
|
||||
next = timeoutName + "1"
|
||||
}
|
||||
if _, ok := seenIds[next]; ok {
|
||||
return renameTimeout(seenIds, next)
|
||||
}
|
||||
return next
|
||||
return renameTimeout(seenIds, next)
|
||||
}
|
||||
|
||||
func (b *codeGenOpBuilder) MakeOperation() (GenOperation, error) {
|
||||
|
@ -323,35 +312,15 @@ func (b *codeGenOpBuilder) MakeOperation() (GenOperation, error) {
|
|||
//
|
||||
// In all cases, resetting definitions to the _original_ (untransformed) spec is not an option:
|
||||
// we take from there the spec possibly already transformed by the GenDefinitions stage.
|
||||
resolver := newTypeResolver(b.GenOpts.LanguageOpts.ManglePackageName(b.ModelsPackage, "models"), b.Doc)
|
||||
resolver := newTypeResolver(b.GenOpts.LanguageOpts.ManglePackageName(b.ModelsPackage, defaultModelsTarget), b.Doc)
|
||||
receiver := "o"
|
||||
|
||||
operation := b.Operation
|
||||
var params, qp, pp, hp, fp GenParameters
|
||||
var hasQueryParams, hasPathParams, hasHeaderParams, hasFormParams, hasFileParams, hasFormValueParams, hasBodyParams bool
|
||||
paramsForOperation := b.Analyzed.ParamsFor(b.Method, b.Path)
|
||||
timeoutName := "timeout"
|
||||
|
||||
idMapping := map[string]map[string]string{
|
||||
"query": make(map[string]string, len(paramsForOperation)),
|
||||
"path": make(map[string]string, len(paramsForOperation)),
|
||||
"formData": make(map[string]string, len(paramsForOperation)),
|
||||
"header": make(map[string]string, len(paramsForOperation)),
|
||||
"body": make(map[string]string, len(paramsForOperation)),
|
||||
}
|
||||
|
||||
seenIds := make(map[string][]string, len(paramsForOperation))
|
||||
for id, p := range paramsForOperation {
|
||||
if _, ok := seenIds[p.Name]; ok {
|
||||
idMapping[p.In][p.Name] = swag.ToGoName(id)
|
||||
} else {
|
||||
idMapping[p.In][p.Name] = swag.ToGoName(p.Name)
|
||||
}
|
||||
seenIds[p.Name] = append(seenIds[p.Name], p.In)
|
||||
if strings.EqualFold(p.Name, timeoutName) {
|
||||
timeoutName = renameTimeout(seenIds, timeoutName)
|
||||
}
|
||||
}
|
||||
idMapping, timeoutName := paramMappings(paramsForOperation)
|
||||
|
||||
for _, p := range paramsForOperation {
|
||||
cp, err := b.MakeParameter(receiver, resolver, p, idMapping)
|
||||
|
@ -489,15 +458,17 @@ func (b *codeGenOpBuilder) MakeOperation() (GenOperation, error) {
|
|||
return GenOperation{
|
||||
GenCommon: GenCommon{
|
||||
Copyright: b.GenOpts.Copyright,
|
||||
TargetImportPath: filepath.ToSlash(b.GenOpts.LanguageOpts.baseImport(b.GenOpts.Target)),
|
||||
TargetImportPath: b.GenOpts.LanguageOpts.baseImport(b.GenOpts.Target),
|
||||
},
|
||||
Package: b.GenOpts.LanguageOpts.ManglePackageName(b.APIPackage, "api"),
|
||||
Package: b.GenOpts.LanguageOpts.ManglePackageName(b.APIPackage, defaultOperationsTarget),
|
||||
PackageAlias: b.APIPackageAlias,
|
||||
RootPackage: b.RootAPIPackage,
|
||||
Name: b.Name,
|
||||
Method: b.Method,
|
||||
Path: b.Path,
|
||||
BasePath: b.BasePath,
|
||||
Tags: operation.Tags,
|
||||
UseTags: len(operation.Tags) > 0 && !b.GenOpts.SkipTagPackages,
|
||||
Description: trimBOM(operation.Description),
|
||||
ReceiverName: receiver,
|
||||
DefaultImports: b.DefaultImports,
|
||||
|
@ -531,6 +502,7 @@ func (b *codeGenOpBuilder) MakeOperation() (GenOperation, error) {
|
|||
ExtraSchemes: extraSchemes,
|
||||
TimeoutName: timeoutName,
|
||||
Extensions: operation.Extensions,
|
||||
StrictResponders: b.GenOpts.StrictResponders,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -573,18 +545,20 @@ func (b *codeGenOpBuilder) MakeResponse(receiver, name string, isSuccess bool, r
|
|||
// assume minimal flattening has been carried on, so there is not $ref in response (but some may remain in response schema)
|
||||
|
||||
res := GenResponse{
|
||||
Package: b.GenOpts.LanguageOpts.ManglePackageName(b.APIPackage, "api"),
|
||||
ModelsPackage: b.ModelsPackage,
|
||||
ReceiverName: receiver,
|
||||
Name: name,
|
||||
Description: trimBOM(resp.Description),
|
||||
DefaultImports: b.DefaultImports,
|
||||
Imports: b.Imports,
|
||||
IsSuccess: isSuccess,
|
||||
Code: code,
|
||||
Method: b.Method,
|
||||
Path: b.Path,
|
||||
Extensions: resp.Extensions,
|
||||
Package: b.GenOpts.LanguageOpts.ManglePackageName(b.APIPackage, defaultOperationsTarget),
|
||||
ModelsPackage: b.ModelsPackage,
|
||||
ReceiverName: receiver,
|
||||
Name: name,
|
||||
Description: trimBOM(resp.Description),
|
||||
DefaultImports: b.DefaultImports,
|
||||
Imports: b.Imports,
|
||||
IsSuccess: isSuccess,
|
||||
Code: code,
|
||||
Method: b.Method,
|
||||
Path: b.Path,
|
||||
Extensions: resp.Extensions,
|
||||
StrictResponders: b.GenOpts.StrictResponders,
|
||||
OperationName: b.Name,
|
||||
}
|
||||
|
||||
// prepare response headers
|
||||
|
@ -615,7 +589,7 @@ func (b *codeGenOpBuilder) MakeHeader(receiver, name string, hdr spec.Header) (G
|
|||
res := GenHeader{
|
||||
sharedValidations: sharedValidationsFromSimple(hdr.CommonValidations, true), // NOTE: Required is not defined by the Swagger schema for header. Set arbitrarily to true for convenience in templates.
|
||||
resolvedType: tpe,
|
||||
Package: b.GenOpts.LanguageOpts.ManglePackageName(b.APIPackage, "api"),
|
||||
Package: b.GenOpts.LanguageOpts.ManglePackageName(b.APIPackage, defaultOperationsTarget),
|
||||
ReceiverName: receiver,
|
||||
ID: id,
|
||||
Name: name,
|
||||
|
@ -662,6 +636,7 @@ func (b *codeGenOpBuilder) MakeHeaderItem(receiver, paramName, indexVar, path, v
|
|||
res.Formatter = stringFormatters[res.GoType]
|
||||
res.IndexVar = indexVar
|
||||
res.HasValidations, res.HasSliceValidations = b.HasValidations(items.CommonValidations, res.resolvedType)
|
||||
res.IsEnumCI = b.GenOpts.AllowEnumCI || hasEnumCI(items.Extensions)
|
||||
|
||||
if items.Items != nil {
|
||||
// Recursively follows nested arrays
|
||||
|
@ -684,7 +659,7 @@ func (b *codeGenOpBuilder) HasValidations(sh spec.CommonValidations, rt resolved
|
|||
hasNumberValidation := sh.Maximum != nil || sh.Minimum != nil || sh.MultipleOf != nil
|
||||
hasStringValidation := sh.MaxLength != nil || sh.MinLength != nil || sh.Pattern != ""
|
||||
hasSliceValidations = sh.MaxItems != nil || sh.MinItems != nil || sh.UniqueItems || len(sh.Enum) > 0
|
||||
hasValidations = (hasNumberValidation || hasStringValidation || hasSliceValidations || rt.IsCustomFormatter) && !rt.IsStream && !rt.IsInterface
|
||||
hasValidations = hasNumberValidation || hasStringValidation || hasSliceValidations || hasFormatValidation(rt)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -703,6 +678,8 @@ func (b *codeGenOpBuilder) MakeParameterItem(receiver, paramName, indexVar, path
|
|||
res.IndexVar = indexVar
|
||||
|
||||
res.HasValidations, res.HasSliceValidations = b.HasValidations(items.CommonValidations, res.resolvedType)
|
||||
res.IsEnumCI = b.GenOpts.AllowEnumCI || hasEnumCI(items.Extensions)
|
||||
res.NeedsIndex = res.HasValidations || res.Converter != "" || (res.IsCustomFormatter && !res.SkipParse)
|
||||
|
||||
if items.Items != nil {
|
||||
// Recursively follows nested arrays
|
||||
|
@ -715,6 +692,7 @@ func (b *codeGenOpBuilder) MakeParameterItem(receiver, paramName, indexVar, path
|
|||
pi.Parent = &res
|
||||
// Propagates HasValidations flag to outer Items definition
|
||||
res.HasValidations = res.HasValidations || pi.HasValidations
|
||||
res.NeedsIndex = res.NeedsIndex || pi.NeedsIndex
|
||||
}
|
||||
|
||||
return res, nil
|
||||
|
@ -727,7 +705,13 @@ func (b *codeGenOpBuilder) MakeParameter(receiver string, resolver *typeResolver
|
|||
|
||||
var child *GenItems
|
||||
id := swag.ToGoName(param.Name)
|
||||
if len(idMapping) > 0 {
|
||||
if goName, ok := param.Extensions["x-go-name"]; ok {
|
||||
id, ok = goName.(string)
|
||||
if !ok {
|
||||
return GenParameter{}, fmt.Errorf(`%s %s, parameter %q: "x-go-name" field must be a string, not a %T`,
|
||||
b.Method, b.Path, param.Name, goName)
|
||||
}
|
||||
} else if len(idMapping) > 0 {
|
||||
id = idMapping[param.In][param.Name]
|
||||
}
|
||||
|
||||
|
@ -776,6 +760,7 @@ func (b *codeGenOpBuilder) MakeParameter(receiver string, resolver *typeResolver
|
|||
res.IsNullable = !param.Required && !param.AllowEmptyValue
|
||||
res.HasValidations, res.HasSliceValidations = b.HasValidations(param.CommonValidations, res.resolvedType)
|
||||
res.HasValidations = res.HasValidations || hasChildValidations
|
||||
res.IsEnumCI = b.GenOpts.AllowEnumCI || hasEnumCI(param.Extensions)
|
||||
}
|
||||
|
||||
// Select codegen strategy for body param validation
|
||||
|
@ -875,9 +860,10 @@ func (b *codeGenOpBuilder) MakeBodyParameterItemsAndMaps(res *GenParameter, it *
|
|||
next.IsAliased = true
|
||||
break
|
||||
}
|
||||
if next.IsInterface || next.IsStream {
|
||||
if next.IsInterface || next.IsStream || next.IsBase64 {
|
||||
next.HasValidations = false
|
||||
}
|
||||
next.NeedsIndex = next.HasValidations || next.Converter != "" || (next.IsCustomFormatter && !next.SkipParse)
|
||||
prev = next
|
||||
next = new(GenItems)
|
||||
|
||||
|
@ -891,15 +877,17 @@ func (b *codeGenOpBuilder) MakeBodyParameterItemsAndMaps(res *GenParameter, it *
|
|||
}
|
||||
}
|
||||
// propagate HasValidations
|
||||
var propag func(child *GenItems) bool
|
||||
propag = func(child *GenItems) bool {
|
||||
var propag func(child *GenItems) (bool, bool)
|
||||
propag = func(child *GenItems) (bool, bool) {
|
||||
if child == nil {
|
||||
return false
|
||||
return false, false
|
||||
}
|
||||
child.HasValidations = child.HasValidations || propag(child.Child)
|
||||
return child.HasValidations
|
||||
cValidations, cIndex := propag(child.Child)
|
||||
child.HasValidations = child.HasValidations || cValidations
|
||||
child.NeedsIndex = child.HasValidations || child.Converter != "" || (child.IsCustomFormatter && !child.SkipParse) || cIndex
|
||||
return child.HasValidations, child.NeedsIndex
|
||||
}
|
||||
items.HasValidations = propag(items)
|
||||
items.HasValidations, items.NeedsIndex = propag(items)
|
||||
|
||||
// resolve nullability conflicts when declaring body as a map of array of an anonymous complex object
|
||||
// (e.g. refer to an extra schema type, which is nullable, but not rendered as a pointer in arrays or maps)
|
||||
|
@ -938,7 +926,7 @@ func (b *codeGenOpBuilder) setBodyParamValidation(p *GenParameter) {
|
|||
var hasSimpleBodyParams, hasSimpleBodyItems, hasSimpleBodyMap, hasModelBodyParams, hasModelBodyItems, hasModelBodyMap bool
|
||||
s := p.Schema
|
||||
if s != nil {
|
||||
doNot := s.IsInterface || s.IsStream
|
||||
doNot := s.IsInterface || s.IsStream || s.IsBase64
|
||||
// composition of primitive fields must be properly identified: hack this through
|
||||
_, isPrimitive := primitives[s.GoType]
|
||||
_, isFormatter := customFormatters[s.GoType]
|
||||
|
@ -949,7 +937,7 @@ func (b *codeGenOpBuilder) setBodyParamValidation(p *GenParameter) {
|
|||
|
||||
if s.IsArray && s.Items != nil {
|
||||
it := s.Items
|
||||
doNot = it.IsInterface || it.IsStream
|
||||
doNot = it.IsInterface || it.IsStream || it.IsBase64
|
||||
hasSimpleBodyItems = !it.IsComplexObject && !(it.IsAliased || doNot)
|
||||
hasModelBodyItems = (it.IsComplexObject || it.IsAliased) && !doNot
|
||||
}
|
||||
|
@ -1015,7 +1003,10 @@ func (b *codeGenOpBuilder) cloneSchema(schema *spec.Schema) *spec.Schema {
|
|||
// This uses a deep clone the spec document to construct a type resolver which knows about definitions when the making of this operation started,
|
||||
// and only these definitions. We are not interested in the "original spec", but in the already transformed spec.
|
||||
func (b *codeGenOpBuilder) saveResolveContext(resolver *typeResolver, schema *spec.Schema) (*typeResolver, *spec.Schema) {
|
||||
rslv := newTypeResolver(b.GenOpts.LanguageOpts.ManglePackageName(resolver.ModelsPackage, "models"), b.Doc.Pristine())
|
||||
if b.PristineDoc == nil {
|
||||
b.PristineDoc = b.Doc.Pristine()
|
||||
}
|
||||
rslv := newTypeResolver(b.GenOpts.LanguageOpts.ManglePackageName(resolver.ModelsPackage, defaultModelsTarget), b.PristineDoc)
|
||||
|
||||
return rslv, b.cloneSchema(schema)
|
||||
}
|
||||
|
@ -1027,19 +1018,23 @@ func (b *codeGenOpBuilder) saveResolveContext(resolver *typeResolver, schema *sp
|
|||
// these ExtraSchemas in the operation's package.
|
||||
// We need to rebuild the schema with a new type resolver to reflect this change in the
|
||||
// models package.
|
||||
func (b *codeGenOpBuilder) liftExtraSchemas(resolver, br *typeResolver, bs *spec.Schema, sc *schemaGenContext) (schema *GenSchema, err error) {
|
||||
func (b *codeGenOpBuilder) liftExtraSchemas(resolver, rslv *typeResolver, bs *spec.Schema, sc *schemaGenContext) (schema *GenSchema, err error) {
|
||||
// restore resolving state before previous call to makeGenSchema()
|
||||
rslv := br
|
||||
sc.Schema = *bs
|
||||
|
||||
pg := sc.shallowClone()
|
||||
pkg := b.GenOpts.LanguageOpts.ManglePackageName(resolver.ModelsPackage, "models")
|
||||
pkg := b.GenOpts.LanguageOpts.ManglePackageName(resolver.ModelsPackage, defaultModelsTarget)
|
||||
|
||||
// make a resolver for current package (i.e. operations)
|
||||
pg.TypeResolver = newTypeResolver("", rslv.Doc).withKeepDefinitionsPackage(pkg)
|
||||
pg.ExtraSchemas = make(map[string]GenSchema, len(sc.ExtraSchemas))
|
||||
pg.UseContainerInName = true
|
||||
|
||||
// rebuild schema within local package
|
||||
if err = pg.makeGenSchema(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// lift nested extra schemas (inlined types)
|
||||
if b.ExtraSchemas == nil {
|
||||
b.ExtraSchemas = make(map[string]GenSchema, len(pg.ExtraSchemas))
|
||||
|
@ -1079,17 +1074,20 @@ func (b *codeGenOpBuilder) buildOperationSchema(schemaPath, containerName, schem
|
|||
TypeResolver: rslv,
|
||||
Named: false,
|
||||
IncludeModel: true,
|
||||
IncludeValidator: true,
|
||||
IncludeValidator: b.GenOpts.IncludeValidator,
|
||||
StrictAdditionalProperties: b.GenOpts.StrictAdditionalProperties,
|
||||
ExtraSchemas: make(map[string]GenSchema),
|
||||
StructTags: b.GenOpts.StructTags,
|
||||
}
|
||||
|
||||
var (
|
||||
br *typeResolver
|
||||
bs *spec.Schema
|
||||
)
|
||||
// these backups are not needed when sch has name.
|
||||
|
||||
if sch.Ref.String() == "" {
|
||||
// backup the type resolver context
|
||||
// (not needed when the schema has a name)
|
||||
br, bs = b.saveResolveContext(rslv, sch)
|
||||
}
|
||||
|
||||
|
@ -1148,3 +1146,119 @@ func (b *codeGenOpBuilder) buildOperationSchema(schemaPath, containerName, schem
|
|||
}
|
||||
return schema, nil
|
||||
}
|
||||
|
||||
func intersectTags(left, right []string) []string {
|
||||
// dedupe
|
||||
uniqueTags := make(map[string]struct{}, maxInt(len(left), len(right)))
|
||||
for _, l := range left {
|
||||
if len(right) == 0 || swag.ContainsStrings(right, l) {
|
||||
uniqueTags[l] = struct{}{}
|
||||
}
|
||||
}
|
||||
filtered := make([]string, 0, len(uniqueTags))
|
||||
// stable output across generations, preserving original order
|
||||
for _, k := range left {
|
||||
if _, ok := uniqueTags[k]; !ok {
|
||||
continue
|
||||
}
|
||||
filtered = append(filtered, k)
|
||||
delete(uniqueTags, k)
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
|
||||
// analyze tags for an operation
|
||||
func (b *codeGenOpBuilder) analyzeTags() (string, []string, bool) {
|
||||
var (
|
||||
filter []string
|
||||
tag string
|
||||
hasTagOverride bool
|
||||
)
|
||||
if b.GenOpts != nil {
|
||||
filter = b.GenOpts.Tags
|
||||
}
|
||||
intersected := intersectTags(pruneEmpty(b.Operation.Tags), filter)
|
||||
if !b.GenOpts.SkipTagPackages && len(intersected) > 0 {
|
||||
// override generation with: x-go-operation-tag
|
||||
tag, hasTagOverride = b.Operation.Extensions.GetString(xGoOperationTag)
|
||||
if !hasTagOverride {
|
||||
// TODO(fred): this part should be delegated to some new TagsFor(operation) in go-openapi/analysis
|
||||
tag = intersected[0]
|
||||
gtags := b.Doc.Spec().Tags
|
||||
for _, gtag := range gtags {
|
||||
if gtag.Name != tag {
|
||||
continue
|
||||
}
|
||||
// honor x-go-name in tag
|
||||
if name, hasGoName := gtag.Extensions.GetString(xGoName); hasGoName {
|
||||
tag = name
|
||||
break
|
||||
}
|
||||
// honor x-go-operation-tag in tag
|
||||
if name, hasOpName := gtag.Extensions.GetString(xGoOperationTag); hasOpName {
|
||||
tag = name
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if tag == b.APIPackage {
|
||||
// confict with "operations" package is handled separately
|
||||
tag = renameOperationPackage(intersected, tag)
|
||||
}
|
||||
b.APIPackage = b.GenOpts.LanguageOpts.ManglePackageName(tag, b.APIPackage) // actual package name
|
||||
b.APIPackageAlias = deconflictTag(intersected, b.APIPackage) // deconflicted import alias
|
||||
return tag, intersected, len(filter) == 0 || len(filter) > 0 && len(intersected) > 0
|
||||
}
|
||||
|
||||
func maxInt(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// deconflictTag ensures generated packages for operations based on tags do not conflict
|
||||
// with other imports
|
||||
func deconflictTag(seenTags []string, pkg string) string {
|
||||
return deconflictPkg(pkg, func(pkg string) string { return renameOperationPackage(seenTags, pkg) })
|
||||
}
|
||||
|
||||
// deconflictPrincipal ensures that whenever an external principal package is added, it doesn't conflict
|
||||
// with standard inports
|
||||
func deconflictPrincipal(pkg string) string {
|
||||
switch pkg {
|
||||
case "principal":
|
||||
return renamePrincipalPackage(pkg)
|
||||
default:
|
||||
return deconflictPkg(pkg, renamePrincipalPackage)
|
||||
}
|
||||
}
|
||||
|
||||
// deconflictPkg renames package names which conflict with standard imports
|
||||
func deconflictPkg(pkg string, renamer func(string) string) string {
|
||||
switch pkg {
|
||||
case "api", "httptransport", "formats":
|
||||
fallthrough
|
||||
case "errors", "runtime", "middleware", "security", "spec", "strfmt", "loads", "swag", "validate":
|
||||
fallthrough
|
||||
case "tls", "http", "fmt", "strings", "log":
|
||||
return renamer(pkg)
|
||||
}
|
||||
return pkg
|
||||
}
|
||||
|
||||
func renameOperationPackage(seenTags []string, pkg string) string {
|
||||
current := strings.ToLower(pkg) + "ops"
|
||||
if len(seenTags) == 0 {
|
||||
return current
|
||||
}
|
||||
for swag.ContainsStringsCI(seenTags, current) {
|
||||
current += "1"
|
||||
}
|
||||
return current
|
||||
}
|
||||
|
||||
func renamePrincipalPackage(pkg string) string {
|
||||
return "auth"
|
||||
}
|
||||
|
|
719
vendor/github.com/go-swagger/go-swagger/generator/shared.go
generated
vendored
719
vendor/github.com/go-swagger/go-swagger/generator/shared.go
generated
vendored
|
@ -16,6 +16,7 @@ package generator
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
@ -24,360 +25,36 @@ import (
|
|||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
"unicode"
|
||||
|
||||
swaggererrors "github.com/go-openapi/errors"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
"golang.org/x/tools/imports"
|
||||
)
|
||||
|
||||
//go:generate go-bindata -mode 420 -modtime 1482416923 -pkg=generator -ignore=.*\.sw? -ignore=.*\.md ./templates/...
|
||||
|
||||
// LanguageOpts to describe a language to the code generator
|
||||
type LanguageOpts struct {
|
||||
ReservedWords []string
|
||||
BaseImportFunc func(string) string `json:"-"`
|
||||
reservedWordsSet map[string]struct{}
|
||||
initialized bool
|
||||
formatFunc func(string, []byte) ([]byte, error)
|
||||
fileNameFunc func(string) string
|
||||
}
|
||||
const (
|
||||
// default generation targets structure
|
||||
defaultModelsTarget = "models"
|
||||
defaultServerTarget = "restapi"
|
||||
defaultClientTarget = "client"
|
||||
defaultOperationsTarget = "operations"
|
||||
defaultClientName = "rest"
|
||||
defaultServerName = "swagger"
|
||||
defaultScheme = "http"
|
||||
)
|
||||
|
||||
// Init the language option
|
||||
func (l *LanguageOpts) Init() {
|
||||
if !l.initialized {
|
||||
l.initialized = true
|
||||
l.reservedWordsSet = make(map[string]struct{})
|
||||
for _, rw := range l.ReservedWords {
|
||||
l.reservedWordsSet[rw] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MangleName makes sure a reserved word gets a safe name
|
||||
func (l *LanguageOpts) MangleName(name, suffix string) string {
|
||||
if _, ok := l.reservedWordsSet[swag.ToFileName(name)]; !ok {
|
||||
return name
|
||||
}
|
||||
return strings.Join([]string{name, suffix}, "_")
|
||||
}
|
||||
|
||||
// MangleVarName makes sure a reserved word gets a safe name
|
||||
func (l *LanguageOpts) MangleVarName(name string) string {
|
||||
nm := swag.ToVarName(name)
|
||||
if _, ok := l.reservedWordsSet[nm]; !ok {
|
||||
return nm
|
||||
}
|
||||
return nm + "Var"
|
||||
}
|
||||
|
||||
// MangleFileName makes sure a file name gets a safe name
|
||||
func (l *LanguageOpts) MangleFileName(name string) string {
|
||||
if l.fileNameFunc != nil {
|
||||
return l.fileNameFunc(name)
|
||||
}
|
||||
return swag.ToFileName(name)
|
||||
}
|
||||
|
||||
// ManglePackageName makes sure a package gets a safe name.
|
||||
// In case of a file system path (e.g. name contains "/" or "\" on Windows), this return only the last element.
|
||||
func (l *LanguageOpts) ManglePackageName(name, suffix string) string {
|
||||
if name == "" {
|
||||
return suffix
|
||||
}
|
||||
pth := filepath.ToSlash(filepath.Clean(name)) // preserve path
|
||||
_, pkg := path.Split(pth) // drop path
|
||||
return l.MangleName(swag.ToFileName(pkg), suffix)
|
||||
}
|
||||
|
||||
// ManglePackagePath makes sure a full package path gets a safe name.
|
||||
// Only the last part of the path is altered.
|
||||
func (l *LanguageOpts) ManglePackagePath(name string, suffix string) string {
|
||||
if name == "" {
|
||||
return suffix
|
||||
}
|
||||
target := filepath.ToSlash(filepath.Clean(name)) // preserve path
|
||||
parts := strings.Split(target, "/")
|
||||
parts[len(parts)-1] = l.ManglePackageName(parts[len(parts)-1], suffix)
|
||||
return strings.Join(parts, "/")
|
||||
}
|
||||
|
||||
// FormatContent formats a file with a language specific formatter
|
||||
func (l *LanguageOpts) FormatContent(name string, content []byte) ([]byte, error) {
|
||||
if l.formatFunc != nil {
|
||||
return l.formatFunc(name, content)
|
||||
}
|
||||
return content, nil
|
||||
}
|
||||
|
||||
func (l *LanguageOpts) baseImport(tgt string) string {
|
||||
if l.BaseImportFunc != nil {
|
||||
return l.BaseImportFunc(tgt)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var golang = GoLangOpts()
|
||||
|
||||
// GoLangOpts for rendering items as golang code
|
||||
func GoLangOpts() *LanguageOpts {
|
||||
var goOtherReservedSuffixes = map[string]bool{
|
||||
// see:
|
||||
// https://golang.org/src/go/build/syslist.go
|
||||
// https://golang.org/doc/install/source#environment
|
||||
|
||||
// goos
|
||||
"android": true,
|
||||
"darwin": true,
|
||||
"dragonfly": true,
|
||||
"freebsd": true,
|
||||
"js": true,
|
||||
"linux": true,
|
||||
"nacl": true,
|
||||
"netbsd": true,
|
||||
"openbsd": true,
|
||||
"plan9": true,
|
||||
"solaris": true,
|
||||
"windows": true,
|
||||
"zos": true,
|
||||
|
||||
// arch
|
||||
"386": true,
|
||||
"amd64": true,
|
||||
"amd64p32": true,
|
||||
"arm": true,
|
||||
"armbe": true,
|
||||
"arm64": true,
|
||||
"arm64be": true,
|
||||
"mips": true,
|
||||
"mipsle": true,
|
||||
"mips64": true,
|
||||
"mips64le": true,
|
||||
"mips64p32": true,
|
||||
"mips64p32le": true,
|
||||
"ppc": true,
|
||||
"ppc64": true,
|
||||
"ppc64le": true,
|
||||
"riscv": true,
|
||||
"riscv64": true,
|
||||
"s390": true,
|
||||
"s390x": true,
|
||||
"sparc": true,
|
||||
"sparc64": true,
|
||||
"wasm": true,
|
||||
|
||||
// other reserved suffixes
|
||||
"test": true,
|
||||
}
|
||||
|
||||
opts := new(LanguageOpts)
|
||||
opts.ReservedWords = []string{
|
||||
"break", "default", "func", "interface", "select",
|
||||
"case", "defer", "go", "map", "struct",
|
||||
"chan", "else", "goto", "package", "switch",
|
||||
"const", "fallthrough", "if", "range", "type",
|
||||
"continue", "for", "import", "return", "var",
|
||||
}
|
||||
opts.formatFunc = func(ffn string, content []byte) ([]byte, error) {
|
||||
opts := new(imports.Options)
|
||||
opts.TabIndent = true
|
||||
opts.TabWidth = 2
|
||||
opts.Fragment = true
|
||||
opts.Comments = true
|
||||
return imports.Process(ffn, content, opts)
|
||||
}
|
||||
opts.fileNameFunc = func(name string) string {
|
||||
// whenever a generated file name ends with a suffix
|
||||
// that is meaningful to go build, adds a "swagger"
|
||||
// suffix
|
||||
parts := strings.Split(swag.ToFileName(name), "_")
|
||||
if goOtherReservedSuffixes[parts[len(parts)-1]] {
|
||||
// file name ending with a reserved arch or os name
|
||||
// are appended an innocuous suffix "swagger"
|
||||
parts = append(parts, "swagger")
|
||||
}
|
||||
return strings.Join(parts, "_")
|
||||
}
|
||||
|
||||
opts.BaseImportFunc = func(tgt string) string {
|
||||
tgt = filepath.Clean(tgt)
|
||||
// On Windows, filepath.Abs("") behaves differently than on Unix.
|
||||
// Windows: yields an error, since Abs() does not know the volume.
|
||||
// UNIX: returns current working directory
|
||||
if tgt == "" {
|
||||
tgt = "."
|
||||
}
|
||||
tgtAbsPath, err := filepath.Abs(tgt)
|
||||
if err != nil {
|
||||
log.Fatalf("could not evaluate base import path with target \"%s\": %v", tgt, err)
|
||||
}
|
||||
|
||||
var tgtAbsPathExtended string
|
||||
tgtAbsPathExtended, err = filepath.EvalSymlinks(tgtAbsPath)
|
||||
if err != nil {
|
||||
log.Fatalf("could not evaluate base import path with target \"%s\" (with symlink resolution): %v", tgtAbsPath, err)
|
||||
}
|
||||
|
||||
gopath := os.Getenv("GOPATH")
|
||||
if gopath == "" {
|
||||
gopath = filepath.Join(os.Getenv("HOME"), "go")
|
||||
}
|
||||
|
||||
var pth string
|
||||
for _, gp := range filepath.SplitList(gopath) {
|
||||
// EvalSymLinks also calls the Clean
|
||||
gopathExtended, er := filepath.EvalSymlinks(gp)
|
||||
if er != nil {
|
||||
log.Fatalln(er)
|
||||
}
|
||||
gopathExtended = filepath.Join(gopathExtended, "src")
|
||||
gp = filepath.Join(gp, "src")
|
||||
|
||||
// At this stage we have expanded and unexpanded target path. GOPATH is fully expanded.
|
||||
// Expanded means symlink free.
|
||||
// We compare both types of targetpath<s> with gopath.
|
||||
// If any one of them coincides with gopath , it is imperative that
|
||||
// target path lies inside gopath. How?
|
||||
// - Case 1: Irrespective of symlinks paths coincide. Both non-expanded paths.
|
||||
// - Case 2: Symlink in target path points to location inside GOPATH. (Expanded Target Path)
|
||||
// - Case 3: Symlink in target path points to directory outside GOPATH (Unexpanded target path)
|
||||
|
||||
// Case 1: - Do nothing case. If non-expanded paths match just generate base import path as if
|
||||
// there are no symlinks.
|
||||
|
||||
// Case 2: - Symlink in target path points to location inside GOPATH. (Expanded Target Path)
|
||||
// First if will fail. Second if will succeed.
|
||||
|
||||
// Case 3: - Symlink in target path points to directory outside GOPATH (Unexpanded target path)
|
||||
// First if will succeed and break.
|
||||
|
||||
//compares non expanded path for both
|
||||
if ok, relativepath := checkPrefixAndFetchRelativePath(tgtAbsPath, gp); ok {
|
||||
pth = relativepath
|
||||
break
|
||||
}
|
||||
|
||||
// Compares non-expanded target path
|
||||
if ok, relativepath := checkPrefixAndFetchRelativePath(tgtAbsPath, gopathExtended); ok {
|
||||
pth = relativepath
|
||||
break
|
||||
}
|
||||
|
||||
// Compares expanded target path.
|
||||
if ok, relativepath := checkPrefixAndFetchRelativePath(tgtAbsPathExtended, gopathExtended); ok {
|
||||
pth = relativepath
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mod, goModuleAbsPath, err := tryResolveModule(tgtAbsPath)
|
||||
switch {
|
||||
case err != nil:
|
||||
log.Fatalf("Failed to resolve module using go.mod file: %s", err)
|
||||
case mod != "":
|
||||
relTgt := relPathToRelGoPath(goModuleAbsPath, tgtAbsPath)
|
||||
if !strings.HasSuffix(mod, relTgt) {
|
||||
return mod + relTgt
|
||||
}
|
||||
return mod
|
||||
}
|
||||
|
||||
if pth == "" {
|
||||
log.Fatalln("target must reside inside a location in the $GOPATH/src or be a module")
|
||||
}
|
||||
return pth
|
||||
}
|
||||
opts.Init()
|
||||
return opts
|
||||
}
|
||||
|
||||
var moduleRe = regexp.MustCompile(`module[ \t]+([^\s]+)`)
|
||||
|
||||
// resolveGoModFile walks up the directory tree starting from 'dir' until it
|
||||
// finds a go.mod file. If go.mod is found it will return the related file
|
||||
// object. If no go.mod file is found it will return an error.
|
||||
func resolveGoModFile(dir string) (*os.File, string, error) {
|
||||
goModPath := filepath.Join(dir, "go.mod")
|
||||
f, err := os.Open(goModPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) && dir != filepath.Dir(dir) {
|
||||
return resolveGoModFile(filepath.Dir(dir))
|
||||
}
|
||||
return nil, "", err
|
||||
}
|
||||
return f, dir, nil
|
||||
}
|
||||
|
||||
// relPathToRelGoPath takes a relative os path and returns the relative go
|
||||
// package path. For unix nothing will change but for windows \ will be
|
||||
// converted to /.
|
||||
func relPathToRelGoPath(modAbsPath, absPath string) string {
|
||||
if absPath == "." {
|
||||
return ""
|
||||
}
|
||||
|
||||
path := strings.TrimPrefix(absPath, modAbsPath)
|
||||
pathItems := strings.Split(path, string(filepath.Separator))
|
||||
return strings.Join(pathItems, "/")
|
||||
}
|
||||
|
||||
func tryResolveModule(baseTargetPath string) (string, string, error) {
|
||||
f, goModAbsPath, err := resolveGoModFile(baseTargetPath)
|
||||
switch {
|
||||
case os.IsNotExist(err):
|
||||
return "", "", nil
|
||||
case err != nil:
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
src, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
match := moduleRe.FindSubmatch(src)
|
||||
if len(match) != 2 {
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
return string(match[1]), goModAbsPath, nil
|
||||
}
|
||||
|
||||
func findSwaggerSpec(nm string) (string, error) {
|
||||
specs := []string{"swagger.json", "swagger.yml", "swagger.yaml"}
|
||||
if nm != "" {
|
||||
specs = []string{nm}
|
||||
}
|
||||
var name string
|
||||
for _, nn := range specs {
|
||||
f, err := os.Stat(nn)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return "", err
|
||||
}
|
||||
if err != nil && os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
if f.IsDir() {
|
||||
return "", fmt.Errorf("%s is a directory", nn)
|
||||
}
|
||||
name = nn
|
||||
break
|
||||
}
|
||||
if name == "" {
|
||||
return "", errors.New("couldn't find a swagger spec")
|
||||
}
|
||||
return name, nil
|
||||
func init() {
|
||||
// all initializations for the generator package
|
||||
debugOptions()
|
||||
initLanguage()
|
||||
initTemplateRepo()
|
||||
initTypes()
|
||||
}
|
||||
|
||||
// DefaultSectionOpts for a given opts, this is used when no config file is passed
|
||||
|
@ -411,14 +88,13 @@ func DefaultSectionOpts(gen *GenOpts) {
|
|||
FileName: "{{ (snakize (pascalize .Name)) }}_responses.go",
|
||||
},
|
||||
}
|
||||
|
||||
} else {
|
||||
ops := []TemplateOpts{}
|
||||
if gen.IncludeParameters {
|
||||
ops = append(ops, TemplateOpts{
|
||||
Name: "parameters",
|
||||
Source: "asset:serverParameter",
|
||||
Target: "{{ if gt (len .Tags) 0 }}{{ joinFilePath .Target (toPackagePath .ServerPackage) (toPackagePath .APIPackage) (toPackagePath .Package) }}{{ else }}{{ joinFilePath .Target (toPackagePath .ServerPackage) (toPackagePath .Package) }}{{ end }}",
|
||||
Target: "{{ if .UseTags }}{{ joinFilePath .Target (toPackagePath .ServerPackage) (toPackagePath .APIPackage) (toPackagePath .Package) }}{{ else }}{{ joinFilePath .Target (toPackagePath .ServerPackage) (toPackagePath .Package) }}{{ end }}",
|
||||
FileName: "{{ (snakize (pascalize .Name)) }}_parameters.go",
|
||||
})
|
||||
}
|
||||
|
@ -426,7 +102,7 @@ func DefaultSectionOpts(gen *GenOpts) {
|
|||
ops = append(ops, TemplateOpts{
|
||||
Name: "urlbuilder",
|
||||
Source: "asset:serverUrlbuilder",
|
||||
Target: "{{ if gt (len .Tags) 0 }}{{ joinFilePath .Target (toPackagePath .ServerPackage) (toPackagePath .APIPackage) (toPackagePath .Package) }}{{ else }}{{ joinFilePath .Target (toPackagePath .ServerPackage) (toPackagePath .Package) }}{{ end }}",
|
||||
Target: "{{ if .UseTags }}{{ joinFilePath .Target (toPackagePath .ServerPackage) (toPackagePath .APIPackage) (toPackagePath .Package) }}{{ else }}{{ joinFilePath .Target (toPackagePath .ServerPackage) (toPackagePath .Package) }}{{ end }}",
|
||||
FileName: "{{ (snakize (pascalize .Name)) }}_urlbuilder.go",
|
||||
})
|
||||
}
|
||||
|
@ -434,7 +110,7 @@ func DefaultSectionOpts(gen *GenOpts) {
|
|||
ops = append(ops, TemplateOpts{
|
||||
Name: "responses",
|
||||
Source: "asset:serverResponses",
|
||||
Target: "{{ if gt (len .Tags) 0 }}{{ joinFilePath .Target (toPackagePath .ServerPackage) (toPackagePath .APIPackage) (toPackagePath .Package) }}{{ else }}{{ joinFilePath .Target (toPackagePath .ServerPackage) (toPackagePath .Package) }}{{ end }}",
|
||||
Target: "{{ if .UseTags }}{{ joinFilePath .Target (toPackagePath .ServerPackage) (toPackagePath .APIPackage) (toPackagePath .Package) }}{{ else }}{{ joinFilePath .Target (toPackagePath .ServerPackage) (toPackagePath .Package) }}{{ end }}",
|
||||
FileName: "{{ (snakize (pascalize .Name)) }}_responses.go",
|
||||
})
|
||||
}
|
||||
|
@ -442,7 +118,7 @@ func DefaultSectionOpts(gen *GenOpts) {
|
|||
ops = append(ops, TemplateOpts{
|
||||
Name: "handler",
|
||||
Source: "asset:serverOperation",
|
||||
Target: "{{ if gt (len .Tags) 0 }}{{ joinFilePath .Target (toPackagePath .ServerPackage) (toPackagePath .APIPackage) (toPackagePath .Package) }}{{ else }}{{ joinFilePath .Target (toPackagePath .ServerPackage) (toPackagePath .Package) }}{{ end }}",
|
||||
Target: "{{ if .UseTags }}{{ joinFilePath .Target (toPackagePath .ServerPackage) (toPackagePath .APIPackage) (toPackagePath .Package) }}{{ else }}{{ joinFilePath .Target (toPackagePath .ServerPackage) (toPackagePath .Package) }}{{ end }}",
|
||||
FileName: "{{ (snakize (pascalize .Name)) }}.go",
|
||||
})
|
||||
}
|
||||
|
@ -487,7 +163,7 @@ func DefaultSectionOpts(gen *GenOpts) {
|
|||
{
|
||||
Name: "main",
|
||||
Source: "asset:serverMain",
|
||||
Target: "{{ joinFilePath .Target \"cmd\" (dasherize (pascalize .Name)) }}-server",
|
||||
Target: "{{ joinFilePath .Target \"cmd\" .MainPackage }}",
|
||||
FileName: "main.go",
|
||||
},
|
||||
{
|
||||
|
@ -521,7 +197,7 @@ func DefaultSectionOpts(gen *GenOpts) {
|
|||
|
||||
}
|
||||
|
||||
// TemplateOpts allows
|
||||
// TemplateOpts allows for codegen customization
|
||||
type TemplateOpts struct {
|
||||
Name string `mapstructure:"name"`
|
||||
Source string `mapstructure:"source"`
|
||||
|
@ -573,37 +249,58 @@ type GenOpts struct {
|
|||
DefaultScheme string
|
||||
DefaultProduces string
|
||||
DefaultConsumes string
|
||||
WithXML bool
|
||||
TemplateDir string
|
||||
Template string
|
||||
RegenerateConfigureAPI bool
|
||||
Operations []string
|
||||
Models []string
|
||||
Tags []string
|
||||
StructTags []string
|
||||
Name string
|
||||
FlagStrategy string
|
||||
CompatibilityMode string
|
||||
ExistingModels string
|
||||
Copyright string
|
||||
SkipTagPackages bool
|
||||
MainPackage string
|
||||
IgnoreOperations bool
|
||||
AllowEnumCI bool
|
||||
StrictResponders bool
|
||||
AcceptDefinitionsOnly bool
|
||||
}
|
||||
|
||||
// CheckOpts carries out some global consistency checks on options.
|
||||
//
|
||||
// At the moment, these checks simply protect TargetPath() and SpecPath()
|
||||
// functions. More checks may be added here.
|
||||
func (g *GenOpts) CheckOpts() error {
|
||||
if g == nil {
|
||||
return errors.New("gen opts are required")
|
||||
}
|
||||
|
||||
if !filepath.IsAbs(g.Target) {
|
||||
if _, err := filepath.Abs(g.Target); err != nil {
|
||||
return fmt.Errorf("could not locate target %s: %v", g.Target, err)
|
||||
}
|
||||
}
|
||||
|
||||
if filepath.IsAbs(g.ServerPackage) {
|
||||
return fmt.Errorf("you shouldn't specify an absolute path in --server-package: %s", g.ServerPackage)
|
||||
}
|
||||
if !filepath.IsAbs(g.Spec) && !strings.HasPrefix(g.Spec, "http://") && !strings.HasPrefix(g.Spec, "https://") {
|
||||
if _, err := filepath.Abs(g.Spec); err != nil {
|
||||
return fmt.Errorf("could not locate spec: %s", g.Spec)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(g.Spec, "http://") || strings.HasPrefix(g.Spec, "https://") {
|
||||
return nil
|
||||
}
|
||||
|
||||
pth, err := findSwaggerSpec(g.Spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// ensure spec path is absolute
|
||||
g.Spec, err = filepath.Abs(pth)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not locate spec: %s", g.Spec)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -670,17 +367,42 @@ func (g *GenOpts) EnsureDefaults() error {
|
|||
if g.defaultsEnsured {
|
||||
return nil
|
||||
}
|
||||
DefaultSectionOpts(g)
|
||||
|
||||
if g.LanguageOpts == nil {
|
||||
g.LanguageOpts = GoLangOpts()
|
||||
g.LanguageOpts = DefaultLanguageFunc()
|
||||
}
|
||||
|
||||
DefaultSectionOpts(g)
|
||||
|
||||
// set defaults for flattening options
|
||||
g.FlattenOpts = &analysis.FlattenOpts{
|
||||
Minimal: true,
|
||||
Verbose: true,
|
||||
RemoveUnused: false,
|
||||
Expand: false,
|
||||
if g.FlattenOpts == nil {
|
||||
g.FlattenOpts = &analysis.FlattenOpts{
|
||||
Minimal: true,
|
||||
Verbose: true,
|
||||
RemoveUnused: false,
|
||||
Expand: false,
|
||||
}
|
||||
}
|
||||
|
||||
if g.DefaultScheme == "" {
|
||||
g.DefaultScheme = defaultScheme
|
||||
}
|
||||
|
||||
if g.DefaultConsumes == "" {
|
||||
g.DefaultConsumes = runtime.JSONMime
|
||||
}
|
||||
|
||||
if g.DefaultProduces == "" {
|
||||
g.DefaultProduces = runtime.JSONMime
|
||||
}
|
||||
|
||||
// always include validator with models
|
||||
g.IncludeValidator = true
|
||||
|
||||
if g.Principal == "" {
|
||||
g.Principal = iface
|
||||
}
|
||||
|
||||
g.defaultsEnsured = true
|
||||
return nil
|
||||
}
|
||||
|
@ -707,19 +429,29 @@ func (g *GenOpts) location(t *TemplateOpts, data interface{}) (string, string, e
|
|||
tags = tagsF.Interface().([]string)
|
||||
}
|
||||
|
||||
pthTpl, err := template.New(t.Name + "-target").Funcs(FuncMap).Parse(t.Target)
|
||||
var useTags bool
|
||||
useTagsF := v.FieldByName("UseTags")
|
||||
if useTagsF.IsValid() {
|
||||
useTags = useTagsF.Interface().(bool)
|
||||
}
|
||||
|
||||
funcMap := FuncMapFunc(g.LanguageOpts)
|
||||
|
||||
pthTpl, err := template.New(t.Name + "-target").Funcs(funcMap).Parse(t.Target)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
fNameTpl, err := template.New(t.Name + "-filename").Funcs(FuncMap).Parse(t.FileName)
|
||||
fNameTpl, err := template.New(t.Name + "-filename").Funcs(funcMap).Parse(t.FileName)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
d := struct {
|
||||
Name, Package, APIPackage, ServerPackage, ClientPackage, ModelPackage, Target string
|
||||
Tags []string
|
||||
Name, Package, APIPackage, ServerPackage, ClientPackage, ModelPackage, MainPackage, Target string
|
||||
Tags []string
|
||||
UseTags bool
|
||||
Context interface{}
|
||||
}{
|
||||
Name: name,
|
||||
Package: pkg,
|
||||
|
@ -727,11 +459,13 @@ func (g *GenOpts) location(t *TemplateOpts, data interface{}) (string, string, e
|
|||
ServerPackage: g.ServerPackage,
|
||||
ClientPackage: g.ClientPackage,
|
||||
ModelPackage: g.ModelPackage,
|
||||
MainPackage: g.MainPackage,
|
||||
Target: g.Target,
|
||||
Tags: tags,
|
||||
UseTags: useTags,
|
||||
Context: data,
|
||||
}
|
||||
|
||||
// pretty.Println(data)
|
||||
var pthBuf bytes.Buffer
|
||||
if e := pthTpl.Execute(&pthBuf, d); e != nil {
|
||||
return "", "", e
|
||||
|
@ -777,7 +511,7 @@ func (g *GenOpts) render(t *TemplateOpts, data interface{}) ([]byte, error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("error while opening %s template file: %v", templateFile, err)
|
||||
}
|
||||
tt, err := template.New(t.Source).Funcs(FuncMap).Parse(string(content))
|
||||
tt, err := template.New(t.Source).Funcs(FuncMapFunc(g.LanguageOpts)).Parse(string(content))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("template parsing failed on template %s: %v", t.Name, err)
|
||||
}
|
||||
|
@ -836,10 +570,10 @@ func (g *GenOpts) write(t *TemplateOpts, data interface{}) error {
|
|||
var writeerr error
|
||||
|
||||
if !t.SkipFormat {
|
||||
formatted, err = g.LanguageOpts.FormatContent(fname, content)
|
||||
formatted, err = g.LanguageOpts.FormatContent(filepath.Join(dir, fname), content)
|
||||
if err != nil {
|
||||
log.Printf("source formatting failed on template-generated source (%q for %s). Check that your template produces valid code", filepath.Join(dir, fname), t.Name)
|
||||
writeerr = ioutil.WriteFile(filepath.Join(dir, fname), content, 0644)
|
||||
writeerr = ioutil.WriteFile(filepath.Join(dir, fname), content, 0644) // #nosec
|
||||
if writeerr != nil {
|
||||
return fmt.Errorf("failed to write (unformatted) file %q in %q: %v", fname, dir, writeerr)
|
||||
}
|
||||
|
@ -848,7 +582,7 @@ func (g *GenOpts) write(t *TemplateOpts, data interface{}) error {
|
|||
}
|
||||
}
|
||||
|
||||
writeerr = ioutil.WriteFile(filepath.Join(dir, fname), formatted, 0644)
|
||||
writeerr = ioutil.WriteFile(filepath.Join(dir, fname), formatted, 0644) // #nosec
|
||||
if writeerr != nil {
|
||||
return fmt.Errorf("failed to write file %q in %q: %v", fname, dir, writeerr)
|
||||
}
|
||||
|
@ -930,42 +664,84 @@ func (g *GenOpts) renderDefinition(gg *GenDefinition) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func validateSpec(path string, doc *loads.Document) (err error) {
|
||||
if doc == nil {
|
||||
if path, doc, err = loadSpec(path); err != nil {
|
||||
func (g *GenOpts) setTemplates() error {
|
||||
templates.LoadDefaults()
|
||||
|
||||
if g.Template != "" {
|
||||
// set contrib templates
|
||||
if err := templates.LoadContrib(g.Template); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
result := validate.Spec(doc, strfmt.Default)
|
||||
if result == nil {
|
||||
return nil
|
||||
}
|
||||
templates.SetAllowOverride(g.AllowTemplateOverride)
|
||||
|
||||
str := fmt.Sprintf("The swagger spec at %q is invalid against swagger specification %s. see errors :\n", path, doc.Version())
|
||||
for _, desc := range result.(*swaggererrors.CompositeError).Errors {
|
||||
str += fmt.Sprintf("- %s\n", desc)
|
||||
}
|
||||
return errors.New(str)
|
||||
}
|
||||
|
||||
func loadSpec(specFile string) (string, *loads.Document, error) {
|
||||
// find swagger spec document, verify it exists
|
||||
specPath := specFile
|
||||
var err error
|
||||
if !strings.HasPrefix(specPath, "http") {
|
||||
specPath, err = findSwaggerSpec(specFile)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
if g.TemplateDir != "" {
|
||||
// set custom templates
|
||||
if err := templates.LoadDir(g.TemplateDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// load swagger spec
|
||||
specDoc, err := loads.Spec(specPath)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
// defaultImports produces a default map for imports with models
|
||||
func (g *GenOpts) defaultImports() map[string]string {
|
||||
baseImport := g.LanguageOpts.baseImport(g.Target)
|
||||
defaultImports := make(map[string]string, 50)
|
||||
|
||||
if g.ExistingModels == "" {
|
||||
// generated models
|
||||
importPath := path.Join(
|
||||
baseImport,
|
||||
g.LanguageOpts.ManglePackagePath(g.ModelPackage, defaultModelsTarget))
|
||||
defaultImports[g.LanguageOpts.ManglePackageName(g.ModelPackage, defaultModelsTarget)] = importPath
|
||||
} else {
|
||||
// external models
|
||||
importPath := g.LanguageOpts.ManglePackagePath(g.ExistingModels, "")
|
||||
defaultImports["models"] = importPath
|
||||
}
|
||||
return specPath, specDoc, nil
|
||||
|
||||
alias, _, target := g.resolvePrincipal()
|
||||
if alias != "" {
|
||||
if pth, _ := path.Split(target); pth != "" {
|
||||
// if principal is specified with an path, generate this import
|
||||
defaultImports[alias] = target
|
||||
} else {
|
||||
// if principal is specified with a relative path, assume it is located in generated target
|
||||
defaultImports[alias] = path.Join(baseImport, target)
|
||||
}
|
||||
}
|
||||
return defaultImports
|
||||
}
|
||||
|
||||
// initImports produces a default map for import with the specified root for operations
|
||||
func (g *GenOpts) initImports(operationsPackage string) map[string]string {
|
||||
baseImport := g.LanguageOpts.baseImport(g.Target)
|
||||
|
||||
imports := make(map[string]string, 50)
|
||||
imports[g.LanguageOpts.ManglePackageName(operationsPackage, defaultOperationsTarget)] = path.Join(
|
||||
baseImport,
|
||||
g.LanguageOpts.ManglePackagePath(operationsPackage, defaultOperationsTarget))
|
||||
return imports
|
||||
}
|
||||
|
||||
// PrincipalAlias returns an aliased type to the principal
|
||||
func (g *GenOpts) PrincipalAlias() string {
|
||||
_, principal, _ := g.resolvePrincipal()
|
||||
return principal
|
||||
}
|
||||
|
||||
func (g *GenOpts) resolvePrincipal() (string, string, string) {
|
||||
dotLocation := strings.LastIndex(g.Principal, ".")
|
||||
if dotLocation < 0 {
|
||||
return "", g.Principal, ""
|
||||
}
|
||||
|
||||
// handle possible conflicts with injected principal package
|
||||
// NOTE(fred): we do not check here for conflicts with packages created from operation tags, only standard imports
|
||||
alias := deconflictPrincipal(importAlias(g.Principal[:dotLocation]))
|
||||
return alias, alias + g.Principal[dotLocation:], g.Principal[:dotLocation]
|
||||
}
|
||||
|
||||
func fileExists(target, name string) bool {
|
||||
|
@ -974,6 +750,7 @@ func fileExists(target, name string) bool {
|
|||
}
|
||||
|
||||
func gatherModels(specDoc *loads.Document, modelNames []string) (map[string]spec.Schema, error) {
|
||||
modelNames = pruneEmpty(modelNames)
|
||||
models, mnc := make(map[string]spec.Schema), len(modelNames)
|
||||
defs := specDoc.Spec().Definitions
|
||||
|
||||
|
@ -1002,7 +779,8 @@ func gatherModels(specDoc *loads.Document, modelNames []string) (map[string]spec
|
|||
return models, nil
|
||||
}
|
||||
|
||||
func appNameOrDefault(specDoc *loads.Document, name, defaultName string) string {
|
||||
// titleOrDefault infers a name for the app from the title of the spec
|
||||
func titleOrDefault(specDoc *loads.Document, name, defaultName string) string {
|
||||
if strings.TrimSpace(name) == "" {
|
||||
if specDoc.Spec().Info != nil && strings.TrimSpace(specDoc.Spec().Info.Title) != "" {
|
||||
name = specDoc.Spec().Info.Title
|
||||
|
@ -1010,16 +788,21 @@ func appNameOrDefault(specDoc *loads.Document, name, defaultName string) string
|
|||
name = defaultName
|
||||
}
|
||||
}
|
||||
return strings.TrimSuffix(strings.TrimSuffix(strings.TrimSuffix(swag.ToGoName(name), "Test"), "API"), "Test")
|
||||
return swag.ToGoName(name)
|
||||
}
|
||||
|
||||
func containsString(names []string, name string) bool {
|
||||
for _, nm := range names {
|
||||
if nm == name {
|
||||
return true
|
||||
}
|
||||
func mainNameOrDefault(specDoc *loads.Document, name, defaultName string) string {
|
||||
// *_test won't do as main server name
|
||||
return strings.TrimSuffix(titleOrDefault(specDoc, name, defaultName), "Test")
|
||||
}
|
||||
|
||||
func appNameOrDefault(specDoc *loads.Document, name, defaultName string) string {
|
||||
// *_test won't do as app names
|
||||
name = strings.TrimSuffix(titleOrDefault(specDoc, name, defaultName), "Test")
|
||||
if name == "" {
|
||||
name = swag.ToGoName(defaultName)
|
||||
}
|
||||
return false
|
||||
return name
|
||||
}
|
||||
|
||||
type opRef struct {
|
||||
|
@ -1037,14 +820,14 @@ func (o opRefs) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
|
|||
func (o opRefs) Less(i, j int) bool { return o[i].Key < o[j].Key }
|
||||
|
||||
func gatherOperations(specDoc *analysis.Spec, operationIDs []string) map[string]opRef {
|
||||
operationIDs = pruneEmpty(operationIDs)
|
||||
var oprefs opRefs
|
||||
|
||||
for method, pathItem := range specDoc.Operations() {
|
||||
for path, operation := range pathItem {
|
||||
// nm := ensureUniqueName(operation.ID, method, path, operations)
|
||||
vv := *operation
|
||||
oprefs = append(oprefs, opRef{
|
||||
Key: swag.ToGoName(strings.ToLower(method) + " " + path),
|
||||
Key: swag.ToGoName(strings.ToLower(method) + " " + strings.Title(path)),
|
||||
Method: method,
|
||||
Path: path,
|
||||
ID: vv.ID,
|
||||
|
@ -1066,7 +849,7 @@ func gatherOperations(specDoc *analysis.Spec, operationIDs []string) map[string]
|
|||
if found && oo.Method != opr.Method && oo.Path != opr.Path {
|
||||
nm = opr.Key
|
||||
}
|
||||
if len(operationIDs) == 0 || containsString(operationIDs, opr.ID) || containsString(operationIDs, nm) {
|
||||
if len(operationIDs) == 0 || swag.ContainsStrings(operationIDs, opr.ID) || swag.ContainsStrings(operationIDs, nm) {
|
||||
opr.ID = nm
|
||||
opr.Op.ID = nm
|
||||
operations[nm] = opr
|
||||
|
@ -1076,43 +859,6 @@ func gatherOperations(specDoc *analysis.Spec, operationIDs []string) map[string]
|
|||
return operations
|
||||
}
|
||||
|
||||
func pascalize(arg string) string {
|
||||
runes := []rune(arg)
|
||||
switch len(runes) {
|
||||
case 0:
|
||||
return ""
|
||||
case 1: // handle special case when we have a single rune that is not handled by swag.ToGoName
|
||||
switch runes[0] {
|
||||
case '+', '-', '#', '_': // those cases are handled differently than swag utility
|
||||
return prefixForName(arg)
|
||||
}
|
||||
}
|
||||
return swag.ToGoName(swag.ToGoName(arg)) // want to remove spaces
|
||||
}
|
||||
|
||||
func prefixForName(arg string) string {
|
||||
first := []rune(arg)[0]
|
||||
if len(arg) == 0 || unicode.IsLetter(first) {
|
||||
return ""
|
||||
}
|
||||
switch first {
|
||||
case '+':
|
||||
return "Plus"
|
||||
case '-':
|
||||
return "Minus"
|
||||
case '#':
|
||||
return "HashTag"
|
||||
// other cases ($,@ etc..) handled by swag.ToGoName
|
||||
}
|
||||
return "Nr"
|
||||
}
|
||||
|
||||
func init() {
|
||||
// this makes the ToGoName func behave with the special
|
||||
// prefixing rule above
|
||||
swag.GoNamePrefixFunc = prefixForName
|
||||
}
|
||||
|
||||
func pruneEmpty(in []string) (out []string) {
|
||||
for _, v := range in {
|
||||
if v != "" {
|
||||
|
@ -1126,73 +872,6 @@ func trimBOM(in string) string {
|
|||
return strings.Trim(in, "\xef\xbb\xbf")
|
||||
}
|
||||
|
||||
func validateAndFlattenSpec(opts *GenOpts, specDoc *loads.Document) (*loads.Document, error) {
|
||||
|
||||
var err error
|
||||
|
||||
// Validate if needed
|
||||
if opts.ValidateSpec {
|
||||
log.Printf("validating spec %v", opts.Spec)
|
||||
if erv := validateSpec(opts.Spec, specDoc); erv != nil {
|
||||
return specDoc, erv
|
||||
}
|
||||
}
|
||||
|
||||
// Restore spec to original
|
||||
opts.Spec, specDoc, err = loadSpec(opts.Spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
absBasePath := specDoc.SpecFilePath()
|
||||
if !filepath.IsAbs(absBasePath) {
|
||||
cwd, _ := os.Getwd()
|
||||
absBasePath = filepath.Join(cwd, absBasePath)
|
||||
}
|
||||
|
||||
// Some preprocessing is required before codegen
|
||||
//
|
||||
// This ensures at least that $ref's in the spec document are canonical,
|
||||
// i.e all $ref are local to this file and point to some uniquely named definition.
|
||||
//
|
||||
// Default option is to ensure minimal flattening of $ref, bundling remote $refs and relocating arbitrary JSON
|
||||
// pointers as definitions.
|
||||
// This preprocessing may introduce duplicate names (e.g. remote $ref with same name). In this case, a definition
|
||||
// suffixed with "OAIGen" is produced.
|
||||
//
|
||||
// Full flattening option farther transforms the spec by moving every complex object (e.g. with some properties)
|
||||
// as a standalone definition.
|
||||
//
|
||||
// Eventually, an "expand spec" option is available. It is essentially useful for testing purposes.
|
||||
//
|
||||
// NOTE(fredbi): spec expansion may produce some unsupported constructs and is not yet protected against the
|
||||
// following cases:
|
||||
// - polymorphic types generation may fail with expansion (expand destructs the reuse intent of the $ref in allOf)
|
||||
// - name duplicates may occur and result in compilation failures
|
||||
// The right place to fix these shortcomings is go-openapi/analysis.
|
||||
|
||||
opts.FlattenOpts.BasePath = absBasePath // BasePath must be absolute
|
||||
opts.FlattenOpts.Spec = analysis.New(specDoc.Spec())
|
||||
|
||||
var preprocessingOption string
|
||||
switch {
|
||||
case opts.FlattenOpts.Expand:
|
||||
preprocessingOption = "expand"
|
||||
case opts.FlattenOpts.Minimal:
|
||||
preprocessingOption = "minimal flattening"
|
||||
default:
|
||||
preprocessingOption = "full flattening"
|
||||
}
|
||||
log.Printf("preprocessing spec with option: %s", preprocessingOption)
|
||||
|
||||
if err = analysis.Flatten(*opts.FlattenOpts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// yields the preprocessed spec document
|
||||
return specDoc, nil
|
||||
}
|
||||
|
||||
// gatherSecuritySchemes produces a sorted representation from a map of spec security schemes
|
||||
func gatherSecuritySchemes(securitySchemes map[string]spec.SecurityScheme, appName, principal, receiver string) (security GenSecuritySchemes) {
|
||||
for scheme, req := range securitySchemes {
|
||||
|
@ -1285,3 +964,17 @@ func sharedValidationsFromSchema(v spec.Schema, isRequired bool) (sh sharedValid
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
func dumpData(data interface{}) error {
|
||||
bb, err := json.MarshalIndent(data, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(os.Stdout, string(bb))
|
||||
return nil
|
||||
}
|
||||
|
||||
func importAlias(pkg string) string {
|
||||
_, k := path.Split(pkg)
|
||||
return k
|
||||
}
|
||||
|
|
248
vendor/github.com/go-swagger/go-swagger/generator/spec.go
generated
vendored
Normal file
248
vendor/github.com/go-swagger/go-swagger/generator/spec.go
generated
vendored
Normal file
|
@ -0,0 +1,248 @@
|
|||
package generator
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
swaggererrors "github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func (g *GenOpts) validateAndFlattenSpec() (*loads.Document, error) {
|
||||
// Load spec document
|
||||
specDoc, err := loads.Spec(g.Spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If accepts definitions only, add dummy swagger header to pass validation
|
||||
if g.AcceptDefinitionsOnly {
|
||||
specDoc, err = applyDefaultSwagger(specDoc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Validate if needed
|
||||
if g.ValidateSpec {
|
||||
log.Printf("validating spec %v", g.Spec)
|
||||
validationErrors := validate.Spec(specDoc, strfmt.Default)
|
||||
if validationErrors != nil {
|
||||
str := fmt.Sprintf("The swagger spec at %q is invalid against swagger specification %s. see errors :\n",
|
||||
g.Spec, specDoc.Version())
|
||||
for _, desc := range validationErrors.(*swaggererrors.CompositeError).Errors {
|
||||
str += fmt.Sprintf("- %s\n", desc)
|
||||
}
|
||||
return nil, errors.New(str)
|
||||
}
|
||||
// TODO(fredbi): due to uncontrolled $ref state in spec, we need to reload the spec atm, or flatten won't
|
||||
// work properly (validate expansion alters the $ref cache in go-openapi/spec)
|
||||
specDoc, _ = loads.Spec(g.Spec)
|
||||
}
|
||||
|
||||
// Flatten spec
|
||||
//
|
||||
// Some preprocessing is required before codegen
|
||||
//
|
||||
// This ensures at least that $ref's in the spec document are canonical,
|
||||
// i.e all $ref are local to this file and point to some uniquely named definition.
|
||||
//
|
||||
// Default option is to ensure minimal flattening of $ref, bundling remote $refs and relocating arbitrary JSON
|
||||
// pointers as definitions.
|
||||
// This preprocessing may introduce duplicate names (e.g. remote $ref with same name). In this case, a definition
|
||||
// suffixed with "OAIGen" is produced.
|
||||
//
|
||||
// Full flattening option farther transforms the spec by moving every complex object (e.g. with some properties)
|
||||
// as a standalone definition.
|
||||
//
|
||||
// Eventually, an "expand spec" option is available. It is essentially useful for testing purposes.
|
||||
//
|
||||
// NOTE(fredbi): spec expansion may produce some unsupported constructs and is not yet protected against the
|
||||
// following cases:
|
||||
// - polymorphic types generation may fail with expansion (expand destructs the reuse intent of the $ref in allOf)
|
||||
// - name duplicates may occur and result in compilation failures
|
||||
//
|
||||
// The right place to fix these shortcomings is go-openapi/analysis.
|
||||
|
||||
g.FlattenOpts.BasePath = specDoc.SpecFilePath()
|
||||
g.FlattenOpts.Spec = analysis.New(specDoc.Spec())
|
||||
|
||||
g.printFlattenOpts()
|
||||
|
||||
if err = analysis.Flatten(*g.FlattenOpts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// yields the preprocessed spec document
|
||||
return specDoc, nil
|
||||
}
|
||||
|
||||
func (g *GenOpts) analyzeSpec() (*loads.Document, *analysis.Spec, error) {
|
||||
// spec preprocessing option
|
||||
if g.PropertiesSpecOrder {
|
||||
g.Spec = WithAutoXOrder(g.Spec)
|
||||
}
|
||||
|
||||
// load, validate and flatten
|
||||
specDoc, err := g.validateAndFlattenSpec()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// analyze the spec
|
||||
analyzed := analysis.New(specDoc.Spec())
|
||||
|
||||
return specDoc, analyzed, nil
|
||||
}
|
||||
|
||||
func (g *GenOpts) printFlattenOpts() {
|
||||
var preprocessingOption string
|
||||
switch {
|
||||
case g.FlattenOpts.Expand:
|
||||
preprocessingOption = "expand"
|
||||
case g.FlattenOpts.Minimal:
|
||||
preprocessingOption = "minimal flattening"
|
||||
default:
|
||||
preprocessingOption = "full flattening"
|
||||
}
|
||||
log.Printf("preprocessing spec with option: %s", preprocessingOption)
|
||||
}
|
||||
|
||||
//findSwaggerSpec fetches a default swagger spec if none is provided
|
||||
func findSwaggerSpec(nm string) (string, error) {
|
||||
specs := []string{"swagger.json", "swagger.yml", "swagger.yaml"}
|
||||
if nm != "" {
|
||||
specs = []string{nm}
|
||||
}
|
||||
var name string
|
||||
for _, nn := range specs {
|
||||
f, err := os.Stat(nn)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
if f.IsDir() {
|
||||
return "", fmt.Errorf("%s is a directory", nn)
|
||||
}
|
||||
name = nn
|
||||
break
|
||||
}
|
||||
if name == "" {
|
||||
return "", errors.New("couldn't find a swagger spec")
|
||||
}
|
||||
return name, nil
|
||||
}
|
||||
|
||||
// WithAutoXOrder amends the spec to specify property order as they appear
|
||||
// in the spec (supports yaml documents only).
|
||||
func WithAutoXOrder(specPath string) string {
|
||||
lookFor := func(ele interface{}, key string) (yaml.MapSlice, bool) {
|
||||
if slice, ok := ele.(yaml.MapSlice); ok {
|
||||
for _, v := range slice {
|
||||
if v.Key == key {
|
||||
if slice, ok := v.Value.(yaml.MapSlice); ok {
|
||||
return slice, ok
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
var addXOrder func(interface{})
|
||||
addXOrder = func(element interface{}) {
|
||||
if props, ok := lookFor(element, "properties"); ok {
|
||||
for i, prop := range props {
|
||||
if pSlice, ok := prop.Value.(yaml.MapSlice); ok {
|
||||
isObject := false
|
||||
xOrderIndex := -1 //Find if x-order already exists
|
||||
|
||||
for i, v := range pSlice {
|
||||
if v.Key == "type" && v.Value == object {
|
||||
isObject = true
|
||||
}
|
||||
if v.Key == xOrder {
|
||||
xOrderIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if xOrderIndex > -1 { //Override existing x-order
|
||||
pSlice[xOrderIndex] = yaml.MapItem{Key: xOrder, Value: i}
|
||||
} else { // append new x-order
|
||||
pSlice = append(pSlice, yaml.MapItem{Key: xOrder, Value: i})
|
||||
}
|
||||
prop.Value = pSlice
|
||||
props[i] = prop
|
||||
|
||||
if isObject {
|
||||
addXOrder(pSlice)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
yamlDoc, err := swag.YAMLData(specPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if defs, ok := lookFor(yamlDoc, "definitions"); ok {
|
||||
for _, def := range defs {
|
||||
addXOrder(def.Value)
|
||||
}
|
||||
}
|
||||
|
||||
addXOrder(yamlDoc)
|
||||
|
||||
out, err := yaml.Marshal(yamlDoc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
tmpFile, err := ioutil.TempFile("", filepath.Base(specPath))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := ioutil.WriteFile(tmpFile.Name(), out, 0); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return tmpFile.Name()
|
||||
}
|
||||
|
||||
func applyDefaultSwagger(doc *loads.Document) (*loads.Document, error) {
|
||||
// bake a minimal swagger spec to pass validation
|
||||
swspec := doc.Spec()
|
||||
if swspec.Swagger == "" {
|
||||
swspec.Swagger = "2.0"
|
||||
}
|
||||
if swspec.Info == nil {
|
||||
info := new(spec.Info)
|
||||
info.Version = "0.0.0"
|
||||
info.Title = "minimal"
|
||||
swspec.Info = info
|
||||
}
|
||||
if swspec.Paths == nil {
|
||||
swspec.Paths = &spec.Paths{}
|
||||
}
|
||||
// rewrite the document with the new addition
|
||||
jazon, err := json.Marshal(swspec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return loads.Analyzed(jazon, swspec.Swagger)
|
||||
}
|
57
vendor/github.com/go-swagger/go-swagger/generator/structs.go
generated
vendored
57
vendor/github.com/go-swagger/go-swagger/generator/structs.go
generated
vendored
|
@ -28,7 +28,7 @@ type GenDefinition struct {
|
|||
GenSchema
|
||||
Package string
|
||||
Imports map[string]string
|
||||
DefaultImports []string
|
||||
DefaultImports map[string]string
|
||||
ExtraSchemas GenSchemaList
|
||||
DependsOn []string
|
||||
External bool
|
||||
|
@ -91,6 +91,9 @@ type GenSchema struct {
|
|||
IncludeValidator bool
|
||||
IncludeModel bool
|
||||
Default interface{}
|
||||
WantsMarshalBinary bool // do we generate MarshalBinary interface?
|
||||
StructTags []string
|
||||
ExtraImports map[string]string // non-standard imports detected when using external types
|
||||
}
|
||||
|
||||
func (g GenSchemaList) Len() int { return len(g) }
|
||||
|
@ -167,9 +170,12 @@ type GenResponse struct {
|
|||
AllowsForStreaming bool
|
||||
|
||||
Imports map[string]string
|
||||
DefaultImports []string
|
||||
DefaultImports map[string]string
|
||||
|
||||
Extensions map[string]interface{}
|
||||
|
||||
StrictResponders bool
|
||||
OperationName string
|
||||
}
|
||||
|
||||
// GenHeader represents a header on a response for code generation
|
||||
|
@ -355,6 +361,8 @@ type GenItems struct {
|
|||
|
||||
// instructs generator to skip the splitting and parsing from CollectionFormat
|
||||
SkipParse bool
|
||||
// instructs generator that some nested structure needs an higher level loop index
|
||||
NeedsIndex bool
|
||||
}
|
||||
|
||||
// ItemsDepth returns a string "items.items..." with as many items as the level of nesting of the array.
|
||||
|
@ -378,9 +386,10 @@ type GenOperationGroup struct {
|
|||
Summary string
|
||||
Description string
|
||||
Imports map[string]string
|
||||
DefaultImports []string
|
||||
DefaultImports map[string]string
|
||||
RootPackage string
|
||||
GenOpts *GenOpts
|
||||
PackageAlias string
|
||||
}
|
||||
|
||||
// GenOperationGroups is a sorted collection of operation groups
|
||||
|
@ -398,13 +407,20 @@ func (g GenStatusCodeResponses) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|
|||
func (g GenStatusCodeResponses) Less(i, j int) bool { return g[i].Code < g[j].Code }
|
||||
|
||||
// MarshalJSON marshals these responses to json
|
||||
//
|
||||
// This is used by DumpData.
|
||||
func (g GenStatusCodeResponses) MarshalJSON() ([]byte, error) {
|
||||
if g == nil {
|
||||
return nil, nil
|
||||
}
|
||||
responses := make(GenStatusCodeResponses, len(g))
|
||||
copy(responses, g)
|
||||
// order marshalled output
|
||||
sort.Sort(responses)
|
||||
|
||||
var buf bytes.Buffer
|
||||
buf.WriteRune('{')
|
||||
for i, v := range g {
|
||||
for i, v := range responses {
|
||||
rb, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -446,11 +462,13 @@ type GenOperation struct {
|
|||
Path string
|
||||
BasePath string
|
||||
Tags []string
|
||||
UseTags bool
|
||||
RootPackage string
|
||||
|
||||
Imports map[string]string
|
||||
DefaultImports []string
|
||||
DefaultImports map[string]string
|
||||
ExtraSchemas GenSchemaList
|
||||
PackageAlias string
|
||||
|
||||
Authorized bool
|
||||
Security []GenSecurityRequirements
|
||||
|
@ -483,6 +501,8 @@ type GenOperation struct {
|
|||
TimeoutName string
|
||||
|
||||
Extensions map[string]interface{}
|
||||
|
||||
StrictResponders bool
|
||||
}
|
||||
|
||||
// GenOperations represents a list of operations to generate
|
||||
|
@ -509,7 +529,7 @@ type GenApp struct {
|
|||
Info *spec.Info
|
||||
ExternalDocs *spec.ExternalDocumentation
|
||||
Imports map[string]string
|
||||
DefaultImports []string
|
||||
DefaultImports map[string]string
|
||||
Schemes []string
|
||||
ExtraSchemes []string
|
||||
Consumes GenSerGroups
|
||||
|
@ -521,7 +541,7 @@ type GenApp struct {
|
|||
SwaggerJSON string
|
||||
// Embedded specs: this is important for when the generated server adds routes.
|
||||
// NOTE: there is a distinct advantage to having this in runtime rather than generated code.
|
||||
// We are noti ever going to generate the router.
|
||||
// We are not ever going to generate the router.
|
||||
// If embedding spec is an issue (e.g. memory usage), this can be excluded with the --exclude-spec
|
||||
// generation option. Alternative methods to serve spec (e.g. from disk, ...) may be implemented by
|
||||
// adding a middleware to the generated API.
|
||||
|
@ -563,16 +583,14 @@ type GenSerGroups []GenSerGroup
|
|||
|
||||
func (g GenSerGroups) Len() int { return len(g) }
|
||||
func (g GenSerGroups) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|
||||
func (g GenSerGroups) Less(i, j int) bool { return g[i].MediaType < g[j].MediaType }
|
||||
func (g GenSerGroups) Less(i, j int) bool { return g[i].Name < g[j].Name }
|
||||
|
||||
// GenSerGroup represents a group of serializers, most likely this is a media type to a list of
|
||||
// prioritized serializers.
|
||||
// GenSerGroup represents a group of serializers: this links a serializer to a list of
|
||||
// prioritized media types (mime).
|
||||
type GenSerGroup struct {
|
||||
ReceiverName string
|
||||
AppName string
|
||||
Name string
|
||||
MediaType string
|
||||
Implementation string
|
||||
GenSerializer
|
||||
|
||||
// All media types for this serializer. The redundant representation allows for easier use in templates
|
||||
AllSerializers GenSerializers
|
||||
}
|
||||
|
||||
|
@ -585,11 +603,12 @@ func (g GenSerializers) Less(i, j int) bool { return g[i].MediaType < g[j].Media
|
|||
|
||||
// GenSerializer represents a single serializer for a particular media type
|
||||
type GenSerializer struct {
|
||||
AppName string // Application name
|
||||
ReceiverName string
|
||||
AppName string
|
||||
Name string
|
||||
MediaType string
|
||||
Implementation string
|
||||
Name string // Name of the Producer/Consumer (e.g. json, yaml, txt, bin)
|
||||
MediaType string // mime
|
||||
Implementation string // func implementing the Producer/Consumer
|
||||
Parameters []string // parameters supported by this serializer
|
||||
}
|
||||
|
||||
// GenSecurityScheme represents a security scheme for code generation
|
||||
|
|
618
vendor/github.com/go-swagger/go-swagger/generator/support.go
generated
vendored
618
vendor/github.com/go-swagger/go-swagger/generator/support.go
generated
vendored
|
@ -1,4 +1,5 @@
|
|||
// Copyright 2015 go-swagger maintainers
|
||||
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -19,21 +20,13 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
goruntime "runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
@ -57,85 +50,37 @@ func GenerateSupport(name string, modelNames, operationIDs []string, opts *GenOp
|
|||
}
|
||||
|
||||
func newAppGenerator(name string, modelNames, operationIDs []string, opts *GenOpts) (*appGenerator, error) {
|
||||
if opts == nil {
|
||||
return nil, errors.New("gen opts are required")
|
||||
}
|
||||
if err := opts.CheckOpts(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
templates.LoadDefaults()
|
||||
if opts.Template != "" {
|
||||
if err := templates.LoadContrib(opts.Template); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
templates.SetAllowOverride(opts.AllowTemplateOverride)
|
||||
|
||||
if opts.TemplateDir != "" {
|
||||
if err := templates.LoadDir(opts.TemplateDir); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Load the spec
|
||||
var err error
|
||||
var specDoc *loads.Document
|
||||
|
||||
opts.Spec, err = findSwaggerSpec(opts.Spec)
|
||||
if err != nil {
|
||||
if err := opts.setTemplates(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !filepath.IsAbs(opts.Spec) {
|
||||
cwd, _ := os.Getwd()
|
||||
opts.Spec = filepath.Join(cwd, opts.Spec)
|
||||
}
|
||||
|
||||
if opts.PropertiesSpecOrder {
|
||||
opts.Spec = WithAutoXOrder(opts.Spec)
|
||||
}
|
||||
|
||||
opts.Spec, specDoc, err = loadSpec(opts.Spec)
|
||||
specDoc, analyzed, err := opts.analyzeSpec()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
specDoc, err = validateAndFlattenSpec(opts, specDoc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
analyzed := analysis.New(specDoc.Spec())
|
||||
|
||||
models, err := gatherModels(specDoc, modelNames)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
operations := gatherOperations(analyzed, operationIDs)
|
||||
if len(operations) == 0 {
|
||||
|
||||
if len(operations) == 0 && !opts.IgnoreOperations {
|
||||
return nil, errors.New("no operations were selected")
|
||||
}
|
||||
|
||||
defaultScheme := opts.DefaultScheme
|
||||
if defaultScheme == "" {
|
||||
defaultScheme = "http"
|
||||
opts.Name = appNameOrDefault(specDoc, name, defaultServerName)
|
||||
if opts.IncludeMain && opts.MainPackage == "" {
|
||||
// default target for the generated main
|
||||
opts.MainPackage = swag.ToCommandName(mainNameOrDefault(specDoc, name, defaultServerName) + "-server")
|
||||
}
|
||||
|
||||
defaultProduces := opts.DefaultProduces
|
||||
if defaultProduces == "" {
|
||||
defaultProduces = runtime.JSONMime
|
||||
}
|
||||
|
||||
defaultConsumes := opts.DefaultConsumes
|
||||
if defaultConsumes == "" {
|
||||
defaultConsumes = runtime.JSONMime
|
||||
}
|
||||
|
||||
opts.Name = appNameOrDefault(specDoc, name, "swagger")
|
||||
apiPackage := opts.LanguageOpts.ManglePackagePath(opts.APIPackage, "api")
|
||||
apiPackage := opts.LanguageOpts.ManglePackagePath(opts.APIPackage, defaultOperationsTarget)
|
||||
return &appGenerator{
|
||||
Name: opts.Name,
|
||||
Receiver: "o",
|
||||
|
@ -145,16 +90,16 @@ func newAppGenerator(name string, modelNames, operationIDs []string, opts *GenOp
|
|||
Operations: operations,
|
||||
Target: opts.Target,
|
||||
DumpData: opts.DumpData,
|
||||
Package: opts.LanguageOpts.ManglePackageName(apiPackage, "api"),
|
||||
Package: opts.LanguageOpts.ManglePackageName(apiPackage, defaultOperationsTarget),
|
||||
APIPackage: apiPackage,
|
||||
ModelsPackage: opts.LanguageOpts.ManglePackagePath(opts.ModelPackage, "definitions"),
|
||||
ServerPackage: opts.LanguageOpts.ManglePackagePath(opts.ServerPackage, "server"),
|
||||
ClientPackage: opts.LanguageOpts.ManglePackagePath(opts.ClientPackage, "client"),
|
||||
OperationsPackage: filepath.Join(opts.LanguageOpts.ManglePackagePath(opts.ServerPackage, "server"), apiPackage),
|
||||
Principal: opts.Principal,
|
||||
DefaultScheme: defaultScheme,
|
||||
DefaultProduces: defaultProduces,
|
||||
DefaultConsumes: defaultConsumes,
|
||||
ModelsPackage: opts.LanguageOpts.ManglePackagePath(opts.ModelPackage, defaultModelsTarget),
|
||||
ServerPackage: opts.LanguageOpts.ManglePackagePath(opts.ServerPackage, defaultServerTarget),
|
||||
ClientPackage: opts.LanguageOpts.ManglePackagePath(opts.ClientPackage, defaultClientTarget),
|
||||
OperationsPackage: filepath.Join(opts.LanguageOpts.ManglePackagePath(opts.ServerPackage, defaultServerTarget), apiPackage),
|
||||
Principal: opts.PrincipalAlias(),
|
||||
DefaultScheme: opts.DefaultScheme,
|
||||
DefaultProduces: opts.DefaultProduces,
|
||||
DefaultConsumes: opts.DefaultConsumes,
|
||||
GenOpts: opts,
|
||||
}, nil
|
||||
}
|
||||
|
@ -170,6 +115,7 @@ type appGenerator struct {
|
|||
ServerPackage string
|
||||
ClientPackage string
|
||||
OperationsPackage string
|
||||
MainPackage string
|
||||
Principal string
|
||||
Models map[string]spec.Schema
|
||||
Operations map[string]opRef
|
||||
|
@ -181,120 +127,14 @@ type appGenerator struct {
|
|||
GenOpts *GenOpts
|
||||
}
|
||||
|
||||
func WithAutoXOrder(specPath string) string {
|
||||
lookFor := func(ele interface{}, key string) (yaml.MapSlice, bool) {
|
||||
if slice, ok := ele.(yaml.MapSlice); ok {
|
||||
for _, v := range slice {
|
||||
if v.Key == key {
|
||||
if slice, ok := v.Value.(yaml.MapSlice); ok {
|
||||
return slice, ok
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
var addXOrder func(interface{})
|
||||
addXOrder = func(element interface{}) {
|
||||
if props, ok := lookFor(element, "properties"); ok {
|
||||
for i, prop := range props {
|
||||
if pSlice, ok := prop.Value.(yaml.MapSlice); ok {
|
||||
isObject := false
|
||||
xOrderIndex := -1 //Find if x-order already exists
|
||||
|
||||
for i, v := range pSlice {
|
||||
if v.Key == "type" && v.Value == object {
|
||||
isObject = true
|
||||
}
|
||||
if v.Key == xOrder {
|
||||
xOrderIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if xOrderIndex > -1 { //Override existing x-order
|
||||
pSlice[xOrderIndex] = yaml.MapItem{Key: xOrder, Value: i}
|
||||
} else { // append new x-order
|
||||
pSlice = append(pSlice, yaml.MapItem{Key: xOrder, Value: i})
|
||||
}
|
||||
prop.Value = pSlice
|
||||
props[i] = prop
|
||||
|
||||
if isObject {
|
||||
addXOrder(pSlice)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
yamlDoc, err := swag.YAMLData(specPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if defs, ok := lookFor(yamlDoc, "definitions"); ok {
|
||||
for _, def := range defs {
|
||||
addXOrder(def.Value)
|
||||
}
|
||||
}
|
||||
|
||||
addXOrder(yamlDoc)
|
||||
|
||||
out, err := yaml.Marshal(yamlDoc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
tmpFile, err := ioutil.TempFile("", filepath.Base(specPath))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := ioutil.WriteFile(tmpFile.Name(), out, 0); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return tmpFile.Name()
|
||||
}
|
||||
|
||||
// 1. Checks if the child path and parent path coincide.
|
||||
// 2. If they do return child path relative to parent path.
|
||||
// 3. Everything else return false
|
||||
func checkPrefixAndFetchRelativePath(childpath string, parentpath string) (bool, string) {
|
||||
// Windows (local) file systems - NTFS, as well as FAT and variants
|
||||
// are case insensitive.
|
||||
cp, pp := childpath, parentpath
|
||||
if goruntime.GOOS == "windows" {
|
||||
cp = strings.ToLower(cp)
|
||||
pp = strings.ToLower(pp)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(cp, pp) {
|
||||
pth, err := filepath.Rel(parentpath, childpath)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
return true, pth
|
||||
}
|
||||
|
||||
return false, ""
|
||||
|
||||
}
|
||||
|
||||
func (a *appGenerator) Generate() error {
|
||||
|
||||
app, err := a.makeCodegenApp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if a.DumpData {
|
||||
bb, err := json.MarshalIndent(app, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(os.Stdout, string(bb))
|
||||
return nil
|
||||
return dumpData(app)
|
||||
}
|
||||
|
||||
// NOTE: relative to previous implem with chan.
|
||||
|
@ -303,10 +143,9 @@ func (a *appGenerator) Generate() error {
|
|||
if a.GenOpts.IncludeModel {
|
||||
log.Printf("rendering %d models", len(app.Models))
|
||||
for _, mod := range app.Models {
|
||||
modCopy := mod
|
||||
modCopy.IncludeValidator = true // a.GenOpts.IncludeValidator
|
||||
modCopy.IncludeModel = true
|
||||
if err := a.GenOpts.renderDefinition(&modCopy); err != nil {
|
||||
mod.IncludeModel = true
|
||||
mod.IncludeValidator = a.GenOpts.IncludeValidator
|
||||
if err := a.GenOpts.renderDefinition(&mod); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -315,19 +154,14 @@ func (a *appGenerator) Generate() error {
|
|||
if a.GenOpts.IncludeHandler {
|
||||
log.Printf("rendering %d operation groups (tags)", app.OperationGroups.Len())
|
||||
for _, opg := range app.OperationGroups {
|
||||
opgCopy := opg
|
||||
log.Printf("rendering %d operations for %s", opg.Operations.Len(), opg.Name)
|
||||
for _, op := range opgCopy.Operations {
|
||||
opCopy := op
|
||||
|
||||
if err := a.GenOpts.renderOperation(&opCopy); err != nil {
|
||||
for _, op := range opg.Operations {
|
||||
if err := a.GenOpts.renderOperation(&op); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Optional OperationGroups templates generation
|
||||
opGroup := opg
|
||||
opGroup.DefaultImports = app.DefaultImports
|
||||
if err := a.GenOpts.renderOperationGroup(&opGroup); err != nil {
|
||||
// optional OperationGroups templates generation
|
||||
if err := a.GenOpts.renderOperationGroup(&opg); err != nil {
|
||||
return fmt.Errorf("error while rendering operation group: %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -345,247 +179,23 @@ func (a *appGenerator) Generate() error {
|
|||
func (a *appGenerator) GenerateSupport(ap *GenApp) error {
|
||||
app := ap
|
||||
if ap == nil {
|
||||
// allows for calling GenerateSupport standalone
|
||||
ca, err := a.makeCodegenApp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
app = &ca
|
||||
}
|
||||
|
||||
baseImport := a.GenOpts.LanguageOpts.baseImport(a.Target)
|
||||
importPath := path.Join(filepath.ToSlash(baseImport), a.GenOpts.LanguageOpts.ManglePackagePath(a.OperationsPackage, ""))
|
||||
app.DefaultImports = append(
|
||||
app.DefaultImports,
|
||||
path.Join(filepath.ToSlash(baseImport), a.GenOpts.LanguageOpts.ManglePackagePath(a.ServerPackage, "")),
|
||||
importPath,
|
||||
)
|
||||
serverPath := path.Join(baseImport,
|
||||
a.GenOpts.LanguageOpts.ManglePackagePath(a.ServerPackage, defaultServerTarget))
|
||||
app.DefaultImports[importAlias(serverPath)] = serverPath
|
||||
|
||||
return a.GenOpts.renderApplication(app)
|
||||
}
|
||||
|
||||
var mediaTypeNames = map[*regexp.Regexp]string{
|
||||
regexp.MustCompile("application/.*json"): "json",
|
||||
regexp.MustCompile("application/.*yaml"): "yaml",
|
||||
regexp.MustCompile("application/.*protobuf"): "protobuf",
|
||||
regexp.MustCompile("application/.*capnproto"): "capnproto",
|
||||
regexp.MustCompile("application/.*thrift"): "thrift",
|
||||
regexp.MustCompile("(?:application|text)/.*xml"): "xml",
|
||||
regexp.MustCompile("text/.*markdown"): "markdown",
|
||||
regexp.MustCompile("text/.*html"): "html",
|
||||
regexp.MustCompile("text/.*csv"): "csv",
|
||||
regexp.MustCompile("text/.*tsv"): "tsv",
|
||||
regexp.MustCompile("text/.*javascript"): "js",
|
||||
regexp.MustCompile("text/.*css"): "css",
|
||||
regexp.MustCompile("text/.*plain"): "txt",
|
||||
regexp.MustCompile("application/.*octet-stream"): "bin",
|
||||
regexp.MustCompile("application/.*tar"): "tar",
|
||||
regexp.MustCompile("application/.*gzip"): "gzip",
|
||||
regexp.MustCompile("application/.*gz"): "gzip",
|
||||
regexp.MustCompile("application/.*raw-stream"): "bin",
|
||||
regexp.MustCompile("application/x-www-form-urlencoded"): "urlform",
|
||||
regexp.MustCompile("multipart/form-data"): "multipartform",
|
||||
}
|
||||
|
||||
var knownProducers = map[string]string{
|
||||
"json": "runtime.JSONProducer()",
|
||||
"yaml": "yamlpc.YAMLProducer()",
|
||||
"xml": "runtime.XMLProducer()",
|
||||
"txt": "runtime.TextProducer()",
|
||||
"bin": "runtime.ByteStreamProducer()",
|
||||
"urlform": "runtime.DiscardProducer",
|
||||
"multipartform": "runtime.DiscardProducer",
|
||||
}
|
||||
|
||||
var knownConsumers = map[string]string{
|
||||
"json": "runtime.JSONConsumer()",
|
||||
"yaml": "yamlpc.YAMLConsumer()",
|
||||
"xml": "runtime.XMLConsumer()",
|
||||
"txt": "runtime.TextConsumer()",
|
||||
"bin": "runtime.ByteStreamConsumer()",
|
||||
"urlform": "runtime.DiscardConsumer",
|
||||
"multipartform": "runtime.DiscardConsumer",
|
||||
}
|
||||
|
||||
func getSerializer(sers []GenSerGroup, ext string) (*GenSerGroup, bool) {
|
||||
for i := range sers {
|
||||
s := &sers[i]
|
||||
if s.Name == ext {
|
||||
return s, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func mediaTypeName(tn string) (string, bool) {
|
||||
for k, v := range mediaTypeNames {
|
||||
if k.MatchString(tn) {
|
||||
return v, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func (a *appGenerator) makeConsumes() (consumes GenSerGroups, consumesJSON bool) {
|
||||
reqCons := a.Analyzed.RequiredConsumes()
|
||||
sort.Strings(reqCons)
|
||||
for _, cons := range reqCons {
|
||||
cn, ok := mediaTypeName(cons)
|
||||
if !ok {
|
||||
nm := swag.ToJSONName(cons)
|
||||
ser := GenSerializer{
|
||||
AppName: a.Name,
|
||||
ReceiverName: a.Receiver,
|
||||
Name: nm,
|
||||
MediaType: cons,
|
||||
Implementation: "",
|
||||
}
|
||||
|
||||
consumes = append(consumes, GenSerGroup{
|
||||
AppName: ser.AppName,
|
||||
ReceiverName: ser.ReceiverName,
|
||||
Name: ser.Name,
|
||||
MediaType: cons,
|
||||
AllSerializers: []GenSerializer{ser},
|
||||
Implementation: ser.Implementation,
|
||||
})
|
||||
continue
|
||||
}
|
||||
nm := swag.ToJSONName(cn)
|
||||
if nm == "json" {
|
||||
consumesJSON = true
|
||||
}
|
||||
|
||||
if ser, ok := getSerializer(consumes, cn); ok {
|
||||
ser.AllSerializers = append(ser.AllSerializers, GenSerializer{
|
||||
AppName: ser.AppName,
|
||||
ReceiverName: ser.ReceiverName,
|
||||
Name: ser.Name,
|
||||
MediaType: cons,
|
||||
Implementation: knownConsumers[nm],
|
||||
})
|
||||
sort.Sort(ser.AllSerializers)
|
||||
continue
|
||||
}
|
||||
|
||||
ser := GenSerializer{
|
||||
AppName: a.Name,
|
||||
ReceiverName: a.Receiver,
|
||||
Name: nm,
|
||||
MediaType: cons,
|
||||
Implementation: knownConsumers[nm],
|
||||
}
|
||||
|
||||
consumes = append(consumes, GenSerGroup{
|
||||
AppName: ser.AppName,
|
||||
ReceiverName: ser.ReceiverName,
|
||||
Name: ser.Name,
|
||||
MediaType: cons,
|
||||
AllSerializers: []GenSerializer{ser},
|
||||
Implementation: ser.Implementation,
|
||||
})
|
||||
}
|
||||
if len(consumes) == 0 {
|
||||
consumes = append(consumes, GenSerGroup{
|
||||
AppName: a.Name,
|
||||
ReceiverName: a.Receiver,
|
||||
Name: "json",
|
||||
MediaType: runtime.JSONMime,
|
||||
AllSerializers: []GenSerializer{{
|
||||
AppName: a.Name,
|
||||
ReceiverName: a.Receiver,
|
||||
Name: "json",
|
||||
MediaType: runtime.JSONMime,
|
||||
Implementation: knownConsumers["json"],
|
||||
}},
|
||||
Implementation: knownConsumers["json"],
|
||||
})
|
||||
consumesJSON = true
|
||||
}
|
||||
sort.Sort(consumes)
|
||||
return
|
||||
}
|
||||
|
||||
func (a *appGenerator) makeProduces() (produces GenSerGroups, producesJSON bool) {
|
||||
reqProds := a.Analyzed.RequiredProduces()
|
||||
sort.Strings(reqProds)
|
||||
for _, prod := range reqProds {
|
||||
pn, ok := mediaTypeName(prod)
|
||||
if !ok {
|
||||
nm := swag.ToJSONName(prod)
|
||||
ser := GenSerializer{
|
||||
AppName: a.Name,
|
||||
ReceiverName: a.Receiver,
|
||||
Name: nm,
|
||||
MediaType: prod,
|
||||
Implementation: "",
|
||||
}
|
||||
produces = append(produces, GenSerGroup{
|
||||
AppName: ser.AppName,
|
||||
ReceiverName: ser.ReceiverName,
|
||||
Name: ser.Name,
|
||||
MediaType: prod,
|
||||
Implementation: ser.Implementation,
|
||||
AllSerializers: []GenSerializer{ser},
|
||||
})
|
||||
continue
|
||||
}
|
||||
nm := swag.ToJSONName(pn)
|
||||
if nm == "json" {
|
||||
producesJSON = true
|
||||
}
|
||||
|
||||
if ser, ok := getSerializer(produces, pn); ok {
|
||||
ser.AllSerializers = append(ser.AllSerializers, GenSerializer{
|
||||
AppName: ser.AppName,
|
||||
ReceiverName: ser.ReceiverName,
|
||||
Name: ser.Name,
|
||||
MediaType: prod,
|
||||
Implementation: knownProducers[nm],
|
||||
})
|
||||
sort.Sort(ser.AllSerializers)
|
||||
continue
|
||||
}
|
||||
|
||||
ser := GenSerializer{
|
||||
AppName: a.Name,
|
||||
ReceiverName: a.Receiver,
|
||||
Name: nm,
|
||||
MediaType: prod,
|
||||
Implementation: knownProducers[nm],
|
||||
}
|
||||
produces = append(produces, GenSerGroup{
|
||||
AppName: ser.AppName,
|
||||
ReceiverName: ser.ReceiverName,
|
||||
Name: ser.Name,
|
||||
MediaType: prod,
|
||||
Implementation: ser.Implementation,
|
||||
AllSerializers: []GenSerializer{ser},
|
||||
})
|
||||
}
|
||||
if len(produces) == 0 {
|
||||
produces = append(produces, GenSerGroup{
|
||||
AppName: a.Name,
|
||||
ReceiverName: a.Receiver,
|
||||
Name: "json",
|
||||
MediaType: runtime.JSONMime,
|
||||
AllSerializers: []GenSerializer{{
|
||||
AppName: a.Name,
|
||||
ReceiverName: a.Receiver,
|
||||
Name: "json",
|
||||
MediaType: runtime.JSONMime,
|
||||
Implementation: knownProducers["json"],
|
||||
}},
|
||||
Implementation: knownProducers["json"],
|
||||
})
|
||||
producesJSON = true
|
||||
}
|
||||
sort.Sort(produces)
|
||||
return
|
||||
}
|
||||
|
||||
func (a *appGenerator) makeSecuritySchemes() GenSecuritySchemes {
|
||||
if a.Principal == "" {
|
||||
a.Principal = "interface{}"
|
||||
}
|
||||
requiredSecuritySchemes := make(map[string]spec.SecurityScheme, len(a.Analyzed.RequiredSecuritySchemes()))
|
||||
for _, scheme := range a.Analyzed.RequiredSecuritySchemes() {
|
||||
if req, ok := a.SpecDoc.Spec().SecurityDefinitions[scheme]; ok && req != nil {
|
||||
|
@ -597,36 +207,25 @@ func (a *appGenerator) makeSecuritySchemes() GenSecuritySchemes {
|
|||
|
||||
func (a *appGenerator) makeCodegenApp() (GenApp, error) {
|
||||
log.Println("building a plan for generation")
|
||||
|
||||
sw := a.SpecDoc.Spec()
|
||||
receiver := a.Receiver
|
||||
|
||||
var defaultImports []string
|
||||
|
||||
jsonb, _ := json.MarshalIndent(a.SpecDoc.OrigSpec(), "", " ")
|
||||
flatjsonb, _ := json.MarshalIndent(a.SpecDoc.Spec(), "", " ")
|
||||
|
||||
consumes, _ := a.makeConsumes()
|
||||
produces, _ := a.makeProduces()
|
||||
sort.Sort(consumes)
|
||||
sort.Sort(produces)
|
||||
security := a.makeSecuritySchemes()
|
||||
baseImport := a.GenOpts.LanguageOpts.baseImport(a.Target)
|
||||
var imports = make(map[string]string)
|
||||
|
||||
var genMods GenDefinitions
|
||||
importPath := a.GenOpts.ExistingModels
|
||||
if a.GenOpts.ExistingModels == "" {
|
||||
imports[a.GenOpts.LanguageOpts.ManglePackageName(a.ModelsPackage, "models")] = path.Join(
|
||||
filepath.ToSlash(baseImport),
|
||||
a.GenOpts.LanguageOpts.ManglePackagePath(a.GenOpts.ModelPackage, "models"))
|
||||
}
|
||||
if importPath != "" {
|
||||
defaultImports = append(defaultImports, importPath)
|
||||
}
|
||||
log.Println("generation target", a.Target)
|
||||
|
||||
baseImport := a.GenOpts.LanguageOpts.baseImport(a.Target)
|
||||
defaultImports := a.GenOpts.defaultImports()
|
||||
imports := a.GenOpts.initImports(a.OperationsPackage)
|
||||
|
||||
log.Println("planning definitions")
|
||||
|
||||
genModels := make(GenDefinitions, 0, len(a.Models))
|
||||
for mn, m := range a.Models {
|
||||
mod, err := makeGenDefinition(
|
||||
model, err := makeGenDefinition(
|
||||
mn,
|
||||
a.ModelsPackage,
|
||||
m,
|
||||
|
@ -636,52 +235,59 @@ func (a *appGenerator) makeCodegenApp() (GenApp, error) {
|
|||
if err != nil {
|
||||
return GenApp{}, fmt.Errorf("error in model %s while planning definitions: %v", mn, err)
|
||||
}
|
||||
if mod != nil {
|
||||
if !mod.External {
|
||||
genMods = append(genMods, *mod)
|
||||
if model != nil {
|
||||
if !model.External {
|
||||
genModels = append(genModels, *model)
|
||||
}
|
||||
|
||||
// Copy model imports to operation imports
|
||||
for alias, pkg := range mod.Imports {
|
||||
// TODO(fredbi): mangle model pkg aliases
|
||||
for alias, pkg := range model.Imports {
|
||||
target := a.GenOpts.LanguageOpts.ManglePackageName(alias, "")
|
||||
imports[target] = pkg
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Sort(genMods)
|
||||
sort.Sort(genModels)
|
||||
|
||||
log.Println("planning operations")
|
||||
tns := make(map[string]struct{})
|
||||
var genOps GenOperations
|
||||
for on, opp := range a.Operations {
|
||||
|
||||
genOps := make(GenOperations, 0, len(a.Operations))
|
||||
for operationName, opp := range a.Operations {
|
||||
o := opp.Op
|
||||
o.Tags = pruneEmpty(o.Tags)
|
||||
o.ID = on
|
||||
o.ID = operationName
|
||||
|
||||
var bldr codeGenOpBuilder
|
||||
bldr.ModelsPackage = a.ModelsPackage
|
||||
bldr.Principal = a.Principal
|
||||
bldr.Target = a.Target
|
||||
bldr.DefaultImports = defaultImports
|
||||
bldr.Imports = imports
|
||||
bldr.DefaultScheme = a.DefaultScheme
|
||||
bldr.Doc = a.SpecDoc
|
||||
bldr.Analyzed = a.Analyzed
|
||||
bldr.BasePath = a.SpecDoc.BasePath()
|
||||
bldr.GenOpts = a.GenOpts
|
||||
bldr := codeGenOpBuilder{
|
||||
ModelsPackage: a.ModelsPackage,
|
||||
Principal: a.GenOpts.PrincipalAlias(),
|
||||
Target: a.Target,
|
||||
DefaultImports: defaultImports,
|
||||
Imports: imports,
|
||||
DefaultScheme: a.DefaultScheme,
|
||||
Doc: a.SpecDoc,
|
||||
Analyzed: a.Analyzed,
|
||||
BasePath: a.SpecDoc.BasePath(),
|
||||
GenOpts: a.GenOpts,
|
||||
Name: operationName,
|
||||
Operation: *o,
|
||||
Method: opp.Method,
|
||||
Path: opp.Path,
|
||||
IncludeValidator: a.GenOpts.IncludeValidator,
|
||||
APIPackage: a.APIPackage, // defaults to main operations package
|
||||
DefaultProduces: a.DefaultProduces,
|
||||
DefaultConsumes: a.DefaultConsumes,
|
||||
}
|
||||
|
||||
tag, tags, ok := bldr.analyzeTags()
|
||||
if !ok {
|
||||
continue // operation filtered according to CLI params
|
||||
}
|
||||
|
||||
// TODO: change operation name to something safe
|
||||
bldr.Name = on
|
||||
bldr.Operation = *o
|
||||
bldr.Method = opp.Method
|
||||
bldr.Path = opp.Path
|
||||
bldr.Authed = len(a.Analyzed.SecurityRequirementsFor(o)) > 0
|
||||
bldr.Security = a.Analyzed.SecurityRequirementsFor(o)
|
||||
bldr.SecurityDefinitions = a.Analyzed.SecurityDefinitionsFor(o)
|
||||
bldr.RootAPIPackage = a.GenOpts.LanguageOpts.ManglePackageName(a.ServerPackage, "server")
|
||||
bldr.IncludeValidator = true
|
||||
bldr.RootAPIPackage = a.GenOpts.LanguageOpts.ManglePackageName(a.ServerPackage, defaultServerTarget)
|
||||
|
||||
bldr.APIPackage = a.APIPackage
|
||||
st := o.Tags
|
||||
if a.GenOpts != nil {
|
||||
st = a.GenOpts.Tags
|
||||
|
@ -691,42 +297,35 @@ func (a *appGenerator) makeCodegenApp() (GenApp, error) {
|
|||
continue
|
||||
}
|
||||
|
||||
if len(intersected) > 0 {
|
||||
tag := intersected[0]
|
||||
bldr.APIPackage = a.GenOpts.LanguageOpts.ManglePackagePath(tag, a.APIPackage)
|
||||
for _, t := range intersected {
|
||||
tns[t] = struct{}{}
|
||||
}
|
||||
}
|
||||
op, err := bldr.MakeOperation()
|
||||
if err != nil {
|
||||
return GenApp{}, err
|
||||
}
|
||||
|
||||
op.ReceiverName = receiver
|
||||
op.Tags = intersected
|
||||
op.Tags = tags // ordered tags for this operation, possibly filtered by CLI params
|
||||
genOps = append(genOps, op)
|
||||
|
||||
}
|
||||
for k := range tns {
|
||||
importPath := filepath.ToSlash(
|
||||
path.Join(
|
||||
filepath.ToSlash(baseImport),
|
||||
a.GenOpts.LanguageOpts.ManglePackagePath(a.OperationsPackage, ""),
|
||||
swag.ToFileName(k)))
|
||||
defaultImports = append(defaultImports, importPath)
|
||||
if !a.GenOpts.SkipTagPackages && tag != "" {
|
||||
importPath := filepath.ToSlash(
|
||||
path.Join(
|
||||
baseImport,
|
||||
a.GenOpts.LanguageOpts.ManglePackagePath(a.OperationsPackage, defaultOperationsTarget),
|
||||
a.GenOpts.LanguageOpts.ManglePackageName(bldr.APIPackage, defaultOperationsTarget),
|
||||
))
|
||||
defaultImports[bldr.APIPackageAlias] = importPath
|
||||
}
|
||||
}
|
||||
sort.Sort(genOps)
|
||||
|
||||
log.Println("grouping operations into packages")
|
||||
opsGroupedByPackage := make(map[string]GenOperations)
|
||||
|
||||
opsGroupedByPackage := make(map[string]GenOperations, len(genOps))
|
||||
for _, operation := range genOps {
|
||||
if operation.Package == "" {
|
||||
operation.Package = a.Package
|
||||
}
|
||||
opsGroupedByPackage[operation.Package] = append(opsGroupedByPackage[operation.Package], operation)
|
||||
opsGroupedByPackage[operation.PackageAlias] = append(opsGroupedByPackage[operation.PackageAlias], operation)
|
||||
}
|
||||
|
||||
var opGroups GenOperationGroups
|
||||
opGroups := make(GenOperationGroups, 0, len(opsGroupedByPackage))
|
||||
for k, v := range opsGroupedByPackage {
|
||||
sort.Sort(v)
|
||||
// trim duplicate extra schemas within the same package
|
||||
|
@ -743,13 +342,20 @@ func (a *appGenerator) makeCodegenApp() (GenApp, error) {
|
|||
op.ExtraSchemas = uniqueExtraSchemas
|
||||
vv = append(vv, op)
|
||||
}
|
||||
var pkg string
|
||||
if len(vv) > 0 {
|
||||
pkg = vv[0].Package
|
||||
} else {
|
||||
pkg = k
|
||||
}
|
||||
|
||||
opGroup := GenOperationGroup{
|
||||
GenCommon: GenCommon{
|
||||
Copyright: a.GenOpts.Copyright,
|
||||
TargetImportPath: filepath.ToSlash(baseImport),
|
||||
TargetImportPath: baseImport,
|
||||
},
|
||||
Name: k,
|
||||
Name: pkg,
|
||||
PackageAlias: k,
|
||||
Operations: vv,
|
||||
DefaultImports: defaultImports,
|
||||
Imports: imports,
|
||||
|
@ -757,13 +363,6 @@ func (a *appGenerator) makeCodegenApp() (GenApp, error) {
|
|||
GenOpts: a.GenOpts,
|
||||
}
|
||||
opGroups = append(opGroups, opGroup)
|
||||
var importPath string
|
||||
if k == a.APIPackage {
|
||||
importPath = path.Join(filepath.ToSlash(baseImport), a.GenOpts.LanguageOpts.ManglePackagePath(a.OperationsPackage, ""))
|
||||
} else {
|
||||
importPath = path.Join(filepath.ToSlash(baseImport), a.GenOpts.LanguageOpts.ManglePackagePath(a.OperationsPackage, ""), k)
|
||||
}
|
||||
defaultImports = append(defaultImports, importPath)
|
||||
}
|
||||
sort.Sort(opGroups)
|
||||
|
||||
|
@ -788,12 +387,15 @@ func (a *appGenerator) makeCodegenApp() (GenApp, error) {
|
|||
basePath = sw.BasePath
|
||||
}
|
||||
|
||||
jsonb, _ := json.MarshalIndent(a.SpecDoc.OrigSpec(), "", " ")
|
||||
flatjsonb, _ := json.MarshalIndent(a.SpecDoc.Spec(), "", " ")
|
||||
|
||||
return GenApp{
|
||||
GenCommon: GenCommon{
|
||||
Copyright: a.GenOpts.Copyright,
|
||||
TargetImportPath: filepath.ToSlash(baseImport),
|
||||
TargetImportPath: baseImport,
|
||||
},
|
||||
APIPackage: a.GenOpts.LanguageOpts.ManglePackageName(a.ServerPackage, "server"),
|
||||
APIPackage: a.GenOpts.LanguageOpts.ManglePackageName(a.ServerPackage, defaultServerTarget),
|
||||
Package: a.Package,
|
||||
ReceiverName: receiver,
|
||||
Name: a.Name,
|
||||
|
@ -810,13 +412,13 @@ func (a *appGenerator) makeCodegenApp() (GenApp, error) {
|
|||
DefaultImports: defaultImports,
|
||||
Imports: imports,
|
||||
SecurityDefinitions: security,
|
||||
Models: genMods,
|
||||
Models: genModels,
|
||||
Operations: genOps,
|
||||
OperationGroups: opGroups,
|
||||
Principal: a.Principal,
|
||||
Principal: a.GenOpts.PrincipalAlias(),
|
||||
SwaggerJSON: generateReadableSpec(jsonb),
|
||||
FlatSwaggerJSON: generateReadableSpec(flatjsonb),
|
||||
ExcludeSpec: a.GenOpts != nil && a.GenOpts.ExcludeSpec,
|
||||
ExcludeSpec: a.GenOpts.ExcludeSpec,
|
||||
GenOpts: a.GenOpts,
|
||||
}, nil
|
||||
}
|
||||
|
|
457
vendor/github.com/go-swagger/go-swagger/generator/template_repo.go
generated
vendored
457
vendor/github.com/go-swagger/go-swagger/generator/template_repo.go
generated
vendored
|
@ -11,6 +11,7 @@ import (
|
|||
"strings"
|
||||
"text/template"
|
||||
"text/template/parse"
|
||||
"unicode"
|
||||
|
||||
"log"
|
||||
|
||||
|
@ -19,177 +20,166 @@ import (
|
|||
"github.com/kr/pretty"
|
||||
)
|
||||
|
||||
var templates *Repository
|
||||
var (
|
||||
assets map[string][]byte
|
||||
protectedTemplates map[string]bool
|
||||
|
||||
// FuncMap is a map with default functions for use n the templates.
|
||||
// FuncMapFunc yields a map with all functions for templates
|
||||
FuncMapFunc func(*LanguageOpts) template.FuncMap
|
||||
|
||||
templates *Repository
|
||||
)
|
||||
|
||||
func initTemplateRepo() {
|
||||
FuncMapFunc = DefaultFuncMap
|
||||
|
||||
// this makes the ToGoName func behave with the special
|
||||
// prefixing rule above
|
||||
swag.GoNamePrefixFunc = prefixForName
|
||||
|
||||
assets = defaultAssets()
|
||||
protectedTemplates = defaultProtectedTemplates()
|
||||
templates = NewRepository(FuncMapFunc(DefaultLanguageFunc()))
|
||||
}
|
||||
|
||||
// DefaultFuncMap yields a map with default functions for use n the templates.
|
||||
// These are available in every template
|
||||
var FuncMap template.FuncMap = map[string]interface{}{
|
||||
"pascalize": pascalize,
|
||||
"camelize": swag.ToJSONName,
|
||||
"varname": golang.MangleVarName,
|
||||
"humanize": swag.ToHumanNameLower,
|
||||
"snakize": golang.MangleFileName,
|
||||
"toPackagePath": func(name string) string {
|
||||
return filepath.FromSlash(golang.ManglePackagePath(name, ""))
|
||||
},
|
||||
"toPackage": func(name string) string {
|
||||
return golang.ManglePackagePath(name, "")
|
||||
},
|
||||
"toPackageName": func(name string) string {
|
||||
return golang.ManglePackageName(name, "")
|
||||
},
|
||||
"dasherize": swag.ToCommandName,
|
||||
"pluralizeFirstWord": func(arg string) string {
|
||||
sentence := strings.Split(arg, " ")
|
||||
if len(sentence) == 1 {
|
||||
return inflect.Pluralize(arg)
|
||||
}
|
||||
|
||||
return inflect.Pluralize(sentence[0]) + " " + strings.Join(sentence[1:], " ")
|
||||
},
|
||||
"json": asJSON,
|
||||
"prettyjson": asPrettyJSON,
|
||||
"hasInsecure": func(arg []string) bool {
|
||||
return swag.ContainsStringsCI(arg, "http") || swag.ContainsStringsCI(arg, "ws")
|
||||
},
|
||||
"hasSecure": func(arg []string) bool {
|
||||
return swag.ContainsStringsCI(arg, "https") || swag.ContainsStringsCI(arg, "wss")
|
||||
},
|
||||
// TODO: simplify redundant functions
|
||||
"stripPackage": func(str, pkg string) string {
|
||||
parts := strings.Split(str, ".")
|
||||
strlen := len(parts)
|
||||
if strlen > 0 {
|
||||
return parts[strlen-1]
|
||||
}
|
||||
return str
|
||||
},
|
||||
"dropPackage": func(str string) string {
|
||||
parts := strings.Split(str, ".")
|
||||
strlen := len(parts)
|
||||
if strlen > 0 {
|
||||
return parts[strlen-1]
|
||||
}
|
||||
return str
|
||||
},
|
||||
"upper": strings.ToUpper,
|
||||
"contains": func(coll []string, arg string) bool {
|
||||
for _, v := range coll {
|
||||
if v == arg {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
},
|
||||
"padSurround": func(entry, padWith string, i, ln int) string {
|
||||
var res []string
|
||||
if i > 0 {
|
||||
for j := 0; j < i; j++ {
|
||||
res = append(res, padWith)
|
||||
}
|
||||
}
|
||||
res = append(res, entry)
|
||||
tot := ln - i - 1
|
||||
for j := 0; j < tot; j++ {
|
||||
res = append(res, padWith)
|
||||
}
|
||||
return strings.Join(res, ",")
|
||||
},
|
||||
"joinFilePath": filepath.Join,
|
||||
"comment": func(str string) string {
|
||||
lines := strings.Split(str, "\n")
|
||||
return (strings.Join(lines, "\n// "))
|
||||
},
|
||||
"blockcomment": func(str string) string {
|
||||
return strings.Replace(str, "*/", "[*]/", -1)
|
||||
},
|
||||
"inspect": pretty.Sprint,
|
||||
"cleanPath": path.Clean,
|
||||
"mediaTypeName": func(orig string) string {
|
||||
return strings.SplitN(orig, ";", 2)[0]
|
||||
},
|
||||
"goSliceInitializer": goSliceInitializer,
|
||||
"hasPrefix": strings.HasPrefix,
|
||||
"stringContains": strings.Contains,
|
||||
func DefaultFuncMap(lang *LanguageOpts) template.FuncMap {
|
||||
return template.FuncMap(map[string]interface{}{
|
||||
"pascalize": pascalize,
|
||||
"camelize": swag.ToJSONName,
|
||||
"varname": lang.MangleVarName,
|
||||
"humanize": swag.ToHumanNameLower,
|
||||
"snakize": lang.MangleFileName,
|
||||
"toPackagePath": func(name string) string {
|
||||
return filepath.FromSlash(lang.ManglePackagePath(name, ""))
|
||||
},
|
||||
"toPackage": func(name string) string {
|
||||
return lang.ManglePackagePath(name, "")
|
||||
},
|
||||
"toPackageName": func(name string) string {
|
||||
return lang.ManglePackageName(name, "")
|
||||
},
|
||||
"dasherize": swag.ToCommandName,
|
||||
"pluralizeFirstWord": pluralizeFirstWord,
|
||||
"json": asJSON,
|
||||
"prettyjson": asPrettyJSON,
|
||||
"hasInsecure": func(arg []string) bool {
|
||||
return swag.ContainsStringsCI(arg, "http") || swag.ContainsStringsCI(arg, "ws")
|
||||
},
|
||||
"hasSecure": func(arg []string) bool {
|
||||
return swag.ContainsStringsCI(arg, "https") || swag.ContainsStringsCI(arg, "wss")
|
||||
},
|
||||
"dropPackage": dropPackage,
|
||||
"upper": strings.ToUpper,
|
||||
"contains": swag.ContainsStrings,
|
||||
"padSurround": padSurround,
|
||||
"joinFilePath": filepath.Join,
|
||||
"comment": padComment,
|
||||
"blockcomment": blockComment,
|
||||
"inspect": pretty.Sprint,
|
||||
"cleanPath": path.Clean,
|
||||
"mediaTypeName": mediaMime,
|
||||
"arrayInitializer": lang.arrayInitializer,
|
||||
"hasPrefix": strings.HasPrefix,
|
||||
"stringContains": strings.Contains,
|
||||
"imports": lang.imports,
|
||||
"dict": dict,
|
||||
})
|
||||
}
|
||||
|
||||
func init() {
|
||||
templates = NewRepository(FuncMap)
|
||||
func defaultAssets() map[string][]byte {
|
||||
return map[string][]byte{
|
||||
// schema validation templates
|
||||
"validation/primitive.gotmpl": MustAsset("templates/validation/primitive.gotmpl"),
|
||||
"validation/customformat.gotmpl": MustAsset("templates/validation/customformat.gotmpl"),
|
||||
"validation/structfield.gotmpl": MustAsset("templates/validation/structfield.gotmpl"),
|
||||
"structfield.gotmpl": MustAsset("templates/structfield.gotmpl"),
|
||||
"schemavalidator.gotmpl": MustAsset("templates/schemavalidator.gotmpl"),
|
||||
"schemapolymorphic.gotmpl": MustAsset("templates/schemapolymorphic.gotmpl"),
|
||||
"schemaembedded.gotmpl": MustAsset("templates/schemaembedded.gotmpl"),
|
||||
|
||||
// schema serialization templates
|
||||
"additionalpropertiesserializer.gotmpl": MustAsset("templates/serializers/additionalpropertiesserializer.gotmpl"),
|
||||
"aliasedserializer.gotmpl": MustAsset("templates/serializers/aliasedserializer.gotmpl"),
|
||||
"allofserializer.gotmpl": MustAsset("templates/serializers/allofserializer.gotmpl"),
|
||||
"basetypeserializer.gotmpl": MustAsset("templates/serializers/basetypeserializer.gotmpl"),
|
||||
"marshalbinaryserializer.gotmpl": MustAsset("templates/serializers/marshalbinaryserializer.gotmpl"),
|
||||
"schemaserializer.gotmpl": MustAsset("templates/serializers/schemaserializer.gotmpl"),
|
||||
"subtypeserializer.gotmpl": MustAsset("templates/serializers/subtypeserializer.gotmpl"),
|
||||
"tupleserializer.gotmpl": MustAsset("templates/serializers/tupleserializer.gotmpl"),
|
||||
|
||||
// schema generation template
|
||||
"docstring.gotmpl": MustAsset("templates/docstring.gotmpl"),
|
||||
"schematype.gotmpl": MustAsset("templates/schematype.gotmpl"),
|
||||
"schemabody.gotmpl": MustAsset("templates/schemabody.gotmpl"),
|
||||
"schema.gotmpl": MustAsset("templates/schema.gotmpl"),
|
||||
"model.gotmpl": MustAsset("templates/model.gotmpl"),
|
||||
"header.gotmpl": MustAsset("templates/header.gotmpl"),
|
||||
|
||||
"swagger_json_embed.gotmpl": MustAsset("templates/swagger_json_embed.gotmpl"),
|
||||
|
||||
// server templates
|
||||
"server/parameter.gotmpl": MustAsset("templates/server/parameter.gotmpl"),
|
||||
"server/urlbuilder.gotmpl": MustAsset("templates/server/urlbuilder.gotmpl"),
|
||||
"server/responses.gotmpl": MustAsset("templates/server/responses.gotmpl"),
|
||||
"server/operation.gotmpl": MustAsset("templates/server/operation.gotmpl"),
|
||||
"server/builder.gotmpl": MustAsset("templates/server/builder.gotmpl"),
|
||||
"server/server.gotmpl": MustAsset("templates/server/server.gotmpl"),
|
||||
"server/configureapi.gotmpl": MustAsset("templates/server/configureapi.gotmpl"),
|
||||
"server/main.gotmpl": MustAsset("templates/server/main.gotmpl"),
|
||||
"server/doc.gotmpl": MustAsset("templates/server/doc.gotmpl"),
|
||||
|
||||
// client templates
|
||||
"client/parameter.gotmpl": MustAsset("templates/client/parameter.gotmpl"),
|
||||
"client/response.gotmpl": MustAsset("templates/client/response.gotmpl"),
|
||||
"client/client.gotmpl": MustAsset("templates/client/client.gotmpl"),
|
||||
"client/facade.gotmpl": MustAsset("templates/client/facade.gotmpl"),
|
||||
}
|
||||
}
|
||||
|
||||
var assets = map[string][]byte{
|
||||
"validation/primitive.gotmpl": MustAsset("templates/validation/primitive.gotmpl"),
|
||||
"validation/customformat.gotmpl": MustAsset("templates/validation/customformat.gotmpl"),
|
||||
"docstring.gotmpl": MustAsset("templates/docstring.gotmpl"),
|
||||
"validation/structfield.gotmpl": MustAsset("templates/validation/structfield.gotmpl"),
|
||||
"modelvalidator.gotmpl": MustAsset("templates/modelvalidator.gotmpl"),
|
||||
"structfield.gotmpl": MustAsset("templates/structfield.gotmpl"),
|
||||
"tupleserializer.gotmpl": MustAsset("templates/tupleserializer.gotmpl"),
|
||||
"additionalpropertiesserializer.gotmpl": MustAsset("templates/additionalpropertiesserializer.gotmpl"),
|
||||
"schematype.gotmpl": MustAsset("templates/schematype.gotmpl"),
|
||||
"schemabody.gotmpl": MustAsset("templates/schemabody.gotmpl"),
|
||||
"schema.gotmpl": MustAsset("templates/schema.gotmpl"),
|
||||
"schemavalidator.gotmpl": MustAsset("templates/schemavalidator.gotmpl"),
|
||||
"model.gotmpl": MustAsset("templates/model.gotmpl"),
|
||||
"header.gotmpl": MustAsset("templates/header.gotmpl"),
|
||||
"swagger_json_embed.gotmpl": MustAsset("templates/swagger_json_embed.gotmpl"),
|
||||
func defaultProtectedTemplates() map[string]bool {
|
||||
return map[string]bool{
|
||||
"dereffedSchemaType": true,
|
||||
"docstring": true,
|
||||
"header": true,
|
||||
"mapvalidator": true,
|
||||
"model": true,
|
||||
"modelvalidator": true,
|
||||
"objectvalidator": true,
|
||||
"primitivefieldvalidator": true,
|
||||
"privstructfield": true,
|
||||
"privtuplefield": true,
|
||||
"propertyValidationDocString": true,
|
||||
"propertyvalidator": true,
|
||||
"schema": true,
|
||||
"schemaBody": true,
|
||||
"schemaType": true,
|
||||
"schemabody": true,
|
||||
"schematype": true,
|
||||
"schemavalidator": true,
|
||||
"serverDoc": true,
|
||||
"slicevalidator": true,
|
||||
"structfield": true,
|
||||
"structfieldIface": true,
|
||||
"subTypeBody": true,
|
||||
"swaggerJsonEmbed": true,
|
||||
"tuplefield": true,
|
||||
"tuplefieldIface": true,
|
||||
"typeSchemaType": true,
|
||||
"validationCustomformat": true,
|
||||
"validationPrimitive": true,
|
||||
"validationStructfield": true,
|
||||
"withBaseTypeBody": true,
|
||||
"withoutBaseTypeBody": true,
|
||||
|
||||
"server/parameter.gotmpl": MustAsset("templates/server/parameter.gotmpl"),
|
||||
"server/urlbuilder.gotmpl": MustAsset("templates/server/urlbuilder.gotmpl"),
|
||||
"server/responses.gotmpl": MustAsset("templates/server/responses.gotmpl"),
|
||||
"server/operation.gotmpl": MustAsset("templates/server/operation.gotmpl"),
|
||||
"server/builder.gotmpl": MustAsset("templates/server/builder.gotmpl"),
|
||||
"server/server.gotmpl": MustAsset("templates/server/server.gotmpl"),
|
||||
"server/configureapi.gotmpl": MustAsset("templates/server/configureapi.gotmpl"),
|
||||
"server/main.gotmpl": MustAsset("templates/server/main.gotmpl"),
|
||||
"server/doc.gotmpl": MustAsset("templates/server/doc.gotmpl"),
|
||||
|
||||
"client/parameter.gotmpl": MustAsset("templates/client/parameter.gotmpl"),
|
||||
"client/response.gotmpl": MustAsset("templates/client/response.gotmpl"),
|
||||
"client/client.gotmpl": MustAsset("templates/client/client.gotmpl"),
|
||||
"client/facade.gotmpl": MustAsset("templates/client/facade.gotmpl"),
|
||||
}
|
||||
|
||||
var protectedTemplates = map[string]bool{
|
||||
"schemabody": true,
|
||||
"privtuplefield": true,
|
||||
"withoutBaseTypeBody": true,
|
||||
"swaggerJsonEmbed": true,
|
||||
"validationCustomformat": true,
|
||||
"tuplefield": true,
|
||||
"header": true,
|
||||
"withBaseTypeBody": true,
|
||||
"primitivefieldvalidator": true,
|
||||
"mapvalidator": true,
|
||||
"propertyValidationDocString": true,
|
||||
"typeSchemaType": true,
|
||||
"docstring": true,
|
||||
"dereffedSchemaType": true,
|
||||
"model": true,
|
||||
"modelvalidator": true,
|
||||
"privstructfield": true,
|
||||
"schemavalidator": true,
|
||||
"tuplefieldIface": true,
|
||||
"tupleSerializer": true,
|
||||
"tupleserializer": true,
|
||||
"schemaSerializer": true,
|
||||
"propertyvalidator": true,
|
||||
"structfieldIface": true,
|
||||
"schemaBody": true,
|
||||
"objectvalidator": true,
|
||||
"schematype": true,
|
||||
"additionalpropertiesserializer": true,
|
||||
"slicevalidator": true,
|
||||
"validationStructfield": true,
|
||||
"validationPrimitive": true,
|
||||
"schemaType": true,
|
||||
"subTypeBody": true,
|
||||
"schema": true,
|
||||
"additionalPropertiesSerializer": true,
|
||||
"serverDoc": true,
|
||||
"structfield": true,
|
||||
"hasDiscriminatedSerializer": true,
|
||||
"discriminatedSerializer": true,
|
||||
// all serializers TODO(fred)
|
||||
"additionalPropertiesSerializer": true,
|
||||
"tupleSerializer": true,
|
||||
"schemaSerializer": true,
|
||||
"hasDiscriminatedSerializer": true,
|
||||
"discriminatedSerializer": true,
|
||||
}
|
||||
}
|
||||
|
||||
// AddFile adds a file to the default repository. It will create a new template based on the filename.
|
||||
|
@ -202,36 +192,6 @@ func AddFile(name, data string) error {
|
|||
return templates.addFile(name, data, false)
|
||||
}
|
||||
|
||||
func asJSON(data interface{}) (string, error) {
|
||||
b, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
func asPrettyJSON(data interface{}) (string, error) {
|
||||
b, err := json.MarshalIndent(data, "", " ")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
func goSliceInitializer(data interface{}) (string, error) {
|
||||
// goSliceInitializer constructs a Go literal initializer from interface{} literals.
|
||||
// e.g. []interface{}{"a", "b"} is transformed in {"a","b",}
|
||||
// e.g. map[string]interface{}{ "a": "x", "b": "y"} is transformed in {"a":"x","b":"y",}.
|
||||
//
|
||||
// NOTE: this is currently used to construct simple slice intializers for default values.
|
||||
// This allows for nicer slice initializers for slices of primitive types and avoid systematic use for json.Unmarshal().
|
||||
b, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.Replace(strings.Replace(strings.Replace(string(b), "}", ",}", -1), "[", "{", -1), "]", ",}", -1), nil
|
||||
}
|
||||
|
||||
// NewRepository creates a new template repository with the provided functions defined
|
||||
func NewRepository(funcs template.FuncMap) *Repository {
|
||||
repo := Repository{
|
||||
|
@ -273,8 +233,6 @@ func (t *Repository) LoadDir(templatePath string) error {
|
|||
if assetName, e := filepath.Rel(templatePath, path); e == nil {
|
||||
if data, e := ioutil.ReadFile(path); e == nil {
|
||||
if ee := t.AddFile(assetName, string(data)); ee != nil {
|
||||
// Fatality is decided by caller
|
||||
// log.Fatal(ee)
|
||||
return fmt.Errorf("could not add template: %v", ee)
|
||||
}
|
||||
}
|
||||
|
@ -515,3 +473,110 @@ func (t *Repository) DumpTemplates() {
|
|||
}
|
||||
log.Println(buf.String())
|
||||
}
|
||||
|
||||
// FuncMap functions
|
||||
|
||||
func asJSON(data interface{}) (string, error) {
|
||||
b, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
func asPrettyJSON(data interface{}) (string, error) {
|
||||
b, err := json.MarshalIndent(data, "", " ")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
func pluralizeFirstWord(arg string) string {
|
||||
sentence := strings.Split(arg, " ")
|
||||
if len(sentence) == 1 {
|
||||
return inflect.Pluralize(arg)
|
||||
}
|
||||
|
||||
return inflect.Pluralize(sentence[0]) + " " + strings.Join(sentence[1:], " ")
|
||||
}
|
||||
|
||||
func dropPackage(str string) string {
|
||||
parts := strings.Split(str, ".")
|
||||
return parts[len(parts)-1]
|
||||
}
|
||||
|
||||
func padSurround(entry, padWith string, i, ln int) string {
|
||||
var res []string
|
||||
if i > 0 {
|
||||
for j := 0; j < i; j++ {
|
||||
res = append(res, padWith)
|
||||
}
|
||||
}
|
||||
res = append(res, entry)
|
||||
tot := ln - i - 1
|
||||
for j := 0; j < tot; j++ {
|
||||
res = append(res, padWith)
|
||||
}
|
||||
return strings.Join(res, ",")
|
||||
}
|
||||
|
||||
func padComment(str string, pads ...string) string {
|
||||
// pads specifes padding to indent multi line comments.Defaults to one space
|
||||
pad := " "
|
||||
lines := strings.Split(str, "\n")
|
||||
if len(pads) > 0 {
|
||||
pad = strings.Join(pads, "")
|
||||
}
|
||||
return (strings.Join(lines, "\n//"+pad))
|
||||
}
|
||||
|
||||
func blockComment(str string) string {
|
||||
return strings.Replace(str, "*/", "[*]/", -1)
|
||||
}
|
||||
|
||||
func pascalize(arg string) string {
|
||||
runes := []rune(arg)
|
||||
switch len(runes) {
|
||||
case 0:
|
||||
return "Empty"
|
||||
case 1: // handle special case when we have a single rune that is not handled by swag.ToGoName
|
||||
switch runes[0] {
|
||||
case '+', '-', '#', '_': // those cases are handled differently than swag utility
|
||||
return prefixForName(arg)
|
||||
}
|
||||
}
|
||||
return swag.ToGoName(swag.ToGoName(arg)) // want to remove spaces
|
||||
}
|
||||
|
||||
func prefixForName(arg string) string {
|
||||
first := []rune(arg)[0]
|
||||
if len(arg) == 0 || unicode.IsLetter(first) {
|
||||
return ""
|
||||
}
|
||||
switch first {
|
||||
case '+':
|
||||
return "Plus"
|
||||
case '-':
|
||||
return "Minus"
|
||||
case '#':
|
||||
return "HashTag"
|
||||
// other cases ($,@ etc..) handled by swag.ToGoName
|
||||
}
|
||||
return "Nr"
|
||||
}
|
||||
|
||||
func dict(values ...interface{}) (map[string]interface{}, error) {
|
||||
if len(values)%2 != 0 {
|
||||
return nil, fmt.Errorf("expected even number of arguments, got %d", len(values))
|
||||
}
|
||||
dict := make(map[string]interface{}, len(values)/2)
|
||||
for i := 0; i < len(values); i += 2 {
|
||||
key, ok := values[i].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected string key, got %+v", values[i])
|
||||
}
|
||||
dict[key] = values[i+1]
|
||||
}
|
||||
return dict, nil
|
||||
}
|
||||
|
|
376
vendor/github.com/go-swagger/go-swagger/generator/types.go
generated
vendored
376
vendor/github.com/go-swagger/go-swagger/generator/types.go
generated
vendored
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/kr/pretty"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -37,27 +38,31 @@ const (
|
|||
str = "string"
|
||||
object = "object"
|
||||
binary = "binary"
|
||||
sHTTP = "http"
|
||||
body = "body"
|
||||
b64 = "byte"
|
||||
)
|
||||
|
||||
// Extensions supported by go-swagger
|
||||
const (
|
||||
xClass = "x-class" // class name used by discriminator
|
||||
xGoCustomTag = "x-go-custom-tag" // additional tag for serializers on struct fields
|
||||
xGoName = "x-go-name" // name of the generated go variable
|
||||
xGoType = "x-go-type" // reuse existing type (do not generate)
|
||||
xIsNullable = "x-isnullable"
|
||||
xNullable = "x-nullable" // turns the schema into a pointer
|
||||
xOmitEmpty = "x-omitempty"
|
||||
xSchemes = "x-schemes" // additional schemes supported for operations (server generation)
|
||||
xOrder = "x-order" // sort order for properties (or any schema)
|
||||
xClass = "x-class" // class name used by discriminator
|
||||
xGoCustomTag = "x-go-custom-tag" // additional tag for serializers on struct fields
|
||||
xGoName = "x-go-name" // name of the generated go variable
|
||||
xGoType = "x-go-type" // reuse existing type (do not generate)
|
||||
xIsNullable = "x-isnullable"
|
||||
xNullable = "x-nullable" // turns the schema into a pointer
|
||||
xOmitEmpty = "x-omitempty"
|
||||
xSchemes = "x-schemes" // additional schemes supported for operations (server generation)
|
||||
xOrder = "x-order" // sort order for properties (or any schema)
|
||||
xGoJSONString = "x-go-json-string"
|
||||
xGoEnumCI = "x-go-enum-ci" // make string enumeration case-insensitive
|
||||
|
||||
xGoOperationTag = "x-go-operation-tag" // additional tag to override generation in operation groups
|
||||
)
|
||||
|
||||
// swaggerTypeMapping contains a mapping from go type to swagger type or format
|
||||
// swaggerTypeName contains a mapping from go type to swagger type or format
|
||||
var swaggerTypeName map[string]string
|
||||
|
||||
func init() {
|
||||
func initTypes() {
|
||||
swaggerTypeName = make(map[string]string)
|
||||
for k, v := range typeMapping {
|
||||
swaggerTypeName[v] = k
|
||||
|
@ -86,6 +91,8 @@ func simpleResolvedType(tn, fmt string, items *spec.Items) (result resolvedType)
|
|||
// special case of swagger format "binary", rendered as io.ReadCloser interface
|
||||
// TODO(fredbi): should set IsCustomFormatter=false when binary
|
||||
result.IsStream = fmt == binary
|
||||
// special case of swagger format "byte", rendered as a strfmt.Base64 type: no validation
|
||||
result.IsBase64 = fmt == b64
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -134,16 +141,15 @@ func newTypeResolver(pkg string, doc *loads.Document) *typeResolver {
|
|||
func knownDefGoType(def string, schema spec.Schema, clear func(string) string) (string, string, string) {
|
||||
debugLog("known def type: %q", def)
|
||||
ext := schema.Extensions
|
||||
if nm, ok := ext.GetString(xGoName); ok {
|
||||
if clear == nil {
|
||||
debugLog("known def type %s no clear: %q", xGoName, nm)
|
||||
return nm, "", ""
|
||||
}
|
||||
debugLog("known def type %s clear: %q -> %q", xGoName, nm, clear(nm))
|
||||
return clear(nm), "", ""
|
||||
nm, hasGoName := ext.GetString(xGoName)
|
||||
|
||||
if hasGoName {
|
||||
debugLog("known def type %s named from %s as %q", def, xGoName, nm)
|
||||
def = nm
|
||||
}
|
||||
v, ok := ext[xGoType]
|
||||
if !ok {
|
||||
extType, isExternalType := hasExternalType(ext)
|
||||
|
||||
if !isExternalType || extType.Embedded {
|
||||
if clear == nil {
|
||||
debugLog("known def type no clear: %q", def)
|
||||
return def, "", ""
|
||||
|
@ -151,25 +157,51 @@ func knownDefGoType(def string, schema spec.Schema, clear func(string) string) (
|
|||
debugLog("known def type clear: %q -> %q", def, clear(def))
|
||||
return clear(def), "", ""
|
||||
}
|
||||
xt := v.(map[string]interface{})
|
||||
t := xt["type"].(string)
|
||||
impIface, ok := xt["import"]
|
||||
|
||||
// external type definition trumps regular type resolution
|
||||
log.Printf("type %s imported as external type %s.%s", def, extType.Import.Package, extType.Type)
|
||||
return extType.Import.Alias + "." + extType.Type, extType.Import.Package, extType.Import.Alias
|
||||
}
|
||||
|
||||
// x-go-type:
|
||||
// type: mytype
|
||||
// import:
|
||||
// package:
|
||||
// alias:
|
||||
// hints:
|
||||
// kind: map|object|array|interface|primitive|stream|tuple
|
||||
// nullable: true|false
|
||||
// embedded: true
|
||||
type externalTypeDefinition struct {
|
||||
Type string
|
||||
Import struct {
|
||||
Package string
|
||||
Alias string
|
||||
}
|
||||
Hints struct {
|
||||
Kind string
|
||||
Nullable bool
|
||||
}
|
||||
Embedded bool
|
||||
}
|
||||
|
||||
func hasExternalType(ext spec.Extensions) (*externalTypeDefinition, bool) {
|
||||
v, ok := ext[xGoType]
|
||||
if !ok {
|
||||
return t, "", ""
|
||||
return nil, false
|
||||
}
|
||||
|
||||
imp := impIface.(map[string]interface{})
|
||||
pkg := imp["package"].(string)
|
||||
al, ok := imp["alias"]
|
||||
var alias string
|
||||
if ok {
|
||||
alias = al.(string)
|
||||
} else {
|
||||
alias = path.Base(pkg)
|
||||
var extType externalTypeDefinition
|
||||
err := mapstructure.Decode(v, &extType)
|
||||
if err != nil {
|
||||
log.Printf("warning: x-go-type extension could not be decoded (%v). Skipped", v)
|
||||
return nil, false
|
||||
}
|
||||
debugLog("known def type %s no clear: %q: pkg=%s, alias=%s", xGoType, alias+"."+t, pkg, alias)
|
||||
return alias + "." + t, pkg, alias
|
||||
if extType.Import.Package != "" && extType.Import.Alias == "" {
|
||||
// NOTE(fred): possible name conflict here (TODO(fred): deconflict this default alias)
|
||||
extType.Import.Alias = path.Base(extType.Import.Package)
|
||||
}
|
||||
debugLogAsJSON("known def external %s type", xGoType, extType)
|
||||
return &extType, true
|
||||
}
|
||||
|
||||
type typeResolver struct {
|
||||
|
@ -218,40 +250,39 @@ func (t *typeResolver) IsNullable(schema *spec.Schema) bool {
|
|||
}
|
||||
|
||||
func (t *typeResolver) resolveSchemaRef(schema *spec.Schema, isRequired bool) (returns bool, result resolvedType, err error) {
|
||||
if schema.Ref.String() != "" {
|
||||
debugLog("resolving ref (anon: %t, req: %t) %s", false, isRequired, schema.Ref.String())
|
||||
returns = true
|
||||
var ref *spec.Schema
|
||||
var er error
|
||||
|
||||
ref, er = spec.ResolveRef(t.Doc.Spec(), &schema.Ref)
|
||||
if er != nil {
|
||||
debugLog("error resolving ref %s: %v", schema.Ref.String(), er)
|
||||
err = er
|
||||
return
|
||||
}
|
||||
res, er := t.ResolveSchema(ref, false, isRequired)
|
||||
if er != nil {
|
||||
err = er
|
||||
return
|
||||
}
|
||||
result = res
|
||||
|
||||
tn := filepath.Base(schema.Ref.GetURL().Fragment)
|
||||
tpe, pkg, alias := knownDefGoType(tn, *ref, t.goTypeName)
|
||||
debugLog("type name %s, package %s, alias %s", tpe, pkg, alias)
|
||||
if tpe != "" {
|
||||
result.GoType = tpe
|
||||
result.Pkg = pkg
|
||||
result.PkgAlias = alias
|
||||
}
|
||||
result.HasDiscriminator = res.HasDiscriminator
|
||||
result.IsBaseType = result.HasDiscriminator
|
||||
result.IsNullable = t.IsNullable(ref)
|
||||
//result.IsAliased = true
|
||||
if schema.Ref.String() == "" {
|
||||
return
|
||||
|
||||
}
|
||||
debugLog("resolving ref (anon: %t, req: %t) %s", false, isRequired, schema.Ref.String())
|
||||
returns = true
|
||||
var ref *spec.Schema
|
||||
var er error
|
||||
|
||||
ref, er = spec.ResolveRef(t.Doc.Spec(), &schema.Ref)
|
||||
if er != nil {
|
||||
debugLog("error resolving ref %s: %v", schema.Ref.String(), er)
|
||||
err = er
|
||||
return
|
||||
}
|
||||
res, er := t.ResolveSchema(ref, false, isRequired)
|
||||
if er != nil {
|
||||
err = er
|
||||
return
|
||||
}
|
||||
result = res
|
||||
|
||||
tn := filepath.Base(schema.Ref.GetURL().Fragment)
|
||||
tpe, pkg, alias := knownDefGoType(tn, *ref, t.goTypeName)
|
||||
debugLog("type name %s, package %s, alias %s", tpe, pkg, alias)
|
||||
if tpe != "" {
|
||||
result.GoType = tpe
|
||||
result.Pkg = pkg
|
||||
result.PkgAlias = alias
|
||||
}
|
||||
result.HasDiscriminator = res.HasDiscriminator
|
||||
result.IsBaseType = result.HasDiscriminator
|
||||
result.IsNullable = t.IsNullable(ref)
|
||||
result.IsEnumCI = false
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -293,6 +324,7 @@ func (t *typeResolver) resolveFormat(schema *spec.Schema, isAnonymous bool, isRe
|
|||
// TODO: should set IsCustomFormatter=false in this case.
|
||||
result.IsPrimitive = schFmt != binary
|
||||
result.IsStream = schFmt == binary
|
||||
result.IsBase64 = schFmt == b64
|
||||
// propagate extensions in resolvedType
|
||||
result.Extensions = schema.Extensions
|
||||
|
||||
|
@ -324,21 +356,6 @@ func (t *typeResolver) isNullable(schema *spec.Schema) bool {
|
|||
return len(schema.Properties) > 0
|
||||
}
|
||||
|
||||
func setIsEmptyOmitted(result *resolvedType, schema *spec.Schema, tpe string) {
|
||||
defaultValue := true
|
||||
if tpe == array {
|
||||
defaultValue = false
|
||||
}
|
||||
v, found := schema.Extensions[xOmitEmpty]
|
||||
if !found {
|
||||
result.IsEmptyOmitted = defaultValue
|
||||
return
|
||||
}
|
||||
|
||||
omitted, cast := v.(bool)
|
||||
result.IsEmptyOmitted = omitted && cast
|
||||
}
|
||||
|
||||
func (t *typeResolver) firstType(schema *spec.Schema) string {
|
||||
if len(schema.Type) == 0 || schema.Type[0] == "" {
|
||||
return object
|
||||
|
@ -396,6 +413,7 @@ func (t *typeResolver) resolveArray(schema *spec.Schema, isAnonymous, isRequired
|
|||
result.ElemType = &rt
|
||||
result.SwaggerType = array
|
||||
result.SwaggerFormat = ""
|
||||
result.IsEnumCI = hasEnumCI(schema.Extensions)
|
||||
t.inferAliasing(&result, schema, isAnonymous, isRequired)
|
||||
result.Extensions = schema.Extensions
|
||||
|
||||
|
@ -627,29 +645,97 @@ func boolExtension(ext spec.Extensions, key string) *bool {
|
|||
return nil
|
||||
}
|
||||
|
||||
func hasEnumCI(ve spec.Extensions) bool {
|
||||
v, ok := ve[xGoEnumCI]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
isEnumCI, ok := v.(bool)
|
||||
// All enumeration types are case-sensitive by default
|
||||
return ok && isEnumCI
|
||||
}
|
||||
|
||||
func (t *typeResolver) shortCircuitResolveExternal(tpe, pkg, alias string, extType *externalTypeDefinition, schema *spec.Schema) resolvedType {
|
||||
// short circuit type resolution for external types
|
||||
var result resolvedType
|
||||
result.Extensions = schema.Extensions
|
||||
result.GoType = tpe
|
||||
result.Pkg = pkg
|
||||
result.PkgAlias = alias
|
||||
result.setKind(extType.Hints.Kind)
|
||||
result.IsNullable = t.IsNullable(schema)
|
||||
|
||||
// other extensions
|
||||
if result.IsArray {
|
||||
result.IsEmptyOmitted = false
|
||||
tpe = "array"
|
||||
}
|
||||
result.setExtensions(schema, tpe)
|
||||
return result
|
||||
}
|
||||
|
||||
func (t *typeResolver) ResolveSchema(schema *spec.Schema, isAnonymous, isRequired bool) (result resolvedType, err error) {
|
||||
debugLog("resolving schema (anon: %t, req: %t) %s", isAnonymous, isRequired, t.ModelName)
|
||||
defer func() {
|
||||
debugLog("returning after resolve schema: %s", pretty.Sprint(result))
|
||||
}()
|
||||
|
||||
if schema == nil {
|
||||
result.IsInterface = true
|
||||
result.GoType = iface
|
||||
return
|
||||
}
|
||||
|
||||
tpe := t.firstType(schema)
|
||||
defer setIsEmptyOmitted(&result, schema, tpe)
|
||||
extType, isExternalType := hasExternalType(schema.Extensions)
|
||||
if isExternalType {
|
||||
tpe, pkg, alias := knownDefGoType(t.ModelName, *schema, t.goTypeName)
|
||||
debugLog("found type declared as external, imported from %s as %s. Has type hints? %t, rendered has embedded? %t",
|
||||
pkg, tpe, extType.Hints.Kind != "", extType.Embedded)
|
||||
|
||||
if extType.Hints.Kind != "" && !extType.Embedded {
|
||||
// use hint to qualify type
|
||||
debugLog("short circuits external type resolution with hint for %s", tpe)
|
||||
result = t.shortCircuitResolveExternal(tpe, pkg, alias, extType, schema)
|
||||
return
|
||||
}
|
||||
|
||||
// use spec to qualify type
|
||||
debugLog("marking type %s as external embedded: %t", tpe, extType.Embedded)
|
||||
// mark this type as an embedded external definition if requested
|
||||
defer func() {
|
||||
result.IsEmbedded = extType.Embedded
|
||||
if result.IsEmbedded {
|
||||
result.ElemType = &resolvedType{
|
||||
GoType: extType.Import.Alias + "." + extType.Type,
|
||||
Pkg: extType.Import.Package,
|
||||
PkgAlias: extType.Import.Alias,
|
||||
IsNullable: extType.Hints.Nullable,
|
||||
}
|
||||
result.setKind(extType.Hints.Kind)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
tpe := t.firstType(schema)
|
||||
var returns bool
|
||||
|
||||
returns, result, err = t.resolveSchemaRef(schema, isRequired)
|
||||
|
||||
if returns {
|
||||
if !isAnonymous {
|
||||
result.IsMap = false
|
||||
result.IsComplexObject = true
|
||||
debugLog("not anonymous ref")
|
||||
}
|
||||
debugLog("returning after ref")
|
||||
debugLog("anonymous after ref")
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
result.setExtensions(schema, tpe)
|
||||
}()
|
||||
|
||||
// special case of swagger type "file", rendered as io.ReadCloser interface
|
||||
if t.firstType(schema) == file {
|
||||
result.SwaggerType = file
|
||||
|
@ -662,7 +748,6 @@ func (t *typeResolver) ResolveSchema(schema *spec.Schema, isAnonymous, isRequire
|
|||
|
||||
returns, result, err = t.resolveFormat(schema, isAnonymous, isRequired)
|
||||
if returns {
|
||||
debugLog("returning after resolve format: %s", pretty.Sprint(result))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -671,7 +756,6 @@ func (t *typeResolver) ResolveSchema(schema *spec.Schema, isAnonymous, isRequire
|
|||
switch tpe {
|
||||
case array:
|
||||
result, err = t.resolveArray(schema, isAnonymous, false)
|
||||
return
|
||||
|
||||
case file, number, integer, boolean:
|
||||
result.Extensions = schema.Extensions
|
||||
|
@ -690,7 +774,6 @@ func (t *typeResolver) ResolveSchema(schema *spec.Schema, isAnonymous, isRequire
|
|||
result.IsNullable = nullableNumber(schema, isRequired)
|
||||
case file:
|
||||
}
|
||||
return
|
||||
|
||||
case str:
|
||||
result.GoType = str
|
||||
|
@ -704,23 +787,21 @@ func (t *typeResolver) ResolveSchema(schema *spec.Schema, isAnonymous, isRequire
|
|||
case object:
|
||||
result, err = t.resolveObject(schema, isAnonymous)
|
||||
if err != nil {
|
||||
return resolvedType{}, err
|
||||
result = resolvedType{}
|
||||
break
|
||||
}
|
||||
result.HasDiscriminator = schema.Discriminator != ""
|
||||
return
|
||||
|
||||
case "null":
|
||||
result.GoType = iface
|
||||
result.SwaggerType = object
|
||||
result.IsNullable = false
|
||||
result.IsInterface = true
|
||||
return
|
||||
|
||||
default:
|
||||
err = fmt.Errorf("unresolvable: %v (format %q)", schema.Type, schema.Format)
|
||||
return
|
||||
}
|
||||
return result, err
|
||||
return
|
||||
}
|
||||
|
||||
// resolvedType is a swagger type that has been resolved and analyzed for usage
|
||||
|
@ -736,6 +817,9 @@ type resolvedType struct {
|
|||
IsNullable bool
|
||||
IsStream bool
|
||||
IsEmptyOmitted bool
|
||||
IsJSONString bool
|
||||
IsEnumCI bool
|
||||
IsBase64 bool
|
||||
|
||||
// A tuple gets rendered as an anonymous struct with P{index} as property name
|
||||
IsTuple bool
|
||||
|
@ -766,6 +850,11 @@ type resolvedType struct {
|
|||
// IsSuperAlias indicates that the aliased type is really the same type,
|
||||
// e.g. in golang, this translates to: type A = B
|
||||
IsSuperAlias bool
|
||||
|
||||
// IsEmbedded applies to externally defined types. When embedded, a type
|
||||
// is generated in models that embeds the external type, with the Validate
|
||||
// method.
|
||||
IsEmbedded bool
|
||||
}
|
||||
|
||||
func (rt *resolvedType) Zero() string {
|
||||
|
@ -799,3 +888,102 @@ func (rt *resolvedType) Zero() string {
|
|||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (rt *resolvedType) setExtensions(schema *spec.Schema, origType string) {
|
||||
rt.IsEnumCI = hasEnumCI(schema.Extensions)
|
||||
rt.setIsEmptyOmitted(schema, origType)
|
||||
rt.setIsJSONString(schema, origType)
|
||||
}
|
||||
|
||||
func (rt *resolvedType) setIsEmptyOmitted(schema *spec.Schema, tpe string) {
|
||||
if v, found := schema.Extensions[xOmitEmpty]; found {
|
||||
omitted, cast := v.(bool)
|
||||
rt.IsEmptyOmitted = omitted && cast
|
||||
return
|
||||
}
|
||||
// array of primitives are by default not empty-omitted, but arrays of aliased type are
|
||||
rt.IsEmptyOmitted = (tpe != array) || (tpe == array && rt.IsAliased)
|
||||
}
|
||||
|
||||
func (rt *resolvedType) setIsJSONString(schema *spec.Schema, tpe string) {
|
||||
_, found := schema.Extensions[xGoJSONString]
|
||||
if !found {
|
||||
rt.IsJSONString = false
|
||||
return
|
||||
}
|
||||
rt.IsJSONString = true
|
||||
}
|
||||
|
||||
func (rt *resolvedType) setKind(kind string) {
|
||||
if kind != "" {
|
||||
debugLog("overriding kind for %s as %s", rt.GoType, kind)
|
||||
}
|
||||
switch kind {
|
||||
case "map":
|
||||
rt.IsMap = true
|
||||
rt.IsArray = false
|
||||
rt.IsComplexObject = false
|
||||
rt.IsInterface = false
|
||||
rt.IsStream = false
|
||||
rt.IsTuple = false
|
||||
rt.IsPrimitive = false
|
||||
rt.SwaggerType = object
|
||||
case "array":
|
||||
rt.IsMap = false
|
||||
rt.IsArray = true
|
||||
rt.IsComplexObject = false
|
||||
rt.IsInterface = false
|
||||
rt.IsStream = false
|
||||
rt.IsTuple = false
|
||||
rt.IsPrimitive = false
|
||||
rt.SwaggerType = array
|
||||
case "object":
|
||||
rt.IsMap = false
|
||||
rt.IsArray = false
|
||||
rt.IsComplexObject = true
|
||||
rt.IsInterface = false
|
||||
rt.IsStream = false
|
||||
rt.IsTuple = false
|
||||
rt.IsPrimitive = false
|
||||
rt.SwaggerType = object
|
||||
case "interface", "null":
|
||||
rt.IsMap = false
|
||||
rt.IsArray = false
|
||||
rt.IsComplexObject = false
|
||||
rt.IsInterface = true
|
||||
rt.IsStream = false
|
||||
rt.IsTuple = false
|
||||
rt.IsPrimitive = false
|
||||
rt.SwaggerType = iface
|
||||
case "stream":
|
||||
rt.IsMap = false
|
||||
rt.IsArray = false
|
||||
rt.IsComplexObject = false
|
||||
rt.IsInterface = false
|
||||
rt.IsStream = true
|
||||
rt.IsTuple = false
|
||||
rt.IsPrimitive = false
|
||||
rt.SwaggerType = file
|
||||
case "tuple":
|
||||
rt.IsMap = false
|
||||
rt.IsArray = false
|
||||
rt.IsComplexObject = false
|
||||
rt.IsInterface = false
|
||||
rt.IsStream = false
|
||||
rt.IsTuple = true
|
||||
rt.IsPrimitive = false
|
||||
rt.SwaggerType = array
|
||||
case "primitive":
|
||||
rt.IsMap = false
|
||||
rt.IsArray = false
|
||||
rt.IsComplexObject = false
|
||||
rt.IsInterface = false
|
||||
rt.IsStream = false
|
||||
rt.IsTuple = false
|
||||
rt.IsPrimitive = true
|
||||
case "":
|
||||
break
|
||||
default:
|
||||
log.Printf("warning: unsupported hint value for external type: %q. Skipped", kind)
|
||||
}
|
||||
}
|
||||
|
|
83
vendor/github.com/go-swagger/go-swagger/scan/enum.go
generated
vendored
Normal file
83
vendor/github.com/go-swagger/go-swagger/scan/enum.go
generated
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
// +build !go1.11
|
||||
|
||||
package scan
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
func upperSnakeCase(s string) string {
|
||||
in := []rune(s)
|
||||
isLower := func(idx int) bool {
|
||||
return idx >= 0 && idx < len(in) && unicode.IsLower(in[idx])
|
||||
}
|
||||
|
||||
out := make([]rune, 0, len(in)+len(in)/2)
|
||||
|
||||
for i, r := range in {
|
||||
if unicode.IsUpper(r) {
|
||||
r = unicode.ToLower(r)
|
||||
if i > 0 && in[i-1] != '_' && (isLower(i-1) || isLower(i+1)) {
|
||||
out = append(out, '_')
|
||||
}
|
||||
}
|
||||
out = append(out, r)
|
||||
}
|
||||
|
||||
return strings.ToUpper(string(out))
|
||||
}
|
||||
|
||||
func getEnumBasicLitValue(basicLit *ast.BasicLit) interface{} {
|
||||
switch basicLit.Kind.String() {
|
||||
case "INT":
|
||||
if result, err := strconv.ParseInt(basicLit.Value, 10, 64); err == nil {
|
||||
return result
|
||||
}
|
||||
case "FLOAT":
|
||||
if result, err := strconv.ParseFloat(basicLit.Value, 64); err == nil {
|
||||
return result
|
||||
}
|
||||
default:
|
||||
return strings.Trim(basicLit.Value, "\"")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getEnumValues(file *ast.File, typeName string) (list []interface{}) {
|
||||
for _, decl := range file.Decls {
|
||||
genDecl, ok := decl.(*ast.GenDecl)
|
||||
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if genDecl.Tok.String() == "const" {
|
||||
for _, spec := range genDecl.Specs {
|
||||
if valueSpec, ok := spec.(*ast.ValueSpec); ok {
|
||||
switch valueSpec.Type.(type) {
|
||||
case *ast.Ident:
|
||||
if valueSpec.Type.(*ast.Ident).Name == typeName {
|
||||
if basicLit, ok := valueSpec.Values[0].(*ast.BasicLit); ok {
|
||||
list = append(list, getEnumBasicLitValue(basicLit))
|
||||
}
|
||||
}
|
||||
default:
|
||||
var name = valueSpec.Names[0].Name
|
||||
if strings.HasPrefix(name, upperSnakeCase(typeName)) {
|
||||
var values = strings.SplitN(name, "__", 2)
|
||||
if len(values) == 2 {
|
||||
list = append(list, values[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
8
vendor/github.com/go-swagger/go-swagger/scan/parameters.go
generated
vendored
8
vendor/github.com/go-swagger/go-swagger/scan/parameters.go
generated
vendored
|
@ -40,6 +40,10 @@ func (pt paramTypable) Typed(tpe, format string) {
|
|||
pt.param.Typed(tpe, format)
|
||||
}
|
||||
|
||||
func (pt paramTypable) WithEnum(values ...interface{}) {
|
||||
pt.param.WithEnum(values...)
|
||||
}
|
||||
|
||||
func (pt paramTypable) SetRef(ref spec.Ref) {
|
||||
pt.param.Ref = ref
|
||||
}
|
||||
|
@ -83,6 +87,10 @@ func (pt itemsTypable) SetRef(ref spec.Ref) {
|
|||
pt.items.Ref = ref
|
||||
}
|
||||
|
||||
func (pt itemsTypable) WithEnum(values ...interface{}) {
|
||||
pt.items.WithEnum(values...)
|
||||
}
|
||||
|
||||
func (pt itemsTypable) Schema() *spec.Schema {
|
||||
return nil
|
||||
}
|
||||
|
|
5
vendor/github.com/go-swagger/go-swagger/scan/responses.go
generated
vendored
5
vendor/github.com/go-swagger/go-swagger/scan/responses.go
generated
vendored
|
@ -38,6 +38,10 @@ func (ht responseTypable) Typed(tpe, format string) {
|
|||
ht.header.Typed(tpe, format)
|
||||
}
|
||||
|
||||
func (ht responseTypable) WithEnum(values ...interface{}) {
|
||||
ht.header.WithEnum(values)
|
||||
}
|
||||
|
||||
func bodyTypable(in string, schema *spec.Schema) (swaggerTypable, *spec.Schema) {
|
||||
if in == "body" {
|
||||
// get the schema for items on the schema property
|
||||
|
@ -85,6 +89,7 @@ func (ht responseTypable) Schema() *spec.Schema {
|
|||
func (ht responseTypable) SetSchema(schema *spec.Schema) {
|
||||
ht.response.Schema = schema
|
||||
}
|
||||
|
||||
func (ht responseTypable) CollectionOf(items *spec.Items, format string) {
|
||||
ht.header.CollectionOf(items, format)
|
||||
}
|
||||
|
|
1
vendor/github.com/go-swagger/go-swagger/scan/scanner.go
generated
vendored
1
vendor/github.com/go-swagger/go-swagger/scan/scanner.go
generated
vendored
|
@ -471,6 +471,7 @@ type swaggerTypable interface {
|
|||
Typed(string, string)
|
||||
SetRef(spec.Ref)
|
||||
Items() swaggerTypable
|
||||
WithEnum(...interface{})
|
||||
Schema() *spec.Schema
|
||||
Level() int
|
||||
}
|
||||
|
|
28
vendor/github.com/go-swagger/go-swagger/scan/schema.go
generated
vendored
28
vendor/github.com/go-swagger/go-swagger/scan/schema.go
generated
vendored
|
@ -81,8 +81,13 @@ func (st schemaTypable) AdditionalProperties() swaggerTypable {
|
|||
st.schema.Typed("object", "")
|
||||
return schemaTypable{st.schema.AdditionalProperties.Schema, st.level + 1}
|
||||
}
|
||||
|
||||
func (st schemaTypable) Level() int { return st.level }
|
||||
|
||||
func (st schemaTypable) WithEnum(values ...interface{}) {
|
||||
st.schema.WithEnum(values...)
|
||||
}
|
||||
|
||||
type schemaValidations struct {
|
||||
current *spec.Schema
|
||||
}
|
||||
|
@ -248,6 +253,18 @@ func (scp *schemaParser) parseDecl(definitions map[string]spec.Schema, decl *sch
|
|||
return err
|
||||
}
|
||||
}
|
||||
if enumName, ok := enumName(decl.Decl.Doc); ok {
|
||||
var enumValues = getEnumValues(decl.File, enumName)
|
||||
if len(enumValues) > 0 {
|
||||
var typeName = reflect.TypeOf(enumValues[0]).String()
|
||||
prop.WithEnum(enumValues...)
|
||||
|
||||
err := swaggerSchemaForType(typeName, prop)
|
||||
if err != nil {
|
||||
return fmt.Errorf("file %s, error is: %v", decl.File.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
case *ast.SelectorExpr:
|
||||
prop := &schemaTypable{schPtr, 0}
|
||||
if strfmtName, ok := strfmtName(decl.Decl.Doc); ok {
|
||||
|
@ -1025,8 +1042,15 @@ func (scp *schemaParser) parseIdentProperty(pkg *loader.PackageInfo, expr *ast.I
|
|||
}
|
||||
|
||||
if enumName, ok := enumName(gd.Doc); ok {
|
||||
log.Println(enumName)
|
||||
return nil
|
||||
var enumValues = getEnumValues(file, enumName)
|
||||
if len(enumValues) > 0 {
|
||||
prop.WithEnum(enumValues...)
|
||||
var typeName = reflect.TypeOf(enumValues[0]).String()
|
||||
err := swaggerSchemaForType(typeName, prop)
|
||||
if err != nil {
|
||||
return fmt.Errorf("file %s, error is: %v", file.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if defaultName, ok := defaultName(gd.Doc); ok {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue