From a295bebe6ecbbc65988609184d86e37ab2d551b8 Mon Sep 17 00:00:00 2001 From: Oleksandr Redko Date: Fri, 14 Nov 2025 18:02:48 +0200 Subject: [PATCH] refactor: enable godoclint linter in golangci-lint (#1576) --- .golangci.yml | 21 +++++++++++++++++++++ lint/filefilter.go | 1 + revivelib/core.go | 1 + rule/confusing_naming.go | 3 ++- rule/exported.go | 24 ++++++++++++------------ rule/string_format.go | 14 ++++++++------ rule/struct_tag.go | 2 +- rule/unchecked_type_assertion.go | 3 ++- rule/unconditional_recursion.go | 9 ++++++--- rule/unsecure_url_scheme.go | 3 ++- rule/use_waitgroup_go.go | 2 +- rule/utils.go | 2 +- rule/var_naming.go | 5 +++-- 13 files changed, 61 insertions(+), 29 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 216d9c4..18c8bf3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -9,6 +9,7 @@ linters: - dupword - gocritic - godot + - godoclint - govet - ineffassign - misspell @@ -19,12 +20,32 @@ linters: - staticcheck - unused + exclusions: + warn-unused: true + rules: + - path: '(.+)_test\.go' + linters: + - godoclint + - linters: + - godoclint + text: 'symbol should have a godoc \("Visit"\)' + settings: gocritic: enable-all: true disabled-checks: - hugeParam - rangeValCopy + godoclint: + default: all + options: + max-len: + length: 120 + require-doc: + ignore-exported: false + ignore-unexported: true + start-with-name: + include-unexported: true govet: enable-all: true disable: diff --git a/lint/filefilter.go b/lint/filefilter.go index 9978597..3a523f2 100644 --- a/lint/filefilter.go +++ b/lint/filefilter.go @@ -41,6 +41,7 @@ func ParseFileFilter(rawFilter string) (*FileFilter, error) { return result, nil } +// String returns the original raw filter definition as it appears in the configuration. func (ff *FileFilter) String() string { return ff.raw } // MatchFileName checks if the file name matches the filter. diff --git a/revivelib/core.go b/revivelib/core.go index 74639b7..b2996a8 100755 --- a/revivelib/core.go +++ b/revivelib/core.go @@ -198,6 +198,7 @@ func normalizeSplit(strs []string) []string { // ArrayFlags type for string list. type ArrayFlags []string +// String returns the space-separated representation of the ArrayFlags. func (i *ArrayFlags) String() string { return strings.Join([]string(*i), " ") } diff --git a/rule/confusing_naming.go b/rule/confusing_naming.go index 83f53a5..ef78b60 100644 --- a/rule/confusing_naming.go +++ b/rule/confusing_naming.go @@ -70,7 +70,8 @@ func (*ConfusingNamingRule) Name() string { 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) { if id.Name == "init" && holder == defaultStructName { // ignore init functions diff --git a/rule/exported.go b/rule/exported.go index eb351cf..cc72d7d 100644 --- a/rule/exported.go +++ b/rule/exported.go @@ -170,15 +170,15 @@ func (w *lintExported) lintFuncDoc(fn *ast.FuncDecl) { case exportedGoDocStatusOK: return // comment is fine 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, ) return } firstCommentLine := w.firstCommentLine(fn.Doc) - 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), + 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), ) } @@ -264,8 +264,8 @@ func (w *lintExported) lintTypeDoc(t *ast.TypeSpec, doc *ast.CommentGroup, first if status == exportedGoDocStatusOK { return } - 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), + 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), ) } @@ -347,8 +347,8 @@ func (w *lintExported) lintValueSpecDoc(vs *ast.ValueSpec, gd *ast.GenDecl, genD if status == exportedGoDocStatusOK { return } - 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), + 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), ) } @@ -362,14 +362,14 @@ const ( exportedGoDocStatusUnexpected ) -func (gds exportedGoDocStatus) Confidence() float64 { +func (gds exportedGoDocStatus) confidence() float64 { if gds == exportedGoDocStatusUnexpected { return 0.8 } return 1 } -func (gds exportedGoDocStatus) CorrectionHint(firstCommentLine string) string { +func (gds exportedGoDocStatus) correctionHint(firstCommentLine string) string { firstWord := strings.Split(firstCommentLine, " ")[0] switch gds { case exportedGoDocStatusCaseMismatch: @@ -501,15 +501,15 @@ func (w *lintExported) lintInterfaceMethod(typeName string, m *ast.Field) { case exportedGoDocStatusOK: return // comment is fine 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, ) return } firstCommentLine := w.firstCommentLine(m.Doc) - 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), + 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), ) } diff --git a/rule/string_format.go b/rule/string_format.go index b653cb1..4c7c865 100644 --- a/rule/string_format.go +++ b/rule/string_format.go @@ -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) } -// 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]*" var parseStringFormatScope = regexp.MustCompile( @@ -165,17 +165,18 @@ func (r *StringFormatRule) parseArgument(argument any, ruleNum int) (scopes stri 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 { 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 { 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 { 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 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) { if ident, ok := call.Fun.(*ast.Ident); ok { // Local function call @@ -227,7 +228,8 @@ func (*lintStringFormatRule) getCallName(call *ast.CallExpr) (callName string, o 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) { if len(call.Args) <= scope.argument { return diff --git a/rule/struct_tag.go b/rule/struct_tag.go index 0830a25..385938c 100644 --- a/rule/struct_tag.go +++ b/rule/struct_tag.go @@ -1003,7 +1003,7 @@ var validateSingleOptions = map[string]struct{}{ "validateFn": {}, } -// These are options that are used in expressions of the form: +// validateLHS are options that are used in expressions of the form: // //