Skip to content

Commit 98018ae

Browse files
committed
Stop egregious Context abuse.
1 parent 59d3a99 commit 98018ae

File tree

4 files changed

+101
-19
lines changed

4 files changed

+101
-19
lines changed

internal/framework/flex/auto_expand.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1165,7 +1165,7 @@ func expandStruct(ctx context.Context, sourcePath path.Path, from any, targetPat
11651165
fromFieldName := fromField.Name
11661166
_, fromFieldOpts := autoflexTags(fromField)
11671167

1168-
toField, ok := findFieldFuzzy(ctx, fromFieldName, typeFrom, typeTo, flexer)
1168+
toField, ok := (&fuzzyFieldFinder{}).findField(ctx, fromFieldName, typeFrom, typeTo, flexer)
11691169
if !ok {
11701170
// Corresponding field not found in to.
11711171
tflog.SubsystemDebug(ctx, subsystemName, "No corresponding field", map[string]any{

internal/framework/flex/auto_expand_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6033,7 +6033,7 @@ func TestFindFieldFuzzy_Combinations(t *testing.T) {
60336033
}
60346034
flexer := newAutoExpander(opts)
60356035

6036-
field, found := findFieldFuzzy(ctx, fieldNameFrom, typeFrom, typeTo, flexer)
6036+
field, found := (&fuzzyFieldFinder{}).findField(ctx, fieldNameFrom, typeFrom, typeTo, flexer)
60376037
if !found {
60386038
t.Fatalf("expected to find field, but found==false")
60396039
}

internal/framework/flex/auto_flatten.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1512,7 +1512,7 @@ func flattenStruct(ctx context.Context, sourcePath path.Path, from any, targetPa
15121512
for fromField := range flattenSourceFields(ctx, typeFrom, flexer.getOptions()) {
15131513
fromFieldName := fromField.Name
15141514

1515-
toField, ok := findFieldFuzzy(ctx, fromFieldName, typeFrom, typeTo, flexer)
1515+
toField, ok := (&fuzzyFieldFinder{}).findField(ctx, fromFieldName, typeFrom, typeTo, flexer)
15161516
if !ok {
15171517
// Corresponding field not found in to.
15181518
tflog.SubsystemDebug(ctx, subsystemName, "No corresponding field", map[string]any{

internal/framework/flex/autoflex.go

Lines changed: 98 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,7 @@ import (
1717
tfreflect "github.com/hashicorp/terraform-provider-aws/internal/reflect"
1818
)
1919

20-
type fieldNamePrefixCtxKey string
21-
2220
const (
23-
fieldNamePrefixRecurse fieldNamePrefixCtxKey = "FIELD_NAME_PREFIX_RECURSE"
24-
fieldNameSuffixRecurse fieldNamePrefixCtxKey = "FIELD_NAME_SUFFIX_RECURSE"
25-
2621
mapBlockKeyFieldName = "MapBlockKey"
2722
)
2823

@@ -74,7 +69,12 @@ var (
7469
plural = pluralize.NewClient()
7570
)
7671

77-
func findFieldFuzzy(ctx context.Context, fieldNameFrom string, typeFrom reflect.Type, typeTo reflect.Type, flexer autoFlexer) (reflect.StructField, bool) {
72+
type fuzzyFieldFinder struct {
73+
prefixRecursionDepth int
74+
suffixRecursionDepth int
75+
}
76+
77+
func (fff *fuzzyFieldFinder) findField(ctx context.Context, fieldNameFrom string, typeFrom reflect.Type, typeTo reflect.Type, flexer autoFlexer) (reflect.StructField, bool) {
7878
// first precedence is exact match (case sensitive)
7979
if fieldTo, ok := typeTo.FieldByName(fieldNameFrom); ok {
8080
return fieldTo, true
@@ -117,16 +117,18 @@ func findFieldFuzzy(ctx context.Context, fieldNameFrom string, typeFrom reflect.
117117
// fourth precedence is using field name prefix
118118
if v := opts.fieldNamePrefix; v != "" {
119119
v = strings.ReplaceAll(v, " ", "")
120-
if ctx.Value(fieldNamePrefixRecurse) == nil {
120+
if fff.prefixRecursionDepth == 0 {
121121
// so it will only recurse once
122-
ctxP := context.WithValue(ctx, fieldNamePrefixRecurse, true)
122+
fff.prefixRecursionDepth++
123123
if trimmed, ok := strings.CutPrefix(fieldNameFrom, v); ok {
124-
if f, ok2 := findFieldFuzzy(ctxP, trimmed, typeFrom, typeTo, flexer); ok2 {
125-
return f, true
124+
if fieldTo, ok := fff.findField(ctx, trimmed, typeFrom, typeTo, flexer); ok {
125+
fff.prefixRecursionDepth--
126+
return fieldTo, true
126127
}
127128
} else {
128-
if f, ok2 := findFieldFuzzy(ctxP, v+fieldNameFrom, typeFrom, typeTo, flexer); ok2 {
129-
return f, true
129+
if fieldTo, ok := fff.findField(ctx, v+fieldNameFrom, typeFrom, typeTo, flexer); ok {
130+
fff.prefixRecursionDepth--
131+
return fieldTo, true
130132
}
131133
}
132134
// no match via prefix mutation; fall through to suffix handling on the original name
@@ -136,20 +138,100 @@ func findFieldFuzzy(ctx context.Context, fieldNameFrom string, typeFrom reflect.
136138
// fifth precedence is using field name suffix
137139
if v := opts.fieldNameSuffix; v != "" {
138140
v = strings.ReplaceAll(v, " ", "")
139-
if ctx.Value(fieldNameSuffixRecurse) == nil {
141+
if fff.suffixRecursionDepth == 0 {
140142
// so it will only recurse once
141-
ctx = context.WithValue(ctx, fieldNameSuffixRecurse, true)
143+
fff.suffixRecursionDepth++
142144
if strings.HasSuffix(fieldNameFrom, v) {
143-
return findFieldFuzzy(ctx, strings.TrimSuffix(fieldNameFrom, v), typeFrom, typeTo, flexer)
145+
fieldTo, ok := fff.findField(ctx, strings.TrimSuffix(fieldNameFrom, v), typeFrom, typeTo, flexer)
146+
fff.suffixRecursionDepth--
147+
return fieldTo, ok
144148
}
145-
return findFieldFuzzy(ctx, fieldNameFrom+v, typeFrom, typeTo, flexer)
149+
fieldTo, ok := fff.findField(ctx, fieldNameFrom+v, typeFrom, typeTo, flexer)
150+
fff.suffixRecursionDepth--
151+
return fieldTo, ok
146152
}
147153
}
148154

149155
// no finds, fuzzy or otherwise - return zero value
150156
return reflect.StructField{}, false
151157
}
152158

159+
// func findFieldFuzzy(ctx context.Context, fieldNameFrom string, typeFrom reflect.Type, typeTo reflect.Type, flexer autoFlexer) (reflect.StructField, bool) {
160+
// // first precedence is exact match (case sensitive)
161+
// if fieldTo, ok := typeTo.FieldByName(fieldNameFrom); ok {
162+
// return fieldTo, true
163+
// }
164+
165+
// // If a "from" field fuzzy matches a "to" field, we are certain the fuzzy match
166+
// // is NOT correct if "from" also contains a field by the fuzzy matched name.
167+
// // For example, if "from" has "Value" and "Values", "Values" should *never*
168+
// // fuzzy match "Value" in "to" since "from" also has "Value". We check "from"
169+
// // to make sure fuzzy matches are not in "from".
170+
171+
// // second precedence is exact match (case insensitive)
172+
// opts := flexer.getOptions()
173+
// for field := range tfreflect.ExportedStructFields(typeTo) {
174+
// fieldNameTo := field.Name
175+
// if opts.isIgnoredField(fieldNameTo) {
176+
// continue
177+
// }
178+
// if fieldTo, ok := typeTo.FieldByName(fieldNameTo); ok && strings.EqualFold(fieldNameFrom, fieldNameTo) && !fieldExistsInStruct(fieldNameTo, typeFrom) {
179+
// // probably could assume validity here since reflect gave the field name
180+
// return fieldTo, true
181+
// }
182+
// }
183+
184+
// // third precedence is singular/plural
185+
// fieldNameTo := plural.Plural(fieldNameFrom)
186+
// if plural.IsSingular(fieldNameFrom) && !fieldExistsInStruct(fieldNameTo, typeFrom) {
187+
// if fieldTo, ok := typeTo.FieldByName(fieldNameTo); ok {
188+
// return fieldTo, true
189+
// }
190+
// }
191+
192+
// fieldNameTo = plural.Singular(fieldNameFrom)
193+
// if plural.IsPlural(fieldNameFrom) && !fieldExistsInStruct(fieldNameTo, typeFrom) {
194+
// if fieldTo, ok := typeTo.FieldByName(fieldNameTo); ok {
195+
// return fieldTo, true
196+
// }
197+
// }
198+
199+
// // fourth precedence is using field name prefix
200+
// if v := opts.fieldNamePrefix; v != "" {
201+
// v = strings.ReplaceAll(v, " ", "")
202+
// if ctx.Value(fieldNamePrefixRecurse) == nil {
203+
// // so it will only recurse once
204+
// ctxP := context.WithValue(ctx, fieldNamePrefixRecurse, true)
205+
// if trimmed, ok := strings.CutPrefix(fieldNameFrom, v); ok {
206+
// if f, ok2 := findFieldFuzzy(ctxP, trimmed, typeFrom, typeTo, flexer); ok2 {
207+
// return f, true
208+
// }
209+
// } else {
210+
// if f, ok2 := findFieldFuzzy(ctxP, v+fieldNameFrom, typeFrom, typeTo, flexer); ok2 {
211+
// return f, true
212+
// }
213+
// }
214+
// // no match via prefix mutation; fall through to suffix handling on the original name
215+
// }
216+
// }
217+
218+
// // fifth precedence is using field name suffix
219+
// if v := opts.fieldNameSuffix; v != "" {
220+
// v = strings.ReplaceAll(v, " ", "")
221+
// if ctx.Value(fieldNameSuffixRecurse) == nil {
222+
// // so it will only recurse once
223+
// ctx = context.WithValue(ctx, fieldNameSuffixRecurse, true)
224+
// if strings.HasSuffix(fieldNameFrom, v) {
225+
// return findFieldFuzzy(ctx, strings.TrimSuffix(fieldNameFrom, v), typeFrom, typeTo, flexer)
226+
// }
227+
// return findFieldFuzzy(ctx, fieldNameFrom+v, typeFrom, typeTo, flexer)
228+
// }
229+
// }
230+
231+
// // no finds, fuzzy or otherwise - return zero value
232+
// return reflect.StructField{}, false
233+
// }
234+
153235
func fieldExistsInStruct(field string, structType reflect.Type) bool {
154236
_, ok := structType.FieldByName(field)
155237
return ok

0 commit comments

Comments
 (0)