forked from forgejo/forgejo
update revive lint to latest commit (#12921)
* update revive lint to latest commit * make fmt * change import
This commit is contained in:
parent
63e8bdaf73
commit
1c3278c2fa
154 changed files with 5965 additions and 8502 deletions
21
vendor/github.com/mgechev/revive/formatter/friendly.go
generated
vendored
21
vendor/github.com/mgechev/revive/formatter/friendly.go
generated
vendored
|
@ -10,11 +10,6 @@ import (
|
|||
"github.com/olekukonko/tablewriter"
|
||||
)
|
||||
|
||||
var (
|
||||
errorEmoji = color.RedString("✘")
|
||||
warningEmoji = color.YellowString("⚠")
|
||||
)
|
||||
|
||||
var newLines = map[rune]bool{
|
||||
0x000A: true,
|
||||
0x000B: true,
|
||||
|
@ -25,6 +20,14 @@ var newLines = map[rune]bool{
|
|||
0x2029: true,
|
||||
}
|
||||
|
||||
func getErrorEmoji() string {
|
||||
return color.RedString("✘")
|
||||
}
|
||||
|
||||
func getWarningEmoji() string {
|
||||
return color.YellowString("⚠")
|
||||
}
|
||||
|
||||
// Friendly is an implementation of the Formatter interface
|
||||
// which formats the errors to JSON.
|
||||
type Friendly struct {
|
||||
|
@ -68,9 +71,9 @@ func (f *Friendly) printFriendlyFailure(failure lint.Failure, severity lint.Seve
|
|||
}
|
||||
|
||||
func (f *Friendly) printHeaderRow(failure lint.Failure, severity lint.Severity) {
|
||||
emoji := warningEmoji
|
||||
emoji := getWarningEmoji()
|
||||
if severity == lint.SeverityError {
|
||||
emoji = errorEmoji
|
||||
emoji = getErrorEmoji()
|
||||
}
|
||||
fmt.Print(f.table([][]string{{emoji, "https://revive.run/r#" + failure.RuleName, color.GreenString(failure.Failure)}}))
|
||||
}
|
||||
|
@ -85,9 +88,9 @@ type statEntry struct {
|
|||
}
|
||||
|
||||
func (f *Friendly) printSummary(errors, warnings int) {
|
||||
emoji := warningEmoji
|
||||
emoji := getWarningEmoji()
|
||||
if errors > 0 {
|
||||
emoji = errorEmoji
|
||||
emoji = getErrorEmoji()
|
||||
}
|
||||
problemsLabel := "problems"
|
||||
if errors+warnings == 1 {
|
||||
|
|
4
vendor/github.com/mgechev/revive/rule/cognitive-complexity.go
generated
vendored
4
vendor/github.com/mgechev/revive/rule/cognitive-complexity.go
generated
vendored
|
@ -52,7 +52,7 @@ type cognitiveComplexityLinter struct {
|
|||
func (w cognitiveComplexityLinter) lint() {
|
||||
f := w.file
|
||||
for _, decl := range f.AST.Decls {
|
||||
if fn, ok := decl.(*ast.FuncDecl); ok {
|
||||
if fn, ok := decl.(*ast.FuncDecl); ok && fn.Body != nil {
|
||||
v := cognitiveComplexityVisitor{}
|
||||
c := v.subTreeComplexity(fn.Body)
|
||||
if c > w.maxComplexity {
|
||||
|
@ -109,7 +109,7 @@ func (v *cognitiveComplexityVisitor) Visit(n ast.Node) ast.Visitor {
|
|||
return nil // skip visiting binexp sub-tree (already visited by binExpComplexity)
|
||||
case *ast.BranchStmt:
|
||||
if n.Label != nil {
|
||||
v.complexity += 1
|
||||
v.complexity++
|
||||
}
|
||||
}
|
||||
// TODO handle (at least) direct recursion
|
||||
|
|
137
vendor/github.com/mgechev/revive/rule/defer.go
generated
vendored
Normal file
137
vendor/github.com/mgechev/revive/rule/defer.go
generated
vendored
Normal file
|
@ -0,0 +1,137 @@
|
|||
package rule
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
|
||||
"github.com/mgechev/revive/lint"
|
||||
)
|
||||
|
||||
// DeferRule lints unused params in functions.
|
||||
type DeferRule struct{}
|
||||
|
||||
// Apply applies the rule to given file.
|
||||
func (r *DeferRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
|
||||
allow := r.allowFromArgs(arguments)
|
||||
|
||||
var failures []lint.Failure
|
||||
onFailure := func(failure lint.Failure) {
|
||||
failures = append(failures, failure)
|
||||
}
|
||||
|
||||
w := lintDeferRule{onFailure: onFailure, allow: allow}
|
||||
|
||||
ast.Walk(w, file.AST)
|
||||
|
||||
return failures
|
||||
}
|
||||
|
||||
// Name returns the rule name.
|
||||
func (r *DeferRule) Name() string {
|
||||
return "defer"
|
||||
}
|
||||
|
||||
func (r *DeferRule) allowFromArgs(args lint.Arguments) map[string]bool {
|
||||
if len(args) < 1 {
|
||||
allow := map[string]bool{
|
||||
"loop": true,
|
||||
"call-chain": true,
|
||||
"method-call": true,
|
||||
"return": true,
|
||||
"recover": true,
|
||||
}
|
||||
|
||||
return allow
|
||||
}
|
||||
|
||||
aa, ok := args[0].([]interface{})
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("Invalid argument '%v' for 'defer' rule. Expecting []string, got %T", args[0], args[0]))
|
||||
}
|
||||
|
||||
allow := make(map[string]bool, len(aa))
|
||||
for _, subcase := range aa {
|
||||
sc, ok := subcase.(string)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("Invalid argument '%v' for 'defer' rule. Expecting string, got %T", subcase, subcase))
|
||||
}
|
||||
allow[sc] = true
|
||||
}
|
||||
|
||||
return allow
|
||||
}
|
||||
|
||||
type lintDeferRule struct {
|
||||
onFailure func(lint.Failure)
|
||||
inALoop bool
|
||||
inADefer bool
|
||||
inAFuncLit bool
|
||||
allow map[string]bool
|
||||
}
|
||||
|
||||
func (w lintDeferRule) Visit(node ast.Node) ast.Visitor {
|
||||
switch n := node.(type) {
|
||||
case *ast.ForStmt:
|
||||
w.visitSubtree(n.Body, w.inADefer, true, w.inAFuncLit)
|
||||
return nil
|
||||
case *ast.RangeStmt:
|
||||
w.visitSubtree(n.Body, w.inADefer, true, w.inAFuncLit)
|
||||
return nil
|
||||
case *ast.FuncLit:
|
||||
w.visitSubtree(n.Body, w.inADefer, false, true)
|
||||
return nil
|
||||
case *ast.ReturnStmt:
|
||||
if len(n.Results) != 0 && w.inADefer && w.inAFuncLit {
|
||||
w.newFailure("return in a defer function has no effect", n, 1.0, "logic", "return")
|
||||
}
|
||||
case *ast.CallExpr:
|
||||
if isIdent(n.Fun, "recover") && !w.inADefer {
|
||||
// confidence is not 1 because recover can be in a function that is deferred elsewhere
|
||||
w.newFailure("recover must be called inside a deferred function", n, 0.8, "logic", "recover")
|
||||
}
|
||||
case *ast.DeferStmt:
|
||||
w.visitSubtree(n.Call.Fun, true, false, false)
|
||||
|
||||
if w.inALoop {
|
||||
w.newFailure("prefer not to defer inside loops", n, 1.0, "bad practice", "loop")
|
||||
}
|
||||
|
||||
switch fn := n.Call.Fun.(type) {
|
||||
case *ast.CallExpr:
|
||||
w.newFailure("prefer not to defer chains of function calls", fn, 1.0, "bad practice", "call-chain")
|
||||
case *ast.SelectorExpr:
|
||||
if id, ok := fn.X.(*ast.Ident); ok {
|
||||
isMethodCall := id != nil && id.Obj != nil && id.Obj.Kind == ast.Typ
|
||||
if isMethodCall {
|
||||
w.newFailure("be careful when deferring calls to methods without pointer receiver", fn, 0.8, "bad practice", "method-call")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return w
|
||||
}
|
||||
|
||||
func (w lintDeferRule) visitSubtree(n ast.Node, inADefer, inALoop, inAFuncLit bool) {
|
||||
nw := &lintDeferRule{
|
||||
onFailure: w.onFailure,
|
||||
inADefer: inADefer,
|
||||
inALoop: inALoop,
|
||||
inAFuncLit: inAFuncLit,
|
||||
allow: w.allow}
|
||||
ast.Walk(nw, n)
|
||||
}
|
||||
|
||||
func (w lintDeferRule) newFailure(msg string, node ast.Node, confidence float64, cat string, subcase string) {
|
||||
if !w.allow[subcase] {
|
||||
return
|
||||
}
|
||||
|
||||
w.onFailure(lint.Failure{
|
||||
Confidence: confidence,
|
||||
Node: node,
|
||||
Category: cat,
|
||||
Failure: msg,
|
||||
})
|
||||
}
|
78
vendor/github.com/mgechev/revive/rule/early-return.go
generated
vendored
Normal file
78
vendor/github.com/mgechev/revive/rule/early-return.go
generated
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
package rule
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/mgechev/revive/lint"
|
||||
)
|
||||
|
||||
// EarlyReturnRule lints given else constructs.
|
||||
type EarlyReturnRule struct{}
|
||||
|
||||
// Apply applies the rule to given file.
|
||||
func (r *EarlyReturnRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
|
||||
var failures []lint.Failure
|
||||
|
||||
onFailure := func(failure lint.Failure) {
|
||||
failures = append(failures, failure)
|
||||
}
|
||||
|
||||
w := lintEarlyReturnRule{onFailure: onFailure}
|
||||
ast.Walk(w, file.AST)
|
||||
return failures
|
||||
}
|
||||
|
||||
// Name returns the rule name.
|
||||
func (r *EarlyReturnRule) Name() string {
|
||||
return "early-return"
|
||||
}
|
||||
|
||||
type lintEarlyReturnRule struct {
|
||||
onFailure func(lint.Failure)
|
||||
}
|
||||
|
||||
func (w lintEarlyReturnRule) Visit(node ast.Node) ast.Visitor {
|
||||
switch n := node.(type) {
|
||||
case *ast.IfStmt:
|
||||
if n.Else == nil {
|
||||
// no else branch
|
||||
return w
|
||||
}
|
||||
|
||||
elseBlock, ok := n.Else.(*ast.BlockStmt)
|
||||
if !ok {
|
||||
// is if-else-if
|
||||
return w
|
||||
}
|
||||
|
||||
lenElseBlock := len(elseBlock.List)
|
||||
if lenElseBlock < 1 {
|
||||
// empty else block, continue (there is another rule that warns on empty blocks)
|
||||
return w
|
||||
}
|
||||
|
||||
lenThenBlock := len(n.Body.List)
|
||||
if lenThenBlock < 1 {
|
||||
// then block is empty thus the stmt can be simplified
|
||||
w.onFailure(lint.Failure{
|
||||
Confidence: 1,
|
||||
Node: n,
|
||||
Failure: "if c { } else {... return} can be simplified to if !c { ... return }",
|
||||
})
|
||||
|
||||
return w
|
||||
}
|
||||
|
||||
_, lastThenStmtIsReturn := n.Body.List[lenThenBlock-1].(*ast.ReturnStmt)
|
||||
_, lastElseStmtIsReturn := elseBlock.List[lenElseBlock-1].(*ast.ReturnStmt)
|
||||
if lastElseStmtIsReturn && !lastThenStmtIsReturn {
|
||||
w.onFailure(lint.Failure{
|
||||
Confidence: 1,
|
||||
Node: n,
|
||||
Failure: "if c {...} else {... return } can be simplified to if !c { ... return } ...",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return w
|
||||
}
|
63
vendor/github.com/mgechev/revive/rule/empty-block.go
generated
vendored
63
vendor/github.com/mgechev/revive/rule/empty-block.go
generated
vendored
|
@ -17,7 +17,7 @@ func (r *EmptyBlockRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure
|
|||
failures = append(failures, failure)
|
||||
}
|
||||
|
||||
w := lintEmptyBlock{make([]*ast.BlockStmt, 0), onFailure}
|
||||
w := lintEmptyBlock{make(map[*ast.BlockStmt]bool, 0), onFailure}
|
||||
ast.Walk(w, file.AST)
|
||||
return failures
|
||||
}
|
||||
|
@ -28,49 +28,38 @@ func (r *EmptyBlockRule) Name() string {
|
|||
}
|
||||
|
||||
type lintEmptyBlock struct {
|
||||
ignore []*ast.BlockStmt
|
||||
ignore map[*ast.BlockStmt]bool
|
||||
onFailure func(lint.Failure)
|
||||
}
|
||||
|
||||
func (w lintEmptyBlock) Visit(node ast.Node) ast.Visitor {
|
||||
fd, ok := node.(*ast.FuncDecl)
|
||||
if ok {
|
||||
w.ignore = append(w.ignore, fd.Body)
|
||||
switch n := node.(type) {
|
||||
case *ast.FuncDecl:
|
||||
w.ignore[n.Body] = true
|
||||
return w
|
||||
}
|
||||
|
||||
fl, ok := node.(*ast.FuncLit)
|
||||
if ok {
|
||||
w.ignore = append(w.ignore, fl.Body)
|
||||
case *ast.FuncLit:
|
||||
w.ignore[n.Body] = true
|
||||
return w
|
||||
}
|
||||
|
||||
block, ok := node.(*ast.BlockStmt)
|
||||
if !ok {
|
||||
return w
|
||||
}
|
||||
|
||||
if mustIgnore(block, w.ignore) {
|
||||
return w
|
||||
}
|
||||
|
||||
if len(block.List) == 0 {
|
||||
w.onFailure(lint.Failure{
|
||||
Confidence: 1,
|
||||
Node: block,
|
||||
Category: "logic",
|
||||
Failure: "this block is empty, you can remove it",
|
||||
})
|
||||
case *ast.RangeStmt:
|
||||
if len(n.Body.List) == 0 {
|
||||
w.onFailure(lint.Failure{
|
||||
Confidence: 0.9,
|
||||
Node: n,
|
||||
Category: "logic",
|
||||
Failure: "this block is empty, you can remove it",
|
||||
})
|
||||
return nil // skip visiting the range subtree (it will produce a duplicated failure)
|
||||
}
|
||||
case *ast.BlockStmt:
|
||||
if !w.ignore[n] && len(n.List) == 0 {
|
||||
w.onFailure(lint.Failure{
|
||||
Confidence: 1,
|
||||
Node: n,
|
||||
Category: "logic",
|
||||
Failure: "this block is empty, you can remove it",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return w
|
||||
}
|
||||
|
||||
func mustIgnore(block *ast.BlockStmt, blackList []*ast.BlockStmt) bool {
|
||||
for _, b := range blackList {
|
||||
if b == block {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
82
vendor/github.com/mgechev/revive/rule/identical-branches.go
generated
vendored
Normal file
82
vendor/github.com/mgechev/revive/rule/identical-branches.go
generated
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
package rule
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/mgechev/revive/lint"
|
||||
)
|
||||
|
||||
// IdenticalBranchesRule warns on constant logical expressions.
|
||||
type IdenticalBranchesRule struct{}
|
||||
|
||||
// Apply applies the rule to given file.
|
||||
func (r *IdenticalBranchesRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
|
||||
var failures []lint.Failure
|
||||
|
||||
onFailure := func(failure lint.Failure) {
|
||||
failures = append(failures, failure)
|
||||
}
|
||||
|
||||
astFile := file.AST
|
||||
w := &lintIdenticalBranches{astFile, onFailure}
|
||||
ast.Walk(w, astFile)
|
||||
return failures
|
||||
}
|
||||
|
||||
// Name returns the rule name.
|
||||
func (r *IdenticalBranchesRule) Name() string {
|
||||
return "identical-branches"
|
||||
}
|
||||
|
||||
type lintIdenticalBranches struct {
|
||||
file *ast.File
|
||||
onFailure func(lint.Failure)
|
||||
}
|
||||
|
||||
func (w *lintIdenticalBranches) Visit(node ast.Node) ast.Visitor {
|
||||
n, ok := node.(*ast.IfStmt)
|
||||
if !ok {
|
||||
return w
|
||||
}
|
||||
|
||||
if n.Else == nil {
|
||||
return w
|
||||
}
|
||||
branches := []*ast.BlockStmt{n.Body}
|
||||
|
||||
elseBranch, ok := n.Else.(*ast.BlockStmt)
|
||||
if !ok { // if-else-if construction
|
||||
return w
|
||||
}
|
||||
branches = append(branches, elseBranch)
|
||||
|
||||
if w.identicalBranches(branches) {
|
||||
w.newFailure(n, "both branches of the if are identical")
|
||||
}
|
||||
|
||||
return w
|
||||
}
|
||||
|
||||
func (w *lintIdenticalBranches) identicalBranches(branches []*ast.BlockStmt) bool {
|
||||
if len(branches) < 2 {
|
||||
return false
|
||||
}
|
||||
|
||||
ref := gofmt(branches[0])
|
||||
for i := 1; i < len(branches); i++ {
|
||||
if gofmt(branches[i]) != ref {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (w lintIdenticalBranches) newFailure(node ast.Node, msg string) {
|
||||
w.onFailure(lint.Failure{
|
||||
Confidence: 1,
|
||||
Node: node,
|
||||
Category: "logic",
|
||||
Failure: msg,
|
||||
})
|
||||
}
|
183
vendor/github.com/mgechev/revive/rule/unconditional-recursion.go
generated
vendored
Normal file
183
vendor/github.com/mgechev/revive/rule/unconditional-recursion.go
generated
vendored
Normal file
|
@ -0,0 +1,183 @@
|
|||
package rule
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/mgechev/revive/lint"
|
||||
)
|
||||
|
||||
// UnconditionalRecursionRule lints given else constructs.
|
||||
type UnconditionalRecursionRule struct{}
|
||||
|
||||
// Apply applies the rule to given file.
|
||||
func (r *UnconditionalRecursionRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
|
||||
var failures []lint.Failure
|
||||
|
||||
onFailure := func(failure lint.Failure) {
|
||||
failures = append(failures, failure)
|
||||
}
|
||||
|
||||
w := lintUnconditionalRecursionRule{onFailure: onFailure}
|
||||
ast.Walk(w, file.AST)
|
||||
return failures
|
||||
}
|
||||
|
||||
// Name returns the rule name.
|
||||
func (r *UnconditionalRecursionRule) Name() string {
|
||||
return "unconditional-recursion"
|
||||
}
|
||||
|
||||
type funcDesc struct {
|
||||
reciverID *ast.Ident
|
||||
id *ast.Ident
|
||||
}
|
||||
|
||||
func (fd *funcDesc) equal(other *funcDesc) bool {
|
||||
receiversAreEqual := (fd.reciverID == nil && other.reciverID == nil) || fd.reciverID != nil && other.reciverID != nil && fd.reciverID.Name == other.reciverID.Name
|
||||
idsAreEqual := (fd.id == nil && other.id == nil) || fd.id.Name == other.id.Name
|
||||
|
||||
return receiversAreEqual && idsAreEqual
|
||||
}
|
||||
|
||||
type funcStatus struct {
|
||||
funcDesc *funcDesc
|
||||
seenConditionalExit bool
|
||||
}
|
||||
|
||||
type lintUnconditionalRecursionRule struct {
|
||||
onFailure func(lint.Failure)
|
||||
currentFunc *funcStatus
|
||||
}
|
||||
|
||||
// Visit will traverse the file AST.
|
||||
// The rule is based in the following algorithm: inside each function body we search for calls to the function itself.
|
||||
// We do not search inside conditional control structures (if, for, switch, ...) because any recursive call inside them is conditioned
|
||||
// We do search inside conditional control structures are statements that will take the control out of the function (return, exit, panic)
|
||||
// If we find conditional control exits, it means the function is NOT unconditionally-recursive
|
||||
// If we find a recursive call before finding any conditional exit, a failure is generated
|
||||
// In resume: if we found a recursive call control-dependant from the entry point of the function then we raise a failure.
|
||||
func (w lintUnconditionalRecursionRule) Visit(node ast.Node) ast.Visitor {
|
||||
switch n := node.(type) {
|
||||
case *ast.FuncDecl:
|
||||
var rec *ast.Ident
|
||||
switch {
|
||||
case n.Recv == nil || n.Recv.NumFields() < 1 || len(n.Recv.List[0].Names) < 1:
|
||||
rec = nil
|
||||
default:
|
||||
rec = n.Recv.List[0].Names[0]
|
||||
}
|
||||
|
||||
w.currentFunc = &funcStatus{&funcDesc{rec, n.Name}, false}
|
||||
case *ast.CallExpr:
|
||||
var funcID *ast.Ident
|
||||
var selector *ast.Ident
|
||||
switch c := n.Fun.(type) {
|
||||
case *ast.Ident:
|
||||
selector = nil
|
||||
funcID = c
|
||||
case *ast.SelectorExpr:
|
||||
var ok bool
|
||||
selector, ok = c.X.(*ast.Ident)
|
||||
if !ok { // a.b....Foo()
|
||||
return nil
|
||||
}
|
||||
funcID = c.Sel
|
||||
default:
|
||||
return w
|
||||
}
|
||||
|
||||
if w.currentFunc != nil && // not in a func body
|
||||
!w.currentFunc.seenConditionalExit && // there is a conditional exit in the function
|
||||
w.currentFunc.funcDesc.equal(&funcDesc{selector, funcID}) {
|
||||
w.onFailure(lint.Failure{
|
||||
Category: "logic",
|
||||
Confidence: 1,
|
||||
Node: n,
|
||||
Failure: "unconditional recursive call",
|
||||
})
|
||||
}
|
||||
case *ast.IfStmt:
|
||||
w.updateFuncStatus(n.Body)
|
||||
w.updateFuncStatus(n.Else)
|
||||
return nil
|
||||
case *ast.SelectStmt:
|
||||
w.updateFuncStatus(n.Body)
|
||||
return nil
|
||||
case *ast.RangeStmt:
|
||||
w.updateFuncStatus(n.Body)
|
||||
return nil
|
||||
case *ast.TypeSwitchStmt:
|
||||
w.updateFuncStatus(n.Body)
|
||||
return nil
|
||||
case *ast.SwitchStmt:
|
||||
w.updateFuncStatus(n.Body)
|
||||
return nil
|
||||
case *ast.GoStmt:
|
||||
for _, a := range n.Call.Args {
|
||||
ast.Walk(w, a) // check if arguments have a recursive call
|
||||
}
|
||||
return nil // recursive async call is not an issue
|
||||
case *ast.ForStmt:
|
||||
if n.Cond != nil {
|
||||
return nil
|
||||
}
|
||||
// unconditional loop
|
||||
return w
|
||||
}
|
||||
|
||||
return w
|
||||
}
|
||||
|
||||
func (w *lintUnconditionalRecursionRule) updateFuncStatus(node ast.Node) {
|
||||
if node == nil || w.currentFunc == nil || w.currentFunc.seenConditionalExit {
|
||||
return
|
||||
}
|
||||
|
||||
w.currentFunc.seenConditionalExit = w.hasControlExit(node)
|
||||
}
|
||||
|
||||
var exitFunctions = map[string]map[string]bool{
|
||||
"os": map[string]bool{"Exit": true},
|
||||
"syscall": map[string]bool{"Exit": true},
|
||||
"log": map[string]bool{
|
||||
"Fatal": true,
|
||||
"Fatalf": true,
|
||||
"Fatalln": true,
|
||||
"Panic": true,
|
||||
"Panicf": true,
|
||||
"Panicln": true,
|
||||
},
|
||||
}
|
||||
|
||||
func (w *lintUnconditionalRecursionRule) hasControlExit(node ast.Node) bool {
|
||||
// isExit returns true if the given node makes control exit the function
|
||||
isExit := func(node ast.Node) bool {
|
||||
switch n := node.(type) {
|
||||
case *ast.ReturnStmt:
|
||||
return true
|
||||
case *ast.CallExpr:
|
||||
if isIdent(n.Fun, "panic") {
|
||||
return true
|
||||
}
|
||||
se, ok := n.Fun.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
id, ok := se.X.(*ast.Ident)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
fn := se.Sel.Name
|
||||
pkg := id.Name
|
||||
if exitFunctions[pkg] != nil && exitFunctions[pkg][fn] { // it's a call to an exit function
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return len(pick(node, isExit, nil)) != 0
|
||||
}
|
115
vendor/github.com/mgechev/revive/rule/unexported-naming.go
generated
vendored
Normal file
115
vendor/github.com/mgechev/revive/rule/unexported-naming.go
generated
vendored
Normal file
|
@ -0,0 +1,115 @@
|
|||
package rule
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
|
||||
"github.com/mgechev/revive/lint"
|
||||
)
|
||||
|
||||
// UnexportedNamingRule lints wrongly named unexported symbols.
|
||||
type UnexportedNamingRule struct{}
|
||||
|
||||
// Apply applies the rule to given file.
|
||||
func (r *UnexportedNamingRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
|
||||
var failures []lint.Failure
|
||||
onFailure := func(failure lint.Failure) {
|
||||
failures = append(failures, failure)
|
||||
}
|
||||
|
||||
ba := &unexportablenamingLinter{onFailure}
|
||||
ast.Walk(ba, file.AST)
|
||||
|
||||
return failures
|
||||
}
|
||||
|
||||
// Name returns the rule name.
|
||||
func (r *UnexportedNamingRule) Name() string {
|
||||
return "unexported-naming"
|
||||
}
|
||||
|
||||
type unexportablenamingLinter struct {
|
||||
onFailure func(lint.Failure)
|
||||
}
|
||||
|
||||
func (unl unexportablenamingLinter) Visit(node ast.Node) ast.Visitor {
|
||||
switch n := node.(type) {
|
||||
case *ast.FuncDecl:
|
||||
unl.lintFunction(n.Type, n.Body)
|
||||
return nil
|
||||
case *ast.FuncLit:
|
||||
unl.lintFunction(n.Type, n.Body)
|
||||
|
||||
return nil
|
||||
case *ast.AssignStmt:
|
||||
if n.Tok != token.DEFINE {
|
||||
return nil
|
||||
}
|
||||
|
||||
ids := []*ast.Ident{}
|
||||
for _, e := range n.Lhs {
|
||||
id, ok := e.(*ast.Ident)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
|
||||
unl.lintIDs(ids)
|
||||
|
||||
case *ast.DeclStmt:
|
||||
gd, ok := n.Decl.(*ast.GenDecl)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(gd.Specs) < 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
vs, ok := gd.Specs[0].(*ast.ValueSpec)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
unl.lintIDs(vs.Names)
|
||||
}
|
||||
|
||||
return unl
|
||||
}
|
||||
|
||||
func (unl unexportablenamingLinter) lintFunction(ft *ast.FuncType, body *ast.BlockStmt) {
|
||||
unl.lintFields(ft.Params)
|
||||
unl.lintFields(ft.Results)
|
||||
|
||||
if body != nil {
|
||||
ast.Walk(unl, body)
|
||||
}
|
||||
}
|
||||
|
||||
func (unl unexportablenamingLinter) lintFields(fields *ast.FieldList) {
|
||||
if fields == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ids := []*ast.Ident{}
|
||||
for _, field := range fields.List {
|
||||
ids = append(ids, field.Names...)
|
||||
}
|
||||
|
||||
unl.lintIDs(ids)
|
||||
}
|
||||
|
||||
func (unl unexportablenamingLinter) lintIDs(ids []*ast.Ident) {
|
||||
for _, id := range ids {
|
||||
if id.IsExported() {
|
||||
unl.onFailure(lint.Failure{
|
||||
Node: id,
|
||||
Confidence: 1,
|
||||
Category: "naming",
|
||||
Failure: fmt.Sprintf("the symbol %s is local, its name should start with a lowercase letter", id.String()),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
4
vendor/github.com/mgechev/revive/rule/unused-receiver.go
generated
vendored
4
vendor/github.com/mgechev/revive/rule/unused-receiver.go
generated
vendored
|
@ -11,7 +11,7 @@ import (
|
|||
type UnusedReceiverRule struct{}
|
||||
|
||||
// Apply applies the rule to given file.
|
||||
func (_ *UnusedReceiverRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
|
||||
func (*UnusedReceiverRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
|
||||
var failures []lint.Failure
|
||||
|
||||
onFailure := func(failure lint.Failure) {
|
||||
|
@ -26,7 +26,7 @@ func (_ *UnusedReceiverRule) Apply(file *lint.File, _ lint.Arguments) []lint.Fai
|
|||
}
|
||||
|
||||
// Name returns the rule name.
|
||||
func (_ *UnusedReceiverRule) Name() string {
|
||||
func (*UnusedReceiverRule) Name() string {
|
||||
return "unused-receiver"
|
||||
}
|
||||
|
||||
|
|
4
vendor/github.com/mgechev/revive/rule/utils.go
generated
vendored
4
vendor/github.com/mgechev/revive/rule/utils.go
generated
vendored
|
@ -182,8 +182,8 @@ func isExprABooleanLit(n ast.Node) (lexeme string, ok bool) {
|
|||
return oper.Name, (oper.Name == trueName || oper.Name == falseName)
|
||||
}
|
||||
|
||||
// gofmt returns a string representation of the expression.
|
||||
func gofmt(x ast.Expr) string {
|
||||
// gofmt returns a string representation of an AST subtree.
|
||||
func gofmt(x interface{}) string {
|
||||
buf := bytes.Buffer{}
|
||||
fs := token.NewFileSet()
|
||||
printer.Fprint(&buf, fs, x)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue