@@ -34,20 +34,29 @@ const name = "preferredmarkers"
3434type analyzer struct {
3535 // equivalentToPreferred maps equivalent marker identifiers to their preferred identifiers
3636 equivalentToPreferred map [string ]string
37+
38+ // preferredToMessage maps preferred marker identifiers to their custom message
39+ preferredToMessage map [string ]string
3740}
3841
3942// newAnalyzer creates a new analysis.Analyzer for the preferredmarkers
4043// linter based on the provided Config.
4144func newAnalyzer (cfg * Config ) * analysis.Analyzer {
4245 a := & analyzer {
4346 equivalentToPreferred : make (map [string ]string ),
47+ preferredToMessage : make (map [string ]string ),
4448 }
4549
4650 // Build the mapping from equivalent identifiers to preferred identifiers
4751 for _ , marker := range cfg .Markers {
4852 for _ , equivalent := range marker .EquivalentIdentifiers {
4953 a .equivalentToPreferred [equivalent .Identifier ] = marker .PreferredIdentifier
5054 }
55+
56+ msg := marker .Message
57+ if msg != "" {
58+ a .preferredToMessage [marker .PreferredIdentifier ] = msg
59+ }
5160 }
5261
5362 analyzer := & analysis.Analyzer {
@@ -75,11 +84,11 @@ func (a *analyzer) run(pass *analysis.Pass) (any, error) {
7584 }
7685
7786 inspect .InspectFields (func (field * ast.Field , _ extractjsontags.FieldTagInfo , markersAccess markers.Markers , qualifiedFieldName string ) {
78- checkField (pass , field , markersAccess , a .equivalentToPreferred , qualifiedFieldName )
87+ checkField (pass , field , markersAccess , a .equivalentToPreferred , a . preferredToMessage , qualifiedFieldName )
7988 })
8089
8190 inspect .InspectTypeSpec (func (typeSpec * ast.TypeSpec , markersAccess markers.Markers ) {
82- checkType (pass , typeSpec , markersAccess , a .equivalentToPreferred )
91+ checkType (pass , typeSpec , markersAccess , a .equivalentToPreferred , a . preferredToMessage )
8392 })
8493
8594 return nil , nil //nolint:nilnil
@@ -88,26 +97,26 @@ func (a *analyzer) run(pass *analysis.Pass) (any, error) {
8897// checkField validates a single struct field for marker usage.
8998// Only checks markers directly on the field, not inherited from type aliases,
9099// since inherited markers are already reported at the type level.
91- func checkField (pass * analysis.Pass , field * ast.Field , markersAccess markers.Markers , equivalentToPreferred map [string ]string , qualifiedFieldName string ) {
100+ func checkField (pass * analysis.Pass , field * ast.Field , markersAccess markers.Markers , equivalentToPreferred , preferredToMessage map [string ]string , qualifiedFieldName string ) {
92101 if field == nil || len (field .Names ) == 0 {
93102 return
94103 }
95104
96105 markerSet := markersAccess .FieldMarkers (field )
97106 check (markerSet , equivalentToPreferred , func (marks []markers.Marker , preferredIdentifier string , preferredExists bool ) {
98- reportMarkers (pass , marks , preferredIdentifier , qualifiedFieldName , field .Pos (), "field" , preferredExists )
107+ reportMarkers (pass , marks , preferredIdentifier , preferredToMessage [ preferredIdentifier ], qualifiedFieldName , field .Pos (), "field" , preferredExists )
99108 })
100109}
101110
102111// checkType validates a single type definition for marker usage.
103- func checkType (pass * analysis.Pass , typeSpec * ast.TypeSpec , markersAccess markers.Markers , equivalentToPreferred map [string ]string ) {
112+ func checkType (pass * analysis.Pass , typeSpec * ast.TypeSpec , markersAccess markers.Markers , equivalentToPreferred , preferredToMessage map [string ]string ) {
104113 if typeSpec == nil {
105114 return
106115 }
107116
108117 markerSet := markersAccess .TypeMarkers (typeSpec )
109118 check (markerSet , equivalentToPreferred , func (marks []markers.Marker , preferredIdentifier string , preferredExists bool ) {
110- reportMarkers (pass , marks , preferredIdentifier , typeSpec .Name .Name , typeSpec .Pos (), "type" , preferredExists )
119+ reportMarkers (pass , marks , preferredIdentifier , preferredToMessage [ preferredIdentifier ], typeSpec .Name .Name , typeSpec .Pos (), "type" , preferredExists )
111120 })
112121}
113122
@@ -193,7 +202,7 @@ func buildTextEdits(marks []markers.Marker, preferredIdentifier string, preferre
193202// reportMarkers generates a diagnostic report for markers that should be
194203// replaced. This function handles the common logic for both field and type
195204// reporting.
196- func reportMarkers (pass * analysis.Pass , marks []markers.Marker , preferredIdentifier , elementName string , pos token.Pos , elementType string , preferredExists bool ) {
205+ func reportMarkers (pass * analysis.Pass , marks []markers.Marker , preferredIdentifier , customMessage , elementName string , pos token.Pos , elementType string , preferredExists bool ) {
197206 if len (marks ) == 0 {
198207 return
199208 }
@@ -206,6 +215,10 @@ func reportMarkers(pass *analysis.Pass, marks []markers.Marker, preferredIdentif
206215 message := fmt .Sprintf ("%s %s uses %s %s, should use preferred marker %q instead" ,
207216 elementType , elementName , markerWord , formatMarkerList (marks ), preferredIdentifier )
208217
218+ if customMessage != "" {
219+ message += fmt .Sprintf (": %s" , customMessage )
220+ }
221+
209222 fixMessage := "remove equivalent markers"
210223 if ! preferredExists {
211224 fixMessage = fmt .Sprintf ("replace with %q" , preferredIdentifier )
0 commit comments