Skip to content

Commit

Permalink
Enhance LocalModule when no go sources found in project root
Browse files Browse the repository at this point in the history
  • Loading branch information
petr-korobeinikov committed Mar 4, 2024
1 parent e9e4f70 commit a4701e5
Show file tree
Hide file tree
Showing 24 changed files with 209 additions and 24 deletions.
74 changes: 53 additions & 21 deletions pkg/gci/gci_test.go
Expand Up @@ -63,28 +63,58 @@ func readConfig(t *testing.T, configPath string) *config.Config {
}

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 @@ -100,6 +130,8 @@ func TestRunWithLocalModuleWithPackageLoadFailure(t *testing.T) {
}

func TestRunWithLocalModuleWithModuleLookupError(t *testing.T) {
t.Skipf("In fact there is no error when no go files found in the project root")

dir := t.TempDir()
// error from trying to list packages under module with no go files
configContent := "sections:\n - LocalModule\n"
Expand Down
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
27 changes: 24 additions & 3 deletions pkg/section/local_module.go
Expand Up @@ -2,8 +2,10 @@ package section

import (
"fmt"
"os"
"strings"

"golang.org/x/mod/modfile"
"golang.org/x/tools/go/packages"

"github.com/daixiang0/gci/pkg/parse"
Expand Down Expand Up @@ -47,7 +49,7 @@ func (m *LocalModule) Configure() error {
}

func findLocalModules() ([]string, error) {
packages, err := packages.Load(
pkgs, err := packages.Load(
// find the package in the current dir and load its module
// NeedFiles so there is some more info in package errors
&packages.Config{Mode: packages.NeedModule | packages.NeedFiles},
Expand All @@ -59,12 +61,21 @@ func findLocalModules() ([]string, error) {

uniqueModules := make(map[string]struct{})

for _, pkg := range packages {
if len(pkg.Errors) != 0 {
for _, pkg := range pkgs {
if len(pkg.Errors) != 0 && !errorsContainListError(pkg.Errors) {
return nil, fmt.Errorf("error reading local packages: %v", pkg.Errors)
}
if pkg.Module != nil {
uniqueModules[pkg.Module.Path] = struct{}{}
} else {
b, err := os.ReadFile("go.mod")
if err != nil {
return nil, fmt.Errorf("failed to read go.mod file directly: %v", err)
}

name := modfile.ModulePath(b)
uniqueModules[name] = struct{}{}

}
}

Expand All @@ -75,3 +86,13 @@ func findLocalModules() ([]string, error) {

return modPaths, nil
}

func errorsContainListError(errors []packages.Error) bool {
for _, v := range errors {
if v.Kind == packages.ListError {
return true
}
}

return false
}

0 comments on commit a4701e5

Please sign in to comment.