Skip to content
Merged
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
26 changes: 25 additions & 1 deletion cmd/oapi-gen/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const (
directiveReadonly = "readonly"
directiveRequired = "required"
directiveFormat = "format"
directiveEnum = "enum"
)

// Generator is a struct documentation generator. It gathers struct
Expand Down Expand Up @@ -78,10 +79,11 @@ type structInfo struct {
Docs map[string]string
Attrs map[string]string
Formats map[string]string
Enums map[string][]string
}

func (i structInfo) Empty() bool {
return len(i.Docs) == 0 && len(i.Attrs) == 0 && len(i.Formats) == 0
return len(i.Docs) == 0 && len(i.Attrs) == 0 && len(i.Formats) == 0 && len(i.Enums) == 0
}

//nolint:cyclop,gocognit // Splitting this will not make it simpler.
Expand Down Expand Up @@ -155,6 +157,7 @@ func (g *Generator) gatherStructInfo(name string, typ *ast.StructType) (structIn
Docs: map[string]string{},
Attrs: map[string]string{},
Formats: map[string]string{},
Enums: map[string][]string{},
}
for _, field := range typ.Fields.List {
if field.Doc == nil {
Expand Down Expand Up @@ -183,6 +186,17 @@ func (g *Generator) gatherStructInfo(name string, typ *ast.StructType) (structIn
return info, fmt.Errorf("format directive should be in format openapi:format=<format>, got %s", d)
}
info.Formats[fldName] = val
case strings.HasPrefix(d, directiveEnum):
_, val, found := strings.Cut(d, "=")
if !found {
return info, fmt.Errorf("enum directive should be in format openapi:enum=foo,bar, got %s", d)
}
// Split by comma and trim spaces
values := strings.Split(val, ",")
for i := range values {
values[i] = strings.TrimSpace(values[i])
}
info.Enums[fldName] = values
}
}
}
Expand Down Expand Up @@ -289,5 +303,15 @@ func ({{ .Name }}) Formats() map[string]string {
}
}
{{ end }}
{{- if .Enums }}
// Enums returns a set of possible enum values per property.
func ({{ .Name }}) Enums() map[string][]string {
return map[string][]string {
{{- range $k, $v := .Enums }}
"{{ $k }}": { {{- range $i, $val := $v }}{{if $i}}, {{end}}"{{ $val }}"{{- end }} },
{{- end }}
}
}
{{ end }}
{{ end }}
`
8 changes: 8 additions & 0 deletions cmd/oapi-gen/testdata/all.go

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

5 changes: 5 additions & 0 deletions cmd/oapi-gen/testdata/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,9 @@ type TestOtherObject struct {
//
//openapi:format=ipv4 // This should be ignored
E string

// F is a field that uses enum values.
//
//openapi:enum=foo,bar // This should be ignored
Comment thread
Ullaakut marked this conversation as resolved.
Comment thread
Ullaakut marked this conversation as resolved.
F string
}
20 changes: 20 additions & 0 deletions gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,10 @@ type formatable interface {
Formats() map[string]string
}

type enumerable interface {
Enums() map[string][]string
}

func customizer(name string, t reflect.Type, _ reflect.StructTag, schema *kin.Schema) error {
v := reflect.New(t).Elem().Interface()

Expand Down Expand Up @@ -392,6 +396,10 @@ func customizer(name string, t reflect.Type, _ reflect.StructTag, schema *kin.Sc
applyFormats(schema, obj)
}

if obj, ok := v.(enumerable); ok {
applyEnums(schema, obj)
}

return nil
}

Expand Down Expand Up @@ -470,3 +478,15 @@ func applyFormats(schema *kin.Schema, obj formatable) {
prop.Value.WithFormat(fmt)
}
}

func applyEnums(schema *kin.Schema, obj enumerable) {
enums := obj.Enums()
for k, prop := range schema.Properties {
enum := enums[k]
if len(enum) == 0 || prop.Value == nil {
continue
}

prop.Value.WithEnum(enum)
}
}
6 changes: 6 additions & 0 deletions gen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,9 @@ func (TestObject) Formats() map[string]string {
"test4": "ipv4",
}
}

func (TestObject) Enums() map[string][]string {
return map[string][]string{
"test4": []string{"192.168.1.0", "192.168.1.1"},
}
}
6 changes: 6 additions & 0 deletions testdata/spec-pkgseg0.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@
"type": "string"
},
"test4": {
"enum": [
[
"192.168.1.0",
"192.168.1.1"
]
],
"format": "ipv4",
"type": "string"
}
Expand Down
6 changes: 6 additions & 0 deletions testdata/spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@
"type": "string"
},
"test4": {
"enum": [
[
"192.168.1.0",
"192.168.1.1"
]
],
"format": "ipv4",
"type": "string"
}
Expand Down
Loading