-
Notifications
You must be signed in to change notification settings - Fork 18.5k
Description
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:
[break]⁁ label
the break keyword is selected, but the server can tell only that the cursor is after break. In:
[break ]⁁label
the selection is the break keyword plus the following space, but the server knows only that the cursor is before label. And in:
[break]⁁
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
breakandlabel, and returns theBranchStmt(a reasonable answer); - in the second case on the first "l" of
label, returning theIdent(again reasonable); but - in the third on the newline following
break, 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).