diff --git a/go/packages/golist.go b/go/packages/golist.go index 2ac7c02a3b..a9a1ba89e8 100644 --- a/go/packages/golist.go +++ b/go/packages/golist.go @@ -673,7 +673,7 @@ func golistDriver(cfg *Config, rootsDirs func() *goInfo, words ...string) (*driv // Run "go list" for complete // information on the specified packages. - buf, err := invokeGo(cfg, golistargs(cfg, words)...) + buf, err := invokeGo(cfg, "list", golistargs(cfg, words)...) if err != nil { return nil, err } @@ -877,7 +877,7 @@ func absJoin(dir string, fileses ...[]string) (res []string) { func golistargs(cfg *Config, words []string) []string { const findFlags = NeedImports | NeedTypes | NeedSyntax | NeedTypesInfo fullargs := []string{ - "list", "-e", "-json", + "-e", "-json", fmt.Sprintf("-compiled=%t", cfg.Mode&(NeedCompiledGoFiles|NeedSyntax|NeedTypesInfo|NeedTypesSizes) != 0), fmt.Sprintf("-test=%t", cfg.Tests), fmt.Sprintf("-export=%t", usesExportData(cfg)), @@ -893,10 +893,13 @@ func golistargs(cfg *Config, words []string) []string { } // invokeGo returns the stdout of a go command invocation. -func invokeGo(cfg *Config, args ...string) (*bytes.Buffer, error) { +func invokeGo(cfg *Config, verb string, args ...string) (*bytes.Buffer, error) { stdout := new(bytes.Buffer) stderr := new(bytes.Buffer) - cmd := exec.CommandContext(cfg.Context, "go", args...) + goArgs := []string{verb} + goArgs = append(goArgs, cfg.BuildFlags...) + goArgs = append(goArgs, args...) + cmd := exec.CommandContext(cfg.Context, "go", goArgs...) // On darwin the cwd gets resolved to the real path, which breaks anything that // expects the working directory to keep the original path, including the // go command when dealing with modules. diff --git a/internal/lsp/cache/modfiles.go b/internal/lsp/cache/modfiles.go index 3fc2b9744b..6d87f43b78 100644 --- a/internal/lsp/cache/modfiles.go +++ b/internal/lsp/cache/modfiles.go @@ -17,14 +17,20 @@ import ( errors "golang.org/x/xerrors" ) -// Borrowed from (internal/imports/mod.go:620) // This function will return the main go.mod file for this folder if it exists and whether the -modfile // flag exists for this version of go. func modfileFlagExists(ctx context.Context, folder string, env []string) (string, bool, error) { - const format = `{{.GoMod}} -{{range context.ReleaseTags}}{{if eq . "go1.14"}}{{.}}{{end}}{{end}} -` - stdout, err := source.InvokeGo(ctx, folder, env, "list", "-m", "-f", format) + var tempEnv []string + for i := range env { + tempEnv = append(tempEnv, env[i]) + if strings.Contains(env[i], "GO111MODULE") { + tempEnv[i] = "GO111MODULE=off" + } + } + // Borrowed from (internal/imports/mod.go:620) + const format = `{{range context.ReleaseTags}}{{if eq . "go1.14"}}{{.}}{{end}}{{end}}` + // Check the go version by running "go list" with modules off. + stdout, err := source.InvokeGo(ctx, folder, tempEnv, "list", "-f", format) if err != nil { return "", false, err } @@ -32,7 +38,16 @@ func modfileFlagExists(ctx context.Context, folder string, env []string) (string if len(lines) < 2 { return "", false, errors.Errorf("unexpected stdout: %q", stdout) } - return lines[0], lines[1] == "go1.14", nil + // Get the go.mod file associated with this module. + b, err := source.InvokeGo(ctx, folder, env, "env", "GOMOD") + if err != nil { + return "", false, err + } + modfile := strings.TrimSpace(b.String()) + if modfile == os.DevNull { + return "", false, errors.Errorf("go env GOMOD did not detect a go.mod file in this folder") + } + return modfile, lines[0] == "go1.14", nil } // The function getModfiles will return the go.mod files associated with the directory that is passed in. @@ -51,22 +66,19 @@ func getModfiles(ctx context.Context, folder string, options source.Options) (*m if modfile == "" || modfile == os.DevNull { return nil, errors.Errorf("go env GOMOD cannot detect a go.mod file in this folder") } - f, err := ioutil.TempFile("", "go.*.mod") + tempFile, err := ioutil.TempFile("", "go.*.mod") if err != nil { return nil, err } - defer f.Close() + defer tempFile.Close() // Copy the current go.mod file into the temporary go.mod file. origFile, err := os.Open(modfile) if err != nil { return nil, err } defer origFile.Close() - if _, err := io.Copy(f, origFile); err != nil { + if _, err := io.Copy(tempFile, origFile); err != nil { return nil, err } - if err := f.Close(); err != nil { - return nil, err - } - return &modfiles{real: modfile, temp: f.Name()}, nil + return &modfiles{real: modfile, temp: tempFile.Name()}, nil }