diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 2d4c9e10e009..e93a772f67b5 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -2620,6 +2620,7 @@ linters: - funlen - gci - ginkgolinter + - gobreakselectinfor - gocheckcompilerdirectives - gochecknoglobals - gochecknoinits @@ -2735,6 +2736,7 @@ linters: - funlen - gci - ginkgolinter + - gobreakselectinfor - gocheckcompilerdirectives - gochecknoglobals - gochecknoinits diff --git a/go.mod b/go.mod index e5c83bc9d932..e1a830de76ef 100644 --- a/go.mod +++ b/go.mod @@ -86,6 +86,7 @@ require ( github.com/pelletier/go-toml/v2 v2.2.2 github.com/polyfloyd/go-errorlint v1.6.0 github.com/quasilyte/go-ruleguard/dsl v0.3.22 + github.com/rnben/go-break-select-in-for v0.1.0 github.com/ryancurrah/gomodguard v1.3.3 github.com/ryanrolds/sqlclosecheck v0.5.1 github.com/sanposhiho/wastedassign/v2 v2.0.7 diff --git a/go.sum b/go.sum index 8dce73dbff62..5c2e90ae5682 100644 --- a/go.sum +++ b/go.sum @@ -456,6 +456,8 @@ github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= +github.com/rnben/go-break-select-in-for v0.1.0 h1:MSykRlo7dtIpS1fta0eRoDGdvF2/7Zz15+S+nSSV85c= +github.com/rnben/go-break-select-in-for v0.1.0/go.mod h1:7JoY3ApLuYoE4iHy1U9X/v5ix10c/9Z54hpFoYhwmow= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 510740d61660..c5cde1c32332 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -324,6 +324,7 @@ "funlen", "gci", "ginkgolinter", + "gobreakselectinfor", "gocheckcompilerdirectives", "gochecknoglobals", "gochecknoinits", diff --git a/pkg/golinters/gobreakselectinfor/gobreakselectinfor.go b/pkg/golinters/gobreakselectinfor/gobreakselectinfor.go new file mode 100644 index 000000000000..3cc2706649ef --- /dev/null +++ b/pkg/golinters/gobreakselectinfor/gobreakselectinfor.go @@ -0,0 +1,19 @@ +package gobreakselectinfor + +import ( + "github.com/rnben/go-break-select-in-for/pkg/analyzer" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/goanalysis" +) + +func New() *goanalysis.Linter { + a := analyzer.Analyzer + + return goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + nil, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/pkg/golinters/gobreakselectinfor/gobreakselectinfor_test.go b/pkg/golinters/gobreakselectinfor/gobreakselectinfor_test.go new file mode 100644 index 000000000000..d1ae27b4c44d --- /dev/null +++ b/pkg/golinters/gobreakselectinfor/gobreakselectinfor_test.go @@ -0,0 +1,11 @@ +package gobreakselectinfor + +import ( + "testing" + + "github.com/golangci/golangci-lint/test/testshared/integration" +) + +func TestFromTestdata(t *testing.T) { + integration.RunTestdata(t) +} diff --git a/pkg/golinters/gobreakselectinfor/testdata/gobreakselectinfor.go b/pkg/golinters/gobreakselectinfor/testdata/gobreakselectinfor.go new file mode 100644 index 000000000000..a84cef5bf313 --- /dev/null +++ b/pkg/golinters/gobreakselectinfor/testdata/gobreakselectinfor.go @@ -0,0 +1,21 @@ +//golangcitest:args -Egobreakselectinfor +package testdata + +func bad(ch <-chan string) { + for { + select { + case <-ch: + break // want "break statement inside select statement inside for loop" + } + } +} + +func good(ch <-chan string) { +OUTER: + for { + select { + case <-ch: + break OUTER + } + } +} diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go index 3a46cbf88e5e..a3cf549b821f 100644 --- a/pkg/lint/lintersdb/builder_linter.go +++ b/pkg/lint/lintersdb/builder_linter.go @@ -33,6 +33,7 @@ import ( "github.com/golangci/golangci-lint/pkg/golinters/funlen" "github.com/golangci/golangci-lint/pkg/golinters/gci" "github.com/golangci/golangci-lint/pkg/golinters/ginkgolinter" + "github.com/golangci/golangci-lint/pkg/golinters/gobreakselectinfor" "github.com/golangci/golangci-lint/pkg/golinters/gocheckcompilerdirectives" "github.com/golangci/golangci-lint/pkg/golinters/gochecknoglobals" "github.com/golangci/golangci-lint/pkg/golinters/gochecknoinits" @@ -318,6 +319,12 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithPresets(linter.PresetStyle). WithURL("https://github.com/nunnatsa/ginkgolinter"), + linter.NewConfig(gobreakselectinfor.New()). + WithSince("1.61.0"). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/rnben/go-break-select-in-for"), + linter.NewConfig(gocheckcompilerdirectives.New()). WithSince("v1.51.0"). WithPresets(linter.PresetBugs).