Skip to content

Commit c117432

Browse files
committed
feat(conflictingmarkers): Make error messages more precise
Updates the `conflictingmarkers` analyzer to include the struct name in the error message, changing the output from: "field <fieldName> has conflicting markers..." to: "field <structName>.<fieldName> has conflicting markers..." This provides more precise context, making it easier for developers to locate the source of the error, especially in complex types. The struct name is reliably determined by inspecting the AST stack during analysis.
1 parent 7ddd54c commit c117432

File tree

2 files changed

+30
-14
lines changed

2 files changed

+30
-14
lines changed

pkg/analysis/conflictingmarkers/analyzer.go

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,25 +68,36 @@ func (a *analyzer) run(pass *analysis.Pass) (any, error) {
6868
}
6969

7070
inspect.InspectFields(func(field *ast.Field, stack []ast.Node, _ extractjsontags.FieldTagInfo, markersAccess markers.Markers) {
71-
checkField(pass, field, markersAccess, a.conflictSets)
71+
var structName string
72+
// Find the struct name from the stack
73+
for i := len(stack) - 2; i >= 0; i-- {
74+
if typeSpec, ok := stack[i].(*ast.TypeSpec); ok {
75+
if _, ok := typeSpec.Type.(*ast.StructType); ok {
76+
structName = typeSpec.Name.Name
77+
break
78+
}
79+
}
80+
}
81+
82+
checkField(pass, field, structName, markersAccess, a.conflictSets)
7283
})
7384

7485
return nil, nil //nolint:nilnil
7586
}
7687

