Skip to content

Commit

Permalink
Fix conversion methods to use correct external type (#3607)
Browse files Browse the repository at this point in the history
* Refactoring

* Add test cases to codegen/service.TestConvertFile()

* Fix conversion methods to use correct external type

* Combine chain of 2 appends into one

* Remove an unnecessary block
  • Loading branch information
tchssk authored Oct 29, 2024
1 parent 4400a80 commit 405ca1c
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 20 deletions.
39 changes: 19 additions & 20 deletions codegen/service/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,7 @@ func ConvertFile(root *expr.RootExpr, service *expr.ServiceExpr) (*codegen.File,
}

// Build header section
pkgs = append(pkgs, &codegen.ImportSpec{Path: "context"})
pkgs = append(pkgs, codegen.GoaImport(""))
pkgs = append(pkgs, &codegen.ImportSpec{Path: "context"}, codegen.GoaImport(""))
path := filepath.Join(codegen.Gendir, codegen.SnakeCase(service.Name), "convert.go")
sections := []*codegen.SectionTemplate{
codegen.Header(service.Name+" service type conversion functions", svc.PkgName, pkgs),
Expand All @@ -238,8 +237,10 @@ func ConvertFile(root *expr.RootExpr, service *expr.ServiceExpr) (*codegen.File,
srcCtx := typeContext("", svc.Scope)
tgtCtx := codegen.NewAttributeContext(false, false, false, tgtPkg, codegen.NewNameScope())
srcAtt := &expr.AttributeExpr{Type: c.User}
tgtAtt := &expr.AttributeExpr{Type: dt}
tgtAtt.AddMeta("struct:type:name", dt.Name()) // Used by transformer to generate the correct type name.
code, tf, err := codegen.GoTransform(
&expr.AttributeExpr{Type: c.User}, &expr.AttributeExpr{Type: dt},
srcAtt, tgtAtt,
"t", "v", srcCtx, tgtCtx, "transform", true)
if err != nil {
return nil, err
Expand Down Expand Up @@ -696,24 +697,22 @@ func compatible(from expr.DataType, to reflect.Type, recs ...compRec) error {
ok bool
field reflect.StructField
)
{
if ef, k := nat.Attribute.Meta["struct:field:external"]; k {
fname = ef[0]
if fname == "-" {
continue
}
field, ok = to.FieldByName(ef[0])
} else if ef, k := nat.Attribute.Meta["struct.field.external"]; k { // Deprecated syntax. Only present for backward compatibility.
fname = ef[0]
if fname == "-" {
continue
}
field, ok = to.FieldByName(ef[0])
} else {
ef := codegen.Goify(ma.ElemName(nat.Name), true)
fname = ef
field, ok = to.FieldByName(ef)
if ef, k := nat.Attribute.Meta["struct:field:external"]; k {
fname = ef[0]
if fname == "-" {
continue
}
field, ok = to.FieldByName(ef[0])
} else if ef, k := nat.Attribute.Meta["struct.field.external"]; k { // Deprecated syntax. Only present for backward compatibility.
fname = ef[0]
if fname == "-" {
continue
}
field, ok = to.FieldByName(ef[0])
} else {
ef := codegen.Goify(ma.ElemName(nat.Name), true)
fname = ef
field, ok = to.FieldByName(ef)
}
if !ok {
return fmt.Errorf("types don't match: could not find field %q of external type %q matching attribute %q of type %q",
Expand Down
2 changes: 2 additions & 0 deletions codegen/service/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,12 @@ func TestConvertFile(t *testing.T) {
{"convert-external-name-required", testdata.ConvertExternalNameRequiredDSL, 1, testdata.ConvertExternalNameRequiredCode},
{"convert-external-name-pointer", testdata.ConvertExternalNamePointerDSL, 1, testdata.ConvertExternalNamePointerCode},
{"convert-external-name-pointer-required", testdata.ConvertExternalNamePointerRequiredDSL, 1, testdata.ConvertExternalNamePointerRequiredCode},
{"convert-external-name-with-initialism", testdata.ConvertExternalNameWithInitialismDSL, 1, testdata.ConvertExternalNameWithInitialismCode},
{"create-external-name", testdata.CreateExternalNameDSL, 1, testdata.CreateExternalNameCode},
{"create-external-name-required", testdata.CreateExternalNameRequiredDSL, 1, testdata.CreateExternalNameRequiredCode},
{"create-external-name-pointer", testdata.CreateExternalNamePointerDSL, 1, testdata.CreateExternalNamePointerCode},
{"create-external-name-pointer-required", testdata.CreateExternalNamePointerRequiredDSL, 1, testdata.CreateExternalNamePointerRequiredCode},
{"create-external-name-with-initialism", testdata.CreateExternalNameWithInitialismDSL, 1, testdata.CreateExternalNameWithInitialismCode},

{"convert-array-string", testdata.ConvertArrayStringDSL, 1, testdata.ConvertArrayStringCode},
{"convert-array-string-required", testdata.ConvertArrayStringRequiredDSL, 1, testdata.ConvertArrayStringRequiredCode},
Expand Down
12 changes: 12 additions & 0 deletions codegen/service/testdata/convert_dsls.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ var ConvertExternalNamePointerRequiredDSL = func() {
})
}

var ConvertExternalNameWithInitialismDSL = func() {
var ExternalNameWithInitialismType = Type("ExternalNameWithInitialismType", func() {
ConvertTo(ApiNameT{})
Attribute("string", String)
})
Service("Service", func() {
Method("Method", func() {
Payload(ExternalNameWithInitialismType)
})
})
}

var ConvertArrayStringDSL = func() {
var ArrayStringType = Type("ArrayStringType", func() {
ConvertTo(ArrayStringT{})
Expand Down
10 changes: 10 additions & 0 deletions codegen/service/testdata/convert_functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ func (t *ExternalNamePointerType) ConvertToExternalNamePointerT() *testdata.Exte
}
`

var ConvertExternalNameWithInitialismCode = `// ConvertToApiNameT creates an instance of ApiNameT initialized from t.
func (t *ExternalNameWithInitialismType) ConvertToApiNameT() *testdata.ApiNameT {
v := &testdata.ApiNameT{}
if t.String != nil {
v.String = *t.String
}
return v
}
`

var ConvertArrayStringCode = `// ConvertToArrayStringT creates an instance of ArrayStringT initialized from t.
func (t *ArrayStringType) ConvertToArrayStringT() *testdata.ArrayStringT {
v := &testdata.ArrayStringT{}
Expand Down
12 changes: 12 additions & 0 deletions codegen/service/testdata/create_dsls.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ var CreateExternalNamePointerRequiredDSL = func() {
})
}

var CreateExternalNameWithInitialismDSL = func() {
var ExternalNameWithInitialismType = Type("ExternalNameWithInitialismType", func() {
CreateFrom(ApiNameT{})
Attribute("string", String)
})
Service("Service", func() {
Method("Method", func() {
Payload(ExternalNameWithInitialismType)
})
})
}

var CreateArrayStringDSL = func() {
var ArrayStringType = Type("ArrayStringType", func() {
CreateFrom(ArrayStringT{})
Expand Down
9 changes: 9 additions & 0 deletions codegen/service/testdata/create_functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ func (t *ExternalNamePointerType) CreateFromExternalNamePointerT(v *testdata.Ext
}
`

var CreateExternalNameWithInitialismCode = `// CreateFromApiNameT initializes t from the fields of v
func (t *ExternalNameWithInitialismType) CreateFromApiNameT(v *testdata.ApiNameT) {
temp := &ExternalNameWithInitialismType{
String: &v.String,
}
*t = *temp
}
`

var CreateArrayStringCode = `// CreateFromArrayStringT initializes t from the fields of v
func (t *ArrayStringType) CreateFromArrayStringT(v *testdata.ArrayStringT) {
temp := &ArrayStringType{}
Expand Down
4 changes: 4 additions & 0 deletions codegen/service/testdata/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ type ExternalNamePointerT struct {
String *string
}

type ApiNameT struct {
String string
}

type ArrayStringT struct {
ArrayString []string
}
Expand Down
8 changes: 8 additions & 0 deletions codegen/transformer.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,14 @@ func (a *AttributeScope) Name(att *expr.AttributeExpr, pkg string, ptr, useDefau
// GoTransform algorithm does not allow for an override.
return a.scope.GoTypeDef(att, ptr, useDefault)
}
if n, ok := att.Meta["struct:type:name"]; ok {
// If the attribute has a "struct:type:name" meta then use it as the
// type name.
if pkg == "" {
return n[0]
}
return pkg + "." + n[0]
}
return a.scope.GoFullTypeName(att, pkg)
}

Expand Down

0 comments on commit 405ca1c

Please sign in to comment.