Skip to content

x/tools/gopls: PathEnclosingInterval is inappropriate for single-point LSP queries #71068

@adonovan

Description

@adonovan

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 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    goplsIssues related to the Go language server, gopls.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions