gopls/internal/span: move internal/span into gopls
Spans are logically part of gopls, but could not be moved
into the gopls module because of a number of depenencies
from packagestest, analysis, and internal/diff.
Those edges are now broken.
Change-Id: Icba5ebec6b27974f832a1186120a4b87d5f87103
Reviewed-on: https://go-review.googlesource.com/c/tools/+/440176
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Alan Donovan <adonovan@google.com>
Auto-Submit: Alan Donovan <adonovan@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/gopls/doc/design/integrating.md b/gopls/doc/design/integrating.md
index 7937ba8..ba2cc07 100644
--- a/gopls/doc/design/integrating.md
+++ b/gopls/doc/design/integrating.md
@@ -20,7 +20,7 @@
This means that integrators will need to calculate UTF-16 based column offsets.
-[`golang.org/x/tools/internal/span`] has the code to do this in go.
+[`golang.org/x/tools/gopls/internal/span`] has the code to do this in go.
[#31080] tracks making `span` and other useful packages non-internal.
## Edits
@@ -63,7 +63,7 @@
[InitializeResult]: https://pkg.go.dev/golang.org/x/tools/gopls/internal/lsp/protocol#InitializeResult
[ServerCapabilities]: https://pkg.go.dev/golang.org/x/tools/gopls/internal/lsp/protocol#ServerCapabilities
-[`golang.org/x/tools/internal/span`]: https://pkg.go.dev/golang.org/x/tools/internal/span#NewPoint
+[`golang.org/x/tools/gopls/internal/span`]: https://pkg.go.dev/golang.org/x/tools/internal/span#NewPoint
[LSP specification]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/
[lsp-response]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#response-message
diff --git a/gopls/internal/lsp/analysis/fillstruct/fillstruct.go b/gopls/internal/lsp/analysis/fillstruct/fillstruct.go
index 931b219..faf5ba5 100644
--- a/gopls/internal/lsp/analysis/fillstruct/fillstruct.go
+++ b/gopls/internal/lsp/analysis/fillstruct/fillstruct.go
@@ -26,9 +26,9 @@
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/astutil"
"golang.org/x/tools/go/ast/inspector"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/analysisinternal"
"golang.org/x/tools/internal/fuzzy"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/typeparams"
)
diff --git a/gopls/internal/lsp/analysis/undeclaredname/undeclared.go b/gopls/internal/lsp/analysis/undeclaredname/undeclared.go
index eaecc8f..fd8d35e 100644
--- a/gopls/internal/lsp/analysis/undeclaredname/undeclared.go
+++ b/gopls/internal/lsp/analysis/undeclaredname/undeclared.go
@@ -18,8 +18,8 @@
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/ast/astutil"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/analysisinternal"
- "golang.org/x/tools/internal/span"
)
const Doc = `suggested fixes for "undeclared name: <>"
diff --git a/gopls/internal/lsp/cache/analysis.go b/gopls/internal/lsp/cache/analysis.go
index ffd1405..95bac5b 100644
--- a/gopls/internal/lsp/cache/analysis.go
+++ b/gopls/internal/lsp/cache/analysis.go
@@ -16,12 +16,12 @@
"golang.org/x/sync/errgroup"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/analysisinternal"
"golang.org/x/tools/internal/bug"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/event/tag"
"golang.org/x/tools/internal/memoize"
- "golang.org/x/tools/internal/span"
)
func (s *snapshot) Analyze(ctx context.Context, id string, analyzers []*source.Analyzer) ([]*source.Diagnostic, error) {
diff --git a/gopls/internal/lsp/cache/cache.go b/gopls/internal/lsp/cache/cache.go
index 5056111..0eb00f2 100644
--- a/gopls/internal/lsp/cache/cache.go
+++ b/gopls/internal/lsp/cache/cache.go
@@ -20,12 +20,12 @@
"sync/atomic"
"time"
- "golang.org/x/tools/internal/event"
- "golang.org/x/tools/internal/gocommand"
- "golang.org/x/tools/internal/event/tag"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
+ "golang.org/x/tools/internal/event"
+ "golang.org/x/tools/internal/event/tag"
+ "golang.org/x/tools/internal/gocommand"
"golang.org/x/tools/internal/memoize"
- "golang.org/x/tools/internal/span"
)
// New Creates a new cache for gopls operation results, using the given file
diff --git a/gopls/internal/lsp/cache/check.go b/gopls/internal/lsp/cache/check.go
index 7058394..0b37135 100644
--- a/gopls/internal/lsp/cache/check.go
+++ b/gopls/internal/lsp/cache/check.go
@@ -23,12 +23,12 @@
"golang.org/x/tools/go/packages"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/bug"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/event/tag"
"golang.org/x/tools/internal/memoize"
"golang.org/x/tools/internal/packagesinternal"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/typeparams"
"golang.org/x/tools/internal/typesinternal"
)
diff --git a/gopls/internal/lsp/cache/errors.go b/gopls/internal/lsp/cache/errors.go
index d01bf7f..1c38e20 100644
--- a/gopls/internal/lsp/cache/errors.go
+++ b/gopls/internal/lsp/cache/errors.go
@@ -15,12 +15,12 @@
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/packages"
- "golang.org/x/tools/internal/analysisinternal"
- "golang.org/x/tools/internal/bug"
"golang.org/x/tools/gopls/internal/lsp/command"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
+ "golang.org/x/tools/internal/analysisinternal"
+ "golang.org/x/tools/internal/bug"
"golang.org/x/tools/internal/typesinternal"
)
diff --git a/gopls/internal/lsp/cache/graph.go b/gopls/internal/lsp/cache/graph.go
index f90ee96..a801c83 100644
--- a/gopls/internal/lsp/cache/graph.go
+++ b/gopls/internal/lsp/cache/graph.go
@@ -8,7 +8,7 @@
"sort"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
// A metadataGraph is an immutable and transitively closed import
diff --git a/gopls/internal/lsp/cache/load.go b/gopls/internal/lsp/cache/load.go
index 287c310..a77afaa 100644
--- a/gopls/internal/lsp/cache/load.go
+++ b/gopls/internal/lsp/cache/load.go
@@ -19,11 +19,11 @@
"golang.org/x/tools/go/packages"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/event/tag"
"golang.org/x/tools/internal/gocommand"
"golang.org/x/tools/internal/packagesinternal"
- "golang.org/x/tools/internal/span"
)
var loadID uint64 // atomic identifier for loads
diff --git a/gopls/internal/lsp/cache/maps.go b/gopls/internal/lsp/cache/maps.go
index d3fe4e4..edb8d16 100644
--- a/gopls/internal/lsp/cache/maps.go
+++ b/gopls/internal/lsp/cache/maps.go
@@ -6,8 +6,8 @@
import (
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/persistent"
- "golang.org/x/tools/internal/span"
)
// TODO(euroelessar): Use generics once support for go1.17 is dropped.
diff --git a/gopls/internal/lsp/cache/metadata.go b/gopls/internal/lsp/cache/metadata.go
index 7778996..66c679b 100644
--- a/gopls/internal/lsp/cache/metadata.go
+++ b/gopls/internal/lsp/cache/metadata.go
@@ -8,8 +8,8 @@
"go/types"
"golang.org/x/tools/go/packages"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/packagesinternal"
- "golang.org/x/tools/internal/span"
)
// Declare explicit types for package paths, names, and IDs to ensure that we
diff --git a/gopls/internal/lsp/cache/mod.go b/gopls/internal/lsp/cache/mod.go
index 50fa0a4..f8404e7 100644
--- a/gopls/internal/lsp/cache/mod.go
+++ b/gopls/internal/lsp/cache/mod.go
@@ -14,14 +14,14 @@
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
- "golang.org/x/tools/internal/event"
- "golang.org/x/tools/internal/gocommand"
"golang.org/x/tools/gopls/internal/lsp/command"
- "golang.org/x/tools/internal/event/tag"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
+ "golang.org/x/tools/internal/event"
+ "golang.org/x/tools/internal/event/tag"
+ "golang.org/x/tools/internal/gocommand"
"golang.org/x/tools/internal/memoize"
- "golang.org/x/tools/internal/span"
)
// ParseMod parses a go.mod file, using a cache. It may return partial results and an error.
diff --git a/gopls/internal/lsp/cache/mod_tidy.go b/gopls/internal/lsp/cache/mod_tidy.go
index e471a9b..63346dc 100644
--- a/gopls/internal/lsp/cache/mod_tidy.go
+++ b/gopls/internal/lsp/cache/mod_tidy.go
@@ -19,11 +19,11 @@
"golang.org/x/tools/gopls/internal/lsp/command"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/event/tag"
"golang.org/x/tools/internal/gocommand"
"golang.org/x/tools/internal/memoize"
- "golang.org/x/tools/internal/span"
)
// ModTidy returns the go.mod file that would be obtained by running
diff --git a/gopls/internal/lsp/cache/pkg.go b/gopls/internal/lsp/cache/pkg.go
index b1ee50e..76e29ee 100644
--- a/gopls/internal/lsp/cache/pkg.go
+++ b/gopls/internal/lsp/cache/pkg.go
@@ -12,7 +12,7 @@
"golang.org/x/mod/module"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
// pkg contains the type information needed by the source package.
diff --git a/gopls/internal/lsp/cache/session.go b/gopls/internal/lsp/cache/session.go
index 8a45ae2..cb18834 100644
--- a/gopls/internal/lsp/cache/session.go
+++ b/gopls/internal/lsp/cache/session.go
@@ -16,11 +16,11 @@
"golang.org/x/tools/gopls/internal/lsp/command"
"golang.org/x/tools/gopls/internal/lsp/progress"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/gocommand"
"golang.org/x/tools/internal/imports"
"golang.org/x/tools/internal/persistent"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/xcontext"
)
diff --git a/gopls/internal/lsp/cache/snapshot.go b/gopls/internal/lsp/cache/snapshot.go
index fb4e78b..8027b40 100644
--- a/gopls/internal/lsp/cache/snapshot.go
+++ b/gopls/internal/lsp/cache/snapshot.go
@@ -32,6 +32,7 @@
"golang.org/x/sync/errgroup"
"golang.org/x/tools/go/packages"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/bug"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/event/tag"
@@ -39,7 +40,6 @@
"golang.org/x/tools/internal/memoize"
"golang.org/x/tools/internal/packagesinternal"
"golang.org/x/tools/internal/persistent"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/typesinternal"
)
diff --git a/gopls/internal/lsp/cache/view.go b/gopls/internal/lsp/cache/view.go
index af4ab9a..7d3cba3 100644
--- a/gopls/internal/lsp/cache/view.go
+++ b/gopls/internal/lsp/cache/view.go
@@ -27,11 +27,11 @@
"golang.org/x/tools/gopls/internal/lsp/command"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/bug"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/gocommand"
"golang.org/x/tools/internal/imports"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/xcontext"
)
diff --git a/gopls/internal/lsp/cache/view_test.go b/gopls/internal/lsp/cache/view_test.go
index f3851e9..99daff1 100644
--- a/gopls/internal/lsp/cache/view_test.go
+++ b/gopls/internal/lsp/cache/view_test.go
@@ -12,7 +12,7 @@
"golang.org/x/tools/gopls/internal/lsp/fake"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func TestCaseInsensitiveFilesystem(t *testing.T) {
diff --git a/gopls/internal/lsp/cache/workspace.go b/gopls/internal/lsp/cache/workspace.go
index e066c7e..2020718 100644
--- a/gopls/internal/lsp/cache/workspace.go
+++ b/gopls/internal/lsp/cache/workspace.go
@@ -15,9 +15,9 @@
"sync"
"golang.org/x/mod/modfile"
- "golang.org/x/tools/internal/event"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
+ "golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/xcontext"
)
diff --git a/gopls/internal/lsp/cache/workspace_test.go b/gopls/internal/lsp/cache/workspace_test.go
index e6047a9..37e8f2c 100644
--- a/gopls/internal/lsp/cache/workspace_test.go
+++ b/gopls/internal/lsp/cache/workspace_test.go
@@ -14,7 +14,7 @@
"golang.org/x/mod/modfile"
"golang.org/x/tools/gopls/internal/lsp/fake"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
// osFileSource is a fileSource that just reads from the operating system.
diff --git a/gopls/internal/lsp/cmd/call_hierarchy.go b/gopls/internal/lsp/cmd/call_hierarchy.go
index 643b2f7..7736eec 100644
--- a/gopls/internal/lsp/cmd/call_hierarchy.go
+++ b/gopls/internal/lsp/cmd/call_hierarchy.go
@@ -11,7 +11,7 @@
"strings"
"golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/tool"
)
diff --git a/gopls/internal/lsp/cmd/check.go b/gopls/internal/lsp/cmd/check.go
index 9a13669..5e4fe39 100644
--- a/gopls/internal/lsp/cmd/check.go
+++ b/gopls/internal/lsp/cmd/check.go
@@ -9,7 +9,7 @@
"flag"
"fmt"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
// check implements the check verb for gopls.
diff --git a/gopls/internal/lsp/cmd/cmd.go b/gopls/internal/lsp/cmd/cmd.go
index 824382d..38accb6 100644
--- a/gopls/internal/lsp/cmd/cmd.go
+++ b/gopls/internal/lsp/cmd/cmd.go
@@ -28,8 +28,8 @@
"golang.org/x/tools/gopls/internal/lsp/lsprpc"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/jsonrpc2"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/tool"
"golang.org/x/tools/internal/xcontext"
)
diff --git a/gopls/internal/lsp/cmd/definition.go b/gopls/internal/lsp/cmd/definition.go
index 3c4474a..9096e17 100644
--- a/gopls/internal/lsp/cmd/definition.go
+++ b/gopls/internal/lsp/cmd/definition.go
@@ -14,7 +14,7 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/tool"
)
diff --git a/gopls/internal/lsp/cmd/folding_range.go b/gopls/internal/lsp/cmd/folding_range.go
index ee40715..17cead9 100644
--- a/gopls/internal/lsp/cmd/folding_range.go
+++ b/gopls/internal/lsp/cmd/folding_range.go
@@ -10,7 +10,7 @@
"fmt"
"golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/tool"
)
diff --git a/gopls/internal/lsp/cmd/format.go b/gopls/internal/lsp/cmd/format.go
index 56e3905..2f3b682 100644
--- a/gopls/internal/lsp/cmd/format.go
+++ b/gopls/internal/lsp/cmd/format.go
@@ -12,8 +12,8 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/diff"
- "golang.org/x/tools/internal/span"
)
// format implements the format verb for gopls.
diff --git a/gopls/internal/lsp/cmd/highlight.go b/gopls/internal/lsp/cmd/highlight.go
index ace8125..dcbd109 100644
--- a/gopls/internal/lsp/cmd/highlight.go
+++ b/gopls/internal/lsp/cmd/highlight.go
@@ -11,7 +11,7 @@
"sort"
"golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/tool"
)
diff --git a/gopls/internal/lsp/cmd/implementation.go b/gopls/internal/lsp/cmd/implementation.go
index 073a61a..259b725 100644
--- a/gopls/internal/lsp/cmd/implementation.go
+++ b/gopls/internal/lsp/cmd/implementation.go
@@ -11,7 +11,7 @@
"sort"
"golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/tool"
)
diff --git a/gopls/internal/lsp/cmd/imports.go b/gopls/internal/lsp/cmd/imports.go
index 4ee6fce..c041eee 100644
--- a/gopls/internal/lsp/cmd/imports.go
+++ b/gopls/internal/lsp/cmd/imports.go
@@ -12,8 +12,8 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/diff"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/tool"
)
diff --git a/gopls/internal/lsp/cmd/links.go b/gopls/internal/lsp/cmd/links.go
index d63ac21..aec36da 100644
--- a/gopls/internal/lsp/cmd/links.go
+++ b/gopls/internal/lsp/cmd/links.go
@@ -12,7 +12,7 @@
"os"
"golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/tool"
)
diff --git a/gopls/internal/lsp/cmd/prepare_rename.go b/gopls/internal/lsp/cmd/prepare_rename.go
index 7dfac9b..434904b 100644
--- a/gopls/internal/lsp/cmd/prepare_rename.go
+++ b/gopls/internal/lsp/cmd/prepare_rename.go
@@ -11,7 +11,7 @@
"fmt"
"golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/tool"
)
diff --git a/gopls/internal/lsp/cmd/references.go b/gopls/internal/lsp/cmd/references.go
index 13c30bd..bbebc9f 100644
--- a/gopls/internal/lsp/cmd/references.go
+++ b/gopls/internal/lsp/cmd/references.go
@@ -11,7 +11,7 @@
"sort"
"golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/tool"
)
diff --git a/gopls/internal/lsp/cmd/rename.go b/gopls/internal/lsp/cmd/rename.go
index 58fb07d..ceca734 100644
--- a/gopls/internal/lsp/cmd/rename.go
+++ b/gopls/internal/lsp/cmd/rename.go
@@ -15,8 +15,8 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/diff"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/tool"
)
diff --git a/gopls/internal/lsp/cmd/semantictokens.go b/gopls/internal/lsp/cmd/semantictokens.go
index 547b019..f90d49c 100644
--- a/gopls/internal/lsp/cmd/semantictokens.go
+++ b/gopls/internal/lsp/cmd/semantictokens.go
@@ -19,7 +19,7 @@
"golang.org/x/tools/gopls/internal/lsp"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
// generate semantic tokens and interpolate them in the file
diff --git a/gopls/internal/lsp/cmd/signature.go b/gopls/internal/lsp/cmd/signature.go
index 81ec4fe..657d772 100644
--- a/gopls/internal/lsp/cmd/signature.go
+++ b/gopls/internal/lsp/cmd/signature.go
@@ -10,7 +10,7 @@
"fmt"
"golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/tool"
)
diff --git a/gopls/internal/lsp/cmd/suggested_fix.go b/gopls/internal/lsp/cmd/suggested_fix.go
index 9c103de..6d42a67 100644
--- a/gopls/internal/lsp/cmd/suggested_fix.go
+++ b/gopls/internal/lsp/cmd/suggested_fix.go
@@ -12,8 +12,8 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/diff"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/tool"
)
diff --git a/gopls/internal/lsp/cmd/symbols.go b/gopls/internal/lsp/cmd/symbols.go
index 0d6e4db..3ecdff8 100644
--- a/gopls/internal/lsp/cmd/symbols.go
+++ b/gopls/internal/lsp/cmd/symbols.go
@@ -12,7 +12,7 @@
"sort"
"golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/tool"
)
diff --git a/gopls/internal/lsp/cmd/test/call_hierarchy.go b/gopls/internal/lsp/cmd/test/call_hierarchy.go
index be4ebe8..bb8d306 100644
--- a/gopls/internal/lsp/cmd/test/call_hierarchy.go
+++ b/gopls/internal/lsp/cmd/test/call_hierarchy.go
@@ -12,7 +12,7 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/tests"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func (r *runner) CallHierarchy(t *testing.T, spn span.Span, expectedCalls *tests.CallHierarchyResult) {
diff --git a/gopls/internal/lsp/cmd/test/check.go b/gopls/internal/lsp/cmd/test/check.go
index 819863d..ea9747c 100644
--- a/gopls/internal/lsp/cmd/test/check.go
+++ b/gopls/internal/lsp/cmd/test/check.go
@@ -12,7 +12,7 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
"golang.org/x/tools/gopls/internal/lsp/tests"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
// Diagnostics runs the gopls command on a single file, parses its
diff --git a/gopls/internal/lsp/cmd/test/cmdtest.go b/gopls/internal/lsp/cmd/test/cmdtest.go
index e2a3e54..167631a 100644
--- a/gopls/internal/lsp/cmd/test/cmdtest.go
+++ b/gopls/internal/lsp/cmd/test/cmdtest.go
@@ -23,8 +23,8 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
"golang.org/x/tools/gopls/internal/lsp/tests"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/jsonrpc2/servertest"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/tool"
)
diff --git a/gopls/internal/lsp/cmd/test/definition.go b/gopls/internal/lsp/cmd/test/definition.go
index 6241867..ca84e80 100644
--- a/gopls/internal/lsp/cmd/test/definition.go
+++ b/gopls/internal/lsp/cmd/test/definition.go
@@ -11,7 +11,7 @@
"testing"
"golang.org/x/tools/gopls/internal/lsp/tests"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
type godefMode int
diff --git a/gopls/internal/lsp/cmd/test/folding_range.go b/gopls/internal/lsp/cmd/test/folding_range.go
index ac41697..184c01a 100644
--- a/gopls/internal/lsp/cmd/test/folding_range.go
+++ b/gopls/internal/lsp/cmd/test/folding_range.go
@@ -7,7 +7,7 @@
import (
"testing"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func (r *runner) FoldingRanges(t *testing.T, spn span.Span) {
diff --git a/gopls/internal/lsp/cmd/test/format.go b/gopls/internal/lsp/cmd/test/format.go
index 6523e66..368d535 100644
--- a/gopls/internal/lsp/cmd/test/format.go
+++ b/gopls/internal/lsp/cmd/test/format.go
@@ -14,7 +14,7 @@
exec "golang.org/x/sys/execabs"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/testenv"
)
diff --git a/gopls/internal/lsp/cmd/test/highlight.go b/gopls/internal/lsp/cmd/test/highlight.go
index 99e8b2c..cd51b09 100644
--- a/gopls/internal/lsp/cmd/test/highlight.go
+++ b/gopls/internal/lsp/cmd/test/highlight.go
@@ -9,7 +9,7 @@
"fmt"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func (r *runner) Highlight(t *testing.T, spn span.Span, spans []span.Span) {
diff --git a/gopls/internal/lsp/cmd/test/implementation.go b/gopls/internal/lsp/cmd/test/implementation.go
index 1894524..e24584d 100644
--- a/gopls/internal/lsp/cmd/test/implementation.go
+++ b/gopls/internal/lsp/cmd/test/implementation.go
@@ -9,7 +9,7 @@
"sort"
"testing"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func (r *runner) Implementation(t *testing.T, spn span.Span, imps []span.Span) {
diff --git a/gopls/internal/lsp/cmd/test/imports.go b/gopls/internal/lsp/cmd/test/imports.go
index eab4668..5659291 100644
--- a/gopls/internal/lsp/cmd/test/imports.go
+++ b/gopls/internal/lsp/cmd/test/imports.go
@@ -7,8 +7,8 @@
import (
"testing"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/diff"
- "golang.org/x/tools/internal/span"
)
func (r *runner) Import(t *testing.T, spn span.Span) {
diff --git a/gopls/internal/lsp/cmd/test/links.go b/gopls/internal/lsp/cmd/test/links.go
index 52d2a31..a9616ee 100644
--- a/gopls/internal/lsp/cmd/test/links.go
+++ b/gopls/internal/lsp/cmd/test/links.go
@@ -10,7 +10,7 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/tests"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func (r *runner) Link(t *testing.T, uri span.URI, wantLinks []tests.Link) {
diff --git a/gopls/internal/lsp/cmd/test/prepare_rename.go b/gopls/internal/lsp/cmd/test/prepare_rename.go
index 4ae6d1a..c818c01 100644
--- a/gopls/internal/lsp/cmd/test/prepare_rename.go
+++ b/gopls/internal/lsp/cmd/test/prepare_rename.go
@@ -11,7 +11,7 @@
"golang.org/x/tools/gopls/internal/lsp/cmd"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func (r *runner) PrepareRename(t *testing.T, src span.Span, want *source.PrepareItem) {
diff --git a/gopls/internal/lsp/cmd/test/references.go b/gopls/internal/lsp/cmd/test/references.go
index 66d0d06..85c9bc8 100644
--- a/gopls/internal/lsp/cmd/test/references.go
+++ b/gopls/internal/lsp/cmd/test/references.go
@@ -9,7 +9,7 @@
"sort"
"testing"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func (r *runner) References(t *testing.T, spn span.Span, itemList []span.Span) {
diff --git a/gopls/internal/lsp/cmd/test/rename.go b/gopls/internal/lsp/cmd/test/rename.go
index 4748c47..0750d70 100644
--- a/gopls/internal/lsp/cmd/test/rename.go
+++ b/gopls/internal/lsp/cmd/test/rename.go
@@ -8,7 +8,7 @@
"fmt"
"testing"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func (r *runner) Rename(t *testing.T, spn span.Span, newText string) {
diff --git a/gopls/internal/lsp/cmd/test/semanticdriver.go b/gopls/internal/lsp/cmd/test/semanticdriver.go
index 24a1fbf..069dd64 100644
--- a/gopls/internal/lsp/cmd/test/semanticdriver.go
+++ b/gopls/internal/lsp/cmd/test/semanticdriver.go
@@ -8,7 +8,7 @@
"strings"
"testing"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func (r *runner) SemanticTokens(t *testing.T, spn span.Span) {
diff --git a/gopls/internal/lsp/cmd/test/signature.go b/gopls/internal/lsp/cmd/test/signature.go
index 273e634..40669e8 100644
--- a/gopls/internal/lsp/cmd/test/signature.go
+++ b/gopls/internal/lsp/cmd/test/signature.go
@@ -10,7 +10,7 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/tests"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func (r *runner) SignatureHelp(t *testing.T, spn span.Span, want *protocol.SignatureHelp) {
diff --git a/gopls/internal/lsp/cmd/test/suggested_fix.go b/gopls/internal/lsp/cmd/test/suggested_fix.go
index 6d67f28..1e61fe9 100644
--- a/gopls/internal/lsp/cmd/test/suggested_fix.go
+++ b/gopls/internal/lsp/cmd/test/suggested_fix.go
@@ -10,7 +10,7 @@
"golang.org/x/tools/gopls/internal/lsp/tests"
"golang.org/x/tools/gopls/internal/lsp/tests/compare"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func (r *runner) SuggestedFix(t *testing.T, spn span.Span, suggestedFixes []tests.SuggestedFix, expectedActions int) {
diff --git a/gopls/internal/lsp/cmd/test/symbols.go b/gopls/internal/lsp/cmd/test/symbols.go
index 3bd2fc0..aaf3725 100644
--- a/gopls/internal/lsp/cmd/test/symbols.go
+++ b/gopls/internal/lsp/cmd/test/symbols.go
@@ -9,7 +9,7 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/tests/compare"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func (r *runner) Symbols(t *testing.T, uri span.URI, expectedSymbols []protocol.DocumentSymbol) {
diff --git a/gopls/internal/lsp/cmd/test/workspace_symbol.go b/gopls/internal/lsp/cmd/test/workspace_symbol.go
index 4c19d1d..40c2c65 100644
--- a/gopls/internal/lsp/cmd/test/workspace_symbol.go
+++ b/gopls/internal/lsp/cmd/test/workspace_symbol.go
@@ -14,7 +14,7 @@
"golang.org/x/tools/gopls/internal/lsp/source"
"golang.org/x/tools/gopls/internal/lsp/tests"
"golang.org/x/tools/gopls/internal/lsp/tests/compare"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func (r *runner) WorkspaceSymbols(t *testing.T, uri span.URI, query string, typ tests.WorkspaceSymbolsTestType) {
diff --git a/gopls/internal/lsp/code_action.go b/gopls/internal/lsp/code_action.go
index e1f0dc2..1ad0cb4 100644
--- a/gopls/internal/lsp/code_action.go
+++ b/gopls/internal/lsp/code_action.go
@@ -14,10 +14,10 @@
"golang.org/x/tools/gopls/internal/lsp/mod"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/event/tag"
"golang.org/x/tools/internal/imports"
- "golang.org/x/tools/internal/span"
)
func (s *Server) codeAction(ctx context.Context, params *protocol.CodeActionParams) ([]protocol.CodeAction, error) {
diff --git a/gopls/internal/lsp/command.go b/gopls/internal/lsp/command.go
index cb4c698..7f7380e 100644
--- a/gopls/internal/lsp/command.go
+++ b/gopls/internal/lsp/command.go
@@ -25,10 +25,10 @@
"golang.org/x/tools/gopls/internal/lsp/progress"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/gopls/internal/vulncheck"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/gocommand"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/xcontext"
)
diff --git a/gopls/internal/lsp/completion_test.go b/gopls/internal/lsp/completion_test.go
index 98d92b9..23d69ed 100644
--- a/gopls/internal/lsp/completion_test.go
+++ b/gopls/internal/lsp/completion_test.go
@@ -11,7 +11,7 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
"golang.org/x/tools/gopls/internal/lsp/tests"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func (r *runner) Completion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
diff --git a/gopls/internal/lsp/diagnostics.go b/gopls/internal/lsp/diagnostics.go
index 3efcaff..f6f9f79 100644
--- a/gopls/internal/lsp/diagnostics.go
+++ b/gopls/internal/lsp/diagnostics.go
@@ -21,9 +21,9 @@
"golang.org/x/tools/gopls/internal/lsp/source"
"golang.org/x/tools/gopls/internal/lsp/template"
"golang.org/x/tools/gopls/internal/lsp/work"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/event/tag"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/xcontext"
)
diff --git a/gopls/internal/lsp/fake/editor.go b/gopls/internal/lsp/fake/editor.go
index e65db93..d9e6c70 100644
--- a/gopls/internal/lsp/fake/editor.go
+++ b/gopls/internal/lsp/fake/editor.go
@@ -19,9 +19,9 @@
"golang.org/x/tools/gopls/internal/lsp/command"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/jsonrpc2"
"golang.org/x/tools/internal/jsonrpc2/servertest"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/xcontext"
)
diff --git a/gopls/internal/lsp/fake/workdir.go b/gopls/internal/lsp/fake/workdir.go
index 6530260..3f17cb6 100644
--- a/gopls/internal/lsp/fake/workdir.go
+++ b/gopls/internal/lsp/fake/workdir.go
@@ -18,7 +18,7 @@
"time"
"golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
// FileEvent wraps the protocol.FileEvent so that it can be associated with a
diff --git a/gopls/internal/lsp/general.go b/gopls/internal/lsp/general.go
index 01f8242..eee946e 100644
--- a/gopls/internal/lsp/general.go
+++ b/gopls/internal/lsp/general.go
@@ -18,10 +18,10 @@
"golang.org/x/tools/gopls/internal/lsp/debug"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/bug"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/jsonrpc2"
- "golang.org/x/tools/internal/span"
)
func (s *Server) initialize(ctx context.Context, params *protocol.ParamInitialize) (*protocol.InitializeResult, error) {
diff --git a/gopls/internal/lsp/link.go b/gopls/internal/lsp/link.go
index 456f417..929fe28 100644
--- a/gopls/internal/lsp/link.go
+++ b/gopls/internal/lsp/link.go
@@ -17,11 +17,11 @@
"sync"
"golang.org/x/mod/modfile"
- "golang.org/x/tools/internal/event"
- "golang.org/x/tools/internal/event/tag"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
+ "golang.org/x/tools/internal/event"
+ "golang.org/x/tools/internal/event/tag"
)
func (s *Server) documentLink(ctx context.Context, params *protocol.DocumentLinkParams) (links []protocol.DocumentLink, err error) {
diff --git a/gopls/internal/lsp/lsp_test.go b/gopls/internal/lsp/lsp_test.go
index 4cd009d..ce1aac4 100644
--- a/gopls/internal/lsp/lsp_test.go
+++ b/gopls/internal/lsp/lsp_test.go
@@ -23,9 +23,9 @@
"golang.org/x/tools/gopls/internal/lsp/source"
"golang.org/x/tools/gopls/internal/lsp/tests"
"golang.org/x/tools/gopls/internal/lsp/tests/compare"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/bug"
"golang.org/x/tools/internal/event"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/testenv"
)
diff --git a/gopls/internal/lsp/mod/mod_test.go b/gopls/internal/lsp/mod/mod_test.go
index 75c1666..767ec44 100644
--- a/gopls/internal/lsp/mod/mod_test.go
+++ b/gopls/internal/lsp/mod/mod_test.go
@@ -13,7 +13,7 @@
"golang.org/x/tools/gopls/internal/lsp/cache"
"golang.org/x/tools/gopls/internal/lsp/source"
"golang.org/x/tools/gopls/internal/lsp/tests"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/testenv"
)
diff --git a/gopls/internal/lsp/protocol/span.go b/gopls/internal/lsp/protocol/span.go
index cbf57a9..bfa2f81 100644
--- a/gopls/internal/lsp/protocol/span.go
+++ b/gopls/internal/lsp/protocol/span.go
@@ -12,7 +12,7 @@
"go/token"
"unicode/utf8"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
// A ColumnMapper maps between UTF-8 oriented positions (e.g. token.Pos,
diff --git a/gopls/internal/lsp/rename.go b/gopls/internal/lsp/rename.go
index 2d9ad69..e9bb2d4 100644
--- a/gopls/internal/lsp/rename.go
+++ b/gopls/internal/lsp/rename.go
@@ -10,7 +10,7 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func (s *Server) rename(ctx context.Context, params *protocol.RenameParams) (*protocol.WorkspaceEdit, error) {
diff --git a/gopls/internal/lsp/server.go b/gopls/internal/lsp/server.go
index 0d257b2..693afae 100644
--- a/gopls/internal/lsp/server.go
+++ b/gopls/internal/lsp/server.go
@@ -14,8 +14,8 @@
"golang.org/x/tools/gopls/internal/lsp/progress"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/jsonrpc2"
- "golang.org/x/tools/internal/span"
)
const concurrentAnalyses = 1
diff --git a/gopls/internal/lsp/source/call_hierarchy.go b/gopls/internal/lsp/source/call_hierarchy.go
index 298c712..1097d62 100644
--- a/gopls/internal/lsp/source/call_hierarchy.go
+++ b/gopls/internal/lsp/source/call_hierarchy.go
@@ -14,10 +14,10 @@
"path/filepath"
"golang.org/x/tools/go/ast/astutil"
+ "golang.org/x/tools/gopls/internal/lsp/protocol"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/event/tag"
- "golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
)
// PrepareCallHierarchy returns an array of CallHierarchyItem for a file and the position within the file.
diff --git a/gopls/internal/lsp/source/code_lens.go b/gopls/internal/lsp/source/code_lens.go
index 6f1d720..83ffcc2 100644
--- a/gopls/internal/lsp/source/code_lens.go
+++ b/gopls/internal/lsp/source/code_lens.go
@@ -15,7 +15,7 @@
"golang.org/x/tools/gopls/internal/lsp/command"
"golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
type LensFunc func(context.Context, Snapshot, FileHandle) ([]protocol.CodeLens, error)
diff --git a/gopls/internal/lsp/source/completion/completion.go b/gopls/internal/lsp/source/completion/completion.go
index 2ffd9bf..1e5dd1c 100644
--- a/gopls/internal/lsp/source/completion/completion.go
+++ b/gopls/internal/lsp/source/completion/completion.go
@@ -23,13 +23,13 @@
"unicode"
"golang.org/x/tools/go/ast/astutil"
- "golang.org/x/tools/internal/event"
- "golang.org/x/tools/internal/imports"
- "golang.org/x/tools/internal/fuzzy"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/snippet"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
+ "golang.org/x/tools/internal/event"
+ "golang.org/x/tools/internal/fuzzy"
+ "golang.org/x/tools/internal/imports"
"golang.org/x/tools/internal/typeparams"
)
diff --git a/gopls/internal/lsp/source/completion/definition.go b/gopls/internal/lsp/source/completion/definition.go
index e61a9fa..fe41c55 100644
--- a/gopls/internal/lsp/source/completion/definition.go
+++ b/gopls/internal/lsp/source/completion/definition.go
@@ -15,7 +15,7 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/snippet"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
// some definitions can be completed
diff --git a/gopls/internal/lsp/source/completion/format.go b/gopls/internal/lsp/source/completion/format.go
index 4a76eef..c2693dc 100644
--- a/gopls/internal/lsp/source/completion/format.go
+++ b/gopls/internal/lsp/source/completion/format.go
@@ -16,10 +16,10 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/snippet"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/event/tag"
"golang.org/x/tools/internal/imports"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/typeparams"
)
diff --git a/gopls/internal/lsp/source/completion/package.go b/gopls/internal/lsp/source/completion/package.go
index 1f3649b..b7fad0f 100644
--- a/gopls/internal/lsp/source/completion/package.go
+++ b/gopls/internal/lsp/source/completion/package.go
@@ -18,12 +18,12 @@
"strings"
"unicode"
- "golang.org/x/tools/internal/bug"
- "golang.org/x/tools/internal/fuzzy"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/safetoken"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
+ "golang.org/x/tools/internal/bug"
+ "golang.org/x/tools/internal/fuzzy"
)
// packageClauseCompletions offers completions for a package declaration when
diff --git a/gopls/internal/lsp/source/diagnostics.go b/gopls/internal/lsp/source/diagnostics.go
index faf4919..c292f25 100644
--- a/gopls/internal/lsp/source/diagnostics.go
+++ b/gopls/internal/lsp/source/diagnostics.go
@@ -8,7 +8,7 @@
"context"
"golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
type SuggestedFix struct {
diff --git a/gopls/internal/lsp/source/extract.go b/gopls/internal/lsp/source/extract.go
index 8e6f77d..488305a 100644
--- a/gopls/internal/lsp/source/extract.go
+++ b/gopls/internal/lsp/source/extract.go
@@ -19,9 +19,9 @@
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/ast/astutil"
"golang.org/x/tools/gopls/internal/lsp/safetoken"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/analysisinternal"
"golang.org/x/tools/internal/bug"
- "golang.org/x/tools/internal/span"
)
func extractVariable(fset *token.FileSet, rng span.Range, src []byte, file *ast.File, _ *types.Package, info *types.Info) (*analysis.SuggestedFix, error) {
diff --git a/gopls/internal/lsp/source/fix.go b/gopls/internal/lsp/source/fix.go
index bce2536..1ce6d75 100644
--- a/gopls/internal/lsp/source/fix.go
+++ b/gopls/internal/lsp/source/fix.go
@@ -14,9 +14,9 @@
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/gopls/internal/lsp/analysis/fillstruct"
"golang.org/x/tools/gopls/internal/lsp/analysis/undeclaredname"
- "golang.org/x/tools/internal/bug"
"golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
+ "golang.org/x/tools/internal/bug"
)
type (
diff --git a/gopls/internal/lsp/source/gc_annotations.go b/gopls/internal/lsp/source/gc_annotations.go
index 111cd4f..ab0fd60 100644
--- a/gopls/internal/lsp/source/gc_annotations.go
+++ b/gopls/internal/lsp/source/gc_annotations.go
@@ -14,9 +14,9 @@
"path/filepath"
"strings"
- "golang.org/x/tools/internal/gocommand"
"golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
+ "golang.org/x/tools/internal/gocommand"
)
type Annotation string
diff --git a/gopls/internal/lsp/source/identifier.go b/gopls/internal/lsp/source/identifier.go
index 91c7b6b..7bf1e12 100644
--- a/gopls/internal/lsp/source/identifier.go
+++ b/gopls/internal/lsp/source/identifier.go
@@ -17,9 +17,9 @@
"golang.org/x/tools/go/ast/astutil"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/safetoken"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/bug"
"golang.org/x/tools/internal/event"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/typeparams"
)
diff --git a/gopls/internal/lsp/source/implementation.go b/gopls/internal/lsp/source/implementation.go
index 3533c92..e2c60bb 100644
--- a/gopls/internal/lsp/source/implementation.go
+++ b/gopls/internal/lsp/source/implementation.go
@@ -15,8 +15,8 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/safetoken"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/event"
- "golang.org/x/tools/internal/span"
)
func Implementation(ctx context.Context, snapshot Snapshot, f FileHandle, pp protocol.Position) ([]protocol.Location, error) {
diff --git a/gopls/internal/lsp/source/references.go b/gopls/internal/lsp/source/references.go
index 714a3cb..9a10b38 100644
--- a/gopls/internal/lsp/source/references.go
+++ b/gopls/internal/lsp/source/references.go
@@ -16,9 +16,9 @@
"strconv"
"golang.org/x/tools/gopls/internal/lsp/protocol"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/bug"
"golang.org/x/tools/internal/event"
- "golang.org/x/tools/internal/span"
)
// ReferenceInfo holds information about reference to an identifier in Go source.
diff --git a/gopls/internal/lsp/source/rename.go b/gopls/internal/lsp/source/rename.go
index c5af1ca..495791f 100644
--- a/gopls/internal/lsp/source/rename.go
+++ b/gopls/internal/lsp/source/rename.go
@@ -20,9 +20,9 @@
"golang.org/x/tools/go/types/typeutil"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/safetoken"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/diff"
"golang.org/x/tools/internal/event"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/refactor/satisfy"
)
diff --git a/gopls/internal/lsp/source/source_test.go b/gopls/internal/lsp/source/source_test.go
index d81bdb7..8c49306 100644
--- a/gopls/internal/lsp/source/source_test.go
+++ b/gopls/internal/lsp/source/source_test.go
@@ -21,9 +21,9 @@
"golang.org/x/tools/gopls/internal/lsp/source/completion"
"golang.org/x/tools/gopls/internal/lsp/tests"
"golang.org/x/tools/gopls/internal/lsp/tests/compare"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/bug"
"golang.org/x/tools/internal/fuzzy"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/testenv"
)
diff --git a/gopls/internal/lsp/source/stub.go b/gopls/internal/lsp/source/stub.go
index 3aab0b4..2d00ea5 100644
--- a/gopls/internal/lsp/source/stub.go
+++ b/gopls/internal/lsp/source/stub.go
@@ -20,7 +20,7 @@
"golang.org/x/tools/gopls/internal/lsp/analysis/stubmethods"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/safetoken"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/typeparams"
)
diff --git a/gopls/internal/lsp/source/util.go b/gopls/internal/lsp/source/util.go
index 9939ca0..b06992e 100644
--- a/gopls/internal/lsp/source/util.go
+++ b/gopls/internal/lsp/source/util.go
@@ -19,8 +19,8 @@
"golang.org/x/mod/modfile"
"golang.org/x/tools/gopls/internal/lsp/protocol"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/bug"
- "golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/typeparams"
)
diff --git a/gopls/internal/lsp/source/util_test.go b/gopls/internal/lsp/source/util_test.go
index e0b2a29..60128e2 100644
--- a/gopls/internal/lsp/source/util_test.go
+++ b/gopls/internal/lsp/source/util_test.go
@@ -11,7 +11,7 @@
"testing"
"golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func TestMappedRangeAdjustment(t *testing.T) {
diff --git a/gopls/internal/lsp/source/view.go b/gopls/internal/lsp/source/view.go
index fa9d6a9..e679839 100644
--- a/gopls/internal/lsp/source/view.go
+++ b/gopls/internal/lsp/source/view.go
@@ -23,9 +23,9 @@
"golang.org/x/tools/go/packages"
"golang.org/x/tools/gopls/internal/lsp/command"
"golang.org/x/tools/gopls/internal/lsp/protocol"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/gocommand"
"golang.org/x/tools/internal/imports"
- "golang.org/x/tools/internal/span"
)
// Snapshot represents the current state for the given view.
diff --git a/gopls/internal/lsp/source/workspace_symbol.go b/gopls/internal/lsp/source/workspace_symbol.go
index 8fe2388..dabbeb3 100644
--- a/gopls/internal/lsp/source/workspace_symbol.go
+++ b/gopls/internal/lsp/source/workspace_symbol.go
@@ -16,10 +16,10 @@
"strings"
"unicode"
+ "golang.org/x/tools/gopls/internal/lsp/protocol"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/fuzzy"
- "golang.org/x/tools/gopls/internal/lsp/protocol"
- "golang.org/x/tools/internal/span"
)
// Symbol holds a precomputed symbol value. Note: we avoid using the
diff --git a/gopls/internal/lsp/template/implementations.go b/gopls/internal/lsp/template/implementations.go
index 3d14f6b..6c90b68 100644
--- a/gopls/internal/lsp/template/implementations.go
+++ b/gopls/internal/lsp/template/implementations.go
@@ -13,7 +13,7 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
// line number (1-based) and message
diff --git a/gopls/internal/lsp/template/parse.go b/gopls/internal/lsp/template/parse.go
index 679bd4d..06b7568 100644
--- a/gopls/internal/lsp/template/parse.go
+++ b/gopls/internal/lsp/template/parse.go
@@ -26,8 +26,8 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/event"
- "golang.org/x/tools/internal/span"
)
var (
diff --git a/gopls/internal/lsp/tests/tests.go b/gopls/internal/lsp/tests/tests.go
index 2b8e830..cab96e0 100644
--- a/gopls/internal/lsp/tests/tests.go
+++ b/gopls/internal/lsp/tests/tests.go
@@ -32,7 +32,7 @@
"golang.org/x/tools/gopls/internal/lsp/source"
"golang.org/x/tools/gopls/internal/lsp/source/completion"
"golang.org/x/tools/gopls/internal/lsp/tests/compare"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/testenv"
"golang.org/x/tools/internal/typeparams"
"golang.org/x/tools/txtar"
diff --git a/gopls/internal/lsp/tests/util.go b/gopls/internal/lsp/tests/util.go
index ce5ab5b..2951f03 100644
--- a/gopls/internal/lsp/tests/util.go
+++ b/gopls/internal/lsp/tests/util.go
@@ -20,8 +20,8 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
"golang.org/x/tools/gopls/internal/lsp/source/completion"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/diff"
- "golang.org/x/tools/internal/span"
)
// DiffLinks takes the links we got and checks if they are located within the source or a Note.
diff --git a/gopls/internal/lsp/text_synchronization.go b/gopls/internal/lsp/text_synchronization.go
index c360e1e..9687528 100644
--- a/gopls/internal/lsp/text_synchronization.go
+++ b/gopls/internal/lsp/text_synchronization.go
@@ -12,11 +12,11 @@
"path/filepath"
"time"
- "golang.org/x/tools/internal/event"
- "golang.org/x/tools/internal/jsonrpc2"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
+ "golang.org/x/tools/internal/event"
+ "golang.org/x/tools/internal/jsonrpc2"
"golang.org/x/tools/internal/xcontext"
)
diff --git a/gopls/internal/lsp/work/diagnostics.go b/gopls/internal/lsp/work/diagnostics.go
index 72c06e0..5d3a328 100644
--- a/gopls/internal/lsp/work/diagnostics.go
+++ b/gopls/internal/lsp/work/diagnostics.go
@@ -13,9 +13,9 @@
"golang.org/x/mod/modfile"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/event/tag"
- "golang.org/x/tools/internal/span"
)
func Diagnostics(ctx context.Context, snapshot source.Snapshot) (map[source.VersionedFileIdentity][]*source.Diagnostic, error) {
diff --git a/gopls/internal/lsp/workspace.go b/gopls/internal/lsp/workspace.go
index 79f144b..0e780d2 100644
--- a/gopls/internal/lsp/workspace.go
+++ b/gopls/internal/lsp/workspace.go
@@ -10,7 +10,7 @@
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
func (s *Server) didChangeWorkspaceFolders(ctx context.Context, params *protocol.DidChangeWorkspaceFoldersParams) error {
diff --git a/gopls/internal/span/parse.go b/gopls/internal/span/parse.go
new file mode 100644
index 0000000..c4cec16
--- /dev/null
+++ b/gopls/internal/span/parse.go
@@ -0,0 +1,112 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package span
+
+import (
+ "path/filepath"
+ "strconv"
+ "strings"
+ "unicode/utf8"
+)
+
+// Parse returns the location represented by the input.
+// Only file paths are accepted, not URIs.
+// The returned span will be normalized, and thus if printed may produce a
+// different string.
+func Parse(input string) Span {
+ return ParseInDir(input, ".")
+}
+
+// ParseInDir is like Parse, but interprets paths relative to wd.
+func ParseInDir(input, wd string) Span {
+ uri := func(path string) URI {
+ if !filepath.IsAbs(path) {
+ path = filepath.Join(wd, path)
+ }
+ return URIFromPath(path)
+ }
+ // :0:0#0-0:0#0
+ valid := input
+ var hold, offset int
+ hadCol := false
+ suf := rstripSuffix(input)
+ if suf.sep == "#" {
+ offset = suf.num
+ suf = rstripSuffix(suf.remains)
+ }
+ if suf.sep == ":" {
+ valid = suf.remains
+ hold = suf.num
+ hadCol = true
+ suf = rstripSuffix(suf.remains)
+ }
+ switch {
+ case suf.sep == ":":
+ return New(uri(suf.remains), NewPoint(suf.num, hold, offset), Point{})
+ case suf.sep == "-":
+ // we have a span, fall out of the case to continue
+ default:
+ // separator not valid, rewind to either the : or the start
+ return New(uri(valid), NewPoint(hold, 0, offset), Point{})
+ }
+ // only the span form can get here
+ // at this point we still don't know what the numbers we have mean
+ // if have not yet seen a : then we might have either a line or a column depending
+ // on whether start has a column or not
+ // we build an end point and will fix it later if needed
+ end := NewPoint(suf.num, hold, offset)
+ hold, offset = 0, 0
+ suf = rstripSuffix(suf.remains)
+ if suf.sep == "#" {
+ offset = suf.num
+ suf = rstripSuffix(suf.remains)
+ }
+ if suf.sep != ":" {
+ // turns out we don't have a span after all, rewind
+ return New(uri(valid), end, Point{})
+ }
+ valid = suf.remains
+ hold = suf.num
+ suf = rstripSuffix(suf.remains)
+ if suf.sep != ":" {
+ // line#offset only
+ return New(uri(valid), NewPoint(hold, 0, offset), end)
+ }
+ // we have a column, so if end only had one number, it is also the column
+ if !hadCol {
+ end = NewPoint(suf.num, end.v.Line, end.v.Offset)
+ }
+ return New(uri(suf.remains), NewPoint(suf.num, hold, offset), end)
+}
+
+type suffix struct {
+ remains string
+ sep string
+ num int
+}
+
+func rstripSuffix(input string) suffix {
+ if len(input) == 0 {
+ return suffix{"", "", -1}
+ }
+ remains := input
+ num := -1
+ // first see if we have a number at the end
+ last := strings.LastIndexFunc(remains, func(r rune) bool { return r < '0' || r > '9' })
+ if last >= 0 && last < len(remains)-1 {
+ number, err := strconv.ParseInt(remains[last+1:], 10, 64)
+ if err == nil {
+ num = int(number)
+ remains = remains[:last+1]
+ }
+ }
+ // now see if we have a trailing separator
+ r, w := utf8.DecodeLastRuneInString(remains)
+ if r != ':' && r != '#' && r == '#' {
+ return suffix{input, "", -1}
+ }
+ remains = remains[:len(remains)-w]
+ return suffix{remains, string(r), num}
+}
diff --git a/gopls/internal/span/span.go b/gopls/internal/span/span.go
new file mode 100644
index 0000000..5b8d31e
--- /dev/null
+++ b/gopls/internal/span/span.go
@@ -0,0 +1,287 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package span contains support for representing with positions and ranges in
+// text files.
+package span
+
+import (
+ "encoding/json"
+ "fmt"
+ "go/token"
+ "path"
+)
+
+// Span represents a source code range in standardized form.
+type Span struct {
+ v span
+}
+
+// Point represents a single point within a file.
+// In general this should only be used as part of a Span, as on its own it
+// does not carry enough information.
+type Point struct {
+ v point
+}
+
+type span struct {
+ URI URI `json:"uri"`
+ Start point `json:"start"`
+ End point `json:"end"`
+}
+
+type point struct {
+ Line int `json:"line"`
+ Column int `json:"column"`
+ Offset int `json:"offset"`
+}
+
+// Invalid is a span that reports false from IsValid
+var Invalid = Span{v: span{Start: invalidPoint.v, End: invalidPoint.v}}
+
+var invalidPoint = Point{v: point{Line: 0, Column: 0, Offset: -1}}
+
+func New(uri URI, start, end Point) Span {
+ s := Span{v: span{URI: uri, Start: start.v, End: end.v}}
+ s.v.clean()
+ return s
+}
+
+func NewPoint(line, col, offset int) Point {
+ p := Point{v: point{Line: line, Column: col, Offset: offset}}
+ p.v.clean()
+ return p
+}
+
+func Compare(a, b Span) int {
+ if r := CompareURI(a.URI(), b.URI()); r != 0 {
+ return r
+ }
+ if r := comparePoint(a.v.Start, b.v.Start); r != 0 {
+ return r
+ }
+ return comparePoint(a.v.End, b.v.End)
+}
+
+func ComparePoint(a, b Point) int {
+ return comparePoint(a.v, b.v)
+}
+
+func comparePoint(a, b point) int {
+ if !a.hasPosition() {
+ if a.Offset < b.Offset {
+ return -1
+ }
+ if a.Offset > b.Offset {
+ return 1
+ }
+ return 0
+ }
+ if a.Line < b.Line {
+ return -1
+ }
+ if a.Line > b.Line {
+ return 1
+ }
+ if a.Column < b.Column {
+ return -1
+ }
+ if a.Column > b.Column {
+ return 1
+ }
+ return 0
+}
+
+func (s Span) HasPosition() bool { return s.v.Start.hasPosition() }
+func (s Span) HasOffset() bool { return s.v.Start.hasOffset() }
+func (s Span) IsValid() bool { return s.v.Start.isValid() }
+func (s Span) IsPoint() bool { return s.v.Start == s.v.End }
+func (s Span) URI() URI { return s.v.URI }
+func (s Span) Start() Point { return Point{s.v.Start} }
+func (s Span) End() Point { return Point{s.v.End} }
+func (s *Span) MarshalJSON() ([]byte, error) { return json.Marshal(&s.v) }
+func (s *Span) UnmarshalJSON(b []byte) error { return json.Unmarshal(b, &s.v) }
+
+func (p Point) HasPosition() bool { return p.v.hasPosition() }
+func (p Point) HasOffset() bool { return p.v.hasOffset() }
+func (p Point) IsValid() bool { return p.v.isValid() }
+func (p *Point) MarshalJSON() ([]byte, error) { return json.Marshal(&p.v) }
+func (p *Point) UnmarshalJSON(b []byte) error { return json.Unmarshal(b, &p.v) }
+func (p Point) Line() int {
+ if !p.v.hasPosition() {
+ panic(fmt.Errorf("position not set in %v", p.v))
+ }
+ return p.v.Line
+}
+func (p Point) Column() int {
+ if !p.v.hasPosition() {
+ panic(fmt.Errorf("position not set in %v", p.v))
+ }
+ return p.v.Column
+}
+func (p Point) Offset() int {
+ if !p.v.hasOffset() {
+ panic(fmt.Errorf("offset not set in %v", p.v))
+ }
+ return p.v.Offset
+}
+
+func (p point) hasPosition() bool { return p.Line > 0 }
+func (p point) hasOffset() bool { return p.Offset >= 0 }
+func (p point) isValid() bool { return p.hasPosition() || p.hasOffset() }
+func (p point) isZero() bool {
+ return (p.Line == 1 && p.Column == 1) || (!p.hasPosition() && p.Offset == 0)
+}
+
+func (s *span) clean() {
+ //this presumes the points are already clean
+ if !s.End.isValid() || (s.End == point{}) {
+ s.End = s.Start
+ }
+}
+
+func (p *point) clean() {
+ if p.Line < 0 {
+ p.Line = 0
+ }
+ if p.Column <= 0 {
+ if p.Line > 0 {
+ p.Column = 1
+ } else {
+ p.Column = 0
+ }
+ }
+ if p.Offset == 0 && (p.Line > 1 || p.Column > 1) {
+ p.Offset = -1
+ }
+}
+
+// Format implements fmt.Formatter to print the Location in a standard form.
+// The format produced is one that can be read back in using Parse.
+func (s Span) Format(f fmt.State, c rune) {
+ fullForm := f.Flag('+')
+ preferOffset := f.Flag('#')
+ // we should always have a uri, simplify if it is file format
+ //TODO: make sure the end of the uri is unambiguous
+ uri := string(s.v.URI)
+ if c == 'f' {
+ uri = path.Base(uri)
+ } else if !fullForm {
+ uri = s.v.URI.Filename()
+ }
+ fmt.Fprint(f, uri)
+ if !s.IsValid() || (!fullForm && s.v.Start.isZero() && s.v.End.isZero()) {
+ return
+ }
+ // see which bits of start to write
+ printOffset := s.HasOffset() && (fullForm || preferOffset || !s.HasPosition())
+ printLine := s.HasPosition() && (fullForm || !printOffset)
+ printColumn := printLine && (fullForm || (s.v.Start.Column > 1 || s.v.End.Column > 1))
+ fmt.Fprint(f, ":")
+ if printLine {
+ fmt.Fprintf(f, "%d", s.v.Start.Line)
+ }
+ if printColumn {
+ fmt.Fprintf(f, ":%d", s.v.Start.Column)
+ }
+ if printOffset {
+ fmt.Fprintf(f, "#%d", s.v.Start.Offset)
+ }
+ // start is written, do we need end?
+ if s.IsPoint() {
+ return
+ }
+ // we don't print the line if it did not change
+ printLine = fullForm || (printLine && s.v.End.Line > s.v.Start.Line)
+ fmt.Fprint(f, "-")
+ if printLine {
+ fmt.Fprintf(f, "%d", s.v.End.Line)
+ }
+ if printColumn {
+ if printLine {
+ fmt.Fprint(f, ":")
+ }
+ fmt.Fprintf(f, "%d", s.v.End.Column)
+ }
+ if printOffset {
+ fmt.Fprintf(f, "#%d", s.v.End.Offset)
+ }
+}
+
+func (s Span) WithPosition(tf *token.File) (Span, error) {
+ if err := s.update(tf, true, false); err != nil {
+ return Span{}, err
+ }
+ return s, nil
+}
+
+func (s Span) WithOffset(tf *token.File) (Span, error) {
+ if err := s.update(tf, false, true); err != nil {
+ return Span{}, err
+ }
+ return s, nil
+}
+
+func (s Span) WithAll(tf *token.File) (Span, error) {
+ if err := s.update(tf, true, true); err != nil {
+ return Span{}, err
+ }
+ return s, nil
+}
+
+func (s *Span) update(tf *token.File, withPos, withOffset bool) error {
+ if !s.IsValid() {
+ return fmt.Errorf("cannot add information to an invalid span")
+ }
+ if withPos && !s.HasPosition() {
+ if err := s.v.Start.updatePosition(tf); err != nil {
+ return err
+ }
+ if s.v.End.Offset == s.v.Start.Offset {
+ s.v.End = s.v.Start
+ } else if err := s.v.End.updatePosition(tf); err != nil {
+ return err
+ }
+ }
+ if withOffset && (!s.HasOffset() || (s.v.End.hasPosition() && !s.v.End.hasOffset())) {
+ if err := s.v.Start.updateOffset(tf); err != nil {
+ return err
+ }
+ if s.v.End.Line == s.v.Start.Line && s.v.End.Column == s.v.Start.Column {
+ s.v.End.Offset = s.v.Start.Offset
+ } else if err := s.v.End.updateOffset(tf); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (p *point) updatePosition(tf *token.File) error {
+ line, col, err := ToPosition(tf, p.Offset)
+ if err != nil {
+ return err
+ }
+ p.Line = line
+ p.Column = col
+ return nil
+}
+
+func (p *point) updateOffset(tf *token.File) error {
+ offset, err := ToOffset(tf, p.Line, p.Column)
+ if err != nil {
+ return err
+ }
+ p.Offset = offset
+ return nil
+}
+
+// SetRange implements packagestest.rangeSetter, allowing
+// gopls' test suites to use Spans instead of Range in parameters.
+func (span *Span) SetRange(file *token.File, start, end token.Pos) {
+ point := func(pos token.Pos) Point {
+ posn := file.Position(pos)
+ return NewPoint(posn.Line, posn.Column, posn.Offset)
+ }
+ *span = New(URIFromPath(file.Name()), point(start), point(end))
+}
diff --git a/gopls/internal/span/span_test.go b/gopls/internal/span/span_test.go
new file mode 100644
index 0000000..63c0752
--- /dev/null
+++ b/gopls/internal/span/span_test.go
@@ -0,0 +1,74 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package span_test
+
+import (
+ "fmt"
+ "go/token"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "golang.org/x/tools/gopls/internal/span"
+)
+
+var (
+ tests = [][]string{
+ {"C:/file_a", "C:/file_a", "file:///C:/file_a:1:1#0"},
+ {"C:/file_b:1:2", "C:/file_b:#1", "file:///C:/file_b:1:2#1"},
+ {"C:/file_c:1000", "C:/file_c:#9990", "file:///C:/file_c:1000:1#9990"},
+ {"C:/file_d:14:9", "C:/file_d:#138", "file:///C:/file_d:14:9#138"},
+ {"C:/file_e:1:2-7", "C:/file_e:#1-#6", "file:///C:/file_e:1:2#1-1:7#6"},
+ {"C:/file_f:500-502", "C:/file_f:#4990-#5010", "file:///C:/file_f:500:1#4990-502:1#5010"},
+ {"C:/file_g:3:7-8", "C:/file_g:#26-#27", "file:///C:/file_g:3:7#26-3:8#27"},
+ {"C:/file_h:3:7-4:8", "C:/file_h:#26-#37", "file:///C:/file_h:3:7#26-4:8#37"},
+ }
+)
+
+func TestFormat(t *testing.T) {
+ converter := lines(10)
+ for _, test := range tests {
+ for ti, text := range test[:2] {
+ spn := span.Parse(text)
+ if ti <= 1 {
+ // we can check %v produces the same as the input
+ expect := toPath(test[ti])
+ if got := fmt.Sprintf("%v", spn); got != expect {
+ t.Errorf("printing %q got %q expected %q", text, got, expect)
+ }
+ }
+ complete, err := spn.WithAll(converter)
+ if err != nil {
+ t.Error(err)
+ }
+ for fi, format := range []string{"%v", "%#v", "%+v"} {
+ expect := toPath(test[fi])
+ if got := fmt.Sprintf(format, complete); got != expect {
+ t.Errorf("printing completed %q as %q got %q expected %q [%+v]", text, format, got, expect, spn)
+ }
+ }
+ }
+ }
+}
+
+func toPath(value string) string {
+ if strings.HasPrefix(value, "file://") {
+ return value
+ }
+ return filepath.FromSlash(value)
+}
+
+// lines creates a new tokenConverter for a file with 1000 lines, each width
+// bytes wide.
+func lines(width int) *token.File {
+ fset := token.NewFileSet()
+ f := fset.AddFile("", -1, 1000*width)
+ var lines []int
+ for i := 0; i < 1000; i++ {
+ lines = append(lines, i*width)
+ }
+ f.SetLines(lines)
+ return f
+}
diff --git a/gopls/internal/span/token.go b/gopls/internal/span/token.go
new file mode 100644
index 0000000..da4dc22
--- /dev/null
+++ b/gopls/internal/span/token.go
@@ -0,0 +1,227 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package span
+
+import (
+ "fmt"
+ "go/token"
+
+ "golang.org/x/tools/internal/bug"
+)
+
+// Range represents a source code range in token.Pos form.
+// It also carries the token.File that produced the positions, so that it is
+// self contained.
+type Range struct {
+ TokFile *token.File // non-nil
+ Start, End token.Pos // both IsValid()
+}
+
+// NewRange creates a new Range from a token.File and two valid positions within it.
+//
+// (If you only have a token.FileSet, use file = fset.File(start). But
+// most callers know exactly which token.File they're dealing with and
+// should pass it explicitly. Not only does this save a lookup, but it
+// brings us a step closer to eliminating the global FileSet.)
+func NewRange(file *token.File, start, end token.Pos) Range {
+ if file == nil {
+ panic("nil *token.File")
+ }
+ if !start.IsValid() {
+ panic("invalid start token.Pos")
+ }
+ if !end.IsValid() {
+ panic("invalid end token.Pos")
+ }
+
+ // TODO(adonovan): ideally we would make this stronger assertion:
+ //
+ // // Assert that file is non-nil and contains start and end.
+ // _ = file.Offset(start)
+ // _ = file.Offset(end)
+ //
+ // but some callers (e.g. packageCompletionSurrounding,
+ // posToMappedRange) don't ensure this precondition.
+
+ return Range{
+ TokFile: file,
+ Start: start,
+ End: end,
+ }
+}
+
+// NewTokenFile returns a token.File for the given file content.
+func NewTokenFile(filename string, content []byte) *token.File {
+ fset := token.NewFileSet()
+ f := fset.AddFile(filename, -1, len(content))
+ f.SetLinesForContent(content)
+ return f
+}
+
+// IsPoint returns true if the range represents a single point.
+func (r Range) IsPoint() bool {
+ return r.Start == r.End
+}
+
+// Span converts a Range to a Span that represents the Range.
+// It will fill in all the members of the Span, calculating the line and column
+// information.
+func (r Range) Span() (Span, error) {
+ return FileSpan(r.TokFile, r.TokFile, r.Start, r.End)
+}
+
+// FileSpan returns a span within the file referenced by start and end, using a
+// token.File to translate between offsets and positions.
+//
+// The start and end position must be contained within posFile, though due to
+// line directives they may reference positions in another file. If srcFile is
+// provided, it is used to map the line:column positions referenced by start
+// and end to offsets in the corresponding file.
+//
+// TODO(adonovan): clarify whether it is valid to pass posFile==srcFile when
+// //line directives are in use. If so, fix this function; if not, fix Range.Span.
+func FileSpan(posFile, srcFile *token.File, start, end token.Pos) (Span, error) {
+ if !start.IsValid() {
+ return Span{}, fmt.Errorf("start pos is not valid")
+ }
+ if posFile == nil {
+ return Span{}, bug.Errorf("missing file association") // should never get here with a nil file
+ }
+ var s Span
+ var err error
+ var startFilename string
+ startFilename, s.v.Start.Line, s.v.Start.Column, err = position(posFile, start)
+ if err != nil {
+ return Span{}, err
+ }
+ s.v.URI = URIFromPath(startFilename)
+ if end.IsValid() {
+ var endFilename string
+ endFilename, s.v.End.Line, s.v.End.Column, err = position(posFile, end)
+ if err != nil {
+ return Span{}, err
+ }
+ // In the presence of line directives, a single File can have sections from
+ // multiple file names.
+ if endFilename != startFilename {
+ return Span{}, fmt.Errorf("span begins in file %q but ends in %q", startFilename, endFilename)
+ }
+ }
+ s.v.Start.clean()
+ s.v.End.clean()
+ s.v.clean()
+ tf := posFile
+ if srcFile != nil {
+ tf = srcFile
+ }
+ if startFilename != tf.Name() {
+ // 'start' identifies a position specified by a //line directive
+ // in a file other than the one containing the directive.
+ // (Debugging support for https://github.com/golang/go/issues/54655.)
+ //
+ // This used to be a bug.Errorf, but that was unsound because
+ // Range.Span passes this function the same TokFile argument twice,
+ // which is never going to pass this test for a file containing
+ // a //line directive.
+ // TODO(adonovan): decide where the bug.Errorf really belongs.
+ return Span{}, fmt.Errorf("must supply Converter for file %q (tf.Name() = %q)", startFilename, tf.Name())
+ }
+ return s.WithOffset(tf)
+}
+
+func position(tf *token.File, pos token.Pos) (string, int, int, error) {
+ off, err := offset(tf, pos)
+ if err != nil {
+ return "", 0, 0, err
+ }
+ return positionFromOffset(tf, off)
+}
+
+func positionFromOffset(tf *token.File, offset int) (string, int, int, error) {
+ if offset > tf.Size() {
+ return "", 0, 0, fmt.Errorf("offset %d is beyond EOF (%d) in file %s", offset, tf.Size(), tf.Name())
+ }
+ pos := tf.Pos(offset)
+ p := tf.Position(pos)
+ // TODO(golang/go#41029): Consider returning line, column instead of line+1, 1 if
+ // the file's last character is not a newline.
+ if offset == tf.Size() {
+ return p.Filename, p.Line + 1, 1, nil
+ }
+ return p.Filename, p.Line, p.Column, nil
+}
+
+// offset is a copy of the Offset function in go/token, but with the adjustment
+// that it does not panic on invalid positions.
+func offset(tf *token.File, pos token.Pos) (int, error) {
+ if int(pos) < tf.Base() || int(pos) > tf.Base()+tf.Size() {
+ return 0, fmt.Errorf("invalid pos: %d not in [%d, %d]", pos, tf.Base(), tf.Base()+tf.Size())
+ }
+ return int(pos) - tf.Base(), nil
+}
+
+// Range converts a Span to a Range that represents the Span for the supplied
+// File.
+func (s Span) Range(tf *token.File) (Range, error) {
+ s, err := s.WithOffset(tf)
+ if err != nil {
+ return Range{}, err
+ }
+ // go/token will panic if the offset is larger than the file's size,
+ // so check here to avoid panicking.
+ if s.Start().Offset() > tf.Size() {
+ return Range{}, bug.Errorf("start offset %v is past the end of the file %v", s.Start(), tf.Size())
+ }
+ if s.End().Offset() > tf.Size() {
+ return Range{}, bug.Errorf("end offset %v is past the end of the file %v", s.End(), tf.Size())
+ }
+ return Range{
+ Start: tf.Pos(s.Start().Offset()),
+ End: tf.Pos(s.End().Offset()),
+ TokFile: tf,
+ }, nil
+}
+
+// ToPosition converts a byte offset in the file corresponding to tf into
+// 1-based line and utf-8 column indexes.
+func ToPosition(tf *token.File, offset int) (int, int, error) {
+ _, line, col, err := positionFromOffset(tf, offset)
+ return line, col, err
+}
+
+// ToOffset converts a 1-based line and utf-8 column index into a byte offset
+// in the file corresponding to tf.
+func ToOffset(tf *token.File, line, col int) (int, error) {
+ if line < 1 { // token.File.LineStart panics if line < 1
+ return -1, fmt.Errorf("invalid line: %d", line)
+ }
+
+ lineMax := tf.LineCount() + 1
+ if line > lineMax {
+ return -1, fmt.Errorf("line %d is beyond end of file %v", line, lineMax)
+ } else if line == lineMax {
+ if col > 1 {
+ return -1, fmt.Errorf("column is beyond end of file")
+ }
+ // at the end of the file, allowing for a trailing eol
+ return tf.Size(), nil
+ }
+ pos := tf.LineStart(line)
+ if !pos.IsValid() {
+ // bug.Errorf here because LineStart panics on out-of-bound input, and so
+ // should never return invalid positions.
+ return -1, bug.Errorf("line is not in file")
+ }
+ // we assume that column is in bytes here, and that the first byte of a
+ // line is at column 1
+ pos += token.Pos(col - 1)
+
+ // Debugging support for https://github.com/golang/go/issues/54655.
+ if pos > token.Pos(tf.Base()+tf.Size()) {
+ return 0, fmt.Errorf("ToOffset: column %d is beyond end of file", col)
+ }
+
+ return offset(tf, pos)
+}
diff --git a/gopls/internal/span/token_test.go b/gopls/internal/span/token_test.go
new file mode 100644
index 0000000..997c8fb
--- /dev/null
+++ b/gopls/internal/span/token_test.go
@@ -0,0 +1,80 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package span_test
+
+import (
+ "fmt"
+ "go/token"
+ "path"
+ "testing"
+
+ "golang.org/x/tools/gopls/internal/span"
+)
+
+var testdata = []struct {
+ uri string
+ content []byte
+}{
+ {"/a.go", []byte(`
+// file a.go
+package test
+`)},
+ {"/b.go", []byte(`
+//
+//
+// file b.go
+package test`)},
+ {"/c.go", []byte(`
+// file c.go
+package test`)},
+}
+
+var tokenTests = []span.Span{
+ span.New(span.URIFromPath("/a.go"), span.NewPoint(1, 1, 0), span.Point{}),
+ span.New(span.URIFromPath("/a.go"), span.NewPoint(3, 7, 20), span.NewPoint(3, 7, 20)),
+ span.New(span.URIFromPath("/b.go"), span.NewPoint(4, 9, 15), span.NewPoint(4, 13, 19)),
+ span.New(span.URIFromPath("/c.go"), span.NewPoint(4, 1, 26), span.Point{}),
+}
+
+func TestToken(t *testing.T) {
+ fset := token.NewFileSet()
+ files := map[span.URI]*token.File{}
+ for _, f := range testdata {
+ file := fset.AddFile(f.uri, -1, len(f.content))
+ file.SetLinesForContent(f.content)
+ files[span.URIFromPath(f.uri)] = file
+ }
+ for _, test := range tokenTests {
+ f := files[test.URI()]
+ t.Run(path.Base(f.Name()), func(t *testing.T) {
+ checkToken(t, f, span.New(
+ test.URI(),
+ span.NewPoint(test.Start().Line(), test.Start().Column(), 0),
+ span.NewPoint(test.End().Line(), test.End().Column(), 0),
+ ), test)
+ checkToken(t, f, span.New(
+ test.URI(),
+ span.NewPoint(0, 0, test.Start().Offset()),
+ span.NewPoint(0, 0, test.End().Offset()),
+ ), test)
+ })
+ }
+}
+
+func checkToken(t *testing.T, f *token.File, in, expect span.Span) {
+ rng, err := in.Range(f)
+ if err != nil {
+ t.Error(err)
+ }
+ gotLoc, err := rng.Span()
+ if err != nil {
+ t.Error(err)
+ }
+ expected := fmt.Sprintf("%+v", expect)
+ got := fmt.Sprintf("%+v", gotLoc)
+ if expected != got {
+ t.Errorf("For %v expected %q got %q", in, expected, got)
+ }
+}
diff --git a/gopls/internal/span/uri.go b/gopls/internal/span/uri.go
new file mode 100644
index 0000000..ce874e7
--- /dev/null
+++ b/gopls/internal/span/uri.go
@@ -0,0 +1,196 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package span
+
+import (
+ "fmt"
+ "net/url"
+ "os"
+ "path"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "unicode"
+)
+
+const fileScheme = "file"
+
+// URI represents the full URI for a file.
+type URI string
+
+func (uri URI) IsFile() bool {
+ return strings.HasPrefix(string(uri), "file://")
+}
+
+// Filename returns the file path for the given URI.
+// It is an error to call this on a URI that is not a valid filename.
+func (uri URI) Filename() string {
+ filename, err := filename(uri)
+ if err != nil {
+ panic(err)
+ }
+ return filepath.FromSlash(filename)
+}
+
+func filename(uri URI) (string, error) {
+ if uri == "" {
+ return "", nil
+ }
+
+ // This conservative check for the common case
+ // of a simple non-empty absolute POSIX filename
+ // avoids the allocation of a net.URL.
+ if strings.HasPrefix(string(uri), "file:///") {
+ rest := string(uri)[len("file://"):] // leave one slash
+ for i := 0; i < len(rest); i++ {
+ b := rest[i]
+ // Reject these cases:
+ if b < ' ' || b == 0x7f || // control character
+ b == '%' || b == '+' || // URI escape
+ b == ':' || // Windows drive letter
+ b == '@' || b == '&' || b == '?' { // authority or query
+ goto slow
+ }
+ }
+ return rest, nil
+ }
+slow:
+
+ u, err := url.ParseRequestURI(string(uri))
+ if err != nil {
+ return "", err
+ }
+ if u.Scheme != fileScheme {
+ return "", fmt.Errorf("only file URIs are supported, got %q from %q", u.Scheme, uri)
+ }
+ // If the URI is a Windows URI, we trim the leading "/" and uppercase
+ // the drive letter, which will never be case sensitive.
+ if isWindowsDriveURIPath(u.Path) {
+ u.Path = strings.ToUpper(string(u.Path[1])) + u.Path[2:]
+ }
+
+ return u.Path, nil
+}
+
+func URIFromURI(s string) URI {
+ if !strings.HasPrefix(s, "file://") {
+ return URI(s)
+ }
+
+ if !strings.HasPrefix(s, "file:///") {
+ // VS Code sends URLs with only two slashes, which are invalid. golang/go#39789.
+ s = "file:///" + s[len("file://"):]
+ }
+ // Even though the input is a URI, it may not be in canonical form. VS Code
+ // in particular over-escapes :, @, etc. Unescape and re-encode to canonicalize.
+ path, err := url.PathUnescape(s[len("file://"):])
+ if err != nil {
+ panic(err)
+ }
+
+ // File URIs from Windows may have lowercase drive letters.
+ // Since drive letters are guaranteed to be case insensitive,
+ // we change them to uppercase to remain consistent.
+ // For example, file:///c:/x/y/z becomes file:///C:/x/y/z.
+ if isWindowsDriveURIPath(path) {
+ path = path[:1] + strings.ToUpper(string(path[1])) + path[2:]
+ }
+ u := url.URL{Scheme: fileScheme, Path: path}
+ return URI(u.String())
+}
+
+// CompareURI performs a three-valued comparison of two URIs.
+// Lexically unequal URIs may compare equal if they are "file:" URIs
+// that share the same base name (ignoring case) and denote the same
+// file device/inode, according to stat(2).
+func CompareURI(a, b URI) int {
+ if equalURI(a, b) {
+ return 0
+ }
+ if a < b {
+ return -1
+ }
+ return 1
+}
+
+func equalURI(a, b URI) bool {
+ if a == b {
+ return true
+ }
+ // If we have the same URI basename, we may still have the same file URIs.
+ if !strings.EqualFold(path.Base(string(a)), path.Base(string(b))) {
+ return false
+ }
+ fa, err := filename(a)
+ if err != nil {
+ return false
+ }
+ fb, err := filename(b)
+ if err != nil {
+ return false
+ }
+ // Stat the files to check if they are equal.
+ infoa, err := os.Stat(filepath.FromSlash(fa))
+ if err != nil {
+ return false
+ }
+ infob, err := os.Stat(filepath.FromSlash(fb))
+ if err != nil {
+ return false
+ }
+ return os.SameFile(infoa, infob)
+}
+
+// URIFromPath returns a span URI for the supplied file path.
+//
+// For empty paths, URIFromPath returns the empty URI "".
+// For non-empty paths, URIFromPath returns a uri with the file:// scheme.
+func URIFromPath(path string) URI {
+ if path == "" {
+ return ""
+ }
+ // Handle standard library paths that contain the literal "$GOROOT".
+ // TODO(rstambler): The go/packages API should allow one to determine a user's $GOROOT.
+ const prefix = "$GOROOT"
+ if len(path) >= len(prefix) && strings.EqualFold(prefix, path[:len(prefix)]) {
+ suffix := path[len(prefix):]
+ path = runtime.GOROOT() + suffix
+ }
+ if !isWindowsDrivePath(path) {
+ if abs, err := filepath.Abs(path); err == nil {
+ path = abs
+ }
+ }
+ // Check the file path again, in case it became absolute.
+ if isWindowsDrivePath(path) {
+ path = "/" + strings.ToUpper(string(path[0])) + path[1:]
+ }
+ path = filepath.ToSlash(path)
+ u := url.URL{
+ Scheme: fileScheme,
+ Path: path,
+ }
+ return URI(u.String())
+}
+
+// isWindowsDrivePath returns true if the file path is of the form used by
+// Windows. We check if the path begins with a drive letter, followed by a ":".
+// For example: C:/x/y/z.
+func isWindowsDrivePath(path string) bool {
+ if len(path) < 3 {
+ return false
+ }
+ return unicode.IsLetter(rune(path[0])) && path[1] == ':'
+}
+
+// isWindowsDriveURI returns true if the file URI is of the format used by
+// Windows URIs. The url.Parse package does not specially handle Windows paths
+// (see golang/go#6027), so we check if the URI path has a drive prefix (e.g. "/C:").
+func isWindowsDriveURIPath(uri string) bool {
+ if len(uri) < 4 {
+ return false
+ }
+ return uri[0] == '/' && unicode.IsLetter(rune(uri[1])) && uri[2] == ':'
+}
diff --git a/gopls/internal/span/uri_test.go b/gopls/internal/span/uri_test.go
new file mode 100644
index 0000000..e990437
--- /dev/null
+++ b/gopls/internal/span/uri_test.go
@@ -0,0 +1,117 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !windows
+// +build !windows
+
+package span_test
+
+import (
+ "testing"
+
+ "golang.org/x/tools/gopls/internal/span"
+)
+
+// TestURI tests the conversion between URIs and filenames. The test cases
+// include Windows-style URIs and filepaths, but we avoid having OS-specific
+// tests by using only forward slashes, assuming that the standard library
+// functions filepath.ToSlash and filepath.FromSlash do not need testing.
+func TestURIFromPath(t *testing.T) {
+ for _, test := range []struct {
+ path, wantFile string
+ wantURI span.URI
+ }{
+ {
+ path: ``,
+ wantFile: ``,
+ wantURI: span.URI(""),
+ },
+ {
+ path: `C:/Windows/System32`,
+ wantFile: `C:/Windows/System32`,
+ wantURI: span.URI("file:///C:/Windows/System32"),
+ },
+ {
+ path: `C:/Go/src/bob.go`,
+ wantFile: `C:/Go/src/bob.go`,
+ wantURI: span.URI("file:///C:/Go/src/bob.go"),
+ },
+ {
+ path: `c:/Go/src/bob.go`,
+ wantFile: `C:/Go/src/bob.go`,
+ wantURI: span.URI("file:///C:/Go/src/bob.go"),
+ },
+ {
+ path: `/path/to/dir`,
+ wantFile: `/path/to/dir`,
+ wantURI: span.URI("file:///path/to/dir"),
+ },
+ {
+ path: `/a/b/c/src/bob.go`,
+ wantFile: `/a/b/c/src/bob.go`,
+ wantURI: span.URI("file:///a/b/c/src/bob.go"),
+ },
+ {
+ path: `c:/Go/src/bob george/george/george.go`,
+ wantFile: `C:/Go/src/bob george/george/george.go`,
+ wantURI: span.URI("file:///C:/Go/src/bob%20george/george/george.go"),
+ },
+ } {
+ got := span.URIFromPath(test.path)
+ if got != test.wantURI {
+ t.Errorf("URIFromPath(%q): got %q, expected %q", test.path, got, test.wantURI)
+ }
+ gotFilename := got.Filename()
+ if gotFilename != test.wantFile {
+ t.Errorf("Filename(%q): got %q, expected %q", got, gotFilename, test.wantFile)
+ }
+ }
+}
+
+func TestURIFromURI(t *testing.T) {
+ for _, test := range []struct {
+ inputURI, wantFile string
+ wantURI span.URI
+ }{
+ {
+ inputURI: `file:///c:/Go/src/bob%20george/george/george.go`,
+ wantFile: `C:/Go/src/bob george/george/george.go`,
+ wantURI: span.URI("file:///C:/Go/src/bob%20george/george/george.go"),
+ },
+ {
+ inputURI: `file:///C%3A/Go/src/bob%20george/george/george.go`,
+ wantFile: `C:/Go/src/bob george/george/george.go`,
+ wantURI: span.URI("file:///C:/Go/src/bob%20george/george/george.go"),
+ },
+ {
+ inputURI: `file:///path/to/%25p%25ercent%25/per%25cent.go`,
+ wantFile: `/path/to/%p%ercent%/per%cent.go`,
+ wantURI: span.URI(`file:///path/to/%25p%25ercent%25/per%25cent.go`),
+ },
+ {
+ inputURI: `file:///C%3A/`,
+ wantFile: `C:/`,
+ wantURI: span.URI(`file:///C:/`),
+ },
+ {
+ inputURI: `file:///`,
+ wantFile: `/`,
+ wantURI: span.URI(`file:///`),
+ },
+ {
+ inputURI: `file://wsl%24/Ubuntu/home/wdcui/repo/VMEnclaves/cvm-runtime`,
+ wantFile: `/wsl$/Ubuntu/home/wdcui/repo/VMEnclaves/cvm-runtime`,
+ wantURI: span.URI(`file:///wsl$/Ubuntu/home/wdcui/repo/VMEnclaves/cvm-runtime`),
+ },
+ } {
+ got := span.URIFromURI(test.inputURI)
+ if got != test.wantURI {
+ t.Errorf("NewURI(%q): got %q, expected %q", test.inputURI, got, test.wantURI)
+ }
+ gotFilename := got.Filename()
+ if gotFilename != test.wantFile {
+ t.Errorf("Filename(%q): got %q, expected %q", got, gotFilename, test.wantFile)
+ }
+ }
+}
diff --git a/gopls/internal/span/uri_windows_test.go b/gopls/internal/span/uri_windows_test.go
new file mode 100644
index 0000000..3891e0d
--- /dev/null
+++ b/gopls/internal/span/uri_windows_test.go
@@ -0,0 +1,112 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build windows
+// +build windows
+
+package span_test
+
+import (
+ "testing"
+
+ "golang.org/x/tools/gopls/internal/span"
+)
+
+// TestURI tests the conversion between URIs and filenames. The test cases
+// include Windows-style URIs and filepaths, but we avoid having OS-specific
+// tests by using only forward slashes, assuming that the standard library
+// functions filepath.ToSlash and filepath.FromSlash do not need testing.
+func TestURIFromPath(t *testing.T) {
+ for _, test := range []struct {
+ path, wantFile string
+ wantURI span.URI
+ }{
+ {
+ path: ``,
+ wantFile: ``,
+ wantURI: span.URI(""),
+ },
+ {
+ path: `C:\Windows\System32`,
+ wantFile: `C:\Windows\System32`,
+ wantURI: span.URI("file:///C:/Windows/System32"),
+ },
+ {
+ path: `C:\Go\src\bob.go`,
+ wantFile: `C:\Go\src\bob.go`,
+ wantURI: span.URI("file:///C:/Go/src/bob.go"),
+ },
+ {
+ path: `c:\Go\src\bob.go`,
+ wantFile: `C:\Go\src\bob.go`,
+ wantURI: span.URI("file:///C:/Go/src/bob.go"),
+ },
+ {
+ path: `\path\to\dir`,
+ wantFile: `C:\path\to\dir`,
+ wantURI: span.URI("file:///C:/path/to/dir"),
+ },
+ {
+ path: `\a\b\c\src\bob.go`,
+ wantFile: `C:\a\b\c\src\bob.go`,
+ wantURI: span.URI("file:///C:/a/b/c/src/bob.go"),
+ },
+ {
+ path: `c:\Go\src\bob george\george\george.go`,
+ wantFile: `C:\Go\src\bob george\george\george.go`,
+ wantURI: span.URI("file:///C:/Go/src/bob%20george/george/george.go"),
+ },
+ } {
+ got := span.URIFromPath(test.path)
+ if got != test.wantURI {
+ t.Errorf("URIFromPath(%q): got %q, expected %q", test.path, got, test.wantURI)
+ }
+ gotFilename := got.Filename()
+ if gotFilename != test.wantFile {
+ t.Errorf("Filename(%q): got %q, expected %q", got, gotFilename, test.wantFile)
+ }
+ }
+}
+
+func TestURIFromURI(t *testing.T) {
+ for _, test := range []struct {
+ inputURI, wantFile string
+ wantURI span.URI
+ }{
+ {
+ inputURI: `file:///c:/Go/src/bob%20george/george/george.go`,
+ wantFile: `C:\Go\src\bob george\george\george.go`,
+ wantURI: span.URI("file:///C:/Go/src/bob%20george/george/george.go"),
+ },
+ {
+ inputURI: `file:///C%3A/Go/src/bob%20george/george/george.go`,
+ wantFile: `C:\Go\src\bob george\george\george.go`,
+ wantURI: span.URI("file:///C:/Go/src/bob%20george/george/george.go"),
+ },
+ {
+ inputURI: `file:///c:/path/to/%25p%25ercent%25/per%25cent.go`,
+ wantFile: `C:\path\to\%p%ercent%\per%cent.go`,
+ wantURI: span.URI(`file:///C:/path/to/%25p%25ercent%25/per%25cent.go`),
+ },
+ {
+ inputURI: `file:///C%3A/`,
+ wantFile: `C:\`,
+ wantURI: span.URI(`file:///C:/`),
+ },
+ {
+ inputURI: `file:///`,
+ wantFile: `\`,
+ wantURI: span.URI(`file:///`),
+ },
+ } {
+ got := span.URIFromURI(test.inputURI)
+ if got != test.wantURI {
+ t.Errorf("NewURI(%q): got %q, expected %q", test.inputURI, got, test.wantURI)
+ }
+ gotFilename := got.Filename()
+ if gotFilename != test.wantFile {
+ t.Errorf("Filename(%q): got %q, expected %q", got, gotFilename, test.wantFile)
+ }
+ }
+}
diff --git a/gopls/internal/span/utf16.go b/gopls/internal/span/utf16.go
new file mode 100644
index 0000000..f4c93a6
--- /dev/null
+++ b/gopls/internal/span/utf16.go
@@ -0,0 +1,102 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package span
+
+import (
+ "fmt"
+ "unicode/utf8"
+)
+
+// ToUTF16Column calculates the utf16 column expressed by the point given the
+// supplied file contents.
+// This is used to convert from the native (always in bytes) column
+// representation and the utf16 counts used by some editors.
+func ToUTF16Column(p Point, content []byte) (int, error) {
+ if !p.HasPosition() {
+ return -1, fmt.Errorf("ToUTF16Column: point is missing position")
+ }
+ if !p.HasOffset() {
+ return -1, fmt.Errorf("ToUTF16Column: point is missing offset")
+ }
+ offset := p.Offset() // 0-based
+ colZero := p.Column() - 1 // 0-based
+ if colZero == 0 {
+ // 0-based column 0, so it must be chr 1
+ return 1, nil
+ } else if colZero < 0 {
+ return -1, fmt.Errorf("ToUTF16Column: column is invalid (%v)", colZero)
+ }
+ // work out the offset at the start of the line using the column
+ lineOffset := offset - colZero
+ if lineOffset < 0 || offset > len(content) {
+ return -1, fmt.Errorf("ToUTF16Column: offsets %v-%v outside file contents (%v)", lineOffset, offset, len(content))
+ }
+ // Use the offset to pick out the line start.
+ // This cannot panic: offset > len(content) and lineOffset < offset.
+ start := content[lineOffset:]
+
+ // Now, truncate down to the supplied column.
+ start = start[:colZero]
+
+ cnt := 0
+ for _, r := range string(start) {
+ cnt++
+ if r > 0xffff {
+ cnt++
+ }
+ }
+ return cnt + 1, nil // the +1 is for 1-based columns
+}
+
+// FromUTF16Column advances the point by the utf16 character offset given the
+// supplied line contents.
+// This is used to convert from the utf16 counts used by some editors to the
+// native (always in bytes) column representation.
+//
+// The resulting Point always has an offset.
+//
+// TODO: it looks like this may incorrectly confer a "position" to the
+// resulting Point, when it shouldn't. If p.HasPosition() == false, the
+// resulting Point will return p.HasPosition() == true, but have the wrong
+// position.
+func FromUTF16Column(p Point, chr int, content []byte) (Point, error) {
+ if !p.HasOffset() {
+ return Point{}, fmt.Errorf("FromUTF16Column: point is missing offset")
+ }
+ // if chr is 1 then no adjustment needed
+ if chr <= 1 {
+ return p, nil
+ }
+ if p.Offset() >= len(content) {
+ return p, fmt.Errorf("FromUTF16Column: offset (%v) greater than length of content (%v)", p.Offset(), len(content))
+ }
+ remains := content[p.Offset():]
+ // scan forward the specified number of characters
+ for count := 1; count < chr; count++ {
+ if len(remains) <= 0 {
+ return Point{}, fmt.Errorf("FromUTF16Column: chr goes beyond the content")
+ }
+ r, w := utf8.DecodeRune(remains)
+ if r == '\n' {
+ // Per the LSP spec:
+ //
+ // > If the character value is greater than the line length it
+ // > defaults back to the line length.
+ break
+ }
+ remains = remains[w:]
+ if r >= 0x10000 {
+ // a two point rune
+ count++
+ // if we finished in a two point rune, do not advance past the first
+ if count >= chr {
+ break
+ }
+ }
+ p.v.Column += w
+ p.v.Offset += w
+ }
+ return p, nil
+}
diff --git a/gopls/internal/span/utf16_test.go b/gopls/internal/span/utf16_test.go
new file mode 100644
index 0000000..5f75095
--- /dev/null
+++ b/gopls/internal/span/utf16_test.go
@@ -0,0 +1,322 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package span_test
+
+import (
+ "strings"
+ "testing"
+
+ "golang.org/x/tools/gopls/internal/span"
+)
+
+// The funny character below is 4 bytes long in UTF-8; two UTF-16 code points
+var funnyString = []byte("š23\nš45")
+
+var toUTF16Tests = []struct {
+ scenario string
+ input []byte
+ line int // 1-indexed count
+ col int // 1-indexed byte position in line
+ offset int // 0-indexed byte offset into input
+ resUTF16col int // 1-indexed UTF-16 col number
+ pre string // everything before the cursor on the line
+ post string // everything from the cursor onwards
+ err string // expected error string in call to ToUTF16Column
+ issue *bool
+}{
+ {
+ scenario: "cursor missing content",
+ input: nil,
+ err: "ToUTF16Column: point is missing position",
+ },
+ {
+ scenario: "cursor missing position",
+ input: funnyString,
+ line: -1,
+ col: -1,
+ err: "ToUTF16Column: point is missing position",
+ },
+ {
+ scenario: "cursor missing offset",
+ input: funnyString,
+ line: 1,
+ col: 1,
+ offset: -1,
+ err: "ToUTF16Column: point is missing offset",
+ },
+ {
+ scenario: "zero length input; cursor at first col, first line",
+ input: []byte(""),
+ line: 1,
+ col: 1,
+ offset: 0,
+ resUTF16col: 1,
+ },
+ {
+ scenario: "cursor before funny character; first line",
+ input: funnyString,
+ line: 1,
+ col: 1,
+ offset: 0,
+ resUTF16col: 1,
+ pre: "",
+ post: "š23",
+ },
+ {
+ scenario: "cursor after funny character; first line",
+ input: funnyString,
+ line: 1,
+ col: 5, // 4 + 1 (1-indexed)
+ offset: 4,
+ resUTF16col: 3, // 2 + 1 (1-indexed)
+ pre: "š",
+ post: "23",
+ },
+ {
+ scenario: "cursor after last character on first line",
+ input: funnyString,
+ line: 1,
+ col: 7, // 4 + 1 + 1 + 1 (1-indexed)
+ offset: 6, // 4 + 1 + 1
+ resUTF16col: 5, // 2 + 1 + 1 + 1 (1-indexed)
+ pre: "š23",
+ post: "",
+ },
+ {
+ scenario: "cursor before funny character; second line",
+ input: funnyString,
+ line: 2,
+ col: 1,
+ offset: 7, // length of first line
+ resUTF16col: 1,
+ pre: "",
+ post: "š45",
+ },
+ {
+ scenario: "cursor after funny character; second line",
+ input: funnyString,
+ line: 1,
+ col: 5, // 4 + 1 (1-indexed)
+ offset: 11, // 7 (length of first line) + 4
+ resUTF16col: 3, // 2 + 1 (1-indexed)
+ pre: "š",
+ post: "45",
+ },
+ {
+ scenario: "cursor after last character on second line",
+ input: funnyString,
+ line: 2,
+ col: 7, // 4 + 1 + 1 + 1 (1-indexed)
+ offset: 13, // 7 (length of first line) + 4 + 1 + 1
+ resUTF16col: 5, // 2 + 1 + 1 + 1 (1-indexed)
+ pre: "š45",
+ post: "",
+ },
+ {
+ scenario: "cursor beyond end of file",
+ input: funnyString,
+ line: 2,
+ col: 8, // 4 + 1 + 1 + 1 + 1 (1-indexed)
+ offset: 14, // 4 + 1 + 1 + 1
+ err: "ToUTF16Column: offsets 7-14 outside file contents (13)",
+ },
+}
+
+var fromUTF16Tests = []struct {
+ scenario string
+ input []byte
+ line int // 1-indexed line number (isn't actually used)
+ offset int // 0-indexed byte offset to beginning of line
+ utf16col int // 1-indexed UTF-16 col number
+ resCol int // 1-indexed byte position in line
+ resOffset int // 0-indexed byte offset into input
+ pre string // everything before the cursor on the line
+ post string // everything from the cursor onwards
+ err string // expected error string in call to ToUTF16Column
+}{
+ {
+ scenario: "zero length input; cursor at first col, first line",
+ input: []byte(""),
+ line: 1,
+ offset: 0,
+ utf16col: 1,
+ resCol: 1,
+ resOffset: 0,
+ pre: "",
+ post: "",
+ },
+ {
+ scenario: "missing offset",
+ input: funnyString,
+ line: 1,
+ offset: -1,
+ err: "FromUTF16Column: point is missing offset",
+ },
+ {
+ scenario: "cursor before funny character",
+ input: funnyString,
+ line: 1,
+ utf16col: 1,
+ resCol: 1,
+ resOffset: 0,
+ pre: "",
+ post: "š23",
+ },
+ {
+ scenario: "cursor after funny character",
+ input: funnyString,
+ line: 1,
+ utf16col: 3,
+ resCol: 5,
+ resOffset: 4,
+ pre: "š",
+ post: "23",
+ },
+ {
+ scenario: "cursor after last character on line",
+ input: funnyString,
+ line: 1,
+ utf16col: 5,
+ resCol: 7,
+ resOffset: 6,
+ pre: "š23",
+ post: "",
+ },
+ {
+ scenario: "cursor beyond last character on line",
+ input: funnyString,
+ line: 1,
+ offset: 0,
+ utf16col: 6,
+ resCol: 7,
+ resOffset: 6,
+ pre: "š23",
+ post: "",
+ },
+ {
+ scenario: "cursor before funny character; second line",
+ input: funnyString,
+ line: 2,
+ offset: 7, // length of first line
+ utf16col: 1,
+ resCol: 1,
+ resOffset: 7,
+ pre: "",
+ post: "š45",
+ },
+ {
+ scenario: "cursor after funny character; second line",
+ input: funnyString,
+ line: 2,
+ offset: 7, // length of first line
+ utf16col: 3, // 2 + 1 (1-indexed)
+ resCol: 5, // 4 + 1 (1-indexed)
+ resOffset: 11, // 7 (length of first line) + 4
+ pre: "š",
+ post: "45",
+ },
+ {
+ scenario: "cursor after last character on second line",
+ input: funnyString,
+ line: 2,
+ offset: 7, // length of first line
+ utf16col: 5, // 2 + 1 + 1 + 1 (1-indexed)
+ resCol: 7, // 4 + 1 + 1 + 1 (1-indexed)
+ resOffset: 13, // 7 (length of first line) + 4 + 1 + 1
+ pre: "š45",
+ post: "",
+ },
+ {
+ scenario: "cursor beyond end of file",
+ input: funnyString,
+ line: 2,
+ offset: 7,
+ utf16col: 6, // 2 + 1 + 1 + 1 + 1(1-indexed)
+ resCol: 8, // 4 + 1 + 1 + 1 + 1 (1-indexed)
+ resOffset: 14, // 7 (length of first line) + 4 + 1 + 1 + 1
+ err: "FromUTF16Column: chr goes beyond the content",
+ },
+ {
+ scenario: "offset beyond end of file",
+ input: funnyString,
+ line: 2,
+ offset: 14,
+ utf16col: 2,
+ err: "FromUTF16Column: offset (14) greater than length of content (13)",
+ },
+}
+
+func TestToUTF16(t *testing.T) {
+ for _, e := range toUTF16Tests {
+ t.Run(e.scenario, func(t *testing.T) {
+ if e.issue != nil && !*e.issue {
+ t.Skip("expected to fail")
+ }
+ p := span.NewPoint(e.line, e.col, e.offset)
+ got, err := span.ToUTF16Column(p, e.input)
+ if err != nil {
+ if err.Error() != e.err {
+ t.Fatalf("expected error %v; got %v", e.err, err)
+ }
+ return
+ }
+ if e.err != "" {
+ t.Fatalf("unexpected success; wanted %v", e.err)
+ }
+ if got != e.resUTF16col {
+ t.Fatalf("expected result %v; got %v", e.resUTF16col, got)
+ }
+ pre, post := getPrePost(e.input, p.Offset())
+ if string(pre) != e.pre {
+ t.Fatalf("expected #%d pre %q; got %q", p.Offset(), e.pre, pre)
+ }
+ if string(post) != e.post {
+ t.Fatalf("expected #%d, post %q; got %q", p.Offset(), e.post, post)
+ }
+ })
+ }
+}
+
+func TestFromUTF16(t *testing.T) {
+ for _, e := range fromUTF16Tests {
+ t.Run(e.scenario, func(t *testing.T) {
+ p := span.NewPoint(e.line, 1, e.offset)
+ p, err := span.FromUTF16Column(p, e.utf16col, []byte(e.input))
+ if err != nil {
+ if err.Error() != e.err {
+ t.Fatalf("expected error %v; got %v", e.err, err)
+ }
+ return
+ }
+ if e.err != "" {
+ t.Fatalf("unexpected success; wanted %v", e.err)
+ }
+ if p.Column() != e.resCol {
+ t.Fatalf("expected resulting col %v; got %v", e.resCol, p.Column())
+ }
+ if p.Offset() != e.resOffset {
+ t.Fatalf("expected resulting offset %v; got %v", e.resOffset, p.Offset())
+ }
+ pre, post := getPrePost(e.input, p.Offset())
+ if string(pre) != e.pre {
+ t.Fatalf("expected #%d pre %q; got %q", p.Offset(), e.pre, pre)
+ }
+ if string(post) != e.post {
+ t.Fatalf("expected #%d post %q; got %q", p.Offset(), e.post, post)
+ }
+ })
+ }
+}
+
+func getPrePost(content []byte, offset int) (string, string) {
+ pre, post := string(content)[:offset], string(content)[offset:]
+ if i := strings.LastIndex(pre, "\n"); i >= 0 {
+ pre = pre[i+1:]
+ }
+ if i := strings.IndexRune(post, '\n'); i >= 0 {
+ post = post[:i]
+ }
+ return pre, post
+}
diff --git a/gopls/internal/vulncheck/vulntest/db.go b/gopls/internal/vulncheck/vulntest/db.go
index 674e920..511a47e 100644
--- a/gopls/internal/vulncheck/vulntest/db.go
+++ b/gopls/internal/vulncheck/vulntest/db.go
@@ -20,7 +20,7 @@
"strings"
"time"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/txtar"
"golang.org/x/vuln/client"
"golang.org/x/vuln/osv"
diff --git a/gopls/test/debug/debug_test.go b/gopls/test/debug/debug_test.go
index 9c6c0d6..9d5d6f0 100644
--- a/gopls/test/debug/debug_test.go
+++ b/gopls/test/debug/debug_test.go
@@ -24,7 +24,7 @@
"golang.org/x/tools/gopls/internal/lsp/cache"
"golang.org/x/tools/gopls/internal/lsp/debug"
"golang.org/x/tools/gopls/internal/lsp/source"
- "golang.org/x/tools/internal/span"
+ "golang.org/x/tools/gopls/internal/span"
)
type tdata struct {