Skip to content

dev: standardization of the integration of formatters #5301

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 9 commits into from
Jan 7, 2025
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
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ issues:
- path: pkg/golinters/godot/godot.go
linters: [staticcheck]
text: "SA1019: settings.CheckAll is deprecated: use Scope instead"
- path: pkg/golinters/gci/gci.go
- path: pkg/goformatters/gci/gci.go
linters: [staticcheck]
text: "SA1019: settings.LocalPrefixes is deprecated: use Sections instead."
- path: pkg/golinters/mnd/mnd.go
Expand Down
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ require (
github.com/gofrs/flock v0.12.1
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a
github.com/golangci/go-printf-func-name v0.1.0
github.com/golangci/gofmt v0.0.0-20241223200906-057b0627d9b9
github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d
github.com/golangci/misspell v0.6.0
github.com/golangci/plugin-module-register v0.1.1
github.com/golangci/revgrep v0.5.3
Expand Down Expand Up @@ -95,7 +95,6 @@ require (
github.com/sashamelentyev/interfacebloat v1.1.0
github.com/sashamelentyev/usestdlibvars v1.28.0
github.com/securego/gosec/v2 v2.21.4
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c
github.com/shirou/gopsutil/v4 v4.24.12
github.com/sirupsen/logrus v1.9.3
github.com/sivchari/containedctx v1.0.3
Expand Down
6 changes: 2 additions & 4 deletions go.sum

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

55 changes: 55 additions & 0 deletions pkg/goformatters/analyzer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package goformatters

import (
"bytes"
"fmt"
"os"
"path/filepath"

"github.com/rogpeppe/go-internal/diff"
"golang.org/x/tools/go/analysis"

"github.com/golangci/golangci-lint/pkg/goanalysis"
"github.com/golangci/golangci-lint/pkg/goformatters/internal"
"github.com/golangci/golangci-lint/pkg/logutils"
)

// NewAnalyzer converts a [Formatter] to an [analysis.Analyzer].
func NewAnalyzer(logger logutils.Log, doc string, formatter Formatter) *analysis.Analyzer {
return &analysis.Analyzer{
Name: formatter.Name(),
Doc: doc,
Run: func(pass *analysis.Pass) (any, error) {
for _, file := range pass.Files {
position, isGoFiles := goanalysis.GetGoFilePosition(pass, file)
if !isGoFiles {
continue
}

input, err := os.ReadFile(position.Filename)
if err != nil {
return nil, fmt.Errorf("unable to open file %s: %w", position.Filename, err)
}

output, err := formatter.Format(position.Filename, input)
if err != nil {
return nil, fmt.Errorf("error while running %s: %w", formatter.Name(), err)
}

if !bytes.Equal(input, output) {
newName := filepath.ToSlash(position.Filename)
oldName := newName + ".orig"

theDiff := diff.Diff(oldName, input, newName, output)

err = internal.ExtractDiagnosticFromPatch(pass, file, string(theDiff), logger)
if err != nil {
return nil, fmt.Errorf("can't extract issues from %s diff output %q: %w", formatter.Name(), string(theDiff), err)
}
}
}

return nil, nil
},
}
}
37 changes: 27 additions & 10 deletions pkg/goformatters/gci/gci.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package gci

import (
"fmt"

gcicfg "github.com/daixiang0/gci/pkg/config"
"github.com/daixiang0/gci/pkg/gci"
"github.com/daixiang0/gci/pkg/log"
"github.com/ldez/grignotin/gomod"

"github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/goformatters/internal"
)

const Name = "gci"
Expand All @@ -14,23 +18,36 @@ type Formatter struct {
config *gcicfg.Config
}

func New(cfg config.GciSettings) (*Formatter, error) {
func New(settings *config.GciSettings) (*Formatter, error) {
log.InitLogger()
_ = log.L().Sync()

modPath, err := gomod.GetModulePath()
if err != nil {
return nil, err
internal.FormatterLogger.Errorf("gci: %v", err)
}

parsedCfg, err := gcicfg.YamlConfig{
cfg := gcicfg.YamlConfig{
Cfg: gcicfg.BoolConfig{
NoInlineComments: cfg.NoInlineComments,
NoPrefixComments: cfg.NoPrefixComments,
SkipGenerated: cfg.SkipGenerated,
CustomOrder: cfg.CustomOrder,
NoLexOrder: cfg.NoLexOrder,
NoInlineComments: settings.NoInlineComments,
NoPrefixComments: settings.NoPrefixComments,
SkipGenerated: settings.SkipGenerated,
CustomOrder: settings.CustomOrder,
NoLexOrder: settings.NoLexOrder,
},
SectionStrings: cfg.Sections,
SectionStrings: settings.Sections,
ModPath: modPath,
}.Parse()
}

if settings.LocalPrefixes != "" {
cfg.SectionStrings = []string{
"standard",
"default",
fmt.Sprintf("prefix(%s)", settings.LocalPrefixes),
}
}

parsedCfg, err := cfg.Parse()
if err != nil {
return nil, err
}
Expand Down
20 changes: 10 additions & 10 deletions pkg/goformatters/gofmt/gofmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ type Formatter struct {
options gofmt.Options
}

func New(cfg config.GoFmtSettings) *Formatter {
var rewriteRules []gofmt.RewriteRule
for _, rule := range cfg.RewriteRules {
rewriteRules = append(rewriteRules, gofmt.RewriteRule(rule))
}
func New(settings *config.GoFmtSettings) *Formatter {
options := gofmt.Options{}

if settings != nil {
options.NeedSimplify = settings.Simplify

return &Formatter{
options: gofmt.Options{
NeedSimplify: cfg.Simplify,
RewriteRules: rewriteRules,
},
for _, rule := range settings.RewriteRules {
options.RewriteRules = append(options.RewriteRules, gofmt.RewriteRule(rule))
}
}

return &Formatter{options: options}
}

func (*Formatter) Name() string {
Expand Down
17 changes: 10 additions & 7 deletions pkg/goformatters/gofumpt/gofumpt.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,18 @@ type Formatter struct {
options gofumpt.Options
}

func New(cfg config.GofumptSettings, goVersion string) *Formatter {
return &Formatter{
options: gofumpt.Options{
func New(settings *config.GofumptSettings, goVersion string) *Formatter {
var options gofumpt.Options

if settings != nil {
options = gofumpt.Options{
LangVersion: getLangVersion(goVersion),
ModulePath: cfg.ModulePath,
ExtraRules: cfg.ExtraRules,
},
ModulePath: settings.ModulePath,
ExtraRules: settings.ExtraRules,
}
}

return &Formatter{options: options}
}

func (*Formatter) Name() string {
Expand All @@ -32,7 +36,6 @@ func (f *Formatter) Format(_ string, src []byte) ([]byte, error) {
return gofumpt.Source(src, f.options)
}

// modified copy of pkg/golinters/gofumpt/gofumpt.go
func getLangVersion(v string) string {
if v == "" {
// TODO: defaults to "1.15", in the future (v2) must be removed.
Expand Down
8 changes: 7 additions & 1 deletion pkg/goformatters/goimports/goimports.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ package goimports

import (
"golang.org/x/tools/imports"

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

const Name = "goimports"

type Formatter struct{}

func New() *Formatter {
func New(settings *config.GoImportsSettings) *Formatter {
if settings != nil {
imports.LocalPrefix = settings.LocalPrefixes
}

return &Formatter{}
}

Expand Down
6 changes: 6 additions & 0 deletions pkg/goformatters/internal/commons.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package internal

import "github.com/golangci/golangci-lint/pkg/logutils"

// FormatterLogger must be use only when the context logger is not available.
var FormatterLogger = logutils.NewStderrLog(logutils.DebugKeyFormatter)
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"golang.org/x/tools/go/analysis"

"github.com/golangci/golangci-lint/pkg/goanalysis"
"github.com/golangci/golangci-lint/pkg/lint/linter"
"github.com/golangci/golangci-lint/pkg/logutils"
)

Expand Down Expand Up @@ -215,7 +214,7 @@ func ExtractDiagnosticFromPatch(
pass *analysis.Pass,
file *ast.File,
patch string,
lintCtx *linter.Context,
logger logutils.Log,
) error {
diffs, err := diffpkg.ParseMultiFileDiff([]byte(patch))
if err != nil {
Expand All @@ -232,12 +231,12 @@ func ExtractDiagnosticFromPatch(

for _, d := range diffs {
if len(d.Hunks) == 0 {
lintCtx.Log.Warnf("Got no hunks in diff %+v", d)
logger.Warnf("Got no hunks in diff %+v", d)
continue
}

for _, hunk := range d.Hunks {
p := hunkChangesParser{log: lintCtx.Log}
p := hunkChangesParser{log: logger}

changes := p.parse(hunk)

Expand Down
8 changes: 4 additions & 4 deletions pkg/goformatters/meta_formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,20 @@ func NewMetaFormatter(log logutils.Log, cfg *config.Config, enabledLinters map[s
m := &MetaFormatter{log: log}

if _, ok := enabledLinters[gofmt.Name]; ok {
m.formatters = append(m.formatters, gofmt.New(cfg.LintersSettings.Gofmt))
m.formatters = append(m.formatters, gofmt.New(&cfg.LintersSettings.Gofmt))
}

if _, ok := enabledLinters[gofumpt.Name]; ok {
m.formatters = append(m.formatters, gofumpt.New(cfg.LintersSettings.Gofumpt, cfg.Run.Go))
m.formatters = append(m.formatters, gofumpt.New(&cfg.LintersSettings.Gofumpt, cfg.Run.Go))
}

if _, ok := enabledLinters[goimports.Name]; ok {
m.formatters = append(m.formatters, goimports.New())
m.formatters = append(m.formatters, goimports.New(&cfg.LintersSettings.Goimports))
}

// gci is a last because the only goal of gci is to handle imports.
if _, ok := enabledLinters[gci.Name]; ok {
formatter, err := gci.New(cfg.LintersSettings.Gci)
formatter, err := gci.New(&cfg.LintersSettings.Gci)
if err != nil {
return nil, fmt.Errorf("gci: creating formatter: %w", err)
}
Expand Down
Loading
Loading