Skip to content

feat: use homogeneous JSON flags #5522

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 11, 2025
Merged
Show file tree
Hide file tree
Changes from 3 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
9 changes: 8 additions & 1 deletion .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,21 @@ jobs:

- run: ./golangci-lint config
- run: ./golangci-lint config path
- run: ./golangci-lint config path --json
# TODO(ldez) after v2: golangci.next.jsonschema.json -> golangci.jsonschema.json
- run: ./golangci-lint config verify --schema jsonschema/golangci.next.jsonschema.json

- run: ./golangci-lint help
- run: ./golangci-lint help linters
- run: ./golangci-lint help linters --json
- run: ./golangci-lint help formatters
- run: ./golangci-lint help formatters --json
- run: ./golangci-lint linters
- run: ./golangci-lint linters --json
- run: ./golangci-lint formatters
- run: ./golangci-lint formatters --json
- run: ./golangci-lint version
- run: ./golangci-lint version --format json
- run: ./golangci-lint version --short
- run: ./golangci-lint version --debug
- run: ./golangci-lint version --json
- run: ./golangci-lint version --json --debug
24 changes: 24 additions & 0 deletions pkg/commands/formatters.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package commands

import (
"encoding/json"
"fmt"

"github.com/fatih/color"
Expand All @@ -14,8 +15,14 @@ import (
"github.com/golangci/golangci-lint/pkg/logutils"
)

type formattersHelp struct {
Enabled []formatterHelp
Disabled []formatterHelp
}

type formattersOptions struct {
config.LoaderOptions
JSON bool
}

type formattersCommand struct {
Expand Down Expand Up @@ -54,6 +61,8 @@ func newFormattersCommand(logger logutils.Log) *formattersCommand {
setupConfigFileFlagSet(fs, &c.opts.LoaderOptions)
setupLintersFlagSet(c.viper, fs)

fs.BoolVar(&c.opts.JSON, "json", false, color.GreenString("Display as JSON"))

c.cmd = formattersCmd

return c
Expand Down Expand Up @@ -103,8 +112,23 @@ func (c *formattersCommand) execute(_ *cobra.Command, _ []string) error {
}
}

if c.opts.JSON {
formatters := formattersHelp{}

for _, lc := range enabledFormatters {
formatters.Enabled = append(formatters.Enabled, newFormatterHelp(lc))
}

for _, lc := range disabledFormatters {
formatters.Disabled = append(formatters.Disabled, newFormatterHelp(lc))
}

return json.NewEncoder(c.cmd.OutOrStdout()).Encode(formatters)
}

color.Green("Enabled by your configuration formatters:\n")
printFormatters(enabledFormatters)

color.Red("\nDisabled by your configuration formatters:\n")
printFormatters(disabledFormatters)

Expand Down
18 changes: 11 additions & 7 deletions pkg/commands/help_formatters.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ type formatterHelp struct {
OriginalURL string `json:"originalURL,omitempty"`
}

func newFormatterHelp(lc *linter.Config) formatterHelp {
return formatterHelp{
Name: lc.Name(),
Desc: formatDescription(lc.Linter.Desc()),
Deprecated: lc.IsDeprecated(),
Since: lc.Since,
OriginalURL: lc.OriginalURL,
}
}

func (c *helpCommand) formattersPreRunE(_ *cobra.Command, _ []string) error {
// The command doesn't depend on the real configuration.
dbManager, err := lintersdb.NewManager(c.log.Child(logutils.DebugKeyLintersDB), config.NewDefault(), lintersdb.NewLinterBuilder())
Expand Down Expand Up @@ -58,13 +68,7 @@ func (c *helpCommand) formattersPrintJSON() error {
continue
}

formatters = append(formatters, formatterHelp{
Name: lc.Name(),
Desc: formatDescription(lc.Linter.Desc()),
Deprecated: lc.IsDeprecated(),
Since: lc.Since,
OriginalURL: lc.OriginalURL,
})
formatters = append(formatters, newFormatterHelp(lc))
}

return json.NewEncoder(c.cmd.OutOrStdout()).Encode(formatters)
Expand Down
36 changes: 20 additions & 16 deletions pkg/commands/help_linters.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,25 @@ type linterHelp struct {
OriginalURL string `json:"originalURL,omitempty"`
}

func newLinterHelp(lc *linter.Config) linterHelp {
groups := []string{config.GroupAll}

if !lc.IsSlowLinter() {
groups = append(groups, config.GroupFast)
}

return linterHelp{
Name: lc.Name(),
Desc: formatDescription(lc.Linter.Desc()),
Groups: slices.Concat(groups, slices.Collect(maps.Keys(lc.Groups))),
Fast: !lc.IsSlowLinter(),
AutoFix: lc.CanAutoFix,
Deprecated: lc.IsDeprecated(),
Since: lc.Since,
OriginalURL: lc.OriginalURL,
}
}

func (c *helpCommand) lintersPreRunE(_ *cobra.Command, _ []string) error {
// The command doesn't depend on the real configuration.
dbManager, err := lintersdb.NewManager(c.log.Child(logutils.DebugKeyLintersDB), config.NewDefault(), lintersdb.NewLinterBuilder())
Expand Down Expand Up @@ -62,22 +81,7 @@ func (c *helpCommand) lintersPrintJSON() error {
continue
}

groups := []string{config.GroupAll}

if !lc.IsSlowLinter() {
groups = append(groups, config.GroupFast)
}

linters = append(linters, linterHelp{
Name: lc.Name(),
Desc: formatDescription(lc.Linter.Desc()),
Groups: slices.Concat(groups, slices.Collect(maps.Keys(lc.Groups))),
Fast: !lc.IsSlowLinter(),
AutoFix: lc.CanAutoFix,
Deprecated: lc.IsDeprecated(),
Since: lc.Since,
OriginalURL: lc.OriginalURL,
})
linters = append(linters, newLinterHelp(lc))
}

return json.NewEncoder(c.cmd.OutOrStdout()).Encode(linters)
Expand Down
30 changes: 27 additions & 3 deletions pkg/commands/linters.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package commands

import (
"encoding/json"
"fmt"

"github.com/fatih/color"
Expand All @@ -14,8 +15,14 @@ import (
"github.com/golangci/golangci-lint/pkg/logutils"
)

type lintersHelp struct {
Enabled []linterHelp
Disabled []linterHelp
}

type lintersOptions struct {
config.LoaderOptions
JSON bool
}

type lintersCommand struct {
Expand Down Expand Up @@ -54,6 +61,8 @@ func newLintersCommand(logger logutils.Log) *lintersCommand {
setupConfigFileFlagSet(fs, &c.opts.LoaderOptions)
setupLintersFlagSet(c.viper, fs)

fs.BoolVar(&c.opts.JSON, "json", false, color.GreenString("Display as JSON"))

c.cmd = lintersCmd

return c
Expand Down Expand Up @@ -85,7 +94,7 @@ func (c *lintersCommand) execute(_ *cobra.Command, _ []string) error {
}

var enabledLinters []*linter.Config
var disabledLCs []*linter.Config
var disabledLinters []*linter.Config

for _, lc := range c.dbManager.GetAllSupportedLinterConfigs() {
if lc.Internal {
Expand All @@ -97,16 +106,31 @@ func (c *lintersCommand) execute(_ *cobra.Command, _ []string) error {
}

if enabledLintersMap[lc.Name()] == nil {
disabledLCs = append(disabledLCs, lc)
disabledLinters = append(disabledLinters, lc)
} else {
enabledLinters = append(enabledLinters, lc)
}
}

if c.opts.JSON {
formatters := lintersHelp{}

for _, lc := range enabledLinters {
formatters.Enabled = append(formatters.Enabled, newLinterHelp(lc))
}

for _, lc := range disabledLinters {
formatters.Disabled = append(formatters.Disabled, newLinterHelp(lc))
}

return json.NewEncoder(c.cmd.OutOrStdout()).Encode(formatters)
}

color.Green("Enabled by your configuration linters:\n")
printLinters(enabledLinters)

color.Red("\nDisabled by your configuration linters:\n")
printLinters(disabledLCs)
printLinters(disabledLinters)

return nil
}
2 changes: 1 addition & 1 deletion pkg/commands/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func (c *migrateCommand) execute(_ *cobra.Command, _ []string) error {

func (c *migrateCommand) preRunE(cmd *cobra.Command, _ []string) error {
switch strings.ToLower(c.opts.format) {
case "", "yml", "yaml", "toml", "json": //nolint:goconst // Constants are useless in this context.
case "", "yml", "yaml", "toml", "json":
// Valid format.
default:
return fmt.Errorf("unsupported format: %s", c.opts.format)
Expand Down
57 changes: 23 additions & 34 deletions pkg/commands/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,28 @@ import (
"io"
"os"
"runtime/debug"
"strings"

"github.com/fatih/color"
"github.com/spf13/cobra"
)

type BuildInfo struct {
GoVersion string `json:"goVersion"`
Version string `json:"version"`
Commit string `json:"commit"`
Date string `json:"date"`
GoVersion string `json:"goVersion"`
Version string `json:"version"`
Commit string `json:"commit"`
Date string `json:"date"`
BuildInfo *debug.BuildInfo `json:"buildInfo,omitempty"`
}

func (b BuildInfo) String() string {
return fmt.Sprintf("golangci-lint has version %s built with %s from %s on %s",
b.Version, b.GoVersion, b.Commit, b.Date)
}

type versionInfo struct {
Info BuildInfo
BuildInfo *debug.BuildInfo
}

type versionOptions struct {
Format string
Debug bool
Debug bool
JSON bool
Short bool
}

type versionCommand struct {
Expand All @@ -55,43 +51,36 @@ func newVersionCommand(info BuildInfo) *versionCommand {
fs := versionCmd.Flags()
fs.SortFlags = false // sort them as they are defined here

fs.StringVar(&c.opts.Format, "format", "", color.GreenString("The version's format can be: 'short', 'json'"))
fs.BoolVar(&c.opts.Debug, "debug", false, color.GreenString("Add build information"))
fs.BoolVar(&c.opts.JSON, "json", false, color.GreenString("Display as JSON"))
fs.BoolVar(&c.opts.Short, "short", false, color.GreenString("Display only the version number"))

c.cmd = versionCmd

return c
}

func (c *versionCommand) execute(_ *cobra.Command, _ []string) error {
var info *debug.BuildInfo
if c.opts.Debug {
info, ok := debug.ReadBuildInfo()
if !ok {
return nil
}

switch strings.ToLower(c.opts.Format) {
case "json":
return json.NewEncoder(os.Stdout).Encode(versionInfo{
Info: c.info,
BuildInfo: info,
})

default:
fmt.Println(info.String())
return printVersion(os.Stdout, c.info)
}
info, _ = debug.ReadBuildInfo()
}

switch strings.ToLower(c.opts.Format) {
case "short":
fmt.Println(c.info.Version)
return nil
switch {
case c.opts.JSON:
c.info.BuildInfo = info

case "json":
return json.NewEncoder(os.Stdout).Encode(c.info)
case c.opts.Short:
fmt.Println(c.info.Version)

return nil

default:
if info != nil {
fmt.Println(info.String())
}

return printVersion(os.Stdout, c.info)
}
}
Expand Down
Loading