The handlers for most gopls RPCs start by computing the node in the syntax tree that is identified by the selection.
An unfortunate limitation of LSP is that in most cases the RPC request indicates the selection by only a single point, the cursor position, losing valuable information. Indicating the selection by '[' and ']' and the cursor by '⁁', in this example:
the break keyword is selected, but the server can tell only that the cursor is after break. In:
the selection is the break keyword plus the following space, but the server knows only that the cursor is before label. And in:
the selection is the break keyword alone, but the server gets only the position after the 'k'.
Gopls makes extensive use of astutil.PathEnclosingInterval for inferring the syntax node from a given selection (start, end). When invoked on an empty selection (end=start), which is the common case in gopls because of the limitation described above, it behaves as if invoked on the interval (start, start+1). That means that it operates
- in the first example on the space between
break and label, and returns the BranchStmt (a reasonable answer);
- in the second case on the first "l" of
label, returning the Ident (again reasonable); but
- in the third on the newline following
break, returning the enclosing BlockStmt, which is not helpful.
It is the wrong tool for the job.
Until such time as LSP furnishes the server with both the start and end points of the selection (which may be a long wait), I propose that we introduce a new function for all single-position queries in gopls that gives the right answers in all three cases (respectively: BranchStmt, Ident, BranchStmt).
@madelinekalil
The handlers for most gopls RPCs start by computing the node in the syntax tree that is identified by the selection.
An unfortunate limitation of LSP is that in most cases the RPC request indicates the selection by only a single point, the cursor position, losing valuable information. Indicating the selection by '[' and ']' and the cursor by '⁁', in this example:
the
breakkeyword is selected, but the server can tell only that the cursor is afterbreak. In:the selection is the
breakkeyword plus the following space, but the server knows only that the cursor is beforelabel. And in:the selection is the
breakkeyword alone, but the server gets only the position after the 'k'.Gopls makes extensive use of astutil.PathEnclosingInterval for inferring the syntax node from a given selection (start, end). When invoked on an empty selection (end=start), which is the common case in gopls because of the limitation described above, it behaves as if invoked on the interval (start, start+1). That means that it operates
breakandlabel, and returns theBranchStmt(a reasonable answer);label, returning theIdent(again reasonable); butbreak, returning the enclosingBlockStmt, which is not helpful.It is the wrong tool for the job.
Until such time as LSP furnishes the server with both the start and end points of the selection (which may be a long wait), I propose that we introduce a new function for all single-position queries in gopls that gives the right answers in all three cases (respectively: BranchStmt, Ident, BranchStmt).
@madelinekalil