1
0
mirror of https://github.com/mgechev/revive.git synced 2025-11-25 22:12:38 +02:00

refactor: replace mutex with sync.Once for rule configuration (#1118)

This commit is contained in:
Oleksandr Redko
2024-11-15 13:03:59 +02:00
committed by GitHub
parent 7ee4500e12
commit 3378f7033b
32 changed files with 118 additions and 297 deletions

View File

@@ -36,12 +36,13 @@ type AddConstantRule struct {
allowList allowList allowList allowList
ignoreFunctions []*regexp.Regexp ignoreFunctions []*regexp.Regexp
strLitLimit int strLitLimit int
sync.Mutex
configureOnce sync.Once
} }
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *AddConstantRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *AddConstantRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
var failures []lint.Failure var failures []lint.Failure
@@ -201,9 +202,6 @@ func (w *lintAddConstantRule) isStructTag(n *ast.BasicLit) bool {
} }
func (r *AddConstantRule) configure(arguments lint.Arguments) { func (r *AddConstantRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.allowList == nil { if r.allowList == nil {
r.strLitLimit = defaultStrLitLimit r.strLitLimit = defaultStrLitLimit
r.allowList = newAllowList() r.allowList = newAllowList()

View File

@@ -11,18 +11,13 @@ import (
// ArgumentsLimitRule lints given else constructs. // ArgumentsLimitRule lints given else constructs.
type ArgumentsLimitRule struct { type ArgumentsLimitRule struct {
max int max int
sync.Mutex
configureOnce sync.Once
} }
const defaultArgumentsLimit = 8 const defaultArgumentsLimit = 8
func (r *ArgumentsLimitRule) configure(arguments lint.Arguments) { func (r *ArgumentsLimitRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.max != 0 {
return
}
if len(arguments) < 1 { if len(arguments) < 1 {
r.max = defaultArgumentsLimit r.max = defaultArgumentsLimit
return return
@@ -37,7 +32,7 @@ func (r *ArgumentsLimitRule) configure(arguments lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *ArgumentsLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *ArgumentsLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
var failures []lint.Failure var failures []lint.Failure
onFailure := func(failure lint.Failure) { onFailure := func(failure lint.Failure) {

View File

@@ -12,15 +12,14 @@ import (
// BannedCharsRule checks if a file contains banned characters. // BannedCharsRule checks if a file contains banned characters.
type BannedCharsRule struct { type BannedCharsRule struct {
bannedCharList []string bannedCharList []string
sync.Mutex
configureOnce sync.Once
} }
const bannedCharsRuleName = "banned-characters" const bannedCharsRuleName = "banned-characters"
func (r *BannedCharsRule) configure(arguments lint.Arguments) { func (r *BannedCharsRule) configure(arguments lint.Arguments) {
r.Lock() if len(arguments) > 0 {
defer r.Unlock()
if r.bannedCharList == nil && len(arguments) > 0 {
checkNumberOfArguments(1, arguments, bannedCharsRuleName) checkNumberOfArguments(1, arguments, bannedCharsRuleName)
r.bannedCharList = r.getBannedCharsList(arguments) r.bannedCharList = r.getBannedCharsList(arguments)
} }
@@ -28,7 +27,7 @@ func (r *BannedCharsRule) configure(arguments lint.Arguments) {
// Apply applied the rule to the given file. // Apply applied the rule to the given file.
func (r *BannedCharsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *BannedCharsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
var failures []lint.Failure var failures []lint.Failure
onFailure := func(failure lint.Failure) { onFailure := func(failure lint.Failure) {

View File

@@ -13,18 +13,13 @@ import (
// CognitiveComplexityRule lints given else constructs. // CognitiveComplexityRule lints given else constructs.
type CognitiveComplexityRule struct { type CognitiveComplexityRule struct {
maxComplexity int maxComplexity int
sync.Mutex
configureOnce sync.Once
} }
const defaultMaxCognitiveComplexity = 7 const defaultMaxCognitiveComplexity = 7
func (r *CognitiveComplexityRule) configure(arguments lint.Arguments) { func (r *CognitiveComplexityRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.maxComplexity != 0 {
return // already configured
}
if len(arguments) < 1 { if len(arguments) < 1 {
r.maxComplexity = defaultMaxCognitiveComplexity r.maxComplexity = defaultMaxCognitiveComplexity
return return
@@ -40,7 +35,7 @@ func (r *CognitiveComplexityRule) configure(arguments lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *CognitiveComplexityRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *CognitiveComplexityRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
var failures []lint.Failure var failures []lint.Failure

View File

@@ -12,16 +12,11 @@ import (
// the comment symbol( // ) and the start of the comment text // the comment symbol( // ) and the start of the comment text
type CommentSpacingsRule struct { type CommentSpacingsRule struct {
allowList []string allowList []string
sync.Mutex
configureOnce sync.Once
} }
func (r *CommentSpacingsRule) configure(arguments lint.Arguments) { func (r *CommentSpacingsRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.allowList != nil {
return // already configured
}
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
@@ -34,7 +29,7 @@ func (r *CommentSpacingsRule) configure(arguments lint.Arguments) {
// Apply the rule. // Apply the rule.
func (r *CommentSpacingsRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { func (r *CommentSpacingsRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure {
r.configure(args) r.configureOnce.Do(func() { r.configure(args) })
var failures []lint.Failure var failures []lint.Failure

View File

@@ -12,22 +12,13 @@ import (
// CommentsDensityRule lints given else constructs. // CommentsDensityRule lints given else constructs.
type CommentsDensityRule struct { type CommentsDensityRule struct {
minimumCommentsDensity int64 minimumCommentsDensity int64
configured bool
sync.Mutex configureOnce sync.Once
} }
const defaultMinimumCommentsPercentage = 0 const defaultMinimumCommentsPercentage = 0
func (r *CommentsDensityRule) configure(arguments lint.Arguments) { func (r *CommentsDensityRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.configured {
return
}
r.configured = true
if len(arguments) < 1 { if len(arguments) < 1 {
r.minimumCommentsDensity = defaultMinimumCommentsPercentage r.minimumCommentsDensity = defaultMinimumCommentsPercentage
return return
@@ -42,7 +33,7 @@ func (r *CommentsDensityRule) configure(arguments lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *CommentsDensityRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *CommentsDensityRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
commentsLines := countDocLines(file.AST.Comments) commentsLines := countDocLines(file.AST.Comments)
statementsCount := countStatements(file.AST) statementsCount := countStatements(file.AST)

View File

@@ -12,32 +12,31 @@ import (
// ContextAsArgumentRule lints given else constructs. // ContextAsArgumentRule lints given else constructs.
type ContextAsArgumentRule struct { type ContextAsArgumentRule struct {
allowTypesLUT map[string]struct{} allowTypesLUT map[string]struct{}
sync.Mutex
configureOnce sync.Once
} }
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *ContextAsArgumentRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { func (r *ContextAsArgumentRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure {
r.Lock() r.configureOnce.Do(func() { r.configure(args) })
if r.allowTypesLUT == nil {
r.allowTypesLUT = getAllowTypesFromArguments(args)
}
r.Unlock()
var failures []lint.Failure var failures []lint.Failure
r.Lock()
walker := lintContextArguments{ walker := lintContextArguments{
allowTypesLUT: r.allowTypesLUT, allowTypesLUT: r.allowTypesLUT,
onFailure: func(failure lint.Failure) { onFailure: func(failure lint.Failure) {
failures = append(failures, failure) failures = append(failures, failure)
}, },
} }
r.Unlock()
ast.Walk(walker, file.AST) ast.Walk(walker, file.AST)
return failures return failures
} }
func (r *ContextAsArgumentRule) configure(arguments lint.Arguments) {
r.allowTypesLUT = getAllowTypesFromArguments(arguments)
}
// Name returns the rule name. // Name returns the rule name.
func (*ContextAsArgumentRule) Name() string { func (*ContextAsArgumentRule) Name() string {
return "context-as-argument" return "context-as-argument"

View File

@@ -14,18 +14,13 @@ import (
// CyclomaticRule lints given else constructs. // CyclomaticRule lints given else constructs.
type CyclomaticRule struct { type CyclomaticRule struct {
maxComplexity int maxComplexity int
sync.Mutex
configureOnce sync.Once
} }
const defaultMaxCyclomaticComplexity = 10 const defaultMaxCyclomaticComplexity = 10
func (r *CyclomaticRule) configure(arguments lint.Arguments) { func (r *CyclomaticRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.maxComplexity != 0 {
return // already configured
}
if len(arguments) < 1 { if len(arguments) < 1 {
r.maxComplexity = defaultMaxCyclomaticComplexity r.maxComplexity = defaultMaxCyclomaticComplexity
return return
@@ -40,7 +35,7 @@ func (r *CyclomaticRule) configure(arguments lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *CyclomaticRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *CyclomaticRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
var failures []lint.Failure var failures []lint.Failure
fileAst := file.AST fileAst := file.AST

View File

@@ -11,22 +11,17 @@ import (
// DeferRule lints unused params in functions. // DeferRule lints unused params in functions.
type DeferRule struct { type DeferRule struct {
allow map[string]bool allow map[string]bool
sync.Mutex
configureOnce sync.Once
} }
func (r *DeferRule) configure(arguments lint.Arguments) { func (r *DeferRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.allow != nil {
return // already configured
}
r.allow = r.allowFromArgs(arguments) r.allow = r.allowFromArgs(arguments)
} }
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *DeferRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *DeferRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
var failures []lint.Failure var failures []lint.Failure
onFailure := func(failure lint.Failure) { onFailure := func(failure lint.Failure) {

View File

@@ -10,13 +10,14 @@ import (
// DotImportsRule lints given else constructs. // DotImportsRule lints given else constructs.
type DotImportsRule struct { type DotImportsRule struct {
sync.Mutex
allowedPackages allowPackages allowedPackages allowPackages
configureOnce sync.Once
} }
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *DotImportsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *DotImportsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
var failures []lint.Failure var failures []lint.Failure
@@ -41,13 +42,6 @@ func (*DotImportsRule) Name() string {
} }
func (r *DotImportsRule) configure(arguments lint.Arguments) { func (r *DotImportsRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.allowedPackages != nil {
return
}
r.allowedPackages = make(allowPackages) r.allowedPackages = make(allowPackages)
if len(arguments) == 0 { if len(arguments) == 0 {
return return

View File

@@ -39,20 +39,12 @@ func mapStyleFromString(s string) (enforceMapStyleType, error) {
// EnforceMapStyleRule implements a rule to enforce `make(map[type]type)` over `map[type]type{}`. // EnforceMapStyleRule implements a rule to enforce `make(map[type]type)` over `map[type]type{}`.
type EnforceMapStyleRule struct { type EnforceMapStyleRule struct {
configured bool
enforceMapStyle enforceMapStyleType enforceMapStyle enforceMapStyleType
sync.Mutex
configureOnce sync.Once
} }
func (r *EnforceMapStyleRule) configure(arguments lint.Arguments) { func (r *EnforceMapStyleRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.configured {
return
}
r.configured = true
if len(arguments) < 1 { if len(arguments) < 1 {
r.enforceMapStyle = enforceMapStyleTypeAny r.enforceMapStyle = enforceMapStyleTypeAny
return return
@@ -72,7 +64,7 @@ func (r *EnforceMapStyleRule) configure(arguments lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *EnforceMapStyleRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *EnforceMapStyleRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
if r.enforceMapStyle == enforceMapStyleTypeAny { if r.enforceMapStyle == enforceMapStyleTypeAny {
// this linter is not configured // this linter is not configured

View File

@@ -41,22 +41,13 @@ func repeatedArgTypeStyleFromString(s string) enforceRepeatedArgTypeStyleType {
// EnforceRepeatedArgTypeStyleRule implements a rule to enforce repeated argument type style. // EnforceRepeatedArgTypeStyleRule implements a rule to enforce repeated argument type style.
type EnforceRepeatedArgTypeStyleRule struct { type EnforceRepeatedArgTypeStyleRule struct {
configured bool
funcArgStyle enforceRepeatedArgTypeStyleType funcArgStyle enforceRepeatedArgTypeStyleType
funcRetValStyle enforceRepeatedArgTypeStyleType funcRetValStyle enforceRepeatedArgTypeStyleType
sync.Mutex configureOnce sync.Once
} }
func (r *EnforceRepeatedArgTypeStyleRule) configure(arguments lint.Arguments) { func (r *EnforceRepeatedArgTypeStyleRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.configured {
return
}
r.configured = true
r.funcArgStyle = enforceRepeatedArgTypeStyleTypeAny r.funcArgStyle = enforceRepeatedArgTypeStyleTypeAny
r.funcRetValStyle = enforceRepeatedArgTypeStyleTypeAny r.funcRetValStyle = enforceRepeatedArgTypeStyleTypeAny
@@ -94,7 +85,7 @@ func (r *EnforceRepeatedArgTypeStyleRule) configure(arguments lint.Arguments) {
// Apply applies the rule to a given file. // Apply applies the rule to a given file.
func (r *EnforceRepeatedArgTypeStyleRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *EnforceRepeatedArgTypeStyleRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
if r.funcArgStyle == enforceRepeatedArgTypeStyleTypeAny && r.funcRetValStyle == enforceRepeatedArgTypeStyleTypeAny { if r.funcArgStyle == enforceRepeatedArgTypeStyleTypeAny && r.funcRetValStyle == enforceRepeatedArgTypeStyleTypeAny {
// This linter is not configured, return no failures. // This linter is not configured, return no failures.

View File

@@ -43,20 +43,12 @@ func sliceStyleFromString(s string) (enforceSliceStyleType, error) {
// EnforceSliceStyleRule implements a rule to enforce `make([]type)` over `[]type{}`. // EnforceSliceStyleRule implements a rule to enforce `make([]type)` over `[]type{}`.
type EnforceSliceStyleRule struct { type EnforceSliceStyleRule struct {
configured bool
enforceSliceStyle enforceSliceStyleType enforceSliceStyle enforceSliceStyleType
sync.Mutex
configureOnce sync.Once
} }
func (r *EnforceSliceStyleRule) configure(arguments lint.Arguments) { func (r *EnforceSliceStyleRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.configured {
return
}
r.configured = true
if len(arguments) < 1 { if len(arguments) < 1 {
r.enforceSliceStyle = enforceSliceStyleTypeAny r.enforceSliceStyle = enforceSliceStyleTypeAny
return return
@@ -76,7 +68,7 @@ func (r *EnforceSliceStyleRule) configure(arguments lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *EnforceSliceStyleRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *EnforceSliceStyleRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
if r.enforceSliceStyle == enforceSliceStyleTypeAny { if r.enforceSliceStyle == enforceSliceStyleTypeAny {
// this linter is not configured // this linter is not configured

View File

@@ -15,17 +15,11 @@ import (
// ErrorStringsRule lints given else constructs. // ErrorStringsRule lints given else constructs.
type ErrorStringsRule struct { type ErrorStringsRule struct {
errorFunctions map[string]map[string]struct{} errorFunctions map[string]map[string]struct{}
sync.Mutex
configureOnce sync.Once
} }
func (r *ErrorStringsRule) configure(arguments lint.Arguments) { func (r *ErrorStringsRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.errorFunctions != nil {
return
}
r.errorFunctions = map[string]map[string]struct{}{ r.errorFunctions = map[string]map[string]struct{}{
"fmt": { "fmt": {
"Errorf": {}, "Errorf": {},
@@ -60,7 +54,7 @@ func (r *ErrorStringsRule) configure(arguments lint.Arguments) {
func (r *ErrorStringsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *ErrorStringsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
var failures []lint.Failure var failures []lint.Failure
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
fileAst := file.AST fileAst := file.AST
walker := lintErrorStrings{ walker := lintErrorStrings{

View File

@@ -55,20 +55,13 @@ func (dc *disabledChecks) isDisabled(checkName string) bool {
// ExportedRule lints given else constructs. // ExportedRule lints given else constructs.
type ExportedRule struct { type ExportedRule struct {
configured bool
stuttersMsg string stuttersMsg string
disabledChecks disabledChecks disabledChecks disabledChecks
sync.Mutex
configureOnce sync.Once
} }
func (r *ExportedRule) configure(arguments lint.Arguments) { func (r *ExportedRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.configured {
return
}
r.configured = true
r.disabledChecks = disabledChecks{PrivateReceivers: true, PublicInterfaces: true} r.disabledChecks = disabledChecks{PrivateReceivers: true, PublicInterfaces: true}
r.stuttersMsg = "stutters" r.stuttersMsg = "stutters"
for _, flag := range arguments { for _, flag := range arguments {
@@ -104,7 +97,7 @@ func (r *ExportedRule) configure(arguments lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *ExportedRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { func (r *ExportedRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure {
r.configure(args) r.configureOnce.Do(func() { r.configure(args) })
var failures []lint.Failure var failures []lint.Failure
if file.IsTest() { if file.IsTest() {

View File

@@ -11,7 +11,8 @@ import (
// FileHeaderRule lints given else constructs. // FileHeaderRule lints given else constructs.
type FileHeaderRule struct { type FileHeaderRule struct {
header string header string
sync.Mutex
configureOnce sync.Once
} }
var ( var (
@@ -20,12 +21,6 @@ var (
) )
func (r *FileHeaderRule) configure(arguments lint.Arguments) { func (r *FileHeaderRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.header != "" {
return // already configured
}
if len(arguments) < 1 { if len(arguments) < 1 {
return return
} }
@@ -39,7 +34,7 @@ func (r *FileHeaderRule) configure(arguments lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *FileHeaderRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *FileHeaderRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
if r.header == "" { if r.header == "" {
return nil return nil

View File

@@ -20,12 +20,13 @@ type FileLengthLimitRule struct {
skipComments bool skipComments bool
// skipBlankLines indicates whether to skip blank lines when counting lines. // skipBlankLines indicates whether to skip blank lines when counting lines.
skipBlankLines bool skipBlankLines bool
sync.Mutex
configureOnce sync.Once
} }
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *FileLengthLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *FileLengthLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
if r.max <= 0 { if r.max <= 0 {
// when max is negative or 0 the rule is disabled // when max is negative or 0 the rule is disabled
@@ -75,13 +76,6 @@ func (r *FileLengthLimitRule) Apply(file *lint.File, arguments lint.Arguments) [
} }
func (r *FileLengthLimitRule) configure(arguments lint.Arguments) { func (r *FileLengthLimitRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.max != 0 {
return // already configured
}
if len(arguments) < 1 { if len(arguments) < 1 {
return // use default return // use default
} }

View File

@@ -13,12 +13,13 @@ import (
// FilenameFormatRule lints source filenames according to a set of regular expressions given as arguments // FilenameFormatRule lints source filenames according to a set of regular expressions given as arguments
type FilenameFormatRule struct { type FilenameFormatRule struct {
format *regexp.Regexp format *regexp.Regexp
sync.Mutex
configureOnce sync.Once
} }
// Apply applies the rule to the given file. // Apply applies the rule to the given file.
func (r *FilenameFormatRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *FilenameFormatRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
filename := filepath.Base(file.Name) filename := filepath.Base(file.Name)
if r.format.MatchString(filename) { if r.format.MatchString(filename) {
@@ -55,13 +56,6 @@ func (*FilenameFormatRule) Name() string {
var defaultFormat = regexp.MustCompile("^[_A-Za-z0-9][_A-Za-z0-9-]*.go$") var defaultFormat = regexp.MustCompile("^[_A-Za-z0-9][_A-Za-z0-9-]*.go$")
func (r *FilenameFormatRule) configure(arguments lint.Arguments) { func (r *FilenameFormatRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.format != nil {
return
}
argsCount := len(arguments) argsCount := len(arguments)
if argsCount == 0 { if argsCount == 0 {
r.format = defaultFormat r.format = defaultFormat

View File

@@ -11,20 +11,13 @@ import (
// FunctionLength lint. // FunctionLength lint.
type FunctionLength struct { type FunctionLength struct {
maxStmt int maxStmt int
maxLines int maxLines int
configured bool
sync.Mutex configureOnce sync.Once
} }
func (r *FunctionLength) configure(arguments lint.Arguments) { func (r *FunctionLength) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
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)
@@ -32,7 +25,7 @@ func (r *FunctionLength) configure(arguments lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *FunctionLength) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *FunctionLength) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
var failures []lint.Failure var failures []lint.Failure

View File

@@ -11,18 +11,13 @@ import (
// FunctionResultsLimitRule lints given else constructs. // FunctionResultsLimitRule lints given else constructs.
type FunctionResultsLimitRule struct { type FunctionResultsLimitRule struct {
max int max int
sync.Mutex
configureOnce sync.Once
} }
const defaultResultsLimit = 3 const defaultResultsLimit = 3
func (r *FunctionResultsLimitRule) configure(arguments lint.Arguments) { func (r *FunctionResultsLimitRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.max != 0 {
return // already configured
}
if len(arguments) < 1 { if len(arguments) < 1 {
r.max = defaultResultsLimit r.max = defaultResultsLimit
return return
@@ -41,7 +36,7 @@ func (r *FunctionResultsLimitRule) configure(arguments lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *FunctionResultsLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *FunctionResultsLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
var failures []lint.Failure var failures []lint.Failure

View File

@@ -10,10 +10,10 @@ import (
// ImportAliasNamingRule lints import alias naming. // ImportAliasNamingRule lints import alias naming.
type ImportAliasNamingRule struct { type ImportAliasNamingRule struct {
configured bool
allowRegexp *regexp.Regexp allowRegexp *regexp.Regexp
denyRegexp *regexp.Regexp denyRegexp *regexp.Regexp
sync.Mutex
configureOnce sync.Once
} }
const defaultImportAliasNamingAllowRule = "^[a-z][a-z0-9]{0,}$" const defaultImportAliasNamingAllowRule = "^[a-z][a-z0-9]{0,}$"
@@ -21,12 +21,6 @@ const defaultImportAliasNamingAllowRule = "^[a-z][a-z0-9]{0,}$"
var defaultImportAliasNamingAllowRegexp = regexp.MustCompile(defaultImportAliasNamingAllowRule) var defaultImportAliasNamingAllowRegexp = regexp.MustCompile(defaultImportAliasNamingAllowRule)
func (r *ImportAliasNamingRule) configure(arguments lint.Arguments) { func (r *ImportAliasNamingRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.configured {
return
}
if len(arguments) == 0 { if len(arguments) == 0 {
r.allowRegexp = defaultImportAliasNamingAllowRegexp r.allowRegexp = defaultImportAliasNamingAllowRegexp
return return
@@ -57,7 +51,7 @@ func (r *ImportAliasNamingRule) configure(arguments lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *ImportAliasNamingRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *ImportAliasNamingRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
var failures []lint.Failure var failures []lint.Failure

View File

@@ -11,29 +11,24 @@ import (
// ImportsBlocklistRule lints given else constructs. // ImportsBlocklistRule lints given else constructs.
type ImportsBlocklistRule struct { type ImportsBlocklistRule struct {
blocklist []*regexp.Regexp blocklist []*regexp.Regexp
sync.Mutex
configureOnce sync.Once
} }
var replaceImportRegexp = regexp.MustCompile(`/?\*\*/?`) var replaceImportRegexp = regexp.MustCompile(`/?\*\*/?`)
func (r *ImportsBlocklistRule) configure(arguments lint.Arguments) { func (r *ImportsBlocklistRule) configure(arguments lint.Arguments) {
r.Lock() r.blocklist = []*regexp.Regexp{}
defer r.Unlock() for _, arg := range arguments {
argStr, ok := arg.(string)
if r.blocklist == nil { if !ok {
r.blocklist = make([]*regexp.Regexp, 0) panic(fmt.Sprintf("Invalid argument to the imports-blocklist rule. Expecting a string, got %T", arg))
for _, arg := range arguments {
argStr, ok := arg.(string)
if !ok {
panic(fmt.Sprintf("Invalid argument to the imports-blocklist rule. Expecting a string, got %T", arg))
}
regStr, err := regexp.Compile(fmt.Sprintf(`(?m)"%s"$`, replaceImportRegexp.ReplaceAllString(argStr, `(\W|\w)*`)))
if err != nil {
panic(fmt.Sprintf("Invalid argument to the imports-blocklist rule. Expecting %q to be a valid regular expression, got: %v", argStr, err))
}
r.blocklist = append(r.blocklist, regStr)
} }
regStr, err := regexp.Compile(fmt.Sprintf(`(?m)"%s"$`, replaceImportRegexp.ReplaceAllString(argStr, `(\W|\w)*`)))
if err != nil {
panic(fmt.Sprintf("Invalid argument to the imports-blocklist rule. Expecting %q to be a valid regular expression, got: %v", argStr, err))
}
r.blocklist = append(r.blocklist, regStr)
} }
} }
@@ -48,7 +43,7 @@ func (r *ImportsBlocklistRule) isBlocklisted(path string) bool {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *ImportsBlocklistRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *ImportsBlocklistRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
var failures []lint.Failure var failures []lint.Failure

View File

@@ -15,18 +15,13 @@ import (
// LineLengthLimitRule lints given else constructs. // LineLengthLimitRule lints given else constructs.
type LineLengthLimitRule struct { type LineLengthLimitRule struct {
max int max int
sync.Mutex
configureOnce sync.Once
} }
const defaultLineLengthLimit = 80 const defaultLineLengthLimit = 80
func (r *LineLengthLimitRule) configure(arguments lint.Arguments) { func (r *LineLengthLimitRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.max != 0 {
return // already configured
}
if len(arguments) < 1 { if len(arguments) < 1 {
r.max = defaultLineLengthLimit r.max = defaultLineLengthLimit
return return
@@ -42,7 +37,7 @@ func (r *LineLengthLimitRule) configure(arguments lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *LineLengthLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *LineLengthLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
var failures []lint.Failure var failures []lint.Failure

View File

@@ -11,14 +11,15 @@ import (
// MaxControlNestingRule lints given else constructs. // MaxControlNestingRule lints given else constructs.
type MaxControlNestingRule struct { type MaxControlNestingRule struct {
max int64 max int64
sync.Mutex
configureOnce sync.Once
} }
const defaultMaxControlNesting = 5 const defaultMaxControlNesting = 5
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *MaxControlNestingRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *MaxControlNestingRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
var failures []lint.Failure var failures []lint.Failure
@@ -107,12 +108,6 @@ func (w *lintMaxControlNesting) walkControlledBlock(b ast.Node) {
} }
func (r *MaxControlNestingRule) configure(arguments lint.Arguments) { func (r *MaxControlNestingRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if !(r.max < 1) {
return // max already configured
}
if len(arguments) < 1 { if len(arguments) < 1 {
r.max = defaultMaxControlNesting r.max = defaultMaxControlNesting
return return

View File

@@ -12,18 +12,13 @@ import (
// MaxPublicStructsRule lints given else constructs. // MaxPublicStructsRule lints given else constructs.
type MaxPublicStructsRule struct { type MaxPublicStructsRule struct {
max int64 max int64
sync.Mutex
configureOnce sync.Once
} }
const defaultMaxPublicStructs = 5 const defaultMaxPublicStructs = 5
func (r *MaxPublicStructsRule) configure(arguments lint.Arguments) { func (r *MaxPublicStructsRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.max != 0 {
return // already configured
}
if len(arguments) < 1 { if len(arguments) < 1 {
r.max = defaultMaxPublicStructs r.max = defaultMaxPublicStructs
return return
@@ -40,7 +35,7 @@ func (r *MaxPublicStructsRule) configure(arguments lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *MaxPublicStructsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *MaxPublicStructsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
var failures []lint.Failure var failures []lint.Failure

View File

@@ -12,18 +12,13 @@ import (
// ReceiverNamingRule lints given else constructs. // ReceiverNamingRule lints given else constructs.
type ReceiverNamingRule struct { type ReceiverNamingRule struct {
receiverNameMaxLength int receiverNameMaxLength int
sync.Mutex
configureOnce sync.Once
} }
const defaultReceiverNameMaxLength = -1 // thus will not check const defaultReceiverNameMaxLength = -1 // thus will not check
func (r *ReceiverNamingRule) configure(arguments lint.Arguments) { func (r *ReceiverNamingRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.receiverNameMaxLength != 0 {
return
}
r.receiverNameMaxLength = defaultReceiverNameMaxLength r.receiverNameMaxLength = defaultReceiverNameMaxLength
if len(arguments) < 1 { if len(arguments) < 1 {
return return
@@ -50,7 +45,7 @@ func (r *ReceiverNamingRule) configure(arguments lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *ReceiverNamingRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { func (r *ReceiverNamingRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure {
r.configure(args) r.configureOnce.Do(func() { r.configure(args) })
var failures []lint.Failure var failures []lint.Failure

View File

@@ -14,15 +14,12 @@ import (
// StructTagRule lints struct tags. // StructTagRule lints struct tags.
type StructTagRule struct { type StructTagRule struct {
userDefined map[string][]string // map: key -> []option userDefined map[string][]string // map: key -> []option
sync.Mutex
configureOnce sync.Once
} }
func (r *StructTagRule) configure(arguments lint.Arguments) { func (r *StructTagRule) configure(arguments lint.Arguments) {
r.Lock() if len(arguments) == 0 {
defer r.Unlock()
mustConfigure := r.userDefined == nil && len(arguments) > 0
if !mustConfigure {
return return
} }
@@ -47,7 +44,7 @@ func (r *StructTagRule) configure(arguments lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *StructTagRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { func (r *StructTagRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure {
r.configure(args) r.configureOnce.Do(func() { r.configure(args) })
var failures []lint.Failure var failures []lint.Failure
onFailure := func(failure lint.Failure) { onFailure := func(failure lint.Failure) {

View File

@@ -15,21 +15,16 @@ const (
// UncheckedTypeAssertionRule lints missing or ignored `ok`-value in dynamic type casts. // UncheckedTypeAssertionRule lints missing or ignored `ok`-value in dynamic type casts.
type UncheckedTypeAssertionRule struct { type UncheckedTypeAssertionRule struct {
sync.Mutex
acceptIgnoredAssertionResult bool acceptIgnoredAssertionResult bool
configured bool
configureOnce sync.Once
} }
func (u *UncheckedTypeAssertionRule) configure(arguments lint.Arguments) { func (r *UncheckedTypeAssertionRule) configure(arguments lint.Arguments) {
u.Lock() if len(arguments) == 0 {
defer u.Unlock()
if len(arguments) == 0 || u.configured {
return return
} }
u.configured = true
args, ok := arguments[0].(map[string]any) args, ok := arguments[0].(map[string]any)
if !ok { if !ok {
panic("Unable to get arguments. Expected object of key-value-pairs.") panic("Unable to get arguments. Expected object of key-value-pairs.")
@@ -38,7 +33,7 @@ func (u *UncheckedTypeAssertionRule) configure(arguments lint.Arguments) {
for k, v := range args { for k, v := range args {
switch k { switch k {
case "acceptIgnoredAssertionResult": case "acceptIgnoredAssertionResult":
u.acceptIgnoredAssertionResult, ok = v.(bool) r.acceptIgnoredAssertionResult, ok = v.(bool)
if !ok { if !ok {
panic(fmt.Sprintf("Unable to parse argument '%s'. Expected boolean.", k)) panic(fmt.Sprintf("Unable to parse argument '%s'. Expected boolean.", k))
} }
@@ -49,8 +44,8 @@ func (u *UncheckedTypeAssertionRule) configure(arguments lint.Arguments) {
} }
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (u *UncheckedTypeAssertionRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { func (r *UncheckedTypeAssertionRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure {
u.configure(args) r.configureOnce.Do(func() { r.configure(args) })
var failures []lint.Failure var failures []lint.Failure
@@ -58,7 +53,7 @@ func (u *UncheckedTypeAssertionRule) Apply(file *lint.File, args lint.Arguments)
onFailure: func(failure lint.Failure) { onFailure: func(failure lint.Failure) {
failures = append(failures, failure) failures = append(failures, failure)
}, },
acceptIgnoredTypeAssertionResult: u.acceptIgnoredAssertionResult, acceptIgnoredTypeAssertionResult: r.acceptIgnoredAssertionResult,
} }
ast.Walk(walker, file.AST) ast.Walk(walker, file.AST)

View File

@@ -14,17 +14,11 @@ import (
// UnhandledErrorRule lints given else constructs. // UnhandledErrorRule lints given else constructs.
type UnhandledErrorRule struct { type UnhandledErrorRule struct {
ignoreList []*regexp.Regexp ignoreList []*regexp.Regexp
sync.Mutex
configureOnce sync.Once
} }
func (r *UnhandledErrorRule) configure(arguments lint.Arguments) { func (r *UnhandledErrorRule) configure(arguments lint.Arguments) {
r.Lock()
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 {
@@ -47,7 +41,7 @@ func (r *UnhandledErrorRule) configure(arguments lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *UnhandledErrorRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { func (r *UnhandledErrorRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure {
r.configure(args) r.configureOnce.Do(func() { r.configure(args) })
var failures []lint.Failure var failures []lint.Failure

View File

@@ -11,22 +11,14 @@ import (
// UnusedParamRule lints unused params in functions. // UnusedParamRule lints unused params in functions.
type UnusedParamRule struct { type UnusedParamRule struct {
configured bool
// regex to check if some name is valid for unused parameter, "^_$" by default // regex to check if some name is valid for unused parameter, "^_$" by default
allowRegex *regexp.Regexp allowRegex *regexp.Regexp
failureMsg string failureMsg string
sync.Mutex
configureOnce sync.Once
} }
func (r *UnusedParamRule) configure(args lint.Arguments) { func (r *UnusedParamRule) configure(args lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.configured {
return
}
r.configured = true
// while by default args is an array, i think it's good to provide structures inside it by default, not arrays or primitives // while by default args is an array, i think it's good to provide structures inside it by default, not arrays or primitives
// it's more compatible to JSON nature of configurations // it's more compatible to JSON nature of configurations
var allowedRegexStr string var allowedRegexStr string
@@ -58,7 +50,7 @@ func (r *UnusedParamRule) configure(args lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *UnusedParamRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { func (r *UnusedParamRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure {
r.configure(args) r.configureOnce.Do(func() { r.configure(args) })
var failures []lint.Failure var failures []lint.Failure
onFailure := func(failure lint.Failure) { onFailure := func(failure lint.Failure) {

View File

@@ -11,22 +11,14 @@ import (
// UnusedReceiverRule lints unused params in functions. // UnusedReceiverRule lints unused params in functions.
type UnusedReceiverRule struct { type UnusedReceiverRule struct {
configured bool
// regex to check if some name is valid for unused parameter, "^_$" by default // regex to check if some name is valid for unused parameter, "^_$" by default
allowRegex *regexp.Regexp allowRegex *regexp.Regexp
failureMsg string failureMsg string
sync.Mutex
configureOnce sync.Once
} }
func (r *UnusedReceiverRule) configure(args lint.Arguments) { func (r *UnusedReceiverRule) configure(args lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.configured {
return
}
r.configured = true
// while by default args is an array, i think it's good to provide structures inside it by default, not arrays or primitives // while by default args is an array, i think it's good to provide structures inside it by default, not arrays or primitives
// it's more compatible to JSON nature of configurations // it's more compatible to JSON nature of configurations
var allowedRegexStr string var allowedRegexStr string
@@ -57,7 +49,7 @@ func (r *UnusedReceiverRule) configure(args lint.Arguments) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *UnusedReceiverRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure { func (r *UnusedReceiverRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure {
r.configure(args) r.configureOnce.Do(func() { r.configure(args) })
var failures []lint.Failure var failures []lint.Failure
onFailure := func(failure lint.Failure) { onFailure := func(failure lint.Failure) {

View File

@@ -18,22 +18,15 @@ 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
allowList []string allowList []string
blockList []string blockList []string
allowUpperCaseConst 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
configureOnce sync.Once
} }
func (r *VarNamingRule) configure(arguments lint.Arguments) { func (r *VarNamingRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if r.configured {
return
}
r.configured = true
if len(arguments) >= 1 { if len(arguments) >= 1 {
r.allowList = getList(arguments[0], "allowlist") r.allowList = getList(arguments[0], "allowlist")
} }
@@ -83,7 +76,7 @@ func (r *VarNamingRule) applyPackageCheckRules(walker *lintNames) {
// Apply applies the rule to given file. // Apply applies the rule to given file.
func (r *VarNamingRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { func (r *VarNamingRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
r.configure(arguments) r.configureOnce.Do(func() { r.configure(arguments) })
var failures []lint.Failure var failures []lint.Failure