fix(lsp): preserve execution-world URI semantics

This commit is contained in:
Tianyi Cui
2026-07-29 04:19:18 +08:00
parent 3537665806
commit 4997fb219e
24 changed files with 162 additions and 107 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/core-data-structures/lsp.md
lsp.md: 62b133cbfdf521e067c56355664d7514a613397f
lsp.zh.md: 51a19a51a8ad92e744cb920a51f3214f68ae0036
lsp.md: 03d0ce2dbe246aadb6f6c9a702fa50e3e792eb09
lsp.zh.md: ef9623f01124bc459d3bbceba340c3870e678baa

View File

@@ -73,7 +73,7 @@ interface LspProviderQuery extends LspQueryRequest {
## Result
A CLOSED discriminated union: navigation operations normalize to `locations`, `hover` to content or `null`. Consumers `switch` on `kind` to exhaustiveness so a new arm breaks compilation until handled. `findReferences` always includes declarations — the provider enforces this internally, so callers get no flag. The `locations` variant carries `resolvedWorkspaceRoot`: the provider's canonical form of the request's `workspaceRoot` and the root its `file:` URIs are relative to, so a caller relativizing display paths uses it rather than the possibly-symlinked request root.
A CLOSED discriminated union: navigation operations normalize to `locations`, `hover` to content or `null`. Consumers `switch` on `kind` to exhaustiveness so a new arm breaks compilation until handled. `findReferences` always includes declarations — the provider enforces this internally, so callers get no flag. The `locations` variant carries `resolvedWorkspaceUri`, the provider's canonical workspace `file:` URI. A caller relativizing location URIs uses that coordinate rather than applying host-platform path rules to the possibly-symlinked request root.
```ts type-equiv
/** One resolved location: a document URI and the range within it. */
@@ -101,13 +101,13 @@ interface LspHover {
* `goToImplementation`) normalize to `locations`; `hover` normalizes to content or `null`.
* Consumers `switch` on `kind` to exhaustiveness so a new arm breaks compilation until handled.
*
* The `locations` variant carries `resolvedWorkspaceRoot`: the provider's canonical form of the
* request's `workspaceRoot`, and the root its `file:` location URIs are relative to. A caller that
* relativizes display paths MUST use this, not the request's (possibly symlinked) `workspaceRoot`;
* otherwise a symlinked workspace misclassifies in-workspace results as external.
* The `locations` variant carries `resolvedWorkspaceUri`: the provider's canonical `file:` URI for
* the request's workspace root. A caller that relativizes location URIs MUST use this, not parse the
* request's possibly symlinked process path with host-platform rules; the execution platform may
* differ from the caller's.
*/
type LspQueryResult =
| { readonly kind: 'locations'; readonly locations: readonly LspLocation[]; readonly resolvedWorkspaceRoot: string }
| { readonly kind: 'locations'; readonly locations: readonly LspLocation[]; readonly resolvedWorkspaceUri: string }
| { readonly kind: 'hover'; readonly hover: LspHover | null }
```

View File

@@ -73,7 +73,7 @@ interface LspProviderQuery extends LspQueryRequest {
## 结果
这是一个闭合的可辨识联合:导航操作规范化为 `locations``hover` 规范化为内容或 `null`。消费方使用 `switch` 对 `kind` 做穷尽处理,因此新增分支会使编译失败,直到完成处理。`findReferences` 始终包含声明;提供方在内部强制保证这一点,因此调用方没有对应 flag。`locations` 变体携带 `resolvedWorkspaceRoot`,即提供方对请求中 `workspaceRoot` 的规范形式,也是其 `file:` URI 所相对的根目录;调用方相对化显示路径时应使用它,而不是可能经过符号链接的请求根目录。
这是一个闭合的可辨识联合:导航操作规范化为 `locations``hover` 规范化为内容或 `null`。消费方使用 `switch` 对 `kind` 做穷尽处理,因此新增分支会使编译失败,直到完成处理。`findReferences` 始终包含声明;提供方在内部强制保证这一点,因此调用方没有对应 flag。`locations` 变体携带 `resolvedWorkspaceUri`,即提供方的规范工作区 `file:` URI调用方相对化位置 URI 时应使用这一坐标,而不是可能经过符号链接的请求根目录应用宿主平台路径规则
```ts type-equiv
/** One resolved location: a document URI and the range within it. */
@@ -101,13 +101,13 @@ interface LspHover {
* `goToImplementation`) normalize to `locations`; `hover` normalizes to content or `null`.
* Consumers `switch` on `kind` to exhaustiveness so a new arm breaks compilation until handled.
*
* The `locations` variant carries `resolvedWorkspaceRoot`: the provider's canonical form of the
* request's `workspaceRoot`, and the root its `file:` location URIs are relative to. A caller that
* relativizes display paths MUST use this, not the request's (possibly symlinked) `workspaceRoot`;
* otherwise a symlinked workspace misclassifies in-workspace results as external.
* The `locations` variant carries `resolvedWorkspaceUri`: the provider's canonical `file:` URI for
* the request's workspace root. A caller that relativizes location URIs MUST use this, not parse the
* request's possibly symlinked process path with host-platform rules; the execution platform may
* differ from the caller's.
*/
type LspQueryResult =
| { readonly kind: 'locations'; readonly locations: readonly LspLocation[]; readonly resolvedWorkspaceRoot: string }
| { readonly kind: 'locations'; readonly locations: readonly LspLocation[]; readonly resolvedWorkspaceUri: string }
| { readonly kind: 'hover'; readonly hover: LspHover | null }
```