aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/go-lintpack
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/go-lintpack')
-rw-r--r--vendor/github.com/go-lintpack/lintpack/.travis.yml7
-rw-r--r--vendor/github.com/go-lintpack/lintpack/LICENSE24
-rw-r--r--vendor/github.com/go-lintpack/lintpack/Makefile14
-rw-r--r--vendor/github.com/go-lintpack/lintpack/README.md32
-rw-r--r--vendor/github.com/go-lintpack/lintpack/astwalk/comment_walker.go41
-rw-r--r--vendor/github.com/go-lintpack/lintpack/astwalk/doc_comment_walker.go48
-rw-r--r--vendor/github.com/go-lintpack/lintpack/astwalk/expr_walker.go29
-rw-r--r--vendor/github.com/go-lintpack/lintpack/astwalk/func_decl_walker.go21
-rw-r--r--vendor/github.com/go-lintpack/lintpack/astwalk/local_comment_walker.go32
-rw-r--r--vendor/github.com/go-lintpack/lintpack/astwalk/local_def_visitor.go51
-rw-r--r--vendor/github.com/go-lintpack/lintpack/astwalk/local_def_walker.go118
-rw-r--r--vendor/github.com/go-lintpack/lintpack/astwalk/local_expr_walker.go27
-rw-r--r--vendor/github.com/go-lintpack/lintpack/astwalk/stmt_list_walker.go31
-rw-r--r--vendor/github.com/go-lintpack/lintpack/astwalk/stmt_walker.go27
-rw-r--r--vendor/github.com/go-lintpack/lintpack/astwalk/type_expr_walker.go114
-rw-r--r--vendor/github.com/go-lintpack/lintpack/astwalk/visitor.go80
-rw-r--r--vendor/github.com/go-lintpack/lintpack/astwalk/walk_handler.go34
-rw-r--r--vendor/github.com/go-lintpack/lintpack/astwalk/walker.go57
-rw-r--r--vendor/github.com/go-lintpack/lintpack/checkers_db.go135
-rw-r--r--vendor/github.com/go-lintpack/lintpack/context.go35
-rw-r--r--vendor/github.com/go-lintpack/lintpack/doc.go5
-rw-r--r--vendor/github.com/go-lintpack/lintpack/go.mod11
-rw-r--r--vendor/github.com/go-lintpack/lintpack/go.sum14
-rw-r--r--vendor/github.com/go-lintpack/lintpack/lintpack.go248
24 files changed, 1235 insertions, 0 deletions
diff --git a/vendor/github.com/go-lintpack/lintpack/.travis.yml b/vendor/github.com/go-lintpack/lintpack/.travis.yml
new file mode 100644
index 000000000..41a0cbac5
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/.travis.yml
@@ -0,0 +1,7 @@
+language: go
+go:
+ - 1.x
+install:
+ - # Prevent default install action "go get -t -v ./...".
+script:
+ - make ci
diff --git a/vendor/github.com/go-lintpack/lintpack/LICENSE b/vendor/github.com/go-lintpack/lintpack/LICENSE
new file mode 100644
index 000000000..de0abccdf
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2018, go-lintpack maintainers
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of Intel Corporation nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/go-lintpack/lintpack/Makefile b/vendor/github.com/go-lintpack/lintpack/Makefile
new file mode 100644
index 000000000..63f21d2f9
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/Makefile
@@ -0,0 +1,14 @@
+.PHONY: test ci
+
+%: # stubs to get makefile param for `test-checker` command
+ @: # see: https://stackoverflow.com/a/6273809/433041
+
+build:
+ go build cmd/lintpack/build.go cmd/lintpack/main.go
+
+test:
+ go test -v -count=1 ./...
+
+ci:
+ go get -t -v ./...
+ go test -v -count=1 ./...
diff --git a/vendor/github.com/go-lintpack/lintpack/README.md b/vendor/github.com/go-lintpack/lintpack/README.md
new file mode 100644
index 000000000..5702228eb
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/README.md
@@ -0,0 +1,32 @@
+[![Build Status][travis-image]][travis-url]
+[![Go Report Card][go-report-image]][go-report-url]
+
+[travis-image]: https://travis-ci.org/go-critic/go-critic.svg?branch=master
+[travis-url]: https://travis-ci.org/go-critic/go-critic
+[go-report-image]: https://goreportcard.com/badge/github.com/go-critic/go-critic
+[go-report-url]: https://goreportcard.com/report/github.com/go-critic/go-critic
+
+## Quick start / Installation / Usage
+
+Install `lintpack`:
+
+```bash
+go get -v -u github.com/go-lintpack/lintpack/...
+```
+
+Install checkers from [go-critic/checkers](https://github.com/go-critic/checkers):
+
+```bash
+# You'll need to have sources under your Go workspace first:
+go get -v -u github.com/go-critic/checkers
+# Now build a linter that includes all checks from that package:
+lintpack build -o gocritic github.com/go-critic/checkers
+# Executable gocritic is created and can be used as a standalone linter.
+```
+
+Produced binary includes basic help as well as supported checks documentation.
+
+So, the process is simple:
+
+* Get the `lintpack` linter builder
+* Build linter from checks implemented in different repos, by various vendors
diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/comment_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/comment_walker.go
new file mode 100644
index 000000000..6c60e3fed
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/astwalk/comment_walker.go
@@ -0,0 +1,41 @@
+package astwalk
+
+import (
+ "go/ast"
+ "strings"
+)
+
+type commentWalker struct {
+ visitor CommentVisitor
+}
+
+func (w *commentWalker) WalkFile(f *ast.File) {
+ if !w.visitor.EnterFile(f) {
+ return
+ }
+
+ for _, cg := range f.Comments {
+ visitCommentGroups(cg, w.visitor.VisitComment)
+ }
+}
+
+func visitCommentGroups(cg *ast.CommentGroup, visit func(*ast.CommentGroup)) {
+ var group []*ast.Comment
+ visitGroup := func(list []*ast.Comment) {
+ if len(list) == 0 {
+ return
+ }
+ cg := &ast.CommentGroup{List: list}
+ visit(cg)
+ }
+ for _, comment := range cg.List {
+ if strings.HasPrefix(comment.Text, "/*") {
+ visitGroup(group)
+ group = group[:0]
+ visitGroup([]*ast.Comment{comment})
+ } else {
+ group = append(group, comment)
+ }
+ }
+ visitGroup(group)
+}
diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/doc_comment_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/doc_comment_walker.go
new file mode 100644
index 000000000..39b536508
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/astwalk/doc_comment_walker.go
@@ -0,0 +1,48 @@
+package astwalk
+
+import (
+ "go/ast"
+)
+
+type docCommentWalker struct {
+ visitor DocCommentVisitor
+}
+
+func (w *docCommentWalker) WalkFile(f *ast.File) {
+ for _, decl := range f.Decls {
+ switch decl := decl.(type) {
+ case *ast.FuncDecl:
+ if decl.Doc != nil {
+ w.visitor.VisitDocComment(decl.Doc)
+ }
+ case *ast.GenDecl:
+ if decl.Doc != nil {
+ w.visitor.VisitDocComment(decl.Doc)
+ }
+ for _, spec := range decl.Specs {
+ switch spec := spec.(type) {
+ case *ast.ImportSpec:
+ if spec.Doc != nil {
+ w.visitor.VisitDocComment(spec.Doc)
+ }
+ case *ast.ValueSpec:
+ if spec.Doc != nil {
+ w.visitor.VisitDocComment(spec.Doc)
+ }
+ case *ast.TypeSpec:
+ if spec.Doc != nil {
+ w.visitor.VisitDocComment(spec.Doc)
+ }
+ ast.Inspect(spec.Type, func(n ast.Node) bool {
+ if n, ok := n.(*ast.Field); ok {
+ if n.Doc != nil {
+ w.visitor.VisitDocComment(n.Doc)
+ }
+ }
+ return true
+ })
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/expr_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/expr_walker.go
new file mode 100644
index 000000000..64098b2b7
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/astwalk/expr_walker.go
@@ -0,0 +1,29 @@
+package astwalk
+
+import "go/ast"
+
+type exprWalker struct {
+ visitor ExprVisitor
+}
+
+func (w *exprWalker) WalkFile(f *ast.File) {
+ if !w.visitor.EnterFile(f) {
+ return
+ }
+
+ for _, decl := range f.Decls {
+ if decl, ok := decl.(*ast.FuncDecl); ok {
+ if !w.visitor.EnterFunc(decl) {
+ continue
+ }
+ }
+
+ ast.Inspect(decl, func(x ast.Node) bool {
+ if x, ok := x.(ast.Expr); ok {
+ w.visitor.VisitExpr(x)
+ return !w.visitor.skipChilds()
+ }
+ return true
+ })
+ }
+}
diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/func_decl_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/func_decl_walker.go
new file mode 100644
index 000000000..90d921f6f
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/astwalk/func_decl_walker.go
@@ -0,0 +1,21 @@
+package astwalk
+
+import "go/ast"
+
+type funcDeclWalker struct {
+ visitor FuncDeclVisitor
+}
+
+func (w *funcDeclWalker) WalkFile(f *ast.File) {
+ if !w.visitor.EnterFile(f) {
+ return
+ }
+
+ for _, decl := range f.Decls {
+ decl, ok := decl.(*ast.FuncDecl)
+ if !ok || !w.visitor.EnterFunc(decl) {
+ continue
+ }
+ w.visitor.VisitFuncDecl(decl)
+ }
+}
diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/local_comment_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/local_comment_walker.go
new file mode 100644
index 000000000..e042f0d5e
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/astwalk/local_comment_walker.go
@@ -0,0 +1,32 @@
+package astwalk
+
+import (
+ "go/ast"
+)
+
+type localCommentWalker struct {
+ visitor LocalCommentVisitor
+}
+
+func (w *localCommentWalker) WalkFile(f *ast.File) {
+ if !w.visitor.EnterFile(f) {
+ return
+ }
+
+ for _, decl := range f.Decls {
+ decl, ok := decl.(*ast.FuncDecl)
+ if !ok || !w.visitor.EnterFunc(decl) {
+ continue
+ }
+
+ for _, cg := range f.Comments {
+ // Not sure that decls/comments are sorted
+ // by positions, so do a naive full scan for now.
+ if cg.Pos() < decl.Pos() || cg.Pos() > decl.End() {
+ continue
+ }
+
+ visitCommentGroups(cg, w.visitor.VisitLocalComment)
+ }
+ }
+}
diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/local_def_visitor.go b/vendor/github.com/go-lintpack/lintpack/astwalk/local_def_visitor.go
new file mode 100644
index 000000000..bed0f44ab
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/astwalk/local_def_visitor.go
@@ -0,0 +1,51 @@
+package astwalk
+
+import (
+ "go/ast"
+)
+
+// LocalDefVisitor visits every name definitions inside a function.
+//
+// Next elements are considered as name definitions:
+// - Function parameters (input, output, receiver)
+// - Every LHS of ":=" assignment that defines a new name
+// - Every local var/const declaration.
+//
+// NOTE: this visitor is experimental.
+// This is also why it lives in a separate file.
+type LocalDefVisitor interface {
+ walkerEvents
+ VisitLocalDef(Name, ast.Expr)
+}
+
+type (
+ // NameKind describes what kind of name Name object holds.
+ NameKind int
+
+ // Name holds ver/const/param definition symbol info.
+ Name struct {
+ ID *ast.Ident
+ Kind NameKind
+
+ // Index is NameVar-specific field that is used to
+ // specify nth tuple element being assigned to the name.
+ Index int
+ }
+)
+
+// NOTE: set of name kinds is not stable and may change over time.
+//
+// TODO(quasilyte): is NameRecv/NameParam/NameResult granularity desired?
+// TODO(quasilyte): is NameVar/NameBind (var vs :=) granularity desired?
+const (
+ // NameParam is function/method receiver/input/output name.
+ // Initializing expression is always nil.
+ NameParam NameKind = iota
+ // NameVar is var or ":=" declared name.
+ // Initizlizing expression may be nil for var-declared names
+ // without explicit initializing expression.
+ NameVar
+ // NameConst is const-declared name.
+ // Initializing expression is never nil.
+ NameConst
+)
diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/local_def_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/local_def_walker.go
new file mode 100644
index 000000000..f6808cbb4
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/astwalk/local_def_walker.go
@@ -0,0 +1,118 @@
+package astwalk
+
+import (
+ "go/ast"
+ "go/token"
+ "go/types"
+)
+
+type localDefWalker struct {
+ visitor LocalDefVisitor
+ info *types.Info
+}
+
+func (w *localDefWalker) WalkFile(f *ast.File) {
+ for _, decl := range f.Decls {
+ decl, ok := decl.(*ast.FuncDecl)
+ if !ok || !w.visitor.EnterFunc(decl) {
+ continue
+ }
+ w.walkFunc(decl)
+ }
+}
+
+func (w *localDefWalker) walkFunc(decl *ast.FuncDecl) {
+ w.walkSignature(decl)
+ w.walkFuncBody(decl)
+}
+
+func (w *localDefWalker) walkFuncBody(decl *ast.FuncDecl) {
+ ast.Inspect(decl.Body, func(x ast.Node) bool {
+ switch x := x.(type) {
+ case *ast.AssignStmt:
+ if x.Tok != token.DEFINE {
+ return false
+ }
+ if len(x.Lhs) != len(x.Rhs) {
+ // Multi-value assignment.
+ // Invariant: there is only 1 RHS.
+ for i, lhs := range x.Lhs {
+ id, ok := lhs.(*ast.Ident)
+ if !ok || w.info.Defs[id] == nil {
+ continue
+ }
+ def := Name{ID: id, Kind: NameVar, Index: i}
+ w.visitor.VisitLocalDef(def, x.Rhs[0])
+ }
+ } else {
+ // Simple 1-1 assignments.
+ for i, lhs := range x.Lhs {
+ id, ok := lhs.(*ast.Ident)
+ if !ok || w.info.Defs[id] == nil {
+ continue
+ }
+ def := Name{ID: id, Kind: NameVar}
+ w.visitor.VisitLocalDef(def, x.Rhs[i])
+ }
+ }
+ return false
+
+ case *ast.GenDecl:
+ // Decls always introduce new names.
+ for _, spec := range x.Specs {
+ spec, ok := spec.(*ast.ValueSpec)
+ if !ok { // Ignore type/import specs
+ return false
+ }
+ switch {
+ case len(spec.Values) == 0:
+ // var-specific decls without explicit init.
+ for _, id := range spec.Names {
+ def := Name{ID: id, Kind: NameVar}
+ w.visitor.VisitLocalDef(def, nil)
+ }
+ case len(spec.Names) != len(spec.Values):
+ // var-specific decls that assign tuple results.
+ for i, id := range spec.Names {
+ def := Name{ID: id, Kind: NameVar, Index: i}
+ w.visitor.VisitLocalDef(def, spec.Values[0])
+ }
+ default:
+ // Can be either var or const decl.
+ kind := NameVar
+ if x.Tok == token.CONST {
+ kind = NameConst
+ }
+ for i, id := range spec.Names {
+ def := Name{ID: id, Kind: kind}
+ w.visitor.VisitLocalDef(def, spec.Values[i])
+ }
+ }
+ }
+ return false
+ }
+
+ return true
+ })
+}
+
+func (w *localDefWalker) walkSignature(decl *ast.FuncDecl) {
+ for _, p := range decl.Type.Params.List {
+ for _, id := range p.Names {
+ def := Name{ID: id, Kind: NameParam}
+ w.visitor.VisitLocalDef(def, nil)
+ }
+ }
+ if decl.Type.Results != nil {
+ for _, p := range decl.Type.Results.List {
+ for _, id := range p.Names {
+ def := Name{ID: id, Kind: NameParam}
+ w.visitor.VisitLocalDef(def, nil)
+ }
+ }
+ }
+ if decl.Recv != nil && len(decl.Recv.List[0].Names) != 0 {
+ def := Name{ID: decl.Recv.List[0].Names[0], Kind: NameParam}
+ w.visitor.VisitLocalDef(def, nil)
+ }
+}
diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/local_expr_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/local_expr_walker.go
new file mode 100644
index 000000000..951fd97e5
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/astwalk/local_expr_walker.go
@@ -0,0 +1,27 @@
+package astwalk
+
+import "go/ast"
+
+type localExprWalker struct {
+ visitor LocalExprVisitor
+}
+
+func (w *localExprWalker) WalkFile(f *ast.File) {
+ if !w.visitor.EnterFile(f) {
+ return
+ }
+
+ for _, decl := range f.Decls {
+ decl, ok := decl.(*ast.FuncDecl)
+ if !ok || !w.visitor.EnterFunc(decl) {
+ continue
+ }
+ ast.Inspect(decl.Body, func(x ast.Node) bool {
+ if x, ok := x.(ast.Expr); ok {
+ w.visitor.VisitLocalExpr(x)
+ return !w.visitor.skipChilds()
+ }
+ return true
+ })
+ }
+}
diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/stmt_list_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/stmt_list_walker.go
new file mode 100644
index 000000000..1cc0493a4
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/astwalk/stmt_list_walker.go
@@ -0,0 +1,31 @@
+package astwalk
+
+import "go/ast"
+
+type stmtListWalker struct {
+ visitor StmtListVisitor
+}
+
+func (w *stmtListWalker) WalkFile(f *ast.File) {
+ if !w.visitor.EnterFile(f) {
+ return
+ }
+
+ for _, decl := range f.Decls {
+ decl, ok := decl.(*ast.FuncDecl)
+ if !ok || !w.visitor.EnterFunc(decl) {
+ continue
+ }
+ ast.Inspect(decl.Body, func(x ast.Node) bool {
+ switch x := x.(type) {
+ case *ast.BlockStmt:
+ w.visitor.VisitStmtList(x.List)
+ case *ast.CaseClause:
+ w.visitor.VisitStmtList(x.Body)
+ case *ast.CommClause:
+ w.visitor.VisitStmtList(x.Body)
+ }
+ return !w.visitor.skipChilds()
+ })
+ }
+}
diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/stmt_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/stmt_walker.go
new file mode 100644
index 000000000..722eeb116
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/astwalk/stmt_walker.go
@@ -0,0 +1,27 @@
+package astwalk
+
+import "go/ast"
+
+type stmtWalker struct {
+ visitor StmtVisitor
+}
+
+func (w *stmtWalker) WalkFile(f *ast.File) {
+ if !w.visitor.EnterFile(f) {
+ return
+ }
+
+ for _, decl := range f.Decls {
+ decl, ok := decl.(*ast.FuncDecl)
+ if !ok || !w.visitor.EnterFunc(decl) {
+ continue
+ }
+ ast.Inspect(decl.Body, func(x ast.Node) bool {
+ if x, ok := x.(ast.Stmt); ok {
+ w.visitor.VisitStmt(x)
+ return !w.visitor.skipChilds()
+ }
+ return true
+ })
+ }
+}
diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/type_expr_walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/type_expr_walker.go
new file mode 100644
index 000000000..24c150084
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/astwalk/type_expr_walker.go
@@ -0,0 +1,114 @@
+package astwalk
+
+import (
+ "go/ast"
+ "go/token"
+ "go/types"
+
+ "github.com/go-toolsmith/astp"
+ "github.com/go-toolsmith/typep"
+)
+
+type typeExprWalker struct {
+ visitor TypeExprVisitor
+ info *types.Info
+}
+
+func (w *typeExprWalker) WalkFile(f *ast.File) {
+ if !w.visitor.EnterFile(f) {
+ return
+ }
+
+ for _, decl := range f.Decls {
+ if decl, ok := decl.(*ast.FuncDecl); ok {
+ if !w.visitor.EnterFunc(decl) {
+ continue
+ }
+ }
+ switch decl := decl.(type) {
+ case *ast.FuncDecl:
+ if !w.visitor.EnterFunc(decl) {
+ continue
+ }
+ w.walkSignature(decl.Type)
+ ast.Inspect(decl.Body, w.walk)
+ case *ast.GenDecl:
+ if decl.Tok == token.IMPORT {
+ continue
+ }
+ ast.Inspect(decl, w.walk)
+ }
+ }
+}
+
+func (w *typeExprWalker) visit(x ast.Expr) bool {
+ w.visitor.VisitTypeExpr(x)
+ return !w.visitor.skipChilds()
+}
+
+func (w *typeExprWalker) walk(x ast.Node) bool {
+ switch x := x.(type) {
+ case *ast.ParenExpr:
+ if typep.IsTypeExpr(w.info, x.X) {
+ return w.visit(x)
+ }
+ return true
+ case *ast.CallExpr:
+ // Pointer conversions require parenthesis around pointer type.
+ // These casts are represented as call expressions.
+ // Because it's impossible for the visitor to distinguish such
+ // "required" parenthesis, walker skips outmost parenthesis in such cases.
+ return w.inspectInner(x.Fun)
+ case *ast.SelectorExpr:
+ // Like with conversions, method expressions are another special.
+ return w.inspectInner(x.X)
+ case *ast.StarExpr:
+ if typep.IsTypeExpr(w.info, x.X) {
+ return w.visit(x)
+ }
+ return true
+ case *ast.MapType:
+ return w.visit(x)
+ case *ast.FuncType:
+ return w.visit(x)
+ case *ast.StructType:
+ return w.visit(x)
+ case *ast.InterfaceType:
+ if !w.visit(x) {
+ return false
+ }
+ for _, method := range x.Methods.List {
+ switch x := method.Type.(type) {
+ case *ast.FuncType:
+ w.walkSignature(x)
+ default:
+ // Embedded interface.
+ w.walk(x)
+ }
+ }
+ return false
+ case *ast.ArrayType:
+ return w.visit(x)
+ }
+ return true
+}
+
+func (w *typeExprWalker) inspectInner(x ast.Expr) bool {
+ parens, ok := x.(*ast.ParenExpr)
+ if ok && typep.IsTypeExpr(w.info, parens.X) && astp.IsStarExpr(parens.X) {
+ ast.Inspect(parens.X, w.walk)
+ return false
+ }
+ return true
+}
+
+func (w *typeExprWalker) walkSignature(typ *ast.FuncType) {
+ for _, p := range typ.Params.List {
+ ast.Inspect(p.Type, w.walk)
+ }
+ if typ.Results != nil {
+ for _, p := range typ.Results.List {
+ ast.Inspect(p.Type, w.walk)
+ }
+ }
+}
diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/visitor.go b/vendor/github.com/go-lintpack/lintpack/astwalk/visitor.go
new file mode 100644
index 000000000..9f973a2b3
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/astwalk/visitor.go
@@ -0,0 +1,80 @@
+package astwalk
+
+import (
+ "go/ast"
+)
+
+// Visitor interfaces.
+type (
+ // DocCommentVisitor visits every doc-comment.
+ // Does not visit doc-comments for function-local definitions (types, etc).
+ // Also does not visit package doc-comment (file-level doc-comments).
+ DocCommentVisitor interface {
+ VisitDocComment(*ast.CommentGroup)
+ }
+
+ // FuncDeclVisitor visits every top-level function declaration.
+ FuncDeclVisitor interface {
+ walkerEvents
+ VisitFuncDecl(*ast.FuncDecl)
+ }
+
+ // ExprVisitor visits every expression inside AST file.
+ ExprVisitor interface {
+ walkerEvents
+ VisitExpr(ast.Expr)
+ }
+
+ // LocalExprVisitor visits every expression inside function body.
+ LocalExprVisitor interface {
+ walkerEvents
+ VisitLocalExpr(ast.Expr)
+ }
+
+ // StmtListVisitor visits every statement list inside function body.
+ // This includes block statement bodies as well as implicit blocks
+ // introduced by case clauses and alike.
+ StmtListVisitor interface {
+ walkerEvents
+ VisitStmtList([]ast.Stmt)
+ }
+
+ // StmtVisitor visits every statement inside function body.
+ StmtVisitor interface {
+ walkerEvents
+ VisitStmt(ast.Stmt)
+ }
+
+ // TypeExprVisitor visits every type describing expression.
+ // It also traverses struct types and interface types to run
+ // checker over their fields/method signatures.
+ TypeExprVisitor interface {
+ walkerEvents
+ VisitTypeExpr(ast.Expr)
+ }
+
+ // LocalCommentVisitor visits every comment inside function body.
+ LocalCommentVisitor interface {
+ walkerEvents
+ VisitLocalComment(*ast.CommentGroup)
+ }
+
+ // CommentVisitor visits every comment.
+ CommentVisitor interface {
+ walkerEvents
+ VisitComment(*ast.CommentGroup)
+ }
+)
+
+// walkerEvents describes common hooks available for most visitor types.
+type walkerEvents interface {
+ // EnterFile is called for every file that is about to be traversed.
+ // If false is returned, file is not visited.
+ EnterFile(*ast.File) bool
+
+ // EnterFunc is called for every function declaration that is about
+ // to be traversed. If false is returned, function is not visited.
+ EnterFunc(*ast.FuncDecl) bool
+
+ skipChilds() bool
+}
diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/walk_handler.go b/vendor/github.com/go-lintpack/lintpack/astwalk/walk_handler.go
new file mode 100644
index 000000000..1f6e948d5
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/astwalk/walk_handler.go
@@ -0,0 +1,34 @@
+package astwalk
+
+import (
+ "go/ast"
+)
+
+// WalkHandler is a type to be embedded into every checker
+// that uses astwalk walkers.
+type WalkHandler struct {
+ // SkipChilds controls whether currently analyzed
+ // node childs should be traversed.
+ //
+ // Value is reset after each visitor invocation,
+ // so there is no need to set value back to false.
+ SkipChilds bool
+}
+
+// EnterFile is a default walkerEvents.EnterFile implementation
+// that reports every file as accepted candidate for checking.
+func (w *WalkHandler) EnterFile(f *ast.File) bool {
+ return true
+}
+
+// EnterFunc is a default walkerEvents.EnterFunc implementation
+// that skips extern function (ones that do not have body).
+func (w *WalkHandler) EnterFunc(decl *ast.FuncDecl) bool {
+ return decl.Body != nil
+}
+
+func (w *WalkHandler) skipChilds() bool {
+ v := w.SkipChilds
+ w.SkipChilds = false
+ return v
+}
diff --git a/vendor/github.com/go-lintpack/lintpack/astwalk/walker.go b/vendor/github.com/go-lintpack/lintpack/astwalk/walker.go
new file mode 100644
index 000000000..fddae710a
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/astwalk/walker.go
@@ -0,0 +1,57 @@
+package astwalk
+
+import (
+ "go/types"
+
+ "github.com/go-lintpack/lintpack"
+)
+
+// WalkerForFuncDecl returns file walker implementation for FuncDeclVisitor.
+func WalkerForFuncDecl(v FuncDeclVisitor) lintpack.FileWalker {
+ return &funcDeclWalker{visitor: v}
+}
+
+// WalkerForExpr returns file walker implementation for ExprVisitor.
+func WalkerForExpr(v ExprVisitor) lintpack.FileWalker {
+ return &exprWalker{visitor: v}
+}
+
+// WalkerForLocalExpr returns file walker implementation for LocalExprVisitor.
+func WalkerForLocalExpr(v LocalExprVisitor) lintpack.FileWalker {
+ return &localExprWalker{visitor: v}
+}
+
+// WalkerForStmtList returns file walker implementation for StmtListVisitor.
+func WalkerForStmtList(v StmtListVisitor) lintpack.FileWalker {
+ return &stmtListWalker{visitor: v}
+}
+
+// WalkerForStmt returns file walker implementation for StmtVisitor.
+func WalkerForStmt(v StmtVisitor) lintpack.FileWalker {
+ return &stmtWalker{visitor: v}
+}
+
+// WalkerForTypeExpr returns file walker implementation for TypeExprVisitor.
+func WalkerForTypeExpr(v TypeExprVisitor, info *types.Info) lintpack.FileWalker {
+ return &typeExprWalker{visitor: v, info: info}
+}
+
+// WalkerForLocalComment returns file walker implementation for LocalCommentVisitor.
+func WalkerForLocalComment(v LocalCommentVisitor) lintpack.FileWalker {
+ return &localCommentWalker{visitor: v}
+}
+
+// WalkerForComment returns file walker implementation for CommentVisitor.
+func WalkerForComment(v CommentVisitor) lintpack.FileWalker {
+ return &commentWalker{visitor: v}
+}
+
+// WalkerForDocComment returns file walker implementation for DocCommentVisitor.
+func WalkerForDocComment(v DocCommentVisitor) lintpack.FileWalker {
+ return &docCommentWalker{visitor: v}
+}
+
+// WalkerForLocalDef returns file walker implementation for LocalDefVisitor.
+func WalkerForLocalDef(v LocalDefVisitor, info *types.Info) lintpack.FileWalker {
+ return &localDefWalker{visitor: v, info: info}
+}
diff --git a/vendor/github.com/go-lintpack/lintpack/checkers_db.go b/vendor/github.com/go-lintpack/lintpack/checkers_db.go
new file mode 100644
index 000000000..83d41b4e4
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/checkers_db.go
@@ -0,0 +1,135 @@
+package lintpack
+
+import (
+ "fmt"
+ "regexp"
+ "sort"
+ "strings"
+
+ "github.com/go-toolsmith/astfmt"
+)
+
+type checkerProto struct {
+ info *CheckerInfo
+ constructor func(*Context) *Checker
+}
+
+// prototypes is a set of registered checkers that are not yet instantiated.
+// Registration should be done with AddChecker function.
+// Initialized checkers can be obtained with NewChecker function.
+var prototypes = make(map[string]checkerProto)
+
+func getCheckersInfo() []*CheckerInfo {
+ infoList := make([]*CheckerInfo, 0, len(prototypes))
+ for _, proto := range prototypes {
+ infoCopy := *proto.info
+ infoList = append(infoList, &infoCopy)
+ }
+ sort.Slice(infoList, func(i, j int) bool {
+ return infoList[i].Name < infoList[j].Name
+ })
+ return infoList
+}
+
+func addChecker(info *CheckerInfo, constructor func(*CheckerContext) FileWalker) {
+ if _, ok := prototypes[info.Name]; ok {
+ panic(fmt.Sprintf("checker with name %q already registered", info.Name))
+ }
+
+ // Validate param value type.
+ for pname, param := range info.Params {
+ switch param.Value.(type) {
+ case string, int, bool:
+ // OK.
+ default:
+ panic(fmt.Sprintf("unsupported %q param type value: %T",
+ pname, param.Value))
+ }
+ }
+
+ trimDocumentation := func(info *CheckerInfo) {
+ fields := []*string{
+ &info.Summary,
+ &info.Details,
+ &info.Before,
+ &info.After,
+ &info.Note,
+ }
+ for _, f := range fields {
+ *f = strings.TrimSpace(*f)
+ }
+ }
+
+ trimDocumentation(info)
+
+ if err := validateCheckerInfo(info); err != nil {
+ panic(err)
+ }
+
+ proto := checkerProto{
+ info: info,
+ constructor: func(ctx *Context) *Checker {
+ var c Checker
+ c.Info = info
+ c.ctx = CheckerContext{
+ Context: ctx,
+ printer: astfmt.NewPrinter(ctx.FileSet),
+ }
+ c.fileWalker = constructor(&c.ctx)
+ return &c
+ },
+ }
+
+ prototypes[info.Name] = proto
+}
+
+func newChecker(ctx *Context, info *CheckerInfo) *Checker {
+ proto, ok := prototypes[info.Name]
+ if !ok {
+ panic(fmt.Sprintf("checker with name %q not registered", info.Name))
+ }
+ return proto.constructor(ctx)
+}
+
+func validateCheckerInfo(info *CheckerInfo) error {
+ steps := []func(*CheckerInfo) error{
+ validateCheckerName,
+ validateCheckerDocumentation,
+ validateCheckerTags,
+ }
+
+ for _, step := range steps {
+ if err := step(info); err != nil {
+ return fmt.Errorf("%q validation error: %v", info.Name, err)
+ }
+ }
+ return nil
+}
+
+var validIdentRE = regexp.MustCompile(`^\w+$`)
+
+func validateCheckerName(info *CheckerInfo) error {
+ if !validIdentRE.MatchString(info.Name) {
+ return fmt.Errorf("checker name contains illegal chars")
+ }
+ return nil
+}
+
+func validateCheckerDocumentation(info *CheckerInfo) error {
+ // TODO(Quasilyte): validate documentation.
+ return nil
+}
+
+func validateCheckerTags(info *CheckerInfo) error {
+ tagSet := make(map[string]bool)
+ for _, tag := range info.Tags {
+ if tagSet[tag] {
+ return fmt.Errorf("duplicated tag %q", tag)
+ }
+ if !validIdentRE.MatchString(tag) {
+ return fmt.Errorf("checker tag %q contains illegal chars", tag)
+ }
+ tagSet[tag] = true
+ }
+ return nil
+}
diff --git a/vendor/github.com/go-lintpack/lintpack/context.go b/vendor/github.com/go-lintpack/lintpack/context.go
new file mode 100644
index 000000000..8671e175c
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/context.go
@@ -0,0 +1,35 @@
+package lintpack
+
+import (
+ "go/ast"
+ "go/types"
+ "strconv"
+)
+
+func resolvePkgObjects(ctx *Context, f *ast.File) {
+ ctx.PkgObjects = make(map[*types.PkgName]string, len(f.Imports))
+
+ for _, spec := range f.Imports {
+ if spec.Name != nil {
+ obj := ctx.TypesInfo.ObjectOf(spec.Name)
+ ctx.PkgObjects[obj.(*types.PkgName)] = spec.Name.Name
+ } else {
+ obj := ctx.TypesInfo.Implicits[spec]
+ ctx.PkgObjects[obj.(*types.PkgName)] = obj.Name()
+ }
+ }
+}
+
+func resolvePkgRenames(ctx *Context, f *ast.File) {
+ ctx.PkgRenames = make(map[string]string)
+
+ for _, spec := range f.Imports {
+ if spec.Name != nil {
+ path, err := strconv.Unquote(spec.Path.Value)
+ if err != nil {
+ panic(err)
+ }
+ ctx.PkgRenames[path] = spec.Name.Name
+ }
+ }
+}
diff --git a/vendor/github.com/go-lintpack/lintpack/doc.go b/vendor/github.com/go-lintpack/lintpack/doc.go
new file mode 100644
index 000000000..4aba342f5
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/doc.go
@@ -0,0 +1,5 @@
+// Package lintpack provides shared API between the linter and its checkers.
+//
+// Linter is usually implemented by creating instances of registered checkers.
+// Checkers are registered by the AddChecker call.
+package lintpack
diff --git a/vendor/github.com/go-lintpack/lintpack/go.mod b/vendor/github.com/go-lintpack/lintpack/go.mod
new file mode 100644
index 000000000..b2e4cd984
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/go.mod
@@ -0,0 +1,11 @@
+module github.com/go-lintpack/lintpack
+
+require (
+ github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6
+ github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086
+ github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30
+ github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8
+ github.com/google/go-cmp v0.2.0
+ github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e
+ golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09
+)
diff --git a/vendor/github.com/go-lintpack/lintpack/go.sum b/vendor/github.com/go-lintpack/lintpack/go.sum
new file mode 100644
index 000000000..bd9f5dcb9
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/go.sum
@@ -0,0 +1,14 @@
+github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6 h1:aTBUNRTatDDU24gbOEKEoLiDwxtc98ga6K/iMTm6fvs=
+github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY=
+github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086 h1:EIMuvbE9fbtQtimdLe5yeXjuC5CeKbQt8zH6GwtIrhM=
+github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg=
+github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30 h1:zRJPftZJNLPDiOtvYbFRwjSbaJAcVOf80TeEmWGe2kQ=
+github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk=
+github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8 h1:vVouagbdmqTVlCIAxpyYsNNTbkKZ3V66VpKOLU/s6W4=
+github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks=
+github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e h1:9MlwzLdW7QSDrhDjFlsEYmxpFyIoXmYRon3dt0io31k=
+github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
+golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09 h1:QJFxMApN9XdBRwtqXfOidB2azUCA4ziuiMTrQ1uBGxw=
+golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
diff --git a/vendor/github.com/go-lintpack/lintpack/lintpack.go b/vendor/github.com/go-lintpack/lintpack/lintpack.go
new file mode 100644
index 000000000..28c3a6354
--- /dev/null
+++ b/vendor/github.com/go-lintpack/lintpack/lintpack.go
@@ -0,0 +1,248 @@
+package lintpack
+
+import (
+ "fmt"
+ "go/ast"
+ "go/token"
+ "go/types"
+
+ "github.com/go-toolsmith/astfmt"
+)
+
+// CheckerCollection provides additional information for a group of checkers.
+type CheckerCollection struct {
+ // URL is a link for a main source of information on the collection.
+ URL string
+}
+
+// AddChecker registers a new checker into a checkers pool.
+// Constructor is used to create a new checker instance.
+// Checker name (defined in CheckerInfo.Name) must be unique.
+//
+// CheckerInfo.Collection is automatically set to the coll (the receiver).
+//
+// If checker is never needed, for example if it is disabled,
+// constructor will not be called.
+func (coll *CheckerCollection) AddChecker(info *CheckerInfo, constructor func(*CheckerContext) FileWalker) {
+ if coll == nil {
+ panic(fmt.Sprintf("adding checker to a nil collection"))
+ }
+ info.Collection = coll
+ addChecker(info, constructor)
+}
+
+// CheckerParam describes a single checker customizable parameter.
+type CheckerParam struct {
+ // Value holds parameter bound value.
+ // It might be overwritten by the integrating linter.
+ //
+ // Permitted types include:
+ // - int
+ // - bool
+ // - string
+ Value interface{}
+
+ // Usage gives an overview about what parameter does.
+ Usage string
+}
+
+// CheckerParams holds all checker-specific parameters.
+//
+// Provides convenient access to the loosely typed underlying map.
+type CheckerParams map[string]*CheckerParam
+
+// Int lookups pname key in underlying map and type-asserts it to int.
+func (params CheckerParams) Int(pname string) int { return params[pname].Value.(int) }
+
+// Bool lookups pname key in underlying map and type-asserts it to bool.
+func (params CheckerParams) Bool(pname string) bool { return params[pname].Value.(bool) }
+
+// String lookups pname key in underlying map and type-asserts it to string.
+func (params CheckerParams) String(pname string) string { return params[pname].Value.(string) }
+
+// CheckerInfo holds checker metadata and structured documentation.
+type CheckerInfo struct {
+ // Name is a checker name.
+ Name string
+
+ // Tags is a list of labels that can be used to enable or disable checker.
+ // Common tags are "experimental" and "performance".
+ Tags []string
+
+ // Params declares checker-specific parameters. Optional.
+ Params CheckerParams
+
+ // Summary is a short one sentence description.
+ // Should not end with a period.
+ Summary string
+
+ // Details extends summary with additional info. Optional.
+ Details string
+
+ // Before is a code snippet of code that will violate rule.
+ Before string
+
+ // After is a code snippet of fixed code that complies to the rule.
+ After string
+
+ // Note is an optional caution message or advice.
+ Note string
+
+ // Collection establishes a checker-to-collection relationship.
+ Collection *CheckerCollection
+}
+
+// GetCheckersInfo returns a checkers info list for all registered checkers.
+// The slice is sorted by a checker name.
+//
+// Info objects can be used to instantiate checkers with NewChecker function.
+func GetCheckersInfo() []*CheckerInfo {
+ return getCheckersInfo()
+}
+
+// HasTag reports whether checker described by the info has specified tag.
+func (info *CheckerInfo) HasTag(tag string) bool {
+ for i := range info.Tags {
+ if info.Tags[i] == tag {
+ return true
+ }
+ }
+ return false
+}
+
+// Checker is an implementation of a check that is described by the associated info.
+type Checker struct {
+ // Info is an info object that was used to instantiate this checker.
+ Info *CheckerInfo
+
+ ctx CheckerContext
+
+ fileWalker FileWalker
+}
+
+// Check runs rule checker over file f.
+func (c *Checker) Check(f *ast.File) []Warning {
+ c.ctx.warnings = c.ctx.warnings[:0]
+ c.fileWalker.WalkFile(f)
+ return c.ctx.warnings
+}
+
+// Warning represents issue that is found by checker.
+type Warning struct {
+ // Node is an AST node that caused warning to trigger.
+ // Can be used to obtain proper error location.
+ Node ast.Node
+
+ // Text is warning message without source location info.
+ Text string
+}
+
+// NewChecker returns initialized checker identified by an info.
+// info must be non-nil.
+// Panics if info describes a checker that was not properly registered.
+func NewChecker(ctx *Context, info *CheckerInfo) *Checker {
+ return newChecker(ctx, info)
+}
+
+// Context is a readonly state shared among every checker.
+type Context struct {
+ // TypesInfo carries parsed packages types information.
+ TypesInfo *types.Info
+
+ // SizesInfo carries alignment and type size information.
+ // Arch-dependent.
+ SizesInfo types.Sizes
+
+ // FileSet is a file set that was used during the program loading.
+ FileSet *token.FileSet
+
+ // Pkg describes package that is being checked.
+ Pkg *types.Package
+
+ // Filename is a currently checked file name.
+ Filename string
+
+ // Require records what optional resources are required
+ // by the checkers set that use this context.
+ //
+ // Every require fields makes associated context field
+ // to be properly initialized.
+ // For example, Context.require.PkgObjects => Context.PkgObjects.
+ Require struct {
+ PkgObjects bool
+ PkgRenames bool
+ }
+
+ // PkgObjects stores all imported packages and their local names.
+ PkgObjects map[*types.PkgName]string
+
+ // PkgRenames maps package path to its local renaming.
+ // Contains no entries for packages that were imported without
+ // explicit local names.
+ PkgRenames map[string]string
+}
+
+// NewContext returns new shared context to be used by every checker.
+//
+// All data carried by the context is readonly for checkers,
+// but can be modified by the integrating application.
+func NewContext(fset *token.FileSet, sizes types.Sizes) *Context {
+ return &Context{
+ FileSet: fset,
+ SizesInfo: sizes,
+ TypesInfo: &types.Info{},
+ }
+}
+
+// SetPackageInfo sets package-related metadata.
+//
+// Must be called for every package being checked.
+func (c *Context) SetPackageInfo(info *types.Info, pkg *types.Package) {
+ if info != nil {
+ // We do this kind of assignment to avoid
+ // changing c.typesInfo field address after
+ // every re-assignment.
+ *c.TypesInfo = *info
+ }
+ c.Pkg = pkg
+}
+
+// SetFileInfo sets file-related metadata.
+//
+// Must be called for every source code file being checked.
+func (c *Context) SetFileInfo(name string, f *ast.File) {
+ c.Filename = name
+ if c.Require.PkgObjects {
+ resolvePkgObjects(c, f)
+ }
+ if c.Require.PkgRenames {
+ resolvePkgRenames(c, f)
+ }
+}
+
+// CheckerContext is checker-local context copy.
+// Fields that are not from Context itself are writeable.
+type CheckerContext struct {
+ *Context
+
+ // printer used to format warning text.
+ printer *astfmt.Printer
+
+ warnings []Warning
+}
+
+// Warn adds a Warning to checker output.
+func (ctx *CheckerContext) Warn(node ast.Node, format string, args ...interface{}) {
+ ctx.warnings = append(ctx.warnings, Warning{
+ Text: ctx.printer.Sprintf(format, args...),
+ Node: node,
+ })
+}
+
+// FileWalker is an interface every checker should implement.
+//
+// The WalkFile method is executed for every Go file inside the
+// package that is being checked.
+type FileWalker interface {
+ WalkFile(*ast.File)
+}