Summary
Responses from downstream servers are mapped back to their injection region by comparing the returned URI string with the virtual URI kakehashi rendered, byte for byte. RFC 3986 §6.2.2 treats %2b and %2B as equivalent, and an escaped unreserved character (%41) as equivalent to the literal one. A server that normalizes differently from kakehashi therefore returns a URI that kakehashi no longer recognizes as its own. Depending on the call site, its locations or edits are dropped or passed through untranslated.
Reproduction
For a host file:///my%2fproject/doc.md (lowercase hex in the host directory), url keeps the escape as it is. A downstream server that uppercases hex (e.g. one re-serializing through vscode-uri) returns file:///my%2Fproject/kakehashi-virtual-uri-<id>.lua. That string differs from the rendered identity, so goto/references results for the region are filtered out (transform_location_for_goto, Case 3).
This predates the virtual-URI encoding work (#1093 and its follow-up). The follow-up keeps filename escapes byte-identical to main wherever main's output was valid, so it neither introduces nor fixes this gap.
Exact-string sites
src/lsp/bridge/protocol/response.rs — transform_location_for_goto, transform_location_link_for_goto
src/lsp/bridge/protocol/workspace_edit.rs — changes re-keying and documentChanges text-document edits
src/lsp/bridge/text_document/call_hierarchy.rs — incoming/outgoing provenance (known_virtual_uris.contains_uri, request_virtual_uri compare), prepare items
src/lsp/bridge/text_document/type_hierarchy.rs — item provenance
src/lsp/bridge/text_document/code_action.rs — workspace_edit_touches_foreign_region
src/lsp/bridge/text_document/document_symbol.rs, inlay_hint.rs — same-virtual-URI checks
src/lsp/bridge/pool/document_tracker.rs — resolve_virtual_uri (showDocument, applyEdit, pushed diagnostics), VirtualUriObserver explicit_uris / provenance sets
Suggested fix
Add one syntax-normalization helper (uppercase escape hex; decode escaped unreserved characters; leave reserved escapes distinct). Compare through it at the sites above, and normalize the keys of the identity sets on both insert and lookup. Keep the exact-match fast path.
Summary
Responses from downstream servers are mapped back to their injection region by comparing the returned URI string with the virtual URI kakehashi rendered, byte for byte. RFC 3986 §6.2.2 treats
%2band%2Bas equivalent, and an escaped unreserved character (%41) as equivalent to the literal one. A server that normalizes differently from kakehashi therefore returns a URI that kakehashi no longer recognizes as its own. Depending on the call site, its locations or edits are dropped or passed through untranslated.Reproduction
For a host
file:///my%2fproject/doc.md(lowercase hex in the host directory),urlkeeps the escape as it is. A downstream server that uppercases hex (e.g. one re-serializing through vscode-uri) returnsfile:///my%2Fproject/kakehashi-virtual-uri-<id>.lua. That string differs from the rendered identity, so goto/references results for the region are filtered out (transform_location_for_goto, Case 3).This predates the virtual-URI encoding work (#1093 and its follow-up). The follow-up keeps filename escapes byte-identical to main wherever main's output was valid, so it neither introduces nor fixes this gap.
Exact-string sites
src/lsp/bridge/protocol/response.rs—transform_location_for_goto,transform_location_link_for_gotosrc/lsp/bridge/protocol/workspace_edit.rs—changesre-keying anddocumentChangestext-document editssrc/lsp/bridge/text_document/call_hierarchy.rs— incoming/outgoing provenance (known_virtual_uris.contains_uri,request_virtual_uricompare), prepare itemssrc/lsp/bridge/text_document/type_hierarchy.rs— item provenancesrc/lsp/bridge/text_document/code_action.rs—workspace_edit_touches_foreign_regionsrc/lsp/bridge/text_document/document_symbol.rs,inlay_hint.rs— same-virtual-URI checkssrc/lsp/bridge/pool/document_tracker.rs—resolve_virtual_uri(showDocument, applyEdit, pushed diagnostics),VirtualUriObserverexplicit_uris/ provenance setsSuggested fix
Add one syntax-normalization helper (uppercase escape hex; decode escaped unreserved characters; leave reserved escapes distinct). Compare through it at the sites above, and normalize the keys of the identity sets on both insert and lookup. Keep the exact-match fast path.