@elaraai/east-diagnostics 1.0.70 → 1.0.72
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/index.d.ts +5 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/jsonrpc-stdio.d.ts +29 -0
- package/dist/src/jsonrpc-stdio.d.ts.map +1 -0
- package/dist/src/jsonrpc-stdio.js +52 -0
- package/dist/src/jsonrpc-stdio.js.map +1 -0
- package/dist/src/lsp.d.ts.map +1 -1
- package/dist/src/lsp.js +40 -66
- package/dist/src/lsp.js.map +1 -1
- package/dist/src/python-lint.d.ts +20 -1
- package/dist/src/python-lint.d.ts.map +1 -1
- package/dist/src/python-lint.js +59 -3
- package/dist/src/python-lint.js.map +1 -1
- package/dist/src/python-lsp-proxy.d.ts +85 -0
- package/dist/src/python-lsp-proxy.d.ts.map +1 -0
- package/dist/src/python-lsp-proxy.js +304 -0
- package/dist/src/python-lsp-proxy.js.map +1 -0
- package/dist/src/python-lsp-server.d.ts +25 -0
- package/dist/src/python-lsp-server.d.ts.map +1 -0
- package/dist/src/python-lsp-server.js +264 -0
- package/dist/src/python-lsp-server.js.map +1 -0
- package/package.json +3 -3
package/dist/src/index.d.ts
CHANGED
|
@@ -9,8 +9,12 @@ export { createDiagnosticsService } from "./service.js";
|
|
|
9
9
|
export type { DiagnosticsService, DiagnosticsServiceOptions } from "./service.js";
|
|
10
10
|
export { runEastLsp } from "./lsp.js";
|
|
11
11
|
export type { EastLspOptions } from "./lsp.js";
|
|
12
|
-
export { findEastPy, runEastPyLint, renderPythonReview, PYTHON_EAST_IMPORT } from "./python-lint.js";
|
|
12
|
+
export { findEastPy, findEastPyProject, runEastPyLint, runEastPyCheck, renderPythonReview, PYTHON_EAST_IMPORT } from "./python-lint.js";
|
|
13
13
|
export type { PythonDiagnostic } from "./python-lint.js";
|
|
14
|
+
export { PythonLspProxy } from "./python-lsp-proxy.js";
|
|
15
|
+
export type { PythonLspProxyOptions } from "./python-lsp-proxy.js";
|
|
16
|
+
export { runEastPyLsp } from "./python-lsp-server.js";
|
|
17
|
+
export type { EastPyLspOptions } from "./python-lsp-server.js";
|
|
14
18
|
export { getEastModule } from "./east-module.js";
|
|
15
19
|
export type { EastModule } from "./east-module.js";
|
|
16
20
|
export { reifyEastType } from "./type-reify.js";
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,mBAAmB,YAAY,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,mBAAmB,YAAY,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACxI,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACvF,OAAO,EAAE,IAAI,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAClE,YAAY,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/src/index.js
CHANGED
|
@@ -2,7 +2,9 @@ export * from "./rules/index.js";
|
|
|
2
2
|
export { runEastRules } from "./run.js";
|
|
3
3
|
export { createDiagnosticsService } from "./service.js";
|
|
4
4
|
export { runEastLsp } from "./lsp.js";
|
|
5
|
-
export { findEastPy, runEastPyLint, renderPythonReview, PYTHON_EAST_IMPORT } from "./python-lint.js";
|
|
5
|
+
export { findEastPy, findEastPyProject, runEastPyLint, runEastPyCheck, renderPythonReview, PYTHON_EAST_IMPORT } from "./python-lint.js";
|
|
6
|
+
export { PythonLspProxy } from "./python-lsp-proxy.js";
|
|
7
|
+
export { runEastPyLsp } from "./python-lsp-server.js";
|
|
6
8
|
export { getEastModule } from "./east-module.js";
|
|
7
9
|
export { reifyEastType } from "./type-reify.js";
|
|
8
10
|
export { rewriteEastAssignability, ASSIGNABILITY_CODES } from "./type-diff-rewrite.js";
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAExI,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACvF,OAAO,EAAE,IAAI,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
export interface JsonRpcMessage {
|
|
6
|
+
jsonrpc: "2.0";
|
|
7
|
+
id?: number | string | null;
|
|
8
|
+
method?: string;
|
|
9
|
+
params?: any;
|
|
10
|
+
result?: unknown;
|
|
11
|
+
error?: {
|
|
12
|
+
code: number;
|
|
13
|
+
message: string;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** Encode one message as a framed chunk. */
|
|
17
|
+
export declare function frame(message: object): string;
|
|
18
|
+
/**
|
|
19
|
+
* A reader that reassembles framed messages from arbitrary chunks. A
|
|
20
|
+
* malformed frame is skipped, not fatal — a session survives a bad message.
|
|
21
|
+
*/
|
|
22
|
+
export declare class FrameReader {
|
|
23
|
+
private readonly onMessage;
|
|
24
|
+
private buffer;
|
|
25
|
+
constructor(onMessage: (message: JsonRpcMessage) => void);
|
|
26
|
+
push(chunk: Buffer): void;
|
|
27
|
+
reset(): void;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=jsonrpc-stdio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonrpc-stdio.d.ts","sourceRoot":"","sources":["../../src/jsonrpc-stdio.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAED,4CAA4C;AAC5C,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG7C;AAED;;;GAGG;AACH,qBAAa,WAAW;IAGV,OAAO,CAAC,QAAQ,CAAC,SAAS;IAFtC,OAAO,CAAC,MAAM,CAAmB;gBAEJ,SAAS,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI;IAEzE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IA0BzB,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/** Encode one message as a framed chunk. */
|
|
6
|
+
export function frame(message) {
|
|
7
|
+
const body = JSON.stringify({ jsonrpc: "2.0", ...message });
|
|
8
|
+
return `Content-Length: ${Buffer.byteLength(body, "utf8")}\r\n\r\n${body}`;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A reader that reassembles framed messages from arbitrary chunks. A
|
|
12
|
+
* malformed frame is skipped, not fatal — a session survives a bad message.
|
|
13
|
+
*/
|
|
14
|
+
export class FrameReader {
|
|
15
|
+
onMessage;
|
|
16
|
+
buffer = Buffer.alloc(0);
|
|
17
|
+
constructor(onMessage) {
|
|
18
|
+
this.onMessage = onMessage;
|
|
19
|
+
}
|
|
20
|
+
push(chunk) {
|
|
21
|
+
this.buffer = Buffer.concat([this.buffer, chunk]);
|
|
22
|
+
for (;;) {
|
|
23
|
+
const headerEnd = this.buffer.indexOf("\r\n\r\n");
|
|
24
|
+
if (headerEnd < 0)
|
|
25
|
+
return;
|
|
26
|
+
const header = this.buffer.subarray(0, headerEnd).toString("utf8");
|
|
27
|
+
const match = /Content-Length:\s*(\d+)/i.exec(header);
|
|
28
|
+
if (match === null) {
|
|
29
|
+
this.buffer = this.buffer.subarray(headerEnd + 4);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const length = Number(match[1]);
|
|
33
|
+
const bodyStart = headerEnd + 4;
|
|
34
|
+
if (this.buffer.length < bodyStart + length)
|
|
35
|
+
return;
|
|
36
|
+
const body = this.buffer.subarray(bodyStart, bodyStart + length).toString("utf8");
|
|
37
|
+
this.buffer = this.buffer.subarray(bodyStart + length);
|
|
38
|
+
let message;
|
|
39
|
+
try {
|
|
40
|
+
message = JSON.parse(body);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
this.onMessage(message);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
reset() {
|
|
49
|
+
this.buffer = Buffer.alloc(0);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=jsonrpc-stdio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonrpc-stdio.js","sourceRoot":"","sources":["../../src/jsonrpc-stdio.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAeH,4CAA4C;AAC5C,MAAM,UAAU,KAAK,CAAC,OAAe;IACnC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAC5D,OAAO,mBAAmB,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;AAC7E,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,WAAW;IAGO;IAFrB,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEjC,YAA6B,SAA4C;QAA5C,cAAS,GAAT,SAAS,CAAmC;IAAG,CAAC;IAE7E,IAAI,CAAC,KAAa;QAChB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QAClD,SAAS,CAAC;YACR,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAClD,IAAI,SAAS,GAAG,CAAC;gBAAE,OAAO;YAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACnE,MAAM,KAAK,GAAG,0BAA0B,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACtD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;gBAClD,SAAS;YACX,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAChC,MAAM,SAAS,GAAG,SAAS,GAAG,CAAC,CAAC;YAChC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,SAAS,GAAG,MAAM;gBAAE,OAAO;YACpD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAClF,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,GAAG,MAAM,CAAC,CAAC;YACvD,IAAI,OAAuB,CAAC;YAC5B,IAAI,CAAC;gBACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAmB,CAAC;YAC/C,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YACD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC;CACF"}
|
package/dist/src/lsp.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lsp.d.ts","sourceRoot":"","sources":["../../src/lsp.ts"],"names":[],"mappings":"AAMA,OAAO,EAA4B,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"lsp.d.ts","sourceRoot":"","sources":["../../src/lsp.ts"],"names":[],"mappings":"AAMA,OAAO,EAA4B,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAoDjF,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC/B,oDAAoD;IACpD,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B;AAED,4DAA4D;AAC5D,wBAAgB,UAAU,CAAC,OAAO,GAAE,cAAmB,GAAG,IAAI,CA6K7D"}
|
package/dist/src/lsp.js
CHANGED
|
@@ -5,7 +5,15 @@
|
|
|
5
5
|
import { readFileSync } from "node:fs";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { createDiagnosticsService } from "./service.js";
|
|
8
|
-
import {
|
|
8
|
+
import { frame, FrameReader } from "./jsonrpc-stdio.js";
|
|
9
|
+
// Minimal LSP server over stdio for TypeScript: full-document sync in,
|
|
10
|
+
// publishDiagnostics out, everything backed by the shared DiagnosticsService.
|
|
11
|
+
// Hand-rolled JSON-RPC framing keeps the package dependency-free.
|
|
12
|
+
//
|
|
13
|
+
// Python is NOT this server's: `runEastPyLsp` (python-lsp-server.ts) is its
|
|
14
|
+
// own server with its own lifecycle, registered for `.py` beside this one. A
|
|
15
|
+
// `.py` document that still reaches here — an old manifest — gets an empty
|
|
16
|
+
// publish, never a verdict.
|
|
9
17
|
const EAST_IMPORT_PATTERN = /@elaraai\//;
|
|
10
18
|
// Vendored / built / generated trees: never diagnose code the user doesn't own.
|
|
11
19
|
const SKIP_PATH = /[/\\](node_modules|dist|build|\.venv|\.git)[/\\]/;
|
|
@@ -56,30 +64,7 @@ export function runEastLsp(options = {}) {
|
|
|
56
64
|
const pending = new Map();
|
|
57
65
|
let shuttingDown = false;
|
|
58
66
|
function send(message) {
|
|
59
|
-
|
|
60
|
-
output.write(`Content-Length: ${Buffer.byteLength(body, "utf8")}\r\n\r\n${body}`);
|
|
61
|
-
}
|
|
62
|
-
/** A python document: the east-py rules, run out of process; published when they answer. */
|
|
63
|
-
function publishPython(path, content) {
|
|
64
|
-
if (content === undefined || SKIP_PATH.test(path) || !PYTHON_EAST_IMPORT.test(content)) {
|
|
65
|
-
send({ method: "textDocument/publishDiagnostics", params: { uri: `file://${path}`, diagnostics: [] } });
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
void runEastPyLint(path, open.has(path) ? content : undefined).then((records) => {
|
|
69
|
-
if (records === null)
|
|
70
|
-
return; // no east-py answered: say nothing rather than "clean"
|
|
71
|
-
const diagnostics = records.map((r) => ({
|
|
72
|
-
range: {
|
|
73
|
-
start: { line: r.line - 1, character: r.column - 1 },
|
|
74
|
-
end: { line: (r.end_line ?? r.line) - 1, character: (r.end_column ?? r.column + 1) - 1 },
|
|
75
|
-
},
|
|
76
|
-
severity: SEVERITY[r.category] ?? 2,
|
|
77
|
-
code: r.rule,
|
|
78
|
-
source: "east-py",
|
|
79
|
-
message: r.message,
|
|
80
|
-
}));
|
|
81
|
-
send({ method: "textDocument/publishDiagnostics", params: { uri: `file://${path}`, diagnostics } });
|
|
82
|
-
});
|
|
67
|
+
output.write(frame(message));
|
|
83
68
|
}
|
|
84
69
|
function publish(path) {
|
|
85
70
|
const content = open.get(path) ?? (() => {
|
|
@@ -90,10 +75,6 @@ export function runEastLsp(options = {}) {
|
|
|
90
75
|
return undefined;
|
|
91
76
|
}
|
|
92
77
|
})();
|
|
93
|
-
if (path.endsWith(".py")) {
|
|
94
|
-
publishPython(path, content);
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
78
|
let diagnostics = [];
|
|
98
79
|
if (content !== undefined && !SKIP_PATH.test(path) && EAST_IMPORT_PATTERN.test(content)) {
|
|
99
80
|
const starts = lineStarts(content);
|
|
@@ -124,6 +105,13 @@ export function runEastLsp(options = {}) {
|
|
|
124
105
|
}
|
|
125
106
|
}, DEBOUNCE_MS));
|
|
126
107
|
}
|
|
108
|
+
/** A python document is another server's: clear it, never judge it. */
|
|
109
|
+
function notOurs(path) {
|
|
110
|
+
if (!path.endsWith(".py"))
|
|
111
|
+
return false;
|
|
112
|
+
send({ method: "textDocument/publishDiagnostics", params: { uri: `file://${path}`, diagnostics: [] } });
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
127
115
|
function handle(message) {
|
|
128
116
|
const { method, id, params } = message;
|
|
129
117
|
if (method === undefined)
|
|
@@ -171,16 +159,17 @@ export function runEastLsp(options = {}) {
|
|
|
171
159
|
send({ id, result: null });
|
|
172
160
|
return;
|
|
173
161
|
case "exit":
|
|
174
|
-
|
|
162
|
+
shutdown(shuttingDown ? 0 : 1);
|
|
175
163
|
return;
|
|
176
164
|
case "textDocument/didOpen": {
|
|
177
165
|
const path = uriToPath(params?.textDocument?.uri ?? "");
|
|
178
166
|
const text = params?.textDocument?.text;
|
|
179
167
|
if (path === undefined || typeof text !== "string")
|
|
180
168
|
return;
|
|
169
|
+
if (notOurs(path))
|
|
170
|
+
return;
|
|
181
171
|
open.set(path, text);
|
|
182
|
-
|
|
183
|
-
service.setOverlay(path, text);
|
|
172
|
+
service.setOverlay(path, text);
|
|
184
173
|
schedule(path);
|
|
185
174
|
return;
|
|
186
175
|
}
|
|
@@ -189,9 +178,10 @@ export function runEastLsp(options = {}) {
|
|
|
189
178
|
const text = params?.contentChanges?.at?.(-1)?.text;
|
|
190
179
|
if (path === undefined || typeof text !== "string")
|
|
191
180
|
return;
|
|
181
|
+
if (notOurs(path))
|
|
182
|
+
return;
|
|
192
183
|
open.set(path, text);
|
|
193
|
-
|
|
194
|
-
service.setOverlay(path, text);
|
|
184
|
+
service.setOverlay(path, text);
|
|
195
185
|
schedule(path);
|
|
196
186
|
return;
|
|
197
187
|
}
|
|
@@ -199,16 +189,16 @@ export function runEastLsp(options = {}) {
|
|
|
199
189
|
const path = uriToPath(params?.textDocument?.uri ?? "");
|
|
200
190
|
if (path === undefined)
|
|
201
191
|
return;
|
|
192
|
+
if (notOurs(path))
|
|
193
|
+
return;
|
|
202
194
|
const text = params?.text;
|
|
203
195
|
if (typeof text === "string") {
|
|
204
196
|
open.set(path, text);
|
|
205
|
-
|
|
206
|
-
service.setOverlay(path, text);
|
|
197
|
+
service.setOverlay(path, text);
|
|
207
198
|
}
|
|
208
199
|
else {
|
|
209
200
|
open.delete(path);
|
|
210
|
-
|
|
211
|
-
service.clearOverlay(path);
|
|
201
|
+
service.clearOverlay(path);
|
|
212
202
|
}
|
|
213
203
|
schedule(path);
|
|
214
204
|
return;
|
|
@@ -234,35 +224,19 @@ export function runEastLsp(options = {}) {
|
|
|
234
224
|
return;
|
|
235
225
|
}
|
|
236
226
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
if (headerEnd < 0)
|
|
244
|
-
return;
|
|
245
|
-
const header = buffer.subarray(0, headerEnd).toString("utf8");
|
|
246
|
-
const match = /Content-Length:\s*(\d+)/i.exec(header);
|
|
247
|
-
if (match === null) {
|
|
248
|
-
buffer = buffer.subarray(headerEnd + 4);
|
|
249
|
-
continue;
|
|
250
|
-
}
|
|
251
|
-
const length = Number(match[1]);
|
|
252
|
-
const bodyStart = headerEnd + 4;
|
|
253
|
-
if (buffer.length < bodyStart + length)
|
|
254
|
-
return;
|
|
255
|
-
const body = buffer.subarray(bodyStart, bodyStart + length).toString("utf8");
|
|
256
|
-
buffer = buffer.subarray(bodyStart + length);
|
|
257
|
-
try {
|
|
258
|
-
handle(JSON.parse(body));
|
|
259
|
-
}
|
|
260
|
-
catch {
|
|
261
|
-
// Malformed frame — skip it rather than dying mid-session.
|
|
262
|
-
}
|
|
227
|
+
const reader = new FrameReader((message) => {
|
|
228
|
+
try {
|
|
229
|
+
handle(message);
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
// Never let one message kill the server.
|
|
263
233
|
}
|
|
264
234
|
});
|
|
265
|
-
input.on("
|
|
266
|
-
|
|
235
|
+
input.on("data", (chunk) => reader.push(chunk));
|
|
236
|
+
// The client going away ends the session: a disconnecting client may never
|
|
237
|
+
// send the `exit` message.
|
|
238
|
+
const shutdown = (code) => exit(code);
|
|
239
|
+
input.on("close", () => shutdown(0));
|
|
240
|
+
input.on("end", () => shutdown(0));
|
|
267
241
|
}
|
|
268
242
|
//# sourceMappingURL=lsp.js.map
|
package/dist/src/lsp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lsp.js","sourceRoot":"","sources":["../../src/lsp.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,wBAAwB,EAA2B,MAAM,cAAc,CAAC;AACjF,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"lsp.js","sourceRoot":"","sources":["../../src/lsp.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,13 +15,32 @@ export declare const PYTHON_EAST_IMPORT: RegExp;
|
|
|
15
15
|
/** The `east-py` command for a file: `EAST_PY_LINT` when set, else the
|
|
16
16
|
* nearest `.venv` above `fromDir`, else `east-py` on PATH. */
|
|
17
17
|
export declare function findEastPy(fromDir: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* The directory of the nearest `pyproject.toml` at or above `fromDir` that
|
|
20
|
+
* depends on east-py — what makes a directory an east-py PROJECT, as opposed
|
|
21
|
+
* to a python file that happens to import `east`. A uv workspace root that
|
|
22
|
+
* declares it counts for every member below it, so the walk continues past a
|
|
23
|
+
* member's own pyproject that says nothing. `undefined` when nothing above
|
|
24
|
+
* declares it.
|
|
25
|
+
*/
|
|
26
|
+
export declare function findEastPyProject(fromDir: string): string | undefined;
|
|
18
27
|
/**
|
|
19
28
|
* The east-py findings for a python file — `""`-free: `[]` when clean,
|
|
20
29
|
* `null` when no east-py answered (absent, failed, or over `budgetMs`), so
|
|
21
30
|
* callers can stay silent. `content` (an unsaved buffer) is linted from a
|
|
22
31
|
* temporary copy under the file's own name; the file itself otherwise.
|
|
32
|
+
* `command` is the `east-py` to run; by default the one `findEastPy` resolves
|
|
33
|
+
* for the file.
|
|
34
|
+
*/
|
|
35
|
+
export declare function runEastPyLint(file: string, content?: string, budgetMs?: number, command?: string): Promise<PythonDiagnostic[] | null>;
|
|
36
|
+
/**
|
|
37
|
+
* The BUILD's findings for a python file — `east-py check --format json
|
|
38
|
+
* --only-if-enabled`, the records `runEastPyLint` returns plus the `build` /
|
|
39
|
+
* `import` rules — `[]` when clean or when the project has not opted into the
|
|
40
|
+
* build tier (`[tool.east-py] check = true`), `null` when no east-py answered.
|
|
41
|
+
* A cold subprocess, the right shape for a hook that runs once per file.
|
|
23
42
|
*/
|
|
24
|
-
export declare function
|
|
43
|
+
export declare function runEastPyCheck(file: string, budgetMs?: number, command?: string): Promise<PythonDiagnostic[] | null>;
|
|
25
44
|
/** The findings as the `<east-code-review>` block the plugin injects — `""` when there are none. */
|
|
26
45
|
export declare function renderPythonReview(records: PythonDiagnostic[]): string;
|
|
27
46
|
//# sourceMappingURL=python-lint.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"python-lint.d.ts","sourceRoot":"","sources":["../../src/python-lint.ts"],"names":[],"mappings":"AAeA,8DAA8D;AAC9D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,YAAY,CAAC;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,oGAAoG;AACpG,eAAO,MAAM,kBAAkB,QAAiE,CAAC;AAEjG;8DAC8D;AAC9D,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAYlD;AAED
|
|
1
|
+
{"version":3,"file":"python-lint.d.ts","sourceRoot":"","sources":["../../src/python-lint.ts"],"names":[],"mappings":"AAeA,8DAA8D;AAC9D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,YAAY,CAAC;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,oGAAoG;AACpG,eAAO,MAAM,kBAAkB,QAAiE,CAAC;AAEjG;8DAC8D;AAC9D,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAYlD;AAKD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAerE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,SAAO,EAAE,OAAO,SAA4B,GAAG,OAAO,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,CAgCtJ;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAO,EAAE,OAAO,SAA4B,GAAG,OAAO,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,CAsBrI;AAED,oGAAoG;AACpG,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAItE"}
|
package/dist/src/python-lint.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
5
|
import { execFile } from "node:child_process";
|
|
6
|
-
import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
8
|
import { basename, dirname, join } from "node:path";
|
|
9
9
|
/** A python file that imports east: `import east`, `from east import …`, `from east.x import …`. */
|
|
@@ -26,14 +26,44 @@ export function findEastPy(fromDir) {
|
|
|
26
26
|
dir = parent;
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
+
/** A `pyproject.toml` that declares an east-py distribution as a dependency. */
|
|
30
|
+
const EAST_PY_DEPENDENCY = /elaraai-east-py(?![\w-])|elaraai-east-py-(?:std|io|datascience|cli)(?![\w-])/;
|
|
31
|
+
/**
|
|
32
|
+
* The directory of the nearest `pyproject.toml` at or above `fromDir` that
|
|
33
|
+
* depends on east-py — what makes a directory an east-py PROJECT, as opposed
|
|
34
|
+
* to a python file that happens to import `east`. A uv workspace root that
|
|
35
|
+
* declares it counts for every member below it, so the walk continues past a
|
|
36
|
+
* member's own pyproject that says nothing. `undefined` when nothing above
|
|
37
|
+
* declares it.
|
|
38
|
+
*/
|
|
39
|
+
export function findEastPyProject(fromDir) {
|
|
40
|
+
let dir = fromDir;
|
|
41
|
+
for (;;) {
|
|
42
|
+
const candidate = join(dir, "pyproject.toml");
|
|
43
|
+
if (existsSync(candidate)) {
|
|
44
|
+
try {
|
|
45
|
+
if (EAST_PY_DEPENDENCY.test(readFileSync(candidate, "utf-8")))
|
|
46
|
+
return dir;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
/* unreadable: keep walking */
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const parent = dirname(dir);
|
|
53
|
+
if (parent === dir)
|
|
54
|
+
return undefined;
|
|
55
|
+
dir = parent;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
29
58
|
/**
|
|
30
59
|
* The east-py findings for a python file — `""`-free: `[]` when clean,
|
|
31
60
|
* `null` when no east-py answered (absent, failed, or over `budgetMs`), so
|
|
32
61
|
* callers can stay silent. `content` (an unsaved buffer) is linted from a
|
|
33
62
|
* temporary copy under the file's own name; the file itself otherwise.
|
|
63
|
+
* `command` is the `east-py` to run; by default the one `findEastPy` resolves
|
|
64
|
+
* for the file.
|
|
34
65
|
*/
|
|
35
|
-
export function runEastPyLint(file, content, budgetMs = 4000) {
|
|
36
|
-
const command = findEastPy(dirname(file));
|
|
66
|
+
export function runEastPyLint(file, content, budgetMs = 4000, command = findEastPy(dirname(file))) {
|
|
37
67
|
let target = file;
|
|
38
68
|
let scratch = null;
|
|
39
69
|
if (content !== undefined) {
|
|
@@ -64,6 +94,32 @@ export function runEastPyLint(file, content, budgetMs = 4000) {
|
|
|
64
94
|
});
|
|
65
95
|
});
|
|
66
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* The BUILD's findings for a python file — `east-py check --format json
|
|
99
|
+
* --only-if-enabled`, the records `runEastPyLint` returns plus the `build` /
|
|
100
|
+
* `import` rules — `[]` when clean or when the project has not opted into the
|
|
101
|
+
* build tier (`[tool.east-py] check = true`), `null` when no east-py answered.
|
|
102
|
+
* A cold subprocess, the right shape for a hook that runs once per file.
|
|
103
|
+
*/
|
|
104
|
+
export function runEastPyCheck(file, budgetMs = 8000, command = findEastPy(dirname(file))) {
|
|
105
|
+
return new Promise((resolveFindings) => {
|
|
106
|
+
execFile(command, ["check", "--format", "json", "--only-if-enabled", file], { timeout: budgetMs, encoding: "utf-8", maxBuffer: 4 * 1024 * 1024, env: { ...process.env, PYTHONIOENCODING: "utf-8" } }, (error, stdout) => {
|
|
107
|
+
if (error !== null && error.code !== 1) {
|
|
108
|
+
resolveFindings(null);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
let records;
|
|
112
|
+
try {
|
|
113
|
+
records = JSON.parse(stdout);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
resolveFindings(null);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
resolveFindings(Array.isArray(records) ? records : null);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
}
|
|
67
123
|
/** The findings as the `<east-code-review>` block the plugin injects — `""` when there are none. */
|
|
68
124
|
export function renderPythonReview(records) {
|
|
69
125
|
if (records.length === 0)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"python-lint.js","sourceRoot":"","sources":["../../src/python-lint.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"python-lint.js","sourceRoot":"","sources":["../../src/python-lint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import { type ChildProcessWithoutNullStreams } from "node:child_process";
|
|
6
|
+
export interface PythonDiagnostic {
|
|
7
|
+
range: {
|
|
8
|
+
start: {
|
|
9
|
+
line: number;
|
|
10
|
+
character: number;
|
|
11
|
+
};
|
|
12
|
+
end: {
|
|
13
|
+
line: number;
|
|
14
|
+
character: number;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
severity?: number;
|
|
18
|
+
code?: string | number;
|
|
19
|
+
source?: string;
|
|
20
|
+
message: string;
|
|
21
|
+
}
|
|
22
|
+
export interface PythonLspProxyOptions {
|
|
23
|
+
/** Called when the child publishes diagnostics for a document. */
|
|
24
|
+
onDiagnostics: (uri: string, diagnostics: PythonDiagnostic[]) => void;
|
|
25
|
+
/** Called when a start fails, with the reason — the owner's cue to fall back. */
|
|
26
|
+
onUnavailable?: (reason: string) => void;
|
|
27
|
+
/** Called with each line the child writes to stderr; defaults to this process's stderr. */
|
|
28
|
+
onStderr?: (line: string) => void;
|
|
29
|
+
/** Resolve the `east-py` command for a file's directory; defaults to `findEastPy`. */
|
|
30
|
+
resolveCommand?: (fromDir: string) => string;
|
|
31
|
+
/** Spawn override, for tests. */
|
|
32
|
+
spawnChild?: (command: string, args: string[]) => ChildProcessWithoutNullStreams;
|
|
33
|
+
/** How long to wait for `initialize`; defaults to 15 s. */
|
|
34
|
+
initializeTimeoutMs?: number;
|
|
35
|
+
/** How long to wait after a crash before respawning; defaults to 5 s. */
|
|
36
|
+
restartBackoffMs?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Owns one long-lived `east-py lsp` process and forwards `.py` documents to it.
|
|
40
|
+
*/
|
|
41
|
+
export declare class PythonLspProxy {
|
|
42
|
+
private readonly options;
|
|
43
|
+
private child;
|
|
44
|
+
private readonly reader;
|
|
45
|
+
private nextId;
|
|
46
|
+
private ready;
|
|
47
|
+
private starting;
|
|
48
|
+
private lastExitAt;
|
|
49
|
+
private lastStderr;
|
|
50
|
+
private disposed;
|
|
51
|
+
/** Documents open on the proxy — what a (re)start replays to the child. */
|
|
52
|
+
private readonly open;
|
|
53
|
+
/** path -> the document version the CURRENT child has been sent, by didOpen or didChange. */
|
|
54
|
+
private readonly seenByChild;
|
|
55
|
+
/** id -> settle(answered): true when the child replied, false when it went away. */
|
|
56
|
+
private readonly pending;
|
|
57
|
+
constructor(options: PythonLspProxyOptions);
|
|
58
|
+
/** Whether a child is up and initialized. */
|
|
59
|
+
get available(): boolean;
|
|
60
|
+
private resolveCommand;
|
|
61
|
+
private unavailable;
|
|
62
|
+
/** Start the child if it is not running. Resolves false when it cannot start. */
|
|
63
|
+
private ensure;
|
|
64
|
+
private start;
|
|
65
|
+
private handleExit;
|
|
66
|
+
private write;
|
|
67
|
+
private handle;
|
|
68
|
+
/**
|
|
69
|
+
* Bring the child up to `doc`: a didOpen when this child has not seen the
|
|
70
|
+
* document, a didChange when it has an older version, nothing when a start
|
|
71
|
+
* just replayed exactly this version.
|
|
72
|
+
*/
|
|
73
|
+
private deliver;
|
|
74
|
+
/** Forward an opened document, starting the child if needed. */
|
|
75
|
+
didOpen(path: string, uri: string, text: string): Promise<void>;
|
|
76
|
+
/** Forward a change. */
|
|
77
|
+
didChange(path: string, uri: string, text: string): Promise<void>;
|
|
78
|
+
/** Forward a save — the moment the build tier runs without waiting. */
|
|
79
|
+
didSave(path: string, uri: string, text: string): Promise<void>;
|
|
80
|
+
/** Forward a close. */
|
|
81
|
+
didClose(path: string, uri: string): void;
|
|
82
|
+
/** Stop the child. */
|
|
83
|
+
dispose(): void;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=python-lsp-proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"python-lsp-proxy.d.ts","sourceRoot":"","sources":["../../src/python-lsp-proxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import { spawn } from "node:child_process";
|
|
6
|
+
import { dirname } from "node:path";
|
|
7
|
+
import { findEastPy } from "./python-lint.js";
|
|
8
|
+
import { frame, FrameReader } from "./jsonrpc-stdio.js";
|
|
9
|
+
// One persistent `east-py lsp` child, proxied (#681).
|
|
10
|
+
//
|
|
11
|
+
// The build check (#653) imports the module, and a process per check pays that
|
|
12
|
+
// import every time: measured here, 0.12s for a module whose dependencies
|
|
13
|
+
// import lazily and 0.81s for one importing torch at module scope, against
|
|
14
|
+
// 0.0003s to re-check in a process that already holds them. So the python
|
|
15
|
+
// server stays warm, and this class owns it: started lazily by the first
|
|
16
|
+
// document, verified by its `initialize` reply, restarted after a crash once
|
|
17
|
+
// the backoff has elapsed with every open document replayed, and killed when
|
|
18
|
+
// its owner goes away — on the handshake timeout too, so a child that will not
|
|
19
|
+
// answer is never left running.
|
|
20
|
+
//
|
|
21
|
+
// Every method is safe to call when no child is running: the proxy stays
|
|
22
|
+
// silent rather than erroring. A START that fails — no command, no reply, a
|
|
23
|
+
// child that dies during the handshake — is reported through `onUnavailable`
|
|
24
|
+
// with the reason, so the owner can fall back (the python launcher drops to a
|
|
25
|
+
// cold `east-py lint` per change) instead of hiding the cause.
|
|
26
|
+
/** How long to wait for the child's `initialize` reply before giving up. */
|
|
27
|
+
const INITIALIZE_TIMEOUT_MS = 15_000;
|
|
28
|
+
/** Backoff after a crash, so a child that dies on startup is not respawned hot. */
|
|
29
|
+
const RESTART_BACKOFF_MS = 5_000;
|
|
30
|
+
/**
|
|
31
|
+
* Owns one long-lived `east-py lsp` process and forwards `.py` documents to it.
|
|
32
|
+
*/
|
|
33
|
+
export class PythonLspProxy {
|
|
34
|
+
options;
|
|
35
|
+
child;
|
|
36
|
+
reader = new FrameReader((message) => this.handle(message));
|
|
37
|
+
nextId = 1;
|
|
38
|
+
ready = false;
|
|
39
|
+
starting;
|
|
40
|
+
lastExitAt = 0;
|
|
41
|
+
lastStderr = "";
|
|
42
|
+
disposed = false;
|
|
43
|
+
/** Documents open on the proxy — what a (re)start replays to the child. */
|
|
44
|
+
open = new Map();
|
|
45
|
+
/** path -> the document version the CURRENT child has been sent, by didOpen or didChange. */
|
|
46
|
+
seenByChild = new Map();
|
|
47
|
+
/** id -> settle(answered): true when the child replied, false when it went away. */
|
|
48
|
+
pending = new Map();
|
|
49
|
+
constructor(options) {
|
|
50
|
+
this.options = options;
|
|
51
|
+
}
|
|
52
|
+
/** Whether a child is up and initialized. */
|
|
53
|
+
get available() {
|
|
54
|
+
return this.ready && this.child !== undefined;
|
|
55
|
+
}
|
|
56
|
+
resolveCommand(fromDir) {
|
|
57
|
+
return (this.options.resolveCommand ?? findEastPy)(fromDir);
|
|
58
|
+
}
|
|
59
|
+
unavailable(reason) {
|
|
60
|
+
this.options.onUnavailable?.(reason);
|
|
61
|
+
}
|
|
62
|
+
/** Start the child if it is not running. Resolves false when it cannot start. */
|
|
63
|
+
async ensure(fromDir) {
|
|
64
|
+
if (this.disposed)
|
|
65
|
+
return false;
|
|
66
|
+
if (this.available)
|
|
67
|
+
return true;
|
|
68
|
+
if (this.starting !== undefined)
|
|
69
|
+
return this.starting;
|
|
70
|
+
if (Date.now() - this.lastExitAt < (this.options.restartBackoffMs ?? RESTART_BACKOFF_MS))
|
|
71
|
+
return false;
|
|
72
|
+
this.starting = this.start(fromDir).finally(() => {
|
|
73
|
+
this.starting = undefined;
|
|
74
|
+
});
|
|
75
|
+
return this.starting;
|
|
76
|
+
}
|
|
77
|
+
async start(fromDir) {
|
|
78
|
+
const command = this.resolveCommand(fromDir);
|
|
79
|
+
let child;
|
|
80
|
+
try {
|
|
81
|
+
const spawnChild = this.options.spawnChild ?? ((c, a) => spawn(c, a, { stdio: "pipe" }));
|
|
82
|
+
child = spawnChild(command, ["lsp"]);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
this.lastExitAt = Date.now();
|
|
86
|
+
this.unavailable(`could not spawn \`${command} lsp\`: ${error.message}`);
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
this.child = child;
|
|
90
|
+
this.reader.reset();
|
|
91
|
+
this.seenByChild.clear();
|
|
92
|
+
this.lastStderr = "";
|
|
93
|
+
child.on("error", (error) => {
|
|
94
|
+
// A spawn failure surfaces here, asynchronously — ENOENT for a command
|
|
95
|
+
// that is not there. The handshake below is what reports it.
|
|
96
|
+
this.lastStderr = error.message;
|
|
97
|
+
this.handleExit(child);
|
|
98
|
+
});
|
|
99
|
+
// `close` follows `exit` once the stdio pipes have drained, so the child's
|
|
100
|
+
// last words on stderr (why it could not start) are read before the
|
|
101
|
+
// bookkeeping is cleared; `exit` alone would race them. The grace timer is
|
|
102
|
+
// for a child whose pipes never close.
|
|
103
|
+
child.on("exit", () => {
|
|
104
|
+
const grace = setTimeout(() => this.handleExit(child), 250);
|
|
105
|
+
grace.unref?.();
|
|
106
|
+
});
|
|
107
|
+
child.on("close", () => this.handleExit(child));
|
|
108
|
+
child.stdout.on("data", (chunk) => {
|
|
109
|
+
if (child === this.child)
|
|
110
|
+
this.reader.push(chunk);
|
|
111
|
+
});
|
|
112
|
+
// The child's stderr is where it says WHY it cannot start (a missing pygls
|
|
113
|
+
// says so there): keep the last line for the failure report and pass every
|
|
114
|
+
// line on, so a log of this process shows the cause.
|
|
115
|
+
let stderrRest = "";
|
|
116
|
+
child.stderr.on("data", (chunk) => {
|
|
117
|
+
stderrRest += chunk.toString("utf8");
|
|
118
|
+
const lines = stderrRest.split(/\r?\n/);
|
|
119
|
+
stderrRest = lines.pop() ?? "";
|
|
120
|
+
for (const line of lines) {
|
|
121
|
+
if (line.trim() === "")
|
|
122
|
+
continue;
|
|
123
|
+
this.lastStderr = line;
|
|
124
|
+
(this.options.onStderr ?? ((l) => process.stderr.write(`[east-py lsp] ${l}\n`)))(line);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
// A pipe reports a failed write as an `error` EVENT, never a throw — so a
|
|
128
|
+
// child that has exited before `initialize` reaches it (a real `east-py`
|
|
129
|
+
// that dies on import; the test stand-in under a loaded runner, v1.0.71's
|
|
130
|
+
// run on main) fails that write with EPIPE, the try/catch in `write` never
|
|
131
|
+
// sees it, and with no listener the event is an uncaught exception that
|
|
132
|
+
// takes the owner down. Nothing to do here: `exit` and `close` report the
|
|
133
|
+
// death, once stderr has said why, and the destroyed pipe refuses further
|
|
134
|
+
// writes in `write`.
|
|
135
|
+
for (const stream of [child.stdin, child.stdout, child.stderr]) {
|
|
136
|
+
stream.on("error", () => undefined);
|
|
137
|
+
}
|
|
138
|
+
// A stray child must be physically unable to hold this process open. The
|
|
139
|
+
// process handle AND its three stdio pipes are separate libuv handles, and
|
|
140
|
+
// the `data` reader above keeps the loop alive on its own — unref every
|
|
141
|
+
// one. (The pipes are Sockets at runtime, which have `unref`; the Readable
|
|
142
|
+
// and Writable types they are declared as do not, hence the guarded call.
|
|
143
|
+
// A test's spawn override may hand back a stand-in with none of them.)
|
|
144
|
+
for (const handle of [child, child.stdout, child.stderr, child.stdin]) {
|
|
145
|
+
const unref = handle.unref;
|
|
146
|
+
if (typeof unref === "function")
|
|
147
|
+
unref.call(handle);
|
|
148
|
+
}
|
|
149
|
+
const id = this.nextId++;
|
|
150
|
+
// The resolver takes the OUTCOME: `handleExit` settles every pending entry
|
|
151
|
+
// as failure so a dying child never hangs the caller and never leaves
|
|
152
|
+
// `ready` true with no child attached.
|
|
153
|
+
const initialized = new Promise((resolve) => {
|
|
154
|
+
const timer = setTimeout(() => resolve(false), this.options.initializeTimeoutMs ?? INITIALIZE_TIMEOUT_MS);
|
|
155
|
+
this.pending.set(id, (answered) => {
|
|
156
|
+
clearTimeout(timer);
|
|
157
|
+
resolve(answered);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
this.write({ jsonrpc: "2.0", id, method: "initialize", params: { processId: process.pid, rootUri: null, capabilities: {} } });
|
|
161
|
+
const ok = await initialized;
|
|
162
|
+
if (!ok) {
|
|
163
|
+
const alive = child === this.child;
|
|
164
|
+
const why = this.lastStderr !== ""
|
|
165
|
+
? this.lastStderr
|
|
166
|
+
: alive ? `no initialize reply within ${this.options.initializeTimeoutMs ?? INITIALIZE_TIMEOUT_MS} ms` : "exited during the handshake";
|
|
167
|
+
// A child that never answered is still running: kill it, or it lives on
|
|
168
|
+
// beside its replacement.
|
|
169
|
+
this.handleExit(child);
|
|
170
|
+
this.unavailable(`\`${command} lsp\` did not start: ${why}`);
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
this.write({ jsonrpc: "2.0", method: "initialized", params: {} });
|
|
174
|
+
this.ready = true;
|
|
175
|
+
// Every document open on the proxy is opened on THIS child — a first start
|
|
176
|
+
// and a restart alike, since the child has seen nothing either way. The
|
|
177
|
+
// caller that triggered the start finds its document already open and
|
|
178
|
+
// sends what it meant to send (a change, a save) rather than a second open.
|
|
179
|
+
for (const [path, doc] of this.open) {
|
|
180
|
+
this.write({ jsonrpc: "2.0", method: "textDocument/didOpen", params: { textDocument: { uri: doc.uri, languageId: "python", version: doc.version, text: doc.text } } });
|
|
181
|
+
this.seenByChild.set(path, doc.version);
|
|
182
|
+
}
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
handleExit(child) {
|
|
186
|
+
// Only the child we currently own: a late `exit` from one already replaced
|
|
187
|
+
// must not clear the fresh one's bookkeeping.
|
|
188
|
+
if (child !== this.child)
|
|
189
|
+
return;
|
|
190
|
+
this.child = undefined;
|
|
191
|
+
this.ready = false;
|
|
192
|
+
this.seenByChild.clear();
|
|
193
|
+
this.lastExitAt = Date.now();
|
|
194
|
+
child.removeAllListeners();
|
|
195
|
+
try {
|
|
196
|
+
child.kill();
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
/* already gone */
|
|
200
|
+
}
|
|
201
|
+
// Killing the process is not enough to let this one exit: its stdio pipes
|
|
202
|
+
// are their own libuv handles, and the `data` reader on stdout keeps the
|
|
203
|
+
// event loop alive after the child is gone. Destroy them explicitly.
|
|
204
|
+
for (const stream of [child.stdout, child.stderr, child.stdin]) {
|
|
205
|
+
try {
|
|
206
|
+
stream.destroy();
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
/* already closed */
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
for (const settle of this.pending.values())
|
|
213
|
+
settle(false);
|
|
214
|
+
this.pending.clear();
|
|
215
|
+
}
|
|
216
|
+
write(message) {
|
|
217
|
+
const child = this.child;
|
|
218
|
+
if (child === undefined || child.stdin.destroyed)
|
|
219
|
+
return;
|
|
220
|
+
try {
|
|
221
|
+
child.stdin.write(frame(message));
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
this.handleExit(child);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
handle(message) {
|
|
228
|
+
if (message.id !== undefined && message.id !== null && message.method === undefined) {
|
|
229
|
+
const settle = this.pending.get(message.id);
|
|
230
|
+
if (settle !== undefined) {
|
|
231
|
+
this.pending.delete(message.id);
|
|
232
|
+
settle(true);
|
|
233
|
+
}
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
if (message.method === "textDocument/publishDiagnostics") {
|
|
237
|
+
const uri = message.params?.uri;
|
|
238
|
+
if (typeof uri === "string") {
|
|
239
|
+
this.options.onDiagnostics(uri, (message.params?.diagnostics ?? []));
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Bring the child up to `doc`: a didOpen when this child has not seen the
|
|
245
|
+
* document, a didChange when it has an older version, nothing when a start
|
|
246
|
+
* just replayed exactly this version.
|
|
247
|
+
*/
|
|
248
|
+
deliver(path, doc) {
|
|
249
|
+
const delivered = this.seenByChild.get(path);
|
|
250
|
+
if (delivered === doc.version)
|
|
251
|
+
return;
|
|
252
|
+
if (delivered === undefined) {
|
|
253
|
+
this.write({ jsonrpc: "2.0", method: "textDocument/didOpen", params: { textDocument: { uri: doc.uri, languageId: "python", version: doc.version, text: doc.text } } });
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
this.write({ jsonrpc: "2.0", method: "textDocument/didChange", params: { textDocument: { uri: doc.uri, version: doc.version }, contentChanges: [{ text: doc.text }] } });
|
|
257
|
+
}
|
|
258
|
+
this.seenByChild.set(path, doc.version);
|
|
259
|
+
}
|
|
260
|
+
/** Forward an opened document, starting the child if needed. */
|
|
261
|
+
async didOpen(path, uri, text) {
|
|
262
|
+
const doc = { uri, text, version: 1 };
|
|
263
|
+
this.open.set(path, doc);
|
|
264
|
+
if (!(await this.ensure(dirname(path))))
|
|
265
|
+
return;
|
|
266
|
+
this.deliver(path, doc);
|
|
267
|
+
}
|
|
268
|
+
/** Forward a change. */
|
|
269
|
+
async didChange(path, uri, text) {
|
|
270
|
+
const known = this.open.get(path);
|
|
271
|
+
const doc = { uri, text, version: (known?.version ?? 0) + 1 };
|
|
272
|
+
this.open.set(path, doc);
|
|
273
|
+
if (!(await this.ensure(dirname(path))))
|
|
274
|
+
return;
|
|
275
|
+
this.deliver(path, doc);
|
|
276
|
+
}
|
|
277
|
+
/** Forward a save — the moment the build tier runs without waiting. */
|
|
278
|
+
async didSave(path, uri, text) {
|
|
279
|
+
const known = this.open.get(path);
|
|
280
|
+
const doc = { uri, text, version: known?.version ?? 1 };
|
|
281
|
+
this.open.set(path, doc);
|
|
282
|
+
if (!(await this.ensure(dirname(path))))
|
|
283
|
+
return;
|
|
284
|
+
this.deliver(path, doc);
|
|
285
|
+
this.write({ jsonrpc: "2.0", method: "textDocument/didSave", params: { textDocument: { uri }, text } });
|
|
286
|
+
}
|
|
287
|
+
/** Forward a close. */
|
|
288
|
+
didClose(path, uri) {
|
|
289
|
+
this.open.delete(path);
|
|
290
|
+
if (!this.available || !this.seenByChild.has(path))
|
|
291
|
+
return;
|
|
292
|
+
this.seenByChild.delete(path);
|
|
293
|
+
this.write({ jsonrpc: "2.0", method: "textDocument/didClose", params: { textDocument: { uri } } });
|
|
294
|
+
}
|
|
295
|
+
/** Stop the child. */
|
|
296
|
+
dispose() {
|
|
297
|
+
this.disposed = true;
|
|
298
|
+
this.open.clear();
|
|
299
|
+
const child = this.child;
|
|
300
|
+
if (child !== undefined)
|
|
301
|
+
this.handleExit(child);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=python-lsp-proxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"python-lsp-proxy.js","sourceRoot":"","sources":["../../src/python-lsp-proxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type PythonDiagnostic as LintRecord } from "./python-lint.js";
|
|
2
|
+
import type { ChildProcessWithoutNullStreams } from "node:child_process";
|
|
3
|
+
export interface EastPyLspOptions {
|
|
4
|
+
input?: NodeJS.ReadableStream;
|
|
5
|
+
output?: NodeJS.WritableStream;
|
|
6
|
+
/** Called on `exit`; defaults to `process.exit`. */
|
|
7
|
+
exit?: (code: number) => void;
|
|
8
|
+
/** Where the launcher explains itself; defaults to this process's stderr. */
|
|
9
|
+
log?: (line: string) => void;
|
|
10
|
+
/** Whether `fromDir` belongs to an east-py project; defaults to the pyproject / venv / override walk. */
|
|
11
|
+
eastPythonProject?: (fromDir: string) => boolean;
|
|
12
|
+
/** Resolve the `east-py` command for a directory; defaults to `findEastPy`. */
|
|
13
|
+
resolveCommand?: (fromDir: string) => string;
|
|
14
|
+
/** Spawn override for the child, for tests. */
|
|
15
|
+
spawnChild?: (command: string, args: string[]) => ChildProcessWithoutNullStreams;
|
|
16
|
+
/** The cold lint used when the child cannot start; defaults to `runEastPyLint`. */
|
|
17
|
+
lint?: (file: string, content: string | undefined) => Promise<LintRecord[] | null>;
|
|
18
|
+
initializeTimeoutMs?: number;
|
|
19
|
+
restartBackoffMs?: number;
|
|
20
|
+
}
|
|
21
|
+
/** Whether a directory belongs to a project that uses east-py — the default gate. */
|
|
22
|
+
export declare function isEastPythonProject(fromDir: string): boolean;
|
|
23
|
+
/** Run the python East language server until the client disconnects. */
|
|
24
|
+
export declare function runEastPyLsp(options?: EastPyLspOptions): void;
|
|
25
|
+
//# sourceMappingURL=python-lsp-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"python-lsp-server.d.ts","sourceRoot":"","sources":["../../src/python-lsp-server.ts"],"names":[],"mappings":"AAQA,OAAO,EAKL,KAAK,gBAAgB,IAAI,UAAU,EACpC,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AA2DzE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC/B,oDAAoD;IACpD,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,6EAA6E;IAC7E,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,yGAAyG;IACzG,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IACjD,+EAA+E;IAC/E,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7C,+CAA+C;IAC/C,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,8BAA8B,CAAC;IACjF,mFAAmF;IACnF,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;IACnF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,qFAAqF;AACrF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAO5D;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,OAAO,GAAE,gBAAqB,GAAG,IAAI,CAoLjE"}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync } from "node:fs";
|
|
6
|
+
import { dirname } from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { frame, FrameReader } from "./jsonrpc-stdio.js";
|
|
9
|
+
import { findEastPy, findEastPyProject, PYTHON_EAST_IMPORT, runEastPyLint, } from "./python-lint.js";
|
|
10
|
+
import { PythonLspProxy } from "./python-lsp-proxy.js";
|
|
11
|
+
// The python language server the Claude Code plugin registers for `.py` files
|
|
12
|
+
// (#681): a launcher around the project's own `east-py lsp`.
|
|
13
|
+
//
|
|
14
|
+
// It is its own server, beside the TypeScript one, rather than a proxy hidden
|
|
15
|
+
// inside it, so each language has its own lifecycle: a python-only project
|
|
16
|
+
// never starts the TypeScript service, a TypeScript project never spawns
|
|
17
|
+
// python, and a crash in one is the other's business no more than a crash in
|
|
18
|
+
// pyright would be. It is a launcher rather than `east-py lsp` itself because
|
|
19
|
+
// a manifest can only name a command on PATH or under the plugin root, and the
|
|
20
|
+
// right `east-py` lives in the project's venv (`findEastPy`).
|
|
21
|
+
//
|
|
22
|
+
// What it does for a `.py` document, in order:
|
|
23
|
+
//
|
|
24
|
+
// 1. Nothing, unless the document imports east AND its directory belongs to an
|
|
25
|
+
// east-py PROJECT — a `pyproject.toml` above it declares an east-py
|
|
26
|
+
// distribution, or `EAST_PY_LINT` names the command outright, or a `.venv`
|
|
27
|
+
// above it has `east-py`. The manifest cannot be conditional, so this
|
|
28
|
+
// process starts for any `.py` file anywhere the plugin is enabled; the gate
|
|
29
|
+
// is what keeps it a silent null server everywhere else. It never claims a
|
|
30
|
+
// file is clean: an empty publish means "not mine".
|
|
31
|
+
// 2. Starts ONE `east-py lsp` child — the warm two-tier server — verified by its
|
|
32
|
+
// `initialize` reply, restarted after a crash with the open documents
|
|
33
|
+
// replayed, killed when the client goes away.
|
|
34
|
+
// 3. Falls back, when that child cannot START, to what the plugin did before
|
|
35
|
+
// the warm server existed: `east-py lint --format json` as a cold subprocess
|
|
36
|
+
// per debounced change. The rules never disappear because pygls is missing;
|
|
37
|
+
// only the build tier does, and stderr says why.
|
|
38
|
+
const LINT_DEBOUNCE_MS = 100;
|
|
39
|
+
const SEVERITY = { error: 1, warning: 2, suggestion: 3 };
|
|
40
|
+
function uriToPath(uri) {
|
|
41
|
+
if (!uri.startsWith("file://"))
|
|
42
|
+
return undefined;
|
|
43
|
+
try {
|
|
44
|
+
return fileURLToPath(uri);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** A lint record in the shape `east-py lsp` publishes, so both paths look the same to the client. */
|
|
51
|
+
function toDiagnostic(record) {
|
|
52
|
+
const endLine = record.end_line ?? record.line;
|
|
53
|
+
const endColumn = record.end_column ?? record.column + 1;
|
|
54
|
+
return {
|
|
55
|
+
range: {
|
|
56
|
+
start: { line: record.line - 1, character: Math.max(record.column - 1, 0) },
|
|
57
|
+
end: { line: endLine - 1, character: Math.max(endColumn - 1, 0) },
|
|
58
|
+
},
|
|
59
|
+
severity: SEVERITY[record.category] ?? 1,
|
|
60
|
+
code: record.code,
|
|
61
|
+
source: "east-py",
|
|
62
|
+
message: `${record.message} [${record.rule}]`,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/** Whether a directory belongs to a project that uses east-py — the default gate. */
|
|
66
|
+
export function isEastPythonProject(fromDir) {
|
|
67
|
+
const override = process.env["EAST_PY_LINT"];
|
|
68
|
+
if (override !== undefined && override !== "")
|
|
69
|
+
return true;
|
|
70
|
+
if (findEastPyProject(fromDir) !== undefined)
|
|
71
|
+
return true;
|
|
72
|
+
// a resolvable venv east-py is evidence enough, pyproject or not
|
|
73
|
+
const command = findEastPy(fromDir);
|
|
74
|
+
return command !== "east-py";
|
|
75
|
+
}
|
|
76
|
+
/** Run the python East language server until the client disconnects. */
|
|
77
|
+
export function runEastPyLsp(options = {}) {
|
|
78
|
+
const input = options.input ?? process.stdin;
|
|
79
|
+
const output = options.output ?? process.stdout;
|
|
80
|
+
const exit = options.exit ?? ((code) => process.exit(code));
|
|
81
|
+
const log = options.log ?? ((line) => process.stderr.write(`[east-py] ${line}\n`));
|
|
82
|
+
const inProject = options.eastPythonProject ?? isEastPythonProject;
|
|
83
|
+
const resolveCommand = options.resolveCommand ?? findEastPy;
|
|
84
|
+
// The fallback runs the same `east-py` the child would have: one resolution
|
|
85
|
+
// for both paths, so "the server cannot start" never turns into "some other
|
|
86
|
+
// east-py on PATH answers instead".
|
|
87
|
+
const lint = options.lint ?? ((file, content) => runEastPyLint(file, content, 4000, resolveCommand(dirname(file))));
|
|
88
|
+
// path -> the client's uri and the current buffer
|
|
89
|
+
const open = new Map();
|
|
90
|
+
const pendingLint = new Map();
|
|
91
|
+
const gated = new Map();
|
|
92
|
+
let mode = "child";
|
|
93
|
+
let shuttingDown = false;
|
|
94
|
+
let disposed = false;
|
|
95
|
+
function send(message) {
|
|
96
|
+
output.write(frame(message));
|
|
97
|
+
}
|
|
98
|
+
function publish(uri, diagnostics) {
|
|
99
|
+
send({ method: "textDocument/publishDiagnostics", params: { uri, diagnostics } });
|
|
100
|
+
}
|
|
101
|
+
const python = new PythonLspProxy({
|
|
102
|
+
onDiagnostics: publish,
|
|
103
|
+
onStderr: (line) => log(`east-py lsp: ${line}`),
|
|
104
|
+
onUnavailable: (reason) => {
|
|
105
|
+
if (mode === "lint")
|
|
106
|
+
return;
|
|
107
|
+
mode = "lint";
|
|
108
|
+
log(`${reason} — falling back to \`east-py lint\` per change; the build tier is off until it starts (east-py lsp --probe says why)`);
|
|
109
|
+
for (const [path, doc] of open)
|
|
110
|
+
lintLater(path, doc.uri);
|
|
111
|
+
},
|
|
112
|
+
...(options.resolveCommand !== undefined ? { resolveCommand: options.resolveCommand } : {}),
|
|
113
|
+
...(options.spawnChild !== undefined ? { spawnChild: options.spawnChild } : {}),
|
|
114
|
+
...(options.initializeTimeoutMs !== undefined ? { initializeTimeoutMs: options.initializeTimeoutMs } : {}),
|
|
115
|
+
...(options.restartBackoffMs !== undefined ? { restartBackoffMs: options.restartBackoffMs } : {}),
|
|
116
|
+
});
|
|
117
|
+
function lintLater(path, uri) {
|
|
118
|
+
const existing = pendingLint.get(path);
|
|
119
|
+
if (existing !== undefined)
|
|
120
|
+
clearTimeout(existing);
|
|
121
|
+
pendingLint.set(path, setTimeout(() => {
|
|
122
|
+
pendingLint.delete(path);
|
|
123
|
+
const doc = open.get(path);
|
|
124
|
+
if (doc === undefined)
|
|
125
|
+
return;
|
|
126
|
+
void lint(path, doc.text).then((records) => {
|
|
127
|
+
// no east-py answered: say nothing rather than "clean"
|
|
128
|
+
if (records === null || open.get(path) !== doc)
|
|
129
|
+
return;
|
|
130
|
+
publish(uri, records.map(toDiagnostic));
|
|
131
|
+
});
|
|
132
|
+
}, LINT_DEBOUNCE_MS));
|
|
133
|
+
}
|
|
134
|
+
/** Whether this document is ours: a `.py` that imports east, in an east-py project. */
|
|
135
|
+
function ours(path, text) {
|
|
136
|
+
if (!path.endsWith(".py") || !PYTHON_EAST_IMPORT.test(text))
|
|
137
|
+
return false;
|
|
138
|
+
const dir = dirname(path);
|
|
139
|
+
let verdict = gated.get(dir);
|
|
140
|
+
if (verdict === undefined) {
|
|
141
|
+
verdict = inProject(dir);
|
|
142
|
+
gated.set(dir, verdict);
|
|
143
|
+
if (!verdict)
|
|
144
|
+
log(`${dir} is not an east-py project (no pyproject.toml above it depends on elaraai-east-py, no .venv east-py, no EAST_PY_LINT): python diagnostics stay idle there`);
|
|
145
|
+
}
|
|
146
|
+
return verdict;
|
|
147
|
+
}
|
|
148
|
+
function forward(kind, path, uri, text) {
|
|
149
|
+
if (!ours(path, text)) {
|
|
150
|
+
const was = open.get(path);
|
|
151
|
+
open.delete(path);
|
|
152
|
+
if (was !== undefined && mode === "child")
|
|
153
|
+
python.didClose(path, uri);
|
|
154
|
+
publish(uri, []);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
open.set(path, { uri, text });
|
|
158
|
+
if (mode === "lint") {
|
|
159
|
+
lintLater(path, uri);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
void (kind === "open" ? python.didOpen(path, uri, text)
|
|
163
|
+
: kind === "save" ? python.didSave(path, uri, text)
|
|
164
|
+
: python.didChange(path, uri, text));
|
|
165
|
+
}
|
|
166
|
+
function readSource(path) {
|
|
167
|
+
try {
|
|
168
|
+
return readFileSync(path, "utf-8");
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
function handle(message) {
|
|
175
|
+
const { method, id, params } = message;
|
|
176
|
+
if (method === undefined)
|
|
177
|
+
return; // a response — we send no requests to the client
|
|
178
|
+
switch (method) {
|
|
179
|
+
case "initialize":
|
|
180
|
+
send({
|
|
181
|
+
id,
|
|
182
|
+
result: {
|
|
183
|
+
capabilities: {
|
|
184
|
+
textDocumentSync: { openClose: true, change: 1, save: { includeText: true } },
|
|
185
|
+
},
|
|
186
|
+
serverInfo: { name: "east-py-diagnostics" },
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
return;
|
|
190
|
+
case "initialized":
|
|
191
|
+
return;
|
|
192
|
+
case "shutdown":
|
|
193
|
+
shuttingDown = true;
|
|
194
|
+
send({ id, result: null });
|
|
195
|
+
return;
|
|
196
|
+
case "exit":
|
|
197
|
+
shutdown(shuttingDown ? 0 : 1);
|
|
198
|
+
return;
|
|
199
|
+
case "textDocument/didOpen": {
|
|
200
|
+
const path = uriToPath(params?.textDocument?.uri ?? "");
|
|
201
|
+
const text = params?.textDocument?.text;
|
|
202
|
+
if (path === undefined || typeof text !== "string")
|
|
203
|
+
return;
|
|
204
|
+
forward("open", path, params.textDocument.uri, text);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
case "textDocument/didChange": {
|
|
208
|
+
const path = uriToPath(params?.textDocument?.uri ?? "");
|
|
209
|
+
const text = params?.contentChanges?.at?.(-1)?.text;
|
|
210
|
+
if (path === undefined || typeof text !== "string")
|
|
211
|
+
return;
|
|
212
|
+
forward("change", path, params.textDocument.uri, text);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
case "textDocument/didSave": {
|
|
216
|
+
const path = uriToPath(params?.textDocument?.uri ?? "");
|
|
217
|
+
if (path === undefined)
|
|
218
|
+
return;
|
|
219
|
+
const text = typeof params?.text === "string" ? params.text : (open.get(path)?.text ?? readSource(path));
|
|
220
|
+
if (text === undefined)
|
|
221
|
+
return;
|
|
222
|
+
forward("save", path, params.textDocument.uri, text);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
case "textDocument/didClose": {
|
|
226
|
+
const uri = params?.textDocument?.uri ?? "";
|
|
227
|
+
const path = uriToPath(uri);
|
|
228
|
+
if (path === undefined)
|
|
229
|
+
return;
|
|
230
|
+
const timer = pendingLint.get(path);
|
|
231
|
+
if (timer !== undefined)
|
|
232
|
+
clearTimeout(timer);
|
|
233
|
+
pendingLint.delete(path);
|
|
234
|
+
if (open.delete(path) && mode === "child")
|
|
235
|
+
python.didClose(path, uri);
|
|
236
|
+
publish(uri, []);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
default:
|
|
240
|
+
if (id !== undefined) {
|
|
241
|
+
send({ id, error: { code: -32601, message: `Method not found: ${method}` } });
|
|
242
|
+
}
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
const reader = new FrameReader(handle);
|
|
247
|
+
input.on("data", (chunk) => reader.push(chunk));
|
|
248
|
+
// The client going away ends the session, and the python child must go with
|
|
249
|
+
// it. Wiring this only to the `exit` MESSAGE is not enough: a disconnecting
|
|
250
|
+
// client may never send one.
|
|
251
|
+
const shutdown = (code) => {
|
|
252
|
+
if (disposed)
|
|
253
|
+
return;
|
|
254
|
+
disposed = true;
|
|
255
|
+
for (const timer of pendingLint.values())
|
|
256
|
+
clearTimeout(timer);
|
|
257
|
+
pendingLint.clear();
|
|
258
|
+
python.dispose();
|
|
259
|
+
exit(code);
|
|
260
|
+
};
|
|
261
|
+
input.on("close", () => shutdown(0));
|
|
262
|
+
input.on("end", () => shutdown(0));
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=python-lsp-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"python-lsp-server.js","sourceRoot":"","sources":["../../src/python-lsp-server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,WAAW,EAAuB,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,GAEd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAyB,MAAM,uBAAuB,CAAC;AAG9E,8EAA8E;AAC9E,6DAA6D;AAC7D,EAAE;AACF,8EAA8E;AAC9E,2EAA2E;AAC3E,yEAAyE;AACzE,6EAA6E;AAC7E,8EAA8E;AAC9E,+EAA+E;AAC/E,8DAA8D;AAC9D,EAAE;AACF,+CAA+C;AAC/C,EAAE;AACF,+EAA+E;AAC/E,uEAAuE;AACvE,8EAA8E;AAC9E,yEAAyE;AACzE,gFAAgF;AAChF,8EAA8E;AAC9E,uDAAuD;AACvD,iFAAiF;AACjF,yEAAyE;AACzE,iDAAiD;AACjD,6EAA6E;AAC7E,gFAAgF;AAChF,+EAA+E;AAC/E,oDAAoD;AAEpD,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B,MAAM,QAAQ,GAA2B,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;AAEjF,SAAS,SAAS,CAAC,GAAW;IAC5B,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IACjD,IAAI,CAAC;QACH,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,qGAAqG;AACrG,SAAS,YAAY,CAAC,MAAkB;IACtC,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC;IAC/C,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACzD,OAAO;QACL,KAAK,EAAE;YACL,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,GAAG,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE;YAC3E,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,GAAG,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE;SAClE;QACD,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QACxC,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,SAAS;QACjB,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,KAAK,MAAM,CAAC,IAAI,GAAG;KAC9C,CAAC;AACJ,CAAC;AAqBD,qFAAqF;AACrF,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC7C,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC3D,IAAI,iBAAiB,CAAC,OAAO,CAAC,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC1D,iEAAiE;IACjE,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IACpC,OAAO,OAAO,KAAK,SAAS,CAAC;AAC/B,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,YAAY,CAAC,UAA4B,EAAE;IACzD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC;IAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAChD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACpE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,IAAI,IAAI,CAAC,CAAC,CAAC;IAC3F,MAAM,SAAS,GAAG,OAAO,CAAC,iBAAiB,IAAI,mBAAmB,CAAC;IACnE,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,UAAU,CAAC;IAC5D,4EAA4E;IAC5E,4EAA4E;IAC5E,oCAAoC;IACpC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,IAAY,EAAE,OAA2B,EAAE,EAAE,CAC1E,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAErE,kDAAkD;IAClD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAyC,CAAC;IAC9D,MAAM,WAAW,GAAG,IAAI,GAAG,EAAyC,CAAC;IACrE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAmB,CAAC;IACzC,IAAI,IAAI,GAAqB,OAAO,CAAC;IACrC,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,SAAS,IAAI,CAAC,OAAe;QAC3B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/B,CAAC;IAED,SAAS,OAAO,CAAC,GAAW,EAAE,WAA+B;QAC3D,IAAI,CAAC,EAAE,MAAM,EAAE,iCAAiC,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC;QAChC,aAAa,EAAE,OAAO;QACtB,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE,CAAC;QAC/C,aAAa,EAAE,CAAC,MAAM,EAAE,EAAE;YACxB,IAAI,IAAI,KAAK,MAAM;gBAAE,OAAO;YAC5B,IAAI,GAAG,MAAM,CAAC;YACd,GAAG,CAAC,GAAG,MAAM,sHAAsH,CAAC,CAAC;YACrI,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI;gBAAE,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3D,CAAC;QACD,GAAG,CAAC,OAAO,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3F,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/E,GAAG,CAAC,OAAO,CAAC,mBAAmB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1G,GAAG,CAAC,OAAO,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClG,CAAC,CAAC;IAEH,SAAS,SAAS,CAAC,IAAY,EAAE,GAAW;QAC1C,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,QAAQ,KAAK,SAAS;YAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;QACnD,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,GAAG,EAAE;YACpC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACzB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,GAAG,KAAK,SAAS;gBAAE,OAAO;YAC9B,KAAK,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;gBACzC,uDAAuD;gBACvD,IAAI,OAAO,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG;oBAAE,OAAO;gBACvD,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;YAC1C,CAAC,CAAC,CAAC;QACL,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC;IACxB,CAAC;IAED,uFAAuF;IACvF,SAAS,IAAI,CAAC,IAAY,EAAE,IAAY;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QAC1E,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;YACzB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACxB,IAAI,CAAC,OAAO;gBAAE,GAAG,CAAC,GAAG,GAAG,2JAA2J,CAAC,CAAC;QACvL,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,SAAS,OAAO,CAAC,IAAgC,EAAE,IAAY,EAAE,GAAW,EAAE,IAAY;QACxF,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACtB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAClB,IAAI,GAAG,KAAK,SAAS,IAAI,IAAI,KAAK,OAAO;gBAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACtE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACjB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9B,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC;YACrD,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC;gBACjD,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED,SAAS,UAAU,CAAC,IAAY;QAC9B,IAAI,CAAC;YACH,OAAO,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACrC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAED,SAAS,MAAM,CAAC,OAAuB;QACrC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QACvC,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,CAAC,iDAAiD;QAEnF,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,YAAY;gBACf,IAAI,CAAC;oBACH,EAAE;oBACF,MAAM,EAAE;wBACN,YAAY,EAAE;4BACZ,gBAAgB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE;yBAC9E;wBACD,UAAU,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE;qBAC5C;iBACF,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,aAAa;gBAChB,OAAO;YACT,KAAK,UAAU;gBACb,YAAY,GAAG,IAAI,CAAC;gBACpB,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC3B,OAAO;YACT,KAAK,MAAM;gBACT,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC/B,OAAO;YACT,KAAK,sBAAsB,CAAC,CAAC,CAAC;gBAC5B,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;gBACxD,MAAM,IAAI,GAAG,MAAM,EAAE,YAAY,EAAE,IAAI,CAAC;gBACxC,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,KAAK,QAAQ;oBAAE,OAAO;gBAC3D,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBACrD,OAAO;YACT,CAAC;YACD,KAAK,wBAAwB,CAAC,CAAC,CAAC;gBAC9B,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;gBACxD,MAAM,IAAI,GAAG,MAAM,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;gBACpD,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,KAAK,QAAQ;oBAAE,OAAO;gBAC3D,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBACvD,OAAO;YACT,CAAC;YACD,KAAK,sBAAsB,CAAC,CAAC,CAAC;gBAC5B,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;gBACxD,IAAI,IAAI,KAAK,SAAS;oBAAE,OAAO;gBAC/B,MAAM,IAAI,GAAG,OAAO,MAAM,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;gBACzG,IAAI,IAAI,KAAK,SAAS;oBAAE,OAAO;gBAC/B,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBACrD,OAAO;YACT,CAAC;YACD,KAAK,uBAAuB,CAAC,CAAC,CAAC;gBAC7B,MAAM,GAAG,GAAW,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,CAAC;gBACpD,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;gBAC5B,IAAI,IAAI,KAAK,SAAS;oBAAE,OAAO;gBAC/B,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACpC,IAAI,KAAK,KAAK,SAAS;oBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;gBAC7C,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACzB,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,OAAO;oBAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;gBACtE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBACjB,OAAO;YACT,CAAC;YACD;gBACE,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;oBACrB,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,qBAAqB,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;gBAChF,CAAC;gBACD,OAAO;QACX,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;IACvC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAExD,4EAA4E;IAC5E,4EAA4E;IAC5E,6BAA6B;IAC7B,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAQ,EAAE;QACtC,IAAI,QAAQ;YAAE,OAAO;QACrB,QAAQ,GAAG,IAAI,CAAC;QAChB,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,MAAM,EAAE;YAAE,YAAY,CAAC,KAAK,CAAC,CAAC;QAC9D,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,CAAC,CAAC;IACF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elaraai/east-diagnostics",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.72",
|
|
4
4
|
"license": "AGPL-3.0-or-later",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "East-aware diagnostic rules over the TypeScript checker — one shared engine for the editor (tsserver plugin), the agent (headless daemon), and CI.",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/node": "^22.18.1",
|
|
46
46
|
"typescript": "~5.9.2",
|
|
47
|
-
"@elaraai/e3": "1.0.
|
|
48
|
-
"@elaraai/east": "1.0.
|
|
47
|
+
"@elaraai/e3": "1.0.72",
|
|
48
|
+
"@elaraai/east": "1.0.72"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "tsc",
|