Skip to content

Commit 08ae805

Browse files
authored
gci: fix standard packages list for go1.24 (#5402)
1 parent 82ad6b6 commit 08ae805

File tree

8 files changed

+409
-2
lines changed

8 files changed

+409
-2
lines changed

.golangci.yml

+1
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ issues:
190190
- test/testdata_etc # test files
191191
- internal/go # extracted from Go code
192192
- internal/x # extracted from x/tools code
193+
- pkg/goformatters/gci/internal # extracted from gci code
193194
exclude-files:
194195
- pkg/goanalysis/runner_checker.go # extracted from x/tools code
195196

pkg/goformatters/gci/gci.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/ldez/grignotin/gomod"
1111

1212
"github.com/golangci/golangci-lint/pkg/config"
13+
gcicfgi "github.com/golangci/golangci-lint/pkg/goformatters/gci/internal/config"
1314
"github.com/golangci/golangci-lint/pkg/goformatters/internal"
1415
)
1516

@@ -28,7 +29,7 @@ func New(settings *config.GciSettings) (*Formatter, error) {
2829
internal.FormatterLogger.Errorf("gci: %v", err)
2930
}
3031

31-
cfg := gcicfg.YamlConfig{
32+
cfg := gcicfgi.YamlConfig{
3233
Cfg: gcicfg.BoolConfig{
3334
NoInlineComments: settings.NoInlineComments,
3435
NoPrefixComments: settings.NoPrefixComments,
@@ -53,7 +54,11 @@ func New(settings *config.GciSettings) (*Formatter, error) {
5354
return nil, err
5455
}
5556

56-
return &Formatter{config: parsedCfg}, nil
57+
return &Formatter{config: &gcicfg.Config{
58+
BoolConfig: parsedCfg.BoolConfig,
59+
Sections: parsedCfg.Sections,
60+
SectionSeparators: parsedCfg.SectionSeparators,
61+
}}, nil
5762
}
5863

5964
func (*Formatter) Name() string {

pkg/goformatters/gci/internal/LICENSE

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
BSD 3-Clause License
2+
3+
Copyright (c) 2020, Xiang Dai
4+
All rights reserved.
5+
6+
Redistribution and use in source and binary forms, with or without
7+
modification, are permitted provided that the following conditions are met:
8+
9+
1. Redistributions of source code must retain the above copyright notice, this
10+
list of conditions and the following disclaimer.
11+
12+
2. Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
16+
3. Neither the name of the copyright holder nor the names of its
17+
contributors may be used to endorse or promote products derived from
18+
this software without specific prior written permission.
19+
20+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package config
2+
3+
import (
4+
"sort"
5+
"strings"
6+
7+
"gopkg.in/yaml.v3"
8+
9+
"github.com/daixiang0/gci/pkg/config"
10+
"github.com/daixiang0/gci/pkg/section"
11+
)
12+
13+
var defaultOrder = map[string]int{
14+
section.StandardType: 0,
15+
section.DefaultType: 1,
16+
section.CustomType: 2,
17+
section.BlankType: 3,
18+
section.DotType: 4,
19+
section.AliasType: 5,
20+
section.LocalModuleType: 6,
21+
}
22+
23+
type Config struct {
24+
config.BoolConfig
25+
Sections section.SectionList
26+
SectionSeparators section.SectionList
27+
}
28+
29+
type YamlConfig struct {
30+
Cfg config.BoolConfig `yaml:",inline"`
31+
SectionStrings []string `yaml:"sections"`
32+
SectionSeparatorStrings []string `yaml:"sectionseparators"`
33+
34+
// Since history issue, Golangci-lint needs Analyzer to run and GCI add an Analyzer layer to integrate.
35+
// The ModPath param is only from analyzer.go, no need to set it in all other places.
36+
ModPath string `yaml:"-"`
37+
}
38+
39+
func (g YamlConfig) Parse() (*Config, error) {
40+
var err error
41+
42+
sections, err := section.Parse(g.SectionStrings)
43+
if err != nil {
44+
return nil, err
45+
}
46+
if sections == nil {
47+
sections = section.DefaultSections()
48+
}
49+
if err := configureSections(sections, g.ModPath); err != nil {
50+
return nil, err
51+
}
52+
53+
// if default order sorted sections
54+
if !g.Cfg.CustomOrder {
55+
sort.Slice(sections, func(i, j int) bool {
56+
sectionI, sectionJ := sections[i].Type(), sections[j].Type()
57+
58+
if g.Cfg.NoLexOrder || strings.Compare(sectionI, sectionJ) != 0 {
59+
return defaultOrder[sectionI] < defaultOrder[sectionJ]
60+
}
61+
62+
return strings.Compare(sections[i].String(), sections[j].String()) < 0
63+
})
64+
}
65+
66+
sectionSeparators, err := section.Parse(g.SectionSeparatorStrings)
67+
if err != nil {
68+
return nil, err
69+
}
70+
if sectionSeparators == nil {
71+
sectionSeparators = section.DefaultSectionSeparators()
72+
}
73+
74+
return &Config{g.Cfg, sections, sectionSeparators}, nil
75+
}
76+
77+
func ParseConfig(in string) (*Config, error) {
78+
config := YamlConfig{}
79+
80+
err := yaml.Unmarshal([]byte(in), &config)
81+
if err != nil {
82+
return nil, err
83+
}
84+
85+
gciCfg, err := config.Parse()
86+
if err != nil {
87+
return nil, err
88+
}
89+
90+
return gciCfg, nil
91+
}
92+
93+
// configureSections now only do golang module path finding.
94+
// Since history issue, Golangci-lint needs Analyzer to run and GCI add an Analyzer layer to integrate.
95+
// The path param is from analyzer.go, in all other places should pass empty string.
96+
func configureSections(sections section.SectionList, path string) error {
97+
for _, sec := range sections {
98+
switch s := sec.(type) {
99+
case *section.LocalModule:
100+
if err := s.Configure(path); err != nil {
101+
return err
102+
}
103+
}
104+
}
105+
return nil
106+
}
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Code borrowed from gci and modified to use new std packages.
2+
3+
https://github.com/daixiang0/gci/pull/227
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package section
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"strings"
7+
8+
"github.com/daixiang0/gci/pkg/section"
9+
)
10+
11+
func Parse(data []string) (section.SectionList, error) {
12+
if len(data) == 0 {
13+
return nil, nil
14+
}
15+
16+
var list section.SectionList
17+
var errString string
18+
for _, d := range data {
19+
s := strings.ToLower(d)
20+
if len(s) == 0 {
21+
return nil, nil
22+
}
23+
24+
if s == "default" {
25+
list = append(list, section.Default{})
26+
} else if s == "standard" {
27+
list = append(list, Standard{})
28+
} else if s == "newline" {
29+
list = append(list, section.NewLine{})
30+
} else if strings.HasPrefix(s, "prefix(") && len(d) > 8 {
31+
list = append(list, section.Custom{Prefix: d[7 : len(d)-1]})
32+
} else if strings.HasPrefix(s, "commentline(") && len(d) > 13 {
33+
list = append(list, section.Custom{Prefix: d[12 : len(d)-1]})
34+
} else if s == "dot" {
35+
list = append(list, section.Dot{})
36+
} else if s == "blank" {
37+
list = append(list, section.Blank{})
38+
} else if s == "alias" {
39+
list = append(list, section.Alias{})
40+
} else if s == "localmodule" {
41+
// pointer because we need to mutate the section at configuration time
42+
list = append(list, &section.LocalModule{})
43+
} else {
44+
errString += fmt.Sprintf(" %s", s)
45+
}
46+
}
47+
if errString != "" {
48+
return nil, errors.New(fmt.Sprintf("invalid params:%s", errString))
49+
}
50+
return list, nil
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package section
2+
3+
import (
4+
"github.com/daixiang0/gci/pkg/parse"
5+
"github.com/daixiang0/gci/pkg/specificity"
6+
)
7+
8+
const StandardType = "standard"
9+
10+
type Standard struct{}
11+
12+
func (s Standard) MatchSpecificity(spec *parse.GciImports) specificity.MatchSpecificity {
13+
if isStandard(spec.Path) {
14+
return specificity.StandardMatch{}
15+
}
16+
return specificity.MisMatch{}
17+
}
18+
19+
func (s Standard) String() string {
20+
return StandardType
21+
}
22+
23+
func (s Standard) Type() string {
24+
return StandardType
25+
}
26+
27+
func isStandard(pkg string) bool {
28+
_, ok := standardPackages[pkg]
29+
return ok
30+
}

0 commit comments

Comments
 (0)