@openrewrite/rewrite 8.86.3 → 8.86.5
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/rewrite-javascript-version.txt +1 -0
- package/dist/rpc/java-rpc-client.d.ts.map +1 -1
- package/dist/rpc/java-rpc-client.js +5 -1
- package/dist/rpc/java-rpc-client.js.map +1 -1
- package/dist/rpc/message-decoder.d.ts +35 -0
- package/dist/rpc/message-decoder.d.ts.map +1 -0
- package/dist/rpc/message-decoder.js +222 -0
- package/dist/rpc/message-decoder.js.map +1 -0
- package/dist/rpc/message-encoder.d.ts +1 -1
- package/dist/rpc/message-encoder.js +1 -1
- package/dist/rpc/server.d.ts.map +1 -1
- package/dist/rpc/server.js +9 -3
- package/dist/rpc/server.js.map +1 -1
- package/package.json +1 -1
- package/src/rpc/java-rpc-client.ts +4 -1
- package/src/rpc/message-decoder.ts +234 -0
- package/src/rpc/message-encoder.ts +1 -1
- package/src/rpc/server.ts +8 -3
- package/src/java/s.js~ +0 -48
- package/src/javascript/s.js~ +0 -48
- package/src/javascript/s2.js~ +0 -68
|
@@ -0,0 +1 @@
|
|
|
1
|
+
8.86.5
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"java-rpc-client.d.ts","sourceRoot":"","sources":["../../src/rpc/java-rpc-client.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,GAAG,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"java-rpc-client.d.ts","sourceRoot":"","sources":["../../src/rpc/java-rpc-client.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,GAAG,MAAM,qBAAqB,CAAC;AAE3C,OAAO,EAAC,UAAU,EAAC,MAAM,eAAe,CAAC;AACzC,OAAO,EAAC,iBAAiB,EAAC,MAAM,gBAAgB,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC3B,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC;IACpB,4FAA4F;IAC5F,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iEAAiE;IACjE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,iBAAiB,CAAC;CACnC;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,iBAAiB;IAEtB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,QAAQ,CAAC,GAAG,EAAE,UAAU;IAF5B,OAAO;IAMP,sFAAsF;WACzE,KAAK,CAAC,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAwEzE;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CA6BjC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAoBtD"}
|
|
@@ -55,6 +55,7 @@ const path = __importStar(require("node:path"));
|
|
|
55
55
|
const readline = __importStar(require("node:readline"));
|
|
56
56
|
const node_child_process_1 = require("node:child_process");
|
|
57
57
|
const rpc = __importStar(require("vscode-jsonrpc/node"));
|
|
58
|
+
const message_decoder_1 = require("./message-decoder");
|
|
58
59
|
const rewrite_rpc_1 = require("./rewrite-rpc");
|
|
59
60
|
/**
|
|
60
61
|
* Test-only wrapper around a spawned `org.openrewrite.maven.rpc.JavaRewriteRpc` process,
|
|
@@ -113,7 +114,10 @@ class JavaRpcTestServer {
|
|
|
113
114
|
};
|
|
114
115
|
child.once("exit", onEarlyExit);
|
|
115
116
|
});
|
|
116
|
-
const connection = rpc.createMessageConnection(
|
|
117
|
+
const connection = rpc.createMessageConnection(
|
|
118
|
+
// Trees and recipe descriptors cross this connection too, so it needs the same headroom
|
|
119
|
+
// as the server's: the default decoder caps an inbound message at V8's ~512 MB string limit.
|
|
120
|
+
new rpc.StreamMessageReader(child.stdout, { contentTypeDecoder: message_decoder_1.chunkedJsonDecoder }), new rpc.StreamMessageWriter(child.stdin), opts.logger);
|
|
117
121
|
// RewriteRpc's constructor calls connection.listen() — no need to call it ourselves.
|
|
118
122
|
const rewriteRpc = new rewrite_rpc_1.RewriteRpc(connection, {
|
|
119
123
|
marketplace: opts.marketplace,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"java-rpc-client.js","sourceRoot":"","sources":["../../src/rpc/java-rpc-client.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"java-rpc-client.js","sourceRoot":"","sources":["../../src/rpc/java-rpc-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { MessageReaderOptions } from "vscode-jsonrpc/node";
|
|
2
|
+
/**
|
|
3
|
+
* The content-type decoder shape vscode-jsonrpc's {@link MessageReaderOptions} accepts. Derived
|
|
4
|
+
* from the reader options rather than deep-imported, because the concrete `ContentTypeDecoder`
|
|
5
|
+
* type is not re-exported from the package entrypoint.
|
|
6
|
+
*/
|
|
7
|
+
export type JsonRpcContentTypeDecoder = NonNullable<MessageReaderOptions["contentTypeDecoder"]>;
|
|
8
|
+
/**
|
|
9
|
+
* Parses JSON directly from its UTF-8 bytes, never materializing the whole document as one JS
|
|
10
|
+
* string. Structural punctuation is recognized byte-by-byte, while every scalar and every object key
|
|
11
|
+
* is handed to the engine's `JSON.parse` as its own small slice — so escaping, number formatting and
|
|
12
|
+
* literal validation match it exactly. This is the mirror of how `jsonFragments` defers to
|
|
13
|
+
* `JSON.stringify`, and it accepts precisely the grammar `JSON.parse` accepts.
|
|
14
|
+
*
|
|
15
|
+
* Byte-level scanning is safe for the ASCII-compatible charsets vscode-jsonrpc supports (`utf-8`,
|
|
16
|
+
* `ascii`): a UTF-8 continuation byte is always >= 0x80, so it can never be mistaken for a quote,
|
|
17
|
+
* backslash, or structural character. Containers are tracked on an explicit stack, so nesting depth
|
|
18
|
+
* is bounded by heap rather than by the call stack.
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseJsonBytes(buf: Buffer, charset: BufferEncoding): unknown;
|
|
21
|
+
/**
|
|
22
|
+
* A drop-in replacement for vscode-jsonrpc's default `application/json` content-type decoder, which
|
|
23
|
+
* does {@code JSON.parse(buffer.toString(charset))}. That intermediate string is capped at V8's
|
|
24
|
+
* String.kMaxLength (~512 MB), so an inbound message above the cap throws "Cannot create a string
|
|
25
|
+
* longer than 0x1fffffe8 characters" before it is ever parsed — the reader drops the message, the
|
|
26
|
+
* peer's request is never answered, and the call hangs until it times out. Parsing straight from the
|
|
27
|
+
* bytes raises the inbound ceiling to Node's Buffer.MAX_LENGTH, matching what {@link
|
|
28
|
+
* chunkedJsonEncoder} does for outbound messages.
|
|
29
|
+
*
|
|
30
|
+
* A UTF-8 (or ASCII) decode never yields more UTF-16 code units than there are bytes, so a body at
|
|
31
|
+
* or under the cap cannot overflow the intermediate string; those take the faster single-string
|
|
32
|
+
* parse, and only genuinely oversized bodies pay for the byte-level walk.
|
|
33
|
+
*/
|
|
34
|
+
export declare const chunkedJsonDecoder: JsonRpcContentTypeDecoder;
|
|
35
|
+
//# sourceMappingURL=message-decoder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-decoder.d.ts","sourceRoot":"","sources":["../../src/rpc/message-decoder.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAU,oBAAoB,EAAC,MAAM,qBAAqB,CAAC;AAEvE;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,GAAG,WAAW,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,CAAC,CAAC;AAmBhG;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAsJ5E;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,EAAE,yBAchC,CAAC"}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.chunkedJsonDecoder = void 0;
|
|
4
|
+
exports.parseJsonBytes = parseJsonBytes;
|
|
5
|
+
/*
|
|
6
|
+
* Copyright 2025 the original author or authors.
|
|
7
|
+
* <p>
|
|
8
|
+
* Licensed under the Moderne Source Available License (the "License");
|
|
9
|
+
* you may not use this file except in compliance with the License.
|
|
10
|
+
* You may obtain a copy of the License at
|
|
11
|
+
* <p>
|
|
12
|
+
* https://docs.moderne.io/licensing/moderne-source-available-license
|
|
13
|
+
* <p>
|
|
14
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
* See the License for the specific language governing permissions and
|
|
18
|
+
* limitations under the License.
|
|
19
|
+
*/
|
|
20
|
+
const buffer_1 = require("buffer");
|
|
21
|
+
const TAB = 0x09, NEWLINE = 0x0a, CARRIAGE_RETURN = 0x0d, SPACE = 0x20;
|
|
22
|
+
const QUOTE = 0x22, PLUS = 0x2b, COMMA = 0x2c, MINUS = 0x2d, PERIOD = 0x2e;
|
|
23
|
+
const ZERO = 0x30, NINE = 0x39, COLON = 0x3a, UPPER_E = 0x45;
|
|
24
|
+
const OPEN_BRACKET = 0x5b, BACKSLASH = 0x5c, CLOSE_BRACKET = 0x5d;
|
|
25
|
+
const LOWER_A = 0x61, LOWER_E = 0x65, LOWER_F = 0x66, LOWER_N = 0x6e, LOWER_T = 0x74, LOWER_Z = 0x7a;
|
|
26
|
+
const OPEN_BRACE = 0x7b, CLOSE_BRACE = 0x7d;
|
|
27
|
+
function isNumberByte(c) {
|
|
28
|
+
return (c >= ZERO && c <= NINE) || c === MINUS || c === PLUS || c === PERIOD || c === LOWER_E || c === UPPER_E;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Parses JSON directly from its UTF-8 bytes, never materializing the whole document as one JS
|
|
32
|
+
* string. Structural punctuation is recognized byte-by-byte, while every scalar and every object key
|
|
33
|
+
* is handed to the engine's `JSON.parse` as its own small slice — so escaping, number formatting and
|
|
34
|
+
* literal validation match it exactly. This is the mirror of how `jsonFragments` defers to
|
|
35
|
+
* `JSON.stringify`, and it accepts precisely the grammar `JSON.parse` accepts.
|
|
36
|
+
*
|
|
37
|
+
* Byte-level scanning is safe for the ASCII-compatible charsets vscode-jsonrpc supports (`utf-8`,
|
|
38
|
+
* `ascii`): a UTF-8 continuation byte is always >= 0x80, so it can never be mistaken for a quote,
|
|
39
|
+
* backslash, or structural character. Containers are tracked on an explicit stack, so nesting depth
|
|
40
|
+
* is bounded by heap rather than by the call stack.
|
|
41
|
+
*/
|
|
42
|
+
function parseJsonBytes(buf, charset) {
|
|
43
|
+
const len = buf.length;
|
|
44
|
+
let i = 0;
|
|
45
|
+
const fail = (what) => {
|
|
46
|
+
throw new SyntaxError(`${what} in JSON at position ${i}`);
|
|
47
|
+
};
|
|
48
|
+
// Advance past insignificant whitespace and return the next byte, which must exist.
|
|
49
|
+
const seek = () => {
|
|
50
|
+
while (i < len) {
|
|
51
|
+
const c = buf[i];
|
|
52
|
+
if (c !== SPACE && c !== TAB && c !== NEWLINE && c !== CARRIAGE_RETURN) {
|
|
53
|
+
return c;
|
|
54
|
+
}
|
|
55
|
+
i++;
|
|
56
|
+
}
|
|
57
|
+
return fail("Unexpected end of JSON input");
|
|
58
|
+
};
|
|
59
|
+
const token = (start, end) => JSON.parse(buf.toString(charset, start, end));
|
|
60
|
+
const readString = () => {
|
|
61
|
+
const start = i++; // opening quote
|
|
62
|
+
while (i < len) {
|
|
63
|
+
const c = buf[i];
|
|
64
|
+
if (c === BACKSLASH) {
|
|
65
|
+
i += 2; // the byte after a backslash is ASCII, so it can never be the closing quote
|
|
66
|
+
}
|
|
67
|
+
else if (c === QUOTE) {
|
|
68
|
+
return token(start, ++i);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
i++;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return fail("Unterminated string");
|
|
75
|
+
};
|
|
76
|
+
const readKey = () => {
|
|
77
|
+
if (seek() !== QUOTE) {
|
|
78
|
+
fail("Expected property name");
|
|
79
|
+
}
|
|
80
|
+
const key = readString();
|
|
81
|
+
if (seek() !== COLON) {
|
|
82
|
+
fail("Expected ':' after property name");
|
|
83
|
+
}
|
|
84
|
+
i++;
|
|
85
|
+
return key;
|
|
86
|
+
};
|
|
87
|
+
// JSON.parse gives __proto__ an own data property rather than setting the prototype.
|
|
88
|
+
const setProperty = (object, key, value) => {
|
|
89
|
+
if (key === "__proto__") {
|
|
90
|
+
Object.defineProperty(object, key, { value, writable: true, enumerable: true, configurable: true });
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
object[key] = value;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const parseValue = () => {
|
|
97
|
+
const stack = [];
|
|
98
|
+
let value;
|
|
99
|
+
nextValue: for (;;) {
|
|
100
|
+
const c = seek();
|
|
101
|
+
if (c === OPEN_BRACE) {
|
|
102
|
+
i++;
|
|
103
|
+
const frame = { object: {} };
|
|
104
|
+
if (seek() === CLOSE_BRACE) {
|
|
105
|
+
i++;
|
|
106
|
+
value = frame.object;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
frame.key = readKey();
|
|
110
|
+
stack.push(frame);
|
|
111
|
+
continue nextValue;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else if (c === OPEN_BRACKET) {
|
|
115
|
+
i++;
|
|
116
|
+
const frame = { array: [] };
|
|
117
|
+
if (seek() === CLOSE_BRACKET) {
|
|
118
|
+
i++;
|
|
119
|
+
value = frame.array;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
stack.push(frame);
|
|
123
|
+
continue nextValue;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else if (c === QUOTE) {
|
|
127
|
+
value = readString();
|
|
128
|
+
}
|
|
129
|
+
else if (c === LOWER_T || c === LOWER_F || c === LOWER_N) {
|
|
130
|
+
const start = i;
|
|
131
|
+
while (i < len && buf[i] >= LOWER_A && buf[i] <= LOWER_Z) {
|
|
132
|
+
i++;
|
|
133
|
+
}
|
|
134
|
+
value = token(start, i); // true | false | null, validated by JSON.parse
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
const start = i;
|
|
138
|
+
while (i < len && isNumberByte(buf[i])) {
|
|
139
|
+
i++;
|
|
140
|
+
}
|
|
141
|
+
if (i === start) {
|
|
142
|
+
fail(`Unexpected token ${JSON.stringify(buf.toString(charset, i, i + 1))}`);
|
|
143
|
+
}
|
|
144
|
+
value = token(start, i);
|
|
145
|
+
}
|
|
146
|
+
// Attach the finished value to its container, closing containers as they end.
|
|
147
|
+
for (;;) {
|
|
148
|
+
const frame = stack[stack.length - 1];
|
|
149
|
+
if (frame === undefined) {
|
|
150
|
+
return value;
|
|
151
|
+
}
|
|
152
|
+
if (frame.array !== undefined) {
|
|
153
|
+
frame.array.push(value);
|
|
154
|
+
const c = seek();
|
|
155
|
+
if (c === COMMA) {
|
|
156
|
+
i++;
|
|
157
|
+
continue nextValue;
|
|
158
|
+
}
|
|
159
|
+
if (c !== CLOSE_BRACKET) {
|
|
160
|
+
fail("Expected ',' or ']' after array element");
|
|
161
|
+
}
|
|
162
|
+
i++;
|
|
163
|
+
value = frame.array;
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
setProperty(frame.object, frame.key, value);
|
|
167
|
+
const c = seek();
|
|
168
|
+
if (c === COMMA) {
|
|
169
|
+
i++;
|
|
170
|
+
frame.key = readKey();
|
|
171
|
+
continue nextValue;
|
|
172
|
+
}
|
|
173
|
+
if (c !== CLOSE_BRACE) {
|
|
174
|
+
fail("Expected ',' or '}' after property value");
|
|
175
|
+
}
|
|
176
|
+
i++;
|
|
177
|
+
value = frame.object;
|
|
178
|
+
}
|
|
179
|
+
stack.pop();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
const value = parseValue();
|
|
184
|
+
while (i < len) {
|
|
185
|
+
const c = buf[i];
|
|
186
|
+
if (c !== SPACE && c !== TAB && c !== NEWLINE && c !== CARRIAGE_RETURN) {
|
|
187
|
+
fail("Unexpected non-whitespace character after JSON");
|
|
188
|
+
}
|
|
189
|
+
i++;
|
|
190
|
+
}
|
|
191
|
+
return value;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* A drop-in replacement for vscode-jsonrpc's default `application/json` content-type decoder, which
|
|
195
|
+
* does {@code JSON.parse(buffer.toString(charset))}. That intermediate string is capped at V8's
|
|
196
|
+
* String.kMaxLength (~512 MB), so an inbound message above the cap throws "Cannot create a string
|
|
197
|
+
* longer than 0x1fffffe8 characters" before it is ever parsed — the reader drops the message, the
|
|
198
|
+
* peer's request is never answered, and the call hangs until it times out. Parsing straight from the
|
|
199
|
+
* bytes raises the inbound ceiling to Node's Buffer.MAX_LENGTH, matching what {@link
|
|
200
|
+
* chunkedJsonEncoder} does for outbound messages.
|
|
201
|
+
*
|
|
202
|
+
* A UTF-8 (or ASCII) decode never yields more UTF-16 code units than there are bytes, so a body at
|
|
203
|
+
* or under the cap cannot overflow the intermediate string; those take the faster single-string
|
|
204
|
+
* parse, and only genuinely oversized bodies pay for the byte-level walk.
|
|
205
|
+
*/
|
|
206
|
+
exports.chunkedJsonDecoder = {
|
|
207
|
+
name: "application/json",
|
|
208
|
+
decode(buffer, options) {
|
|
209
|
+
try {
|
|
210
|
+
const buf = Buffer.isBuffer(buffer) ?
|
|
211
|
+
buffer :
|
|
212
|
+
Buffer.from(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
213
|
+
return Promise.resolve((buf.byteLength <= buffer_1.constants.MAX_STRING_LENGTH ?
|
|
214
|
+
JSON.parse(buf.toString(options.charset)) :
|
|
215
|
+
parseJsonBytes(buf, options.charset)));
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
return Promise.reject(err);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
//# sourceMappingURL=message-decoder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-decoder.js","sourceRoot":"","sources":["../../src/rpc/message-decoder.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,7 +18,7 @@ export declare function jsonFragments(value: unknown): Generator<string>;
|
|
|
18
18
|
* serializes a message to UTF-8 bytes without ever materializing the whole document as a single JS
|
|
19
19
|
* string. The default encoder does {@code Buffer.from(JSON.stringify(msg))}; a large enough
|
|
20
20
|
* PrepareRecipe response (a deep recipe tree) overflows V8's single-string limit and throws
|
|
21
|
-
* "
|
|
21
|
+
* "RangeError: Invalid string length", hanging the RPC call. Streaming the
|
|
22
22
|
* fragments into a Buffer raises the ceiling to Node's Buffer.MAX_LENGTH (multiple GB) while
|
|
23
23
|
* producing byte-identical output. (True unbounded streaming needs chunked framing — Content-Length
|
|
24
24
|
* still requires the whole body up front — so this is a ceiling raise, not a removal.)
|
|
@@ -71,7 +71,7 @@ function* jsonFragments(value) {
|
|
|
71
71
|
* serializes a message to UTF-8 bytes without ever materializing the whole document as a single JS
|
|
72
72
|
* string. The default encoder does {@code Buffer.from(JSON.stringify(msg))}; a large enough
|
|
73
73
|
* PrepareRecipe response (a deep recipe tree) overflows V8's single-string limit and throws
|
|
74
|
-
* "
|
|
74
|
+
* "RangeError: Invalid string length", hanging the RPC call. Streaming the
|
|
75
75
|
* fragments into a Buffer raises the ceiling to Node's Buffer.MAX_LENGTH (multiple GB) while
|
|
76
76
|
* producing byte-identical output. (True unbounded streaming needs chunked framing — Content-Length
|
|
77
77
|
* still requires the whole body up front — so this is a ceiling raise, not a removal.)
|
package/dist/rpc/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/rpc/server.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/rpc/server.ts"],"names":[],"mappings":";AA0BA,OAAO,SAAS,CAAC;AACjB,OAAO,SAAS,CAAC;AACjB,OAAO,SAAS,CAAC;AACjB,OAAO,SAAS,CAAC;AACjB,OAAO,eAAe,CAAC"}
|
package/dist/rpc/server.js
CHANGED
|
@@ -51,6 +51,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
51
51
|
*/
|
|
52
52
|
const rpc = __importStar(require("vscode-jsonrpc/node"));
|
|
53
53
|
const rewrite_rpc_1 = require("./rewrite-rpc");
|
|
54
|
+
const message_decoder_1 = require("./message-decoder");
|
|
54
55
|
const message_encoder_1 = require("./message-encoder");
|
|
55
56
|
const fs = __importStar(require("fs"));
|
|
56
57
|
const commander_1 = require("commander");
|
|
@@ -161,10 +162,15 @@ async function main() {
|
|
|
161
162
|
};
|
|
162
163
|
pyroscope = initPyroscope(logger);
|
|
163
164
|
// Create the connection with the custom logger
|
|
164
|
-
const connection = rpc.createMessageConnection(
|
|
165
|
+
const connection = rpc.createMessageConnection(
|
|
166
|
+
// Parse incoming messages straight from their bytes: a large inbound message (e.g. a tree
|
|
167
|
+
// carrying RecipesThatMadeChanges markers, whose recipe descriptors repeat per changed file)
|
|
168
|
+
// overflows V8's ~512 MB string limit in the default `JSON.parse(buffer.toString())` decoder,
|
|
169
|
+
// which drops the message and hangs the caller until it times out.
|
|
170
|
+
new rpc.StreamMessageReader(process.stdin, { contentTypeDecoder: message_decoder_1.chunkedJsonDecoder }),
|
|
165
171
|
// Serialize outgoing messages without materializing the whole document as one JS string:
|
|
166
|
-
// a large PrepareRecipe response (a deep recipe tree) overflows
|
|
167
|
-
//
|
|
172
|
+
// a large PrepareRecipe response (a deep recipe tree) overflows the same limit in the
|
|
173
|
+
// default `Buffer.from(JSON.stringify(msg))` encoder.
|
|
168
174
|
new rpc.StreamMessageWriter(process.stdout, { contentTypeEncoder: message_encoder_1.chunkedJsonEncoder }), logger);
|
|
169
175
|
if (options.traceRpcMessages) {
|
|
170
176
|
await connection.trace(rpc.Trace.Verbose, logger).catch((err) => {
|
package/dist/rpc/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/rpc/server.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/rpc/server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -18,6 +18,7 @@ import * as path from "node:path";
|
|
|
18
18
|
import * as readline from "node:readline";
|
|
19
19
|
import {ChildProcessWithoutNullStreams, spawn} from "node:child_process";
|
|
20
20
|
import * as rpc from "vscode-jsonrpc/node";
|
|
21
|
+
import {chunkedJsonDecoder} from "./message-decoder";
|
|
21
22
|
import {RewriteRpc} from "./rewrite-rpc";
|
|
22
23
|
import {RecipeMarketplace} from "../marketplace";
|
|
23
24
|
|
|
@@ -104,7 +105,9 @@ export class JavaRpcTestServer {
|
|
|
104
105
|
});
|
|
105
106
|
|
|
106
107
|
const connection = rpc.createMessageConnection(
|
|
107
|
-
|
|
108
|
+
// Trees and recipe descriptors cross this connection too, so it needs the same headroom
|
|
109
|
+
// as the server's: the default decoder caps an inbound message at V8's ~512 MB string limit.
|
|
110
|
+
new rpc.StreamMessageReader(child.stdout, {contentTypeDecoder: chunkedJsonDecoder}),
|
|
108
111
|
new rpc.StreamMessageWriter(child.stdin),
|
|
109
112
|
opts.logger,
|
|
110
113
|
);
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 the original author or authors.
|
|
3
|
+
* <p>
|
|
4
|
+
* Licensed under the Moderne Source Available License (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
* <p>
|
|
8
|
+
* https://docs.moderne.io/licensing/moderne-source-available-license
|
|
9
|
+
* <p>
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import {constants} from "buffer";
|
|
17
|
+
import type {Message, MessageReaderOptions} from "vscode-jsonrpc/node";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The content-type decoder shape vscode-jsonrpc's {@link MessageReaderOptions} accepts. Derived
|
|
21
|
+
* from the reader options rather than deep-imported, because the concrete `ContentTypeDecoder`
|
|
22
|
+
* type is not re-exported from the package entrypoint.
|
|
23
|
+
*/
|
|
24
|
+
export type JsonRpcContentTypeDecoder = NonNullable<MessageReaderOptions["contentTypeDecoder"]>;
|
|
25
|
+
|
|
26
|
+
const TAB = 0x09, NEWLINE = 0x0a, CARRIAGE_RETURN = 0x0d, SPACE = 0x20;
|
|
27
|
+
const QUOTE = 0x22, PLUS = 0x2b, COMMA = 0x2c, MINUS = 0x2d, PERIOD = 0x2e;
|
|
28
|
+
const ZERO = 0x30, NINE = 0x39, COLON = 0x3a, UPPER_E = 0x45;
|
|
29
|
+
const OPEN_BRACKET = 0x5b, BACKSLASH = 0x5c, CLOSE_BRACKET = 0x5d;
|
|
30
|
+
const LOWER_A = 0x61, LOWER_E = 0x65, LOWER_F = 0x66, LOWER_N = 0x6e, LOWER_T = 0x74, LOWER_Z = 0x7a;
|
|
31
|
+
const OPEN_BRACE = 0x7b, CLOSE_BRACE = 0x7d;
|
|
32
|
+
|
|
33
|
+
function isNumberByte(c: number): boolean {
|
|
34
|
+
return (c >= ZERO && c <= NINE) || c === MINUS || c === PLUS || c === PERIOD || c === LOWER_E || c === UPPER_E;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface Frame {
|
|
38
|
+
readonly array?: unknown[];
|
|
39
|
+
readonly object?: Record<string, unknown>;
|
|
40
|
+
key?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Parses JSON directly from its UTF-8 bytes, never materializing the whole document as one JS
|
|
45
|
+
* string. Structural punctuation is recognized byte-by-byte, while every scalar and every object key
|
|
46
|
+
* is handed to the engine's `JSON.parse` as its own small slice — so escaping, number formatting and
|
|
47
|
+
* literal validation match it exactly. This is the mirror of how `jsonFragments` defers to
|
|
48
|
+
* `JSON.stringify`, and it accepts precisely the grammar `JSON.parse` accepts.
|
|
49
|
+
*
|
|
50
|
+
* Byte-level scanning is safe for the ASCII-compatible charsets vscode-jsonrpc supports (`utf-8`,
|
|
51
|
+
* `ascii`): a UTF-8 continuation byte is always >= 0x80, so it can never be mistaken for a quote,
|
|
52
|
+
* backslash, or structural character. Containers are tracked on an explicit stack, so nesting depth
|
|
53
|
+
* is bounded by heap rather than by the call stack.
|
|
54
|
+
*/
|
|
55
|
+
export function parseJsonBytes(buf: Buffer, charset: BufferEncoding): unknown {
|
|
56
|
+
const len = buf.length;
|
|
57
|
+
let i = 0;
|
|
58
|
+
|
|
59
|
+
const fail = (what: string): never => {
|
|
60
|
+
throw new SyntaxError(`${what} in JSON at position ${i}`);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// Advance past insignificant whitespace and return the next byte, which must exist.
|
|
64
|
+
const seek = (): number => {
|
|
65
|
+
while (i < len) {
|
|
66
|
+
const c = buf[i];
|
|
67
|
+
if (c !== SPACE && c !== TAB && c !== NEWLINE && c !== CARRIAGE_RETURN) {
|
|
68
|
+
return c;
|
|
69
|
+
}
|
|
70
|
+
i++;
|
|
71
|
+
}
|
|
72
|
+
return fail("Unexpected end of JSON input");
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const token = (start: number, end: number): unknown => JSON.parse(buf.toString(charset, start, end));
|
|
76
|
+
|
|
77
|
+
const readString = (): string => {
|
|
78
|
+
const start = i++; // opening quote
|
|
79
|
+
while (i < len) {
|
|
80
|
+
const c = buf[i];
|
|
81
|
+
if (c === BACKSLASH) {
|
|
82
|
+
i += 2; // the byte after a backslash is ASCII, so it can never be the closing quote
|
|
83
|
+
} else if (c === QUOTE) {
|
|
84
|
+
return token(start, ++i) as string;
|
|
85
|
+
} else {
|
|
86
|
+
i++;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return fail("Unterminated string");
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const readKey = (): string => {
|
|
93
|
+
if (seek() !== QUOTE) {
|
|
94
|
+
fail("Expected property name");
|
|
95
|
+
}
|
|
96
|
+
const key = readString();
|
|
97
|
+
if (seek() !== COLON) {
|
|
98
|
+
fail("Expected ':' after property name");
|
|
99
|
+
}
|
|
100
|
+
i++;
|
|
101
|
+
return key;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// JSON.parse gives __proto__ an own data property rather than setting the prototype.
|
|
105
|
+
const setProperty = (object: Record<string, unknown>, key: string, value: unknown): void => {
|
|
106
|
+
if (key === "__proto__") {
|
|
107
|
+
Object.defineProperty(object, key, {value, writable: true, enumerable: true, configurable: true});
|
|
108
|
+
} else {
|
|
109
|
+
object[key] = value;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const parseValue = (): unknown => {
|
|
114
|
+
const stack: Frame[] = [];
|
|
115
|
+
let value: unknown;
|
|
116
|
+
|
|
117
|
+
nextValue: for (; ;) {
|
|
118
|
+
const c = seek();
|
|
119
|
+
if (c === OPEN_BRACE) {
|
|
120
|
+
i++;
|
|
121
|
+
const frame: Frame = {object: {}};
|
|
122
|
+
if (seek() === CLOSE_BRACE) {
|
|
123
|
+
i++;
|
|
124
|
+
value = frame.object;
|
|
125
|
+
} else {
|
|
126
|
+
frame.key = readKey();
|
|
127
|
+
stack.push(frame);
|
|
128
|
+
continue nextValue;
|
|
129
|
+
}
|
|
130
|
+
} else if (c === OPEN_BRACKET) {
|
|
131
|
+
i++;
|
|
132
|
+
const frame: Frame = {array: []};
|
|
133
|
+
if (seek() === CLOSE_BRACKET) {
|
|
134
|
+
i++;
|
|
135
|
+
value = frame.array;
|
|
136
|
+
} else {
|
|
137
|
+
stack.push(frame);
|
|
138
|
+
continue nextValue;
|
|
139
|
+
}
|
|
140
|
+
} else if (c === QUOTE) {
|
|
141
|
+
value = readString();
|
|
142
|
+
} else if (c === LOWER_T || c === LOWER_F || c === LOWER_N) {
|
|
143
|
+
const start = i;
|
|
144
|
+
while (i < len && buf[i] >= LOWER_A && buf[i] <= LOWER_Z) {
|
|
145
|
+
i++;
|
|
146
|
+
}
|
|
147
|
+
value = token(start, i); // true | false | null, validated by JSON.parse
|
|
148
|
+
} else {
|
|
149
|
+
const start = i;
|
|
150
|
+
while (i < len && isNumberByte(buf[i])) {
|
|
151
|
+
i++;
|
|
152
|
+
}
|
|
153
|
+
if (i === start) {
|
|
154
|
+
fail(`Unexpected token ${JSON.stringify(buf.toString(charset, i, i + 1))}`);
|
|
155
|
+
}
|
|
156
|
+
value = token(start, i);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Attach the finished value to its container, closing containers as they end.
|
|
160
|
+
for (; ;) {
|
|
161
|
+
const frame = stack[stack.length - 1];
|
|
162
|
+
if (frame === undefined) {
|
|
163
|
+
return value;
|
|
164
|
+
}
|
|
165
|
+
if (frame.array !== undefined) {
|
|
166
|
+
frame.array.push(value);
|
|
167
|
+
const c = seek();
|
|
168
|
+
if (c === COMMA) {
|
|
169
|
+
i++;
|
|
170
|
+
continue nextValue;
|
|
171
|
+
}
|
|
172
|
+
if (c !== CLOSE_BRACKET) {
|
|
173
|
+
fail("Expected ',' or ']' after array element");
|
|
174
|
+
}
|
|
175
|
+
i++;
|
|
176
|
+
value = frame.array;
|
|
177
|
+
} else {
|
|
178
|
+
setProperty(frame.object!, frame.key!, value);
|
|
179
|
+
const c = seek();
|
|
180
|
+
if (c === COMMA) {
|
|
181
|
+
i++;
|
|
182
|
+
frame.key = readKey();
|
|
183
|
+
continue nextValue;
|
|
184
|
+
}
|
|
185
|
+
if (c !== CLOSE_BRACE) {
|
|
186
|
+
fail("Expected ',' or '}' after property value");
|
|
187
|
+
}
|
|
188
|
+
i++;
|
|
189
|
+
value = frame.object!;
|
|
190
|
+
}
|
|
191
|
+
stack.pop();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const value = parseValue();
|
|
197
|
+
while (i < len) {
|
|
198
|
+
const c = buf[i];
|
|
199
|
+
if (c !== SPACE && c !== TAB && c !== NEWLINE && c !== CARRIAGE_RETURN) {
|
|
200
|
+
fail("Unexpected non-whitespace character after JSON");
|
|
201
|
+
}
|
|
202
|
+
i++;
|
|
203
|
+
}
|
|
204
|
+
return value;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* A drop-in replacement for vscode-jsonrpc's default `application/json` content-type decoder, which
|
|
209
|
+
* does {@code JSON.parse(buffer.toString(charset))}. That intermediate string is capped at V8's
|
|
210
|
+
* String.kMaxLength (~512 MB), so an inbound message above the cap throws "Cannot create a string
|
|
211
|
+
* longer than 0x1fffffe8 characters" before it is ever parsed — the reader drops the message, the
|
|
212
|
+
* peer's request is never answered, and the call hangs until it times out. Parsing straight from the
|
|
213
|
+
* bytes raises the inbound ceiling to Node's Buffer.MAX_LENGTH, matching what {@link
|
|
214
|
+
* chunkedJsonEncoder} does for outbound messages.
|
|
215
|
+
*
|
|
216
|
+
* A UTF-8 (or ASCII) decode never yields more UTF-16 code units than there are bytes, so a body at
|
|
217
|
+
* or under the cap cannot overflow the intermediate string; those take the faster single-string
|
|
218
|
+
* parse, and only genuinely oversized bodies pay for the byte-level walk.
|
|
219
|
+
*/
|
|
220
|
+
export const chunkedJsonDecoder: JsonRpcContentTypeDecoder = {
|
|
221
|
+
name: "application/json",
|
|
222
|
+
decode(buffer: Uint8Array, options: { charset: BufferEncoding }): Promise<Message> {
|
|
223
|
+
try {
|
|
224
|
+
const buf = Buffer.isBuffer(buffer) ?
|
|
225
|
+
buffer :
|
|
226
|
+
Buffer.from(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
227
|
+
return Promise.resolve((buf.byteLength <= constants.MAX_STRING_LENGTH ?
|
|
228
|
+
JSON.parse(buf.toString(options.charset)) :
|
|
229
|
+
parseJsonBytes(buf, options.charset)) as Message);
|
|
230
|
+
} catch (err) {
|
|
231
|
+
return Promise.reject(err);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
};
|
|
@@ -96,7 +96,7 @@ export function* jsonFragments(value: unknown): Generator<string> {
|
|
|
96
96
|
* serializes a message to UTF-8 bytes without ever materializing the whole document as a single JS
|
|
97
97
|
* string. The default encoder does {@code Buffer.from(JSON.stringify(msg))}; a large enough
|
|
98
98
|
* PrepareRecipe response (a deep recipe tree) overflows V8's single-string limit and throws
|
|
99
|
-
* "
|
|
99
|
+
* "RangeError: Invalid string length", hanging the RPC call. Streaming the
|
|
100
100
|
* fragments into a Buffer raises the ceiling to Node's Buffer.MAX_LENGTH (multiple GB) while
|
|
101
101
|
* producing byte-identical output. (True unbounded streaming needs chunked framing — Content-Length
|
|
102
102
|
* still requires the whole body up front — so this is a ceiling raise, not a removal.)
|
package/src/rpc/server.ts
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import * as rpc from "vscode-jsonrpc/node";
|
|
18
18
|
import {RewriteRpc} from "./rewrite-rpc";
|
|
19
|
+
import {chunkedJsonDecoder} from "./message-decoder";
|
|
19
20
|
import {chunkedJsonEncoder} from "./message-encoder";
|
|
20
21
|
import * as fs from "fs";
|
|
21
22
|
import {Command} from 'commander';
|
|
@@ -142,10 +143,14 @@ async function main() {
|
|
|
142
143
|
|
|
143
144
|
// Create the connection with the custom logger
|
|
144
145
|
const connection = rpc.createMessageConnection(
|
|
145
|
-
|
|
146
|
+
// Parse incoming messages straight from their bytes: a large inbound message (e.g. a tree
|
|
147
|
+
// carrying RecipesThatMadeChanges markers, whose recipe descriptors repeat per changed file)
|
|
148
|
+
// overflows V8's ~512 MB string limit in the default `JSON.parse(buffer.toString())` decoder,
|
|
149
|
+
// which drops the message and hangs the caller until it times out.
|
|
150
|
+
new rpc.StreamMessageReader(process.stdin, {contentTypeDecoder: chunkedJsonDecoder}),
|
|
146
151
|
// Serialize outgoing messages without materializing the whole document as one JS string:
|
|
147
|
-
// a large PrepareRecipe response (a deep recipe tree) overflows
|
|
148
|
-
//
|
|
152
|
+
// a large PrepareRecipe response (a deep recipe tree) overflows the same limit in the
|
|
153
|
+
// default `Buffer.from(JSON.stringify(msg))` encoder.
|
|
149
154
|
new rpc.StreamMessageWriter(process.stdout, {contentTypeEncoder: chunkedJsonEncoder}),
|
|
150
155
|
logger
|
|
151
156
|
);
|
package/src/java/s.js~
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
|
|
4
|
-
const VISITOR_FILE = path.join(__dirname, "visitor.ts");
|
|
5
|
-
|
|
6
|
-
function addMiddleArgToVisitContainer(content) {
|
|
7
|
-
const lines = content.split("\n");
|
|
8
|
-
const updatedLines = [];
|
|
9
|
-
|
|
10
|
-
let currentMethod = null;
|
|
11
|
-
|
|
12
|
-
for (let i = 0; i < lines.length; i++) {
|
|
13
|
-
let line = lines[i];
|
|
14
|
-
|
|
15
|
-
const methodMatch = line.match(/^\s*(?:public\s+|private\s+|protected\s+)?(?:async\s+)?(\w+)\s*\(.*\)\s*{/);
|
|
16
|
-
if (methodMatch) {
|
|
17
|
-
currentMethod = methodMatch[1];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const callMatch = line.match(/(\bvisitContainer\s*\()\s*([^,]+)\s*,\s*([^)\n]+)\)/);
|
|
21
|
-
if (callMatch) {
|
|
22
|
-
// Derive context from variable name or some keyword around
|
|
23
|
-
const arg1 = callMatch[2].trim();
|
|
24
|
-
let context = "UNKNOWN";
|
|
25
|
-
if (/case/i.test(line)) context = "CASE_LABEL";
|
|
26
|
-
else if (/block/i.test(arg1)) context = "BLOCK";
|
|
27
|
-
else if (/param/i.test(arg1)) context = "PARAM";
|
|
28
|
-
else if (/arg/i.test(arg1)) context = "ARGUMENT";
|
|
29
|
-
else context = arg1.toUpperCase().replace(/[^A-Z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
30
|
-
|
|
31
|
-
const locationString = `"${currentMethod ? currentMethod.toUpperCase() + "_" + context : context}"`;
|
|
32
|
-
line = line.replace(callMatch[0], `${callMatch[1]}${callMatch[2]}, ${locationString}, ${callMatch[3]})`);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
updatedLines.push(line);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return updatedLines.join("\n");
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function main() {
|
|
42
|
-
const original = fs.readFileSync(VISITOR_FILE, "utf8");
|
|
43
|
-
const updated = addMiddleArgToVisitContainer(original);
|
|
44
|
-
fs.writeFileSync(VISITOR_FILE, updated, "utf8");
|
|
45
|
-
console.log("✅ visitContainer calls amended.");
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
main();
|
package/src/javascript/s.js~
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
|
|
4
|
-
const VISITOR_FILE = path.join(__dirname, "visitor.ts");
|
|
5
|
-
|
|
6
|
-
function addMiddleArgToVisitContainer(content) {
|
|
7
|
-
const lines = content.split("\n");
|
|
8
|
-
const updatedLines = [];
|
|
9
|
-
|
|
10
|
-
let currentMethod = null;
|
|
11
|
-
|
|
12
|
-
for (let i = 0; i < lines.length; i++) {
|
|
13
|
-
let line = lines[i];
|
|
14
|
-
|
|
15
|
-
const methodMatch = line.match(/^\s*(?:public\s+|private\s+|protected\s+)?(?:async\s+)?(\w+)\s*\(.*\)\s*{/);
|
|
16
|
-
if (methodMatch) {
|
|
17
|
-
currentMethod = methodMatch[1];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const callMatch = line.match(/(\bvisitContainer\s*\()\s*([^,]+)\s*,\s*([^)\n]+)\)/);
|
|
21
|
-
if (callMatch) {
|
|
22
|
-
// Derive context from variable name or some keyword around
|
|
23
|
-
const arg1 = callMatch[2].trim();
|
|
24
|
-
let context = "UNKNOWN";
|
|
25
|
-
if (/case/i.test(line)) context = "CASE_LABEL";
|
|
26
|
-
else if (/block/i.test(arg1)) context = "BLOCK";
|
|
27
|
-
else if (/param/i.test(arg1)) context = "PARAM";
|
|
28
|
-
else if (/arg/i.test(arg1)) context = "ARGUMENT";
|
|
29
|
-
else context = arg1.toUpperCase().replace(/[^A-Z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
30
|
-
|
|
31
|
-
const locationString = `"${currentMethod ? currentMethod.toUpperCase() + "_" + context : context}"`;
|
|
32
|
-
line = line.replace(callMatch[0], `${callMatch[1]}${callMatch[2]}, ${locationString}, ${callMatch[3]})`);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
updatedLines.push(line);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return updatedLines.join("\n");
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function main() {
|
|
42
|
-
const original = fs.readFileSync(VISITOR_FILE, "utf8");
|
|
43
|
-
const updated = addMiddleArgToVisitContainer(original);
|
|
44
|
-
fs.writeFileSync(VISITOR_FILE, updated, "utf8");
|
|
45
|
-
console.log("✅ visitContainer calls amended.");
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
main();
|
package/src/javascript/s2.js~
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
|
|
4
|
-
const VISITOR_FILE = path.join(__dirname, "visitor.ts");
|
|
5
|
-
|
|
6
|
-
function toUpperUnderscore(name) {
|
|
7
|
-
return name
|
|
8
|
-
.replace(/([a-z])([A-Z])/g, "$1_$2")
|
|
9
|
-
.replace(/[\W]+/g, "_")
|
|
10
|
-
.replace(/^_+|_+$/g, "")
|
|
11
|
-
.toUpperCase();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function extractPropertyFromLine(line) {
|
|
15
|
-
// Case 1: match property from lambda: el => el.property
|
|
16
|
-
let match = line.match(/el\s*=>\s*el\.([a-zA-Z0-9_]+)/);
|
|
17
|
-
if (match) return match[1];
|
|
18
|
-
|
|
19
|
-
// Case 2: match assignment target like: draft.valueType = await ...
|
|
20
|
-
match = line.match(/\b([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)\s*=.*\s*await\b/);
|
|
21
|
-
if (match) return match[2];
|
|
22
|
-
|
|
23
|
-
return "UNKNOWN";
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function addMiddleArgToVisitContainer(content) {
|
|
27
|
-
const lines = content.split("\n");
|
|
28
|
-
const updatedLines = [];
|
|
29
|
-
|
|
30
|
-
let currentMethod = null;
|
|
31
|
-
|
|
32
|
-
for (let i = 0; i < lines.length; i++) {
|
|
33
|
-
let line = lines[i];
|
|
34
|
-
|
|
35
|
-
const methodMatch = line.match(/^ +(?:public|protected|private)?\s*(?:override\s+)?(?:async\s+)?(visit[A-Z][A-Za-z0-9_]*)\s*\(/);
|
|
36
|
-
if (methodMatch) {
|
|
37
|
-
const fullMethod = methodMatch[1]; // e.g. visitExpressionWithTypeArguments
|
|
38
|
-
// Strip the "visit" prefix and convert to UPPER_UNDERSCORE
|
|
39
|
-
currentMethod = fullMethod.startsWith("visit") ? fullMethod.slice(5) : fullMethod;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const visitCallMatch = line.match(/(\bvisitContainer\s*\()\s*([^,]+)\s*,\s*([^)\n]+)\)/);
|
|
43
|
-
if (visitCallMatch) {
|
|
44
|
-
const objectArg = visitCallMatch[2].trim();
|
|
45
|
-
const restArg = visitCallMatch[3].trim();
|
|
46
|
-
|
|
47
|
-
const property = extractPropertyFromLine(line);
|
|
48
|
-
const method = currentMethod || "UNKNOWN";
|
|
49
|
-
|
|
50
|
-
const locationValue = `"${toUpperUnderscore(method)}_${toUpperUnderscore(property)}"`;
|
|
51
|
-
|
|
52
|
-
line = line.replace(visitCallMatch[0], `${visitCallMatch[1]}${objectArg}, ${locationValue}, ${restArg})`);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
updatedLines.push(line);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return updatedLines.join("\n");
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function main() {
|
|
62
|
-
const original = fs.readFileSync(VISITOR_FILE, "utf8");
|
|
63
|
-
const updated = addMiddleArgToVisitContainer(original);
|
|
64
|
-
fs.writeFileSync(VISITOR_FILE, updated, "utf8");
|
|
65
|
-
console.log("✅ visitContainer calls amended with location strings.");
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
main();
|