Repository: ogen-go/ogen
Pull request #514 (2022-08-02 01:27:37)

fix(gen): return `ErrNotImplemented` for array defaults


Patch:
diff --git a/examples/ex_github/oas_defaults_gen.go b/examples/ex_github/oas_defaults_gen.go
index ae14fab9..0fddffba 100644
--- a/examples/ex_github/oas_defaults_gen.go
+++ b/examples/ex_github/oas_defaults_gen.go
@@ -206,13 +206,6 @@ func (s *OrgsCreateInvitationReq) setDefaults() {
 
 // setDefaults set default value of fields.
 func (s *OrgsCreateWebhookReq) setDefaults() {
-	{
-		s.Events = make([]string, 1)
-		{
-			val := string("push")
-			s.Events[0] = val
-		}
-	}
 	{
 		val := bool(true)
 		s.Active.SetTo(val)
@@ -229,13 +222,6 @@ func (s *OrgsSetMembershipForUserReq) setDefaults() {
 
 // setDefaults set default value of fields.
 func (s *OrgsUpdateWebhookReq) setDefaults() {
-	{
-		s.Events = make([]string, 1)
-		{
-			val := string("push")
-			s.Events[0] = val
-		}
-	}
 	{
 		val := bool(true)
 		s.Active.SetTo(val)
@@ -464,13 +450,6 @@ func (s *ReposCreateUsingTemplateReq) setDefaults() {
 
 // setDefaults set default value of fields.
 func (s *ReposCreateWebhookReq) setDefaults() {
-	{
-		s.Events = make([]string, 1)
-		{
-			val := string("push")
-			s.Events[0] = val
-		}
-	}
 	{
 		val := bool(true)
 		s.Active.SetTo(val)
@@ -531,13 +510,6 @@ func (s *ReposUpdateReq) setDefaults() {
 
 // setDefaults set default value of fields.
 func (s *ReposUpdateWebhookReq) setDefaults() {
-	{
-		s.Events = make([]string, 1)
-		{
-			val := string("push")
-			s.Events[0] = val
-		}
-	}
 	{
 		val := bool(true)
 		s.Active.SetTo(val)
diff --git a/examples/go.mod b/examples/go.mod
index 5ba1610e..d678f1ab 100644
--- a/examples/go.mod
+++ b/examples/go.mod
@@ -30,7 +30,4 @@ require (
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
 
-replace (
-	github.com/ogen-go/ogen v0.0.0 => ./..
-	gopkg.in/yaml.v3 v3.0.1 => github.com/go-faster/yamlx v0.0.0-20220711115722-810b8bfdedac
-)
+replace github.com/ogen-go/ogen v0.0.0 => ./..
diff --git a/examples/go.sum b/examples/go.sum
index 3f3d9240..d38de816 100644
--- a/examples/go.sum
+++ b/examples/go.sum
@@ -9,8 +9,6 @@ github.com/go-faster/errors v0.6.1 h1:nNIPOBkprlKzkThvS/0YaX8Zs9KewLCOSFQS5BU06F
 github.com/go-faster/errors v0.6.1/go.mod h1:5MGV2/2T9yvlrbhe9pD9LO5Z/2zCSq2T8j+Jpi2LAyY=
 github.com/go-faster/jx v0.38.1 h1:xHgCqbZA3OZNqwaZ6bXXMlGSBAMrENPJsBYT4g1xtAQ=
 github.com/go-faster/jx v0.38.1/go.mod h1:o7XQ3K95HwNxkBlrpUQIqjcXp4SmDIb9SyohdSVOeQs=
-github.com/go-faster/yamlx v0.0.0-20220711115722-810b8bfdedac h1:SlS3wbHlFz8YJhCiuTSuNRnQeaxOihFLndiy2pO/RH0=
-github.com/go-faster/yamlx v0.0.0-20220711115722-810b8bfdedac/go.mod h1:b+ejL9yLd6fuo3EukHdurhS0khqr/Z5F7CWeZ4AdEnQ=
 github.com/go-faster/yamlx v0.2.1 h1:siwZJO/r3gajIoJbrjoDMjEuVye8xMc8bwmnfNDaZb4=
 github.com/go-faster/yamlx v0.2.1/go.mod h1:AbOy9l8mnD+zAzBYndLxj9IKLEFpUvSi/At3Ygh0kUU=
 github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@@ -67,3 +65,5 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogR
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/gen/_template/defaults/set.tmpl b/gen/_template/defaults/set.tmpl
index 22668e01..25bf9a36 100644
--- a/gen/_template/defaults/set.tmpl
+++ b/gen/_template/defaults/set.tmpl
@@ -2,6 +2,7 @@
 {{- define "defaults/set" -}}
 
 {{ $t := $.Type }}
+
 {{- if or ($t.IsPrimitive) ($t.IsEnum) ($t.IsAlias) -}}
 	{{- template "defaults/val" default_elem $t $.Var $.Default }}
 	{{ $.Var }} = val
@@ -9,19 +10,14 @@
 	{{- if $val.IsNil }}
 		{{- if $t.GenericVariant.Nullable }}
 		{{ $.Var }}.Null = true
-	{{- end }}
+		{{- end }}
 	{{- else }}
 		{{- template "defaults/val" default_elem $t.GenericOf $.Var $.Default }}
 		{{ $.Var }}.SetTo(val)
 	{{- end }}
-{{- else if $t.IsArray -}}
-	{{ $.Var }} = make({{ $t.Go }}, {{ len $.Default.Value }})
-	{{- range $i, $d := $.Default.Value }}
-	{
-		{{- template "defaults/val" sub_default_elem $t.Item $.Var $d }}
-		{{ $.Var }}[{{ $i }}] = val
-	}
-	{{- end }}
+{{- else if $t.IsPointer -}}
+    {{- template "defaults/val" default_elem $t.PointerTo $.Var $.Default }}
+	{{ $.Var }} = &val
 {{- else -}}
 	{{ errorf "unsupported %#v: %s" $.Default.Value $t }}
 {{- end }}
diff --git a/gen/errors.go b/gen/errors.go
index 9a0cc85d..0b3a0345 100644
--- a/gen/errors.go
+++ b/gen/errors.go
@@ -57,6 +57,10 @@ func (e *ErrUnsupportedContentTypes) Error() string {
 }
 
 func (g *Generator) fail(err error) error {
+	if err == nil {
+		return nil
+	}
+
 	hook := g.opt.NotImplementedHook
 	if hook == nil {
 		hook = func(string, error) {}
diff --git a/gen/gen_schema.go b/gen/gen_schema.go
index fccbc748..0223a74e 100644
--- a/gen/gen_schema.go
+++ b/gen/gen_schema.go
@@ -41,6 +41,7 @@ func saveSchemaTypes(ctx *genctx, gen *schemaGen) error {
 func (g *Generator) generateSchema(ctx *genctx, name string, schema *jsonschema.Schema, optional bool) (*ir.Type, error) {
 	gen := newSchemaGen(g.opt.Filename, ctx.lookupRef)
 	gen.log = g.log.Named("schemagen")
+	gen.fail = g.fail
 
 	t, err := gen.generate(name, schema, optional)
 	if err != nil {
diff --git a/gen/ir/go.go b/gen/ir/go.go
index 0be6eb97..d6b7b8ac 100644
--- a/gen/ir/go.go
+++ b/gen/ir/go.go
@@ -1,10 +1,12 @@
 package ir
 
-import "fmt"
+import (
+	"fmt"
+)
 
 // PrintGoValue prints given value as Go value.
-func PrintGoValue(val interface{}) string {
-	switch v := val.(type) {
+func PrintGoValue(v interface{}) string {
+	switch v := v.(type) {
 	case nil:
 		return ""
 	case string:
diff --git a/gen/schema_gen.go b/gen/schema_gen.go
index 450f914b..3e4bce45 100644
--- a/gen/schema_gen.go
+++ b/gen/schema_gen.go
@@ -17,6 +17,7 @@ type schemaGen struct {
 	localRefs map[string]*ir.Type
 	lookupRef func(ref string) (*ir.Type, bool)
 	nameRef   func(ref string) (string, error)
+	fail      func(err error) error
 
 	filename string
 	log      *zap.Logger
@@ -34,6 +35,9 @@ func newSchemaGen(filename string, lookupRef func(ref string) (*ir.Type, bool))
 			}
 			return name, nil
 		},
+		fail: func(err error) error {
+			return err
+		},
 		filename: filename,
 		log:      zap.NewNop(),
 	}
@@ -84,8 +88,20 @@ func (g *schemaGen) generate2(name string, schema *jsonschema.Schema) (ret *ir.T
 			return nil, errors.Wrapf(err, "schema name: %q", ref)
 		}
 	}
-	if schema.DefaultSet && schema.Type == jsonschema.Object {
-		return nil, &ErrNotImplemented{Name: "object defaults"}
+
+	if schema.DefaultSet {
+		var implErr error
+		switch schema.Type {
+		case jsonschema.Object:
+			implErr = &ErrNotImplemented{Name: "object defaults"}
+		case jsonschema.Array:
+			implErr = &ErrNotImplemented{Name: "array defaults"}
+		}
+		// Do not fail schema generation if we cannot handle defaults.
+		if err := g.fail(implErr); err != nil {
+			return nil, err
+		}
+		schema.DefaultSet = implErr == nil
 	}
 
 	if n := schema.XOgenName; n != "" {


Test patch:
diff --git a/gen_test.go b/gen_test.go
index b23d0512..3eacfb1f 100644
--- a/gen_test.go
+++ b/gen_test.go
@@ -135,6 +135,7 @@ func TestGenerate(t *testing.T) {
 				"sum types with same names",
 				"sum type parameter",
 				"unsupported content types",
+				"array defaults",
 			},
 			"manga.json":            {},
 			"telegram_bot_api.json": {},