Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
module github.com/mgechev/revive

go 1.20
go 1.21

require (
github.com/BurntSushi/toml v1.4.0
github.com/chavacava/garif v0.1.0
github.com/fatih/color v1.17.0
github.com/fatih/structtag v1.2.0
github.com/hashicorp/go-version v1.7.0
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517
github.com/mitchellh/go-homedir v1.1.0
github.com/olekukonko/tablewriter v0.0.5
Expand All @@ -19,6 +20,7 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/stretchr/testify v1.9.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.14.0 // indirect
)
27 changes: 4 additions & 23 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc=
github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
Expand All @@ -37,32 +35,15 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
53 changes: 51 additions & 2 deletions lint/linter.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@ package lint
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"go/token"
"os"
"os/exec"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync"

goversion "github.com/hashicorp/go-version"
)

// ReadFile defines an abstraction for reading files.
Expand Down Expand Up @@ -78,9 +84,19 @@ func (l *Linter) Lint(packages [][]string, ruleSet []Rule, config Config) (<-cha
}

func (l *Linter) lintPackage(filenames []string, ruleSet []Rule, config Config, failures chan Failure) error {
if len(filenames) == 0 {
return nil
}

goVersion, err := detectGoVersion(filepath.Dir(filenames[0]))
if err != nil {
return err
}

pkg := &Package{
fset: token.NewFileSet(),
files: map[string]*File{},
fset: token.NewFileSet(),
files: map[string]*File{},
goVersion: goVersion,
}
for _, filename := range filenames {
content, err := l.readFile(filename)
Expand Down Expand Up @@ -108,6 +124,39 @@ func (l *Linter) lintPackage(filenames []string, ruleSet []Rule, config Config,
return nil
}

func detectGoVersion(dir string) (ver *goversion.Version, err error) {
// https://github.com/golang/go/issues/44753#issuecomment-790089020
cmd := exec.Command("go", "list", "-m", "-json")
cmd.Dir = dir

raw, err := cmd.Output()
if err != nil {
return nil, fmt.Errorf("command go list: %w", err)
}

var v struct {
GoMod string `json:"GoMod"`
GoVersion string `json:"GoVersion"`
}
if err = json.Unmarshal(raw, &v); err != nil {
return nil, fmt.Errorf("can't parse the output of go list: %w", err)
}

if v.GoMod == "" {
// this package is outside a module, so assume
// an old-style source directory

if v := os.Getenv("GOVERSION"); v != "" {
return goversion.NewVersion(strings.TrimPrefix(v, "go"))
}

// assume the last version that does not have generics
return goversion.Must(goversion.NewVersion("1.17")), nil
}

return goversion.NewVersion(strings.TrimPrefix(v.GoVersion, "go"))
}

// isGenerated reports whether the source file is generated code
// according the rules from https://golang.org/s/generatedcode.
// This is inherited from the original go lint.
Expand Down
14 changes: 12 additions & 2 deletions lint/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ import (
"go/types"
"sync"

goversion "github.com/hashicorp/go-version"

"github.com/mgechev/revive/internal/typeparams"
)

// Package represents a package in the project.
type Package struct {
fset *token.FileSet
files map[string]*File
fset *token.FileSet
files map[string]*File
goVersion *goversion.Version

typesPkg *types.Package
typesInfo *types.Info
Expand All @@ -29,6 +32,8 @@ var (
trueValue = 1
falseValue = 2
notSet = 3

go122 = goversion.Must(goversion.NewVersion("1.22"))
)

// Files return package's files.
Expand Down Expand Up @@ -188,3 +193,8 @@ func (p *Package) lint(rules []Rule, config Config, failures chan Failure) {
}
wg.Wait()
}

// IsAtLeastGo122 returns true if the Go version for this package is 1.22 or higher, false otherwise
func (p *Package) IsAtLeastGo122() bool {
return p.goVersion.GreaterThanOrEqual(go122)
}
8 changes: 5 additions & 3 deletions rule/datarace.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func (*DataRaceRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
onFailure := func(failure lint.Failure) {
failures = append(failures, failure)
}
w := lintDataRaces{onFailure: onFailure}
w := lintDataRaces{onFailure: onFailure, go122for: file.Pkg.IsAtLeastGo122()}

ast.Walk(w, file.AST)

Expand All @@ -30,6 +30,7 @@ func (*DataRaceRule) Name() string {

type lintDataRaces struct {
onFailure func(failure lint.Failure)
go122for bool
}

func (w lintDataRaces) Visit(n ast.Node) ast.Visitor {
Expand All @@ -47,7 +48,7 @@ func (w lintDataRaces) Visit(n ast.Node) ast.Visitor {
if results != nil {
returnIDs = w.ExtractReturnIDs(results.List)
}
fl := &lintFunctionForDataRaces{onFailure: w.onFailure, returnIDs: returnIDs, rangeIDs: map[*ast.Object]struct{}{}}
fl := &lintFunctionForDataRaces{onFailure: w.onFailure, returnIDs: returnIDs, rangeIDs: map[*ast.Object]struct{}{}, go122for: w.go122for}
ast.Walk(fl, node.Body)

return nil
Expand All @@ -69,6 +70,7 @@ type lintFunctionForDataRaces struct {
onFailure func(failure lint.Failure)
returnIDs map[*ast.Object]struct{}
rangeIDs map[*ast.Object]struct{}
go122for bool
}

func (w lintFunctionForDataRaces) Visit(node ast.Node) ast.Visitor {
Expand Down Expand Up @@ -118,7 +120,7 @@ func (w lintFunctionForDataRaces) Visit(node ast.Node) ast.Visitor {
_, isReturnID := w.returnIDs[id.Obj]

switch {
case isRangeID:
case isRangeID && !w.go122for:
w.onFailure(lint.Failure{
Confidence: 1,
Node: id,
Expand Down
4 changes: 4 additions & 0 deletions rule/range-val-address.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ type RangeValAddress struct{}
func (*RangeValAddress) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
var failures []lint.Failure

if file.Pkg.IsAtLeastGo122() {
return failures
}

walker := rangeValAddress{
file: file,
onFailure: func(failure lint.Failure) {
Expand Down
4 changes: 4 additions & 0 deletions rule/range-val-in-closure.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ type RangeValInClosureRule struct{}
func (*RangeValInClosureRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
var failures []lint.Failure

if file.Pkg.IsAtLeastGo122() {
return failures
}

walker := rangeValInClosure{
onFailure: func(failure lint.Failure) {
failures = append(failures, failure)
Expand Down