mirror of
https://github.com/mgechev/revive.git
synced 2025-11-23 22:04:49 +02:00
refactor: enable godoclint linter in golangci-lint (#1576)
This commit is contained in:
@@ -9,6 +9,7 @@ linters:
|
|||||||
- dupword
|
- dupword
|
||||||
- gocritic
|
- gocritic
|
||||||
- godot
|
- godot
|
||||||
|
- godoclint
|
||||||
- govet
|
- govet
|
||||||
- ineffassign
|
- ineffassign
|
||||||
- misspell
|
- misspell
|
||||||
@@ -19,12 +20,32 @@ linters:
|
|||||||
- staticcheck
|
- staticcheck
|
||||||
- unused
|
- unused
|
||||||
|
|
||||||
|
exclusions:
|
||||||
|
warn-unused: true
|
||||||
|
rules:
|
||||||
|
- path: '(.+)_test\.go'
|
||||||
|
linters:
|
||||||
|
- godoclint
|
||||||
|
- linters:
|
||||||
|
- godoclint
|
||||||
|
text: 'symbol should have a godoc \("Visit"\)'
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
gocritic:
|
gocritic:
|
||||||
enable-all: true
|
enable-all: true
|
||||||
disabled-checks:
|
disabled-checks:
|
||||||
- hugeParam
|
- hugeParam
|
||||||
- rangeValCopy
|
- rangeValCopy
|
||||||
|
godoclint:
|
||||||
|
default: all
|
||||||
|
options:
|
||||||
|
max-len:
|
||||||
|
length: 120
|
||||||
|
require-doc:
|
||||||
|
ignore-exported: false
|
||||||
|
ignore-unexported: true
|
||||||
|
start-with-name:
|
||||||
|
include-unexported: true
|
||||||
govet:
|
govet:
|
||||||
enable-all: true
|
enable-all: true
|
||||||
disable:
|
disable:
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ func ParseFileFilter(rawFilter string) (*FileFilter, error) {
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the original raw filter definition as it appears in the configuration.
|
||||||
func (ff *FileFilter) String() string { return ff.raw }
|
func (ff *FileFilter) String() string { return ff.raw }
|
||||||
|
|
||||||
// MatchFileName checks if the file name matches the filter.
|
// MatchFileName checks if the file name matches the filter.
|
||||||
|
|||||||
@@ -198,6 +198,7 @@ func normalizeSplit(strs []string) []string {
|
|||||||
// ArrayFlags type for string list.
|
// ArrayFlags type for string list.
|
||||||
type ArrayFlags []string
|
type ArrayFlags []string
|
||||||
|
|
||||||
|
// String returns the space-separated representation of the ArrayFlags.
|
||||||
func (i *ArrayFlags) String() string {
|
func (i *ArrayFlags) String() string {
|
||||||
return strings.Join([]string(*i), " ")
|
return strings.Join([]string(*i), " ")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,8 @@ func (*ConfusingNamingRule) Name() string {
|
|||||||
return "confusing-naming"
|
return "confusing-naming"
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkMethodName checks if a given method/function name is similar (just case differences) to other method/function of the same struct/file.
|
// checkMethodName checks if a given method/function name is similar (just case differences) to other method/function
|
||||||
|
// of the same struct/file.
|
||||||
func checkMethodName(holder string, id *ast.Ident, w *lintConfusingNames) {
|
func checkMethodName(holder string, id *ast.Ident, w *lintConfusingNames) {
|
||||||
if id.Name == "init" && holder == defaultStructName {
|
if id.Name == "init" && holder == defaultStructName {
|
||||||
// ignore init functions
|
// ignore init functions
|
||||||
|
|||||||
@@ -170,15 +170,15 @@ func (w *lintExported) lintFuncDoc(fn *ast.FuncDecl) {
|
|||||||
case exportedGoDocStatusOK:
|
case exportedGoDocStatusOK:
|
||||||
return // comment is fine
|
return // comment is fine
|
||||||
case exportedGoDocStatusMissing:
|
case exportedGoDocStatusMissing:
|
||||||
w.addFailuref(fn, status.Confidence(), lint.FailureCategoryComments,
|
w.addFailuref(fn, status.confidence(), lint.FailureCategoryComments,
|
||||||
"exported %s %s should have comment or be unexported", kind, name,
|
"exported %s %s should have comment or be unexported", kind, name,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
firstCommentLine := w.firstCommentLine(fn.Doc)
|
firstCommentLine := w.firstCommentLine(fn.Doc)
|
||||||
w.addFailuref(fn.Doc, status.Confidence(), lint.FailureCategoryComments,
|
w.addFailuref(fn.Doc, status.confidence(), lint.FailureCategoryComments,
|
||||||
`comment on exported %s %s should be of the form "%s ..."%s`, kind, name, fn.Name.Name, status.CorrectionHint(firstCommentLine),
|
`comment on exported %s %s should be of the form "%s ..."%s`, kind, name, fn.Name.Name, status.correctionHint(firstCommentLine),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,8 +264,8 @@ func (w *lintExported) lintTypeDoc(t *ast.TypeSpec, doc *ast.CommentGroup, first
|
|||||||
if status == exportedGoDocStatusOK {
|
if status == exportedGoDocStatusOK {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.addFailuref(doc, status.Confidence(), lint.FailureCategoryComments,
|
w.addFailuref(doc, status.confidence(), lint.FailureCategoryComments,
|
||||||
`comment on exported type %v should be of the form "%s ..." (with optional leading article)%s`, t.Name, typeName, status.CorrectionHint(firstCommentLine),
|
`comment on exported type %v should be of the form "%s ..." (with optional leading article)%s`, t.Name, typeName, status.correctionHint(firstCommentLine),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,8 +347,8 @@ func (w *lintExported) lintValueSpecDoc(vs *ast.ValueSpec, gd *ast.GenDecl, genD
|
|||||||
if status == exportedGoDocStatusOK {
|
if status == exportedGoDocStatusOK {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.addFailuref(doc, status.Confidence(), lint.FailureCategoryComments,
|
w.addFailuref(doc, status.confidence(), lint.FailureCategoryComments,
|
||||||
`comment on exported %s %s should be of the form "%s ..."%s`, kind, name, name, status.CorrectionHint(firstCommentLine),
|
`comment on exported %s %s should be of the form "%s ..."%s`, kind, name, name, status.correctionHint(firstCommentLine),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,14 +362,14 @@ const (
|
|||||||
exportedGoDocStatusUnexpected
|
exportedGoDocStatusUnexpected
|
||||||
)
|
)
|
||||||
|
|
||||||
func (gds exportedGoDocStatus) Confidence() float64 {
|
func (gds exportedGoDocStatus) confidence() float64 {
|
||||||
if gds == exportedGoDocStatusUnexpected {
|
if gds == exportedGoDocStatusUnexpected {
|
||||||
return 0.8
|
return 0.8
|
||||||
}
|
}
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gds exportedGoDocStatus) CorrectionHint(firstCommentLine string) string {
|
func (gds exportedGoDocStatus) correctionHint(firstCommentLine string) string {
|
||||||
firstWord := strings.Split(firstCommentLine, " ")[0]
|
firstWord := strings.Split(firstCommentLine, " ")[0]
|
||||||
switch gds {
|
switch gds {
|
||||||
case exportedGoDocStatusCaseMismatch:
|
case exportedGoDocStatusCaseMismatch:
|
||||||
@@ -501,15 +501,15 @@ func (w *lintExported) lintInterfaceMethod(typeName string, m *ast.Field) {
|
|||||||
case exportedGoDocStatusOK:
|
case exportedGoDocStatusOK:
|
||||||
return // comment is fine
|
return // comment is fine
|
||||||
case exportedGoDocStatusMissing:
|
case exportedGoDocStatusMissing:
|
||||||
w.addFailuref(m, status.Confidence(), lint.FailureCategoryComments,
|
w.addFailuref(m, status.confidence(), lint.FailureCategoryComments,
|
||||||
"public interface method %s.%s should be commented", typeName, name,
|
"public interface method %s.%s should be commented", typeName, name,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
firstCommentLine := w.firstCommentLine(m.Doc)
|
firstCommentLine := w.firstCommentLine(m.Doc)
|
||||||
w.addFailuref(m.Doc, status.Confidence(), lint.FailureCategoryComments,
|
w.addFailuref(m.Doc, status.confidence(), lint.FailureCategoryComments,
|
||||||
`comment on exported interface method %s.%s should be of the form "%s ..."%s`, typeName, name, name, status.CorrectionHint(firstCommentLine),
|
`comment on exported interface method %s.%s should be of the form "%s ..."%s`, typeName, name, name, status.correctionHint(firstCommentLine),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ type stringFormatSubruleScope struct {
|
|||||||
field string // (optional) If the argument to be checked is a struct, which member of the struct is checked against the rule (top level members only)
|
field string // (optional) If the argument to be checked is a struct, which member of the struct is checked against the rule (top level members only)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regex inserted to match valid function/struct field identifiers.
|
// identRegex matches valid function/struct field identifiers.
|
||||||
const identRegex = "[_A-Za-z][_A-Za-z0-9]*"
|
const identRegex = "[_A-Za-z][_A-Za-z0-9]*"
|
||||||
|
|
||||||
var parseStringFormatScope = regexp.MustCompile(
|
var parseStringFormatScope = regexp.MustCompile(
|
||||||
@@ -165,17 +165,18 @@ func (r *StringFormatRule) parseArgument(argument any, ruleNum int) (scopes stri
|
|||||||
return scopes, regex, negated, errorMessage, nil
|
return scopes, regex, negated, errorMessage, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report an invalid config, this is specifically the user's fault.
|
// configError reports an invalid config, this is specifically the user's fault.
|
||||||
func (*StringFormatRule) configError(msg string, ruleNum, option int) error {
|
func (*StringFormatRule) configError(msg string, ruleNum, option int) error {
|
||||||
return fmt.Errorf("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.
|
// parseError reports a general config parsing failure, this may be the user's fault, but it isn't known for certain.
|
||||||
func (*StringFormatRule) parseError(msg string, ruleNum, option int) error {
|
func (*StringFormatRule) parseError(msg string, ruleNum, option int) error {
|
||||||
return fmt.Errorf("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.
|
// parseScopeError reports a general scope config parsing failure, this may be the user's fault,
|
||||||
|
// but it isn't known for certain.
|
||||||
func (*StringFormatRule) parseScopeError(msg string, ruleNum, option, scopeNum int) error {
|
func (*StringFormatRule) parseScopeError(msg string, ruleNum, option, scopeNum int) error {
|
||||||
return fmt.Errorf("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)
|
||||||
}
|
}
|
||||||
@@ -204,7 +205,7 @@ func (w *lintStringFormatRule) Visit(node ast.Node) ast.Visitor {
|
|||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the name of a call expression in the form of package.Func or Func.
|
// getCallName returns the name of a call expression in the form of package.Func or Func.
|
||||||
func (*lintStringFormatRule) getCallName(call *ast.CallExpr) (callName string, ok bool) {
|
func (*lintStringFormatRule) getCallName(call *ast.CallExpr) (callName string, ok bool) {
|
||||||
if ident, ok := call.Fun.(*ast.Ident); ok {
|
if ident, ok := call.Fun.(*ast.Ident); ok {
|
||||||
// Local function call
|
// Local function call
|
||||||
@@ -227,7 +228,8 @@ func (*lintStringFormatRule) getCallName(call *ast.CallExpr) (callName string, o
|
|||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply a single format rule to a call expression (should be done after verifying the that the call expression matches the rule's scope).
|
// apply a single format rule to a call expression
|
||||||
|
// (should be done after verifying the that the call expression matches the rule's scope).
|
||||||
func (r *stringFormatSubrule) apply(call *ast.CallExpr, scope *stringFormatSubruleScope) {
|
func (r *stringFormatSubrule) apply(call *ast.CallExpr, scope *stringFormatSubruleScope) {
|
||||||
if len(call.Args) <= scope.argument {
|
if len(call.Args) <= scope.argument {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1003,7 +1003,7 @@ var validateSingleOptions = map[string]struct{}{
|
|||||||
"validateFn": {},
|
"validateFn": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are options that are used in expressions of the form:
|
// validateLHS are options that are used in expressions of the form:
|
||||||
//
|
//
|
||||||
// <option> = <RHS>
|
// <option> = <RHS>
|
||||||
var validateLHS = map[string]struct{}{
|
var validateLHS = map[string]struct{}{
|
||||||
|
|||||||
@@ -136,7 +136,8 @@ func (w *lintUncheckedTypeAssertion) handleAssignment(n *ast.AssignStmt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handles "return foo(.*bar)" - one of them is enough to fail as golang does not forward the type cast tuples in return statements.
|
// handleReturn handles "return foo(.*bar)" - one of them is enough to fail
|
||||||
|
// as Go does not forward the type cast tuples in return statements.
|
||||||
func (w *lintUncheckedTypeAssertion) handleReturn(n *ast.ReturnStmt) {
|
func (w *lintUncheckedTypeAssertion) handleReturn(n *ast.ReturnStmt) {
|
||||||
for _, r := range n.Results {
|
for _, r := range n.Results {
|
||||||
w.requireNoTypeAssert(r)
|
w.requireNoTypeAssert(r)
|
||||||
|
|||||||
@@ -79,11 +79,14 @@ type lintUnconditionalRecursionRule struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Visit will traverse function's body we search for calls to the function itself.
|
// Visit will traverse function's body we search for calls to the function itself.
|
||||||
// We do not search inside conditional control structures (if, for, switch, ...) because any recursive call inside them is conditioned.
|
// We do not search inside conditional control structures (if, for, switch, ...)
|
||||||
// We do search inside conditional control structures are statements that will take the control out of the function (return, exit, panic).
|
// because any recursive call inside them is conditioned.
|
||||||
|
// We do search inside conditional control structures are statements
|
||||||
|
// that will take the control out of the function (return, exit, panic).
|
||||||
// If we find conditional control exits, it means the function is NOT unconditionally-recursive.
|
// If we find conditional control exits, it means the function is NOT unconditionally-recursive.
|
||||||
// If we find a recursive call before finding any conditional exit, a failure is generated.
|
// If we find a recursive call before finding any conditional exit, a failure is generated.
|
||||||
// In resume: if we found a recursive call control-dependent from the entry point of the function then we raise a failure.
|
// In resume: if we found a recursive call control-dependent from the entry point of
|
||||||
|
// the function then we raise a failure.
|
||||||
func (w *lintUnconditionalRecursionRule) Visit(node ast.Node) ast.Visitor {
|
func (w *lintUnconditionalRecursionRule) Visit(node ast.Node) ast.Visitor {
|
||||||
switch n := node.(type) {
|
switch n := node.(type) {
|
||||||
case *ast.CallExpr:
|
case *ast.CallExpr:
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ import (
|
|||||||
"github.com/mgechev/revive/lint"
|
"github.com/mgechev/revive/lint"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UnsecureURLSchemeRule checks if a file contains string literals with unsecure URL schemes (for example: http://... in place of https://...).
|
// UnsecureURLSchemeRule checks if a file contains string literals with unsecure URL schemes.
|
||||||
|
// For example: http://... in place of https://....
|
||||||
type UnsecureURLSchemeRule struct{}
|
type UnsecureURLSchemeRule struct{}
|
||||||
|
|
||||||
// Apply applied the rule to the given file.
|
// Apply applied the rule to the given file.
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ func (*lintUseWaitGroupGo) isCallToWgAdd(stmt ast.Stmt) bool {
|
|||||||
return ok && astutils.IsPkgDotName(call.Fun, "wg", "Add")
|
return ok && astutils.IsPkgDotName(call.Fun, "wg", "Add")
|
||||||
}
|
}
|
||||||
|
|
||||||
// function used when calling astutils.SeekNode that search for calls to wg.Done.
|
// wgDonePicker is used when calling astutils.SeekNode that search for calls to wg.Done.
|
||||||
func wgDonePicker(n ast.Node) bool {
|
func wgDonePicker(n ast.Node) bool {
|
||||||
call, ok := n.(*ast.CallExpr)
|
call, ok := n.(*ast.CallExpr)
|
||||||
result := ok && astutils.IsPkgDotName(call.Fun, "wg", "Done")
|
result := ok && astutils.IsPkgDotName(call.Fun, "wg", "Done")
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"github.com/mgechev/revive/lint"
|
"github.com/mgechev/revive/lint"
|
||||||
)
|
)
|
||||||
|
|
||||||
// exitChecker is a function type that checks whether a function call is an exit function.
|
// exitFuncChecker is a function type that checks whether a function call is an exit function.
|
||||||
type exitFuncChecker func(args []ast.Expr) bool
|
type exitFuncChecker func(args []ast.Expr) bool
|
||||||
|
|
||||||
var alwaysTrue exitFuncChecker = func([]ast.Expr) bool { return true }
|
var alwaysTrue exitFuncChecker = func([]ast.Expr) bool { return true }
|
||||||
|
|||||||
@@ -372,7 +372,8 @@ func (w *lintNames) Visit(n ast.Node) ast.Visitor {
|
|||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
// isUpperCaseConst checks if a string is in constant name format like `SOME_CONST`, `SOME_CONST_2`, `X123_3`, `_SOME_PRIVATE_CONST`.
|
// isUpperCaseConst checks if a string is in constant name format like `SOME_CONST`, `SOME_CONST_2`,
|
||||||
|
// `X123_3`, `_SOME_PRIVATE_CONST`.
|
||||||
// See #851, #865.
|
// See #851, #865.
|
||||||
func isUpperCaseConst(s string) bool {
|
func isUpperCaseConst(s string) bool {
|
||||||
if s == "" {
|
if s == "" {
|
||||||
@@ -418,7 +419,7 @@ func isUpperOrDigit(r rune) bool {
|
|||||||
return isUpper(r) || isDigit(r)
|
return isUpper(r) || isDigit(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// isUpper checks if rune is a simple digit.
|
// isDigit checks if rune is a simple digit.
|
||||||
//
|
//
|
||||||
// We don't use unicode.IsDigit as it returns true for a large variety of digits that are not 0-9.
|
// We don't use unicode.IsDigit as it returns true for a large variety of digits that are not 0-9.
|
||||||
func isDigit(r rune) bool {
|
func isDigit(r rune) bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user