Skip to content

Commit

Permalink
all: integrate lintpack as internal framework (#937)
Browse files Browse the repository at this point in the history
Instead of using a lintpack as a dependency, clone
most of its code that we need.

This is an intermediate step to make transition to
go/analysis easier. Now we don't need to keep
lintpack dependency in sync and can make
framework/linter compatible with go/analysis later.

Doing a v0.5.0 release is suggested.

Updates #854

Signed-off-by: Iskander Sharipov <quasilyte@gmail.com>
  • Loading branch information
quasilyte committed Jun 15, 2020
1 parent e76e5c0 commit 94678bc
Show file tree
Hide file tree
Showing 105 changed files with 2,159 additions and 392 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Expand Up @@ -3,7 +3,7 @@
*.dll
*.so
*.dylib
gocritic
/gocritic

pkg/

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Expand Up @@ -87,7 +87,7 @@ you'll find all answers there in a short time.

3. Define checker type and constructor function inside a new file under `checkers/${checkerName}_checker.go`.

4. Define a `lintpack.CheckerInfo` within an `init()` function in your new file. Specify the checker `Name`, `Summary`, `Before`, and `After` fields. It's a good idea to also specify appropriate `Tags` (e.g. `"diagnostic"`, `"style"`, `"performace"`, `"opinionated"`); new checkers should generally include the `"experimental"` tag.
4. Define a `linter.CheckerInfo` within an `init()` function in your new file. Specify the checker `Name`, `Summary`, `Before`, and `After` fields. It's a good idea to also specify appropriate `Tags` (e.g. `"diagnostic"`, `"style"`, `"performace"`, `"opinionated"`); new checkers should generally include the `"experimental"` tag.

5. Register the checker by calling `AddChecker` function in `init()`, passing in the `CheckerInfo`.

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -40,7 +40,7 @@ cover:
goveralls -package github.com/go-critic/go-critic/checkers -coverprofile=coverage.out -service travis-ci -repotoken ${COVERALLS_TOKEN}

gocritic:
lintpack build -o gocritic -linter.version='v0.4.3' -linter.name='gocritic' github.com/go-critic/go-critic/checkers
go build -o gocritic ./cmd/gocritic

install:
go install ./cmd/gocritic
22 changes: 5 additions & 17 deletions README.md
Expand Up @@ -34,28 +34,16 @@ The latest documentation is available at [go-critic.github.io](https://go-critic

For most users, using `go-critic` under [golangci-lint](https://github.com/golangci/golangci-lint) is enough.

Instructions below describe how to install "bare" `go-critic`.
Precompiled `go-critic` binaries can be found at [releases](https://github.com/go-critic/go-critic/releases) page.

If you don't have [lintpack](https://github.com/go-lintpack/lintpack) installed, do:
Instructions below show how to build `go-critic` from sources.

```bash
go get -v github.com/go-lintpack/lintpack/...
GO111MODULE=on go get -v -u github.com/go-critic/go-critic/cmd/gocritic
```

Get `go-critic` checkers:

```bash
go get -v github.com/go-critic/go-critic/...
```

After that, you can create `gocritic` binary by running:

```bash
cd $(go env GOPATH)/src/github.com/go-critic/go-critic &&
make gocritic
```

> Windows note: `lintpack build` might emit a warning. See https://github.com/go-critic/go-critic/issues/760.
If the command above does not work, you can try cloning this repository
under your `GOPATH` and run `make gocritic`.

## Usage

Expand Down
8 changes: 4 additions & 4 deletions checkers/appendAssign_checker.go
Expand Up @@ -5,15 +5,15 @@ import (
"go/token"
"go/types"

"github.com/go-lintpack/lintpack"
"github.com/go-critic/go-critic/checkers/internal/astwalk"
"github.com/go-critic/go-critic/framework/linter"
"github.com/go-toolsmith/astequal"
"github.com/go-toolsmith/astp"
"golang.org/x/tools/go/ast/astutil"
)

func init() {
var info lintpack.CheckerInfo
var info linter.CheckerInfo
info.Name = "appendAssign"
info.Tags = []string{"diagnostic"}
info.Summary = "Detects suspicious append result assignments"
Expand All @@ -24,14 +24,14 @@ p.negatives = append(p.negatives, y)`
p.positives = append(p.positives, x)
p.negatives = append(p.negatives, y)`

collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker {
collection.AddChecker(&info, func(ctx *linter.CheckerContext) linter.FileWalker {
return astwalk.WalkerForStmt(&appendAssignChecker{ctx: ctx})
})
}

type appendAssignChecker struct {
astwalk.WalkHandler
ctx *lintpack.CheckerContext
ctx *linter.CheckerContext
}

func (c *appendAssignChecker) VisitStmt(stmt ast.Stmt) {
Expand Down
8 changes: 4 additions & 4 deletions checkers/appendCombine_checker.go
Expand Up @@ -4,14 +4,14 @@ import (
"go/ast"
"go/token"

"github.com/go-lintpack/lintpack"
"github.com/go-critic/go-critic/checkers/internal/astwalk"
"github.com/go-critic/go-critic/framework/linter"
"github.com/go-toolsmith/astcast"
"github.com/go-toolsmith/astequal"
)

func init() {
var info lintpack.CheckerInfo
var info linter.CheckerInfo
info.Name = "appendCombine"
info.Tags = []string{"performance"}
info.Summary = "Detects `append` chains to the same slice that can be done in a single `append` call"
Expand All @@ -20,14 +20,14 @@ xs = append(xs, 1)
xs = append(xs, 2)`
info.After = `xs = append(xs, 1, 2)`

collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker {
collection.AddChecker(&info, func(ctx *linter.CheckerContext) linter.FileWalker {
return astwalk.WalkerForStmtList(&appendCombineChecker{ctx: ctx})
})
}

type appendCombineChecker struct {
astwalk.WalkHandler
ctx *lintpack.CheckerContext
ctx *linter.CheckerContext
}

func (c *appendCombineChecker) VisitStmtList(list []ast.Stmt) {
Expand Down
8 changes: 4 additions & 4 deletions checkers/argOrder_checker.go
Expand Up @@ -4,30 +4,30 @@ import (
"go/ast"
"go/types"

"github.com/go-lintpack/lintpack"
"github.com/go-critic/go-critic/checkers/internal/astwalk"
"github.com/go-critic/go-critic/framework/linter"
"github.com/go-toolsmith/astcast"
"github.com/go-toolsmith/astcopy"
"github.com/go-toolsmith/astp"
"github.com/go-toolsmith/typep"
)

func init() {
var info lintpack.CheckerInfo
var info linter.CheckerInfo
info.Name = "argOrder"
info.Tags = []string{"diagnostic", "experimental"}
info.Summary = "Detects suspicious arguments order"
info.Before = `strings.HasPrefix("#", userpass)`
info.After = `strings.HasPrefix(userpass, "#")`

collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker {
collection.AddChecker(&info, func(ctx *linter.CheckerContext) linter.FileWalker {
return astwalk.WalkerForExpr(&argOrderChecker{ctx: ctx})
})
}

type argOrderChecker struct {
astwalk.WalkHandler
ctx *lintpack.CheckerContext
ctx *linter.CheckerContext
}

func (c *argOrderChecker) VisitExpr(expr ast.Expr) {
Expand Down
8 changes: 4 additions & 4 deletions checkers/assignOp_checker.go
Expand Up @@ -4,29 +4,29 @@ import (
"go/ast"
"go/token"

"github.com/go-lintpack/lintpack"
"github.com/go-critic/go-critic/checkers/internal/astwalk"
"github.com/go-critic/go-critic/framework/linter"
"github.com/go-toolsmith/astcopy"
"github.com/go-toolsmith/astequal"
"github.com/go-toolsmith/typep"
)

func init() {
var info lintpack.CheckerInfo
var info linter.CheckerInfo
info.Name = "assignOp"
info.Tags = []string{"style"}
info.Summary = "Detects assignments that can be simplified by using assignment operators"
info.Before = `x = x * 2`
info.After = `x *= 2`

collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker {
collection.AddChecker(&info, func(ctx *linter.CheckerContext) linter.FileWalker {
return astwalk.WalkerForStmt(&assignOpChecker{ctx: ctx})
})
}

type assignOpChecker struct {
astwalk.WalkHandler
ctx *lintpack.CheckerContext
ctx *linter.CheckerContext
}

func (c *assignOpChecker) VisitStmt(stmt ast.Stmt) {
Expand Down
8 changes: 4 additions & 4 deletions checkers/badCall_checker.go
Expand Up @@ -3,28 +3,28 @@ package checkers
import (
"go/ast"

"github.com/go-lintpack/lintpack"
"github.com/go-critic/go-critic/checkers/internal/astwalk"
"github.com/go-critic/go-critic/framework/linter"
"github.com/go-toolsmith/astcast"
"github.com/go-toolsmith/astcopy"
)

func init() {
var info lintpack.CheckerInfo
var info linter.CheckerInfo
info.Name = "badCall"
info.Tags = []string{"diagnostic", "experimental"}
info.Summary = "Detects suspicious function calls"
info.Before = `strings.Replace(s, from, to, 0)`
info.After = `strings.Replace(s, from, to, -1)`

collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker {
collection.AddChecker(&info, func(ctx *linter.CheckerContext) linter.FileWalker {
return astwalk.WalkerForExpr(&badCallChecker{ctx: ctx})
})
}

type badCallChecker struct {
astwalk.WalkHandler
ctx *lintpack.CheckerContext
ctx *linter.CheckerContext
}

func (c *badCallChecker) VisitExpr(expr ast.Expr) {
Expand Down
10 changes: 5 additions & 5 deletions checkers/badCond_checker.go
Expand Up @@ -5,9 +5,9 @@ import (
"go/constant"
"go/token"

"github.com/go-critic/go-critic/checkers/internal/lintutil"
"github.com/go-lintpack/lintpack"
"github.com/go-critic/go-critic/checkers/internal/astwalk"
"github.com/go-critic/go-critic/checkers/internal/lintutil"
"github.com/go-critic/go-critic/framework/linter"
"github.com/go-toolsmith/astcast"
"github.com/go-toolsmith/astcopy"
"github.com/go-toolsmith/astequal"
Expand All @@ -16,7 +16,7 @@ import (
)

func init() {
var info lintpack.CheckerInfo
var info linter.CheckerInfo
info.Name = "badCond"
info.Tags = []string{"diagnostic", "experimental"}
info.Summary = "Detects suspicious condition expressions"
Expand All @@ -29,14 +29,14 @@ for i := 0; i < n; i++ {
xs[i] = 0
}`

collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker {
collection.AddChecker(&info, func(ctx *linter.CheckerContext) linter.FileWalker {
return astwalk.WalkerForFuncDecl(&badCondChecker{ctx: ctx})
})
}

type badCondChecker struct {
astwalk.WalkHandler
ctx *lintpack.CheckerContext
ctx *linter.CheckerContext
}

func (c *badCondChecker) VisitFuncDecl(decl *ast.FuncDecl) {
Expand Down
8 changes: 4 additions & 4 deletions checkers/badRegexp_checker.go
Expand Up @@ -8,20 +8,20 @@ import (
"unicode"
"unicode/utf8"

"github.com/go-lintpack/lintpack"
"github.com/go-critic/go-critic/checkers/internal/astwalk"
"github.com/go-critic/go-critic/framework/linter"
"github.com/quasilyte/regex/syntax"
)

func init() {
var info lintpack.CheckerInfo
var info linter.CheckerInfo
info.Name = "badRegexp"
info.Tags = []string{"diagnostic", "experimental"}
info.Summary = "Detects suspicious regexp patterns"
info.Before = "regexp.MustCompile(`(?:^aa|bb|cc)foo[aba]`)"
info.After = "regexp.MustCompile(`^(?:aa|bb|cc)foo[ab]`)"

collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker {
collection.AddChecker(&info, func(ctx *linter.CheckerContext) linter.FileWalker {
opts := &syntax.ParserOptions{}
c := &badRegexpChecker{
ctx: ctx,
Expand All @@ -33,7 +33,7 @@ func init() {

type badRegexpChecker struct {
astwalk.WalkHandler
ctx *lintpack.CheckerContext
ctx *linter.CheckerContext

parser *syntax.Parser
cause ast.Expr
Expand Down
10 changes: 5 additions & 5 deletions checkers/boolExprSimplify_checker.go
Expand Up @@ -6,9 +6,9 @@ import (
"go/token"
"strconv"

"github.com/go-critic/go-critic/checkers/internal/lintutil"
"github.com/go-lintpack/lintpack"
"github.com/go-critic/go-critic/checkers/internal/astwalk"
"github.com/go-critic/go-critic/checkers/internal/lintutil"
"github.com/go-critic/go-critic/framework/linter"
"github.com/go-toolsmith/astcast"
"github.com/go-toolsmith/astcopy"
"github.com/go-toolsmith/astequal"
Expand All @@ -18,7 +18,7 @@ import (
)

func init() {
var info lintpack.CheckerInfo
var info linter.CheckerInfo
info.Name = "boolExprSimplify"
info.Tags = []string{"style", "experimental"}
info.Summary = "Detects bool expressions that can be simplified"
Expand All @@ -29,14 +29,14 @@ b := !(x) == !(y)`
a := elapsed < expectElapsedMin
b := (x) == (y)`

collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker {
collection.AddChecker(&info, func(ctx *linter.CheckerContext) linter.FileWalker {
return astwalk.WalkerForExpr(&boolExprSimplifyChecker{ctx: ctx})
})
}

type boolExprSimplifyChecker struct {
astwalk.WalkHandler
ctx *lintpack.CheckerContext
ctx *linter.CheckerContext
hasFloats bool
}

Expand Down
8 changes: 4 additions & 4 deletions checkers/builtinShadow_checker.go
Expand Up @@ -3,26 +3,26 @@ package checkers
import (
"go/ast"

"github.com/go-lintpack/lintpack"
"github.com/go-critic/go-critic/checkers/internal/astwalk"
"github.com/go-critic/go-critic/framework/linter"
)

func init() {
var info lintpack.CheckerInfo
var info linter.CheckerInfo
info.Name = "builtinShadow"
info.Tags = []string{"style", "opinionated"}
info.Summary = "Detects when predeclared identifiers shadowed in assignments"
info.Before = `len := 10`
info.After = `length := 10`

collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker {
collection.AddChecker(&info, func(ctx *linter.CheckerContext) linter.FileWalker {
return astwalk.WalkerForLocalDef(&builtinShadowChecker{ctx: ctx}, ctx.TypesInfo)
})
}

type builtinShadowChecker struct {
astwalk.WalkHandler
ctx *lintpack.CheckerContext
ctx *linter.CheckerContext
}

func (c *builtinShadowChecker) VisitLocalDef(name astwalk.Name, _ ast.Expr) {
Expand Down

0 comments on commit 94678bc

Please sign in to comment.