Denis Isaev 7274db714c fix #479: update go-critic to fix deps
This update should fix go get issues because of deps.

go-critic:
$ git cherry -v c3db6069acc5
+ fe28ac328f474c02e2383ca2bf44a606929a7048 checkers: add integration
tests with cgo for dupImports (#846)
+ 48a15b03b630252319474ba5ddc8455d2aebf34f checkers: fix fold-ranges
for floats in boolExprSimplify (#849)
+ 7bf73388643eb226addf2d5ed8a2c104be244b2e checkers: fix "Output:"
false positive in commentedOutCode (#852)
+ f6f702b31734df26415c2bd135f272d1a34d2973 checkers: extend
yodaStyleExpr supported ops list (#856)
+ 07bf84df361735ad1d90f84e79eb60c8386325c7 fix dependencies (#857)
+ 1df30086654074503eab008bdde4f3ce1921128d checkers: fix collection
URL (#860)

x/tools:
$ git cherry -v 685fecacd0a0 521d6ed310dd | fgrep -v internal/lsp
+ fe54fb35175bb1c0c175e2335e23d7fa90ca987a apidiff: represent a Report as a list of Changes
+ 15bbd99efc6f20619676dec93f914d12e5139e83 all: run go mod tidy
+ bb3b3ca95aec36bfc4a5cb10b58022e64aca735b go/packages: add some documentation for extractPackage
+ 4bf14f7f0668366a4275c6ef5e99bd8e807da1d3 internal/span: fix off-by-one in ToUTF16Column
+ cb2dda6eabdf9160e66ca7293897f984154a7f8b go/packages: deduplicate file parsing
+ 9e44c1c403071e0c2831952513e7b948587d94af go/internal/gccgoimporter: update package to match std lib version
+ 36563e24a2627da92566d43aa1c7a2dd895fc60d cmd/vet: verify potentially-recursive Stringers are actually Stringers
+ 31fd60d6bfdcfb2861856aa5b333bb135f6bbfd8 x/tools/go/packages/packagestest: fix GOPROXY file URLs for Windows
+ 2d660fb8a000e1c288dc2f2150401b364922ebe9 go/packages/packagestest: fix GOPROXY file URLs for Windows
+ 7af746645d5165109de0b5cb499980c22812dfc2 internal/span: fix another off-by-one in ToUTF16Column
+ 9d4d845e86f14303813298ede731a971dd65b593 cmd/goimports: add -format-only flag
+ 83df196e5764ed2415c28c1f39ba6cb3db747da0 internal/span: add a filename only print for spans
+ 5cec639030af3a6ada2732d9bfa1d3731ed55106 go/analysis: proposed fact enumeration API
+ 9cb3dcf692a103de0fd68c26f4f04183e0933f7c internal/span: update the offset if the end offset should be valid but is not
+ 2d16b83fe98cd1bed9e2ce9fdc86bd438d14aab7 go/vcs: ignore "mod" VCS type
+ 95299016986435f846545c27f956768ad3c3cb2f lostcancel: do not analyze cancel variable which defined outside current function scope
+ 8a42e17289ea392d63892321ce1f40bd07efcc9f compilebench: clean up different benchmark types
+ eeb76a0c47a3b97e99f330dc14174ef14777d2ba compilebench: factor running build tool commands
+ 60140f09094406e46618ef436a26dd8394983503 compilebench: add a linker benchmark
+ e31d36578abb3d202c4007c3747bf8ebb7c51011 compilebench: handle missing MemStats more gracefully
+ d996b19ee77cd9c8df974510f23b0696cedf1ca1 go/analysis/analysistest: fix word usage
+ 73554e0f78058c37e5421bc48273a72400172221 go/analysis/passes: fix bugs discovered in std
+ 35884eef200b5fc81c9044f644a8d9d911262488 cmd/vet: print help to stdout only
+ 45e43b2cb4facd370abb846ebf35575161849f3b go/packages/packagestest: fix MustCopyFileTree so that file fragments are always slash form
+ d81a07b7e58487eed036bf115fa834653590d6cd go/analysis/passes/bools: eliminate quadratic runtime, output
+ 2a413a02cc735933997fa1b467a7b27bc1b82567 godoc/static: let client use vet check returned by /compile endpoint
+ 4789ca9922f080dd3a8fc3c74df1c1306db2bb0b go/analysis/internal/analysisflags: call gob.Register on deleted analyzers
+ d1a3278ee74994e9aa609e9e711c616bba677d5d godoc/util: serve SVG files raw
+ 1da8801a9502f29f3f03edfc3149b947e6e1913c godoc: declare small victory over the punched card tyranny
+ 757ca719ca9689950c69081c10c5300fbb8e35db imports: rename to internal/imports
+ 0133cac3176f225883c5d817146de8633ed07ebc cmd/goimports: reuse cached state
+ 26647e34d3c04fd3eaef6fb824493b00af7b1b26 imports: allow nil Options in Process
2019-06-10 11:33:31 +03:00

158 lines
3.7 KiB
Go

package checkers
import (
"fmt"
"go/ast"
"go/token"
"regexp"
"strings"
"github.com/go-lintpack/lintpack"
"github.com/go-lintpack/lintpack/astwalk"
"github.com/go-toolsmith/strparse"
)
func init() {
var info lintpack.CheckerInfo
info.Name = "commentedOutCode"
info.Tags = []string{"diagnostic", "experimental"}
info.Summary = "Detects commented-out code inside function bodies"
info.Before = `
// fmt.Println("Debugging hard")
foo(1, 2)`
info.After = `foo(1, 2)`
collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker {
return astwalk.WalkerForLocalComment(&commentedOutCodeChecker{
ctx: ctx,
notQuiteFuncCall: regexp.MustCompile(`\w+\s+\([^)]*\)\s*$`),
})
})
}
type commentedOutCodeChecker struct {
astwalk.WalkHandler
ctx *lintpack.CheckerContext
fn *ast.FuncDecl
notQuiteFuncCall *regexp.Regexp
}
func (c *commentedOutCodeChecker) EnterFunc(fn *ast.FuncDecl) bool {
c.fn = fn // Need to store current function inside checker context
return fn.Body != nil
}
func (c *commentedOutCodeChecker) VisitLocalComment(cg *ast.CommentGroup) {
s := cg.Text() // Collect text once
// We do multiple heuristics to avoid false positives.
// Many things can be improved here.
markers := []string{
"TODO", // TODO comments with code are permitted.
// "http://" is interpreted as a label with comment.
// There are other protocols we might want to include.
"http://",
"https://",
"e.g. ", // Clearly not a "selector expr" (mostly due to extra space)
}
for _, m := range markers {
if strings.Contains(s, m) {
return
}
}
// Some very short comment that can be skipped.
// Usually triggering on these results in false positive.
// Unless there is a very popular call like print/println.
cond := len(s) < len("quite too short") &&
!strings.Contains(s, "print") &&
!strings.Contains(s, "fmt.") &&
!strings.Contains(s, "log.")
if cond {
return
}
// Almost looks like a commented-out function call,
// but there is a whitespace between function name and
// parameters list. Skip these to avoid false positives.
if c.notQuiteFuncCall.MatchString(s) {
return
}
stmt := strparse.Stmt(s)
if c.isPermittedStmt(stmt) {
return
}
if stmt != strparse.BadStmt {
c.warn(cg)
return
}
// Don't try to parse one-liner as block statement
if len(cg.List) == 1 && !strings.Contains(s, "\n") {
return
}
// Some attempts to avoid false positives.
if c.skipBlock(s) {
return
}
// Add braces to make block statement from
// multiple statements.
stmt = strparse.Stmt(fmt.Sprintf("{ %s }", s))
if stmt, ok := stmt.(*ast.BlockStmt); ok && len(stmt.List) != 0 {
c.warn(cg)
}
}
func (c *commentedOutCodeChecker) skipBlock(s string) bool {
lines := strings.Split(s, "\n") // There is at least 1 line, that's invariant
// Special example test block.
if isExampleTestFunc(c.fn) && strings.Contains(lines[0], "Output:") {
return true
}
return false
}
func (c *commentedOutCodeChecker) isPermittedStmt(stmt ast.Stmt) bool {
switch stmt := stmt.(type) {
case *ast.ExprStmt:
return c.isPermittedExpr(stmt.X)
case *ast.LabeledStmt:
return c.isPermittedStmt(stmt.Stmt)
case *ast.DeclStmt:
decl := stmt.Decl.(*ast.GenDecl)
return decl.Tok == token.TYPE
default:
return false
}
}
func (c *commentedOutCodeChecker) isPermittedExpr(x ast.Expr) bool {
// Permit anything except expressions that can be used
// with complete result discarding.
switch x := x.(type) {
case *ast.CallExpr:
return false
case *ast.UnaryExpr:
// "<-" channel receive is not permitted.
return x.Op != token.ARROW
default:
return true
}
}
func (c *commentedOutCodeChecker) warn(cause ast.Node) {
c.ctx.Warn(cause, "may want to remove commented-out code")
}