Skip to content

Commit

Permalink
internal/lsp: handle panic in hoverRune by using token.Pos
Browse files Browse the repository at this point in the history
All operations within a file should be in terms of token.Pos, until the
value must be returned.

Fixes golang/go#48492

Change-Id: I2adfcad8b4729386700c08ba4618e033bf7c3db5
Reviewed-on: https://go-review.googlesource.com/c/tools/+/351629
Run-TryBot: Rebecca Stambler <[email protected]>
Trust: Rebecca Stambler <[email protected]>
gopls-CI: kokoro <[email protected]>
TryBot-Result: Go Bot <[email protected]>
Reviewed-by: Robert Findley <[email protected]>
  • Loading branch information
stamblerre committed Sep 22, 2021
1 parent c8db761 commit 6d1e33f
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 13 deletions.
17 changes: 17 additions & 0 deletions gopls/internal/regtest/misc/hover_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"
"testing"

"golang.org/x/tools/internal/lsp/fake"
. "golang.org/x/tools/internal/lsp/regtest"
"golang.org/x/tools/internal/testenv"
)
Expand Down Expand Up @@ -113,3 +114,19 @@ type Example struct`
env.Editor.Hover(env.Ctx, "main.go", env.RegexpSearch("main.go", "Example"))
})
}

func TestHoverRune_48492(t *testing.T) {
const files = `
-- go.mod --
module mod.com
go 1.18
-- main.go --
package main
`
Run(t, files, func(t *testing.T, env *Env) {
env.OpenFile("main.go")
env.EditBuffer("main.go", fake.NewEdit(0, 0, 1, 0, "package main\nfunc main() {\nconst x = `\nfoo\n`\n}"))
env.Editor.Hover(env.Ctx, "main.go", env.RegexpSearch("main.go", "foo"))
})
}
20 changes: 7 additions & 13 deletions internal/lsp/source/hover.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,19 +137,20 @@ func hoverRune(ctx context.Context, snapshot Snapshot, fh FileHandle, position p
var ErrNoRuneFound = errors.New("no rune found")

// findRune returns rune information for a position in a file.
func findRune(ctx context.Context, snapshot Snapshot, fh FileHandle, pos protocol.Position) (rune, MappedRange, error) {
func findRune(ctx context.Context, snapshot Snapshot, fh FileHandle, position protocol.Position) (rune, MappedRange, error) {
pkg, pgf, err := GetParsedFile(ctx, snapshot, fh, NarrowestPackage)
if err != nil {
return 0, MappedRange{}, err
}
spn, err := pgf.Mapper.PointSpan(pos)
spn, err := pgf.Mapper.PointSpan(position)
if err != nil {
return 0, MappedRange{}, err
}
rng, err := spn.Range(pgf.Mapper.Converter)
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
Expand All @@ -158,7 +159,7 @@ func findRune(ctx context.Context, snapshot Snapshot, fh FileHandle, pos protoco
if found {
return false
}
if n, ok := n.(*ast.BasicLit); ok && rng.Start >= n.Pos() && rng.Start <= n.End() {
if n, ok := n.(*ast.BasicLit); ok && pos >= n.Pos() && pos <= n.End() {
lit = n
found = true
}
Expand Down Expand Up @@ -202,16 +203,9 @@ func findRune(ctx context.Context, snapshot Snapshot, fh FileHandle, pos protoco
// It's a string, scan only if it contains a unicode escape sequence under or before the
// current cursor position.
var found bool
strMappedRng, err := posToMappedRange(snapshot, pkg, lit.Pos(), lit.End())
if err != nil {
return 0, MappedRange{}, err
}
strRng, err := strMappedRng.Range()
if err != nil {
return 0, MappedRange{}, err
}
offset := strRng.Start.Character
for i := pos.Character - offset; i > 0; i-- {
litOffset := pgf.Tok.Offset(lit.Pos())
offset := pgf.Tok.Offset(pos)
for i := offset - litOffset; i > 0; i-- {
// Start at the cursor position and search backward for the beginning of a rune escape sequence.
rr, _ := utf8.DecodeRuneInString(lit.Value[i:])
if rr == utf8.RuneError {
Expand Down

0 comments on commit 6d1e33f

Please sign in to comment.