Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure that imports are not removed in generated code #406

Merged
merged 4 commits into from
Jan 27, 2023
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
7 changes: 7 additions & 0 deletions changelog/@unreleased/pr-406.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
type: fix
fix:
description: Fixes an issue where generated code would not include imports that
referenced packages where the last component of the package path was of the form
"v[0-9]+".
links:
- https://github.com/palantir/conjure-go/pull/406
16 changes: 16 additions & 0 deletions conjure/conjure.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
package conjure

import (
"os"
"path/filepath"
"sort"

"github.com/dave/jennifer/jen"
"github.com/palantir/conjure-go/v6/conjure-api/conjure/spec"
"github.com/palantir/conjure-go/v6/conjure/snip"
"github.com/palantir/conjure-go/v6/conjure/types"
"github.com/palantir/go-ptimports/v2/ptimports"
"github.com/pkg/errors"
)

Expand All @@ -30,11 +32,25 @@ func Generate(conjureDefinition spec.ConjureDefinition, outputConfiguration Outp
if err != nil {
return err
}
// write the generated files
for _, file := range files {
if err := file.Write(); err != nil {
return err
}
}
// format all the generated files after they have been written.
// Must be done after all the files are written to ensure that imports are processed correctly (goimports adds named
// aliases for imports where the inferred package name differs from the actual package name, and this can only be
// properly determined after all generated code is written -- see https://github.com/palantir/conjure-go/issues/405).
for _, file := range files {
goFileSrc, err := ptimports.Process(file.absPath, nil, nil)
if err != nil {
return errors.Wrapf(err, "failed to run ptimports on generated Go source for file %s", file.absPath)
}
if err := os.WriteFile(file.absPath, goFileSrc, 0644); err != nil {
return errors.Wrapf(err, "failed to write file")
}
}
return nil
}

Expand Down
5 changes: 4 additions & 1 deletion conjure/outputs.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ func (f *OutputFile) Render() ([]byte, error) {
return nil, errors.Wrapf(err, "failed to generate Go source for file %s", f.absPath)
}

goFileSrc, err := ptimports.Process("", buf.Bytes(), &ptimports.Options{Refactor: true})
goFileSrc, err := ptimports.Process("", buf.Bytes(), &ptimports.Options{
Refactor: true,
FormatOnly: true,
})
if err != nil {
return nil, errors.Wrapf(err, "failed to run ptimports on generated Go source for file %s", f.absPath)
}
Expand Down
5 changes: 5 additions & 0 deletions integration_test/testgenerated/imports/imports.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@ types:
package: com.palantir.pkg2.api
fields:
data: Struct1
ObjectInPackageEndingInVersion:
package: com.palantir.pkg4.v2
fields:
name: string
Union:
package: com.palantir.pkg3.api
union:
one: Struct1
two: Struct2
three: ObjectInPackageEndingInVersion
13 changes: 0 additions & 13 deletions integration_test/testgenerated/imports/imports_test.go

This file was deleted.

40 changes: 32 additions & 8 deletions integration_test/testgenerated/imports/pkg3/api/unions.conjure.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,27 @@ import (

"github.com/palantir/conjure-go/v6/integration_test/testgenerated/imports/pkg1/api"
api1 "github.com/palantir/conjure-go/v6/integration_test/testgenerated/imports/pkg2/api"
v2 "github.com/palantir/conjure-go/v6/integration_test/testgenerated/imports/pkg4/v2"
"github.com/palantir/pkg/safejson"
"github.com/palantir/pkg/safeyaml"
)

type Union struct {
typ string
one *api.Struct1
two *api1.Struct2
typ string
one *api.Struct1
two *api1.Struct2
three *v2.ObjectInPackageEndingInVersion
}

type unionDeserializer struct {
Type string `json:"type"`
One *api.Struct1 `json:"one"`
Two *api1.Struct2 `json:"two"`
Type string `json:"type"`
One *api.Struct1 `json:"one"`
Two *api1.Struct2 `json:"two"`
Three *v2.ObjectInPackageEndingInVersion `json:"three"`
}

func (u *unionDeserializer) toStruct() Union {
return Union{typ: u.Type, one: u.One, two: u.Two}
return Union{typ: u.Type, one: u.One, two: u.Two, three: u.Three}
}

func (u *Union) toSerializer() (interface{}, error) {
Expand All @@ -42,6 +45,11 @@ func (u *Union) toSerializer() (interface{}, error) {
Type string `json:"type"`
Two api1.Struct2 `json:"two"`
}{Type: "two", Two: *u.two}, nil
case "three":
return struct {
Type string `json:"type"`
Three v2.ObjectInPackageEndingInVersion `json:"three"`
}{Type: "three", Three: *u.three}, nil
}
}

