mirror of
https://github.com/mgechev/revive.git
synced 2024-12-12 10:44:59 +02:00
refactor: replace panic with error in rules (#1126)
Co-authored-by: chavacava <salvadorcavadini+github@gmail.com> Co-authored-by: Oleksandr Redko <oleksandr.red+github@gmail.com>
This commit is contained in:
parent
10d9697cc2
commit
9b15f3fcb6
@ -106,7 +106,7 @@ func (l *Linter) Lint(packages [][]string, ruleSet []Rule, config Config) (<-cha
|
|||||||
for n := range packages {
|
for n := range packages {
|
||||||
go func(pkg []string, gover *goversion.Version) {
|
go func(pkg []string, gover *goversion.Version) {
|
||||||
if err := l.lintPackage(pkg, gover, ruleSet, config, failures); err != nil {
|
if err := l.lintPackage(pkg, gover, ruleSet, config, failures); err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, "error during linting: "+err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package rule
|
package rule
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -45,7 +46,7 @@ func (r *AddConstantRule) Apply(file *lint.File, arguments lint.Arguments) []lin
|
|||||||
var configureErr error
|
var configureErr error
|
||||||
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
if configureErr != nil {
|
if configureErr != nil {
|
||||||
return []lint.Failure{lint.NewInternalFailure(configureErr.Error())}
|
return newInternalFailureError(configureErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
@ -232,35 +233,35 @@ func (r *AddConstantRule) configure(arguments lint.Arguments) error {
|
|||||||
}
|
}
|
||||||
list, ok := v.(string)
|
list, ok := v.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Errorf("invalid argument to the add-constant rule, string expected. Got '%v' (%T)", v, v)
|
return fmt.Errorf("invalid argument to the add-constant rule, string expected. Got '%v' (%T)", v, v)
|
||||||
}
|
}
|
||||||
r.allowList.add(kind, list)
|
r.allowList.add(kind, list)
|
||||||
case "maxLitCount":
|
case "maxLitCount":
|
||||||
sl, ok := v.(string)
|
sl, ok := v.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Errorf("invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v' (%T)", v, v)
|
return fmt.Errorf("invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v' (%T)", v, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
limit, err := strconv.Atoi(sl)
|
limit, err := strconv.Atoi(sl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Errorf("invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v'", v)
|
return fmt.Errorf("invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v'", v)
|
||||||
}
|
}
|
||||||
r.strLitLimit = limit
|
r.strLitLimit = limit
|
||||||
case "ignoreFuncs":
|
case "ignoreFuncs":
|
||||||
excludes, ok := v.(string)
|
excludes, ok := v.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Errorf("invalid argument to the ignoreFuncs parameter of add-constant rule, string expected. Got '%v' (%T)", v, v)
|
return fmt.Errorf("invalid argument to the ignoreFuncs parameter of add-constant rule, string expected. Got '%v' (%T)", v, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, exclude := range strings.Split(excludes, ",") {
|
for _, exclude := range strings.Split(excludes, ",") {
|
||||||
exclude = strings.Trim(exclude, " ")
|
exclude = strings.Trim(exclude, " ")
|
||||||
if exclude == "" {
|
if exclude == "" {
|
||||||
fmt.Errorf("invalid argument to the ignoreFuncs parameter of add-constant rule, expected regular expression must not be empty.")
|
return errors.New("invalid argument to the ignoreFuncs parameter of add-constant rule, expected regular expression must not be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
exp, err := regexp.Compile(exclude)
|
exp, err := regexp.Compile(exclude)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Errorf("invalid argument to the ignoreFuncs parameter of add-constant rule: regexp %q does not compile: %v", exclude, err)
|
return fmt.Errorf("invalid argument to the ignoreFuncs parameter of add-constant rule: regexp %q does not compile: %w", exclude, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.ignoreFunctions = append(r.ignoreFunctions, exp)
|
r.ignoreFunctions = append(r.ignoreFunctions, exp)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package rule
|
package rule
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"sync"
|
"sync"
|
||||||
@ -17,22 +18,28 @@ type ArgumentsLimitRule struct {
|
|||||||
|
|
||||||
const defaultArgumentsLimit = 8
|
const defaultArgumentsLimit = 8
|
||||||
|
|
||||||
func (r *ArgumentsLimitRule) configure(arguments lint.Arguments) {
|
func (r *ArgumentsLimitRule) configure(arguments lint.Arguments) error {
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
r.max = defaultArgumentsLimit
|
r.max = defaultArgumentsLimit
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
maxArguments, ok := arguments[0].(int64) // Alt. non panicking version
|
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`)
|
return errors.New(`invalid value passed as argument number to the "argument-limit" rule`)
|
||||||
}
|
}
|
||||||
r.max = int(maxArguments)
|
r.max = int(maxArguments)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
|
||||||
|
@ -18,16 +18,30 @@ type BannedCharsRule struct {
|
|||||||
|
|
||||||
const bannedCharsRuleName = "banned-characters"
|
const bannedCharsRuleName = "banned-characters"
|
||||||
|
|
||||||
func (r *BannedCharsRule) configure(arguments lint.Arguments) {
|
func (r *BannedCharsRule) configure(arguments lint.Arguments) error {
|
||||||
if len(arguments) > 0 {
|
if len(arguments) > 0 {
|
||||||
checkNumberOfArguments(1, arguments, bannedCharsRuleName)
|
err := checkNumberOfArguments(1, arguments, bannedCharsRuleName)
|
||||||
r.bannedCharList = r.getBannedCharsList(arguments)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
list, err := r.getBannedCharsList(arguments)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
r.bannedCharList = list
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
onFailure := func(failure lint.Failure) {
|
onFailure := func(failure lint.Failure) {
|
||||||
@ -49,17 +63,17 @@ func (*BannedCharsRule) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getBannedCharsList converts arguments into the banned characters list
|
// getBannedCharsList converts arguments into the banned characters list
|
||||||
func (r *BannedCharsRule) getBannedCharsList(args lint.Arguments) []string {
|
func (r *BannedCharsRule) getBannedCharsList(args lint.Arguments) ([]string, error) {
|
||||||
var bannedChars []string
|
var bannedChars []string
|
||||||
for _, char := range args {
|
for _, char := range args {
|
||||||
charStr, ok := char.(string)
|
charStr, ok := char.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid argument for the %s rule: expecting a string, got %T", r.Name(), char))
|
return nil, fmt.Errorf("invalid argument for the %s rule: expecting a string, got %T", r.Name(), char)
|
||||||
}
|
}
|
||||||
bannedChars = append(bannedChars, charStr)
|
bannedChars = append(bannedChars, charStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return bannedChars
|
return bannedChars, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type lintBannedCharsRule struct {
|
type lintBannedCharsRule struct {
|
||||||
|
@ -19,23 +19,29 @@ type CognitiveComplexityRule struct {
|
|||||||
|
|
||||||
const defaultMaxCognitiveComplexity = 7
|
const defaultMaxCognitiveComplexity = 7
|
||||||
|
|
||||||
func (r *CognitiveComplexityRule) configure(arguments lint.Arguments) {
|
func (r *CognitiveComplexityRule) configure(arguments lint.Arguments) error {
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
r.maxComplexity = defaultMaxCognitiveComplexity
|
r.maxComplexity = defaultMaxCognitiveComplexity
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
complexity, ok := arguments[0].(int64)
|
complexity, ok := arguments[0].(int64)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("invalid argument type for cognitive-complexity, expected int64, got %T", arguments[0]))
|
return fmt.Errorf("invalid argument type for cognitive-complexity, expected int64, got %T", arguments[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
r.maxComplexity = int(complexity)
|
r.maxComplexity = int(complexity)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
|
||||||
|
@ -16,20 +16,26 @@ type CommentSpacingsRule struct {
|
|||||||
configureOnce sync.Once
|
configureOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *CommentSpacingsRule) configure(arguments lint.Arguments) {
|
func (r *CommentSpacingsRule) configure(arguments lint.Arguments) error {
|
||||||
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
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("invalid argument %v for %s; expected string but got %T", arg, r.Name(), arg))
|
return fmt.Errorf("invalid argument %v for %s; expected string but got %T", arg, r.Name(), arg)
|
||||||
}
|
}
|
||||||
r.allowList = append(r.allowList, `//`+allow)
|
r.allowList = append(r.allowList, `//`+allow)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, arguments lint.Arguments) []lint.Failure {
|
||||||
r.configureOnce.Do(func() { r.configure(args) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
|
||||||
|
@ -18,23 +18,29 @@ type CommentsDensityRule struct {
|
|||||||
|
|
||||||
const defaultMinimumCommentsPercentage = 0
|
const defaultMinimumCommentsPercentage = 0
|
||||||
|
|
||||||
func (r *CommentsDensityRule) configure(arguments lint.Arguments) {
|
func (r *CommentsDensityRule) configure(arguments lint.Arguments) error {
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
r.minimumCommentsDensity = defaultMinimumCommentsPercentage
|
r.minimumCommentsDensity = defaultMinimumCommentsPercentage
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var ok bool
|
var ok bool
|
||||||
r.minimumCommentsDensity, ok = arguments[0].(int64)
|
r.minimumCommentsDensity, ok = arguments[0].(int64)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("invalid argument for %q rule: argument should be an int, got %T", r.Name(), arguments[0]))
|
return fmt.Errorf("invalid argument for %q rule: argument should be an int, got %T", r.Name(), arguments[0])
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
commentsLines := countDocLines(file.AST.Comments)
|
commentsLines := countDocLines(file.AST.Comments)
|
||||||
statementsCount := countStatements(file.AST)
|
statementsCount := countStatements(file.AST)
|
||||||
density := (float32(commentsLines) / float32(statementsCount+commentsLines)) * 100
|
density := (float32(commentsLines) / float32(statementsCount+commentsLines)) * 100
|
||||||
|
@ -17,8 +17,13 @@ type ContextAsArgumentRule struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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, arguments lint.Arguments) []lint.Failure {
|
||||||
r.configureOnce.Do(func() { r.configure(args) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
for _, decl := range file.AST.Decls {
|
for _, decl := range file.AST.Decls {
|
||||||
@ -59,27 +64,32 @@ func (*ContextAsArgumentRule) Name() string {
|
|||||||
return "context-as-argument"
|
return "context-as-argument"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ContextAsArgumentRule) configure(arguments lint.Arguments) {
|
func (r *ContextAsArgumentRule) configure(arguments lint.Arguments) error {
|
||||||
r.allowTypes = r.getAllowTypesFromArguments(arguments)
|
types, err := r.getAllowTypesFromArguments(arguments)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.allowTypes = types
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ContextAsArgumentRule) getAllowTypesFromArguments(args lint.Arguments) map[string]struct{} {
|
func (r *ContextAsArgumentRule) getAllowTypesFromArguments(args lint.Arguments) (map[string]struct{}, error) {
|
||||||
allowTypesBefore := []string{}
|
allowTypesBefore := []string{}
|
||||||
if len(args) >= 1 {
|
if len(args) >= 1 {
|
||||||
argKV, ok := args[0].(map[string]any)
|
argKV, ok := args[0].(map[string]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid argument to the context-as-argument rule. Expecting a k,v map, got %T", args[0]))
|
return nil, fmt.Errorf("invalid argument to the context-as-argument rule. Expecting a k,v map, got %T", args[0])
|
||||||
}
|
}
|
||||||
for k, v := range argKV {
|
for k, v := range argKV {
|
||||||
switch k {
|
switch k {
|
||||||
case "allowTypesBefore":
|
case "allowTypesBefore":
|
||||||
typesBefore, ok := v.(string)
|
typesBefore, ok := v.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid argument to the context-as-argument.allowTypesBefore rule. Expecting a string, got %T", v))
|
return nil, fmt.Errorf("invalid argument to the context-as-argument.allowTypesBefore rule. Expecting a string, got %T", v)
|
||||||
}
|
}
|
||||||
allowTypesBefore = append(allowTypesBefore, strings.Split(typesBefore, ",")...)
|
allowTypesBefore = append(allowTypesBefore, strings.Split(typesBefore, ",")...)
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Invalid argument to the context-as-argument rule. Unrecognized key %s", k))
|
return nil, fmt.Errorf("invalid argument to the context-as-argument rule. Unrecognized key %s", k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,5 +100,5 @@ func (r *ContextAsArgumentRule) getAllowTypesFromArguments(args lint.Arguments)
|
|||||||
}
|
}
|
||||||
|
|
||||||
result["context.Context"] = struct{}{} // context.Context is always allowed before another context.Context
|
result["context.Context"] = struct{}{} // context.Context is always allowed before another context.Context
|
||||||
return result
|
return result, nil
|
||||||
}
|
}
|
||||||
|
@ -20,22 +20,28 @@ type CyclomaticRule struct {
|
|||||||
|
|
||||||
const defaultMaxCyclomaticComplexity = 10
|
const defaultMaxCyclomaticComplexity = 10
|
||||||
|
|
||||||
func (r *CyclomaticRule) configure(arguments lint.Arguments) {
|
func (r *CyclomaticRule) configure(arguments lint.Arguments) error {
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
r.maxComplexity = defaultMaxCyclomaticComplexity
|
r.maxComplexity = defaultMaxCyclomaticComplexity
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
complexity, ok := arguments[0].(int64) // Alt. non panicking version
|
complexity, ok := arguments[0].(int64) // Alt. non panicking version
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("invalid argument for cyclomatic complexity; expected int but got %T", arguments[0]))
|
return fmt.Errorf("invalid argument for cyclomatic complexity; expected int but got %T", arguments[0])
|
||||||
}
|
}
|
||||||
r.maxComplexity = int(complexity)
|
r.maxComplexity = int(complexity)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
for _, decl := range file.AST.Decls {
|
for _, decl := range file.AST.Decls {
|
||||||
|
@ -15,13 +15,23 @@ type DeferRule struct {
|
|||||||
configureOnce sync.Once
|
configureOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DeferRule) configure(arguments lint.Arguments) {
|
func (r *DeferRule) configure(arguments lint.Arguments) error {
|
||||||
r.allow = r.allowFromArgs(arguments)
|
list, err := r.allowFromArgs(arguments)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.allow = list
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
onFailure := func(failure lint.Failure) {
|
onFailure := func(failure lint.Failure) {
|
||||||
@ -39,7 +49,7 @@ func (*DeferRule) Name() string {
|
|||||||
return "defer"
|
return "defer"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*DeferRule) allowFromArgs(args lint.Arguments) map[string]bool {
|
func (*DeferRule) allowFromArgs(args lint.Arguments) (map[string]bool, error) {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
allow := map[string]bool{
|
allow := map[string]bool{
|
||||||
"loop": true,
|
"loop": true,
|
||||||
@ -50,24 +60,24 @@ func (*DeferRule) allowFromArgs(args lint.Arguments) map[string]bool {
|
|||||||
"immediate-recover": true,
|
"immediate-recover": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
return allow
|
return allow, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
aa, ok := args[0].([]any)
|
aa, ok := args[0].([]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid argument '%v' for 'defer' rule. Expecting []string, got %T", args[0], args[0]))
|
return nil, fmt.Errorf("invalid argument '%v' for 'defer' rule. Expecting []string, got %T", args[0], args[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
allow := make(map[string]bool, len(aa))
|
allow := make(map[string]bool, len(aa))
|
||||||
for _, subcase := range aa {
|
for _, subcase := range aa {
|
||||||
sc, ok := subcase.(string)
|
sc, ok := subcase.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid argument '%v' for 'defer' rule. Expecting string, got %T", subcase, subcase))
|
return nil, fmt.Errorf("invalid argument '%v' for 'defer' rule. Expecting string, got %T", subcase, subcase)
|
||||||
}
|
}
|
||||||
allow[sc] = true
|
allow[sc] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return allow
|
return allow, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type lintDeferRule struct {
|
type lintDeferRule struct {
|
||||||
|
@ -17,7 +17,12 @@ type DotImportsRule struct {
|
|||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
|
||||||
@ -41,30 +46,31 @@ func (*DotImportsRule) Name() string {
|
|||||||
return "dot-imports"
|
return "dot-imports"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DotImportsRule) configure(arguments lint.Arguments) {
|
func (r *DotImportsRule) configure(arguments lint.Arguments) error {
|
||||||
r.allowedPackages = allowPackages{}
|
r.allowedPackages = allowPackages{}
|
||||||
if len(arguments) == 0 {
|
if len(arguments) == 0 {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
args, ok := arguments[0].(map[string]any)
|
args, ok := arguments[0].(map[string]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid argument to the dot-imports rule. Expecting a k,v map, got %T", arguments[0]))
|
return fmt.Errorf("invalid argument to the dot-imports rule. Expecting a k,v map, got %T", arguments[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if allowedPkgArg, ok := args["allowedPackages"]; ok {
|
if allowedPkgArg, ok := args["allowedPackages"]; ok {
|
||||||
pkgs, ok := allowedPkgArg.([]any)
|
pkgs, ok := allowedPkgArg.([]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid argument to the dot-imports rule, []string expected. Got '%v' (%T)", allowedPkgArg, allowedPkgArg))
|
return fmt.Errorf("invalid argument to the dot-imports rule, []string expected. Got '%v' (%T)", allowedPkgArg, allowedPkgArg)
|
||||||
}
|
}
|
||||||
for _, p := range pkgs {
|
for _, p := range pkgs {
|
||||||
pkg, ok := p.(string)
|
pkg, ok := p.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid argument to the dot-imports rule, string expected. Got '%v' (%T)", p, p))
|
return fmt.Errorf("invalid argument to the dot-imports rule, string expected. Got '%v' (%T)", p, p)
|
||||||
}
|
}
|
||||||
r.allowedPackages.add(pkg)
|
r.allowedPackages.add(pkg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type lintImports struct {
|
type lintImports struct {
|
||||||
|
@ -44,35 +44,40 @@ type EnforceMapStyleRule struct {
|
|||||||
configureOnce sync.Once
|
configureOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *EnforceMapStyleRule) configure(arguments lint.Arguments) {
|
func (r *EnforceMapStyleRule) configure(arguments lint.Arguments) error {
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
r.enforceMapStyle = enforceMapStyleTypeAny
|
r.enforceMapStyle = enforceMapStyleTypeAny
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
enforceMapStyle, ok := arguments[0].(string)
|
enforceMapStyle, ok := arguments[0].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid argument '%v' for 'enforce-map-style' rule. Expecting string, got %T", arguments[0], arguments[0]))
|
return fmt.Errorf("invalid argument '%v' for 'enforce-map-style' rule. Expecting string, got %T", arguments[0], arguments[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
r.enforceMapStyle, err = mapStyleFromString(enforceMapStyle)
|
r.enforceMapStyle, err = mapStyleFromString(enforceMapStyle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("Invalid argument to the enforce-map-style rule: %v", err))
|
return fmt.Errorf("invalid argument to the enforce-map-style rule: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
if r.enforceMapStyle == enforceMapStyleTypeAny {
|
if r.enforceMapStyle == enforceMapStyleTypeAny {
|
||||||
// this linter is not configured
|
// this linter is not configured
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
|
||||||
astFile := file.AST
|
astFile := file.AST
|
||||||
ast.Inspect(astFile, func(n ast.Node) bool {
|
ast.Inspect(astFile, func(n ast.Node) bool {
|
||||||
switch v := n.(type) {
|
switch v := n.(type) {
|
||||||
|
@ -16,14 +16,14 @@ const (
|
|||||||
enforceRepeatedArgTypeStyleTypeFull enforceRepeatedArgTypeStyleType = "full"
|
enforceRepeatedArgTypeStyleTypeFull enforceRepeatedArgTypeStyleType = "full"
|
||||||
)
|
)
|
||||||
|
|
||||||
func repeatedArgTypeStyleFromString(s string) enforceRepeatedArgTypeStyleType {
|
func repeatedArgTypeStyleFromString(s string) (enforceRepeatedArgTypeStyleType, error) {
|
||||||
switch s {
|
switch s {
|
||||||
case string(enforceRepeatedArgTypeStyleTypeAny), "":
|
case string(enforceRepeatedArgTypeStyleTypeAny), "":
|
||||||
return enforceRepeatedArgTypeStyleTypeAny
|
return enforceRepeatedArgTypeStyleTypeAny, nil
|
||||||
case string(enforceRepeatedArgTypeStyleTypeShort):
|
case string(enforceRepeatedArgTypeStyleTypeShort):
|
||||||
return enforceRepeatedArgTypeStyleTypeShort
|
return enforceRepeatedArgTypeStyleTypeShort, nil
|
||||||
case string(enforceRepeatedArgTypeStyleTypeFull):
|
case string(enforceRepeatedArgTypeStyleTypeFull):
|
||||||
return enforceRepeatedArgTypeStyleTypeFull
|
return enforceRepeatedArgTypeStyleTypeFull, nil
|
||||||
default:
|
default:
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
"invalid repeated arg type style: %s (expecting one of %v)",
|
"invalid repeated arg type style: %s (expecting one of %v)",
|
||||||
@ -35,7 +35,7 @@ func repeatedArgTypeStyleFromString(s string) enforceRepeatedArgTypeStyleType {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
panic(fmt.Sprintf("Invalid argument to the enforce-repeated-arg-type-style rule: %v", err))
|
return "", fmt.Errorf("invalid argument to the enforce-repeated-arg-type-style rule: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,45 +47,67 @@ type EnforceRepeatedArgTypeStyleRule struct {
|
|||||||
configureOnce sync.Once
|
configureOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *EnforceRepeatedArgTypeStyleRule) configure(arguments lint.Arguments) {
|
func (r *EnforceRepeatedArgTypeStyleRule) configure(arguments lint.Arguments) error {
|
||||||
r.funcArgStyle = enforceRepeatedArgTypeStyleTypeAny
|
r.funcArgStyle = enforceRepeatedArgTypeStyleTypeAny
|
||||||
r.funcRetValStyle = enforceRepeatedArgTypeStyleTypeAny
|
r.funcRetValStyle = enforceRepeatedArgTypeStyleTypeAny
|
||||||
|
|
||||||
if len(arguments) == 0 {
|
if len(arguments) == 0 {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
switch funcArgStyle := arguments[0].(type) {
|
switch funcArgStyle := arguments[0].(type) {
|
||||||
case string:
|
case string:
|
||||||
r.funcArgStyle = repeatedArgTypeStyleFromString(funcArgStyle)
|
argstyle, err := repeatedArgTypeStyleFromString(funcArgStyle)
|
||||||
r.funcRetValStyle = repeatedArgTypeStyleFromString(funcArgStyle)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.funcArgStyle = argstyle
|
||||||
|
valstyle, err := repeatedArgTypeStyleFromString(funcArgStyle)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.funcRetValStyle = valstyle
|
||||||
case map[string]any: // expecting map[string]string
|
case map[string]any: // expecting map[string]string
|
||||||
for k, v := range funcArgStyle {
|
for k, v := range funcArgStyle {
|
||||||
switch k {
|
switch k {
|
||||||
case "funcArgStyle":
|
case "funcArgStyle":
|
||||||
val, ok := v.(string)
|
val, ok := v.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid map value type for 'enforce-repeated-arg-type-style' rule. Expecting string, got %T", v))
|
return fmt.Errorf("invalid map value type for 'enforce-repeated-arg-type-style' rule. Expecting string, got %T", v)
|
||||||
}
|
}
|
||||||
r.funcArgStyle = repeatedArgTypeStyleFromString(val)
|
valstyle, err := repeatedArgTypeStyleFromString(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.funcArgStyle = valstyle
|
||||||
case "funcRetValStyle":
|
case "funcRetValStyle":
|
||||||
val, ok := v.(string)
|
val, ok := v.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid map value '%v' for 'enforce-repeated-arg-type-style' rule. Expecting string, got %T", v, v))
|
return fmt.Errorf("invalid map value '%v' for 'enforce-repeated-arg-type-style' rule. Expecting string, got %T", v, v)
|
||||||
}
|
}
|
||||||
r.funcRetValStyle = repeatedArgTypeStyleFromString(val)
|
argstyle, err := repeatedArgTypeStyleFromString(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.funcRetValStyle = argstyle
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Invalid map key for 'enforce-repeated-arg-type-style' rule. Expecting 'funcArgStyle' or 'funcRetValStyle', got %v", k))
|
return fmt.Errorf("invalid map key for 'enforce-repeated-arg-type-style' rule. Expecting 'funcArgStyle' or 'funcRetValStyle', got %v", k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Invalid argument '%v' for 'import-alias-naming' rule. Expecting string or map[string]string, got %T", arguments[0], arguments[0]))
|
return fmt.Errorf("invalid argument '%v' for 'import-alias-naming' rule. Expecting string or map[string]string, got %T", arguments[0], arguments[0])
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
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.
|
||||||
|
@ -48,27 +48,33 @@ type EnforceSliceStyleRule struct {
|
|||||||
configureOnce sync.Once
|
configureOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *EnforceSliceStyleRule) configure(arguments lint.Arguments) {
|
func (r *EnforceSliceStyleRule) configure(arguments lint.Arguments) error {
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
r.enforceSliceStyle = enforceSliceStyleTypeAny
|
r.enforceSliceStyle = enforceSliceStyleTypeAny
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
enforceSliceStyle, ok := arguments[0].(string)
|
enforceSliceStyle, ok := arguments[0].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid argument '%v' for 'enforce-slice-style' rule. Expecting string, got %T", arguments[0], arguments[0]))
|
return fmt.Errorf("invalid argument '%v' for 'enforce-slice-style' rule. Expecting string, got %T", arguments[0], arguments[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
r.enforceSliceStyle, err = sliceStyleFromString(enforceSliceStyle)
|
r.enforceSliceStyle, err = sliceStyleFromString(enforceSliceStyle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("Invalid argument to the enforce-slice-style rule: %v", err))
|
return fmt.Errorf("invalid argument to the enforce-slice-style rule: %w", err)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
if r.enforceSliceStyle == enforceSliceStyleTypeAny {
|
if r.enforceSliceStyle == enforceSliceStyleTypeAny {
|
||||||
// this linter is not configured
|
// this linter is not configured
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package rule
|
package rule
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/token"
|
"go/token"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -19,7 +20,7 @@ type ErrorStringsRule struct {
|
|||||||
configureOnce sync.Once
|
configureOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ErrorStringsRule) configure(arguments lint.Arguments) {
|
func (r *ErrorStringsRule) configure(arguments lint.Arguments) error {
|
||||||
r.errorFunctions = map[string]map[string]struct{}{
|
r.errorFunctions = map[string]map[string]struct{}{
|
||||||
"fmt": {
|
"fmt": {
|
||||||
"Errorf": {},
|
"Errorf": {},
|
||||||
@ -46,15 +47,21 @@ func (r *ErrorStringsRule) configure(arguments lint.Arguments) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(invalidCustomFunctions) != 0 {
|
if len(invalidCustomFunctions) != 0 {
|
||||||
panic("found invalid custom function: " + strings.Join(invalidCustomFunctions, ","))
|
return fmt.Errorf("found invalid custom function: " + strings.Join(invalidCustomFunctions, ","))
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply applies the rule to given file.
|
// Apply applies the rule to given file.
|
||||||
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 configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
r.configureOnce.Do(func() { r.configure(arguments) })
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
var failures []lint.Failure
|
||||||
|
|
||||||
fileAst := file.AST
|
fileAst := file.AST
|
||||||
walker := lintErrorStrings{
|
walker := lintErrorStrings{
|
||||||
|
@ -70,7 +70,7 @@ type ExportedRule struct {
|
|||||||
configureOnce sync.Once
|
configureOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ExportedRule) configure(arguments lint.Arguments) {
|
func (r *ExportedRule) configure(arguments lint.Arguments) error {
|
||||||
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 {
|
||||||
@ -96,17 +96,24 @@ func (r *ExportedRule) configure(arguments lint.Arguments) {
|
|||||||
case "disableChecksOnVariables":
|
case "disableChecksOnVariables":
|
||||||
r.disabledChecks.Var = true
|
r.disabledChecks.Var = true
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Unknown configuration flag %s for %s rule", flag, r.Name()))
|
return fmt.Errorf("unknown configuration flag %s for %s rule", flag, r.Name())
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Invalid argument for the %s rule: expecting a string, got %T", r.Name(), flag))
|
return fmt.Errorf("invalid argument for the %s rule: expecting a string, got %T", r.Name(), flag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, arguments lint.Arguments) []lint.Failure {
|
||||||
r.configureOnce.Do(func() { r.configure(args) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
if file.IsTest() {
|
if file.IsTest() {
|
||||||
|
@ -20,21 +20,27 @@ var (
|
|||||||
singleRegexp = regexp.MustCompile("^//")
|
singleRegexp = regexp.MustCompile("^//")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *FileHeaderRule) configure(arguments lint.Arguments) {
|
func (r *FileHeaderRule) configure(arguments lint.Arguments) error {
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var ok bool
|
var ok bool
|
||||||
r.header, ok = arguments[0].(string)
|
r.header, ok = arguments[0].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("invalid argument for \"file-header\" rule: argument should be a string, got %T", arguments[0]))
|
return fmt.Errorf(`invalid argument for "file-header" rule: argument should be a string, got %T`, arguments[0])
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
if r.header == "" {
|
if r.header == "" {
|
||||||
return nil
|
return nil
|
||||||
@ -69,7 +75,7 @@ func (r *FileHeaderRule) Apply(file *lint.File, arguments lint.Arguments) []lint
|
|||||||
|
|
||||||
regex, err := regexp.Compile(r.header)
|
regex, err := regexp.Compile(r.header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err.Error())
|
return newInternalFailureError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !regex.MatchString(comment) {
|
if !regex.MatchString(comment) {
|
||||||
|
@ -26,7 +26,12 @@ type FileLengthLimitRule struct {
|
|||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
@ -44,7 +49,7 @@ func (r *FileLengthLimitRule) Apply(file *lint.File, arguments lint.Arguments) [
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
if err := scanner.Err(); err != nil {
|
||||||
panic(err.Error())
|
return newInternalFailureError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lines := all
|
lines := all
|
||||||
@ -75,37 +80,38 @@ func (r *FileLengthLimitRule) Apply(file *lint.File, arguments lint.Arguments) [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *FileLengthLimitRule) configure(arguments lint.Arguments) {
|
func (r *FileLengthLimitRule) configure(arguments lint.Arguments) error {
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
return // use default
|
return nil // use default
|
||||||
}
|
}
|
||||||
|
|
||||||
argKV, ok := arguments[0].(map[string]any)
|
argKV, ok := arguments[0].(map[string]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf(`invalid argument to the "file-length-limit" rule. Expecting a k,v map, got %T`, arguments[0]))
|
return fmt.Errorf(`invalid argument to the "file-length-limit" rule. Expecting a k,v map, got %T`, arguments[0])
|
||||||
}
|
}
|
||||||
for k, v := range argKV {
|
for k, v := range argKV {
|
||||||
switch k {
|
switch k {
|
||||||
case "max":
|
case "max":
|
||||||
maxLines, ok := v.(int64)
|
maxLines, ok := v.(int64)
|
||||||
if !ok || maxLines < 0 {
|
if !ok || maxLines < 0 {
|
||||||
panic(fmt.Sprintf(`invalid configuration value for max lines in "file-length-limit" rule; need positive int64 but got %T`, arguments[0]))
|
return fmt.Errorf(`invalid configuration value for max lines in "file-length-limit" rule; need positive int64 but got %T`, arguments[0])
|
||||||
}
|
}
|
||||||
r.max = int(maxLines)
|
r.max = int(maxLines)
|
||||||
case "skipComments":
|
case "skipComments":
|
||||||
skipComments, ok := v.(bool)
|
skipComments, ok := v.(bool)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf(`invalid configuration value for skip comments in "file-length-limit" rule; need bool but got %T`, arguments[1]))
|
return fmt.Errorf(`invalid configuration value for skip comments in "file-length-limit" rule; need bool but got %T`, arguments[1])
|
||||||
}
|
}
|
||||||
r.skipComments = skipComments
|
r.skipComments = skipComments
|
||||||
case "skipBlankLines":
|
case "skipBlankLines":
|
||||||
skipBlankLines, ok := v.(bool)
|
skipBlankLines, ok := v.(bool)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf(`invalid configuration value for skip blank lines in "file-length-limit" rule; need bool but got %T`, arguments[2]))
|
return fmt.Errorf(`invalid configuration value for skip blank lines in "file-length-limit" rule; need bool but got %T`, arguments[2])
|
||||||
}
|
}
|
||||||
r.skipBlankLines = skipBlankLines
|
r.skipBlankLines = skipBlankLines
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns the rule name.
|
// Name returns the rule name.
|
||||||
|
@ -19,7 +19,12 @@ type FilenameFormatRule struct {
|
|||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
filename := filepath.Base(file.Name)
|
filename := filepath.Base(file.Name)
|
||||||
if r.format.MatchString(filename) {
|
if r.format.MatchString(filename) {
|
||||||
@ -55,27 +60,29 @@ 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) error {
|
||||||
argsCount := len(arguments)
|
argsCount := len(arguments)
|
||||||
if argsCount == 0 {
|
if argsCount == 0 {
|
||||||
r.format = defaultFormat
|
r.format = defaultFormat
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if argsCount > 1 {
|
if argsCount > 1 {
|
||||||
panic(fmt.Sprintf("rule %q expects only one argument, got %d %v", r.Name(), argsCount, arguments))
|
return fmt.Errorf("rule %q expects only one argument, got %d %v", r.Name(), argsCount, arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
arg := arguments[0]
|
arg := arguments[0]
|
||||||
str, ok := arg.(string)
|
str, ok := arg.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("rule %q expects a string argument, got %v of type %T", r.Name(), arg, arg))
|
return fmt.Errorf("rule %q expects a string argument, got %v of type %T", r.Name(), arg, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
format, err := regexp.Compile(str)
|
format, err := regexp.Compile(str)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("rule %q expects a valid regexp argument, got %v for %s", r.Name(), err, arg))
|
return fmt.Errorf("rule %q expects a valid regexp argument, got error for %s: %w", r.Name(), str, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.format = format
|
r.format = format
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -17,15 +17,24 @@ type FunctionLength struct {
|
|||||||
configureOnce sync.Once
|
configureOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *FunctionLength) configure(arguments lint.Arguments) {
|
func (r *FunctionLength) configure(arguments lint.Arguments) error {
|
||||||
maxStmt, maxLines := r.parseArguments(arguments)
|
maxStmt, maxLines, err := r.parseArguments(arguments)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
r.maxStmt = int(maxStmt)
|
r.maxStmt = int(maxStmt)
|
||||||
r.maxLines = int(maxLines)
|
r.maxLines = int(maxLines)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
for _, decl := range file.AST.Decls {
|
for _, decl := range file.AST.Decls {
|
||||||
@ -74,33 +83,33 @@ func (*FunctionLength) Name() string {
|
|||||||
const defaultFuncStmtsLimit = 50
|
const defaultFuncStmtsLimit = 50
|
||||||
const defaultFuncLinesLimit = 75
|
const defaultFuncLinesLimit = 75
|
||||||
|
|
||||||
func (*FunctionLength) parseArguments(arguments lint.Arguments) (maxStmt, maxLines int64) {
|
func (*FunctionLength) parseArguments(arguments lint.Arguments) (maxStmt, maxLines int64, err error) {
|
||||||
if len(arguments) == 0 {
|
if len(arguments) == 0 {
|
||||||
return defaultFuncStmtsLimit, defaultFuncLinesLimit
|
return defaultFuncStmtsLimit, defaultFuncLinesLimit, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const minArguments = 2
|
const minArguments = 2
|
||||||
if len(arguments) != minArguments {
|
if len(arguments) != minArguments {
|
||||||
panic(fmt.Sprintf(`invalid configuration for "function-length" rule, expected %d arguments but got %d`, minArguments, len(arguments)))
|
return 0, 0, fmt.Errorf(`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)
|
||||||
if !maxStmtOk {
|
if !maxStmtOk {
|
||||||
panic(fmt.Sprintf(`invalid configuration value for max statements in "function-length" rule; need int64 but got %T`, arguments[0]))
|
return 0, 0, fmt.Errorf(`invalid configuration value for max statements in "function-length" rule; need int64 but got %T`, arguments[0])
|
||||||
}
|
}
|
||||||
if maxStmt < 0 {
|
if maxStmt < 0 {
|
||||||
panic(fmt.Sprintf(`the configuration value for max statements in "function-length" rule cannot be negative, got %d`, maxStmt))
|
return 0, 0, fmt.Errorf(`the configuration value for max statements in "function-length" rule cannot be negative, got %d`, maxStmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
maxLines, maxLinesOk := arguments[1].(int64)
|
maxLines, maxLinesOk := arguments[1].(int64)
|
||||||
if !maxLinesOk {
|
if !maxLinesOk {
|
||||||
panic(fmt.Sprintf(`invalid configuration value for max lines in "function-length" rule; need int64 but got %T`, arguments[1]))
|
return 0, 0, fmt.Errorf(`invalid configuration value for max lines in "function-length" rule; need int64 but got %T`, arguments[1])
|
||||||
}
|
}
|
||||||
if maxLines < 0 {
|
if maxLines < 0 {
|
||||||
panic(fmt.Sprintf(`the configuration value for max statements in "function-length" rule cannot be negative, got %d`, maxLines))
|
return 0, 0, fmt.Errorf(`the configuration value for max statements in "function-length" rule cannot be negative, got %d`, maxLines)
|
||||||
}
|
}
|
||||||
|
|
||||||
return maxStmt, maxLines
|
return maxStmt, maxLines, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*FunctionLength) countLines(b *ast.BlockStmt, file *lint.File) int {
|
func (*FunctionLength) countLines(b *ast.BlockStmt, file *lint.File) int {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package rule
|
package rule
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"sync"
|
"sync"
|
||||||
@ -17,7 +18,12 @@ type FunctionResultsLimitRule struct {
|
|||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
for _, decl := range file.AST.Decls {
|
for _, decl := range file.AST.Decls {
|
||||||
@ -53,19 +59,20 @@ func (*FunctionResultsLimitRule) Name() string {
|
|||||||
|
|
||||||
const defaultResultsLimit = 3
|
const defaultResultsLimit = 3
|
||||||
|
|
||||||
func (r *FunctionResultsLimitRule) configure(arguments lint.Arguments) {
|
func (r *FunctionResultsLimitRule) configure(arguments lint.Arguments) error {
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
r.max = defaultResultsLimit
|
r.max = defaultResultsLimit
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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]))
|
return fmt.Errorf(`invalid value passed as return results number to the "function-result-limit" rule; need int64 but got %T`, arguments[0])
|
||||||
}
|
}
|
||||||
if maxResults < 0 {
|
if maxResults < 0 {
|
||||||
panic(`the value passed as return results number to the "function-result-limit" rule cannot be negative`)
|
return errors.New(`the value passed as return results number to the "function-result-limit" rule cannot be negative`)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.max = int(maxResults)
|
r.max = int(maxResults)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -20,38 +20,54 @@ 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) error {
|
||||||
if len(arguments) == 0 {
|
if len(arguments) == 0 {
|
||||||
r.allowRegexp = defaultImportAliasNamingAllowRegexp
|
r.allowRegexp = defaultImportAliasNamingAllowRegexp
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
switch namingRule := arguments[0].(type) {
|
switch namingRule := arguments[0].(type) {
|
||||||
case string:
|
case string:
|
||||||
r.setAllowRule(namingRule)
|
err := r.setAllowRule(namingRule)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
case map[string]any: // expecting map[string]string
|
case map[string]any: // expecting map[string]string
|
||||||
for k, v := range namingRule {
|
for k, v := range namingRule {
|
||||||
switch k {
|
switch k {
|
||||||
case "allowRegex":
|
case "allowRegex":
|
||||||
r.setAllowRule(v)
|
err := r.setAllowRule(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
case "denyRegex":
|
case "denyRegex":
|
||||||
r.setDenyRule(v)
|
err := r.setDenyRule(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Invalid map key for 'import-alias-naming' rule. Expecting 'allowRegex' or 'denyRegex', got %v", k))
|
return fmt.Errorf("invalid map key for 'import-alias-naming' rule. Expecting 'allowRegex' or 'denyRegex', got %v", k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Invalid argument '%v' for 'import-alias-naming' rule. Expecting string or map[string]string, got %T", arguments[0], arguments[0]))
|
return fmt.Errorf("invalid argument '%v' for 'import-alias-naming' rule. Expecting string or map[string]string, got %T", arguments[0], arguments[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.allowRegexp == nil && r.denyRegexp == nil {
|
if r.allowRegexp == nil && r.denyRegexp == nil {
|
||||||
r.allowRegexp = defaultImportAliasNamingAllowRegexp
|
r.allowRegexp = defaultImportAliasNamingAllowRegexp
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
|
||||||
@ -93,28 +109,30 @@ func (*ImportAliasNamingRule) Name() string {
|
|||||||
return "import-alias-naming"
|
return "import-alias-naming"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ImportAliasNamingRule) setAllowRule(value any) {
|
func (r *ImportAliasNamingRule) setAllowRule(value any) error {
|
||||||
namingRule, ok := value.(string)
|
namingRule, ok := value.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid argument '%v' for import-alias-naming allowRegexp rule. Expecting string, got %T", value, value))
|
return fmt.Errorf("invalid argument '%v' for import-alias-naming allowRegexp rule. Expecting string, got %T", value, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
namingRuleRegexp, err := regexp.Compile(namingRule)
|
namingRuleRegexp, err := regexp.Compile(namingRule)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("Invalid argument to the import-alias-naming allowRegexp rule. Expecting %q to be a valid regular expression, got: %v", namingRule, err))
|
return fmt.Errorf("invalid argument to the import-alias-naming allowRegexp rule. Expecting %q to be a valid regular expression, got: %w", namingRule, err)
|
||||||
}
|
}
|
||||||
r.allowRegexp = namingRuleRegexp
|
r.allowRegexp = namingRuleRegexp
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ImportAliasNamingRule) setDenyRule(value any) {
|
func (r *ImportAliasNamingRule) setDenyRule(value any) error {
|
||||||
namingRule, ok := value.(string)
|
namingRule, ok := value.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid argument '%v' for import-alias-naming denyRegexp rule. Expecting string, got %T", value, value))
|
return fmt.Errorf("invalid argument '%v' for import-alias-naming denyRegexp rule. Expecting string, got %T", value, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
namingRuleRegexp, err := regexp.Compile(namingRule)
|
namingRuleRegexp, err := regexp.Compile(namingRule)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("Invalid argument to the import-alias-naming denyRegexp rule. Expecting %q to be a valid regular expression, got: %v", namingRule, err))
|
return fmt.Errorf("invalid argument to the import-alias-naming denyRegexp rule. Expecting %q to be a valid regular expression, got: %w", namingRule, err)
|
||||||
}
|
}
|
||||||
r.denyRegexp = namingRuleRegexp
|
r.denyRegexp = namingRuleRegexp
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -17,19 +17,20 @@ type ImportsBlocklistRule struct {
|
|||||||
|
|
||||||
var replaceImportRegexp = regexp.MustCompile(`/?\*\*/?`)
|
var replaceImportRegexp = regexp.MustCompile(`/?\*\*/?`)
|
||||||
|
|
||||||
func (r *ImportsBlocklistRule) configure(arguments lint.Arguments) {
|
func (r *ImportsBlocklistRule) configure(arguments lint.Arguments) error {
|
||||||
r.blocklist = []*regexp.Regexp{}
|
r.blocklist = []*regexp.Regexp{}
|
||||||
for _, arg := range arguments {
|
for _, arg := range arguments {
|
||||||
argStr, ok := arg.(string)
|
argStr, ok := arg.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid argument to the imports-blocklist rule. Expecting a string, got %T", arg))
|
return fmt.Errorf("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)*`)))
|
regStr, err := regexp.Compile(fmt.Sprintf(`(?m)"%s"$`, replaceImportRegexp.ReplaceAllString(argStr, `(\W|\w)*`)))
|
||||||
if err != nil {
|
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))
|
return fmt.Errorf("invalid argument to the imports-blocklist rule. Expecting %q to be a valid regular expression, got: %w", argStr, err)
|
||||||
}
|
}
|
||||||
r.blocklist = append(r.blocklist, regStr)
|
r.blocklist = append(r.blocklist, regStr)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ImportsBlocklistRule) isBlocklisted(path string) bool {
|
func (r *ImportsBlocklistRule) isBlocklisted(path string) bool {
|
||||||
@ -43,7 +44,12 @@ 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package rule
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/token"
|
"go/token"
|
||||||
"strings"
|
"strings"
|
||||||
@ -21,23 +22,29 @@ type LineLengthLimitRule struct {
|
|||||||
|
|
||||||
const defaultLineLengthLimit = 80
|
const defaultLineLengthLimit = 80
|
||||||
|
|
||||||
func (r *LineLengthLimitRule) configure(arguments lint.Arguments) {
|
func (r *LineLengthLimitRule) configure(arguments lint.Arguments) error {
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
r.max = defaultLineLengthLimit
|
r.max = defaultLineLengthLimit
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
maxLength, ok := arguments[0].(int64) // Alt. non panicking version
|
maxLength, ok := arguments[0].(int64) // Alt. non panicking version
|
||||||
if !ok || maxLength < 0 {
|
if !ok || maxLength < 0 {
|
||||||
panic(`invalid value passed as argument number to the "line-length-limit" rule`)
|
return errors.New(`invalid value passed as argument number to the "line-length-limit" rule`)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.max = int(maxLength)
|
r.max = int(maxLength)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package rule
|
package rule
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"sync"
|
"sync"
|
||||||
@ -19,7 +20,12 @@ 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
|
||||||
@ -107,17 +113,21 @@ func (w *lintMaxControlNesting) walkControlledBlock(b ast.Node) {
|
|||||||
w.nestingLevelAcc = oldNestingLevel
|
w.nestingLevelAcc = oldNestingLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *MaxControlNestingRule) configure(arguments lint.Arguments) {
|
func (r *MaxControlNestingRule) configure(arguments lint.Arguments) error {
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
r.max = defaultMaxControlNesting
|
r.max = defaultMaxControlNesting
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
checkNumberOfArguments(1, arguments, r.Name())
|
check := checkNumberOfArguments(1, arguments, r.Name())
|
||||||
|
if check != nil {
|
||||||
|
return check
|
||||||
|
}
|
||||||
|
|
||||||
maxNesting, ok := arguments[0].(int64) // Alt. non panicking version
|
maxNesting, ok := arguments[0].(int64) // Alt. non panicking version
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(`invalid value passed as argument number to the "max-control-nesting" rule`)
|
return errors.New(`invalid value passed as argument number to the "max-control-nesting" rule`)
|
||||||
}
|
}
|
||||||
r.max = maxNesting
|
r.max = maxNesting
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package rule
|
package rule
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"strings"
|
"strings"
|
||||||
@ -18,24 +19,33 @@ type MaxPublicStructsRule struct {
|
|||||||
|
|
||||||
const defaultMaxPublicStructs = 5
|
const defaultMaxPublicStructs = 5
|
||||||
|
|
||||||
func (r *MaxPublicStructsRule) configure(arguments lint.Arguments) {
|
func (r *MaxPublicStructsRule) configure(arguments lint.Arguments) error {
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
r.max = defaultMaxPublicStructs
|
r.max = defaultMaxPublicStructs
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
checkNumberOfArguments(1, arguments, r.Name())
|
err := checkNumberOfArguments(1, arguments, r.Name())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
maxStructs, ok := arguments[0].(int64) // Alt. non panicking version
|
maxStructs, ok := arguments[0].(int64) // Alt. non panicking version
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(`invalid value passed as argument number to the "max-public-structs" rule`)
|
return errors.New(`invalid value passed as argument number to the "max-public-structs" rule`)
|
||||||
}
|
}
|
||||||
r.max = maxStructs
|
r.max = maxStructs
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
|
||||||
|
@ -18,15 +18,15 @@ type ReceiverNamingRule struct {
|
|||||||
|
|
||||||
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) error {
|
||||||
r.receiverNameMaxLength = defaultReceiverNameMaxLength
|
r.receiverNameMaxLength = defaultReceiverNameMaxLength
|
||||||
if len(arguments) < 1 {
|
if len(arguments) < 1 {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
args, ok := arguments[0].(map[string]any)
|
args, ok := arguments[0].(map[string]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Unable to get arguments for rule %s. Expected object of key-value-pairs.", r.Name()))
|
return fmt.Errorf("unable to get arguments for rule %s. Expected object of key-value-pairs", r.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range args {
|
for k, v := range args {
|
||||||
@ -34,18 +34,24 @@ func (r *ReceiverNamingRule) configure(arguments lint.Arguments) {
|
|||||||
case "maxLength":
|
case "maxLength":
|
||||||
value, ok := v.(int64)
|
value, ok := v.(int64)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid value %v for argument %s of rule %s, expected integer value got %T", v, k, r.Name(), v))
|
return fmt.Errorf("invalid value %v for argument %s of rule %s, expected integer value got %T", v, k, r.Name(), v)
|
||||||
}
|
}
|
||||||
r.receiverNameMaxLength = int(value)
|
r.receiverNameMaxLength = int(value)
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Unknown argument %s for %s rule.", k, r.Name()))
|
return fmt.Errorf("unknown argument %s for %s rule", k, r.Name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, arguments lint.Arguments) []lint.Failure {
|
||||||
r.configureOnce.Do(func() { r.configure(args) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
typeReceiver := map[string]string{}
|
typeReceiver := map[string]string{}
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
@ -23,7 +23,11 @@ func (*StringFormatRule) Apply(file *lint.File, arguments lint.Arguments) []lint
|
|||||||
}
|
}
|
||||||
|
|
||||||
w := lintStringFormatRule{onFailure: onFailure}
|
w := lintStringFormatRule{onFailure: onFailure}
|
||||||
w.parseArguments(arguments)
|
err := w.parseArguments(arguments)
|
||||||
|
if err != nil {
|
||||||
|
return newInternalFailureError(err)
|
||||||
|
}
|
||||||
|
|
||||||
ast.Walk(w, file.AST)
|
ast.Walk(w, file.AST)
|
||||||
|
|
||||||
return failures
|
return failures
|
||||||
@ -41,10 +45,9 @@ func (StringFormatRule) ParseArgumentsTest(arguments lint.Arguments) *string {
|
|||||||
// Parse the arguments in a goroutine, defer a recover() call, return the error encountered (or nil if there was no error)
|
// Parse the arguments in a goroutine, defer a recover() call, return the error encountered (or nil if there was no error)
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
err := recover()
|
err := w.parseArguments(arguments)
|
||||||
c <- err
|
c <- err
|
||||||
}()
|
}()
|
||||||
w.parseArguments(arguments)
|
|
||||||
}()
|
}()
|
||||||
err := <-c
|
err := <-c
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -81,9 +84,12 @@ const identRegex = "[_A-Za-z][_A-Za-z0-9]*"
|
|||||||
var parseStringFormatScope = regexp.MustCompile(
|
var parseStringFormatScope = regexp.MustCompile(
|
||||||
fmt.Sprintf("^(%s(?:\\.%s)?)(?:\\[([0-9]+)\\](?:\\.(%s))?)?$", identRegex, identRegex, identRegex))
|
fmt.Sprintf("^(%s(?:\\.%s)?)(?:\\[([0-9]+)\\](?:\\.(%s))?)?$", identRegex, identRegex, identRegex))
|
||||||
|
|
||||||
func (w *lintStringFormatRule) parseArguments(arguments lint.Arguments) {
|
func (w *lintStringFormatRule) parseArguments(arguments lint.Arguments) error {
|
||||||
for i, argument := range arguments {
|
for i, argument := range arguments {
|
||||||
scopes, regex, negated, errorMessage := w.parseArgument(argument, i)
|
scopes, regex, negated, errorMessage, err := w.parseArgument(argument, i)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
w.rules = append(w.rules, stringFormatSubrule{
|
w.rules = append(w.rules, stringFormatSubrule{
|
||||||
parent: w,
|
parent: w,
|
||||||
scopes: scopes,
|
scopes: scopes,
|
||||||
@ -92,30 +98,31 @@ func (w *lintStringFormatRule) parseArguments(arguments lint.Arguments) {
|
|||||||
errorMessage: errorMessage,
|
errorMessage: errorMessage,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w lintStringFormatRule) parseArgument(argument any, ruleNum int) (scopes stringFormatSubruleScopes, regex *regexp.Regexp, negated bool, errorMessage string) {
|
func (w lintStringFormatRule) parseArgument(argument any, ruleNum int) (scopes stringFormatSubruleScopes, regex *regexp.Regexp, negated bool, errorMessage string, err error) {
|
||||||
g, ok := argument.([]any) // Cast to generic slice first
|
g, ok := argument.([]any) // Cast to generic slice first
|
||||||
if !ok {
|
if !ok {
|
||||||
w.configError("argument is not a slice", ruleNum, 0)
|
return stringFormatSubruleScopes{}, regex, false, "", w.configError("argument is not a slice", ruleNum, 0)
|
||||||
}
|
}
|
||||||
if len(g) < 2 {
|
if len(g) < 2 {
|
||||||
w.configError("less than two slices found in argument, scope and regex are required", ruleNum, len(g)-1)
|
return stringFormatSubruleScopes{}, regex, false, "", w.configError("less than two slices found in argument, scope and regex are required", ruleNum, len(g)-1)
|
||||||
}
|
}
|
||||||
rule := make([]string, len(g))
|
rule := make([]string, len(g))
|
||||||
for i, obj := range g {
|
for i, obj := range g {
|
||||||
val, ok := obj.(string)
|
val, ok := obj.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
w.configError("unexpected value, string was expected", ruleNum, i)
|
return stringFormatSubruleScopes{}, regex, false, "", w.configError("unexpected value, string was expected", ruleNum, i)
|
||||||
}
|
}
|
||||||
rule[i] = val
|
rule[i] = val
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate scope and regex length
|
// Validate scope and regex length
|
||||||
if rule[0] == "" {
|
if rule[0] == "" {
|
||||||
w.configError("empty scope provided", ruleNum, 0)
|
return stringFormatSubruleScopes{}, regex, false, "", w.configError("empty scope provided", ruleNum, 0)
|
||||||
} else if len(rule[1]) < 2 {
|
} else if len(rule[1]) < 2 {
|
||||||
w.configError("regex is too small (regexes should begin and end with '/')", ruleNum, 1)
|
return stringFormatSubruleScopes{}, regex, false, "", w.configError("regex is too small (regexes should begin and end with '/')", ruleNum, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse rule scopes
|
// Parse rule scopes
|
||||||
@ -126,24 +133,24 @@ func (w lintStringFormatRule) parseArgument(argument any, ruleNum int) (scopes s
|
|||||||
rawScope = strings.TrimSpace(rawScope)
|
rawScope = strings.TrimSpace(rawScope)
|
||||||
|
|
||||||
if len(rawScope) == 0 {
|
if len(rawScope) == 0 {
|
||||||
w.parseScopeError("empty scope in rule scopes:", ruleNum, 0, scopeNum)
|
return stringFormatSubruleScopes{}, regex, false, "", w.parseScopeError("empty scope in rule scopes:", ruleNum, 0, scopeNum)
|
||||||
}
|
}
|
||||||
|
|
||||||
scope := stringFormatSubruleScope{}
|
scope := stringFormatSubruleScope{}
|
||||||
matches := parseStringFormatScope.FindStringSubmatch(rawScope)
|
matches := parseStringFormatScope.FindStringSubmatch(rawScope)
|
||||||
if matches == nil {
|
if matches == nil {
|
||||||
// The rule's scope didn't match the parsing regex at all, probably a configuration error
|
// The rule's scope didn't match the parsing regex at all, probably a configuration error
|
||||||
w.parseScopeError("unable to parse rule scope", ruleNum, 0, scopeNum)
|
return stringFormatSubruleScopes{}, regex, false, "", w.parseScopeError("unable to parse rule scope", ruleNum, 0, scopeNum)
|
||||||
} else if len(matches) != 4 {
|
} else if len(matches) != 4 {
|
||||||
// The rule's scope matched the parsing regex, but an unexpected number of submatches was returned, probably a bug
|
// The rule's scope matched the parsing regex, but an unexpected number of submatches was returned, probably a bug
|
||||||
w.parseScopeError(fmt.Sprintf("unexpected number of submatches when parsing scope: %d, expected 4", len(matches)), ruleNum, 0, scopeNum)
|
return stringFormatSubruleScopes{}, regex, false, "", w.parseScopeError(fmt.Sprintf("unexpected number of submatches when parsing scope: %d, expected 4", len(matches)), ruleNum, 0, scopeNum)
|
||||||
}
|
}
|
||||||
scope.funcName = matches[1]
|
scope.funcName = matches[1]
|
||||||
if len(matches[2]) > 0 {
|
if len(matches[2]) > 0 {
|
||||||
var err error
|
var err error
|
||||||
scope.argument, err = strconv.Atoi(matches[2])
|
scope.argument, err = strconv.Atoi(matches[2])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.parseScopeError("unable to parse argument number in rule scope", ruleNum, 0, scopeNum)
|
return stringFormatSubruleScopes{}, regex, false, "", w.parseScopeError("unable to parse argument number in rule scope", ruleNum, 0, scopeNum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(matches[3]) > 0 {
|
if len(matches[3]) > 0 {
|
||||||
@ -159,31 +166,31 @@ func (w lintStringFormatRule) parseArgument(argument any, ruleNum int) (scopes s
|
|||||||
if negated {
|
if negated {
|
||||||
offset++
|
offset++
|
||||||
}
|
}
|
||||||
regex, err := regexp.Compile(rule[1][offset : len(rule[1])-1])
|
regex, errr := regexp.Compile(rule[1][offset : len(rule[1])-1])
|
||||||
if err != nil {
|
if errr != nil {
|
||||||
w.parseError(fmt.Sprintf("unable to compile %s as regexp", rule[1]), ruleNum, 1)
|
return stringFormatSubruleScopes{}, regex, false, "", w.parseError(fmt.Sprintf("unable to compile %s as regexp", rule[1]), ruleNum, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use custom error message if provided
|
// Use custom error message if provided
|
||||||
if len(rule) == 3 {
|
if len(rule) == 3 {
|
||||||
errorMessage = rule[2]
|
errorMessage = rule[2]
|
||||||
}
|
}
|
||||||
return scopes, regex, negated, errorMessage
|
return scopes, regex, negated, errorMessage, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report an invalid config, this is specifically the user's fault
|
// Report an invalid config, this is specifically the user's fault
|
||||||
func (lintStringFormatRule) configError(msg string, ruleNum, option int) {
|
func (lintStringFormatRule) configError(msg string, ruleNum, option int) error {
|
||||||
panic(fmt.Sprintf("invalid configuration for string-format: %s [argument %d, option %d]", msg, ruleNum, option))
|
return fmt.Errorf("invalid configuration for string-format: %s [argument %d, option %d]", msg, ruleNum, option)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report a general config parsing failure, this may be the user's fault, but it isn't known for certain
|
// Report a general config parsing failure, this may be the user's fault, but it isn't known for certain
|
||||||
func (lintStringFormatRule) parseError(msg string, ruleNum, option int) {
|
func (lintStringFormatRule) parseError(msg string, ruleNum, option int) error {
|
||||||
panic(fmt.Sprintf("failed to parse configuration for string-format: %s [argument %d, option %d]", msg, ruleNum, option))
|
return fmt.Errorf("failed to parse configuration for string-format: %s [argument %d, option %d]", msg, ruleNum, option)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report a general scope config parsing failure, this may be the user's fault, but it isn't known for certain
|
// Report a general scope config parsing failure, this may be the user's fault, but it isn't known for certain
|
||||||
func (lintStringFormatRule) parseScopeError(msg string, ruleNum, option, scopeNum int) {
|
func (lintStringFormatRule) parseScopeError(msg string, ruleNum, option, scopeNum int) error {
|
||||||
panic(fmt.Sprintf("failed to parse configuration for string-format: %s [argument %d, option %d, scope index %d]", msg, ruleNum, option, scopeNum))
|
return fmt.Errorf("failed to parse configuration for string-format: %s [argument %d, option %d, scope index %d]", msg, ruleNum, option, scopeNum)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w lintStringFormatRule) Visit(node ast.Node) ast.Visitor {
|
func (w lintStringFormatRule) Visit(node ast.Node) ast.Visitor {
|
||||||
|
@ -18,21 +18,24 @@ type StructTagRule struct {
|
|||||||
configureOnce sync.Once
|
configureOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *StructTagRule) configure(arguments lint.Arguments) {
|
func (r *StructTagRule) configure(arguments lint.Arguments) error {
|
||||||
if len(arguments) == 0 {
|
if len(arguments) == 0 {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
checkNumberOfArguments(1, arguments, r.Name())
|
err := checkNumberOfArguments(1, arguments, r.Name())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
r.userDefined = make(map[string][]string, len(arguments))
|
r.userDefined = make(map[string][]string, len(arguments))
|
||||||
for _, arg := range arguments {
|
for _, arg := range arguments {
|
||||||
item, ok := arg.(string)
|
item, ok := arg.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid argument to the %s rule. Expecting a string, got %v (of type %T)", r.Name(), arg, arg))
|
return fmt.Errorf("invalid argument to the %s rule. Expecting a string, got %v (of type %T)", r.Name(), arg, arg)
|
||||||
}
|
}
|
||||||
parts := strings.Split(item, ",")
|
parts := strings.Split(item, ",")
|
||||||
if len(parts) < 2 {
|
if len(parts) < 2 {
|
||||||
panic(fmt.Sprintf("Invalid argument to the %s rule. Expecting a string of the form key[,option]+, got %s", r.Name(), item))
|
return fmt.Errorf("invalid argument to the %s rule. Expecting a string of the form key[,option]+, got %s", r.Name(), item)
|
||||||
}
|
}
|
||||||
key := strings.TrimSpace(parts[0])
|
key := strings.TrimSpace(parts[0])
|
||||||
for i := 1; i < len(parts); i++ {
|
for i := 1; i < len(parts); i++ {
|
||||||
@ -40,11 +43,17 @@ func (r *StructTagRule) configure(arguments lint.Arguments) {
|
|||||||
r.userDefined[key] = append(r.userDefined[key], option)
|
r.userDefined[key] = append(r.userDefined[key], option)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, arguments lint.Arguments) []lint.Failure {
|
||||||
r.configureOnce.Do(func() { r.configure(args) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
onFailure := func(failure lint.Failure) {
|
onFailure := func(failure lint.Failure) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package rule
|
package rule
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"sync"
|
"sync"
|
||||||
@ -20,14 +21,14 @@ type UncheckedTypeAssertionRule struct {
|
|||||||
configureOnce sync.Once
|
configureOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *UncheckedTypeAssertionRule) configure(arguments lint.Arguments) {
|
func (r *UncheckedTypeAssertionRule) configure(arguments lint.Arguments) error {
|
||||||
if len(arguments) == 0 {
|
if len(arguments) == 0 {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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.")
|
return errors.New("unable to get arguments. Expected object of key-value-pairs")
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range args {
|
for k, v := range args {
|
||||||
@ -35,17 +36,23 @@ func (r *UncheckedTypeAssertionRule) configure(arguments lint.Arguments) {
|
|||||||
case "acceptIgnoredAssertionResult":
|
case "acceptIgnoredAssertionResult":
|
||||||
r.acceptIgnoredAssertionResult, ok = v.(bool)
|
r.acceptIgnoredAssertionResult, ok = v.(bool)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Unable to parse argument '%s'. Expected boolean.", k))
|
return fmt.Errorf("unable to parse argument '%s'. Expected boolean", k)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Unknown argument: %s", k))
|
return fmt.Errorf("unknown argument: %s", k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply applies the rule to given file.
|
// Apply applies the rule to given file.
|
||||||
func (r *UncheckedTypeAssertionRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure {
|
func (r *UncheckedTypeAssertionRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
|
||||||
r.configureOnce.Do(func() { r.configure(args) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package rule
|
package rule
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/types"
|
"go/types"
|
||||||
@ -18,30 +19,36 @@ type UnhandledErrorRule struct {
|
|||||||
configureOnce sync.Once
|
configureOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *UnhandledErrorRule) configure(arguments lint.Arguments) {
|
func (r *UnhandledErrorRule) configure(arguments lint.Arguments) error {
|
||||||
for _, arg := range arguments {
|
for _, arg := range arguments {
|
||||||
argStr, ok := arg.(string)
|
argStr, ok := arg.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid argument to the unhandled-error rule. Expecting a string, got %T", arg))
|
return fmt.Errorf("invalid argument to the unhandled-error rule. Expecting a string, got %T", arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
argStr = strings.Trim(argStr, " ")
|
argStr = strings.Trim(argStr, " ")
|
||||||
if argStr == "" {
|
if argStr == "" {
|
||||||
panic("Invalid argument to the unhandled-error rule, expected regular expression must not be empty.")
|
return errors.New("invalid argument to the unhandled-error rule, expected regular expression must not be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
exp, err := regexp.Compile(argStr)
|
exp, err := regexp.Compile(argStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("Invalid argument to the unhandled-error rule: regexp %q does not compile: %v", argStr, err))
|
return fmt.Errorf("invalid argument to the unhandled-error rule: regexp %q does not compile: %w", argStr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.ignoreList = append(r.ignoreList, exp)
|
r.ignoreList = append(r.ignoreList, exp)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, arguments lint.Arguments) []lint.Failure {
|
||||||
r.configureOnce.Do(func() { r.configure(args) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
|
||||||
|
@ -20,20 +20,20 @@ type UnusedParamRule struct {
|
|||||||
configureOnce sync.Once
|
configureOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *UnusedParamRule) configure(args lint.Arguments) {
|
func (r *UnusedParamRule) configure(args lint.Arguments) error {
|
||||||
// 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
|
||||||
r.allowRegex = allowBlankIdentifierRegex
|
r.allowRegex = allowBlankIdentifierRegex
|
||||||
r.failureMsg = "parameter '%s' seems to be unused, consider removing or renaming it as _"
|
r.failureMsg = "parameter '%s' seems to be unused, consider removing or renaming it as _"
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
// Arguments = [{}]
|
// Arguments = [{}]
|
||||||
options := args[0].(map[string]any)
|
options := args[0].(map[string]any)
|
||||||
|
|
||||||
allowRegexParam, ok := options["allowRegex"]
|
allowRegexParam, ok := options["allowRegex"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
// Arguments = [{allowRegex="^_"}]
|
// Arguments = [{allowRegex="^_"}]
|
||||||
allowRegexStr, ok := allowRegexParam.(string)
|
allowRegexStr, ok := allowRegexParam.(string)
|
||||||
@ -43,14 +43,21 @@ func (r *UnusedParamRule) configure(args lint.Arguments) {
|
|||||||
var err error
|
var err error
|
||||||
r.allowRegex, err = regexp.Compile(allowRegexStr)
|
r.allowRegex, err = regexp.Compile(allowRegexStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("error configuring %s rule: allowRegex is not valid regex [%s]: %v", r.Name(), allowRegexStr, err))
|
return fmt.Errorf("error configuring %s rule: allowRegex is not valid regex [%s]: %w", r.Name(), allowRegexStr, err)
|
||||||
}
|
}
|
||||||
r.failureMsg = "parameter '%s' seems to be unused, consider removing or renaming it to match " + r.allowRegex.String()
|
r.failureMsg = "parameter '%s' seems to be unused, consider removing or renaming it to match " + r.allowRegex.String()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, arguments lint.Arguments) []lint.Failure {
|
||||||
r.configureOnce.Do(func() { r.configure(args) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
|
||||||
onFailure := func(failure lint.Failure) {
|
onFailure := func(failure lint.Failure) {
|
||||||
|
@ -18,20 +18,20 @@ type UnusedReceiverRule struct {
|
|||||||
configureOnce sync.Once
|
configureOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *UnusedReceiverRule) configure(args lint.Arguments) {
|
func (r *UnusedReceiverRule) configure(args lint.Arguments) error {
|
||||||
// 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
|
||||||
r.allowRegex = allowBlankIdentifierRegex
|
r.allowRegex = allowBlankIdentifierRegex
|
||||||
r.failureMsg = "method receiver '%s' is not referenced in method's body, consider removing or renaming it as _"
|
r.failureMsg = "method receiver '%s' is not referenced in method's body, consider removing or renaming it as _"
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
// Arguments = [{}]
|
// Arguments = [{}]
|
||||||
options := args[0].(map[string]any)
|
options := args[0].(map[string]any)
|
||||||
|
|
||||||
allowRegexParam, ok := options["allowRegex"]
|
allowRegexParam, ok := options["allowRegex"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
// Arguments = [{allowRegex="^_"}]
|
// Arguments = [{allowRegex="^_"}]
|
||||||
allowRegexStr, ok := allowRegexParam.(string)
|
allowRegexStr, ok := allowRegexParam.(string)
|
||||||
@ -41,14 +41,21 @@ func (r *UnusedReceiverRule) configure(args lint.Arguments) {
|
|||||||
var err error
|
var err error
|
||||||
r.allowRegex, err = regexp.Compile(allowRegexStr)
|
r.allowRegex, err = regexp.Compile(allowRegexStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("error configuring [unused-receiver] rule: allowRegex is not valid regex [%s]: %v", allowRegexStr, err))
|
return fmt.Errorf("error configuring [unused-receiver] rule: allowRegex is not valid regex [%s]: %w", allowRegexStr, err)
|
||||||
}
|
}
|
||||||
r.failureMsg = "method receiver '%s' is not referenced in method's body, consider removing or renaming it to match " + r.allowRegex.String()
|
r.failureMsg = "method receiver '%s' is not referenced in method's body, consider removing or renaming it to match " + r.allowRegex.String()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, arguments lint.Arguments) []lint.Failure {
|
||||||
r.configureOnce.Do(func() { r.configure(args) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
|
||||||
for _, decl := range file.AST.Decls {
|
for _, decl := range file.AST.Decls {
|
||||||
|
@ -105,10 +105,11 @@ func gofmt(x any) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// checkNumberOfArguments fails if the given number of arguments is not, at least, the expected one
|
// checkNumberOfArguments fails if the given number of arguments is not, at least, the expected one
|
||||||
func checkNumberOfArguments(expected int, args lint.Arguments, ruleName string) {
|
func checkNumberOfArguments(expected int, args lint.Arguments, ruleName string) error {
|
||||||
if len(args) < expected {
|
if len(args) < expected {
|
||||||
panic(fmt.Sprintf("not enough arguments for %s rule, expected %d, got %d. Please check the rule's documentation", ruleName, expected, len(args)))
|
return fmt.Errorf("not enough arguments for %s rule, expected %d, got %d. Please check the rule's documentation", ruleName, expected, len(args))
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var directiveCommentRE = regexp.MustCompile("^//(line |extern |export |[a-z0-9]+:[a-z0-9])") // see https://go-review.googlesource.com/c/website/+/442516/1..2/_content/doc/comment.md#494
|
var directiveCommentRE = regexp.MustCompile("^//(line |extern |export |[a-z0-9]+:[a-z0-9])") // see https://go-review.googlesource.com/c/website/+/442516/1..2/_content/doc/comment.md#494
|
||||||
@ -121,3 +122,8 @@ func isDirectiveComment(line string) bool {
|
|||||||
func isCallToExitFunction(pkgName, functionName string) bool {
|
func isCallToExitFunction(pkgName, functionName string) bool {
|
||||||
return exitFunctions[pkgName] != nil && exitFunctions[pkgName][functionName]
|
return exitFunctions[pkgName] != nil && exitFunctions[pkgName][functionName]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newInternalFailureError returns an slice of Failure with a single internal failure in it
|
||||||
|
func newInternalFailureError(e error) []lint.Failure {
|
||||||
|
return []lint.Failure{lint.NewInternalFailure(e.Error())}
|
||||||
|
}
|
||||||
|
@ -33,13 +33,21 @@ type VarNamingRule struct {
|
|||||||
configureOnce sync.Once
|
configureOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *VarNamingRule) configure(arguments lint.Arguments) {
|
func (r *VarNamingRule) configure(arguments lint.Arguments) error {
|
||||||
if len(arguments) >= 1 {
|
if len(arguments) >= 1 {
|
||||||
r.allowList = getList(arguments[0], "allowlist")
|
list, err := getList(arguments[0], "allowlist")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.allowList = list
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(arguments) >= 2 {
|
if len(arguments) >= 2 {
|
||||||
r.blockList = getList(arguments[1], "blocklist")
|
list, err := getList(arguments[1], "blocklist")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.blockList = list
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(arguments) >= 3 {
|
if len(arguments) >= 3 {
|
||||||
@ -47,18 +55,19 @@ func (r *VarNamingRule) configure(arguments lint.Arguments) {
|
|||||||
thirdArgument := arguments[2]
|
thirdArgument := arguments[2]
|
||||||
asSlice, ok := thirdArgument.([]any)
|
asSlice, ok := thirdArgument.([]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid third argument to the var-naming rule. Expecting a %s of type slice, got %T", "options", arguments[2]))
|
return fmt.Errorf("invalid third argument to the var-naming rule. Expecting a %s of type slice, got %T", "options", arguments[2])
|
||||||
}
|
}
|
||||||
if len(asSlice) != 1 {
|
if len(asSlice) != 1 {
|
||||||
panic(fmt.Sprintf("Invalid third argument to the var-naming rule. Expecting a %s of type slice, of len==1, but %d", "options", len(asSlice)))
|
return fmt.Errorf("invalid third argument to the var-naming rule. Expecting a %s of type slice, of len==1, but %d", "options", len(asSlice))
|
||||||
}
|
}
|
||||||
args, ok := asSlice[0].(map[string]any)
|
args, ok := asSlice[0].(map[string]any)
|
||||||
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]))
|
return fmt.Errorf("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.allowUpperCaseConst = 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"
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *VarNamingRule) applyPackageCheckRules(walker *lintNames) {
|
func (r *VarNamingRule) applyPackageCheckRules(walker *lintNames) {
|
||||||
@ -83,7 +92,12 @@ 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.configureOnce.Do(func() { r.configure(arguments) })
|
var configureErr error
|
||||||
|
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
|
||||||
|
|
||||||
|
if configureErr != nil {
|
||||||
|
return newInternalFailureError(configureErr)
|
||||||
|
}
|
||||||
|
|
||||||
var failures []lint.Failure
|
var failures []lint.Failure
|
||||||
|
|
||||||
@ -263,18 +277,18 @@ func (w *lintNames) Visit(n ast.Node) ast.Visitor {
|
|||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
func getList(arg any, argName string) []string {
|
func getList(arg any, argName string) ([]string, error) {
|
||||||
args, ok := arg.([]any)
|
args, ok := arg.([]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid argument to the var-naming rule. Expecting a %s of type slice with initialisms, got %T", argName, arg))
|
return nil, fmt.Errorf("invalid argument to the var-naming rule. Expecting a %s of type slice with initialisms, got %T", argName, arg)
|
||||||
}
|
}
|
||||||
var list []string
|
var list []string
|
||||||
for _, v := range args {
|
for _, v := range args {
|
||||||
val, ok := v.(string)
|
val, ok := v.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Invalid %s values of the var-naming rule. Expecting slice of strings but got element of type %T", val, arg))
|
return nil, fmt.Errorf("invalid %s values of the var-naming rule. Expecting slice of strings but got element of type %T", val, arg)
|
||||||
}
|
}
|
||||||
list = append(list, val)
|
list = append(list, val)
|
||||||
}
|
}
|
||||||
return list
|
return list, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user