oh-my-opencode 5.0.0-beta.31 → 5.0.0-beta.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +136 -44
- package/dist/cli-node/index.js +136 -44
- package/dist/features/background-agent/parent-wake-notifier-types.d.ts +1 -1
- package/dist/features/background-agent/parent-wake-prompt-dispatch.d.ts +1 -1
- package/dist/features/background-agent/parent-wake-session-inspector.d.ts +1 -1
- package/dist/features/monitor/manager-internals.d.ts +1 -1
- package/dist/features/monitor/output-injector-types.d.ts +1 -1
- package/dist/features/team-mode/tools/messaging-live-delivery-recipient.d.ts +1 -0
- package/dist/features/team-mode/tools/messaging-runtime.d.ts +1 -0
- package/dist/hooks/anthropic-context-window-limit-recovery/tool-result-storage.d.ts +11 -0
- package/dist/index.js +286 -99
- package/dist/skills/ultimate-browsing/references/insane-search/README.md +9 -2
- package/dist/tools/session-manager/directory-filter.d.ts +2 -0
- package/dist/tui.js +109 -23
- package/package.json +16 -15
- package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +47 -19
- package/packages/lsp-core/src/lsp/client-diagnostics-pull-timeout.test.ts +64 -0
- package/packages/lsp-core/src/lsp/client.ts +6 -3
- package/packages/lsp-core/src/lsp/controlled-clock-test-support.ts +61 -0
- package/packages/lsp-core/src/lsp/fixtures/workspace-edit-server.mjs +10 -3
- package/packages/lsp-core/src/lsp/timer-provider.ts +13 -0
- package/packages/lsp-core/src/lsp/transport-request-timeout.test.ts +73 -0
- package/packages/lsp-core/src/lsp/transport.ts +7 -2
- package/packages/lsp-core/src/lsp/workspace-document-state.test.ts +84 -1
- package/packages/lsp-core/src/lsp/workspace-document-state.ts +30 -11
- package/packages/lsp-core/src/tools/parameters.test.ts +51 -0
- package/packages/lsp-daemon/dist/cli.js +41 -16
- package/packages/lsp-daemon/dist/client.js +41 -16
- package/packages/lsp-daemon/dist/index.js +41 -16
- package/packages/lsp-tools-mcp/dist/cli.js +41 -16
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +41 -16
- package/packages/lsp-tools-mcp/dist/mcp.js +41 -16
- package/packages/lsp-tools-mcp/dist/tools.js +41 -16
- package/packages/lsp-tools-mcp/package.json +1 -1
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +3 -17
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +3 -17
- package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +39 -16
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +5 -4
- package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +489 -4
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -2
- package/packages/omo-codex/plugin/components/ultrawork/scripts/sync-directive.mjs +30 -14
- package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +4 -0
- package/packages/omo-codex/plugin/components/ultrawork/src/directive.ts +5 -2
- package/packages/omo-codex/plugin/components/ultrawork/test/directive-source.test.ts +14 -8
- package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +12 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +4 -2
- package/packages/omo-codex/plugin/components/ulw-loop/README.md +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +9 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.d.ts +14 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +10 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.d.ts +8 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.js +113 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +7 -5
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +775 -312
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +18 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.d.ts +13 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +14 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +17 -9
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +17 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.d.ts +13 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.js +19 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.d.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.js +53 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.d.ts +9 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.js +85 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +41 -99
- package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.js +4 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +184 -14
- package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.d.ts +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.js +33 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +3 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +15 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +17 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +7 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +25 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-template.ts +127 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +8 -12
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +18 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +23 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +19 -9
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +18 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-missing-recovery.ts +27 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-aggregate.ts +57 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-artifacts.ts +103 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-fields.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +50 -116
- package/packages/omo-codex/plugin/components/ulw-loop/src/review-blockers.ts +4 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +186 -12
- package/packages/omo-codex/plugin/components/ulw-loop/src/status-next-actions.ts +36 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +22 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +66 -3
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-template.test.ts +92 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-status-next-actions.test.ts +183 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +13 -3
- package/packages/omo-codex/plugin/components/ulw-loop/test/guided-recovery.test.ts +105 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-aggregate.test.ts +101 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +16 -15
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-senpi-surface.test.ts +131 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate.test.ts +5 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +300 -3
- package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +9 -3
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/package-lock.json +13 -13
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +31 -2
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +9 -2
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +17 -0
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +11 -1
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +13 -0
- package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +5 -2
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +2 -2
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +9 -2
- package/dist/features/builtin-skills/index.d.ts +0 -1
- package/dist/features/builtin-skills/skill-file-loader.d.ts +0 -1
- package/dist/features/builtin-skills/skills/agent-browser-skill.d.ts +0 -1
- package/dist/features/builtin-skills/skills/agent-browser-template.d.ts +0 -1
- package/dist/features/builtin-skills/skills/debugging.d.ts +0 -1
- package/dist/features/builtin-skills/skills/dev-browser.d.ts +0 -1
- package/dist/features/builtin-skills/skills/frontend.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-sections/commit-atomic-planning.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-sections/commit-context-analysis.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-sections/commit-execution-verification.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-sections/commit-workflow.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-sections/history-search-workflow.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-sections/overview.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-sections/quick-reference.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-sections/rebase-workflow.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-skill-metadata.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master.d.ts +0 -1
- package/dist/features/builtin-skills/skills/index.d.ts +0 -1
- package/dist/features/builtin-skills/skills/init-deep.d.ts +0 -1
- package/dist/features/builtin-skills/skills/playwright-cli.d.ts +0 -1
- package/dist/features/builtin-skills/skills/playwright-mcp-skill.d.ts +0 -1
- package/dist/features/builtin-skills/skills/playwright.d.ts +0 -1
- package/dist/features/builtin-skills/skills/remove-ai-slops.d.ts +0 -1
- package/dist/features/builtin-skills/skills/review-work.d.ts +0 -1
- package/dist/features/builtin-skills/skills/security-research.d.ts +0 -1
- package/dist/features/builtin-skills/skills/security-review.d.ts +0 -1
- package/dist/features/builtin-skills/skills/team-mode.d.ts +0 -1
- package/dist/features/builtin-skills/skills/visual-qa.d.ts +0 -1
- package/dist/features/builtin-skills/skills.d.ts +0 -1
- package/dist/features/builtin-skills/types.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/agent-loader.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/command-loader.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/discovery-core.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/discovery-paths.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/discovery.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/hook-loader.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/index.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/install-path-resolver.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/installed-plugin-database.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/loaded-plugin.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/loader.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/mcp-server-loader.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/plugin-key.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/plugin-manifest.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/plugin-path-resolver.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/plugin-settings.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/scope-filter.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/skill-loader.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/types.d.ts +0 -1
- package/dist/shared/prompt-async-gate/message-inspection-error.d.ts +0 -1
- package/dist/shared/prompt-async-gate/pending-tool-turn.d.ts +0 -1
- package/dist/shared/prompt-async-gate/prompt-message-state.d.ts +0 -1
- package/dist/shared/prompt-async-gate/queue.d.ts +0 -1
- package/dist/shared/prompt-async-gate/recent-dispatches.d.ts +0 -1
- package/dist/shared/prompt-async-gate/reservations.d.ts +0 -1
- package/dist/shared/prompt-async-gate/semantic-dedupe.d.ts +0 -1
- package/dist/shared/prompt-async-gate/session-idle-dispatch.d.ts +0 -1
- package/dist/shared/prompt-async-gate/timing.d.ts +0 -1
- package/dist/shared/prompt-async-gate/types.d.ts +0 -1
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +0 -483
- package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +0 -490
|
@@ -1250,6 +1250,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
|
1250
1250
|
// ../lsp-core/src/lsp/connection.ts
|
|
1251
1251
|
import { pathToFileURL } from "node:url";
|
|
1252
1252
|
|
|
1253
|
+
// ../lsp-core/src/lsp/timer-provider.ts
|
|
1254
|
+
var realTimerProvider = {
|
|
1255
|
+
now: () => Date.now(),
|
|
1256
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
1257
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
1258
|
+
};
|
|
1259
|
+
|
|
1253
1260
|
// ../lsp-core/src/lsp/constants.ts
|
|
1254
1261
|
var DEFAULT_MAX_REFERENCES = 200;
|
|
1255
1262
|
var DEFAULT_MAX_SYMBOLS = 200;
|
|
@@ -1789,6 +1796,7 @@ class LspClientTransport {
|
|
|
1789
1796
|
this.documentFormattingSupported = false;
|
|
1790
1797
|
this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
1791
1798
|
this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
1799
|
+
this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
|
|
1792
1800
|
}
|
|
1793
1801
|
pid() {
|
|
1794
1802
|
return this.proc?.pid;
|
|
@@ -1889,7 +1897,7 @@ class LspClientTransport {
|
|
|
1889
1897
|
const options = args[1];
|
|
1890
1898
|
const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
|
|
1891
1899
|
const timeoutController = new AbortController;
|
|
1892
|
-
const timeoutHandle = setTimeout(() => {
|
|
1900
|
+
const timeoutHandle = this.timerProvider.setTimeout(() => {
|
|
1893
1901
|
const stderrTail = this.stderrBuffer.slice(-5).join(`
|
|
1894
1902
|
`);
|
|
1895
1903
|
timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
|
|
@@ -1908,7 +1916,7 @@ class LspClientTransport {
|
|
|
1908
1916
|
}
|
|
1909
1917
|
throw error;
|
|
1910
1918
|
} finally {
|
|
1911
|
-
clearTimeout(timeoutHandle);
|
|
1919
|
+
this.timerProvider.clearTimeout(timeoutHandle);
|
|
1912
1920
|
combinedSignal.dispose();
|
|
1913
1921
|
}
|
|
1914
1922
|
}
|
|
@@ -2289,6 +2297,17 @@ function canonicalPath(filePath) {
|
|
|
2289
2297
|
return absolute;
|
|
2290
2298
|
}
|
|
2291
2299
|
}
|
|
2300
|
+
function normalizeDocumentUri(uri) {
|
|
2301
|
+
let decoded = uri;
|
|
2302
|
+
try {
|
|
2303
|
+
decoded = decodeURIComponent(uri);
|
|
2304
|
+
} catch {
|
|
2305
|
+
decoded = uri;
|
|
2306
|
+
}
|
|
2307
|
+
if (process.platform !== "win32")
|
|
2308
|
+
return decoded;
|
|
2309
|
+
return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
|
|
2310
|
+
}
|
|
2292
2311
|
function isSameOrDescendant(candidate, parent) {
|
|
2293
2312
|
const suffix = relative2(parent, candidate);
|
|
2294
2313
|
return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
|
|
@@ -2305,7 +2324,12 @@ class WorkspaceDocumentState {
|
|
|
2305
2324
|
this.openDocuments = new Map;
|
|
2306
2325
|
this.openByUri = new Map;
|
|
2307
2326
|
this.openPromises = new Map;
|
|
2308
|
-
this.
|
|
2327
|
+
this.timerProvider = options.timerProvider ?? {
|
|
2328
|
+
now: options.now ?? (() => Date.now()),
|
|
2329
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
2330
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
2331
|
+
};
|
|
2332
|
+
this.now = () => this.timerProvider.now();
|
|
2309
2333
|
this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
|
|
2310
2334
|
}
|
|
2311
2335
|
async openFile(filePath) {
|
|
@@ -2327,7 +2351,7 @@ class WorkspaceDocumentState {
|
|
|
2327
2351
|
return this.openDocuments.get(canonicalPath(filePath))?.version;
|
|
2328
2352
|
}
|
|
2329
2353
|
getStoredDiagnostics(uri) {
|
|
2330
|
-
const state = this.openByUri.get(uri);
|
|
2354
|
+
const state = this.openByUri.get(normalizeDocumentUri(uri));
|
|
2331
2355
|
if (!state)
|
|
2332
2356
|
return [];
|
|
2333
2357
|
return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
|
|
@@ -2349,13 +2373,13 @@ class WorkspaceDocumentState {
|
|
|
2349
2373
|
return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
|
|
2350
2374
|
}
|
|
2351
2375
|
getPullCache(snapshot) {
|
|
2352
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
2376
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
2353
2377
|
if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
|
|
2354
2378
|
return null;
|
|
2355
2379
|
return state.pullCache;
|
|
2356
2380
|
}
|
|
2357
2381
|
recordPullDiagnostics(snapshot, report) {
|
|
2358
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
2382
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
2359
2383
|
if (!state)
|
|
2360
2384
|
return;
|
|
2361
2385
|
state.pullCache = {
|
|
@@ -2365,7 +2389,7 @@ class WorkspaceDocumentState {
|
|
|
2365
2389
|
};
|
|
2366
2390
|
}
|
|
2367
2391
|
recordPublishedDiagnostics(params) {
|
|
2368
|
-
const state = this.openByUri.get(params.uri);
|
|
2392
|
+
const state = this.openByUri.get(normalizeDocumentUri(params.uri));
|
|
2369
2393
|
if (!state)
|
|
2370
2394
|
return;
|
|
2371
2395
|
state.publishGeneration += 1;
|
|
@@ -2379,7 +2403,7 @@ class WorkspaceDocumentState {
|
|
|
2379
2403
|
this.notifyWaiters(state);
|
|
2380
2404
|
}
|
|
2381
2405
|
resolvePushDiagnostics(snapshot) {
|
|
2382
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
2406
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
2383
2407
|
if (!state?.lastPublish)
|
|
2384
2408
|
return { status: "missing" };
|
|
2385
2409
|
const publish = state.lastPublish;
|
|
@@ -2393,7 +2417,7 @@ class WorkspaceDocumentState {
|
|
|
2393
2417
|
return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
|
|
2394
2418
|
}
|
|
2395
2419
|
waitForDiagnosticsActivity(snapshot, timeoutMs) {
|
|
2396
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
2420
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
2397
2421
|
if (!state || timeoutMs <= 0)
|
|
2398
2422
|
return Promise.resolve();
|
|
2399
2423
|
return new Promise((resolveActivity) => {
|
|
@@ -2402,11 +2426,11 @@ class WorkspaceDocumentState {
|
|
|
2402
2426
|
if (settled)
|
|
2403
2427
|
return;
|
|
2404
2428
|
settled = true;
|
|
2405
|
-
clearTimeout(timer);
|
|
2429
|
+
this.timerProvider.clearTimeout(timer);
|
|
2406
2430
|
state.waiters.delete(finish);
|
|
2407
2431
|
resolveActivity();
|
|
2408
2432
|
};
|
|
2409
|
-
const timer = setTimeout(finish, timeoutMs);
|
|
2433
|
+
const timer = this.timerProvider.setTimeout(finish, timeoutMs);
|
|
2410
2434
|
if (typeof timer.unref === "function")
|
|
2411
2435
|
timer.unref();
|
|
2412
2436
|
state.waiters.add(finish);
|
|
@@ -2514,7 +2538,7 @@ class WorkspaceDocumentState {
|
|
|
2514
2538
|
waiters: new Set
|
|
2515
2539
|
};
|
|
2516
2540
|
this.openDocuments.set(path2, state);
|
|
2517
|
-
this.openByUri.set(state.uri, state);
|
|
2541
|
+
this.openByUri.set(normalizeDocumentUri(state.uri), state);
|
|
2518
2542
|
this.notifyWaiters(state);
|
|
2519
2543
|
await this.sendNotification("textDocument/didOpen", {
|
|
2520
2544
|
textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
|
|
@@ -2539,7 +2563,7 @@ class WorkspaceDocumentState {
|
|
|
2539
2563
|
}
|
|
2540
2564
|
async closeDocument(state) {
|
|
2541
2565
|
this.openDocuments.delete(state.path);
|
|
2542
|
-
this.openByUri.delete(state.uri);
|
|
2566
|
+
this.openByUri.delete(normalizeDocumentUri(state.uri));
|
|
2543
2567
|
this.clearDiagnostics(state.uri);
|
|
2544
2568
|
this.notifyWaiters(state);
|
|
2545
2569
|
await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
|
|
@@ -3626,6 +3650,7 @@ class LspClient extends LspClientConnection {
|
|
|
3626
3650
|
this.diagnosticPullErrors = [];
|
|
3627
3651
|
this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
|
|
3628
3652
|
this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
|
|
3653
|
+
timerProvider: this.timerProvider,
|
|
3629
3654
|
versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
|
|
3630
3655
|
});
|
|
3631
3656
|
this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
|
|
@@ -3729,7 +3754,7 @@ class LspClient extends LspClientConnection {
|
|
|
3729
3754
|
const absPath = this.resolveWorkspacePath(filePath);
|
|
3730
3755
|
const uri = pathToFileURL3(absPath).href;
|
|
3731
3756
|
await this.openFile(absPath);
|
|
3732
|
-
const deadlineAt =
|
|
3757
|
+
const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
|
|
3733
3758
|
for (;; ) {
|
|
3734
3759
|
signal?.throwIfAborted();
|
|
3735
3760
|
const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
|
|
@@ -3742,7 +3767,7 @@ class LspClient extends LspClientConnection {
|
|
|
3742
3767
|
if (!pushFallbackOnly) {
|
|
3743
3768
|
const cached = this.documents.getPullCache(snapshot);
|
|
3744
3769
|
try {
|
|
3745
|
-
const remainingMs2 = deadlineAt -
|
|
3770
|
+
const remainingMs2 = deadlineAt - this.timerProvider.now();
|
|
3746
3771
|
if (remainingMs2 <= 0)
|
|
3747
3772
|
return this.freshnessTimeout(absPath);
|
|
3748
3773
|
const result = await this.sendRequest("textDocument/diagnostic", {
|
|
@@ -3777,7 +3802,7 @@ class LspClient extends LspClientConnection {
|
|
|
3777
3802
|
}
|
|
3778
3803
|
if (!pushFallbackOnly)
|
|
3779
3804
|
continue;
|
|
3780
|
-
const remainingMs = deadlineAt -
|
|
3805
|
+
const remainingMs = deadlineAt - this.timerProvider.now();
|
|
3781
3806
|
if (remainingMs <= 0) {
|
|
3782
3807
|
if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
|
|
3783
3808
|
const cached = this.documents.getPullCache(snapshot);
|
|
@@ -15,6 +15,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
|
15
15
|
// ../lsp-core/src/lsp/connection.ts
|
|
16
16
|
import { pathToFileURL } from "node:url";
|
|
17
17
|
|
|
18
|
+
// ../lsp-core/src/lsp/timer-provider.ts
|
|
19
|
+
var realTimerProvider = {
|
|
20
|
+
now: () => Date.now(),
|
|
21
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
22
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
23
|
+
};
|
|
24
|
+
|
|
18
25
|
// ../lsp-core/src/lsp/constants.ts
|
|
19
26
|
var DEFAULT_MAX_REFERENCES = 200;
|
|
20
27
|
var DEFAULT_MAX_SYMBOLS = 200;
|
|
@@ -631,6 +638,7 @@ class LspClientTransport {
|
|
|
631
638
|
this.documentFormattingSupported = false;
|
|
632
639
|
this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
633
640
|
this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
641
|
+
this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
|
|
634
642
|
}
|
|
635
643
|
pid() {
|
|
636
644
|
return this.proc?.pid;
|
|
@@ -731,7 +739,7 @@ class LspClientTransport {
|
|
|
731
739
|
const options = args[1];
|
|
732
740
|
const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
|
|
733
741
|
const timeoutController = new AbortController;
|
|
734
|
-
const timeoutHandle = setTimeout(() => {
|
|
742
|
+
const timeoutHandle = this.timerProvider.setTimeout(() => {
|
|
735
743
|
const stderrTail = this.stderrBuffer.slice(-5).join(`
|
|
736
744
|
`);
|
|
737
745
|
timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
|
|
@@ -750,7 +758,7 @@ class LspClientTransport {
|
|
|
750
758
|
}
|
|
751
759
|
throw error;
|
|
752
760
|
} finally {
|
|
753
|
-
clearTimeout(timeoutHandle);
|
|
761
|
+
this.timerProvider.clearTimeout(timeoutHandle);
|
|
754
762
|
combinedSignal.dispose();
|
|
755
763
|
}
|
|
756
764
|
}
|
|
@@ -1141,6 +1149,17 @@ function canonicalPath(filePath) {
|
|
|
1141
1149
|
return absolute;
|
|
1142
1150
|
}
|
|
1143
1151
|
}
|
|
1152
|
+
function normalizeDocumentUri(uri) {
|
|
1153
|
+
let decoded = uri;
|
|
1154
|
+
try {
|
|
1155
|
+
decoded = decodeURIComponent(uri);
|
|
1156
|
+
} catch {
|
|
1157
|
+
decoded = uri;
|
|
1158
|
+
}
|
|
1159
|
+
if (process.platform !== "win32")
|
|
1160
|
+
return decoded;
|
|
1161
|
+
return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
|
|
1162
|
+
}
|
|
1144
1163
|
function isSameOrDescendant(candidate, parent) {
|
|
1145
1164
|
const suffix = relative(parent, candidate);
|
|
1146
1165
|
return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
|
|
@@ -1157,7 +1176,12 @@ class WorkspaceDocumentState {
|
|
|
1157
1176
|
this.openDocuments = new Map;
|
|
1158
1177
|
this.openByUri = new Map;
|
|
1159
1178
|
this.openPromises = new Map;
|
|
1160
|
-
this.
|
|
1179
|
+
this.timerProvider = options.timerProvider ?? {
|
|
1180
|
+
now: options.now ?? (() => Date.now()),
|
|
1181
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
1182
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
1183
|
+
};
|
|
1184
|
+
this.now = () => this.timerProvider.now();
|
|
1161
1185
|
this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
|
|
1162
1186
|
}
|
|
1163
1187
|
async openFile(filePath) {
|
|
@@ -1179,7 +1203,7 @@ class WorkspaceDocumentState {
|
|
|
1179
1203
|
return this.openDocuments.get(canonicalPath(filePath))?.version;
|
|
1180
1204
|
}
|
|
1181
1205
|
getStoredDiagnostics(uri) {
|
|
1182
|
-
const state = this.openByUri.get(uri);
|
|
1206
|
+
const state = this.openByUri.get(normalizeDocumentUri(uri));
|
|
1183
1207
|
if (!state)
|
|
1184
1208
|
return [];
|
|
1185
1209
|
return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
|
|
@@ -1201,13 +1225,13 @@ class WorkspaceDocumentState {
|
|
|
1201
1225
|
return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
|
|
1202
1226
|
}
|
|
1203
1227
|
getPullCache(snapshot) {
|
|
1204
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1228
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1205
1229
|
if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
|
|
1206
1230
|
return null;
|
|
1207
1231
|
return state.pullCache;
|
|
1208
1232
|
}
|
|
1209
1233
|
recordPullDiagnostics(snapshot, report) {
|
|
1210
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1234
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1211
1235
|
if (!state)
|
|
1212
1236
|
return;
|
|
1213
1237
|
state.pullCache = {
|
|
@@ -1217,7 +1241,7 @@ class WorkspaceDocumentState {
|
|
|
1217
1241
|
};
|
|
1218
1242
|
}
|
|
1219
1243
|
recordPublishedDiagnostics(params) {
|
|
1220
|
-
const state = this.openByUri.get(params.uri);
|
|
1244
|
+
const state = this.openByUri.get(normalizeDocumentUri(params.uri));
|
|
1221
1245
|
if (!state)
|
|
1222
1246
|
return;
|
|
1223
1247
|
state.publishGeneration += 1;
|
|
@@ -1231,7 +1255,7 @@ class WorkspaceDocumentState {
|
|
|
1231
1255
|
this.notifyWaiters(state);
|
|
1232
1256
|
}
|
|
1233
1257
|
resolvePushDiagnostics(snapshot) {
|
|
1234
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1258
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1235
1259
|
if (!state?.lastPublish)
|
|
1236
1260
|
return { status: "missing" };
|
|
1237
1261
|
const publish = state.lastPublish;
|
|
@@ -1245,7 +1269,7 @@ class WorkspaceDocumentState {
|
|
|
1245
1269
|
return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
|
|
1246
1270
|
}
|
|
1247
1271
|
waitForDiagnosticsActivity(snapshot, timeoutMs) {
|
|
1248
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1272
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1249
1273
|
if (!state || timeoutMs <= 0)
|
|
1250
1274
|
return Promise.resolve();
|
|
1251
1275
|
return new Promise((resolveActivity) => {
|
|
@@ -1254,11 +1278,11 @@ class WorkspaceDocumentState {
|
|
|
1254
1278
|
if (settled)
|
|
1255
1279
|
return;
|
|
1256
1280
|
settled = true;
|
|
1257
|
-
clearTimeout(timer);
|
|
1281
|
+
this.timerProvider.clearTimeout(timer);
|
|
1258
1282
|
state.waiters.delete(finish);
|
|
1259
1283
|
resolveActivity();
|
|
1260
1284
|
};
|
|
1261
|
-
const timer = setTimeout(finish, timeoutMs);
|
|
1285
|
+
const timer = this.timerProvider.setTimeout(finish, timeoutMs);
|
|
1262
1286
|
if (typeof timer.unref === "function")
|
|
1263
1287
|
timer.unref();
|
|
1264
1288
|
state.waiters.add(finish);
|
|
@@ -1366,7 +1390,7 @@ class WorkspaceDocumentState {
|
|
|
1366
1390
|
waiters: new Set
|
|
1367
1391
|
};
|
|
1368
1392
|
this.openDocuments.set(path, state);
|
|
1369
|
-
this.openByUri.set(state.uri, state);
|
|
1393
|
+
this.openByUri.set(normalizeDocumentUri(state.uri), state);
|
|
1370
1394
|
this.notifyWaiters(state);
|
|
1371
1395
|
await this.sendNotification("textDocument/didOpen", {
|
|
1372
1396
|
textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
|
|
@@ -1391,7 +1415,7 @@ class WorkspaceDocumentState {
|
|
|
1391
1415
|
}
|
|
1392
1416
|
async closeDocument(state) {
|
|
1393
1417
|
this.openDocuments.delete(state.path);
|
|
1394
|
-
this.openByUri.delete(state.uri);
|
|
1418
|
+
this.openByUri.delete(normalizeDocumentUri(state.uri));
|
|
1395
1419
|
this.clearDiagnostics(state.uri);
|
|
1396
1420
|
this.notifyWaiters(state);
|
|
1397
1421
|
await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
|
|
@@ -2478,6 +2502,7 @@ class LspClient extends LspClientConnection {
|
|
|
2478
2502
|
this.diagnosticPullErrors = [];
|
|
2479
2503
|
this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
|
|
2480
2504
|
this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
|
|
2505
|
+
timerProvider: this.timerProvider,
|
|
2481
2506
|
versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
|
|
2482
2507
|
});
|
|
2483
2508
|
this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
|
|
@@ -2581,7 +2606,7 @@ class LspClient extends LspClientConnection {
|
|
|
2581
2606
|
const absPath = this.resolveWorkspacePath(filePath);
|
|
2582
2607
|
const uri = pathToFileURL3(absPath).href;
|
|
2583
2608
|
await this.openFile(absPath);
|
|
2584
|
-
const deadlineAt =
|
|
2609
|
+
const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
|
|
2585
2610
|
for (;; ) {
|
|
2586
2611
|
signal?.throwIfAborted();
|
|
2587
2612
|
const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
|
|
@@ -2594,7 +2619,7 @@ class LspClient extends LspClientConnection {
|
|
|
2594
2619
|
if (!pushFallbackOnly) {
|
|
2595
2620
|
const cached = this.documents.getPullCache(snapshot);
|
|
2596
2621
|
try {
|
|
2597
|
-
const remainingMs2 = deadlineAt -
|
|
2622
|
+
const remainingMs2 = deadlineAt - this.timerProvider.now();
|
|
2598
2623
|
if (remainingMs2 <= 0)
|
|
2599
2624
|
return this.freshnessTimeout(absPath);
|
|
2600
2625
|
const result = await this.sendRequest("textDocument/diagnostic", {
|
|
@@ -2629,7 +2654,7 @@ class LspClient extends LspClientConnection {
|
|
|
2629
2654
|
}
|
|
2630
2655
|
if (!pushFallbackOnly)
|
|
2631
2656
|
continue;
|
|
2632
|
-
const remainingMs = deadlineAt -
|
|
2657
|
+
const remainingMs = deadlineAt - this.timerProvider.now();
|
|
2633
2658
|
if (remainingMs <= 0) {
|
|
2634
2659
|
if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
|
|
2635
2660
|
const cached = this.documents.getPullCache(snapshot);
|
|
@@ -17,6 +17,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
|
17
17
|
// ../lsp-core/src/lsp/connection.ts
|
|
18
18
|
import { pathToFileURL } from "node:url";
|
|
19
19
|
|
|
20
|
+
// ../lsp-core/src/lsp/timer-provider.ts
|
|
21
|
+
var realTimerProvider = {
|
|
22
|
+
now: () => Date.now(),
|
|
23
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
24
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
25
|
+
};
|
|
26
|
+
|
|
20
27
|
// ../lsp-core/src/lsp/constants.ts
|
|
21
28
|
var DEFAULT_MAX_REFERENCES = 200;
|
|
22
29
|
var DEFAULT_MAX_SYMBOLS = 200;
|
|
@@ -633,6 +640,7 @@ class LspClientTransport {
|
|
|
633
640
|
this.documentFormattingSupported = false;
|
|
634
641
|
this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
635
642
|
this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
643
|
+
this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
|
|
636
644
|
}
|
|
637
645
|
pid() {
|
|
638
646
|
return this.proc?.pid;
|
|
@@ -733,7 +741,7 @@ class LspClientTransport {
|
|
|
733
741
|
const options = args[1];
|
|
734
742
|
const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
|
|
735
743
|
const timeoutController = new AbortController;
|
|
736
|
-
const timeoutHandle = setTimeout(() => {
|
|
744
|
+
const timeoutHandle = this.timerProvider.setTimeout(() => {
|
|
737
745
|
const stderrTail = this.stderrBuffer.slice(-5).join(`
|
|
738
746
|
`);
|
|
739
747
|
timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
|
|
@@ -752,7 +760,7 @@ class LspClientTransport {
|
|
|
752
760
|
}
|
|
753
761
|
throw error;
|
|
754
762
|
} finally {
|
|
755
|
-
clearTimeout(timeoutHandle);
|
|
763
|
+
this.timerProvider.clearTimeout(timeoutHandle);
|
|
756
764
|
combinedSignal.dispose();
|
|
757
765
|
}
|
|
758
766
|
}
|
|
@@ -1143,6 +1151,17 @@ function canonicalPath(filePath) {
|
|
|
1143
1151
|
return absolute;
|
|
1144
1152
|
}
|
|
1145
1153
|
}
|
|
1154
|
+
function normalizeDocumentUri(uri) {
|
|
1155
|
+
let decoded = uri;
|
|
1156
|
+
try {
|
|
1157
|
+
decoded = decodeURIComponent(uri);
|
|
1158
|
+
} catch {
|
|
1159
|
+
decoded = uri;
|
|
1160
|
+
}
|
|
1161
|
+
if (process.platform !== "win32")
|
|
1162
|
+
return decoded;
|
|
1163
|
+
return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
|
|
1164
|
+
}
|
|
1146
1165
|
function isSameOrDescendant(candidate, parent) {
|
|
1147
1166
|
const suffix = relative(parent, candidate);
|
|
1148
1167
|
return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
|
|
@@ -1159,7 +1178,12 @@ class WorkspaceDocumentState {
|
|
|
1159
1178
|
this.openDocuments = new Map;
|
|
1160
1179
|
this.openByUri = new Map;
|
|
1161
1180
|
this.openPromises = new Map;
|
|
1162
|
-
this.
|
|
1181
|
+
this.timerProvider = options.timerProvider ?? {
|
|
1182
|
+
now: options.now ?? (() => Date.now()),
|
|
1183
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
1184
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
1185
|
+
};
|
|
1186
|
+
this.now = () => this.timerProvider.now();
|
|
1163
1187
|
this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
|
|
1164
1188
|
}
|
|
1165
1189
|
async openFile(filePath) {
|
|
@@ -1181,7 +1205,7 @@ class WorkspaceDocumentState {
|
|
|
1181
1205
|
return this.openDocuments.get(canonicalPath(filePath))?.version;
|
|
1182
1206
|
}
|
|
1183
1207
|
getStoredDiagnostics(uri) {
|
|
1184
|
-
const state = this.openByUri.get(uri);
|
|
1208
|
+
const state = this.openByUri.get(normalizeDocumentUri(uri));
|
|
1185
1209
|
if (!state)
|
|
1186
1210
|
return [];
|
|
1187
1211
|
return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
|
|
@@ -1203,13 +1227,13 @@ class WorkspaceDocumentState {
|
|
|
1203
1227
|
return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
|
|
1204
1228
|
}
|
|
1205
1229
|
getPullCache(snapshot) {
|
|
1206
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1230
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1207
1231
|
if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
|
|
1208
1232
|
return null;
|
|
1209
1233
|
return state.pullCache;
|
|
1210
1234
|
}
|
|
1211
1235
|
recordPullDiagnostics(snapshot, report) {
|
|
1212
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1236
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1213
1237
|
if (!state)
|
|
1214
1238
|
return;
|
|
1215
1239
|
state.pullCache = {
|
|
@@ -1219,7 +1243,7 @@ class WorkspaceDocumentState {
|
|
|
1219
1243
|
};
|
|
1220
1244
|
}
|
|
1221
1245
|
recordPublishedDiagnostics(params) {
|
|
1222
|
-
const state = this.openByUri.get(params.uri);
|
|
1246
|
+
const state = this.openByUri.get(normalizeDocumentUri(params.uri));
|
|
1223
1247
|
if (!state)
|
|
1224
1248
|
return;
|
|
1225
1249
|
state.publishGeneration += 1;
|
|
@@ -1233,7 +1257,7 @@ class WorkspaceDocumentState {
|
|
|
1233
1257
|
this.notifyWaiters(state);
|
|
1234
1258
|
}
|
|
1235
1259
|
resolvePushDiagnostics(snapshot) {
|
|
1236
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1260
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1237
1261
|
if (!state?.lastPublish)
|
|
1238
1262
|
return { status: "missing" };
|
|
1239
1263
|
const publish = state.lastPublish;
|
|
@@ -1247,7 +1271,7 @@ class WorkspaceDocumentState {
|
|
|
1247
1271
|
return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
|
|
1248
1272
|
}
|
|
1249
1273
|
waitForDiagnosticsActivity(snapshot, timeoutMs) {
|
|
1250
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1274
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1251
1275
|
if (!state || timeoutMs <= 0)
|
|
1252
1276
|
return Promise.resolve();
|
|
1253
1277
|
return new Promise((resolveActivity) => {
|
|
@@ -1256,11 +1280,11 @@ class WorkspaceDocumentState {
|
|
|
1256
1280
|
if (settled)
|
|
1257
1281
|
return;
|
|
1258
1282
|
settled = true;
|
|
1259
|
-
clearTimeout(timer);
|
|
1283
|
+
this.timerProvider.clearTimeout(timer);
|
|
1260
1284
|
state.waiters.delete(finish);
|
|
1261
1285
|
resolveActivity();
|
|
1262
1286
|
};
|
|
1263
|
-
const timer = setTimeout(finish, timeoutMs);
|
|
1287
|
+
const timer = this.timerProvider.setTimeout(finish, timeoutMs);
|
|
1264
1288
|
if (typeof timer.unref === "function")
|
|
1265
1289
|
timer.unref();
|
|
1266
1290
|
state.waiters.add(finish);
|
|
@@ -1368,7 +1392,7 @@ class WorkspaceDocumentState {
|
|
|
1368
1392
|
waiters: new Set
|
|
1369
1393
|
};
|
|
1370
1394
|
this.openDocuments.set(path, state);
|
|
1371
|
-
this.openByUri.set(state.uri, state);
|
|
1395
|
+
this.openByUri.set(normalizeDocumentUri(state.uri), state);
|
|
1372
1396
|
this.notifyWaiters(state);
|
|
1373
1397
|
await this.sendNotification("textDocument/didOpen", {
|
|
1374
1398
|
textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
|
|
@@ -1393,7 +1417,7 @@ class WorkspaceDocumentState {
|
|
|
1393
1417
|
}
|
|
1394
1418
|
async closeDocument(state) {
|
|
1395
1419
|
this.openDocuments.delete(state.path);
|
|
1396
|
-
this.openByUri.delete(state.uri);
|
|
1420
|
+
this.openByUri.delete(normalizeDocumentUri(state.uri));
|
|
1397
1421
|
this.clearDiagnostics(state.uri);
|
|
1398
1422
|
this.notifyWaiters(state);
|
|
1399
1423
|
await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
|
|
@@ -2480,6 +2504,7 @@ class LspClient extends LspClientConnection {
|
|
|
2480
2504
|
this.diagnosticPullErrors = [];
|
|
2481
2505
|
this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
|
|
2482
2506
|
this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
|
|
2507
|
+
timerProvider: this.timerProvider,
|
|
2483
2508
|
versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
|
|
2484
2509
|
});
|
|
2485
2510
|
this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
|
|
@@ -2583,7 +2608,7 @@ class LspClient extends LspClientConnection {
|
|
|
2583
2608
|
const absPath = this.resolveWorkspacePath(filePath);
|
|
2584
2609
|
const uri = pathToFileURL3(absPath).href;
|
|
2585
2610
|
await this.openFile(absPath);
|
|
2586
|
-
const deadlineAt =
|
|
2611
|
+
const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
|
|
2587
2612
|
for (;; ) {
|
|
2588
2613
|
signal?.throwIfAborted();
|
|
2589
2614
|
const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
|
|
@@ -2596,7 +2621,7 @@ class LspClient extends LspClientConnection {
|
|
|
2596
2621
|
if (!pushFallbackOnly) {
|
|
2597
2622
|
const cached = this.documents.getPullCache(snapshot);
|
|
2598
2623
|
try {
|
|
2599
|
-
const remainingMs2 = deadlineAt -
|
|
2624
|
+
const remainingMs2 = deadlineAt - this.timerProvider.now();
|
|
2600
2625
|
if (remainingMs2 <= 0)
|
|
2601
2626
|
return this.freshnessTimeout(absPath);
|
|
2602
2627
|
const result = await this.sendRequest("textDocument/diagnostic", {
|
|
@@ -2631,7 +2656,7 @@ class LspClient extends LspClientConnection {
|
|
|
2631
2656
|
}
|
|
2632
2657
|
if (!pushFallbackOnly)
|
|
2633
2658
|
continue;
|
|
2634
|
-
const remainingMs = deadlineAt -
|
|
2659
|
+
const remainingMs = deadlineAt - this.timerProvider.now();
|
|
2635
2660
|
if (remainingMs <= 0) {
|
|
2636
2661
|
if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
|
|
2637
2662
|
const cached = this.documents.getPullCache(snapshot);
|