Skip to content

x/tools/gopls/internal/analysis/modernize: the ./... command is ineffective for certain repositories that use the multi-module pattern #73650

@cuishuang

Description

@cuishuang

Go version

go1.24.2

Output of go env in your module/workspace:

AR='ar'
CC='clang'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='0'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='clang++'
GCCGO='gccgo'
GO111MODULE='auto'
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/Users/xxx/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/xxx/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch arm64 -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/9t/839s3jmj73bcgyp5x_xh3gw00000gn/T/go-build2973783802=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/Users/xxxx/20250428/tools/gopls/go.mod'
GOMODCACHE='/Users/xxx/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/xxx/go'
GOPRIVATE=''
GOPROXY='https://goproxy.cn,direct'
GOROOT='/usr/local/go'
GOSUMDB='off'
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/xxx/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.24.2'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

In many repositories that use the multi-module pattern (often monorepos), if there is a go.mod file in one directory, the Go files in a subdirectory that also contains a go.mod file will not be processed.

This organizational structure may violate the best practices of multi-module setups, but I have found that such situations are prevalent in many open-source projects.

For example, for the following organizational structure and code:

➜  tmp20250509 tree -f
.
├── ./diff.go
├── ./go.mod
├── ./go.sum
└── ./utils
    ├── ./utils/go.mod
    └── ./utils/utils.go

2 directories, 5 files
➜  tmp20250509 cat diff.go       
package main

func main() {
	Diff()
}

func Diff() {

	toPaths := map[string]string{
		"diff1": "11111",
		"diff2": "22222",
	}

	paths := make(map[string]string)
	for key, value := range toPaths {
		paths[key] = value
	}

}
➜  tmp20250509 cat utils/utils.go 
package utilssss

func Demo() {

	toPaths := map[string]string{
		"1": "one",
		"2": "two",
	}

	paths := make(map[string]string)
	for key, value := range toPaths {
		paths[key] = value
	}

What did you see happen?

After executing modernize -fix -test ./...

➜  tmp20250509 modernize  -fix -test ./... 
➜  tmp20250509 
➜  tmp20250509 
➜  tmp20250509 cat diff.go       
package main

import "maps"

func main() {
	Diff()
}

func Diff() {

	toPaths := map[string]string{
		"diff1": "11111",
		"diff2": "22222",
	}

	paths := make(map[string]string)
	maps.Copy(paths, toPaths)

}
➜  tmp20250509 
➜  tmp20250509 cat utils/utils.go
package utilssss

func Demo() {

	toPaths := map[string]string{
		"1": "one",
		"2": "two",
	}

	paths := make(map[string]string)
	for key, value := range toPaths {
		paths[key] = value
	}

}

The diff.go file has changed as expected, while utils/utils.go has not changed.

What did you expect to see?

I'm not sure if this is expected behavior or a bug. However, I think that since ./... is explicitly specified, it should process the Go files in the current directory and all its subdirectories. Otherwise, this situation would lead to inconsistencies in style within the same repository.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ToolProposalIssues describing a requested change to a Go tool or command-line program.ToolsThis label describes issues relating to any tools in the x/tools repository.WaitingForInfoIssue is not actionable because of missing required information, which needs to be provided.goplsIssues related to the Go language server, gopls.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions