Skip to content

Commit 7659ceb

Browse files
author
Thirukumaran Vaseeharan
committed
make gci linter fixable
1 parent ec95236 commit 7659ceb

File tree

2 files changed

+82
-15
lines changed

2 files changed

+82
-15
lines changed

pkg/golinters/gci.go

Lines changed: 80 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
package golinters
22

33
import (
4+
"bytes"
45
"fmt"
5-
"strings"
6+
"sync"
67

7-
gci "github.com/daixiang0/gci/pkg/analyzer"
8+
gcicfg "github.com/daixiang0/gci/pkg/configuration"
9+
"github.com/daixiang0/gci/pkg/gci"
10+
gciio "github.com/daixiang0/gci/pkg/io"
11+
"github.com/pkg/errors"
12+
"github.com/shazow/go-diff/difflib"
813
"golang.org/x/tools/go/analysis"
914

1015
"github.com/golangci/golangci-lint/pkg/config"
@@ -15,34 +20,94 @@ import (
1520
const gciName = "gci"
1621

1722
func NewGci(settings *config.GciSettings) *goanalysis.Linter {
18-
var linterCfg map[string]map[string]interface{}
23+
var cfg *gci.GciConfiguration
24+
var mu sync.Mutex
25+
var resIssues []goanalysis.Issue
26+
differ := difflib.New()
1927

2028
if settings != nil {
21-
cfg := map[string]interface{}{
22-
gci.NoInlineCommentsFlag: settings.NoInlineComments,
23-
gci.NoPrefixCommentsFlag: settings.NoPrefixComments,
24-
gci.SectionsFlag: strings.Join(settings.Sections, gci.SectionDelimiter),
25-
gci.SectionSeparatorsFlag: strings.Join(settings.SectionSeparator, gci.SectionDelimiter),
29+
strcfg := gci.GciStringConfiguration{
30+
Cfg: gcicfg.FormatterConfiguration{
31+
NoInlineComments: settings.NoInlineComments,
32+
NoPrefixComments: settings.NoPrefixComments,
33+
},
34+
SectionStrings: settings.Sections,
35+
SectionSeparatorStrings: settings.SectionSeparator,
2636
}
27-
2837
if settings.LocalPrefixes != "" {
2938
prefix := []string{"standard", "default", fmt.Sprintf("prefix(%s)", settings.LocalPrefixes)}
30-
cfg[gci.SectionsFlag] = strings.Join(prefix, gci.SectionDelimiter)
39+
strcfg.SectionStrings = prefix
3140
}
3241

33-
linterCfg = map[string]map[string]interface{}{
34-
gci.Analyzer.Name: cfg,
35-
}
42+
cfg, _ = strcfg.Parse()
3643
}
3744

45+
analyzer := &analysis.Analyzer{
46+
Name: gciName,
47+
Doc: goanalysis.TheOnlyanalyzerDoc,
48+
}
3849
return goanalysis.NewLinter(
3950
gciName,
4051
"Gci controls golang package import order and makes it always deterministic.",
41-
[]*analysis.Analyzer{gci.Analyzer},
42-
linterCfg,
52+
[]*analysis.Analyzer{analyzer},
53+
nil,
4354
).WithContextSetter(func(lintCtx *linter.Context) {
4455
if settings.LocalPrefixes != "" {
4556
lintCtx.Log.Warnf("gci: `local-prefixes` is deprecated, use `sections` and `prefix(%s)` instead.", settings.LocalPrefixes)
4657
}
58+
59+
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
60+
var fileNames []string
61+
for _, f := range pass.Files {
62+
pos := pass.Fset.PositionFor(f.Pos(), false)
63+
fileNames = append(fileNames, pos.Filename)
64+
}
65+
66+
var issues []goanalysis.Issue
67+
for _, f := range fileNames {
68+
fio := gciio.File{FilePath: f}
69+
source, result, err := gci.LoadFormatGoFile(fio, *cfg)
70+
if err != nil {
71+
return nil, err
72+
}
73+
if result == nil {
74+
continue
75+
}
76+
77+
if !bytes.Equal(source, result) {
78+
diff := bytes.Buffer{}
79+
_, err = diff.WriteString(fmt.Sprintf("--- %[1]s\n+++ %[1]s\n", f))
80+
if err != nil {
81+
return nil, fmt.Errorf("can't write diff header: %v", err)
82+
}
83+
84+
err = differ.Diff(&diff, bytes.NewReader(source), bytes.NewReader(result))
85+
if err != nil {
86+
return nil, fmt.Errorf("can't get gci diff output: %v", err)
87+
}
88+
89+
is, err := extractIssuesFromPatch(diff.String(), lintCtx.Log, lintCtx, gciName)
90+
if err != nil {
91+
return nil, errors.Wrapf(err, "can't extract issues from gci diff output %q", diff.String())
92+
}
93+
94+
for i := range is {
95+
issues = append(issues, goanalysis.NewIssue(&is[i], pass))
96+
}
97+
}
98+
}
99+
100+
if len(issues) == 0 {
101+
return nil, nil
102+
}
103+
104+
mu.Lock()
105+
resIssues = append(resIssues, issues...)
106+
mu.Unlock()
107+
108+
return nil, nil
109+
}
110+
}).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
111+
return resIssues
47112
}).WithLoadMode(goanalysis.LoadModeSyntax)
48113
}

pkg/golinters/gofmt_common.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ func (p *hunkChangesParser) parse(h *diffpkg.Hunk) []Change {
210210
func getErrorTextForLinter(lintCtx *linter.Context, linterName string) string {
211211
text := "File is not formatted"
212212
switch linterName {
213+
case gciName:
214+
text = "File is not `gci`-ed"
213215
case gofumptName:
214216
text = "File is not `gofumpt`-ed"
215217
if lintCtx.Settings().Gofumpt.ExtraRules {

0 commit comments

Comments
 (0)