Skip to content

TS7 LSP: documentHighlight returns nothing when the file path contains '@' #64758

Open

Description

@snapwich

🔎 Search Terms

documentHighlight, document highlight, URI encoding, percent-encoding, %40, @ in path, Neovim, LSP

🕗 Version & Regression Information

  • I was unable to test this on prior versions because this code is in the TS7 language server only. The old tsserver (through vtsls) does not have this problem.

I reproduced it with tsc --lsp 7.0.2. The same code is on main at ba1819f.

⏯ Playground Link

Not applicable. The problem is in the language server.

💻 Code

Put this file in a directory whose path contains @, for example /tmp/a@b/proj/x.ts, with an empty tsconfig.json next to it:

const foo = 1;
console.log(foo);
console.log(foo);

🙁 Actual behavior

textDocument/documentHighlight on foo (line 0, character 7) returns an empty array if the client sends the path with @ not encoded:

URI that the client sends Highlights
file:///tmp/a@b/proj/x.ts 0
file:///tmp/a%40b/proj/x.ts 3
file:///tmp/plain/proj/x.ts 3

Neovim sends the first form (vim.uri_from_fname("/tmp/a@b/x.ts") gives file:///tmp/a@b/x.ts). Thus, in Neovim, document highlights and features that use them (for example, jump to next reference) do not work in projects whose path contains @. Other requests, such as textDocument/references, work correctly on the same file.

🙂 Expected behavior

The server returns 3 highlights for all three URIs. The two a@b URIs identify the same file, and the server opens that file correctly from both forms.

Additional information about the issue

Cause. tsc/internal/ls/documenthighlights.go:30 filters the results with a raw string compare:

if mh.Uri == documentUri {
  • mh.Uri comes from lsconv.FileNameToDocumentURI, which encodes @ as %40 (tsc/internal/ls/lsconv/converters.go:315).
  • documentUri is the string that the client sent, without changes.

When the client does not encode @, the strings are different, and the filter removes all highlights. VS Code does not see this problem because vscode-uri also encodes @ as %40 (URI.file('/tmp/a@b/x.ts').toString() gives file:///tmp/a%40b/x.ts). Thus the two sides always agree.

Why this is a server problem. RFC 3986 permits @ in a path segment without encoding, so the client URI is valid. Also, the LSP specification (URI section) says:

Clients and servers should not assume that each other are encoding the same way (for example a client encoding colons in drive letters cannot assume server responses will have encoded colons).

Possible fix. Compare file names, not URI strings:

if mh.Uri.FileName() == documentUri.FileName() {

Another possible fix is to normalize documentUri one time before the loop. Other characters in extraEscapeReplacer (', (, ), *, +, ,, ;, =, !, $, &, and so on) probably cause the same problem with clients that do not encode them.

Related: #43261 had the same type of cause (a path-case mismatch caused document highlights to fail) in tsserver.

Environment

  • Neovim v0.12.0-dev, Linux (WSL2)
  • tsc --lsp 7.0.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions