Skip to content

Commit

Permalink
feat: add sloglint linter (#4133)
Browse files Browse the repository at this point in the history
  • Loading branch information
tmzane authored Oct 19, 2023
1 parent cf93cf5 commit 39c5fd1
Show file tree
Hide file tree
Showing 15 changed files with 157 additions and 0 deletions.
16 changes: 16 additions & 0 deletions .golangci.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1799,6 +1799,20 @@ linters-settings:
packages:
- github.com/jmoiron/sqlx

sloglint:
# Enforce using key-value pairs only (incompatible with attr-only).
# Default: false
kv-only: true
# Enforce using attributes only (incompatible with kv-only).
# Default: false
attr-only: true
# Enforce using constants instead of raw keys.
# Default: false
no-raw-keys: true
# Enforce putting arguments on separate lines.
# Default: false
args-on-sep-lines: true

staticcheck:
# Deprecated: use the global `run.go` instead.
go: "1.15"
Expand Down Expand Up @@ -2295,6 +2309,7 @@ linters:
- revive
- rowserrcheck
- scopelint
- sloglint
- sqlclosecheck
- staticcheck
- structcheck
Expand Down Expand Up @@ -2413,6 +2428,7 @@ linters:
- revive
- rowserrcheck
- scopelint
- sloglint
- sqlclosecheck
- staticcheck
- structcheck
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ require (
github.com/yeya24/promlinter v0.2.0
github.com/ykadowak/zerologlint v0.1.3
gitlab.com/bosi/decorder v0.4.1
go-simpler.org/sloglint v0.1.2
go.tmz.dev/musttag v0.7.2
golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea
golang.org/x/tools v0.14.0
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.

14 changes: 14 additions & 0 deletions pkg/config/linters_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ var defaultLintersSettings = LintersSettings{
Ignore: "",
Qualified: false,
},
SlogLint: SlogLintSettings{
KVOnly: false,
AttrOnly: false,
NoRawKeys: false,
ArgsOnSepLines: false,
},
TagAlign: TagAlignSettings{
Align: true,
Sort: true,
Expand Down Expand Up @@ -222,6 +228,7 @@ type LintersSettings struct {
Reassign ReassignSettings
Revive ReviveSettings
RowsErrCheck RowsErrCheckSettings
SlogLint SlogLintSettings
Staticcheck StaticCheckSettings
Structcheck StructCheckSettings
Stylecheck StaticCheckSettings
Expand Down Expand Up @@ -717,6 +724,13 @@ type RowsErrCheckSettings struct {
Packages []string
}

type SlogLintSettings struct {
KVOnly bool `mapstructure:"kv-only"`
AttrOnly bool `mapstructure:"attr-only"`
NoRawKeys bool `mapstructure:"no-raw-keys"`
ArgsOnSepLines bool `mapstructure:"args-on-sep-lines"`
}

type StaticCheckSettings struct {
// Deprecated: use the global `run.go` instead.
GoVersion string `mapstructure:"go"`
Expand Down
27 changes: 27 additions & 0 deletions pkg/golinters/sloglint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package golinters

import (
"go-simpler.org/sloglint"
"golang.org/x/tools/go/analysis"

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

func NewSlogLint(settings *config.SlogLintSettings) *goanalysis.Linter {
var opts *sloglint.Options
if settings != nil {
opts = &sloglint.Options{
KVOnly: settings.KVOnly,
AttrOnly: settings.AttrOnly,
NoRawKeys: settings.NoRawKeys,
ArgsOnSepLines: settings.ArgsOnSepLines,
}
}

a := sloglint.New(opts)

return goanalysis.
NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil).
WithLoadMode(goanalysis.LoadModeTypesInfo)
}
8 changes: 8 additions & 0 deletions pkg/lint/lintersdb/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
reassignCfg *config.ReassignSettings
reviveCfg *config.ReviveSettings
rowserrcheckCfg *config.RowsErrCheckSettings
sloglintCfg *config.SlogLintSettings
staticcheckCfg *config.StaticCheckSettings
structcheckCfg *config.StructCheckSettings
stylecheckCfg *config.StaticCheckSettings
Expand Down Expand Up @@ -208,6 +209,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
reassignCfg = &m.cfg.LintersSettings.Reassign
reviveCfg = &m.cfg.LintersSettings.Revive
rowserrcheckCfg = &m.cfg.LintersSettings.RowsErrCheck
sloglintCfg = &m.cfg.LintersSettings.SlogLint
staticcheckCfg = &m.cfg.LintersSettings.Staticcheck
structcheckCfg = &m.cfg.LintersSettings.Structcheck
stylecheckCfg = &m.cfg.LintersSettings.Stylecheck
Expand Down Expand Up @@ -750,6 +752,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithPresets(linter.PresetBugs, linter.PresetSQL).
WithURL("https://github.com/jingyugao/rowserrcheck"),

linter.NewConfig(golinters.NewSlogLint(sloglintCfg)).
WithSince("v1.55.0").
WithLoadForGoAnalysis().
WithPresets(linter.PresetStyle, linter.PresetFormatting).
WithURL("https://github.com/go-simpler/sloglint"),

linter.NewConfig(golinters.NewScopelint()).
WithSince("v1.12.0").
WithPresets(linter.PresetBugs).
Expand Down
3 changes: 3 additions & 0 deletions test/testdata/configs/sloglint_args_on_sep_lines.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
linters-settings:
sloglint:
args-on-sep-lines: true
3 changes: 3 additions & 0 deletions test/testdata/configs/sloglint_attr_only.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
linters-settings:
sloglint:
attr-only: true
3 changes: 3 additions & 0 deletions test/testdata/configs/sloglint_kv_only.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
linters-settings:
sloglint:
kv-only: true
3 changes: 3 additions & 0 deletions test/testdata/configs/sloglint_no_raw_keys.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
linters-settings:
sloglint:
no-raw-keys: true
13 changes: 13 additions & 0 deletions test/testdata/sloglint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//go:build go1.21

//golangcitest:args -Esloglint
package testdata

import "log/slog"

func test() {
slog.Info("msg", "foo", 1, "bar", 2)
slog.Info("msg", slog.Int("foo", 1), slog.Int("bar", 2))

slog.Info("msg", "foo", 1, slog.Int("bar", 2)) // want `key-value pairs and attributes should not be mixed`
}
17 changes: 17 additions & 0 deletions test/testdata/sloglint_args_on_sep_lines.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//go:build go1.21

//golangcitest:args -Esloglint
//golangcitest:config_path testdata/configs/sloglint_args_on_sep_lines.yml
package testdata

import "log/slog"

func test() {
slog.Info("msg", "foo", 1)
slog.Info("msg",
"foo", 1,
"bar", 2,
)

slog.Info("msg", "foo", 1, "bar", 2) // want `arguments should be put on separate lines`
}
13 changes: 13 additions & 0 deletions test/testdata/sloglint_attr_only.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//go:build go1.21

//golangcitest:args -Esloglint
//golangcitest:config_path testdata/configs/sloglint_attr_only.yml
package testdata

import "log/slog"

func test() {
slog.Info("msg", slog.Int("foo", 1), slog.Int("bar", 2))

slog.Info("msg", "foo", 1, "bar", 2) // want `key-value pairs should not be used`
}
13 changes: 13 additions & 0 deletions test/testdata/sloglint_kv_only.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//go:build go1.21

//golangcitest:args -Esloglint
//golangcitest:config_path testdata/configs/sloglint_kv_only.yml
package testdata

import "log/slog"

func test() {
slog.Info("msg", "foo", 1, "bar", 2)

slog.Info("msg", slog.Int("foo", 1), slog.Int("bar", 2)) // want `attributes should not be used`
}
21 changes: 21 additions & 0 deletions test/testdata/sloglint_no_raw_keys.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//go:build go1.21

//golangcitest:args -Esloglint
//golangcitest:config_path testdata/configs/sloglint_no_raw_keys.yml
package testdata

import "log/slog"

const foo = "foo"

func Foo(value int) slog.Attr {
return slog.Int("foo", value)
}

func test() {
slog.Info("msg", foo, 1)
slog.Info("msg", Foo(1))

slog.Info("msg", "foo", 1) // want `raw keys should not be used`
slog.Info("msg", slog.Int("foo", 1)) // want `raw keys should not be used`
}

0 comments on commit 39c5fd1

Please sign in to comment.