Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance LocalModule when no go sources found in project root #192

Merged
merged 1 commit into from Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -50,8 +50,8 @@ Since v0.9.0, GCI always puts C import block as the first.

### LocalModule

Local module detection is done via listing packages from *the directory where
`gci` is invoked* and reading the modules off these. This means:
Local module detection is done via reading the module name from the `go.mod`
file in *the directory where `gci` is invoked*. This means:

- This mode works when `gci` is invoked from a module root (i.e. directory
containing `go.mod`)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -8,6 +8,7 @@ require (
github.com/spf13/cobra v1.6.1
github.com/stretchr/testify v1.8.1
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
gopkg.in/yaml.v3 v3.0.1
Expand All @@ -19,6 +20,5 @@ 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/mod v0.8.0 // indirect
golang.org/x/sys v0.5.0 // indirect
)
95 changes: 54 additions & 41 deletions pkg/gci/gci_test.go
Expand Up @@ -21,10 +21,6 @@ func init() {
}

func TestRun(t *testing.T) {
// if runtime.GOOS == "windows" {
// t.Skip("Skipping test on Windows")
// }

for i := range testCases {
t.Run(fmt.Sprintf("run case: %s", testCases[i].name), func(t *testing.T) {
config, err := config.ParseConfig(testCases[i].config)
Expand Down Expand Up @@ -56,35 +52,65 @@ func chdir(t *testing.T, dir string) {
func readConfig(t *testing.T, configPath string) *config.Config {
rawConfig, err := os.ReadFile(configPath)
require.NoError(t, err)
config, err := config.ParseConfig(string(rawConfig))
cfg, err := config.ParseConfig(string(rawConfig))
require.NoError(t, err)

return config
return cfg
}

func TestRunWithLocalModule(t *testing.T) {
moduleDir := filepath.Join("testdata", "module")
// files with a corresponding '*.out.go' file containing the expected
// result of formatting
testedFiles := []string{
"main.go",
filepath.Join("internal", "foo", "lib.go"),
tests := []struct {
name string
moduleDir string
// files with a corresponding '*.out.go' file containing the expected
// result of formatting
testedFiles []string
}{
{
name: `default module test case`,
moduleDir: filepath.Join("testdata", "module"),
testedFiles: []string{
"main.go",
filepath.Join("internal", "foo", "lib.go"),
},
},
{
name: `canonical module without go sources in root dir`,
moduleDir: filepath.Join("testdata", "module_canonical"),
testedFiles: []string{
filepath.Join("cmd", "client", "main.go"),
filepath.Join("cmd", "server", "main.go"),
filepath.Join("internal", "foo", "lib.go"),
},
},
{
name: `non-canonical module without go sources in root dir`,
moduleDir: filepath.Join("testdata", "module_noncanonical"),
testedFiles: []string{
filepath.Join("cmd", "client", "main.go"),
filepath.Join("cmd", "server", "main.go"),
filepath.Join("internal", "foo", "lib.go"),
},
},
}

// run subtests for expected module loading behaviour
chdir(t, moduleDir)
cfg := readConfig(t, "config.yaml")

for _, path := range testedFiles {
t.Run(path, func(t *testing.T) {
// *.go -> *.out.go
expected, err := os.ReadFile(strings.TrimSuffix(path, ".go") + ".out.go")
require.NoError(t, err)

_, got, err := LoadFormatGoFile(io.File{path}, *cfg)

require.NoError(t, err)
require.Equal(t, string(expected), string(got))
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// run subtests for expected module loading behaviour
chdir(t, tt.moduleDir)
cfg := readConfig(t, "config.yaml")

for _, path := range tt.testedFiles {
t.Run(path, func(t *testing.T) {
// *.go -> *.out.go
expected, err := os.ReadFile(strings.TrimSuffix(path, ".go") + ".out.go")
require.NoError(t, err)

_, got, err := LoadFormatGoFile(io.File{path}, *cfg)

require.NoError(t, err)
require.Equal(t, string(expected), string(got))
})
}
})
}
}
Expand All @@ -96,18 +122,5 @@ func TestRunWithLocalModuleWithPackageLoadFailure(t *testing.T) {

chdir(t, dir)
_, err := config.ParseConfig(configContent)
require.ErrorContains(t, err, "failed to load local modules: ")
}

func TestRunWithLocalModuleWithModuleLookupError(t *testing.T) {
dir := t.TempDir()
// error from trying to list packages under module with no go files
configContent := "sections:\n - LocalModule\n"
goModContent := "module example.com/foo\n"
require.NoError(t, os.WriteFile(filepath.Join(dir, "go.mod"), []byte(goModContent), 0o644))

chdir(t, dir)
_, err := config.ParseConfig(configContent)
require.ErrorContains(t, err, "error reading local packages: ")
require.ErrorContains(t, err, dir)
require.ErrorContains(t, err, "go.mod: open go.mod:")
}
23 changes: 0 additions & 23 deletions pkg/gci/testdata.go
Expand Up @@ -1293,29 +1293,6 @@ import (
"fmt"
"net"
)
`,
},
{
"basic module",
// implicitly relies on the local module name being: github.com/daixiang0/gci
`sections:
- Standard
- LocalModule
`,
`package main
import (
"os"
"github.com/daixiang0/gci/cmd/gci"
)
`,
`package main
import (
"os"
"github.com/daixiang0/gci/cmd/gci"
)
`,
},
}
4 changes: 4 additions & 0 deletions pkg/gci/testdata/module_canonical/.gitattributes
@@ -0,0 +1,4 @@
# try and stop git running on Windows from converting line endings from
# in all Go files under this directory. This is to avoid inconsistent test
# results when `gci` strips "\r" characters
**/*.go eol=lf
9 changes: 9 additions & 0 deletions pkg/gci/testdata/module_canonical/cmd/client/main.go
@@ -0,0 +1,9 @@
package main

import (
"example.com/service/internal"
"example.com/service/internal/bar"
"example.com/service/internal/foo"
"golang.org/x/net"
"log"
)
11 changes: 11 additions & 0 deletions pkg/gci/testdata/module_canonical/cmd/client/main.out.go
@@ -0,0 +1,11 @@
package main

import (
"log"

"golang.org/x/net"

"example.com/service/internal"
"example.com/service/internal/bar"
"example.com/service/internal/foo"
)
9 changes: 9 additions & 0 deletions pkg/gci/testdata/module_canonical/cmd/server/main.go
@@ -0,0 +1,9 @@
package main

import (
"example.com/service/internal"
"example.com/service/internal/bar"
"example.com/service/internal/foo"
"golang.org/x/net"
"log"
)
11 changes: 11 additions & 0 deletions pkg/gci/testdata/module_canonical/cmd/server/main.out.go
@@ -0,0 +1,11 @@
package main

import (
"log"

"golang.org/x/net"

"example.com/service/internal"
"example.com/service/internal/bar"
"example.com/service/internal/foo"
)
4 changes: 4 additions & 0 deletions pkg/gci/testdata/module_canonical/config.yaml
@@ -0,0 +1,4 @@
sections:
- Standard
- Default
- LocalModule
3 changes: 3 additions & 0 deletions pkg/gci/testdata/module_canonical/go.mod
@@ -0,0 +1,3 @@
module example.com/service

go 1.20
1 change: 1 addition & 0 deletions pkg/gci/testdata/module_canonical/internal/bar/lib.go
@@ -0,0 +1 @@
package bar
6 changes: 6 additions & 0 deletions pkg/gci/testdata/module_canonical/internal/foo/lib.go
@@ -0,0 +1,6 @@
package foo

import (
"example.com/service/internal/bar"
"log"
)
7 changes: 7 additions & 0 deletions pkg/gci/testdata/module_canonical/internal/foo/lib.out.go
@@ -0,0 +1,7 @@
package foo

import (
"log"

"example.com/service/internal/bar"
)
1 change: 1 addition & 0 deletions pkg/gci/testdata/module_canonical/internal/lib.go
@@ -0,0 +1 @@
package internal
4 changes: 4 additions & 0 deletions pkg/gci/testdata/module_noncanonical/.gitattributes
@@ -0,0 +1,4 @@
# try and stop git running on Windows from converting line endings from
# in all Go files under this directory. This is to avoid inconsistent test
# results when `gci` strips "\r" characters
**/*.go eol=lf
9 changes: 9 additions & 0 deletions pkg/gci/testdata/module_noncanonical/cmd/client/main.go
@@ -0,0 +1,9 @@
package main

import (
"golang.org/x/net"
"log"
"service/internal"
"service/internal/bar"
"service/internal/foo"
)
11 changes: 11 additions & 0 deletions pkg/gci/testdata/module_noncanonical/cmd/client/main.out.go
@@ -0,0 +1,11 @@
package main

import (
"log"

"golang.org/x/net"

"service/internal"
"service/internal/bar"
"service/internal/foo"
)
9 changes: 9 additions & 0 deletions pkg/gci/testdata/module_noncanonical/cmd/server/main.go
@@ -0,0 +1,9 @@
package main

import (
"golang.org/x/net"
"log"
"service/internal"
"service/internal/bar"
"service/internal/foo"
)
11 changes: 11 additions & 0 deletions pkg/gci/testdata/module_noncanonical/cmd/server/main.out.go
@@ -0,0 +1,11 @@
package main

import (
"log"

"golang.org/x/net"

"service/internal"
"service/internal/bar"
"service/internal/foo"
)
4 changes: 4 additions & 0 deletions pkg/gci/testdata/module_noncanonical/config.yaml
@@ -0,0 +1,4 @@
sections:
- Standard
- Default
- LocalModule
3 changes: 3 additions & 0 deletions pkg/gci/testdata/module_noncanonical/go.mod
@@ -0,0 +1,3 @@
module service

go 1.20
1 change: 1 addition & 0 deletions pkg/gci/testdata/module_noncanonical/internal/bar/lib.go
@@ -0,0 +1 @@
package bar
6 changes: 6 additions & 0 deletions pkg/gci/testdata/module_noncanonical/internal/foo/lib.go
@@ -0,0 +1,6 @@
package foo

import (
"log"
"service/internal/bar"
)
7 changes: 7 additions & 0 deletions pkg/gci/testdata/module_noncanonical/internal/foo/lib.out.go
@@ -0,0 +1,7 @@
package foo

import (
"log"

"service/internal/bar"
)
1 change: 1 addition & 0 deletions pkg/gci/testdata/module_noncanonical/internal/lib.go
@@ -0,0 +1 @@
package internal