Skip to content

Commit 8a0dd0c

Browse files
committed
feat: post-process formatters
1 parent f996a66 commit 8a0dd0c

File tree

11 files changed

+359
-28
lines changed

11 files changed

+359
-28
lines changed

Diff for: go.mod

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ require (
4444
github.com/gofrs/flock v0.12.1
4545
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a
4646
github.com/golangci/go-printf-func-name v0.1.0
47-
github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9
47+
github.com/golangci/gofmt v0.0.0-20241223200906-057b0627d9b9
4848
github.com/golangci/misspell v0.6.0
4949
github.com/golangci/plugin-module-register v0.1.1
5050
github.com/golangci/revgrep v0.5.3
@@ -65,7 +65,7 @@ require (
6565
github.com/kyoh86/exportloopref v0.1.11
6666
github.com/lasiar/canonicalheader v1.1.2
6767
github.com/ldez/gomoddirectives v0.6.0
68-
github.com/ldez/grignotin v0.6.0
68+
github.com/ldez/grignotin v0.7.0
6969
github.com/ldez/tagliatelle v0.7.1
7070
github.com/ldez/usetesting v0.2.2
7171
github.com/leonklingele/grouper v1.1.2

Diff for: go.sum

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: pkg/config/config.go

+34-22
Original file line numberDiff line numberDiff line change
@@ -93,32 +93,15 @@ func detectGoVersion() string {
9393
// else it returns `go` version if present,
9494
// else it returns empty.
9595
func detectGoVersionFromGoMod() string {
96-
info, err := gomod.GetModuleInfo()
97-
if err != nil {
98-
return ""
99-
}
100-
101-
wd, err := os.Getwd()
96+
modPath, err := gomod.GetGoModPath()
10297
if err != nil {
103-
return ""
104-
}
105-
106-
slices.SortFunc(info, func(a, b gomod.ModInfo) int {
107-
return cmp.Compare(len(b.Path), len(a.Path))
108-
})
109-
110-
goMod := info[0]
111-
for _, m := range info {
112-
if !strings.HasPrefix(wd, m.Dir) {
113-
continue
98+
modPath = detectGoModFallback()
99+
if modPath == "" {
100+
return ""
114101
}
115-
116-
goMod = m
117-
118-
break
119102
}
120103

121-
file, err := parseGoMod(goMod.GoMod)
104+
file, err := parseGoMod(modPath)
122105
if err != nil {
123106
return ""
124107
}
@@ -144,3 +127,32 @@ func parseGoMod(goMod string) (*modfile.File, error) {
144127

145128
return modfile.Parse("go.mod", raw, nil)
146129
}
130+
131+
func detectGoModFallback() string {
132+
info, err := gomod.GetModuleInfo()
133+
if err != nil {
134+
return ""
135+
}
136+
137+
wd, err := os.Getwd()
138+
if err != nil {
139+
return ""
140+
}
141+
142+
slices.SortFunc(info, func(a, b gomod.ModInfo) int {
143+
return cmp.Compare(len(b.Path), len(a.Path))
144+
})
145+
146+
goMod := info[0]
147+
for _, m := range info {
148+
if !strings.HasPrefix(wd, m.Dir) {
149+
continue
150+
}
151+
152+
goMod = m
153+
154+
break
155+
}
156+
157+
return goMod.GoMod
158+
}

Diff for: pkg/goformatters/formaters.go

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package goformatters
2+
3+
type Formatter interface {
4+
Name() string
5+
Format(filename string, src []byte) ([]byte, error)
6+
}

Diff for: pkg/goformatters/gci/gci.go

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package gci
2+
3+
import (
4+
gcicfg "github.com/daixiang0/gci/pkg/config"
5+
"github.com/daixiang0/gci/pkg/gci"
6+
"github.com/ldez/grignotin/gomod"
7+
8+
"github.com/golangci/golangci-lint/pkg/config"
9+
)
10+
11+
const Name = "gci"
12+
13+
type Formatter struct {
14+
config *gcicfg.Config
15+
}
16+
17+
func New(cfg config.GciSettings) (*Formatter, error) {
18+
modPath, err := gomod.GetModulePath()
19+
if err != nil {
20+
return nil, err
21+
}
22+
23+
parsedCfg, err := gcicfg.YamlConfig{
24+
Cfg: gcicfg.BoolConfig{
25+
NoInlineComments: cfg.NoInlineComments,
26+
NoPrefixComments: cfg.NoPrefixComments,
27+
SkipGenerated: cfg.SkipGenerated,
28+
CustomOrder: cfg.CustomOrder,
29+
NoLexOrder: cfg.NoLexOrder,
30+
},
31+
SectionStrings: cfg.Sections,
32+
ModPath: modPath,
33+
}.Parse()
34+
if err != nil {
35+
return nil, err
36+
}
37+
38+
return &Formatter{config: parsedCfg}, nil
39+
}
40+
41+
func (*Formatter) Name() string {
42+
return Name
43+
}
44+
45+
func (f *Formatter) Format(filename string, src []byte) ([]byte, error) {
46+
_, formatted, err := gci.LoadFormat(src, filename, *f.config)
47+
return formatted, err
48+
}

Diff for: pkg/goformatters/gofmt/gofmt.go

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package gofmt
2+
3+
import (
4+
"github.com/golangci/gofmt/gofmt"
5+
6+
"github.com/golangci/golangci-lint/pkg/config"
7+
)
8+
9+
const Name = "gofmt"
10+
11+
type Formatter struct {
12+
options gofmt.Options
13+
}
14+
15+
func New(cfg config.GoFmtSettings) *Formatter {
16+
var rewriteRules []gofmt.RewriteRule
17+
for _, rule := range cfg.RewriteRules {
18+
rewriteRules = append(rewriteRules, gofmt.RewriteRule(rule))
19+
}
20+
21+
return &Formatter{
22+
options: gofmt.Options{
23+
NeedSimplify: cfg.Simplify,
24+
RewriteRules: rewriteRules,
25+
},
26+
}
27+
}
28+
29+
func (*Formatter) Name() string {
30+
return Name
31+
}
32+
33+
func (f *Formatter) Format(filename string, src []byte) ([]byte, error) {
34+
return gofmt.Source(filename, src, f.options)
35+
}

Diff for: pkg/goformatters/gofumpt/gofumpt.go

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package gofumpt
2+
3+
import (
4+
"strings"
5+
6+
gofumpt "mvdan.cc/gofumpt/format"
7+
8+
"github.com/golangci/golangci-lint/pkg/config"
9+
)
10+
11+
const Name = "gofumpt"
12+
13+
type Formatter struct {
14+
options gofumpt.Options
15+
}
16+
17+
func New(cfg config.GofumptSettings, goVersion string) *Formatter {
18+
return &Formatter{
19+
options: gofumpt.Options{
20+
LangVersion: getLangVersion(goVersion),
21+
ModulePath: cfg.ModulePath,
22+
ExtraRules: cfg.ExtraRules,
23+
},
24+
}
25+
}
26+
27+
func (*Formatter) Name() string {
28+
return Name
29+
}
30+
31+
func (f *Formatter) Format(_ string, src []byte) ([]byte, error) {
32+
return gofumpt.Source(src, f.options)
33+
}
34+
35+
// modified copy of pkg/golinters/gofumpt/gofumpt.go
36+
func getLangVersion(v string) string {
37+
if v == "" {
38+
// TODO: defaults to "1.15", in the future (v2) must be removed.
39+
return "go1.15"
40+
}
41+
42+
return "go" + strings.TrimPrefix(v, "go")
43+
}

Diff for: pkg/goformatters/goimports/goimports.go

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package goimports
2+
3+
import (
4+
"golang.org/x/tools/imports"
5+
)
6+
7+
const Name = "goimports"
8+
9+
type Formatter struct{}
10+
11+
func New() *Formatter {
12+
return &Formatter{}
13+
}
14+
15+
func (*Formatter) Name() string {
16+
return Name
17+
}
18+
19+
func (*Formatter) Format(filename string, src []byte) ([]byte, error) {
20+
// The `imports.LocalPrefix` (`settings.LocalPrefixes`) is a global var.
21+
return imports.Process(filename, src, nil)
22+
}

Diff for: pkg/lint/runner.go

+7
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ func NewRunner(log logutils.Log, cfg *config.Config, args []string, goenv *gouti
6060
return nil, fmt.Errorf("failed to get enabled linters: %w", err)
6161
}
6262

63+
formatter, err := processors.NewFormatter(log, cfg, fileCache, enabledLinters)
64+
if err != nil {
65+
return nil, fmt.Errorf("failed to create formatter: %w", err)
66+
}
67+
6368
return &Runner{
6469
Processors: []processors.Processor{
6570
processors.NewCgo(goenv),
@@ -95,6 +100,8 @@ func NewRunner(log logutils.Log, cfg *config.Config, args []string, goenv *gouti
95100

96101
// The fixer still needs to see paths for the issues that are relative to the current directory.
97102
processors.NewFixer(cfg, log, fileCache),
103+
// The fommatter needs to be after the fixer and the last processor that use fileCache.
104+
formatter,
98105

99106
// Now we can modify the issues for output.
100107
processors.NewPathPrefixer(cfg.Output.PathPrefix),

Diff for: pkg/result/processors/fixer.go

+11
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ import (
1313
"os"
1414
"slices"
1515

16+
"github.com/golangci/golangci-lint/pkg/goformatters/gci"
17+
"github.com/golangci/golangci-lint/pkg/goformatters/gofmt"
18+
"github.com/golangci/golangci-lint/pkg/goformatters/gofumpt"
19+
"github.com/golangci/golangci-lint/pkg/goformatters/goimports"
1620
"golang.org/x/exp/maps"
1721

1822
"github.com/golangci/golangci-lint/internal/x/tools/diff"
@@ -71,11 +75,18 @@ func (p Fixer) process(issues []result.Issue) ([]result.Issue, error) {
7175
// filenames / linters / edits
7276
editsByLinter := make(map[string]map[string][]diff.Edit)
7377

78+
formatters := []string{gofumpt.Name, goimports.Name, gofmt.Name, gci.Name}
79+
7480
var notFixableIssues []result.Issue
7581

7682
for i := range issues {
7783
issue := issues[i]
7884

85+
if slices.Contains(formatters, issue.FromLinter) {
86+
notFixableIssues = append(notFixableIssues, issue)
87+
continue
88+
}
89+
7990
if issue.SuggestedFixes == nil || skipNoTextEdit(&issue) {
8091
notFixableIssues = append(notFixableIssues, issue)
8192
continue

0 commit comments

Comments
 (0)