1
1
package golinters
2
2
3
3
import (
4
+ "bytes"
4
5
"fmt"
5
- "strings "
6
+ "sync "
6
7
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"
8
13
"golang.org/x/tools/go/analysis"
9
14
10
15
"github.com/golangci/golangci-lint/pkg/config"
@@ -15,34 +20,94 @@ import (
15
20
const gciName = "gci"
16
21
17
22
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 ()
19
27
20
28
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 ,
26
36
}
27
-
28
37
if settings .LocalPrefixes != "" {
29
38
prefix := []string {"standard" , "default" , fmt .Sprintf ("prefix(%s)" , settings .LocalPrefixes )}
30
- cfg [ gci . SectionsFlag ] = strings . Join ( prefix , gci . SectionDelimiter )
39
+ strcfg . SectionStrings = prefix
31
40
}
32
41
33
- linterCfg = map [string ]map [string ]interface {}{
34
- gci .Analyzer .Name : cfg ,
35
- }
42
+ cfg , _ = strcfg .Parse ()
36
43
}
37
44
45
+ analyzer := & analysis.Analyzer {
46
+ Name : gciName ,
47
+ Doc : goanalysis .TheOnlyanalyzerDoc ,
48
+ }
38
49
return goanalysis .NewLinter (
39
50
gciName ,
40
51
"Gci controls golang package import order and makes it always deterministic." ,
41
- []* analysis.Analyzer {gci . Analyzer },
42
- linterCfg ,
52
+ []* analysis.Analyzer {analyzer },
53
+ nil ,
43
54
).WithContextSetter (func (lintCtx * linter.Context ) {
44
55
if settings .LocalPrefixes != "" {
45
56
lintCtx .Log .Warnf ("gci: `local-prefixes` is deprecated, use `sections` and `prefix(%s)` instead." , settings .LocalPrefixes )
46
57
}
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
47
112
}).WithLoadMode (goanalysis .LoadModeSyntax )
48
113
}
0 commit comments