11package golinters
22
33import (
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 (
1520const gciName = "gci"
1621
1722func 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}
0 commit comments