gopls/internal/template: fix completion token boundary conditions

The template completion logic checked to see if the cursor position was
inside a logical {{ }} block, but the boundary conditions in the
relevant checks was wrong: in one case, a panic would occur if the
cursor was in between the pair of left braces. In another, it would
panic even if the cursor was at the start of a pair of left braces.

Fix the boundary conditions, with a test.

Fixes golang/go#57621

Change-Id: I826349906ee1ae67b2c5378e1b59d56e94c14fb2
Reviewed-on: https://go-review.googlesource.com/c/tools/+/622875
Auto-Submit: Robert Findley <rfindley@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Rob Findley 2024-10-28 18:25:20 +00:00 коммит произвёл Gopher Robot
Родитель 91421d7314
Коммит 73d6794ebb
2 изменённых файлов: 31 добавлений и 3 удалений

Просмотреть файл

@ -84,13 +84,15 @@ func inTemplate(fc *Parsed, pos protocol.Position) int {
offset := fc.FromPosition(pos)
// this could be a binary search, as the tokens are ordered
for _, tk := range fc.tokens {
if tk.Start < offset && offset <= tk.End {
if tk.Start+len(Left) <= offset && offset+len(Right) <= tk.End {
return tk.Start
}
}
for _, x := range fc.elided {
if x > offset {
// fc.elided is sorted
if x+len(Left) > offset {
// fc.elided is sorted, and x is the position where a '{{' was replaced
// by ' '. We consider only cases where the replaced {{ is to the left
// of the cursor.
break
}
// If the interval [x,offset] does not contain Left or Right

Просмотреть файл

@ -228,4 +228,30 @@ func shorten(fn protocol.DocumentURI) string {
return pieces[j-2] + "/" + pieces[j-1]
}
func TestCompletionPanic_Issue57621(t *testing.T) {
const src = `
-- go.mod --
module mod.com
go 1.12
-- hello.tmpl --
{{range .Planets}}
Hello {{
{{end}}
`
Run(t, src, func(t *testing.T, env *Env) {
env.OpenFile("hello.tmpl")
// None of these should panic.
env.Completion(env.RegexpSearch("hello.tmpl", `Hello ()\{\{`))
env.Completion(env.RegexpSearch("hello.tmpl", `Hello \{()\{`))
env.Completion(env.RegexpSearch("hello.tmpl", `Hello \{\{()`))
env.Completion(env.RegexpSearch("hello.tmpl", `()\{\{range`))
env.Completion(env.RegexpSearch("hello.tmpl", `\{()\{range`))
env.Completion(env.RegexpSearch("hello.tmpl", `\{\{()range`))
env.Completion(env.RegexpSearch("hello.tmpl", `Planets()}}`))
env.Completion(env.RegexpSearch("hello.tmpl", `Planets}()}`))
env.Completion(env.RegexpSearch("hello.tmpl", `Planets}}()`))
})
}
// Hover needs tests