Expand Down Expand Up @@ -78,7 +86,7 @@ func (u *Union) UnmarshalYAML(unmarshal func(interface{}) error) error {
return safejson.Unmarshal(jsonBytes, *&u)
}

func (u *Union) AcceptFuncs(oneFunc func(api.Struct1) error, twoFunc func(api1.Struct2) error, unknownFunc func(string) error) error {
func (u *Union) AcceptFuncs(oneFunc func(api.Struct1) error, twoFunc func(api1.Struct2) error, threeFunc func(v2.ObjectInPackageEndingInVersion) error, unknownFunc func(string) error) error {
switch u.typ {
default:
if u.typ == "" {
Expand All @@ -89,6 +97,8 @@ func (u *Union) AcceptFuncs(oneFunc func(api.Struct1) error, twoFunc func(api1.S
return oneFunc(*u.one)
case "two":
return twoFunc(*u.two)
case "three":
return threeFunc(*u.three)
}
}

Expand All @@ -100,6 +110,10 @@ func (u *Union) TwoNoopSuccess(api1.Struct2) error {
return nil
}

func (u *Union) ThreeNoopSuccess(v2.ObjectInPackageEndingInVersion) error {
return nil
}

func (u *Union) ErrorOnUnknown(typeName string) error {
return fmt.Errorf("invalid value in union type. Type name: %s", typeName)
}
Expand All @@ -115,12 +129,15 @@ func (u *Union) Accept(v UnionVisitor) error {
return v.VisitOne(*u.one)
case "two":
return v.VisitTwo(*u.two)
case "three":
return v.VisitThree(*u.three)
}
}

type UnionVisitor interface {
VisitOne(v api.Struct1) error
VisitTwo(v api1.Struct2) error
VisitThree(v v2.ObjectInPackageEndingInVersion) error
VisitUnknown(typeName string) error
}

Expand All @@ -135,12 +152,15 @@ func (u *Union) AcceptWithContext(ctx context.Context, v UnionVisitorWithContext
return v.VisitOneWithContext(ctx, *u.one)
case "two":
return v.VisitTwoWithContext(ctx, *u.two)
case "three":
return v.VisitThreeWithContext(ctx, *u.three)
}
}

type UnionVisitorWithContext interface {
VisitOneWithContext(ctx context.Context, v api.Struct1) error
VisitTwoWithContext(ctx context.Context, v api1.Struct2) error
VisitThreeWithContext(ctx context.Context, v v2.ObjectInPackageEndingInVersion) error
VisitUnknownWithContext(ctx context.Context, typeName string) error
}

Expand All @@ -151,3 +171,7 @@ func NewUnionFromOne(v api.Struct1) Union {
func NewUnionFromTwo(v api1.Struct2) Union {
return Union{typ: "two", two: &v}
}

func NewUnionFromThree(v v2.ObjectInPackageEndingInVersion) Union {
return Union{typ: "three", three: &v}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/palantir/conjure-go/v6/integration_test/testgenerated/imports/pkg1/api"
api1 "github.com/palantir/conjure-go/v6/integration_test/testgenerated/imports/pkg2/api"
v2 "github.com/palantir/conjure-go/v6/integration_test/testgenerated/imports/pkg4/v2"
)

type UnionWithT[T any] Union
Expand All @@ -26,11 +27,14 @@ func (u *UnionWithT[T]) Accept(ctx context.Context, v UnionVisitorWithT[T]) (T,
return v.VisitOne(ctx, *u.one)
case "two":
return v.VisitTwo(ctx, *u.two)
case "three":
return v.VisitThree(ctx, *u.three)
}
}

type UnionVisitorWithT[T any] interface {
VisitOne(ctx context.Context, v api.Struct1) (T, error)
VisitTwo(ctx context.Context, v api1.Struct2) (T, error)
VisitThree(ctx context.Context, v v2.ObjectInPackageEndingInVersion) (T, error)
VisitUnknown(ctx context.Context, typ string) (T, error)
}
28 changes: 28 additions & 0 deletions integration_test/testgenerated/imports/pkg4/v2/structs.conjure.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// This file was generated by Conjure and should not be manually edited.

package v2

import (
"github.com/palantir/pkg/safejson"
"github.com/palantir/pkg/safeyaml"
)

type ObjectInPackageEndingInVersion struct {
Name string `json:"name"`
}

func (o ObjectInPackageEndingInVersion) MarshalYAML() (interface{}, error) {
jsonBytes, err := safejson.Marshal(o)
if err != nil {
return nil, err
}
return safeyaml.JSONtoYAMLMapSlice(jsonBytes)
}

func (o *ObjectInPackageEndingInVersion) UnmarshalYAML(unmarshal func(interface{}) error) error {
jsonBytes, err := safeyaml.UnmarshalerToJSONBytes(unmarshal)
if err != nil {
return err
}
return safejson.Unmarshal(jsonBytes, *&o)
}