Skip to content

Commit 1baa9aa

Browse files
committed
feat: add iotamixing linter
1 parent 2691aac commit 1baa9aa

File tree

11 files changed

+184
-1
lines changed

11 files changed

+184
-1
lines changed

.golangci.next.reference.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ linters:
6868
- ineffassign
6969
- interfacebloat
7070
- intrange
71+
- iotamixing
7172
- ireturn
7273
- lll
7374
- loggercheck
@@ -184,6 +185,7 @@ linters:
184185
- ineffassign
185186
- interfacebloat
186187
- intrange
188+
- iotamixing
187189
- ireturn
188190
- lll
189191
- loggercheck
@@ -2032,6 +2034,11 @@ linters-settings:
20322034
# Default: 10
20332035
max: 5
20342036

2037+
iotamixing:
2038+
# Whether to report individual consts rather than just the const block.
2039+
# Default: false
2040+
report-individual: true
2041+
20352042
ireturn:
20362043
# List of interfaces to allow.
20372044
# Lists of the keywords and regular expressions matched to interface or package names can be used.

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
module github.com/golangci/golangci-lint
22

3-
go 1.23.0
3+
go 1.23.3
4+
5+
toolchain go1.23.11
46

57
require (
68
4d63.com/gocheckcompilerdirectives v1.3.0
79
4d63.com/gochecknoglobals v0.2.2
810
github.com/4meepo/tagalign v1.4.2
911
github.com/Abirdcfly/dupword v0.1.3
12+
github.com/AdminBenni/iota-mixing v0.0.5
1013
github.com/Antonboom/errname v1.0.0
1114
github.com/Antonboom/nilnil v1.0.1
1215
github.com/Antonboom/testifylint v1.5.2

go.sum

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jsonschema/golangci.next.jsonschema.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@
387387
"ineffassign",
388388
"interfacebloat",
389389
"intrange",
390+
"iotamixing",
390391
"ireturn",
391392
"lll",
392393
"loggercheck",
@@ -2084,6 +2085,17 @@
20842085
}
20852086
}
20862087
},
2088+
"iotamixing": {
2089+
"type": "object",
2090+
"additionalProperties": false,
2091+
"properties": {
2092+
"report-individual": {
2093+
"description": "Whether to report individual consts rather than just the const block.",
2094+
"type": "boolean",
2095+
"default": false
2096+
}
2097+
}
2098+
},
20872099
"ireturn": {
20882100
"type": "object",
20892101
"additionalProperties": false,

pkg/config/linters_settings.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ type LintersSettings struct {
255255
ImportAs ImportAsSettings
256256
Inamedparam INamedParamSettings
257257
InterfaceBloat InterfaceBloatSettings
258+
IotaMixing IotaMixingSettings
258259
Ireturn IreturnSettings
259260
Lll LllSettings
260261
LoggerCheck LoggerCheckSettings
@@ -704,6 +705,10 @@ type InterfaceBloatSettings struct {
704705
Max int `mapstructure:"max"`
705706
}
706707

708+
type IotaMixingSettings struct {
709+
ReportIndividual bool `mapstructure:"report-individual"`
710+
}
711+
707712
type IreturnSettings struct {
708713
Allow []string `mapstructure:"allow"`
709714
Reject []string `mapstructure:"reject"`
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package iotamixing
2+
3+
import (
4+
"golang.org/x/tools/go/analysis"
5+
6+
"github.com/AdminBenni/iota-mixing/pkg/analyzer"
7+
"github.com/AdminBenni/iota-mixing/pkg/analyzer/flags"
8+
9+
"github.com/golangci/golangci-lint/pkg/config"
10+
"github.com/golangci/golangci-lint/pkg/goanalysis"
11+
)
12+
13+
func New(settings *config.IotaMixingSettings) *goanalysis.Linter {
14+
a := analyzer.GetIotaMixingAnalyzer()
15+
16+
flags.SetupFlags(&a.Flags)
17+
18+
cfg := map[string]map[string]any{}
19+
if settings != nil {
20+
cfg[a.Name] = map[string]any{flags.ReportIndividualFlagName: settings.ReportIndividual}
21+
}
22+
23+
return goanalysis.NewLinter(
24+
a.Name,
25+
a.Doc,
26+
[]*analysis.Analyzer{a},
27+
cfg,
28+
).WithLoadMode(goanalysis.LoadModeSyntax)
29+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package iotamixing
2+
3+
import (
4+
"testing"
5+
6+
"github.com/golangci/golangci-lint/test/testshared/integration"
7+
)
8+
9+
func TestFromTestdata(t *testing.T) {
10+
integration.RunTestdata(t)
11+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//golangcitest:args -Eiotamixing
2+
//golangcitest:config_path testdata/iotamixing-report-individual.yml
3+
package testdata
4+
5+
import "fmt"
6+
7+
const (
8+
InvalidPerIndividualIotaDeclAboveAnything = "anything" // want "InvalidPerIndividualIotaDeclAboveAnything is a const with r-val in same const block as iota. keep iotas in separate const blocks"
9+
InvalidPerIndividualIotaDeclAboveNotZero = iota
10+
InvalidPerIndividualIotaDeclAboveNotOne
11+
InvalidPerIndividualIotaDeclAboveNotTwo
12+
)
13+
14+
const (
15+
InvalidPerIndividualIotaDeclBelowZero = iota
16+
InvalidPerIndividualIotaDeclBelowOne
17+
InvalidPerIndividualIotaDeclBelowTwo
18+
InvalidPerIndividualIotaDeclBelowAnything = "anything" // want "InvalidPerIndividualIotaDeclBelowAnything is a const with r-val in same const block as iota. keep iotas in separate const blocks"
19+
)
20+
21+
const (
22+
InvalidPerIndividualIotaDeclBetweenZero = iota
23+
InvalidPerIndividualIotaDeclBetweenOne
24+
InvalidPerIndividualIotaDeclBetweenAnything = "anything" // want "InvalidPerIndividualIotaDeclBetweenAnything is a const with r-val in same const block as iota. keep iotas in separate const blocks"
25+
InvalidPerIndividualIotaDeclBetweenNotTwo
26+
)
27+
28+
const (
29+
InvalidPerIndividualIotaDeclMultipleAbove = "above" // want "InvalidPerIndividualIotaDeclMultipleAbove is a const with r-val in same const block as iota. keep iotas in separate const blocks"
30+
InvalidPerIndividualIotaDeclMultipleNotZero = iota
31+
InvalidPerIndividualIotaDeclMultipleNotOne
32+
InvalidPerIndividualIotaDeclMultipleBetween = "between" // want "InvalidPerIndividualIotaDeclMultipleBetween is a const with r-val in same const block as iota. keep iotas in separate const blocks"
33+
InvalidPerIndividualIotaDeclMultipleNotTwo
34+
InvalidPerIndividualIotaDeclMultipleBelow = "below" // want "InvalidPerIndividualIotaDeclMultipleBelow is a const with r-val in same const block as iota. keep iotas in separate const blocks"
35+
)
36+
37+
const (
38+
ValidPerIndividualIotaZero = iota
39+
ValidPerIndividualIotaOne
40+
ValidPerIndividualIotaTwo
41+
)
42+
43+
const (
44+
ValidPerIndividualRegularSomething = "something"
45+
ValidPerIndividualRegularAnything = "anything"
46+
)
47+
48+
func _() {
49+
fmt.Println("using the std import so goland doesn't nuke it")
50+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
linters-settings:
2+
iotamixing:
3+
report-individual: true
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//golangcitest:args -Eiotamixing
2+
package testdata
3+
4+
import "fmt"
5+
6+
// iota mixing in const block containing an iota and r-val declared above.
7+
const ( // want "iota mixing. keep iotas in separate blocks to consts with r-val"
8+
InvalidPerBlockIotaDeclAboveAnything = "anything"
9+
InvalidPerBlockIotaDeclAboveNotZero = iota
10+
InvalidPerBlockIotaDeclAboveNotOne
11+
InvalidPerBlockIotaDeclAboveNotTwo
12+
)
13+
14+
// iota mixing in const block containing an iota and r-val declared below.
15+
const ( // want "iota mixing. keep iotas in separate blocks to consts with r-val"
16+
InvalidPerBlockIotaDeclBelowZero = iota
17+
InvalidPerBlockIotaDeclBelowOne
18+
InvalidPerBlockIotaDeclBelowTwo
19+
InvalidPerBlockIotaDeclBelowAnything = "anything"
20+
)
21+
22+
// iota mixing in const block containing an iota and r-val declared between consts.
23+
const ( // want "iota mixing. keep iotas in separate blocks to consts with r-val"
24+
InvalidPerBlockIotaDeclBetweenZero = iota
25+
InvalidPerBlockIotaDeclBetweenOne
26+
InvalidPerBlockIotaDeclBetweenAnything = "anything"
27+
InvalidPerBlockIotaDeclBetweenNotTwo
28+
)
29+
30+
// iota mixing in const block containing an iota and r-vals declared above, between, and below consts.
31+
const ( // want "iota mixing. keep iotas in separate blocks to consts with r-val"
32+
InvalidPerBlockIotaDeclMultipleAbove = "above"
33+
InvalidPerBlockIotaDeclMultipleNotZero = iota
34+
InvalidPerBlockIotaDeclMultipleNotOne
35+
InvalidPerBlockIotaDeclMultipleBetween = "between"
36+
InvalidPerBlockIotaDeclMultipleNotTwo
37+
InvalidPerBlockIotaDeclMultipleBelow = "below"
38+
)
39+
40+
// no iota mixing in a const block containing an iota and no r-vals.
41+
const (
42+
ValidPerBlockIotaZero = iota
43+
ValidPerBlockIotaOne
44+
ValidPerBlockIotaTwo
45+
)
46+
47+
// no iota mixing in a const block containing r-vals and no iota.
48+
const (
49+
ValidPerBlockRegularSomething = "something"
50+
ValidPerBlockRegularAnything = "anything"
51+
)
52+
53+
func _() {
54+
fmt.Println("using the std import so goland doesn't nuke it")
55+
}

0 commit comments

Comments
 (0)