77-
func checkField(pass *analysis.Pass, field *ast.Field, markersAccess markers.Markers, conflictSets []ConflictSet) {
88+
func checkField(pass *analysis.Pass, field *ast.Field, structName string, markersAccess markers.Markers, conflictSets []ConflictSet) {
7889
if field == nil || len(field.Names) == 0 {
7990
return
8091
}
8192

8293
markers := utils.TypeAwareMarkerCollectionForField(pass, markersAccess, field)
8394

8495
for _, conflictSet := range conflictSets {
85-
checkConflict(pass, field, markers, conflictSet)
96+
checkConflict(pass, field, structName, markers, conflictSet)
8697
}
8798
}
8899

89-
func checkConflict(pass *analysis.Pass, field *ast.Field, markers markers.MarkerSet, conflictSet ConflictSet) {
100+
func checkConflict(pass *analysis.Pass, field *ast.Field, structName string, markers markers.MarkerSet, conflictSet ConflictSet) {
90101
// Track which sets have markers present
91102
conflictingMarkers := make([]sets.Set[string], 0)
92103

@@ -106,11 +117,11 @@ func checkConflict(pass *analysis.Pass, field *ast.Field, markers markers.Marker
106117

107118
// If two or more sets have markers, report the conflict
108119
if len(conflictingMarkers) >= 2 {
109-
reportConflict(pass, field, conflictSet, conflictingMarkers)
120+
reportConflict(pass, field, structName, conflictSet, conflictingMarkers)
110121
}
111122
}
112123

113-
func reportConflict(pass *analysis.Pass, field *ast.Field, conflictSet ConflictSet, conflictingMarkers []sets.Set[string]) {
124+
func reportConflict(pass *analysis.Pass, field *ast.Field, structName string, conflictSet ConflictSet, conflictingMarkers []sets.Set[string]) {
114125
// Build a descriptive message showing which sets conflict
115126
setDescriptions := make([]string, 0, len(conflictingMarkers))
116127

@@ -119,8 +130,13 @@ func reportConflict(pass *analysis.Pass, field *ast.Field, conflictSet ConflictS
119130
setDescriptions = append(setDescriptions, fmt.Sprintf("%v", markersList))
120131
}
121132

133+
fieldName := field.Names[0].Name
134+
if structName != "" {
135+
fieldName = structName + "." + fieldName
136+
}
137+
122138
message := fmt.Sprintf("field %s has conflicting markers: %s: {%s}. %s",
123-
field.Names[0].Name,
139+
fieldName,
124140
conflictSet.Name,
125141
strings.Join(setDescriptions, ", "),
126142
conflictSet.Description)

pkg/analysis/conflictingmarkers/testdata/src/a/a.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,31 +17,31 @@ type TestStruct struct {
1717
// Conflict: marker1 vs marker3 (both with values)
1818
// +marker1:=value1
1919
// +marker3:=value2
20-
ConflictWithValuesField string `json:"conflictWithValuesField"` // want "field ConflictWithValuesField has conflicting markers: test_conflict: \\{\\[marker1\\], \\[marker3\\]\\}. Test markers conflict with each other"
20+
ConflictWithValuesField string `json:"conflictWithValuesField"` // want "field TestStruct.ConflictWithValuesField has conflicting markers: test_conflict: \\{\\[marker1\\], \\[marker3\\]\\}. Test markers conflict with each other"
2121

2222
// Conflict: marker1 vs marker3 (mixed with and without values)
2323
// +marker1
2424
// +marker3:=someValue
25-
ConflictMixedField string `json:"conflictMixedField"` // want "field ConflictMixedField has conflicting markers: test_conflict: \\{\\[marker1\\], \\[marker3\\]\\}. Test markers conflict with each other"
25+
ConflictMixedField string `json:"conflictMixedField"` // want "field TestStruct.ConflictMixedField has conflicting markers: test_conflict: \\{\\[marker1\\], \\[marker3\\]\\}. Test markers conflict with each other"
2626

2727
// Multiple conflicts with multiple markers in each set:
2828
// +marker1
2929
// +marker2
3030
// +marker3
3131
// +marker4
32-
MultipleConflictsField string `json:"multipleConflictsField"` // want "field MultipleConflictsField has conflicting markers: test_conflict: \\{\\[marker1 marker2\\], \\[marker3 marker4\\]\\}. Test markers conflict with each other"
32+
MultipleConflictsField string `json:"multipleConflictsField"` // want "field TestStruct.MultipleConflictsField has conflicting markers: test_conflict: \\{\\[marker1 marker2\\], \\[marker3 marker4\\]\\}. Test markers conflict with each other"
3333

3434
// Three-way conflict: marker5 vs marker7 vs marker9
3535
// +marker5
3636
// +marker7
3737
// +marker9
38-
ThreeWayConflictField string `json:"threeWayConflictField"` // want "field ThreeWayConflictField has conflicting markers: three_way_conflict: \\{\\[marker5\\], \\[marker7\\], \\[marker9\\]\\}. Three-way conflict between marker sets"
38+
ThreeWayConflictField string `json:"threeWayConflictField"` // want "field TestStruct.ThreeWayConflictField has conflicting markers: three_way_conflict: \\{\\[marker5\\], \\[marker7\\], \\[marker9\\]\\}. Three-way conflict between marker sets"
3939

4040
// Three-way conflict with values
4141
// +marker6:=value1
4242
// +marker8:=value2
4343
// +marker10:=value3
44-
ThreeWayConflictWithValuesField string `json:"threeWayConflictWithValuesField"` // want "field ThreeWayConflictWithValuesField has conflicting markers: three_way_conflict: \\{\\[marker6\\], \\[marker8\\], \\[marker10\\]\\}. Three-way conflict between marker sets"
44+
ThreeWayConflictWithValuesField string `json:"threeWayConflictWithValuesField"` // want "field TestStruct.ThreeWayConflictWithValuesField has conflicting markers: three_way_conflict: \\{\\[marker6\\], \\[marker8\\], \\[marker10\\]\\}. Three-way conflict between marker sets"
4545

4646
// Valid field with markers from same set in three-way conflict
4747
// +marker5
@@ -55,10 +55,10 @@ type TestStruct struct {
5555
// +marker8
5656
// +marker9
5757
// +marker10
58-
ThreeWayMultipleMarkersField string `json:"threeWayMultipleMarkersField"` // want "field ThreeWayMultipleMarkersField has conflicting markers: three_way_conflict: \\{\\[marker5 marker6\\], \\[marker7 marker8\\], \\[marker10 marker9\\]\\}. Three-way conflict between marker sets"
58+
ThreeWayMultipleMarkersField string `json:"threeWayMultipleMarkersField"` // want "field TestStruct.ThreeWayMultipleMarkersField has conflicting markers: three_way_conflict: \\{\\[marker5 marker6\\], \\[marker7 marker8\\], \\[marker10 marker9\\]\\}. Three-way conflict between marker sets"
5959

6060
// Three-way conflict with only subset of sets triggered (sets 1 and 2 only)
6161
// +marker5
6262
// +marker7
63-
SubsetThreeWayConflictField string `json:"subsetThreeWayConflictField"` // want "field SubsetThreeWayConflictField has conflicting markers: three_way_conflict: \\{\\[marker5\\], \\[marker7\\]\\}. Three-way conflict between marker sets"
63+
SubsetThreeWayConflictField string `json:"subsetThreeWayConflictField"` // want "field TestStruct.SubsetThreeWayConflictField has conflicting markers: three_way_conflict: \\{\\[marker5\\], \\[marker7\\]\\}. Three-way conflict between marker sets"
6464
}

0 commit comments

Comments
 (0)