forked from golang/tools
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
internal/lsp: show errors when the user is in the wrong directory
If we encounter `go list` errors when loading a user's package, we should try to see if they've encountered any of our common error cases. They are: 1) a user has GO111MODULE=off, but is outside of their GOPATH, and 2) a user is in module mode but doesn't have a go.mod file. Fortunately, go/packages does a great job handling edge cases so gopls will work well for most of them. The main issue will be unresolved imports. These show up in DepErrors in `go list`, so go/packages doesn't propagate them through to the list of errors. This will require changes to go/packages. Updates golang/go#31668 Change-Id: Ibd5253b33b38caffeaad54a403c74c0b861fcc14 Reviewed-on: https://go-review.googlesource.com/c/tools/+/194018 Run-TryBot: Rebecca Stambler <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Cottrell <[email protected]>
- Loading branch information
1 parent
7956c30
commit 6aeba54
Showing
8 changed files
with
119 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package source | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"path/filepath" | ||
"strings" | ||
|
||
"golang.org/x/tools/internal/span" | ||
) | ||
|
||
func checkCommonErrors(ctx context.Context, view View, uri span.URI) (string, error) { | ||
// Some cases we should be able to detect: | ||
// | ||
// 1. The user is in GOPATH mode and is working outside their GOPATH | ||
// 2. The user is in module mode and has opened a subdirectory of their module | ||
// | ||
gopath := os.Getenv("GOPATH") | ||
cfg := view.Config(ctx) | ||
|
||
// Invoke `go env GOMOD` inside of the directory of the file. | ||
fdir := filepath.Dir(uri.Filename()) | ||
b, err := invokeGo(ctx, fdir, cfg.Env, "env", "GOMOD") | ||
if err != nil { | ||
return "", err | ||
} | ||
modFile := strings.TrimSpace(b.String()) | ||
if modFile == filepath.FromSlash("/dev/null") { | ||
modFile = "" | ||
} | ||
|
||
// Not inside of a module. | ||
inAModule := modFile != "" | ||
inGopath := strings.HasPrefix(uri.Filename(), filepath.Join(gopath, "src")) | ||
moduleMode := os.Getenv("GO111MODULE") | ||
|
||
var msg string | ||
// The user is in a module. | ||
if inAModule { | ||
// The workspace root is open to a directory different from the module root. | ||
if modRoot := filepath.Dir(modFile); cfg.Dir != filepath.Dir(modFile) { | ||
msg = fmt.Sprintf("Your workspace root is %s, but your module root is %s. Please add %s as a workspace folder.", cfg.Dir, modRoot, modRoot) | ||
} | ||
} else if inGopath { | ||
if moduleMode == "on" { | ||
msg = "You are in module mode, but you are not inside of a module. Please create a module." | ||
} | ||
} else { | ||
msg = "You are neither in a module nor in your GOPATH. Please see X for information on how to set up your Go project." | ||
} | ||
return msg, nil | ||
} | ||
|
||
// invokeGo returns the stdout of a go command invocation. | ||
// Borrowed from golang.org/x/tools/go/packages/golist.go. | ||
func invokeGo(ctx context.Context, dir string, env []string, args ...string) (*bytes.Buffer, error) { | ||
stdout := new(bytes.Buffer) | ||
stderr := new(bytes.Buffer) | ||
cmd := exec.CommandContext(ctx, "go", args...) | ||
// 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. | ||
// The Go stdlib has a special feature where if the cwd and the PWD are the | ||
// same node then it trusts the PWD, so by setting it in the env for the child | ||
// process we fix up all the paths returned by the go command. | ||
cmd.Env = append(append([]string{}, env...), "PWD="+dir) | ||
cmd.Dir = dir | ||
cmd.Stdout = stdout | ||
cmd.Stderr = stderr | ||
|
||
if err := cmd.Run(); err != nil { | ||
// Check for 'go' executable not being found. | ||
if ee, ok := err.(*exec.Error); ok && ee.Err == exec.ErrNotFound { | ||
return nil, fmt.Errorf("'gopls requires 'go', but %s", exec.ErrNotFound) | ||
} | ||
if _, ok := err.(*exec.ExitError); !ok { | ||
// Catastrophic error: | ||
// - context cancellation | ||
return nil, fmt.Errorf("couldn't exec 'go %v': %s %T", args, err, err) | ||
} | ||
} | ||
return stdout, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters