Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/authenticated-api/stdhttp/api/api.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions examples/minimal-server/stdhttp/api/ping.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions examples/petstore-expanded/stdhttp/api/petstore.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions internal/test/issues/issue-1963/issue1963.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions internal/test/issues/issue-2190/issue2190.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions internal/test/issues/issue-2232/issue2232.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions internal/test/strict-server/stdhttp/server.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 19 additions & 24 deletions pkg/codegen/codegen.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ import (
"go/scanner"
"io"
"io/fs"
"maps"
"net/http"
"os"
"runtime/debug"
"slices"
"sort"
"strings"
"text/template"
Expand Down Expand Up @@ -103,11 +105,8 @@ func constructImportMapping(importMapping map[string]string) importMap {
)

{
var packagePaths []string
for _, packageName := range importMapping {
packagePaths = append(packagePaths, packageName)
}
sort.Strings(packagePaths)
packagePaths := slices.Collect(maps.Values(importMapping))
slices.Sort(packagePaths)

for _, packagePath := range packagePaths {
if _, ok := pathToImport[packagePath]; !ok && packagePath != importMappingCurrentPackage {
Expand Down Expand Up @@ -255,7 +254,7 @@ func Generate(spec *openapi3.T, opts Configuration) (string, error) {
if err != nil {
return "", fmt.Errorf("error getting type definition imports: %w", err)
}
MergeImports(xGoTypeImports, imprts)
maps.Copy(xGoTypeImports, imprts)
}

var serverURLsDefinitions string
Expand Down Expand Up @@ -626,11 +625,7 @@ func GenerateConstants(t *template.Template, ops []OperationDefinition) (string,
}
}

var providerNames []string
for providerName := range providerNameMap {
providerNames = append(providerNames, providerName)
}

providerNames := slices.Collect(maps.Keys(providerNameMap))
sort.Strings(providerNames)

constants.SecuritySchemeProviderNames = append(constants.SecuritySchemeProviderNames, providerNames...)
Expand Down Expand Up @@ -944,7 +939,7 @@ func resolvedNameForComponent(section, name string, contentType ...string) strin
}
if len(matches) > 0 {
if len(matches) > 1 {
sort.Strings(matches)
slices.Sort(matches)
}
return globalState.resolvedNames[matches[0]]
}
Expand Down Expand Up @@ -1243,14 +1238,14 @@ func OperationSchemaImports(s *Schema) (map[string]goImport, error) {
if err != nil {
return nil, err
}
MergeImports(res, imprts)
maps.Copy(res, imprts)
}

imprts, err := GoSchemaImports(&openapi3.SchemaRef{Value: s.OAPISchema})
if err != nil {
return nil, err
}
MergeImports(res, imprts)
maps.Copy(res, imprts)
return res, nil
}

Expand All @@ -1263,7 +1258,7 @@ func OperationImports(ops []OperationDefinition) (map[string]goImport, error) {
if err != nil {
return nil, err
}
MergeImports(res, imprts)
maps.Copy(res, imprts)
}
}

Expand All @@ -1272,7 +1267,7 @@ func OperationImports(ops []OperationDefinition) (map[string]goImport, error) {
if err != nil {
return nil, err
}
MergeImports(res, imprts)
maps.Copy(res, imprts)
}

for _, b := range op.Responses {
Expand All @@ -1281,7 +1276,7 @@ func OperationImports(ops []OperationDefinition) (map[string]goImport, error) {
if err != nil {
return nil, err
}
MergeImports(res, imprts)
maps.Copy(res, imprts)
}
}

Expand Down Expand Up @@ -1316,7 +1311,7 @@ func GetTypeDefinitionsImports(swagger *openapi3.T, excludeSchemas []string) (ma
}

for _, imprts := range []map[string]goImport{schemaImports, reqBodiesImports, responsesImports, parametersImports} {
MergeImports(res, imprts)
maps.Copy(res, imprts)
}
return res, nil
}
Expand All @@ -1343,14 +1338,14 @@ func GoSchemaImports(schemas ...*openapi3.SchemaRef) (map[string]goImport, error
if err != nil {
return nil, err
}
MergeImports(res, imprts)
maps.Copy(res, imprts)
}
} else if t.Is("array") {
imprts, err := GoSchemaImports(schemaVal.Items)
if err != nil {
return nil, err
}
MergeImports(res, imprts)
maps.Copy(res, imprts)
}
}
return res, nil
Expand All @@ -1371,7 +1366,7 @@ func GetSchemaImports(schemas map[string]*openapi3.SchemaRef, excludeSchemas []s
if err != nil {
return nil, err
}
MergeImports(res, imprts)
maps.Copy(res, imprts)
}
return res, nil
}
Expand All @@ -1389,7 +1384,7 @@ func GetRequestBodiesImports(bodies map[string]*openapi3.RequestBodyRef) (map[st
if err != nil {
return nil, err
}
MergeImports(res, imprts)
maps.Copy(res, imprts)
}
}
return res, nil
Expand All @@ -1408,7 +1403,7 @@ func GetResponsesImports(responses map[string]*openapi3.ResponseRef) (map[string
if err != nil {
return nil, err
}
MergeImports(res, imprts)
maps.Copy(res, imprts)
}
}
return res, nil
Expand All @@ -1424,7 +1419,7 @@ func GetParametersImports(params map[string]*openapi3.ParameterRef) (map[string]
if err != nil {
return nil, err
}
MergeImports(res, imprts)
maps.Copy(res, imprts)
}
return res, nil
}
Expand Down
43 changes: 25 additions & 18 deletions pkg/codegen/gather.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package codegen

import (
"cmp"
"fmt"
"sort"
"slices"
"strings"

"github.com/getkin/kin-openapi/openapi3"

"github.com/oapi-codegen/oapi-codegen/v2/pkg/util"
)

var _ fmt.Stringer = (*SchemaPath)(nil)

// SchemaPath represents the document location of a schema, e.g.
// ["components", "schemas", "Pet", "properties", "name"].
type SchemaPath []string
Expand All @@ -18,6 +22,8 @@ func (sp SchemaPath) String() string {
return strings.Join(sp, "/")
}

var _ fmt.Stringer = (*SchemaContext)(nil)

// SchemaContext identifies where in the OpenAPI document a schema was found.
type SchemaContext int

Expand Down Expand Up @@ -82,13 +88,13 @@ func (sc SchemaContext) Suffix() string {
// GatheredSchema represents a schema discovered during the gather pass,
// along with its document location and context metadata.
type GatheredSchema struct {
Path SchemaPath
Context SchemaContext
Ref string // $ref string if this is a reference
Schema *openapi3.Schema // The resolved schema value
OperationID string // Enclosing operation's ID, if any
ContentType string // Media type, if from request/response body
StatusCode string // HTTP status code, if from a response
Path SchemaPath
Context SchemaContext
Ref string // $ref string if this is a reference
Schema *openapi3.Schema // The resolved schema value
OperationID string // Enclosing operation's ID, if any
ContentType string // Media type, if from request/response body
StatusCode string // HTTP status code, if from a response
ParamIndex int // Parameter index within an operation
ComponentName string // The component name (e.g., "Bar" for components/schemas/Bar)
GoNameOverride string // x-go-name override from the component or its parent container
Expand All @@ -105,11 +111,13 @@ func GatherSchemas(spec *openapi3.T, opts Configuration) []*GatheredSchema {
var schemas []*GatheredSchema

if spec.Components != nil {
schemas = append(schemas, gatherComponentSchemas(spec.Components)...)
schemas = append(schemas, gatherComponentParameters(spec.Components)...)
schemas = append(schemas, gatherComponentResponses(spec.Components)...)
schemas = append(schemas, gatherComponentRequestBodies(spec.Components)...)
schemas = append(schemas, gatherComponentHeaders(spec.Components)...)
schemas = slices.Concat(
gatherComponentSchemas(spec.Components),
gatherComponentParameters(spec.Components),
gatherComponentResponses(spec.Components),
gatherComponentRequestBodies(spec.Components),
gatherComponentHeaders(spec.Components),
)
}

// Gather client response wrapper types for operations that will generate
Expand Down Expand Up @@ -268,10 +276,8 @@ func gatherComponentHeaders(components *openapi3.Components) []*GatheredSchema {
// `<OperationId>Response`. These don't correspond to a real schema in the
// spec but they need names that don't collide with real types.
func gatherClientResponseWrappers(spec *openapi3.T) []*GatheredSchema {
var result []*GatheredSchema

if spec.Paths == nil {
return result
return nil
}

// Collect all operations sorted for determinism
Expand All @@ -296,10 +302,11 @@ func gatherClientResponseWrappers(spec *openapi3.T) []*GatheredSchema {
}

// Sort by operationID for determinism
sort.Slice(ops, func(i, j int) bool {
return ops[i].op.OperationID < ops[j].op.OperationID
slices.SortFunc(ops, func(a, b opEntry) int {
return cmp.Compare(a.op.OperationID, b.op.OperationID)
})

result := make([]*GatheredSchema, 0, len(ops))
for _, entry := range ops {
result = append(result, &GatheredSchema{
Path: SchemaPath{"paths", entry.path, entry.method, "x-client-response-wrapper"},
Expand Down
25 changes: 9 additions & 16 deletions pkg/codegen/merge_schemas.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package codegen
import (
"errors"
"fmt"
"maps"
"strings"

"github.com/getkin/kin-openapi/openapi3"
Expand Down Expand Up @@ -87,14 +88,10 @@ func mergeAllOf(allOf []*openapi3.SchemaRef) (openapi3.Schema, error) {
func mergeOpenapiSchemas(s1, s2 openapi3.Schema, allOf bool) (openapi3.Schema, error) {
var result openapi3.Schema

result.Extensions = make(map[string]any)
for k, v := range s1.Extensions {
result.Extensions[k] = v
}
for k, v := range s2.Extensions {
// TODO: Check for collisions
result.Extensions[k] = v
}
result.Extensions = make(map[string]any, len(s1.Extensions)+len(s2.Extensions))
maps.Copy(result.Extensions, s1.Extensions)
// TODO: Check for collisions
maps.Copy(result.Extensions, s2.Extensions)

result.OneOf = append(s1.OneOf, s2.OneOf...)

Expand Down Expand Up @@ -195,14 +192,10 @@ func mergeOpenapiSchemas(s1, s2 openapi3.Schema, allOf bool) (openapi3.Schema, e
result.Required = append(s1.Required, s2.Required...)

// We merge all properties
result.Properties = make(map[string]*openapi3.SchemaRef)
for k, v := range s1.Properties {
result.Properties[k] = v
}
for k, v := range s2.Properties {
// TODO: detect conflicts
result.Properties[k] = v
}
result.Properties = make(map[string]*openapi3.SchemaRef, len(s1.Properties)+len(s2.Properties))
maps.Copy(result.Properties, s1.Properties)
// TODO: detect conflicts
maps.Copy(result.Properties, s2.Properties)

if isAdditionalPropertiesExplicitFalse(&s1) || isAdditionalPropertiesExplicitFalse(&s2) {
result.WithoutAdditionalProperties()
Expand Down
Loading
Loading