Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions .golangci.next.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ linters:
- goconst
- gocritic
- gocyclo
- godoclint
- godot
- godox
- goheader
Expand Down Expand Up @@ -170,6 +171,7 @@ linters:
- goconst
- gocritic
- gocyclo
- godoclint
- godot
- godox
- goheader
Expand Down Expand Up @@ -1266,6 +1268,74 @@ linters:
# Default: 30 (but we recommend 10-20)
min-complexity: 10

godoclint:
# Default set of rules to enable.
# Possible values are: `basic`, `all` or `none`.
# Default: `basic` (enables `pkg-doc`, `single-pkg-doc`, `start-with-name`, and `deprecated`)
default: all

# List of rules to enable in addition to the default set.
# Default: empty
enable:
# Check proper package-level godoc, if any.
# https://github.com/godoc-lint/godoc-lint?tab=readme-ov-file#pkg-doc
- pkg-doc
# Assert at most one godoc per package.
# https://github.com/godoc-lint/godoc-lint?tab=readme-ov-file#single-pkg-doc
- single-pkg-doc
# Require all packages to have a godoc.
# https://github.com/godoc-lint/godoc-lint?tab=readme-ov-file#require-pkg-doc
- require-pkg-doc
# Assert symbol godocs start with the symbol name.
# https://github.com/godoc-lint/godoc-lint?tab=readme-ov-file#start-with-name
- start-with-name
# Require godoc for all public symbols.
# https://github.com/godoc-lint/godoc-lint?tab=readme-ov-file#require-doc
- require-doc
# Assert correct formatting of deprecation notes.
# https://github.com/godoc-lint/godoc-lint?tab=readme-ov-file#deprecated
- deprecated
# Assert maximum line length for godocs.
# https://github.com/godoc-lint/godoc-lint?tab=readme-ov-file#max-len
- max-len
# Assert no unused link in godocs.
# https://github.com/godoc-lint/godoc-lint?tab=readme-ov-file#no-unused-link
- no-unused-link

# List of rules to disable.
# Default: empty
disable:
- pkg-doc
- single-pkg-doc
- require-pkg-doc
- start-with-name
- require-doc
- deprecated
- max-len
- no-unused-link

# A map for fine-tuning individual rules.
# All subkeys are optional.
options:
max-len:
# Maximum line length for godocs, not including the `// `, or `/*` or `*/` tokens.
# Default: 77
length: 127

require-doc:
# Ignore exported (public) symbols when applying the `require-doc` rule.
# Default: false
ignore-exported: true

# Ignore unexported (private) symbols when applying the `require-doc` rule.
# Default: true
ignore-unexported: false

start-with-name:
# Include unexported symbols when applying the `start-with-name` rule.
# Default: false
include-unexported: true

godot:
# Comments to be checked: `declarations`, `toplevel`, `noinline` or `all`.
# Default: declarations
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ require (
github.com/go-critic/go-critic v0.13.0
github.com/go-viper/mapstructure/v2 v2.4.0
github.com/go-xmlfmt/xmlfmt v1.1.3
github.com/godoc-lint/godoc-lint v0.10.0
github.com/gofrs/flock v0.12.1
github.com/golangci/asciicheck v0.5.0
github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32
Expand Down
2 changes: 2 additions & 0 deletions go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

84 changes: 84 additions & 0 deletions jsonschema/golangci.next.jsonschema.json
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,18 @@
"-QF1012"
]
},
"godoclint-rules": {
"enum": [
"pkg-doc",
"single-pkg-doc",
"require-pkg-doc",
"start-with-name",
"require-doc",
"deprecated",
"max-len",
"no-unused-link"
]
},
"gosec-rules": {
"enum": [
"G101",
Expand Down Expand Up @@ -795,6 +807,7 @@
"goconst",
"gocritic",
"gocyclo",
"godoclint",
"godot",
"godox",
"err113",
Expand Down Expand Up @@ -1848,6 +1861,74 @@
}
}
},
"godoclintSettings": {
"type": "object",
"properties": {
"default": {
"type": "string",
"enum": ["all", "basic", "none"],
"default": "basic",
"description": "Default set of rules to enable."
},
"enable": {
"description": "List of rules to enable in addition to the default set.",
"type": "array",
"uniqueItems": true,
"items": {
"$ref": "#/definitions/godoclint-rules"
}
},
"disable": {
"description": "List of rules to disable.",
"type": "array",
"uniqueItems": true,
"items": {
"$ref": "#/definitions/godoclint-rules"
}
},
"options": {
"type": "object",
"description": "A map for setting individual rule options.",
"properties": {
"max-len": {
"type": "object",
"properties": {
"length": {
"type": "integer",
"description": "Maximum line length for godocs, not including the `// `, or `/*` or `*/` tokens.",
"default": 77
}
}
},
"require-doc": {
"type": "object",
"properties": {
"ignore-exported": {
"type": "boolean",
"description": "Ignore exported (public) symbols when applying the `require-doc` rule.",
"default": false
},
"ignore-unexported": {
"type": "boolean",
"description": "Ignore unexported (private) symbols when applying the `require-doc` rule.",
"default": true
}
}
},
"start-with-name": {
"type": "object",
"properties": {
"include-unexported": {
"type": "boolean",
"description": "Include unexported symbols when applying the `start-with-name` rule.",
"default": false
}
}
}
}
}
}
},
"godotSettings": {
"type": "object",
"additionalProperties": false,
Expand Down Expand Up @@ -4547,6 +4628,9 @@
"gocyclo": {
"$ref": "#/definitions/settings/definitions/gocycloSettings"
},
"godoclint": {
"$ref": "#/definitions/settings/definitions/godoclintSettings"
},
"godot": {
"$ref": "#/definitions/settings/definitions/godotSettings"
},
Expand Down
19 changes: 19 additions & 0 deletions pkg/config/linters_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ type LintersSettings struct {
Goconst GoConstSettings `mapstructure:"goconst"`
Gocritic GoCriticSettings `mapstructure:"gocritic"`
Gocyclo GoCycloSettings `mapstructure:"gocyclo"`
Godoclint GodoclintSettings `mapstructure:"godoclint"`
Godot GodotSettings `mapstructure:"godot"`
Godox GodoxSettings `mapstructure:"godox"`
Goheader GoHeaderSettings `mapstructure:"goheader"`
Expand Down Expand Up @@ -520,6 +521,24 @@ type GoCycloSettings struct {
MinComplexity int `mapstructure:"min-complexity"`
}

type GodoclintSettings struct {
Default *string `mapstructure:"default"`
Enable []string `mapstructure:"enable"`
Disable []string `mapstructure:"disable"`
Options struct {
MaxLen struct {
Length *uint `mapstructure:"length"`
} `mapstructure:"max-len"`
RequireDoc struct {
IgnoreExported *bool `mapstructure:"ignore-exported"`
IgnoreUnexported *bool `mapstructure:"ignore-unexported"`
} `mapstructure:"require-doc"`
StartWithName struct {
IncludeUnexported *bool `mapstructure:"include-unexported"`
} `mapstructure:"start-with-name"`
} `mapstructure:"options"`
}

type GodotSettings struct {
Scope string `mapstructure:"scope"`
Exclude []string `mapstructure:"exclude"`
Expand Down
109 changes: 109 additions & 0 deletions pkg/golinters/godoclint/godoclint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package godoclint

import (
"errors"
"fmt"
"slices"

glcompose "github.com/godoc-lint/godoc-lint/pkg/compose"
glconfig "github.com/godoc-lint/godoc-lint/pkg/config"
"github.com/godoc-lint/godoc-lint/pkg/model"

"github.com/golangci/golangci-lint/v2/pkg/config"
"github.com/golangci/golangci-lint/v2/pkg/goanalysis"
"github.com/golangci/golangci-lint/v2/pkg/golinters/internal"
)

func New(settings *config.GodoclintSettings) *goanalysis.Linter {
var pcfg glconfig.PlainConfig

if settings != nil {
err := checkSettings(settings)
if err != nil {
internal.LinterLogger.Fatalf("godoclint: %v", err)
}

// The following options are explicitly ignored: they must be handled globally with exclusions or nolint directives.
// - Include
// - Exclude

// The following options are explicitly ignored: these options cannot work as expected because the global configuration about tests.
// - Options.MaxLenIncludeTests
// - Options.PkgDocIncludeTests
// - Options.SinglePkgDocIncludeTests
// - Options.RequirePkgDocIncludeTests
// - Options.RequireDocIncludeTests
// - Options.StartWithNameIncludeTests
// - Options.NoUnusedLinkIncludeTests

pcfg = glconfig.PlainConfig{
Default: settings.Default,
Enable: settings.Enable,
Disable: settings.Disable,
Options: &glconfig.PlainRuleOptions{
MaxLenLength: settings.Options.MaxLen.Length,
MaxLenIncludeTests: pointer(true),
PkgDocIncludeTests: pointer(false),
SinglePkgDocIncludeTests: pointer(true),
RequirePkgDocIncludeTests: pointer(false),
RequireDocIncludeTests: pointer(true),
RequireDocIgnoreExported: settings.Options.RequireDoc.IgnoreExported,
RequireDocIgnoreUnexported: settings.Options.RequireDoc.IgnoreUnexported,
StartWithNameIncludeTests: pointer(false),
StartWithNameIncludeUnexported: settings.Options.StartWithName.IncludeUnexported,
NoUnusedLinkIncludeTests: pointer(true),
},
}
}

composition := glcompose.Compose(glcompose.CompositionConfig{
BaseDirPlainConfig: &pcfg,
ExitFunc: func(_ int, err error) {
internal.LinterLogger.Errorf("godoclint: %v", err)
},
})

return goanalysis.
NewLinterFromAnalyzer(composition.Analyzer.GetAnalyzer()).
WithLoadMode(goanalysis.LoadModeSyntax)
}

func checkSettings(settings *config.GodoclintSettings) error {
switch deref(settings.Default) {
case string(model.DefaultSetAll):
if len(settings.Enable) > 0 {
return errors.New("cannot use 'enable' with 'default=all'")
}

case string(model.DefaultSetNone):
if len(settings.Disable) > 0 {
return errors.New("cannot use 'disable' with 'default=none'")
}

default:
for _, rule := range settings.Enable {
if slices.Contains(settings.Disable, rule) {
return fmt.Errorf("a rule cannot be enabled and disabled at the same time: '%s'", rule)
}
}

for _, rule := range settings.Disable {
if slices.Contains(settings.Enable, rule) {
return fmt.Errorf("a rule cannot be enabled and disabled at the same time: '%s'", rule)
}
}
}

return nil
}

func pointer[T any](v T) *T { return &v }

func deref[T any](v *T) T {
if v == nil {
var zero T
return zero
}

return *v
}
11 changes: 11 additions & 0 deletions pkg/golinters/godoclint/godoclint_integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package godoclint

import (
"testing"

"github.com/golangci/golangci-lint/v2/test/testshared/integration"
)

func TestFromTestdata(t *testing.T) {
integration.RunTestdata(t)
}
22 changes: 22 additions & 0 deletions pkg/golinters/godoclint/testdata/godoclint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: "2"

linters:
settings:
godoclint:
default: none
enable:
- pkg-doc
- require-pkg-doc
- start-with-name
- require-doc
- deprecated
- max-len
- no-unused-link
options:
start-with-name:
include-unexported: true
require-doc:
ignore-exported: false
ignore-unexported: false
max-len:
length: 127
Loading
Loading