Skip to content

Commit

Permalink
integrate Golangci-lint with localmodule enabled
Browse files Browse the repository at this point in the history
Signed-off-by: Loong <long0dai@foxmail.com>
  • Loading branch information
daixiang0 committed Mar 27, 2024
1 parent 4725b0c commit d11711b
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 46 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/gci.yml
Expand Up @@ -8,7 +8,7 @@ jobs:
name: Build ${{ matrix.target_os }}_${{ matrix.target_arch }} binaries
runs-on: ${{ matrix.os }}
env:
GOVER: 1.18
GOVER: 1.21
GOOS: ${{ matrix.target_os }}
GOARCH: ${{ matrix.target_arch }}
GOPROXY: https://proxy.golang.org
Expand All @@ -34,11 +34,11 @@ jobs:
target_arch: arm
steps:
- name: Set up Go ${{ env.GOVER }}
uses: actions/setup-go@v2
uses: actions/setup-go@v5
with:
go-version: ${{ env.GOVER }}
- name: Check out code into the Go module directory
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Cache Go modules (Linux)
if: matrix.target_os == 'linux'
uses: actions/cache@v3
Expand Down Expand Up @@ -71,7 +71,7 @@ jobs:
${{ matrix.target_os }}-${{ matrix.target_arch }}-go-${{ env.GOVER }}-build-
- name: golangci-lint
if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux'
uses: golangci/golangci-lint-action@v3.2.0
uses: golangci/golangci-lint-action@v4
with:
version: ${{ env.GOLANGCILINT_VER }}
- name: Run make test
Expand Down
17 changes: 11 additions & 6 deletions README.md
Expand Up @@ -101,13 +101,14 @@ Flags:
--custom-order Enable custom order of sections
-d, --debug Enables debug output from the formatter
-h, --help help for print
-s, --section stringArray Sections define how inputs will be processed. Section names are case-insensitive and may contain parameters in (). The section order is standard > default > custom > blank > dot > alias. The default value is [standard,default].
-s, --section stringArray Sections define how inputs will be processed. Section names are case-insensitive and may contain parameters in (). The section order is standard > default > custom > blank > dot > alias > localmodule. The default value is [standard,default].
standard - standard section that Go provides officially, like "fmt"
Prefix(github.com/daixiang0) - custom section, groups all imports with the specified Prefix. Imports will be matched to the longest Prefix. Multiple custom prefixes may be provided, they will be rendered as distinct sections separated by newline. You can regroup multiple prefixes by separating them with comma: Prefix(github.com/daixiang0,gitlab.com/daixiang0,daixiang0)
default - default section, contains all rest imports
blank - blank section, contains all blank imports.
dot - dot section, contains all dot imports. (default [standard,default])
alias - alias section, contains all alias imports.
localmodule: localmodule section, contains all imports from local packages
--skip-generated Skip generated files
--skip-vendor Skip files inside vendor directory
```
Expand All @@ -126,13 +127,14 @@ Flags:
--custom-order Enable custom order of sections
-d, --debug Enables debug output from the formatter
-h, --help help for write
-s, --section stringArray Sections define how inputs will be processed. Section names are case-insensitive and may contain parameters in (). The section order is standard > default > custom > blank > dot > alias. The default value is [standard,default].
-s, --section stringArray Sections define how inputs will be processed. Section names are case-insensitive and may contain parameters in (). The section order is standard > default > custom > blank > dot > alias > localmodule. The default value is [standard,default].
standard - standard section that Go provides officially, like "fmt"
Prefix(github.com/daixiang0) - custom section, groups all imports with the specified Prefix. Imports will be matched to the longest Prefix. Multiple custom prefixes may be provided, they will be rendered as distinct sections separated by newline. You can regroup multiple prefixes by separating them with comma: Prefix(github.com/daixiang0,gitlab.com/daixiang0,daixiang0)
default - default section, contains all rest imports
blank - blank section, contains all blank imports.
dot - dot section, contains all dot imports. (default [standard,default])
alias - alias section, contains all alias imports.
localmodule: localmodule section, contains all imports from local packages
--skip-generated Skip generated files
--skip-vendor Skip files inside vendor directory
```
Expand All @@ -148,13 +150,14 @@ Flags:
--custom-order Enable custom order of sections
-d, --debug Enables debug output from the formatter
-h, --help help for list
-s, --section stringArray Sections define how inputs will be processed. Section names are case-insensitive and may contain parameters in (). The section order is standard > default > custom > blank > dot > alias. The default value is [standard,default].
-s, --section stringArray Sections define how inputs will be processed. Section names are case-insensitive and may contain parameters in (). The section order is standard > default > custom > blank > dot > alias > localmodule. The default value is [standard,default].
standard - standard section that Go provides officially, like "fmt"
Prefix(github.com/daixiang0) - custom section, groups all imports with the specified Prefix. Imports will be matched to the longest Prefix. Multiple custom prefixes may be provided, they will be rendered as distinct sections separated by newline. You can regroup multiple prefixes by separating them with comma: Prefix(github.com/daixiang0,gitlab.com/daixiang0,daixiang0)
default - default section, contains all rest imports
blank - blank section, contains all blank imports.
alias - alias section, contains all alias imports.
dot - dot section, contains all dot imports. (default [standard,default])
alias - alias section, contains all alias imports.
localmodule: localmodule section, contains all imports from local packages
--skip-generated Skip generated files
--skip-vendor Skip files inside vendor directory
```
Expand All @@ -170,13 +173,14 @@ Flags:
--custom-order Enable custom order of sections
-d, --debug Enables debug output from the formatter
-h, --help help for diff
-s, --section stringArray Sections define how inputs will be processed. Section names are case-insensitive and may contain parameters in (). The section order is standard > default > custom > blank > dot > alias. The default value is [standard,default].
-s, --section stringArray Sections define how inputs will be processed. Section names are case-insensitive and may contain parameters in (). The section order is standard > default > custom > blank > dot > alias > localmodule. The default value is [standard,default].
standard - standard section that Go provides officially, like "fmt"
Prefix(github.com/daixiang0) - custom section, groups all imports with the specified Prefix. Imports will be matched to the longest Prefix. Multiple custom prefixes may be provided, they will be rendered as distinct sections separated by newline. You can regroup multiple prefixes by separating them with comma: Prefix(github.com/daixiang0,gitlab.com/daixiang0,daixiang0)
default - default section, contains all rest imports
blank - blank section, contains all blank imports.
alias - alias section, contains all alias imports.
dot - dot section, contains all dot imports. (default [standard,default])
alias - alias section, contains all alias imports.
localmodule: localmodule section, contains all imports from local packages
--skip-generated Skip generated files
--skip-vendor Skip files inside vendor directory
```
Expand Down Expand Up @@ -367,3 +371,4 @@ import (
- Add more testcases
- Support imports completion (please use `goimports` first then use GCI)
- Optimize comments
- Remove Analyzer layer and fully use analyzer syntax
5 changes: 3 additions & 2 deletions cmd/gci/gcicommand.go
Expand Up @@ -48,13 +48,14 @@ func (e *Executor) newGciCommand(use, short, long string, aliases []string, stdI

debug = cmd.Flags().BoolP("debug", "d", false, "Enables debug output from the formatter")

sectionHelp := `Sections define how inputs will be processed. Section names are case-insensitive and may contain parameters in (). The section order is standard > default > custom > blank > dot > alias. The default value is [standard,default].
sectionHelp := `Sections define how inputs will be processed. Section names are case-insensitive and may contain parameters in (). The section order is standard > default > custom > blank > dot > alias > localmodule. The default value is [standard,default].
standard - standard section that Go provides officially, like "fmt"
Prefix(github.com/daixiang0) - custom section, groups all imports with the specified Prefix. Imports will be matched to the longest Prefix. Multiple custom prefixes may be provided, they will be rendered as distinct sections separated by newline. You can regroup multiple prefixes by separating them with comma: Prefix(github.com/daixiang0,gitlab.com/daixiang0,daixiang0)
default - default section, contains all rest imports
blank - blank section, contains all blank imports.
dot - dot section, contains all dot imports.
alias - alias section, contains all alias imports.`
alias - alias section, contains all alias imports.
localmodule: localmodule section, contains all imports from local packages`

skipGenerated = cmd.Flags().Bool("skip-generated", false, "Skip generated files")
skipVendor = cmd.Flags().Bool("skip-vendor", false, "Skip files inside vendor directory")
Expand Down
14 changes: 8 additions & 6 deletions go.mod
@@ -1,16 +1,19 @@
module github.com/daixiang0/gci

go 1.18
go 1.21

toolchain go1.22.1

require (
github.com/golangci/modinfo v0.3.3
github.com/hexops/gotextdiff v1.0.3
github.com/pmezard/go-difflib v1.0.0
github.com/spf13/cobra v1.6.1
github.com/stretchr/testify v1.8.1
github.com/stretchr/testify v1.9.0
go.uber.org/zap v1.24.0
golang.org/x/mod v0.8.0
golang.org/x/sync v0.1.0
golang.org/x/tools v0.6.0
golang.org/x/mod v0.16.0
golang.org/x/sync v0.6.0
golang.org/x/tools v0.19.0
gopkg.in/yaml.v3 v3.0.1
)

Expand All @@ -20,5 +23,4 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/sys v0.5.0 // indirect
)
28 changes: 13 additions & 15 deletions go.sum
@@ -1,13 +1,17 @@
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golangci/modinfo v0.3.3 h1:YBQDZpDMJpe5mtd0klUFYL8tSVkmF3cmm0fZ48sc7+s=
github.com/golangci/modinfo v0.3.3/go.mod h1:wytF1M5xl9u0ij8YSvhkEVPP3M5Mc7XLl1pxH3B2aUM=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
Expand All @@ -16,30 +20,24 @@ github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUq
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
19 changes: 15 additions & 4 deletions pkg/analyzer/analyzer.go
Expand Up @@ -5,7 +5,9 @@ import (
"go/token"
"strings"

"github.com/golangci/modinfo"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"

"github.com/daixiang0/gci/pkg/config"
"github.com/daixiang0/gci/pkg/gci"
Expand Down Expand Up @@ -45,6 +47,10 @@ var Analyzer = &analysis.Analyzer{
Name: "gci",
Doc: "A tool that control Go package import order and make it always deterministic.",
Run: runAnalysis,
Requires: []*analysis.Analyzer{
inspect.Analyzer,
modinfo.Analyzer,
},
}

func runAnalysis(pass *analysis.Pass) (interface{}, error) {
Expand All @@ -62,8 +68,12 @@ func runAnalysis(pass *analysis.Pass) (interface{}, error) {
return nil, InvalidNumberOfFilesInAnalysis{expectedNumFiles, foundNumFiles}
}

// read configuration options
gciCfg, err := parseGciConfiguration()
file, err := modinfo.FindModuleFromPass(pass)
if err != nil {
return nil, err
}

gciCfg, err := generateGciConfiguration(file.Path).Parse()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -91,7 +101,7 @@ func runAnalysis(pass *analysis.Pass) (interface{}, error) {
return nil, nil
}

func parseGciConfiguration() (*config.Config, error) {
func generateGciConfiguration(modPath string) *config.YamlConfig {
fmtCfg := config.BoolConfig{
NoInlineComments: noInlineComments,
NoPrefixComments: noPrefixComments,
Expand All @@ -109,7 +119,8 @@ func parseGciConfiguration() (*config.Config, error) {
sectionSeparatorStrings = strings.Split(sectionSeparatorsStr, SectionDelimiter)
fmt.Println(sectionSeparatorsStr)
}
return config.YamlConfig{Cfg: fmtCfg, SectionStrings: sectionStrings, SectionSeparatorStrings: sectionSeparatorStrings}.Parse()

return &config.YamlConfig{Cfg: fmtCfg, SectionStrings: sectionStrings, SectionSeparatorStrings: sectionSeparatorStrings, ModPath: modPath}
}

func generateCmdLine(cfg config.Config) string {
Expand Down
13 changes: 10 additions & 3 deletions pkg/config/config.go
Expand Up @@ -38,6 +38,10 @@ type YamlConfig struct {
Cfg BoolConfig `yaml:",inline"`
SectionStrings []string `yaml:"sections"`
SectionSeparatorStrings []string `yaml:"sectionseparators"`

// Since history issue, Golangci-lint needs Analyzer to run and GCI add an Anzlyzer layer to integrate.
// The ModPath param is only from analyer.go, no need to set it in all other places.
ModPath string `yaml:"-"`
}

func (g YamlConfig) Parse() (*Config, error) {
Expand All @@ -50,7 +54,7 @@ func (g YamlConfig) Parse() (*Config, error) {
if sections == nil {
sections = section.DefaultSections()
}
if err := configureSections(sections); err != nil {
if err := configureSections(sections, g.ModPath); err != nil {
return nil, err
}

Expand Down Expand Up @@ -93,11 +97,14 @@ func ParseConfig(in string) (*Config, error) {
return gciCfg, nil
}

func configureSections(sections section.SectionList) error {
// configureSections now only do golang module path finding.
// Since history issue, Golangci-lint needs Analyzer to run and GCI add an Anzlyzer layer to integrate.
// The path param is from analyer.go, in all other places should pass empty string.
func configureSections(sections section.SectionList, path string) error {
for _, sec := range sections {
switch s := sec.(type) {
case *section.LocalModule:
if err := s.Configure(); err != nil {
if err := s.Configure(path); err != nil {
return err
}
}
Expand Down
15 changes: 9 additions & 6 deletions pkg/section/local_module.go
Expand Up @@ -35,14 +35,17 @@ func (m *LocalModule) Type() string {

// Configure configures the module section by finding the module
// for the current path
func (m *LocalModule) Configure() error {
modPath, err := findLocalModule()
if err != nil {
return fmt.Errorf("finding local modules for `localModule` configuration: %w", err)
func (m *LocalModule) Configure(path string) error {
if path != "" {
m.Path = path
} else {
path, err := findLocalModule()
if err != nil {
return fmt.Errorf("finding local modules for `localModule` configuration: %w", err)
}
m.Path = path
}

m.Path = modPath

return nil
}

Expand Down

0 comments on commit d11711b

Please sign in to comment.