Skip to content

Commit 3a5dcd2

Browse files
authored
private/model/api: Update SDK code generation for colliding field names (#96)
Ports aws/aws-sdk-go#1713 to the v2 SDK. Fixing the issue where API field names could collide with SDK generated methods. Fix #78
1 parent ed4e5c9 commit 3a5dcd2

File tree

3 files changed

+90
-2
lines changed

3 files changed

+90
-2
lines changed

private/model/api/load.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ func (a *API) Setup() {
6363
if !a.NoRenameToplevelShapes {
6464
a.renameToplevelShapes()
6565
}
66+
67+
a.renameCollidingFields()
6668
a.updateTopLevelShapeReferences()
6769
a.createInputOutputShapes()
6870
a.customizationPasses()

private/model/api/passes.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,49 @@ func (a *API) renameExportable() {
229229
}
230230
}
231231

232+
// renameCollidingFields will rename any fields that uses an SDK or Golang
233+
// specific name.
234+
func (a *API) renameCollidingFields() {
235+
for _, v := range a.Shapes {
236+
namesWithSet := map[string]struct{}{}
237+
for k, field := range v.MemberRefs {
238+
if strings.HasPrefix(k, "Set") {
239+
namesWithSet[k] = struct{}{}
240+
}
241+
242+
if collides(k) {
243+
renameCollidingField(k, v, field)
244+
}
245+
}
246+
247+
// checks if any field names collide with setters.
248+
for name := range namesWithSet {
249+
if field, ok := v.MemberRefs["Set"+name]; ok {
250+
renameCollidingField(name, v, field)
251+
}
252+
}
253+
}
254+
}
255+
256+
// collides will return true if it is a name used by the SDK or Golang.
257+
func collides(name string) bool {
258+
switch name {
259+
case "String",
260+
"GoString",
261+
"Validate":
262+
return true
263+
default:
264+
return false
265+
}
266+
}
267+
268+
func renameCollidingField(name string, v *Shape, field *ShapeRef) {
269+
newName := name + "_"
270+
fmt.Printf("Shape %s's field %q renamed to %q\n", v.ShapeName, name, newName)
271+
delete(v.MemberRefs, name)
272+
v.MemberRefs[newName] = field
273+
}
274+
232275
// createInputOutputShapes creates toplevel input/output shapes if they
233276
// have not been defined in the API. This normalizes all APIs to always
234277
// have an input and output structure in the signature.

private/model/api/passes_test.go

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
package api
44

55
import (
6+
"reflect"
67
"testing"
78
)
89

910
func TestUniqueInputAndOutputs(t *testing.T) {
10-
testCases := [][]struct {
11+
cases := [][]struct {
1112
expectedInput string
1213
expectedOutput string
1314
operation string
@@ -38,7 +39,7 @@ func TestUniqueInputAndOutputs(t *testing.T) {
3839
},
3940
}
4041

41-
for _, c := range testCases {
42+
for _, c := range cases {
4243
a := &API{
4344
name: "FooService",
4445
Operations: map[string]*Operation{},
@@ -92,3 +93,45 @@ func TestUniqueInputAndOutputs(t *testing.T) {
9293

9394
}
9495
}
96+
97+
func TestCollidingFields(t *testing.T) {
98+
cases := []struct {
99+
api *API
100+
expected []*Shapes
101+
}{
102+
{
103+
&API{
104+
name: "FooService",
105+
Shapes: []*Shapes{
106+
{
107+
MemberRefs: map[string]*ShapeRef{
108+
"String": &ShapeRef{},
109+
"GoString": &ShapeRef{},
110+
"Validate": &ShapeRef{},
111+
"Foo": &ShapeRef{},
112+
"SetFoo": &ShapeRef{},
113+
},
114+
},
115+
},
116+
},
117+
[]*Shapes{
118+
{
119+
MemberRefs: map[string]*ShapeRef{
120+
"String_": &ShapeRef{},
121+
"GoString_": &ShapeRef{},
122+
"Validate_": &ShapeRef{},
123+
"Foo": &ShapeRef{},
124+
"SetFoo_": &ShapeRef{},
125+
},
126+
},
127+
},
128+
},
129+
}
130+
131+
for _, c := range testCases {
132+
c.api.renameCollidingFields()
133+
if !reflect.DeepEqual(c.api.Shapes, c.expected) {
134+
t.Errorf("expected %v, but received %v", c.expected, c.api.Shapes)
135+
}
136+
}
137+
}

0 commit comments

Comments
 (0)