diff --git a/_integration_tests/integration_test.go b/_integration_tests/integration_test.go index 89359605..bab23049 100644 --- a/_integration_tests/integration_test.go +++ b/_integration_tests/integration_test.go @@ -167,6 +167,49 @@ func TestIssue161(t *testing.T) { } } +func TestIssue301(t *testing.T) { + defer cleanup("./issue301/*") + if err := goagen("./issue301", "bootstrap", "-d", "github.com/shogo82148/goa-v1/_integration_tests/issue301/design"); err != nil { + t.Error(err.Error()) + } + if err := gobuild("./issue301"); err != nil { + t.Error(err.Error()) + } + b, err := os.ReadFile("./issue301/app/user_types.go") + if err != nil { + t.Fatal("failed to load user_types.go") + } + + // include user definition type: "github.com/shogo82148/goa-v1/design" + expectedImport := `import ( + goa "github.com/shogo82148/goa-v1" + "github.com/shogo82148/goa-v1/design" + "time" +)` + + expectedFinalize := `func (ut *issue301Type) Finalize() { + var defaultPrimitiveTypeNumber float64 = 3.140000 + if ut.PrimitiveTypeNumber == nil { + ut.PrimitiveTypeNumber = &defaultPrimitiveTypeNumber + } + var defaultPrimitiveTypeTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") + if ut.PrimitiveTypeTime == nil { + ut.PrimitiveTypeTime = &defaultPrimitiveTypeTime + } + var defaultUserDefinitionType design.SecuritySchemeKind = 10 + if ut.UserDefinitionType == nil { + ut.UserDefinitionType = &defaultUserDefinitionType + } +}` + if !strings.Contains(string(b), expectedImport) { + t.Errorf("Failed to generate 'import' block code that sets default values for user-defined types. Generated context:\n%s", string(b)) + } + + if !strings.Contains(string(b), expectedFinalize) { + t.Errorf("Failed to generate 'Finalize' function code that sets default values for user-defined types. Generated context:\n%s", string(b)) + } +} + func goagen(dir, command string, args ...string) error { pkg, err := build.Import("github.com/shogo82148/goa-v1/goagen", "", 0) if err != nil { diff --git a/_integration_tests/issue301/design/design.go b/_integration_tests/issue301/design/design.go new file mode 100644 index 00000000..7ce7f1b6 --- /dev/null +++ b/_integration_tests/issue301/design/design.go @@ -0,0 +1,39 @@ +package design + +import ( + . "github.com/shogo82148/goa-v1/design" + . "github.com/shogo82148/goa-v1/design/apidsl" +) + +var _ = API("issue301", func() { + Title("This API has user definition type default values") + Host("localhost:8080") + Scheme("https") +}) + +var _ = Resource("issue301", func() { + Action("test", func() { + Routing(GET("user-definition")) + Payload(Issue301Payload) + Response(OK) + }) +}) + +var Issue301Payload = Type("Issue301Type", func() { + Attribute("user-definition-type", Integer, func() { + Default(10) + Metadata("struct:field:type", "design.SecuritySchemeKind", "github.com/shogo82148/goa-v1/design") + }) + + Attribute("primitive-type-number", Number, func() { + Default(3.14) + }) + + Attribute("primitive-type-time", DateTime, func() { + Default("2006-01-02T15:04:05Z") + }) + + Required("user-definition-type") + Required("primitive-type-number") + Required("primitive-type-time") +}) diff --git a/goagen/codegen/finalizer.go b/goagen/codegen/finalizer.go index 05aa65ee..c44ac1a1 100644 --- a/goagen/codegen/finalizer.go +++ b/goagen/codegen/finalizer.go @@ -25,6 +25,7 @@ func NewFinalizer() *Finalizer { "tabs": Tabs, "goify": Goify, "gotyperef": GoTypeRef, + "gotypedef": GoTypeDef, "add": Add, "finalizeCode": f.Code, } @@ -163,7 +164,7 @@ func PrintVal(t design.DataType, val interface{}) string { const ( assignmentTmpl = `{{ if .catt.Type.IsPrimitive }}{{ $defaultName := (print "default" (goify .field true)) }}{{/* -*/}}{{ tabs .depth }}var {{ $defaultName }}{{if .isDatetime}}, _{{end}} = {{ .defaultVal }} +*/}}{{ tabs .depth }}{{if .isDatetime}}var {{ $defaultName }}, _ = {{ .defaultVal }}{{ else }}var {{ $defaultName }} {{ gotypedef .catt 0 false false }} = {{ .defaultVal }}{{end}} {{ tabs .depth }}if {{ .target }}.{{ goify .field true }} == nil { {{ tabs .depth }} {{ .target }}.{{ goify .field true }} = &{{ $defaultName }} }{{ else }}{{ tabs .depth }}if {{ .target }}.{{ goify .field true }} == nil { diff --git a/goagen/codegen/finalizer_test.go b/goagen/codegen/finalizer_test.go index 54f95eec..ae17ce7d 100644 --- a/goagen/codegen/finalizer_test.go +++ b/goagen/codegen/finalizer_test.go @@ -4,6 +4,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/shogo82148/goa-v1/design" + "github.com/shogo82148/goa-v1/dslengine" "github.com/shogo82148/goa-v1/goagen/codegen" ) @@ -160,20 +161,44 @@ var _ = Describe("Struct finalize code generation", func() { Ω(code).Should(Equal(recursiveAssignmentCodeB)) }) }) + + Context("given an object with a user definition type", func() { + BeforeEach(func() { + att = &design.AttributeDefinition{ + Type: &design.Object{ + "foo": &design.AttributeDefinition{ + Type: design.String, + Metadata: dslengine.MetadataDefinition{ + "struct:field:type": []string{"UserDefinitionType", "github.com/shogo82148/goa-v1/goagen/codegen_test"}, + }, + DefaultValue: UserDefinitionType("bar"), + }, + }, + } + target = "ut" + }) + It("finalizes the fields", func() { + code := finalizer.Code(att, target, 0) + Ω(code).Should(Equal(userTypeAssignmentCode)) + }) + }) }) +// UserDefinitionType is a user defined type used in the unit tests. +type UserDefinitionType string + const ( - primitiveAssignmentCode = `var defaultFoo = "bar" + primitiveAssignmentCode = `var defaultFoo string = "bar" if ut.Foo == nil { ut.Foo = &defaultFoo }` - numberAssignmentCodeIntDefault = `var defaultFoo = 50.000000 + numberAssignmentCodeIntDefault = `var defaultFoo float64 = 50.000000 if ut.Foo == nil { ut.Foo = &defaultFoo }` - numberAssignmentCode = `var defaultFoo = 0.000000 + numberAssignmentCode = `var defaultFoo float64 = 0.000000 if ut.Foo == nil { ut.Foo = &defaultFoo }` @@ -192,13 +217,18 @@ if ut.Foo == nil { }` recursiveAssignmentCodeB = ` for _, e := range ut.Elems { - var defaultOther = "foo" + var defaultOther string = "foo" if e.Other == nil { e.Other = &defaultOther } } -var defaultOther = "foo" +var defaultOther string = "foo" if ut.Other == nil { ut.Other = &defaultOther }` + + userTypeAssignmentCode = `var defaultFoo UserDefinitionType = "bar" +if ut.Foo == nil { + ut.Foo = &defaultFoo +}` )