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>
This commit is contained in:
Robert Findley 2022-05-28 09:55:17 -04:00
parent 9d7bf95bad
commit 0cdf4b588d
11 changed files with 42 additions and 75 deletions

View File

@ -39,14 +39,10 @@ func Hover(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle,
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 @@ func Hover(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle,
// 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
}

View File

@ -105,12 +105,22 @@ func (m *ColumnMapper) RangeToSpanRange(r Range) (span.Range, error) {
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) {

View File

@ -445,23 +445,17 @@ func Completion(ctx context.Context, snapshot source.Snapshot, fh source.FileHan
}
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 @@ func Completion(ctx context.Context, snapshot source.Snapshot, fh source.FileHan
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,
},

View File

@ -28,7 +28,7 @@ import (
// 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 @@ func packageClauseCompletions(ctx context.Context, snapshot source.Snapshot, fh
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)
}

View File

@ -17,7 +17,7 @@ import (
"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 @@ func Highlight(ctx context.Context, snapshot Snapshot, fh FileHandle, pos protoc
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

View File

@ -142,15 +142,10 @@ func findRune(ctx context.Context, snapshot Snapshot, fh FileHandle, position pr
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

View File

@ -77,7 +77,7 @@ type Declaration struct {
// 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 @@ func Identifier(ctx context.Context, snapshot Snapshot, fh FileHandle, pos proto
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
}

View File

@ -227,15 +227,11 @@ func qualifiedObjsAtProtocolPos(ctx context.Context, s Snapshot, uri span.URI, p
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
}

View File

@ -16,7 +16,7 @@ import (
"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 @@ func SignatureHelp(ctx context.Context, snapshot Snapshot, fh FileHandle, pos pr
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 @@ FindCall:
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 @@ FindCall:
// 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 @@ FindCall:
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

View File

@ -28,17 +28,13 @@ func Completion(ctx context.Context, snapshot source.Snapshot, fh source.Version
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

View File

@ -30,18 +30,14 @@ func Hover(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle,
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 {