@orkestrel/probe 0.0.6 → 0.0.8
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/src/core/index.cjs +12 -4
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +24 -8
- package/dist/src/core/index.d.ts +24 -8
- package/dist/src/core/index.js +12 -4
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +139 -288
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +80 -24
- package/dist/src/server/index.d.ts +80 -24
- package/dist/src/server/index.js +141 -289
- package/dist/src/server/index.js.map +1 -1
- package/package.json +5 -4
|
@@ -9,7 +9,8 @@ let _src_core = require("../core/index.cjs");
|
|
|
9
9
|
let _orkestrel_emitter = require("@orkestrel/emitter");
|
|
10
10
|
let _orkestrel_queue = require("@orkestrel/queue");
|
|
11
11
|
let _orkestrel_timeout = require("@orkestrel/timeout");
|
|
12
|
-
let
|
|
12
|
+
let _orkestrel_lsp = require("@orkestrel/lsp");
|
|
13
|
+
let _orkestrel_lsp_server = require("@orkestrel/lsp/server");
|
|
13
14
|
let node_stream = require("node:stream");
|
|
14
15
|
let node_timers_promises = require("node:timers/promises");
|
|
15
16
|
let _orkestrel_mcp = require("@orkestrel/mcp");
|
|
@@ -114,12 +115,18 @@ function resolveWorkspaceFile(workspace, target, mutate = false) {
|
|
|
114
115
|
* A containment walk and the write that follows it are separate calls, so a process that swaps the
|
|
115
116
|
* final component between them decides where the bytes land. `writeFileSync` opens with the default
|
|
116
117
|
* `w` flag, which follows a symbolic link at that component and creates the file when it is absent,
|
|
117
|
-
* so the walk's reading does not bind the write. Opening `O_WRONLY |
|
|
118
|
-
*
|
|
118
|
+
* so the walk's reading does not bind the write. Opening `O_WRONLY | O_NOFOLLOW` moves that
|
|
119
|
+
* decision into the call that writes: a link at the final component refuses the open, and the
|
|
119
120
|
* omitted `O_CREAT` fails `ENOENT` for a target that has gone since the walk saw it. This is the
|
|
120
121
|
* mutating counterpart of the `wx` flag every create in this package uses. Which code the refusal
|
|
121
122
|
* carries is the host's; Linux with Node v22.22.2 reported `ELOOP` on 2026-08-24.
|
|
122
123
|
*
|
|
124
|
+
* Truncation runs through the held descriptor rather than through an `O_TRUNC` flag, so it reaches
|
|
125
|
+
* the file the open bound. A Windows host refuses the numeric `O_TRUNC` without `O_CREAT` outright:
|
|
126
|
+
* measured on 2026-08-26 on Windows 11 with Node v24.19.0 over NTFS, `openSync` reported `EINVAL`
|
|
127
|
+
* for `O_WRONLY | O_TRUNC` and for `O_RDWR | O_TRUNC` while `O_WRONLY` alone opened, and adding
|
|
128
|
+
* `O_CREAT` would trade that refusal for the create this function must never perform.
|
|
129
|
+
*
|
|
123
130
|
* A directory component stays open, because Node exposes no descriptor-relative call to walk and
|
|
124
131
|
* write through one set of descriptors. Where a host's Node build defines no `O_NOFOLLOW`, that flag
|
|
125
132
|
* contributes nothing to the flag set and the final component is open on that host too.
|
|
@@ -139,8 +146,9 @@ function resolveWorkspaceFile(workspace, target, mutate = false) {
|
|
|
139
146
|
* ```
|
|
140
147
|
*/
|
|
141
148
|
function overwriteFile(file, text) {
|
|
142
|
-
const descriptor = (0, node_fs.openSync)(file, node_fs.constants.O_WRONLY | node_fs.constants.
|
|
149
|
+
const descriptor = (0, node_fs.openSync)(file, node_fs.constants.O_WRONLY | node_fs.constants.O_NOFOLLOW);
|
|
143
150
|
try {
|
|
151
|
+
(0, node_fs.ftruncateSync)(descriptor, 0);
|
|
144
152
|
(0, node_fs.writeFileSync)(descriptor, text, "utf8");
|
|
145
153
|
} finally {
|
|
146
154
|
(0, node_fs.closeSync)(descriptor);
|
|
@@ -515,24 +523,6 @@ function matchesWorkspaceModule(path) {
|
|
|
515
523
|
return /\.(?:[cm]?[jt]sx?|vue|json)$/.test(path);
|
|
516
524
|
}
|
|
517
525
|
/**
|
|
518
|
-
* Reads a JSON-RPC frame's declared byte length.
|
|
519
|
-
*
|
|
520
|
-
* @param header - The frame header text without its terminating empty line
|
|
521
|
-
* @returns The non-negative content length, or `undefined` for an invalid header
|
|
522
|
-
*
|
|
523
|
-
* @example
|
|
524
|
-
* ```ts
|
|
525
|
-
* parseContentLength('Content-Length: 128') // 128
|
|
526
|
-
* parseContentLength('Content-Type: application/json') // undefined
|
|
527
|
-
* ```
|
|
528
|
-
*/
|
|
529
|
-
function parseContentLength(header) {
|
|
530
|
-
const text = /(?:^|\r\n)Content-Length:\s*(\d+)(?:\r\n|$)/i.exec(header)?.[1];
|
|
531
|
-
if (text === void 0) return void 0;
|
|
532
|
-
const length = Number.parseInt(text, 10);
|
|
533
|
-
return Number.isSafeInteger(length) && length >= 0 ? length : void 0;
|
|
534
|
-
}
|
|
535
|
-
/**
|
|
536
526
|
* Normalizes a caught or foreign error into readable text.
|
|
537
527
|
*
|
|
538
528
|
* @param value - The value to describe
|
|
@@ -806,7 +796,7 @@ var Overlay = class {
|
|
|
806
796
|
};
|
|
807
797
|
//#endregion
|
|
808
798
|
//#region package.json
|
|
809
|
-
var version = "0.0.
|
|
799
|
+
var version = "0.0.8";
|
|
810
800
|
var peerDependencies = {
|
|
811
801
|
"oxlint": "^1.77.0",
|
|
812
802
|
"typescript": "^6.0.0",
|
|
@@ -818,13 +808,22 @@ var peerDependencies = {
|
|
|
818
808
|
* Inspects virtual documents through one resident Oxlint language server.
|
|
819
809
|
*
|
|
820
810
|
* @remarks
|
|
821
|
-
* Construction starts the target workspace's Oxlint binary with its Language Server Protocol
|
|
822
|
-
*
|
|
823
|
-
*
|
|
811
|
+
* Construction starts the target workspace's Oxlint binary with its Language Server Protocol mode
|
|
812
|
+
* and hands the conversation to `@orkestrel/lsp`: `createStdioTransport` owns the child process and
|
|
813
|
+
* its bytes, and `createLSPClient` owns the framing, the request correlation, the capabilities this
|
|
814
|
+
* stage advertises, and the choice between pulled and pushed diagnostics. This stage owns the
|
|
815
|
+
* workspace, the candidate identity, and the projection from a diagnostic to an `Issue`.
|
|
816
|
+
*
|
|
817
|
+
* Each inspection opens the supplied text by URI, waits for the client's diagnostics, and closes the
|
|
818
|
+
* document without writing it to disk. The caller's own signal is what bounds that wait, so a server
|
|
819
|
+
* that admits a document and publishes nothing refuses the inspection when the caller's bound
|
|
820
|
+
* expires rather than holding it for the life of the process. This stage mints no bound of its own
|
|
821
|
+
* for the wait: a second one would race the caller's, and the answer would depend on scheduling.
|
|
824
822
|
*
|
|
825
823
|
* Teardown is bounded at both ends. Warming waits for the server's `initialize` response and the
|
|
826
|
-
* ending waits for its `shutdown` reply, and the protocol leaves both answers to the server, so
|
|
827
|
-
*
|
|
824
|
+
* ending waits for its `shutdown` reply, and the protocol leaves both answers to the server, so the
|
|
825
|
+
* client's deadline bounds each exchange and the transport's cooperative window takes the ending
|
|
826
|
+
* back with a signal when that window passes.
|
|
828
827
|
*
|
|
829
828
|
* The URI is the path the candidate declared, so the candidate receives exactly the rule set the
|
|
830
829
|
* workspace's own lint gate applies to that path, including an override anchored to one directory,
|
|
@@ -837,24 +836,20 @@ var peerDependencies = {
|
|
|
837
836
|
* @example
|
|
838
837
|
* ```ts
|
|
839
838
|
* const stage = new LintStage('/srv/checkout')
|
|
840
|
-
* const check = await stage.inspect(subject)
|
|
839
|
+
* const check = await stage.inspect(subject, { signal: AbortSignal.timeout(30_000) })
|
|
841
840
|
* await stage.destroy()
|
|
842
841
|
* ```
|
|
843
842
|
*/
|
|
844
843
|
var LintStage = class {
|
|
845
844
|
#workspace;
|
|
846
845
|
#deadline = 2e3;
|
|
846
|
+
#documents = /* @__PURE__ */ new Set();
|
|
847
847
|
#warmth;
|
|
848
|
-
#
|
|
849
|
-
#
|
|
850
|
-
#documents = /* @__PURE__ */ new Map();
|
|
851
|
-
#publishes = /* @__PURE__ */ new Map();
|
|
852
|
-
#refusals = /* @__PURE__ */ new Map();
|
|
853
|
-
#child;
|
|
854
|
-
#buffer = Buffer.alloc(0);
|
|
855
|
-
#sequence = 0;
|
|
848
|
+
#client;
|
|
849
|
+
#ending;
|
|
856
850
|
#closing;
|
|
857
851
|
#progress = 0;
|
|
852
|
+
#revision = 0;
|
|
858
853
|
#destroyed = false;
|
|
859
854
|
/**
|
|
860
855
|
* Starts warming the target workspace's Oxlint language server.
|
|
@@ -872,8 +867,8 @@ var LintStage = class {
|
|
|
872
867
|
get progress() {
|
|
873
868
|
return this.#progress;
|
|
874
869
|
}
|
|
875
|
-
inspect(subject) {
|
|
876
|
-
return guardStage(this.stage, this.#inspect(subject));
|
|
870
|
+
inspect(subject, options) {
|
|
871
|
+
return guardStage(this.stage, this.#inspect(subject, options));
|
|
877
872
|
}
|
|
878
873
|
destroy() {
|
|
879
874
|
if (this.#closing !== void 0) return this.#closing;
|
|
@@ -881,13 +876,18 @@ var LintStage = class {
|
|
|
881
876
|
this.#closing = guardStage(this.stage, this.#destroy());
|
|
882
877
|
return this.#closing;
|
|
883
878
|
}
|
|
884
|
-
async #inspect(subject) {
|
|
879
|
+
async #inspect(subject, options) {
|
|
885
880
|
if (this.#destroyed) throw (0, _src_core.createDestroyedError)("lint stage");
|
|
881
|
+
if (options === void 0) throw new _src_core.ProbeError("The lint stage inspects only under a bound its caller supplies", {
|
|
882
|
+
origin: "claimant",
|
|
883
|
+
code: "refused",
|
|
884
|
+
context: { stage: this.stage }
|
|
885
|
+
});
|
|
886
886
|
const started = performance.now();
|
|
887
|
-
await this.#
|
|
887
|
+
const client = await this.#warmed();
|
|
888
888
|
if (this.#destroyed) throw (0, _src_core.createDestroyedError)("lint stage");
|
|
889
889
|
const issues = [];
|
|
890
|
-
for (const draft of [...subject.files, subject.test]) issues.push(...await this.#document(draft));
|
|
890
|
+
for (const draft of [...subject.files, subject.test]) issues.push(...await this.#document(client, draft, options.signal));
|
|
891
891
|
return {
|
|
892
892
|
stage: this.stage,
|
|
893
893
|
elapsed: Math.round(performance.now() - started),
|
|
@@ -895,118 +895,86 @@ var LintStage = class {
|
|
|
895
895
|
};
|
|
896
896
|
}
|
|
897
897
|
async #destroy() {
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
const
|
|
902
|
-
|
|
903
|
-
|
|
898
|
+
await this.#client?.destroy();
|
|
899
|
+
}
|
|
900
|
+
async #warm() {
|
|
901
|
+
const binary = resolveWorkspaceBinary(this.#workspace, "oxlint");
|
|
902
|
+
const client = (0, _orkestrel_lsp.createLSPClient)({
|
|
903
|
+
transport: (0, _orkestrel_lsp_server.createStdioTransport)({
|
|
904
|
+
server: {
|
|
905
|
+
command: [
|
|
906
|
+
process.execPath,
|
|
907
|
+
binary,
|
|
908
|
+
"--lsp"
|
|
909
|
+
],
|
|
910
|
+
directory: this.#workspace
|
|
911
|
+
},
|
|
912
|
+
grace: this.#deadline / 2
|
|
913
|
+
}),
|
|
914
|
+
workspace: (0, node_url.pathToFileURL)(this.#workspace).href,
|
|
915
|
+
timeout: this.#deadline
|
|
904
916
|
});
|
|
905
|
-
|
|
917
|
+
this.#client = client;
|
|
918
|
+
client.emitter.on("exit", (exit) => this.#retire(exit));
|
|
919
|
+
await client.start();
|
|
920
|
+
return client;
|
|
906
921
|
}
|
|
907
922
|
async #warmed() {
|
|
908
|
-
const timeout = (0, _orkestrel_timeout.createTimeout)({ ms: this.#deadline });
|
|
909
|
-
timeout.start();
|
|
910
923
|
try {
|
|
911
|
-
return await
|
|
912
|
-
} catch {
|
|
913
|
-
|
|
914
|
-
} finally {
|
|
915
|
-
timeout.clear();
|
|
916
|
-
}
|
|
917
|
-
}
|
|
918
|
-
async #release(child, released) {
|
|
919
|
-
const timeout = (0, _orkestrel_timeout.createTimeout)({ ms: this.#deadline });
|
|
920
|
-
timeout.start();
|
|
921
|
-
try {
|
|
922
|
-
await Promise.race([this.#retire(child).then(() => released), this.#expiry(timeout)]);
|
|
923
|
-
} catch {
|
|
924
|
-
child.kill("SIGKILL");
|
|
925
|
-
await released;
|
|
926
|
-
} finally {
|
|
927
|
-
timeout.clear();
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
async #retire(child) {
|
|
931
|
-
try {
|
|
932
|
-
await this.#request("shutdown", void 0);
|
|
933
|
-
this.#notify("exit", void 0);
|
|
934
|
-
} catch {
|
|
935
|
-
child.kill("SIGKILL");
|
|
924
|
+
return await this.#warmth;
|
|
925
|
+
} catch (error) {
|
|
926
|
+
throw this.#translate(error);
|
|
936
927
|
}
|
|
937
928
|
}
|
|
938
|
-
#
|
|
939
|
-
|
|
940
|
-
timeout.signal.addEventListener("abort", () => reject(new _src_core.ProbeError(`The Oxlint language server did not exit within ${timeout.ms} ms`, {
|
|
941
|
-
origin: "instrument",
|
|
942
|
-
code: "deadline",
|
|
943
|
-
context: {
|
|
944
|
-
stage: this.stage,
|
|
945
|
-
deadline: timeout.ms
|
|
946
|
-
}
|
|
947
|
-
})), { once: true });
|
|
948
|
-
});
|
|
949
|
-
}
|
|
950
|
-
async #warm() {
|
|
951
|
-
const binary = resolveWorkspaceBinary(this.#workspace, "oxlint");
|
|
952
|
-
const child = (0, node_child_process.spawn)(process.execPath, [binary, "--lsp"], {
|
|
953
|
-
cwd: this.#workspace,
|
|
954
|
-
stdio: "pipe"
|
|
955
|
-
});
|
|
956
|
-
this.#child = child;
|
|
957
|
-
child.stderr.resume();
|
|
958
|
-
child.stdout.on("data", (chunk) => this.#read(chunk));
|
|
959
|
-
child.stdin.on("error", (error) => this.#fail(error));
|
|
960
|
-
child.on("error", (error) => this.#fail(error));
|
|
961
|
-
child.on("exit", (code, signal) => this.#exit(code, signal));
|
|
962
|
-
await this.#request("initialize", {
|
|
963
|
-
processId: process.pid,
|
|
964
|
-
rootUri: (0, node_url.pathToFileURL)(this.#workspace).href,
|
|
965
|
-
capabilities: {},
|
|
966
|
-
workspaceFolders: [{
|
|
967
|
-
uri: (0, node_url.pathToFileURL)(this.#workspace).href,
|
|
968
|
-
name: "workspace"
|
|
969
|
-
}]
|
|
970
|
-
});
|
|
971
|
-
this.#notify("initialized", {});
|
|
972
|
-
return child;
|
|
929
|
+
#retire(exit) {
|
|
930
|
+
this.#ending = exit.signal === null ? `code ${exit.code}` : `signal ${exit.signal}`;
|
|
973
931
|
}
|
|
974
|
-
#document(draft) {
|
|
932
|
+
async #document(client, draft, signal) {
|
|
975
933
|
const uri = (0, node_url.pathToFileURL)(resolveWorkspaceFile(this.#workspace, draft.path)).href;
|
|
976
|
-
if (this.#
|
|
934
|
+
if (this.#documents.has(uri)) throw new _src_core.ProbeError(`The lint stage is already inspecting ${draft.path}`, {
|
|
977
935
|
origin: "claimant",
|
|
978
936
|
code: "refused",
|
|
979
937
|
context: {
|
|
980
938
|
stage: this.stage,
|
|
981
939
|
path: draft.path
|
|
982
940
|
}
|
|
983
|
-
})
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
this.#refusals.set(uri, reject);
|
|
988
|
-
}).finally(() => this.#close(uri));
|
|
941
|
+
});
|
|
942
|
+
this.#documents.add(uri);
|
|
943
|
+
this.#progress += 1;
|
|
944
|
+
this.#revision += 1;
|
|
989
945
|
try {
|
|
990
|
-
|
|
946
|
+
const diagnostics = await client.open({
|
|
991
947
|
uri,
|
|
992
948
|
languageId: inferDocumentLanguage(draft.path),
|
|
993
|
-
version: this.#
|
|
949
|
+
version: this.#revision,
|
|
994
950
|
text: draft.text
|
|
995
|
-
} });
|
|
996
|
-
this.#
|
|
951
|
+
}, { signal });
|
|
952
|
+
return this.#issues(normalizePath(draft.path), diagnostics);
|
|
997
953
|
} catch (error) {
|
|
998
|
-
|
|
954
|
+
if (signal.aborted) throw this.#abandoned(draft.path);
|
|
955
|
+
throw this.#translate(error, draft.path);
|
|
956
|
+
} finally {
|
|
957
|
+
this.#progress -= 1;
|
|
958
|
+
this.#documents.delete(uri);
|
|
959
|
+
await client.close(uri).catch(() => void 0);
|
|
999
960
|
}
|
|
1000
|
-
return inspected;
|
|
1001
961
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
962
|
+
#abandoned(path) {
|
|
963
|
+
return new _src_core.ProbeError("The lint stage inspection stopped at the bound its caller supplied", {
|
|
964
|
+
origin: "claimant",
|
|
965
|
+
code: "deadline",
|
|
966
|
+
context: {
|
|
967
|
+
stage: this.stage,
|
|
968
|
+
path
|
|
969
|
+
}
|
|
970
|
+
});
|
|
1007
971
|
}
|
|
1008
|
-
#
|
|
1009
|
-
|
|
972
|
+
#translate(error, path) {
|
|
973
|
+
if (this.#destroyed) return (0, _src_core.createDestroyedError)("lint stage");
|
|
974
|
+
const ending = this.#ending;
|
|
975
|
+
if (ending !== void 0) return this.#fault(`The Oxlint language server exited with ${ending}`, error, path);
|
|
976
|
+
if (error instanceof Error) return error;
|
|
977
|
+
return this.#fault(describeUnknown(error), error, path);
|
|
1010
978
|
}
|
|
1011
979
|
#fault(message, cause, path) {
|
|
1012
980
|
return new _src_core.ProbeError(message, {
|
|
@@ -1019,153 +987,22 @@ var LintStage = class {
|
|
|
1019
987
|
...cause === void 0 ? {} : { cause }
|
|
1020
988
|
});
|
|
1021
989
|
}
|
|
1022
|
-
|
|
1023
|
-
return
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
this.#responses.set(id, resolve);
|
|
1037
|
-
this.#failures.set(id, reject);
|
|
1038
|
-
});
|
|
1039
|
-
try {
|
|
1040
|
-
this.#send({
|
|
1041
|
-
jsonrpc: "2.0",
|
|
1042
|
-
id,
|
|
1043
|
-
method,
|
|
1044
|
-
params
|
|
1045
|
-
});
|
|
1046
|
-
} catch (error) {
|
|
1047
|
-
const reject = this.#failures.get(id);
|
|
1048
|
-
this.#responses.delete(id);
|
|
1049
|
-
this.#failures.delete(id);
|
|
1050
|
-
reject?.(this.#fault(describeUnknown(error), error));
|
|
1051
|
-
}
|
|
1052
|
-
return response;
|
|
1053
|
-
}
|
|
1054
|
-
#notify(method, params) {
|
|
1055
|
-
this.#sequence += 1;
|
|
1056
|
-
this.#send({
|
|
1057
|
-
jsonrpc: "2.0",
|
|
1058
|
-
method,
|
|
1059
|
-
params
|
|
1060
|
-
});
|
|
1061
|
-
}
|
|
1062
|
-
#send(message) {
|
|
1063
|
-
const child = this.#child;
|
|
1064
|
-
if (this.#ending !== void 0) throw this.#fault(`The Oxlint language server exited with ${this.#ending}`);
|
|
1065
|
-
if (child === void 0) throw this.#fault("The Oxlint language server is not running");
|
|
1066
|
-
if (!child.stdin.writable) throw this.#fault("The Oxlint language server closed its input");
|
|
1067
|
-
const content = JSON.stringify(message);
|
|
1068
|
-
const header = `Content-Length: ${Buffer.byteLength(content)}\r\n\r\n`;
|
|
1069
|
-
child.stdin.write(header + content);
|
|
1070
|
-
}
|
|
1071
|
-
#read(chunk) {
|
|
1072
|
-
this.#buffer = Buffer.concat([this.#buffer, chunk]);
|
|
1073
|
-
while (this.#frame());
|
|
1074
|
-
}
|
|
1075
|
-
#frame() {
|
|
1076
|
-
const boundary = this.#buffer.indexOf("\r\n\r\n");
|
|
1077
|
-
if (boundary < 0) return false;
|
|
1078
|
-
const length = parseContentLength(this.#buffer.subarray(0, boundary).toString("ascii"));
|
|
1079
|
-
if (length === void 0) {
|
|
1080
|
-
this.#fail(this.#fault("Oxlint sent an invalid JSON-RPC frame header"));
|
|
1081
|
-
return false;
|
|
1082
|
-
}
|
|
1083
|
-
const start = boundary + 4;
|
|
1084
|
-
const end = start + length;
|
|
1085
|
-
if (this.#buffer.length < end) return false;
|
|
1086
|
-
const content = this.#buffer.subarray(start, end).toString("utf8");
|
|
1087
|
-
this.#buffer = this.#buffer.subarray(end);
|
|
1088
|
-
try {
|
|
1089
|
-
const message = JSON.parse(content);
|
|
1090
|
-
this.#receive(message);
|
|
1091
|
-
} catch (error) {
|
|
1092
|
-
this.#fail(this.#fault(`Oxlint sent invalid JSON: ${describeUnknown(error)}`, error));
|
|
1093
|
-
}
|
|
1094
|
-
return true;
|
|
1095
|
-
}
|
|
1096
|
-
#receive(message) {
|
|
1097
|
-
if (typeof message !== "object" || message === null) return;
|
|
1098
|
-
if ("id" in message && typeof message.id === "number") {
|
|
1099
|
-
const id = message.id;
|
|
1100
|
-
const resolve = this.#responses.get(id);
|
|
1101
|
-
const reject = this.#failures.get(id);
|
|
1102
|
-
this.#responses.delete(id);
|
|
1103
|
-
this.#failures.delete(id);
|
|
1104
|
-
if ("error" in message && message.error !== void 0) reject?.(this.#fault(describeUnknown(message.error)));
|
|
1105
|
-
else resolve?.("result" in message ? message.result : void 0);
|
|
1106
|
-
return;
|
|
1107
|
-
}
|
|
1108
|
-
if (!("method" in message) || message.method !== "textDocument/publishDiagnostics") return;
|
|
1109
|
-
if (!("params" in message) || typeof message.params !== "object" || message.params === null) return;
|
|
1110
|
-
const params = message.params;
|
|
1111
|
-
if (!("uri" in params) || typeof params.uri !== "string") return;
|
|
1112
|
-
if (!("diagnostics" in params) || !Array.isArray(params.diagnostics)) return;
|
|
1113
|
-
const publish = this.#publishes.get(params.uri);
|
|
1114
|
-
if (publish === void 0) return;
|
|
1115
|
-
publish(this.#issues(params.uri, params.diagnostics));
|
|
1116
|
-
}
|
|
1117
|
-
#issues(uri, diagnostics) {
|
|
1118
|
-
const path = this.#documents.get(uri);
|
|
1119
|
-
if (path === void 0) return [];
|
|
1120
|
-
const issues = [];
|
|
1121
|
-
for (const diagnostic of diagnostics) {
|
|
1122
|
-
if (typeof diagnostic !== "object" || diagnostic === null) continue;
|
|
1123
|
-
if (!("message" in diagnostic) || typeof diagnostic.message !== "string") continue;
|
|
1124
|
-
if (!("range" in diagnostic) || typeof diagnostic.range !== "object" || diagnostic.range === null) {
|
|
1125
|
-
issues.push({
|
|
1126
|
-
origin: "claimant",
|
|
1127
|
-
path,
|
|
1128
|
-
message: diagnostic.message
|
|
1129
|
-
});
|
|
1130
|
-
continue;
|
|
1131
|
-
}
|
|
1132
|
-
const range = diagnostic.range;
|
|
1133
|
-
if (!("start" in range) || typeof range.start !== "object" || range.start === null) {
|
|
1134
|
-
issues.push({
|
|
1135
|
-
origin: "claimant",
|
|
1136
|
-
path,
|
|
1137
|
-
message: diagnostic.message
|
|
1138
|
-
});
|
|
1139
|
-
continue;
|
|
1140
|
-
}
|
|
1141
|
-
const start = range.start;
|
|
1142
|
-
if (!("line" in start) || typeof start.line !== "number") {
|
|
1143
|
-
issues.push({
|
|
1144
|
-
origin: "claimant",
|
|
1145
|
-
path,
|
|
1146
|
-
message: diagnostic.message
|
|
1147
|
-
});
|
|
1148
|
-
continue;
|
|
990
|
+
#issues(path, diagnostics) {
|
|
991
|
+
return diagnostics.map((diagnostic) => ({
|
|
992
|
+
origin: "claimant",
|
|
993
|
+
path,
|
|
994
|
+
message: diagnostic.message,
|
|
995
|
+
range: {
|
|
996
|
+
start: {
|
|
997
|
+
line: diagnostic.range.start.line,
|
|
998
|
+
character: diagnostic.range.start.character
|
|
999
|
+
},
|
|
1000
|
+
end: {
|
|
1001
|
+
line: diagnostic.range.end.line,
|
|
1002
|
+
character: diagnostic.range.end.character
|
|
1003
|
+
}
|
|
1149
1004
|
}
|
|
1150
|
-
|
|
1151
|
-
origin: "claimant",
|
|
1152
|
-
path,
|
|
1153
|
-
message: diagnostic.message,
|
|
1154
|
-
line: start.line + 1
|
|
1155
|
-
});
|
|
1156
|
-
}
|
|
1157
|
-
return issues;
|
|
1158
|
-
}
|
|
1159
|
-
#fail(error) {
|
|
1160
|
-
for (const reject of this.#failures.values()) reject(error);
|
|
1161
|
-
for (const reject of this.#refusals.values()) reject(error);
|
|
1162
|
-
this.#responses.clear();
|
|
1163
|
-
this.#failures.clear();
|
|
1164
|
-
this.#publishes.clear();
|
|
1165
|
-
this.#refusals.clear();
|
|
1166
|
-
}
|
|
1167
|
-
#exit(code, signal) {
|
|
1168
|
-
this.#fail(this.#fault(`The Oxlint language server exited with ${this.#describe(code, signal)}`));
|
|
1005
|
+
}));
|
|
1169
1006
|
}
|
|
1170
1007
|
};
|
|
1171
1008
|
//#endregion
|
|
@@ -1796,11 +1633,19 @@ var RuntimeStage = class {
|
|
|
1796
1633
|
path,
|
|
1797
1634
|
message
|
|
1798
1635
|
};
|
|
1636
|
+
const character = "column" in stack && typeof stack.column === "number" ? stack.column - 1 : 0;
|
|
1637
|
+
const position = {
|
|
1638
|
+
line: stack.line - 1,
|
|
1639
|
+
character
|
|
1640
|
+
};
|
|
1799
1641
|
return {
|
|
1800
1642
|
origin: "claimant",
|
|
1801
1643
|
path,
|
|
1802
1644
|
message,
|
|
1803
|
-
|
|
1645
|
+
range: {
|
|
1646
|
+
start: position,
|
|
1647
|
+
end: position
|
|
1648
|
+
}
|
|
1804
1649
|
};
|
|
1805
1650
|
}
|
|
1806
1651
|
return {
|
|
@@ -2142,7 +1987,10 @@ var TypeStage = class {
|
|
|
2142
1987
|
origin: "claimant",
|
|
2143
1988
|
path,
|
|
2144
1989
|
message,
|
|
2145
|
-
|
|
1990
|
+
range: {
|
|
1991
|
+
start: diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start),
|
|
1992
|
+
end: diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start + (diagnostic.length ?? 0))
|
|
1993
|
+
}
|
|
2146
1994
|
};
|
|
2147
1995
|
}
|
|
2148
1996
|
};
|
|
@@ -2435,16 +2283,18 @@ var Probe = class {
|
|
|
2435
2283
|
const release = await this.#admitType();
|
|
2436
2284
|
try {
|
|
2437
2285
|
const stage = this.#type;
|
|
2438
|
-
return await this.#inspectStage(stage, stage.progress, stage.inspect(inspection.subject, inspection.claim.project), inspection.claim);
|
|
2286
|
+
return await this.#inspectStage(stage, stage.progress, () => stage.inspect(inspection.subject, inspection.claim.project), inspection.claim);
|
|
2439
2287
|
} finally {
|
|
2440
2288
|
release();
|
|
2441
2289
|
}
|
|
2442
2290
|
}
|
|
2443
2291
|
#inspectLint(inspection) {
|
|
2444
|
-
|
|
2292
|
+
const stage = this.#lint;
|
|
2293
|
+
return this.#inspectStage(stage, stage.progress, (signal) => stage.inspect(inspection.subject, { signal }), inspection.claim);
|
|
2445
2294
|
}
|
|
2446
2295
|
#inspectRuntime(inspection) {
|
|
2447
|
-
|
|
2296
|
+
const stage = this.#runtime;
|
|
2297
|
+
return this.#inspectStage(stage, stage.progress, () => stage.inspect(inspection.subject), inspection.claim);
|
|
2448
2298
|
}
|
|
2449
2299
|
async #inspectStage(stage, progress, operation, claim) {
|
|
2450
2300
|
try {
|
|
@@ -2457,12 +2307,14 @@ var Probe = class {
|
|
|
2457
2307
|
async #bound(operation, message, stage, progress) {
|
|
2458
2308
|
const timeout = (0, _orkestrel_timeout.createTimeout)({ ms: this.#deadline });
|
|
2459
2309
|
timeout.start();
|
|
2310
|
+
const expiry = this.#expiry(timeout, message, stage, progress);
|
|
2311
|
+
const refusal = expiry.catch((error) => error);
|
|
2460
2312
|
try {
|
|
2461
|
-
return await Promise.race([operation
|
|
2313
|
+
return await Promise.race([operation(timeout.signal), expiry]);
|
|
2462
2314
|
} catch (error) {
|
|
2463
2315
|
if (!timeout.expired) throw error;
|
|
2464
2316
|
await this.#recycle(stage);
|
|
2465
|
-
throw
|
|
2317
|
+
throw await refusal;
|
|
2466
2318
|
} finally {
|
|
2467
2319
|
timeout.clear();
|
|
2468
2320
|
}
|
|
@@ -2503,7 +2355,7 @@ var Probe = class {
|
|
|
2503
2355
|
try {
|
|
2504
2356
|
const stage = this.#type;
|
|
2505
2357
|
try {
|
|
2506
|
-
return await this.#bound(stage.resolve(claim.project), `The type stage project resolution exceeded ${this.#deadline} ms`, stage, stage.progress);
|
|
2358
|
+
return await this.#bound(() => stage.resolve(claim.project), `The type stage project resolution exceeded ${this.#deadline} ms`, stage, stage.progress);
|
|
2507
2359
|
} catch (error) {
|
|
2508
2360
|
this.#emitExpiry(stage, claim);
|
|
2509
2361
|
throw error;
|
|
@@ -2544,7 +2396,7 @@ var Probe = class {
|
|
|
2544
2396
|
}
|
|
2545
2397
|
async #destroyStage(stage) {
|
|
2546
2398
|
try {
|
|
2547
|
-
await this.#bound(stage.destroy(), `The ${stage.stage} stage teardown exceeded ${this.#deadline} ms`, stage, stage.progress);
|
|
2399
|
+
await this.#bound(() => stage.destroy(), `The ${stage.stage} stage teardown exceeded ${this.#deadline} ms`, stage, stage.progress);
|
|
2548
2400
|
} catch (error) {
|
|
2549
2401
|
if (!(error instanceof _src_core.ProbeError) || !this.#deadlines.has(error)) throw error;
|
|
2550
2402
|
}
|
|
@@ -2753,7 +2605,6 @@ exports.matchesWorkspaceModule = matchesWorkspaceModule;
|
|
|
2753
2605
|
exports.normalizePath = normalizePath;
|
|
2754
2606
|
exports.normalizeValue = normalizeValue;
|
|
2755
2607
|
exports.overwriteFile = overwriteFile;
|
|
2756
|
-
exports.parseContentLength = parseContentLength;
|
|
2757
2608
|
exports.readWorkspaceManifest = readWorkspaceManifest;
|
|
2758
2609
|
exports.relativeWorkspaceFile = relativeWorkspaceFile;
|
|
2759
2610
|
exports.relativeWorkspaceMessage = relativeWorkspaceMessage;
|