internal/lsp/source: eliminate ColumnMapper.PointSpan in favor of Pos
It turns out PointSpan was only ever used as part of an oft repeated
pattern to get a token.Pos from a protocol position. Cut out the
middle.
Change-Id: I0b2c0fc3d335e6bbd3c1ac72c6f75e2c40c60ca5
Reviewed-on: https://go-review.googlesource.com/c/tools/+/408717
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
diff --git a/internal/lsp/mod/hover.go b/internal/lsp/mod/hover.go
index 96bc0c0..03c3679 100644
--- a/internal/lsp/mod/hover.go
+++ b/internal/lsp/mod/hover.go
@@ -39,14 +39,10 @@
if err != nil {
return nil, fmt.Errorf("getting modfile handle: %w", err)
}
- spn, err := pm.Mapper.PointSpan(position)
+ pos, err := pm.Mapper.Pos(position)
if err != nil {
return nil, fmt.Errorf("computing cursor position: %w", err)
}
- hoverRng, err := spn.Range(pm.Mapper.TokFile)
- if err != nil {
- return nil, fmt.Errorf("computing hover range: %w", err)
- }
// Confirm that the cursor is at the position of a require statement.
var req *modfile.Require
@@ -61,7 +57,7 @@
// Shift the start position to the location of the
// dependency within the require statement.
startPos, endPos = s+i, s+i+len(dep)
- if token.Pos(startPos) <= hoverRng.Start && hoverRng.Start <= token.Pos(endPos) {
+ if token.Pos(startPos) <= pos && pos <= token.Pos(endPos) {
req = r
break
}
diff --git a/internal/lsp/protocol/span.go b/internal/lsp/protocol/span.go
index dac53cb..bb30aeb 100644
--- a/internal/lsp/protocol/span.go
+++ b/internal/lsp/protocol/span.go
@@ -105,12 +105,22 @@
return spn.Range(m.TokFile)
}
-func (m *ColumnMapper) PointSpan(p Position) (span.Span, error) {
+// Pos returns the token.Pos corresponding to the given protocol position.
+func (m *ColumnMapper) Pos(p Position) (token.Pos, error) {
start, err := m.Point(p)
if err != nil {
- return span.Span{}, err
+ return token.NoPos, err
}
- return span.New(m.URI, start, start).WithAll(m.TokFile)
+ // TODO: refactor the span package to avoid creating this unnecessary end position.
+ spn, err := span.New(m.URI, start, start).WithAll(m.TokFile)
+ if err != nil {
+ return token.NoPos, err
+ }
+ rng, err := spn.Range(m.TokFile)
+ if err != nil {
+ return token.NoPos, err
+ }
+ return rng.Start, nil
}
func (m *ColumnMapper) Point(p Position) (span.Point, error) {
diff --git a/internal/lsp/source/completion/completion.go b/internal/lsp/source/completion/completion.go
index 11b9497..bb1c68d 100644
--- a/internal/lsp/source/completion/completion.go
+++ b/internal/lsp/source/completion/completion.go
@@ -445,23 +445,17 @@
}
return items, surrounding, nil
}
- spn, err := pgf.Mapper.PointSpan(protoPos)
- if err != nil {
- return nil, nil, err
- }
- rng, err := spn.Range(pgf.Mapper.TokFile)
+ pos, err := pgf.Mapper.Pos(protoPos)
if err != nil {
return nil, nil, err
}
// Completion is based on what precedes the cursor.
// Find the path to the position before pos.
- path, _ := astutil.PathEnclosingInterval(pgf.File, rng.Start-1, rng.Start-1)
+ path, _ := astutil.PathEnclosingInterval(pgf.File, pos-1, pos-1)
if path == nil {
return nil, nil, fmt.Errorf("cannot find node enclosing position")
}
- pos := rng.Start
-
// Check if completion at this position is valid. If not, return early.
switch n := path[0].(type) {
case *ast.BasicLit:
@@ -524,7 +518,7 @@
pos: pos,
seen: make(map[types.Object]bool),
enclosingFunc: enclosingFunction(path, pkg.GetTypesInfo()),
- enclosingCompositeLiteral: enclosingCompositeLiteral(path, rng.Start, pkg.GetTypesInfo()),
+ enclosingCompositeLiteral: enclosingCompositeLiteral(path, pos, pkg.GetTypesInfo()),
deepState: deepCompletionState{
enabled: opts.DeepCompletion,
},
diff --git a/internal/lsp/source/completion/package.go b/internal/lsp/source/completion/package.go
index ed9f8fd..21244ef 100644
--- a/internal/lsp/source/completion/package.go
+++ b/internal/lsp/source/completion/package.go
@@ -28,7 +28,7 @@
// packageClauseCompletions offers completions for a package declaration when
// one is not present in the given file.
-func packageClauseCompletions(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle, pos protocol.Position) ([]CompletionItem, *Selection, error) {
+func packageClauseCompletions(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle, position protocol.Position) ([]CompletionItem, *Selection, error) {
// We know that the AST for this file will be empty due to the missing
// package declaration, but parse it anyway to get a mapper.
pgf, err := snapshot.ParseGo(ctx, fh, source.ParseFull)
@@ -36,16 +36,12 @@
return nil, nil, err
}
- cursorSpan, err := pgf.Mapper.PointSpan(pos)
- if err != nil {
- return nil, nil, err
- }
- rng, err := cursorSpan.Range(pgf.Mapper.TokFile)
+ pos, err := pgf.Mapper.Pos(position)
if err != nil {
return nil, nil, err
}
- surrounding, err := packageCompletionSurrounding(snapshot.FileSet(), pgf, rng.Start)
+ surrounding, err := packageCompletionSurrounding(snapshot.FileSet(), pgf, pos)
if err != nil {
return nil, nil, fmt.Errorf("invalid position for package completion: %w", err)
}
diff --git a/internal/lsp/source/highlight.go b/internal/lsp/source/highlight.go
index a3887af..4be078b 100644
--- a/internal/lsp/source/highlight.go
+++ b/internal/lsp/source/highlight.go
@@ -17,7 +17,7 @@
"golang.org/x/tools/internal/lsp/protocol"
)
-func Highlight(ctx context.Context, snapshot Snapshot, fh FileHandle, pos protocol.Position) ([]protocol.Range, error) {
+func Highlight(ctx context.Context, snapshot Snapshot, fh FileHandle, position protocol.Position) ([]protocol.Range, error) {
ctx, done := event.Start(ctx, "source.Highlight")
defer done()
@@ -33,24 +33,20 @@
return nil, fmt.Errorf("getting file for Highlight: %w", err)
}
- spn, err := pgf.Mapper.PointSpan(pos)
+ pos, err := pgf.Mapper.Pos(position)
if err != nil {
return nil, err
}
- rng, err := spn.Range(pgf.Mapper.TokFile)
- if err != nil {
- return nil, err
- }
- path, _ := astutil.PathEnclosingInterval(pgf.File, rng.Start, rng.Start)
+ path, _ := astutil.PathEnclosingInterval(pgf.File, pos, pos)
if len(path) == 0 {
- return nil, fmt.Errorf("no enclosing position found for %v:%v", int(pos.Line), int(pos.Character))
+ return nil, fmt.Errorf("no enclosing position found for %v:%v", position.Line, position.Character)
}
// If start == end for astutil.PathEnclosingInterval, the 1-char interval
// following start is used instead. As a result, we might not get an exact
// match so we should check the 1-char interval to the left of the passed
// in position to see if that is an exact match.
if _, ok := path[0].(*ast.Ident); !ok {
- if p, _ := astutil.PathEnclosingInterval(pgf.File, rng.Start-1, rng.Start-1); p != nil {
+ if p, _ := astutil.PathEnclosingInterval(pgf.File, pos-1, pos-1); p != nil {
switch p[0].(type) {
case *ast.Ident, *ast.SelectorExpr:
path = p // use preceding ident/selector
diff --git a/internal/lsp/source/hover.go b/internal/lsp/source/hover.go
index d764cdd..58ea969 100644
--- a/internal/lsp/source/hover.go
+++ b/internal/lsp/source/hover.go
@@ -142,15 +142,10 @@
if err != nil {
return 0, MappedRange{}, err
}
- spn, err := pgf.Mapper.PointSpan(position)
+ pos, err := pgf.Mapper.Pos(position)
if err != nil {
return 0, MappedRange{}, err
}
- rng, err := spn.Range(pgf.Mapper.TokFile)
- if err != nil {
- return 0, MappedRange{}, err
- }
- pos := rng.Start
// Find the basic literal enclosing the given position, if there is one.
var lit *ast.BasicLit
diff --git a/internal/lsp/source/identifier.go b/internal/lsp/source/identifier.go
index f2938f2..40655e2 100644
--- a/internal/lsp/source/identifier.go
+++ b/internal/lsp/source/identifier.go
@@ -77,7 +77,7 @@
// Identifier returns identifier information for a position
// in a file, accounting for a potentially incomplete selector.
-func Identifier(ctx context.Context, snapshot Snapshot, fh FileHandle, pos protocol.Position) (*IdentifierInfo, error) {
+func Identifier(ctx context.Context, snapshot Snapshot, fh FileHandle, position protocol.Position) (*IdentifierInfo, error) {
ctx, done := event.Start(ctx, "source.Identifier")
defer done()
@@ -104,16 +104,12 @@
bug.Report("missing package file", bug.Data{"pkg": pkg.ID(), "file": fh.URI()})
return nil, err
}
- spn, err := pgf.Mapper.PointSpan(pos)
- if err != nil {
- return nil, err
- }
- rng, err := spn.Range(pgf.Mapper.TokFile)
+ pos, err := pgf.Mapper.Pos(position)
if err != nil {
return nil, err
}
var ident *IdentifierInfo
- ident, findErr = findIdentifier(ctx, snapshot, pkg, pgf, rng.Start)
+ ident, findErr = findIdentifier(ctx, snapshot, pkg, pgf, pos)
if findErr == nil {
return ident, nil
}
diff --git a/internal/lsp/source/implementation.go b/internal/lsp/source/implementation.go
index b122a5d..6666605 100644
--- a/internal/lsp/source/implementation.go
+++ b/internal/lsp/source/implementation.go
@@ -227,15 +227,11 @@
if err != nil {
return nil, err
}
- spn, err := pgf.Mapper.PointSpan(pp)
+ pos, err := pgf.Mapper.Pos(pp)
if err != nil {
return nil, err
}
- rng, err := spn.Range(pgf.Mapper.TokFile)
- if err != nil {
- return nil, err
- }
- offset, err := safetoken.Offset(pgf.Tok, rng.Start)
+ offset, err := safetoken.Offset(pgf.Tok, pos)
if err != nil {
return nil, err
}
diff --git a/internal/lsp/source/signature_help.go b/internal/lsp/source/signature_help.go
index 1d35931..813f67e 100644
--- a/internal/lsp/source/signature_help.go
+++ b/internal/lsp/source/signature_help.go
@@ -16,7 +16,7 @@
"golang.org/x/tools/internal/lsp/protocol"
)
-func SignatureHelp(ctx context.Context, snapshot Snapshot, fh FileHandle, pos protocol.Position) (*protocol.SignatureInformation, int, error) {
+func SignatureHelp(ctx context.Context, snapshot Snapshot, fh FileHandle, position protocol.Position) (*protocol.SignatureInformation, int, error) {
ctx, done := event.Start(ctx, "source.SignatureHelp")
defer done()
@@ -24,17 +24,13 @@
if err != nil {
return nil, 0, fmt.Errorf("getting file for SignatureHelp: %w", err)
}
- spn, err := pgf.Mapper.PointSpan(pos)
- if err != nil {
- return nil, 0, err
- }
- rng, err := spn.Range(pgf.Mapper.TokFile)
+ pos, err := pgf.Mapper.Pos(position)
if err != nil {
return nil, 0, err
}
// Find a call expression surrounding the query position.
var callExpr *ast.CallExpr
- path, _ := astutil.PathEnclosingInterval(pgf.File, rng.Start, rng.Start)
+ path, _ := astutil.PathEnclosingInterval(pgf.File, pos, pos)
if path == nil {
return nil, 0, fmt.Errorf("cannot find node enclosing position")
}
@@ -42,7 +38,7 @@
for _, node := range path {
switch node := node.(type) {
case *ast.CallExpr:
- if rng.Start >= node.Lparen && rng.Start <= node.Rparen {
+ if pos >= node.Lparen && pos <= node.Rparen {
callExpr = node
break FindCall
}
@@ -77,7 +73,7 @@
// Handle builtin functions separately.
if obj, ok := obj.(*types.Builtin); ok {
- return builtinSignature(ctx, snapshot, callExpr, obj.Name(), rng.Start)
+ return builtinSignature(ctx, snapshot, callExpr, obj.Name(), pos)
}
// Get the type information for the function being called.
@@ -91,7 +87,7 @@
return nil, 0, fmt.Errorf("cannot find signature for Fun %[1]T (%[1]v)", callExpr.Fun)
}
- activeParam := activeParameter(callExpr, sig.Params().Len(), sig.Variadic(), rng.Start)
+ activeParam := activeParameter(callExpr, sig.Params().Len(), sig.Variadic(), pos)
var (
name string
diff --git a/internal/lsp/work/completion.go b/internal/lsp/work/completion.go
index 300d13c..c7227bc 100644
--- a/internal/lsp/work/completion.go
+++ b/internal/lsp/work/completion.go
@@ -28,17 +28,13 @@
if err != nil {
return nil, fmt.Errorf("getting go.work file handle: %w", err)
}
- spn, err := pw.Mapper.PointSpan(position)
+ pos, err := pw.Mapper.Pos(position)
if err != nil {
return nil, fmt.Errorf("computing cursor position: %w", err)
}
- rng, err := spn.Range(pw.Mapper.TokFile)
- if err != nil {
- return nil, fmt.Errorf("computing range: %w", err)
- }
// Find the use statement the user is in.
- cursor := rng.Start - 1
+ cursor := pos - 1
use, pathStart, _ := usePath(pw, cursor)
if use == nil {
return &protocol.CompletionList{}, nil
diff --git a/internal/lsp/work/hover.go b/internal/lsp/work/hover.go
index 5fa6828..8f7822d 100644
--- a/internal/lsp/work/hover.go
+++ b/internal/lsp/work/hover.go
@@ -30,18 +30,14 @@
if err != nil {
return nil, fmt.Errorf("getting go.work file handle: %w", err)
}
- spn, err := pw.Mapper.PointSpan(position)
+ pos, err := pw.Mapper.Pos(position)
if err != nil {
return nil, fmt.Errorf("computing cursor position: %w", err)
}
- hoverRng, err := spn.Range(pw.Mapper.TokFile)
- if err != nil {
- return nil, fmt.Errorf("computing hover range: %w", err)
- }
// Confirm that the cursor is inside a use statement, and then find
// the position of the use statement's directory path.
- use, pathStart, pathEnd := usePath(pw, hoverRng.Start)
+ use, pathStart, pathEnd := usePath(pw, pos)
// The cursor position is not on a use statement.
if use == nil {