mirror of
https://github.com/mgechev/revive.git
synced 2025-04-27 12:12:10 +02:00
code cleanup (#1054)
This commit is contained in:
parent
798ce21849
commit
ca2a32b087
@ -160,12 +160,15 @@ func (w *lintAddConstantRule) isIgnoredFunc(fName string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *lintAddConstantRule) checkStrLit(n *ast.BasicLit) {
|
func (w *lintAddConstantRule) checkStrLit(n *ast.BasicLit) {
|
||||||
|
const IgnoreMarker = -1
|
||||||
|
|
||||||
if w.allowList[kindSTRING][n.Value] {
|
if w.allowList[kindSTRING][n.Value] {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
count := w.strLits[n.Value]
|
count := w.strLits[n.Value]
|
||||||
if count >= 0 {
|
mustCheck := count > IgnoreMarker
|
||||||
|
if mustCheck {
|
||||||
w.strLits[n.Value] = count + 1
|
w.strLits[n.Value] = count + 1
|
||||||
if w.strLits[n.Value] > w.strLitLimit {
|
if w.strLits[n.Value] > w.strLitLimit {
|
||||||
w.onFailure(lint.Failure{
|
w.onFailure(lint.Failure{
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
// ArgumentsLimitRule lints given else constructs.
|
// ArgumentsLimitRule lints given else constructs.
|
||||||
type ArgumentsLimitRule struct {
|
type ArgumentsLimitRule struct {
|
||||||
total int
|
max int
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,18 +19,20 @@ const defaultArgumentsLimit = 8
|
|||||||
func (r *ArgumentsLimitRule) configure(arguments lint.Arguments) {
|
func (r *ArgumentsLimitRule) configure(arguments lint.Arguments) {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
if r.total == 0 {
|
if r.max != 0 {
|
||||||
if len(arguments) < 1 {
|
|
||||||
r.total = defaultArgumentsLimit
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
total, ok := arguments[0].(int64) // Alt. non panicking version
|
if len(arguments) < 1 {
|
||||||
|
r.max = defaultArgumentsLimit
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
maxArguments, ok := arguments[0].(int64) // Alt. non panicking version
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(`invalid value passed as argument number to the "argument-limit" rule`)
|
panic(`invalid value passed as argument number to the "argument-limit" rule`)
|
||||||
}
|
}
|
||||||
r.total = int(total)
|
r.max = int(maxArguments)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply applies the rule to given file.
|
// Apply applies the rule to given file.
|
||||||
@ -43,7 +45,7 @@ func (r *ArgumentsLimitRule) Apply(file *lint.File, arguments lint.Arguments) []
|
|||||||
}
|
}
|
||||||
|
|
||||||
walker := lintArgsNum{
|
walker := lintArgsNum{
|
||||||
total: r.total,
|
max: r.max,
|
||||||
onFailure: onFailure,
|
onFailure: onFailure,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,27 +60,30 @@ func (*ArgumentsLimitRule) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type lintArgsNum struct {
|
type lintArgsNum struct {
|
||||||
total int
|
max int
|
||||||
onFailure func(lint.Failure)
|
onFailure func(lint.Failure)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w lintArgsNum) Visit(n ast.Node) ast.Visitor {
|
func (w lintArgsNum) Visit(n ast.Node) ast.Visitor {
|
||||||
node, ok := n.(*ast.FuncDecl)
|
node, ok := n.(*ast.FuncDecl)
|
||||||
if ok {
|
if !ok {
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
num := 0
|
num := 0
|
||||||
for _, l := range node.Type.Params.List {
|
for _, l := range node.Type.Params.List {
|
||||||
for range l.Names {
|
for range l.Names {
|
||||||
num++
|
num++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if num > w.total {
|
|
||||||
|
if num > w.max {
|
||||||
w.onFailure(lint.Failure{
|
w.onFailure(lint.Failure{
|
||||||
Confidence: 1,
|
Confidence: 1,
|
||||||
Failure: fmt.Sprintf("maximum number of arguments per function exceeded; max %d but got %d", w.total, num),
|
Failure: fmt.Sprintf("maximum number of arguments per function exceeded; max %d but got %d", w.max, num),
|
||||||
Node: node.Type,
|
Node: node.Type,
|
||||||
})
|
})
|
||||||
return w
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return w
|
return nil // skip visiting the body of the function
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ func (r *BlankImportsRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failu
|
|||||||
const (
|
const (
|
||||||
message = "a blank import should be only in a main or test package, or have a comment justifying it"
|
message = "a blank import should be only in a main or test package, or have a comment justifying it"
|
||||||
category = "imports"
|
category = "imports"
|
||||||
|
|
||||||
embedImportPath = `"embed"`
|
embedImportPath = `"embed"`
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,7 +38,8 @@ func (r *BlankImportsRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failu
|
|||||||
continue // Ignore non-blank imports.
|
continue // Ignore non-blank imports.
|
||||||
}
|
}
|
||||||
|
|
||||||
if i > 0 {
|
isNotFirstElement := i > 0
|
||||||
|
if isNotFirstElement {
|
||||||
prev := file.AST.Imports[i-1]
|
prev := file.AST.Imports[i-1]
|
||||||
prevPos := file.ToPosition(prev.Pos())
|
prevPos := file.ToPosition(prev.Pos())
|
||||||
|
|
||||||
|
@ -45,7 +45,6 @@ func (w *lintBoolLiteral) Visit(node ast.Node) ast.Visitor {
|
|||||||
lexeme, ok := isExprABooleanLit(n.X)
|
lexeme, ok := isExprABooleanLit(n.X)
|
||||||
if !ok {
|
if !ok {
|
||||||
lexeme, ok = isExprABooleanLit(n.Y)
|
lexeme, ok = isExprABooleanLit(n.Y)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,9 @@ const defaultMaxCognitiveComplexity = 7
|
|||||||
func (r *CognitiveComplexityRule) configure(arguments lint.Arguments) {
|
func (r *CognitiveComplexityRule) configure(arguments lint.Arguments) {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
if r.maxComplexity == 0 {
|
if r.maxComplexity != 0 {
|
||||||
|
return // already configured
|
||||||
|
}
|
||||||
|
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
r.maxComplexity = defaultMaxCognitiveComplexity
|
r.maxComplexity = defaultMaxCognitiveComplexity
|
||||||
@ -32,8 +34,8 @@ func (r *CognitiveComplexityRule) configure(arguments lint.Arguments) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("invalid argument type for cognitive-complexity, expected int64, got %T", arguments[0]))
|
panic(fmt.Sprintf("invalid argument type for cognitive-complexity, expected int64, got %T", arguments[0]))
|
||||||
}
|
}
|
||||||
|
|
||||||
r.maxComplexity = int(complexity)
|
r.maxComplexity = int(complexity)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply applies the rule to given file.
|
// Apply applies the rule to given file.
|
||||||
|
@ -18,8 +18,10 @@ type CommentSpacingsRule struct {
|
|||||||
func (r *CommentSpacingsRule) configure(arguments lint.Arguments) {
|
func (r *CommentSpacingsRule) configure(arguments lint.Arguments) {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
|
if r.allowList != nil {
|
||||||
|
return // already configured
|
||||||
|
}
|
||||||
|
|
||||||
if r.allowList == nil {
|
|
||||||
r.allowList = []string{}
|
r.allowList = []string{}
|
||||||
for _, arg := range arguments {
|
for _, arg := range arguments {
|
||||||
allow, ok := arg.(string) // Alt. non panicking version
|
allow, ok := arg.(string) // Alt. non panicking version
|
||||||
@ -28,7 +30,6 @@ func (r *CommentSpacingsRule) configure(arguments lint.Arguments) {
|
|||||||
}
|
}
|
||||||
r.allowList = append(r.allowList, `//`+allow)
|
r.allowList = append(r.allowList, `//`+allow)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the rule.
|
// Apply the rule.
|
||||||
|
@ -41,8 +41,9 @@ func (w *lintConstantLogicalExpr) Visit(node ast.Node) ast.Visitor {
|
|||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
if gofmt(n.X) != gofmt(n.Y) { // check if subexpressions are the same
|
subExpressionsAreNotEqual := gofmt(n.X) != gofmt(n.Y)
|
||||||
return w
|
if subExpressionsAreNotEqual {
|
||||||
|
return w // nothing to say
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles cases like: a <= a, a == a, a >= a
|
// Handles cases like: a <= a, a == a, a >= a
|
||||||
|
@ -22,7 +22,10 @@ const defaultMaxCyclomaticComplexity = 10
|
|||||||
func (r *CyclomaticRule) configure(arguments lint.Arguments) {
|
func (r *CyclomaticRule) configure(arguments lint.Arguments) {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
if r.maxComplexity == 0 {
|
if r.maxComplexity != 0 {
|
||||||
|
return // already configured
|
||||||
|
}
|
||||||
|
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
r.maxComplexity = defaultMaxCyclomaticComplexity
|
r.maxComplexity = defaultMaxCyclomaticComplexity
|
||||||
return
|
return
|
||||||
@ -33,7 +36,6 @@ func (r *CyclomaticRule) configure(arguments lint.Arguments) {
|
|||||||
panic(fmt.Sprintf("invalid argument for cyclomatic complexity; expected int but got %T", arguments[0]))
|
panic(fmt.Sprintf("invalid argument for cyclomatic complexity; expected int but got %T", arguments[0]))
|
||||||
}
|
}
|
||||||
r.maxComplexity = int(complexity)
|
r.maxComplexity = int(complexity)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply applies the rule to given file.
|
// Apply applies the rule to given file.
|
||||||
@ -70,7 +72,11 @@ type lintCyclomatic struct {
|
|||||||
func (w lintCyclomatic) Visit(_ ast.Node) ast.Visitor {
|
func (w lintCyclomatic) Visit(_ ast.Node) ast.Visitor {
|
||||||
f := w.file
|
f := w.file
|
||||||
for _, decl := range f.AST.Decls {
|
for _, decl := range f.AST.Decls {
|
||||||
if fn, ok := decl.(*ast.FuncDecl); ok {
|
fn, ok := decl.(*ast.FuncDecl)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
c := complexity(fn)
|
c := complexity(fn)
|
||||||
if c > w.complexity {
|
if c > w.complexity {
|
||||||
w.onFailure(lint.Failure{
|
w.onFailure(lint.Failure{
|
||||||
@ -82,19 +88,19 @@ func (w lintCyclomatic) Visit(_ ast.Node) ast.Visitor {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// funcName returns the name representation of a function or method:
|
// funcName returns the name representation of a function or method:
|
||||||
// "(Type).Name" for methods or simply "Name" for functions.
|
// "(Type).Name" for methods or simply "Name" for functions.
|
||||||
func funcName(fn *ast.FuncDecl) string {
|
func funcName(fn *ast.FuncDecl) string {
|
||||||
if fn.Recv != nil {
|
declarationHasReceiver := fn.Recv != nil && fn.Recv.NumFields() > 0
|
||||||
if fn.Recv.NumFields() > 0 {
|
if declarationHasReceiver {
|
||||||
typ := fn.Recv.List[0].Type
|
typ := fn.Recv.List[0].Type
|
||||||
return fmt.Sprintf("(%s).%s", recvString(typ), fn.Name)
|
return fmt.Sprintf("(%s).%s", recvString(typ), fn.Name)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return fn.Name.Name
|
return fn.Name.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,9 +73,10 @@ func (w lintDeepExit) Visit(node ast.Node) ast.Visitor {
|
|||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
fn := fc.Sel.Name
|
|
||||||
pkg := id.Name
|
pkg := id.Name
|
||||||
if w.exitFunctions[pkg] != nil && w.exitFunctions[pkg][fn] { // it's a call to an exit function
|
fn := fc.Sel.Name
|
||||||
|
isACallToExitFunction := w.exitFunctions[pkg] != nil && w.exitFunctions[pkg][fn]
|
||||||
|
if isACallToExitFunction {
|
||||||
w.onFailure(lint.Failure{
|
w.onFailure(lint.Failure{
|
||||||
Confidence: 1,
|
Confidence: 1,
|
||||||
Node: ce,
|
Node: ce,
|
||||||
|
@ -16,10 +16,12 @@ type DeferRule struct {
|
|||||||
|
|
||||||
func (r *DeferRule) configure(arguments lint.Arguments) {
|
func (r *DeferRule) configure(arguments lint.Arguments) {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
if r.allow == nil {
|
defer r.Unlock()
|
||||||
r.allow = r.allowFromArgs(arguments)
|
if r.allow != nil {
|
||||||
|
return // already configured
|
||||||
}
|
}
|
||||||
r.Unlock()
|
|
||||||
|
r.allow = r.allowFromArgs(arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply applies the rule to given file.
|
// Apply applies the rule to given file.
|
||||||
|
@ -81,12 +81,13 @@ type lintImports struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w lintImports) Visit(_ ast.Node) ast.Visitor {
|
func (w lintImports) Visit(_ ast.Node) ast.Visitor {
|
||||||
for _, is := range w.fileAst.Imports {
|
for _, importSpec := range w.fileAst.Imports {
|
||||||
if is.Name != nil && is.Name.Name == "." && !w.allowPackages.isAllowedPackage(is.Path.Value) {
|
isDotImport := importSpec.Name != nil && importSpec.Name.Name == "."
|
||||||
|
if isDotImport && !w.allowPackages.isAllowedPackage(importSpec.Path.Value) {
|
||||||
w.onFailure(lint.Failure{
|
w.onFailure(lint.Failure{
|
||||||
Confidence: 1,
|
Confidence: 1,
|
||||||
Failure: "should not use dot imports",
|
Failure: "should not use dot imports",
|
||||||
Node: is,
|
Node: importSpec,
|
||||||
Category: "imports",
|
Category: "imports",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -94,8 +94,8 @@ func (r *EnforceMapStyleRule) Apply(file *lint.File, arguments lint.Arguments) [
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(v.Elts) > 0 {
|
isEmptyMap := len(v.Elts) > 0
|
||||||
// not an empty map
|
if isEmptyMap {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,8 +101,8 @@ func (r *EnforceSliceStyleRule) Apply(file *lint.File, arguments lint.Arguments)
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(v.Elts) > 0 {
|
isNotEmptySlice := len(v.Elts) > 0
|
||||||
// not an empty slice
|
if isNotEmptySlice {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,8 +132,8 @@ func (r *EnforceSliceStyleRule) Apply(file *lint.File, arguments lint.Arguments)
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(v.Args) < 2 {
|
isInvalidMakeDeclaration := len(v.Args) < 2
|
||||||
// skip invalid make declarations
|
if isInvalidMakeDeclaration {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,8 +148,8 @@ func (r *EnforceSliceStyleRule) Apply(file *lint.File, arguments lint.Arguments)
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if arg.Value != "0" {
|
isSliceSizeNotZero := arg.Value != "0"
|
||||||
// skip slice with non-zero size
|
if isSliceSizeNotZero {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,8 +160,8 @@ func (r *EnforceSliceStyleRule) Apply(file *lint.File, arguments lint.Arguments)
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if arg.Value != "0" {
|
isNonZeroCapacitySlice := arg.Value != "0"
|
||||||
// skip non-zero capacity slice
|
if isNonZeroCapacitySlice {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,10 @@ var (
|
|||||||
func (r *FileHeaderRule) configure(arguments lint.Arguments) {
|
func (r *FileHeaderRule) configure(arguments lint.Arguments) {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
if r.header == "" {
|
if r.header != "" {
|
||||||
|
return // already configured
|
||||||
|
}
|
||||||
|
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -32,7 +35,6 @@ func (r *FileHeaderRule) configure(arguments lint.Arguments) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("invalid argument for \"file-header\" rule: argument should be a string, got %T", arguments[0]))
|
panic(fmt.Sprintf("invalid argument for \"file-header\" rule: argument should be a string, got %T", arguments[0]))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply applies the rule to given file.
|
// Apply applies the rule to given file.
|
||||||
|
@ -20,12 +20,14 @@ type FunctionLength struct {
|
|||||||
func (r *FunctionLength) configure(arguments lint.Arguments) {
|
func (r *FunctionLength) configure(arguments lint.Arguments) {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
if !r.configured {
|
if r.configured {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
r.configured = true
|
||||||
maxStmt, maxLines := r.parseArguments(arguments)
|
maxStmt, maxLines := r.parseArguments(arguments)
|
||||||
r.maxStmt = int(maxStmt)
|
r.maxStmt = int(maxStmt)
|
||||||
r.maxLines = int(maxLines)
|
r.maxLines = int(maxLines)
|
||||||
r.configured = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply applies the rule to given file.
|
// Apply applies the rule to given file.
|
||||||
@ -61,8 +63,9 @@ func (*FunctionLength) parseArguments(arguments lint.Arguments) (maxStmt, maxLin
|
|||||||
return defaultFuncStmtsLimit, defaultFuncLinesLimit
|
return defaultFuncStmtsLimit, defaultFuncLinesLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(arguments) != 2 {
|
const minArguments = 2
|
||||||
panic(fmt.Sprintf(`invalid configuration for "function-length" rule, expected 2 arguments but got %d`, len(arguments)))
|
if len(arguments) != minArguments {
|
||||||
|
panic(fmt.Sprintf(`invalid configuration for "function-length" rule, expected %d arguments but got %d`, minArguments, len(arguments)))
|
||||||
}
|
}
|
||||||
|
|
||||||
maxStmt, maxStmtOk := arguments[0].(int64)
|
maxStmt, maxStmtOk := arguments[0].(int64)
|
||||||
@ -98,7 +101,8 @@ func (w lintFuncLength) Visit(n ast.Node) ast.Visitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body := node.Body
|
body := node.Body
|
||||||
if body == nil || len(node.Body.List) == 0 {
|
emptyBody := body == nil || len(node.Body.List) == 0
|
||||||
|
if emptyBody {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,11 +19,15 @@ const defaultResultsLimit = 3
|
|||||||
func (r *FunctionResultsLimitRule) configure(arguments lint.Arguments) {
|
func (r *FunctionResultsLimitRule) configure(arguments lint.Arguments) {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
if r.max == 0 {
|
if r.max != 0 {
|
||||||
|
return // already configured
|
||||||
|
}
|
||||||
|
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
r.max = defaultResultsLimit
|
r.max = defaultResultsLimit
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
maxResults, ok := arguments[0].(int64) // Alt. non panicking version
|
maxResults, ok := arguments[0].(int64) // Alt. non panicking version
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf(`invalid value passed as return results number to the "function-result-limit" rule; need int64 but got %T`, arguments[0]))
|
panic(fmt.Sprintf(`invalid value passed as return results number to the "function-result-limit" rule; need int64 but got %T`, arguments[0]))
|
||||||
@ -31,8 +35,8 @@ func (r *FunctionResultsLimitRule) configure(arguments lint.Arguments) {
|
|||||||
if maxResults < 0 {
|
if maxResults < 0 {
|
||||||
panic(`the value passed as return results number to the "function-result-limit" rule cannot be negative`)
|
panic(`the value passed as return results number to the "function-result-limit" rule cannot be negative`)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.max = int(maxResults)
|
r.max = int(maxResults)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply applies the rule to given file.
|
// Apply applies the rule to given file.
|
||||||
@ -67,7 +71,8 @@ func (w lintFunctionResultsNum) Visit(n ast.Node) ast.Visitor {
|
|||||||
node, ok := n.(*ast.FuncDecl)
|
node, ok := n.(*ast.FuncDecl)
|
||||||
if ok {
|
if ok {
|
||||||
num := 0
|
num := 0
|
||||||
if node.Type.Results != nil {
|
hasResults := node.Type.Results != nil
|
||||||
|
if hasResults {
|
||||||
num = node.Type.Results.NumFields()
|
num = node.Type.Results.NumFields()
|
||||||
}
|
}
|
||||||
if num > w.max {
|
if num > w.max {
|
||||||
@ -76,8 +81,10 @@ func (w lintFunctionResultsNum) Visit(n ast.Node) ast.Visitor {
|
|||||||
Failure: fmt.Sprintf("maximum number of return results per function exceeded; max %d but got %d", w.max, num),
|
Failure: fmt.Sprintf("maximum number of return results per function exceeded; max %d but got %d", w.max, num),
|
||||||
Node: node.Type,
|
Node: node.Type,
|
||||||
})
|
})
|
||||||
return w
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil // skip visiting function's body
|
||||||
}
|
}
|
||||||
|
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
@ -33,15 +33,25 @@ type lintReturnRule struct {
|
|||||||
onFailure func(lint.Failure)
|
onFailure func(lint.Failure)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getterPrefix = "GET"
|
||||||
|
|
||||||
|
var lenGetterPrefix = len(getterPrefix)
|
||||||
|
|
||||||
func isGetter(name string) bool {
|
func isGetter(name string) bool {
|
||||||
if strings.HasPrefix(strings.ToUpper(name), "GET") {
|
nameHasGetterPrefix := strings.HasPrefix(strings.ToUpper(name), getterPrefix)
|
||||||
if len(name) > 3 {
|
if !nameHasGetterPrefix {
|
||||||
c := name[3]
|
return false
|
||||||
return !(c >= 'a' && c <= 'z')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isJustGet := len(name) == lenGetterPrefix
|
||||||
|
if isJustGet {
|
||||||
return false
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
c := name[lenGetterPrefix]
|
||||||
|
lowerCaseAfterGetterPrefix := c >= 'a' && c <= 'z'
|
||||||
|
|
||||||
|
return !lowerCaseAfterGetterPrefix
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasResults(rs *ast.FieldList) bool {
|
func hasResults(rs *ast.FieldList) bool {
|
||||||
|
@ -39,9 +39,11 @@ func (w *lintIdenticalBranches) Visit(node ast.Node) ast.Visitor {
|
|||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Else == nil {
|
noElseBranch := n.Else == nil
|
||||||
|
if noElseBranch {
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
branches := []*ast.BlockStmt{n.Body}
|
branches := []*ast.BlockStmt{n.Body}
|
||||||
|
|
||||||
elseBranch, ok := n.Else.(*ast.BlockStmt)
|
elseBranch, ok := n.Else.(*ast.BlockStmt)
|
||||||
@ -59,14 +61,15 @@ func (w *lintIdenticalBranches) Visit(node ast.Node) ast.Visitor {
|
|||||||
|
|
||||||
func (lintIdenticalBranches) identicalBranches(branches []*ast.BlockStmt) bool {
|
func (lintIdenticalBranches) identicalBranches(branches []*ast.BlockStmt) bool {
|
||||||
if len(branches) < 2 {
|
if len(branches) < 2 {
|
||||||
return false
|
return false // only one branch to compare thus we return
|
||||||
}
|
}
|
||||||
|
|
||||||
ref := gofmt(branches[0])
|
referenceBranch := gofmt(branches[0])
|
||||||
refSize := len(branches[0].List)
|
referenceBranchSize := len(branches[0].List)
|
||||||
for i := 1; i < len(branches); i++ {
|
for i := 1; i < len(branches); i++ {
|
||||||
currentSize := len(branches[i].List)
|
currentBranch := branches[i]
|
||||||
if currentSize != refSize || gofmt(branches[i]) != ref {
|
currentBranchSize := len(currentBranch.List)
|
||||||
|
if currentBranchSize != referenceBranchSize || gofmt(currentBranch) != referenceBranch {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,10 @@ const defaultLineLengthLimit = 80
|
|||||||
func (r *LineLengthLimitRule) configure(arguments lint.Arguments) {
|
func (r *LineLengthLimitRule) configure(arguments lint.Arguments) {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
if r.max == 0 {
|
if r.max != 0 {
|
||||||
|
return // already configured
|
||||||
|
}
|
||||||
|
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
r.max = defaultLineLengthLimit
|
r.max = defaultLineLengthLimit
|
||||||
return
|
return
|
||||||
@ -35,7 +38,7 @@ func (r *LineLengthLimitRule) configure(arguments lint.Arguments) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
r.max = int(maxLength)
|
r.max = int(maxLength)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply applies the rule to given file.
|
// Apply applies the rule to given file.
|
||||||
|
@ -110,7 +110,7 @@ func (r *MaxControlNestingRule) configure(arguments lint.Arguments) {
|
|||||||
r.Lock()
|
r.Lock()
|
||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
if !(r.max < 1) {
|
if !(r.max < 1) {
|
||||||
return // max already set
|
return // max already configured
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
|
@ -19,7 +19,10 @@ const defaultMaxPublicStructs = 5
|
|||||||
func (r *MaxPublicStructsRule) configure(arguments lint.Arguments) {
|
func (r *MaxPublicStructsRule) configure(arguments lint.Arguments) {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
if r.max < 1 {
|
if r.max == 0 {
|
||||||
|
return // already configured
|
||||||
|
}
|
||||||
|
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
r.max = defaultMaxPublicStructs
|
r.max = defaultMaxPublicStructs
|
||||||
return
|
return
|
||||||
@ -32,7 +35,7 @@ func (r *MaxPublicStructsRule) configure(arguments lint.Arguments) {
|
|||||||
panic(`invalid value passed as argument number to the "max-public-structs" rule`)
|
panic(`invalid value passed as argument number to the "max-public-structs" rule`)
|
||||||
}
|
}
|
||||||
r.max = maxStructs
|
r.max = maxStructs
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply applies the rule to given file.
|
// Apply applies the rule to given file.
|
||||||
|
@ -20,7 +20,12 @@ type StructTagRule struct {
|
|||||||
func (r *StructTagRule) configure(arguments lint.Arguments) {
|
func (r *StructTagRule) configure(arguments lint.Arguments) {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
if r.userDefined == nil && len(arguments) > 0 {
|
|
||||||
|
mustConfigure := r.userDefined == nil && len(arguments) > 0
|
||||||
|
if !mustConfigure {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
checkNumberOfArguments(1, arguments, r.Name())
|
checkNumberOfArguments(1, arguments, r.Name())
|
||||||
r.userDefined = make(map[string][]string, len(arguments))
|
r.userDefined = make(map[string][]string, len(arguments))
|
||||||
for _, arg := range arguments {
|
for _, arg := range arguments {
|
||||||
@ -38,7 +43,6 @@ func (r *StructTagRule) configure(arguments lint.Arguments) {
|
|||||||
r.userDefined[key] = append(r.userDefined[key], option)
|
r.userDefined[key] = append(r.userDefined[key], option)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply applies the rule to given file.
|
// Apply applies the rule to given file.
|
||||||
@ -75,11 +79,13 @@ type lintStructTagRule struct {
|
|||||||
func (w lintStructTagRule) Visit(node ast.Node) ast.Visitor {
|
func (w lintStructTagRule) Visit(node ast.Node) ast.Visitor {
|
||||||
switch n := node.(type) {
|
switch n := node.(type) {
|
||||||
case *ast.StructType:
|
case *ast.StructType:
|
||||||
if n.Fields == nil || n.Fields.NumFields() < 1 {
|
isEmptyStruct := n.Fields == nil || n.Fields.NumFields() < 1
|
||||||
|
if isEmptyStruct {
|
||||||
return nil // skip empty structs
|
return nil // skip empty structs
|
||||||
}
|
}
|
||||||
w.usedTagNbr = map[int]bool{} // init
|
|
||||||
w.usedTagName = map[string]bool{} // init
|
w.usedTagNbr = map[int]bool{}
|
||||||
|
w.usedTagName = map[string]bool{}
|
||||||
for _, f := range n.Fields.List {
|
for _, f := range n.Fields.List {
|
||||||
if f.Tag != nil {
|
if f.Tag != nil {
|
||||||
w.checkTaggedField(f)
|
w.checkTaggedField(f)
|
||||||
|
@ -50,26 +50,23 @@ func (l *lintTimeEqual) Visit(node ast.Node) ast.Visitor {
|
|||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
xtyp := l.file.Pkg.TypeOf(expr.X)
|
typeOfX := l.file.Pkg.TypeOf(expr.X)
|
||||||
ytyp := l.file.Pkg.TypeOf(expr.Y)
|
typeOfY := l.file.Pkg.TypeOf(expr.Y)
|
||||||
|
bothAreOfTimeType := isNamedType(typeOfX, "time", "Time") && isNamedType(typeOfY, "time", "Time")
|
||||||
if !isNamedType(xtyp, "time", "Time") || !isNamedType(ytyp, "time", "Time") {
|
if !bothAreOfTimeType {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
var failure string
|
negateStr := ""
|
||||||
switch expr.Op {
|
if token.NEQ == expr.Op {
|
||||||
case token.EQL:
|
negateStr = "!"
|
||||||
failure = fmt.Sprintf("use %s.Equal(%s) instead of %q operator", gofmt(expr.X), gofmt(expr.Y), expr.Op)
|
|
||||||
case token.NEQ:
|
|
||||||
failure = fmt.Sprintf("use !%s.Equal(%s) instead of %q operator", gofmt(expr.X), gofmt(expr.Y), expr.Op)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
l.onFailure(lint.Failure{
|
l.onFailure(lint.Failure{
|
||||||
Category: "time",
|
Category: "time",
|
||||||
Confidence: 1,
|
Confidence: 1,
|
||||||
Node: node,
|
Node: node,
|
||||||
Failure: failure,
|
Failure: fmt.Sprintf("use %s%s.Equal(%s) instead of %q operator", negateStr, gofmt(expr.X), gofmt(expr.Y), expr.Op),
|
||||||
})
|
})
|
||||||
|
|
||||||
return l
|
return l
|
||||||
|
@ -90,6 +90,7 @@ func isNamedType(typ types.Type, importPath, name string) bool {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
tn := n.Obj()
|
|
||||||
return tn != nil && tn.Pkg() != nil && tn.Pkg().Path() == importPath && tn.Name() == name
|
typeName := n.Obj()
|
||||||
|
return typeName != nil && typeName.Pkg() != nil && typeName.Pkg().Path() == importPath && typeName.Name() == name
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ func (u *UncheckedTypeAssertionRule) Apply(file *lint.File, args lint.Arguments)
|
|||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
|
||||||
walker := &lintUnchekedTypeAssertion{
|
walker := &lintUncheckedTypeAssertion{
|
||||||
onFailure: func(failure lint.Failure) {
|
onFailure: func(failure lint.Failure) {
|
||||||
failures = append(failures, failure)
|
failures = append(failures, failure)
|
||||||
},
|
},
|
||||||
@ -71,7 +71,7 @@ func (*UncheckedTypeAssertionRule) Name() string {
|
|||||||
return "unchecked-type-assertion"
|
return "unchecked-type-assertion"
|
||||||
}
|
}
|
||||||
|
|
||||||
type lintUnchekedTypeAssertion struct {
|
type lintUncheckedTypeAssertion struct {
|
||||||
onFailure func(lint.Failure)
|
onFailure func(lint.Failure)
|
||||||
acceptIgnoredTypeAssertionResult bool
|
acceptIgnoredTypeAssertionResult bool
|
||||||
}
|
}
|
||||||
@ -89,14 +89,14 @@ func isTypeSwitch(e *ast.TypeAssertExpr) bool {
|
|||||||
return e.Type == nil
|
return e.Type == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *lintUnchekedTypeAssertion) requireNoTypeAssert(expr ast.Expr) {
|
func (w *lintUncheckedTypeAssertion) requireNoTypeAssert(expr ast.Expr) {
|
||||||
e, ok := expr.(*ast.TypeAssertExpr)
|
e, ok := expr.(*ast.TypeAssertExpr)
|
||||||
if ok && !isTypeSwitch(e) {
|
if ok && !isTypeSwitch(e) {
|
||||||
w.addFailure(e, ruleUTAMessagePanic)
|
w.addFailure(e, ruleUTAMessagePanic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *lintUnchekedTypeAssertion) handleIfStmt(n *ast.IfStmt) {
|
func (w *lintUncheckedTypeAssertion) handleIfStmt(n *ast.IfStmt) {
|
||||||
ifCondition, ok := n.Cond.(*ast.BinaryExpr)
|
ifCondition, ok := n.Cond.(*ast.BinaryExpr)
|
||||||
if ok {
|
if ok {
|
||||||
w.requireNoTypeAssert(ifCondition.X)
|
w.requireNoTypeAssert(ifCondition.X)
|
||||||
@ -104,7 +104,7 @@ func (w *lintUnchekedTypeAssertion) handleIfStmt(n *ast.IfStmt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *lintUnchekedTypeAssertion) requireBinaryExpressionWithoutTypeAssertion(expr ast.Expr) {
|
func (w *lintUncheckedTypeAssertion) requireBinaryExpressionWithoutTypeAssertion(expr ast.Expr) {
|
||||||
binaryExpr, ok := expr.(*ast.BinaryExpr)
|
binaryExpr, ok := expr.(*ast.BinaryExpr)
|
||||||
if ok {
|
if ok {
|
||||||
w.requireNoTypeAssert(binaryExpr.X)
|
w.requireNoTypeAssert(binaryExpr.X)
|
||||||
@ -112,19 +112,19 @@ func (w *lintUnchekedTypeAssertion) requireBinaryExpressionWithoutTypeAssertion(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *lintUnchekedTypeAssertion) handleCaseClause(n *ast.CaseClause) {
|
func (w *lintUncheckedTypeAssertion) handleCaseClause(n *ast.CaseClause) {
|
||||||
for _, expr := range n.List {
|
for _, expr := range n.List {
|
||||||
w.requireNoTypeAssert(expr)
|
w.requireNoTypeAssert(expr)
|
||||||
w.requireBinaryExpressionWithoutTypeAssertion(expr)
|
w.requireBinaryExpressionWithoutTypeAssertion(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *lintUnchekedTypeAssertion) handleSwitch(n *ast.SwitchStmt) {
|
func (w *lintUncheckedTypeAssertion) handleSwitch(n *ast.SwitchStmt) {
|
||||||
w.requireNoTypeAssert(n.Tag)
|
w.requireNoTypeAssert(n.Tag)
|
||||||
w.requireBinaryExpressionWithoutTypeAssertion(n.Tag)
|
w.requireBinaryExpressionWithoutTypeAssertion(n.Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *lintUnchekedTypeAssertion) handleAssignment(n *ast.AssignStmt) {
|
func (w *lintUncheckedTypeAssertion) handleAssignment(n *ast.AssignStmt) {
|
||||||
if len(n.Rhs) == 0 {
|
if len(n.Rhs) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -148,21 +148,21 @@ func (w *lintUnchekedTypeAssertion) handleAssignment(n *ast.AssignStmt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handles "return foo(.*bar)" - one of them is enough to fail as golang does not forward the type cast tuples in return statements
|
// handles "return foo(.*bar)" - one of them is enough to fail as golang does not forward the type cast tuples in return statements
|
||||||
func (w *lintUnchekedTypeAssertion) handleReturn(n *ast.ReturnStmt) {
|
func (w *lintUncheckedTypeAssertion) handleReturn(n *ast.ReturnStmt) {
|
||||||
for _, r := range n.Results {
|
for _, r := range n.Results {
|
||||||
w.requireNoTypeAssert(r)
|
w.requireNoTypeAssert(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *lintUnchekedTypeAssertion) handleRange(n *ast.RangeStmt) {
|
func (w *lintUncheckedTypeAssertion) handleRange(n *ast.RangeStmt) {
|
||||||
w.requireNoTypeAssert(n.X)
|
w.requireNoTypeAssert(n.X)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *lintUnchekedTypeAssertion) handleChannelSend(n *ast.SendStmt) {
|
func (w *lintUncheckedTypeAssertion) handleChannelSend(n *ast.SendStmt) {
|
||||||
w.requireNoTypeAssert(n.Value)
|
w.requireNoTypeAssert(n.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *lintUnchekedTypeAssertion) Visit(node ast.Node) ast.Visitor {
|
func (w *lintUncheckedTypeAssertion) Visit(node ast.Node) ast.Visitor {
|
||||||
switch n := node.(type) {
|
switch n := node.(type) {
|
||||||
case *ast.RangeStmt:
|
case *ast.RangeStmt:
|
||||||
w.handleRange(n)
|
w.handleRange(n)
|
||||||
@ -183,7 +183,7 @@ func (w *lintUnchekedTypeAssertion) Visit(node ast.Node) ast.Visitor {
|
|||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *lintUnchekedTypeAssertion) addFailure(n *ast.TypeAssertExpr, why string) {
|
func (w *lintUncheckedTypeAssertion) addFailure(n *ast.TypeAssertExpr, why string) {
|
||||||
s := fmt.Sprintf("type cast result is unchecked in %v - %s", gofmt(n), why)
|
s := fmt.Sprintf("type cast result is unchecked in %v - %s", gofmt(n), why)
|
||||||
w.onFailure(lint.Failure{
|
w.onFailure(lint.Failure{
|
||||||
Category: "bad practice",
|
Category: "bad practice",
|
||||||
|
@ -185,9 +185,10 @@ func (lintUnconditionalRecursionRule) hasControlExit(node ast.Node) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn := se.Sel.Name
|
functionName := se.Sel.Name
|
||||||
pkg := id.Name
|
pkgName := id.Name
|
||||||
if exitFunctions[pkg] != nil && exitFunctions[pkg][fn] { // it's a call to an exit function
|
isCallToExitFunction := exitFunctions[pkgName] != nil && exitFunctions[pkgName][functionName]
|
||||||
|
if isCallToExitFunction {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,12 @@ type UnhandledErrorRule struct {
|
|||||||
|
|
||||||
func (r *UnhandledErrorRule) configure(arguments lint.Arguments) {
|
func (r *UnhandledErrorRule) configure(arguments lint.Arguments) {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
if r.ignoreList == nil {
|
defer r.Unlock()
|
||||||
|
|
||||||
|
if r.ignoreList != nil {
|
||||||
|
return // already configured
|
||||||
|
}
|
||||||
|
|
||||||
for _, arg := range arguments {
|
for _, arg := range arguments {
|
||||||
argStr, ok := arg.(string)
|
argStr, ok := arg.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -38,8 +43,6 @@ func (r *UnhandledErrorRule) configure(arguments lint.Arguments) {
|
|||||||
|
|
||||||
r.ignoreList = append(r.ignoreList, exp)
|
r.ignoreList = append(r.ignoreList, exp)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
r.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply applies the rule to given file.
|
// Apply applies the rule to given file.
|
||||||
@ -130,9 +133,9 @@ func (w *lintUnhandledErrors) funcName(call *ast.CallExpr) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
name := fn.FullName()
|
name := fn.FullName()
|
||||||
name = strings.Replace(name, "(", "", -1)
|
name = strings.ReplaceAll(name, "(", "")
|
||||||
name = strings.Replace(name, ")", "", -1)
|
name = strings.ReplaceAll(name, ")", "")
|
||||||
name = strings.Replace(name, "*", "", -1)
|
name = strings.ReplaceAll(name, "*", "")
|
||||||
|
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
@ -46,13 +46,15 @@ type lintVarDeclarations struct {
|
|||||||
func (w *lintVarDeclarations) Visit(node ast.Node) ast.Visitor {
|
func (w *lintVarDeclarations) Visit(node ast.Node) ast.Visitor {
|
||||||
switch v := node.(type) {
|
switch v := node.(type) {
|
||||||
case *ast.GenDecl:
|
case *ast.GenDecl:
|
||||||
if v.Tok != token.CONST && v.Tok != token.VAR {
|
isVarOrConstDeclaration := v.Tok == token.CONST || v.Tok == token.VAR
|
||||||
|
if !isVarOrConstDeclaration {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
w.lastGen = v
|
w.lastGen = v
|
||||||
return w
|
return w
|
||||||
case *ast.ValueSpec:
|
case *ast.ValueSpec:
|
||||||
if w.lastGen.Tok == token.CONST {
|
isConstDeclaration := w.lastGen.Tok == token.CONST
|
||||||
|
if isConstDeclaration {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if len(v.Names) > 1 || v.Type == nil || len(v.Values) == 0 {
|
if len(v.Names) > 1 || v.Type == nil || len(v.Values) == 0 {
|
||||||
@ -64,14 +66,14 @@ func (w *lintVarDeclarations) Visit(node ast.Node) ast.Visitor {
|
|||||||
if isIdent(v.Names[0], "_") {
|
if isIdent(v.Names[0], "_") {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// If the RHS is a zero value, suggest dropping it.
|
// If the RHS is a isZero value, suggest dropping it.
|
||||||
zero := false
|
isZero := false
|
||||||
if lit, ok := rhs.(*ast.BasicLit); ok {
|
if lit, ok := rhs.(*ast.BasicLit); ok {
|
||||||
zero = zeroLiteral[lit.Value]
|
isZero = zeroLiteral[lit.Value]
|
||||||
} else if isIdent(rhs, "nil") {
|
} else if isIdent(rhs, "nil") {
|
||||||
zero = true
|
isZero = true
|
||||||
}
|
}
|
||||||
if zero {
|
if isZero {
|
||||||
w.onFailure(lint.Failure{
|
w.onFailure(lint.Failure{
|
||||||
Confidence: 0.9,
|
Confidence: 0.9,
|
||||||
Node: rhs,
|
Node: rhs,
|
||||||
|
@ -19,9 +19,9 @@ var upperCaseConstRE = regexp.MustCompile(`^_?[A-Z][A-Z\d]*(_[A-Z\d]+)*$`)
|
|||||||
// VarNamingRule lints given else constructs.
|
// VarNamingRule lints given else constructs.
|
||||||
type VarNamingRule struct {
|
type VarNamingRule struct {
|
||||||
configured bool
|
configured bool
|
||||||
allowlist []string
|
allowList []string
|
||||||
blocklist []string
|
blockList []string
|
||||||
upperCaseConst bool // if true - allows to use UPPER_SOME_NAMES for constants
|
allowUpperCaseConst bool // if true - allows to use UPPER_SOME_NAMES for constants
|
||||||
skipPackageNameChecks bool
|
skipPackageNameChecks bool
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
@ -35,11 +35,11 @@ func (r *VarNamingRule) configure(arguments lint.Arguments) {
|
|||||||
|
|
||||||
r.configured = true
|
r.configured = true
|
||||||
if len(arguments) >= 1 {
|
if len(arguments) >= 1 {
|
||||||
r.allowlist = getList(arguments[0], "allowlist")
|
r.allowList = getList(arguments[0], "allowlist")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(arguments) >= 2 {
|
if len(arguments) >= 2 {
|
||||||
r.blocklist = getList(arguments[1], "blocklist")
|
r.blockList = getList(arguments[1], "blocklist")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(arguments) >= 3 {
|
if len(arguments) >= 3 {
|
||||||
@ -56,7 +56,7 @@ func (r *VarNamingRule) configure(arguments lint.Arguments) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid third argument to the var-naming rule. Expecting a %s of type slice, of len==1, with map, but %T", "options", asSlice[0]))
|
panic(fmt.Sprintf("Invalid third argument to the var-naming rule. Expecting a %s of type slice, of len==1, with map, but %T", "options", asSlice[0]))
|
||||||
}
|
}
|
||||||
r.upperCaseConst = fmt.Sprint(args["upperCaseConst"]) == "true"
|
r.allowUpperCaseConst = fmt.Sprint(args["upperCaseConst"]) == "true"
|
||||||
r.skipPackageNameChecks = fmt.Sprint(args["skipPackageNameChecks"]) == "true"
|
r.skipPackageNameChecks = fmt.Sprint(args["skipPackageNameChecks"]) == "true"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,12 +93,12 @@ func (r *VarNamingRule) Apply(file *lint.File, arguments lint.Arguments) []lint.
|
|||||||
walker := lintNames{
|
walker := lintNames{
|
||||||
file: file,
|
file: file,
|
||||||
fileAst: fileAst,
|
fileAst: fileAst,
|
||||||
allowlist: r.allowlist,
|
allowList: r.allowList,
|
||||||
blocklist: r.blocklist,
|
blockList: r.blockList,
|
||||||
onFailure: func(failure lint.Failure) {
|
onFailure: func(failure lint.Failure) {
|
||||||
failures = append(failures, failure)
|
failures = append(failures, failure)
|
||||||
},
|
},
|
||||||
upperCaseConst: r.upperCaseConst,
|
upperCaseConst: r.allowUpperCaseConst,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !r.skipPackageNameChecks {
|
if !r.skipPackageNameChecks {
|
||||||
@ -151,7 +151,7 @@ func (w *lintNames) check(id *ast.Ident, thing string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
should := lint.Name(id.Name, w.allowlist, w.blocklist)
|
should := lint.Name(id.Name, w.allowList, w.blockList)
|
||||||
if id.Name == should {
|
if id.Name == should {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -177,8 +177,8 @@ type lintNames struct {
|
|||||||
file *lint.File
|
file *lint.File
|
||||||
fileAst *ast.File
|
fileAst *ast.File
|
||||||
onFailure func(lint.Failure)
|
onFailure func(lint.Failure)
|
||||||
allowlist []string
|
allowList []string
|
||||||
blocklist []string
|
blockList []string
|
||||||
upperCaseConst bool
|
upperCaseConst bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ func (w lintWaitGroupByValueRule) Visit(node ast.Node) ast.Visitor {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil // skip visiting function body
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lintWaitGroupByValueRule) isWaitGroup(ft ast.Expr) bool {
|
func (lintWaitGroupByValueRule) isWaitGroup(ft ast.Expr) bool {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user