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
17 changes: 3 additions & 14 deletions pkg/linters/appendbytestring/appendbytestring.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,17 @@ import (
"go/ast"

"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"

"github.com/github/gh-aw/pkg/linters/internal/analyzerutil"
"github.com/github/gh-aw/pkg/linters/internal/astutil"
"github.com/github/gh-aw/pkg/linters/internal/filecheck"
"github.com/github/gh-aw/pkg/linters/internal/nolint"
)

// Analyzer is the append-byte-string analysis pass.
var Analyzer = &analysis.Analyzer{
Name: "appendbytestring",
Doc: "reports append(b, []byte(s)...) calls where s is a string that can be simplified to append(b, s...)",
URL: "https://github.com/github/gh-aw/tree/main/pkg/linters/appendbytestring",
Requires: []*analysis.Analyzer{inspect.Analyzer, nolint.Analyzer, filecheck.Analyzer},
Run: run,
}
var Analyzer = analyzerutil.New("appendbytestring", "reports append(b, []byte(s)...) calls where s is a string that can be simplified to append(b, s...)", run)

func run(pass *analysis.Pass) (any, error) {
insp, err := astutil.Inspector(pass)
if err != nil {
return nil, err
}
noLintIndex, err := nolint.Index(pass)
if err != nil {
return nil, err
Expand All @@ -39,10 +29,9 @@ func run(pass *analysis.Pass) (any, error) {
}

nodeFilter := []ast.Node{(*ast.CallExpr)(nil)}
insp.Preorder(nodeFilter, func(n ast.Node) {
return analyzerutil.Preorder(pass, nodeFilter, func(n ast.Node) {
analyzeAppendByteString(pass, n, generatedFiles, noLintIndex)
})
return nil, nil
}

// analyzeAppendByteString checks whether a call is an append(b, []byte(s)...)
Expand Down
17 changes: 3 additions & 14 deletions pkg/linters/appendoneelement/appendoneelement.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,17 @@ import (
"go/types"

"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"

"github.com/github/gh-aw/pkg/linters/internal/analyzerutil"
"github.com/github/gh-aw/pkg/linters/internal/astutil"
"github.com/github/gh-aw/pkg/linters/internal/filecheck"
"github.com/github/gh-aw/pkg/linters/internal/nolint"
)

// Analyzer is the append-one-element analysis pass.
var Analyzer = &analysis.Analyzer{
Name: "appendoneelement",
Doc: "reports append(s, []T{x}...) calls where a single-element slice literal is spread and can be simplified to append(s, x)",
URL: "https://github.com/github/gh-aw/tree/main/pkg/linters/appendoneelement",
Requires: []*analysis.Analyzer{inspect.Analyzer, nolint.Analyzer, filecheck.Analyzer},
Run: run,
}
var Analyzer = analyzerutil.New("appendoneelement", "reports append(s, []T{x}...) calls where a single-element slice literal is spread and can be simplified to append(s, x)", run)

func run(pass *analysis.Pass) (any, error) {
insp, err := astutil.Inspector(pass)
if err != nil {
return nil, err
}
noLintIndex, err := nolint.Index(pass)
if err != nil {
return nil, err
Expand All @@ -40,10 +30,9 @@ func run(pass *analysis.Pass) (any, error) {
}

nodeFilter := []ast.Node{(*ast.CallExpr)(nil)}
insp.Preorder(nodeFilter, func(n ast.Node) {
return analyzerutil.Preorder(pass, nodeFilter, func(n ast.Node) {
analyzeAppendOneElement(pass, n, generatedFiles, noLintIndex)
})
return nil, nil
}

// analyzeAppendOneElement checks whether a call is an append(s, []T{x}...) that
Expand Down
17 changes: 3 additions & 14 deletions pkg/linters/bytesbufferstring/bytesbufferstring.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,17 @@ import (
"go/types"

"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"

"github.com/github/gh-aw/pkg/linters/internal/analyzerutil"
"github.com/github/gh-aw/pkg/linters/internal/astutil"
"github.com/github/gh-aw/pkg/linters/internal/filecheck"
"github.com/github/gh-aw/pkg/linters/internal/nolint"
)

// Analyzer is the bytes-buffer-string analysis pass.
var Analyzer = &analysis.Analyzer{
Name: "bytesbufferstring",
Doc: "reports string(buf.Bytes()) calls where buf is a bytes.Buffer value and suggests buf.String() instead",
URL: "https://github.com/github/gh-aw/tree/main/pkg/linters/bytesbufferstring",
Requires: []*analysis.Analyzer{inspect.Analyzer, nolint.Analyzer, filecheck.Analyzer},
Run: run,
}
var Analyzer = analyzerutil.New("bytesbufferstring", "reports string(buf.Bytes()) calls where buf is a bytes.Buffer value and suggests buf.String() instead", run)

func run(pass *analysis.Pass) (any, error) {
insp, err := astutil.Inspector(pass)
if err != nil {
return nil, err
}
noLintIndex, err := nolint.Index(pass)
if err != nil {
return nil, err
Expand All @@ -40,10 +30,9 @@ func run(pass *analysis.Pass) (any, error) {
}

nodeFilter := []ast.Node{(*ast.CallExpr)(nil)}
insp.Preorder(nodeFilter, func(n ast.Node) {
return analyzerutil.Preorder(pass, nodeFilter, func(n ast.Node) {
analyzeStringBytesCall(pass, n, generatedFiles, noLintIndex)
})
return nil, nil
}

// analyzeStringBytesCall checks whether a call is a string(buf.Bytes()) that
Expand Down
17 changes: 3 additions & 14 deletions pkg/linters/bytescomparestring/bytescomparestring.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
"go/types"

"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"

"github.com/github/gh-aw/pkg/linters/internal/analyzerutil"
"github.com/github/gh-aw/pkg/linters/internal/astutil"
"github.com/github/gh-aw/pkg/linters/internal/filecheck"
"github.com/github/gh-aw/pkg/linters/internal/nolint"
Expand All @@ -21,19 +21,9 @@ import (
const bytesPkg = "bytes"

// Analyzer is the bytes-compare-string analysis pass.
var Analyzer = &analysis.Analyzer{
Name: "bytescomparestring",
Doc: "flags string(a) == string(b) and string(a) != string(b) as []byte comparisons written the long way; use bytes.Equal for clearer intent",
URL: "https://github.com/github/gh-aw/tree/main/pkg/linters/bytescomparestring",
Requires: []*analysis.Analyzer{inspect.Analyzer, nolint.Analyzer, filecheck.Analyzer},
Run: run,
}
var Analyzer = analyzerutil.New("bytescomparestring", "flags string(a) == string(b) and string(a) != string(b) as []byte comparisons written the long way; use bytes.Equal for clearer intent", run)

func run(pass *analysis.Pass) (any, error) {
insp, err := astutil.Inspector(pass)
if err != nil {
return nil, err
}
noLintIndex, err := nolint.Index(pass)
if err != nil {
return nil, err
Expand All @@ -45,10 +35,9 @@ func run(pass *analysis.Pass) (any, error) {

seenImportFiles := make(map[token.Pos]bool)
nodeFilter := []ast.Node{(*ast.BinaryExpr)(nil)}
insp.Preorder(nodeFilter, func(n ast.Node) {
return analyzerutil.Preorder(pass, nodeFilter, func(n ast.Node) {
analyzeBinaryExpr(pass, n, generatedFiles, noLintIndex, seenImportFiles)
})
return nil, nil
}

// analyzeBinaryExpr checks whether a binary expression is a string(a) == string(b)
Expand Down
18 changes: 3 additions & 15 deletions pkg/linters/contextcancelnotdeferred/contextcancelnotdeferred.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (
"go/types"

"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"

"github.com/github/gh-aw/pkg/linters/internal/analyzerutil"
"github.com/github/gh-aw/pkg/linters/internal/astutil"
"github.com/github/gh-aw/pkg/linters/internal/filecheck"
"github.com/github/gh-aw/pkg/linters/internal/nolint"
Expand All @@ -19,21 +19,11 @@ import (
var pkgLog = logger.New("linters:contextcancelnotdeferred")

// Analyzer is the context-cancel-not-deferred analysis pass.
var Analyzer = &analysis.Analyzer{
Name: "contextcancelnotdeferred",
Doc: "reports context cancel functions that are called directly instead of deferred",
URL: "https://github.com/github/gh-aw/tree/main/pkg/linters/contextcancelnotdeferred",
Requires: []*analysis.Analyzer{inspect.Analyzer, nolint.Analyzer, filecheck.Analyzer},
Run: run,
}
var Analyzer = analyzerutil.New("contextcancelnotdeferred", "reports context cancel functions that are called directly instead of deferred", run)

func run(pass *analysis.Pass) (any, error) {
pkgLog.Printf("analyzing package %s", pass.Pkg.Path())

insp, err := astutil.Inspector(pass)
if err != nil {
return nil, err
}
noLintIndex, err := nolint.Index(pass)
if err != nil {
return nil, err
Expand All @@ -47,11 +37,9 @@ func run(pass *analysis.Pass) (any, error) {
(*ast.FuncDecl)(nil),
}

insp.Preorder(nodeFilter, func(n ast.Node) {
return analyzerutil.Preorder(pass, nodeFilter, func(n ast.Node) {
inspectCancelFuncDecl(pass, n, noLintIndex, generatedFiles)
})

return nil, nil
}

func inspectCancelFuncDecl(pass *analysis.Pass, n ast.Node, noLintIndex nolint.DirectiveIndex, generatedFiles filecheck.GeneratedIndex) {
Expand Down
10 changes: 2 additions & 8 deletions pkg/linters/ctxbackground/ctxbackground.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,15 @@ import (
"go/types"

"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"

"github.com/github/gh-aw/pkg/linters/internal/analyzerutil"
"github.com/github/gh-aw/pkg/linters/internal/astutil"
"github.com/github/gh-aw/pkg/linters/internal/filecheck"
"github.com/github/gh-aw/pkg/linters/internal/nolint"
)

// Analyzer is the ctx-background analysis pass.
var Analyzer = &analysis.Analyzer{
Name: "ctxbackground",
Doc: "reports calls to context.Background() inside functions that already receive a context.Context parameter",
URL: "https://github.com/github/gh-aw/tree/main/pkg/linters/ctxbackground",
Requires: []*analysis.Analyzer{inspect.Analyzer, nolint.Analyzer, filecheck.Analyzer},
Run: run,
}
var Analyzer = analyzerutil.New("ctxbackground", "reports calls to context.Background() inside functions that already receive a context.Context parameter", run)

func run(pass *analysis.Pass) (any, error) {
insp, err := astutil.Inspector(pass)
Expand Down
15 changes: 5 additions & 10 deletions pkg/linters/deferinloop/deferinloop.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
"go/ast"

"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/inspector"

"github.com/github/gh-aw/pkg/linters/internal/analyzerutil"
"github.com/github/gh-aw/pkg/linters/internal/astutil"
"github.com/github/gh-aw/pkg/linters/internal/filecheck"
"github.com/github/gh-aw/pkg/linters/internal/nolint"
Expand All @@ -21,21 +21,16 @@ import (
var pkgLog = logger.New("linters:deferinloop")

// Analyzer is the defer-in-loop analysis pass.
var Analyzer = &analysis.Analyzer{
Name: "deferinloop",
Doc: "reports defer statements enclosed anywhere within a for or range loop body; a function literal between a defer and an enclosing loop is treated as a new scope boundary, making the defer exempt; test files are not checked",
URL: "https://github.com/github/gh-aw/tree/main/pkg/linters/deferinloop",
Requires: []*analysis.Analyzer{inspect.Analyzer, nolint.Analyzer, filecheck.Analyzer},
Run: run,
}
var Analyzer = analyzerutil.New("deferinloop", "reports defer statements enclosed anywhere within a for or range loop body; a function literal between a defer and an enclosing loop is treated as a new scope boundary, making the defer exempt; test files are not checked", run)

func run(pass *analysis.Pass) (any, error) {
pkgLog.Printf("analyzing package %s", pass.Pkg.Path())

insp, err := astutil.Inspector(pass)
if err != nil {
return nil, err
}

pkgLog.Printf("analyzing package %s", pass.Pkg.Path())

noLintIndex, err := nolint.Index(pass)
if err != nil {
return nil, err
Expand Down
17 changes: 3 additions & 14 deletions pkg/linters/errorfwrapv/errorfwrapv.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
"strconv"

"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"

"github.com/github/gh-aw/pkg/linters/internal/analyzerutil"
"github.com/github/gh-aw/pkg/linters/internal/astutil"
"github.com/github/gh-aw/pkg/linters/internal/filecheck"
"github.com/github/gh-aw/pkg/linters/internal/nolint"
Expand Down Expand Up @@ -47,23 +47,13 @@ type formatVerb struct {
const formatArgOffset = 1

// Analyzer is the errorfwrapv analysis pass.
var Analyzer = &analysis.Analyzer{
Name: "errorfwrapv",
Doc: "reports fmt.Errorf calls that pass error arguments without %w wrapping",
URL: "https://github.com/github/gh-aw/tree/main/pkg/linters/errorfwrapv",
Requires: []*analysis.Analyzer{inspect.Analyzer, nolint.Analyzer, filecheck.Analyzer},
Run: run,
}
var Analyzer = analyzerutil.New("errorfwrapv", "reports fmt.Errorf calls that pass error arguments without %w wrapping", run)

func run(pass *analysis.Pass) (any, error) {
if errorIface == nil {
return nil, errors.New("failed to resolve built-in error interface from types.Universe")
}

insp, err := astutil.Inspector(pass)
if err != nil {
return nil, err
}
noLintIndex, err := nolint.Index(pass)
if err != nil {
return nil, err
Expand All @@ -74,10 +64,9 @@ func run(pass *analysis.Pass) (any, error) {
}

nodeFilter := []ast.Node{(*ast.CallExpr)(nil)}
insp.Preorder(nodeFilter, func(n ast.Node) {
return analyzerutil.Preorder(pass, nodeFilter, func(n ast.Node) {
analyzeFmtErrorfCall(pass, n, generatedFiles, noLintIndex)
})
return nil, nil
}

// analyzeFmtErrorfCall checks whether a call expression is a fmt.Errorf that
Expand Down
18 changes: 3 additions & 15 deletions pkg/linters/errormessage/errormessage.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (
"strings"

"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"

"github.com/github/gh-aw/pkg/linters/internal/analyzerutil"
"github.com/github/gh-aw/pkg/linters/internal/astutil"
"github.com/github/gh-aw/pkg/linters/internal/filecheck"
"github.com/github/gh-aw/pkg/linters/internal/nolint"
Expand All @@ -27,13 +27,7 @@ var (
)

// Analyzer is the errormessage analysis pass.
var Analyzer = &analysis.Analyzer{
Name: "errormessage",
Doc: "reports non-actionable error message patterns in changed files",
URL: "https://github.com/github/gh-aw/tree/main/pkg/linters/errormessage",
Requires: []*analysis.Analyzer{inspect.Analyzer, nolint.Analyzer, filecheck.Analyzer},
Run: run,
}
var Analyzer = analyzerutil.New("errormessage", "reports non-actionable error message patterns in changed files", run)

func init() {
Analyzer.Flags.StringVar(&changedFilesCSV, "changed-files", "", "comma-separated list of changed file paths to lint (when empty, analyzer is a no-op)")
Expand All @@ -47,10 +41,6 @@ func run(pass *analysis.Pass) (any, error) {
}
pkgLog.Printf("analyzing package %s (%d changed files)", pass.Pkg.Path(), len(changed))

insp, err := astutil.Inspector(pass)
if err != nil {
return nil, err
}
noLintIndex, err := nolint.Index(pass)
if err != nil {
return nil, err
Expand All @@ -61,7 +51,7 @@ func run(pass *analysis.Pass) (any, error) {
}

nodeFilter := []ast.Node{(*ast.CallExpr)(nil)}
insp.Preorder(nodeFilter, func(n ast.Node) {
return analyzerutil.Preorder(pass, nodeFilter, func(n ast.Node) {
call, ok := n.(*ast.CallExpr)
if !ok {
return
Expand All @@ -87,8 +77,6 @@ func run(pass *analysis.Pass) (any, error) {

checkNewValidationSuggestion(pass, call)
})

return nil, nil
}

func parseChangedFiles(csv string) map[string]struct{} {
Expand Down
Loading
Loading