internal/lsp: handle major versions above v0/v1 in workspace module mode

Workspace mode did not yet support major versions other than v0/v1. To
do so, we have to check the major version before creating the fake gopls
workspace pseudoversion that goes in the workspace module.

Fixes golang/go#41807

Change-Id: I108fe504fdf9e9a0ce23f7102991c9ae78f12a9f
Reviewed-on: https://go-review.googlesource.com/c/tools/+/260004
Trust: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
This commit is contained in:
Rebecca Stambler 2020-10-06 21:08:57 -04:00
parent 03e951c4ab
commit ffec97847f
5 changed files with 78 additions and 5 deletions

View File

@ -455,3 +455,59 @@ var _ = fmt.Printf
env.GoToDefinition("/tmp/foo.go", env.RegexpSearch("/tmp/foo.go", `Printf`))
})
}
func TestMultiModuleV2(t *testing.T) {
const multiModule = `
-- moda/a/go.mod --
module a.com
require b.com/v2 v2.0.0
-- moda/a/a.go --
package a
import (
"b.com/v2/b"
)
func main() {
var x int
_ = b.Hi()
}
-- modb/go.mod --
module b.com
-- modb/b/b.go --
package b
func Hello() int {
var x int
}
-- modb/v2/go.mod --
module b.com/v2
-- modb/v2/b/b.go --
package b
func Hi() int {
var x int
}
-- modc/go.mod --
module gopkg.in/yaml.v1 // test gopkg.in versions
-- modc/main.go --
package main
func main() {
var x int
}
`
withOptions(
WithModes(Experimental),
).run(t, multiModule, func(t *testing.T, env *Env) {
env.Await(
env.DiagnosticAtRegexp("moda/a/a.go", "x"),
env.DiagnosticAtRegexp("modb/b/b.go", "x"),
env.DiagnosticAtRegexp("modb/v2/b/b.go", "x"),
env.DiagnosticAtRegexp("modc/main.go", "x"),
)
})
}

View File

@ -278,7 +278,7 @@ func typeCheck(ctx context.Context, snapshot *snapshot, m *metadata, mode source
// meaningless, and we don't want clients to access it.
if m.module != nil {
version := m.module.Version
if version == source.WorkspaceModuleVersion {
if source.IsWorkspaceModuleVersion(version) {
version = ""
}
pkg.version = &module.Version{

View File

@ -20,6 +20,7 @@ import (
"sync"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/packages"
"golang.org/x/tools/internal/event"
@ -1545,7 +1546,14 @@ func (s *snapshot) BuildWorkspaceModFile(ctx context.Context) (*modfile.File, er
}
path := parsed.File.Module.Mod.Path
paths[path] = mod
file.AddNewRequire(path, source.WorkspaceModuleVersion, false)
// If the module's path includes a major version, we expect it to have
// a matching major version.
_, majorVersion, _ := module.SplitPathVersion(path)
if majorVersion == "" {
majorVersion = "/v0"
}
majorVersion = strings.TrimLeft(majorVersion, "/.") // handle gopkg.in versions
file.AddNewRequire(path, source.WorkspaceModuleVersion(majorVersion), false)
if err := file.AddReplace(path, "", mod.rootURI.Filename(), ""); err != nil {
return nil, err
}

View File

@ -88,7 +88,7 @@ func ExtractGoCommandError(ctx context.Context, snapshot source.Snapshot, fh sou
path, version := match[1], match[2]
// Any module versions that come from the workspace module should not
// be shown to the user.
if version == source.WorkspaceModuleVersion {
if source.IsWorkspaceModuleVersion(version) {
continue
}
if err := module.Check(path, version); err != nil {

View File

@ -548,8 +548,17 @@ var (
PackagesLoadError = errors.New("packages.Load error")
)
// WorkspaceModuleVersion is the nonexistent pseudoversion used in the
// WorkspaceModuleVersion is the nonexistent pseudoversion suffix used in the
// construction of the workspace module. It is exported so that we can make
// sure not to show this version to end users in error messages, to avoid
// confusion.
const WorkspaceModuleVersion = "v0.0.0-goplsworkspace"
// The major version is not included, as that depends on the module path.
const workspaceModuleVersion = ".0.0-goplsworkspace"
func IsWorkspaceModuleVersion(version string) bool {
return strings.HasSuffix(version, workspaceModuleVersion)
}
func WorkspaceModuleVersion(majorVersion string) string {
return majorVersion + workspaceModuleVersion
}