@openrewrite/rewrite 8.92.15 → 8.92.17

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.
Files changed (114) hide show
  1. package/dist/javascript/add-import.d.ts.map +1 -1
  2. package/dist/javascript/add-import.js +3 -2
  3. package/dist/javascript/add-import.js.map +1 -1
  4. package/dist/javascript/amd.d.ts.map +1 -1
  5. package/dist/javascript/amd.js +3 -2
  6. package/dist/javascript/amd.js.map +1 -1
  7. package/dist/javascript/binding.js +3 -3
  8. package/dist/javascript/binding.js.map +1 -1
  9. package/dist/javascript/comparator.d.ts.map +1 -1
  10. package/dist/javascript/comparator.js +4 -0
  11. package/dist/javascript/comparator.js.map +1 -1
  12. package/dist/javascript/format/tabs-and-indents-visitor.d.ts.map +1 -1
  13. package/dist/javascript/format/tabs-and-indents-visitor.js +31 -4
  14. package/dist/javascript/format/tabs-and-indents-visitor.js.map +1 -1
  15. package/dist/javascript/index.d.ts +3 -0
  16. package/dist/javascript/index.d.ts.map +1 -1
  17. package/dist/javascript/index.js +3 -0
  18. package/dist/javascript/index.js.map +1 -1
  19. package/dist/javascript/markers.d.ts +12 -0
  20. package/dist/javascript/markers.d.ts.map +1 -1
  21. package/dist/javascript/markers.js +17 -2
  22. package/dist/javascript/markers.js.map +1 -1
  23. package/dist/javascript/migrate/es6/modernize-octal-escape-sequences.d.ts.map +1 -1
  24. package/dist/javascript/migrate/es6/modernize-octal-escape-sequences.js +28 -32
  25. package/dist/javascript/migrate/es6/modernize-octal-escape-sequences.js.map +1 -1
  26. package/dist/javascript/node-resolution-result.js +3 -2
  27. package/dist/javascript/node-resolution-result.js.map +1 -1
  28. package/dist/javascript/parser.d.ts +9 -0
  29. package/dist/javascript/parser.d.ts.map +1 -1
  30. package/dist/javascript/parser.js +185 -88
  31. package/dist/javascript/parser.js.map +1 -1
  32. package/dist/javascript/preconditions.d.ts +11 -0
  33. package/dist/javascript/preconditions.d.ts.map +1 -1
  34. package/dist/javascript/preconditions.js +14 -0
  35. package/dist/javascript/preconditions.js.map +1 -1
  36. package/dist/javascript/print.d.ts +10 -1
  37. package/dist/javascript/print.d.ts.map +1 -1
  38. package/dist/javascript/print.js +120 -77
  39. package/dist/javascript/print.js.map +1 -1
  40. package/dist/javascript/search/index.d.ts +1 -0
  41. package/dist/javascript/search/index.d.ts.map +1 -1
  42. package/dist/javascript/search/index.js +1 -0
  43. package/dist/javascript/search/index.js.map +1 -1
  44. package/dist/javascript/search/is-vendored-or-bundled.d.ts +13 -0
  45. package/dist/javascript/search/is-vendored-or-bundled.d.ts.map +1 -0
  46. package/dist/javascript/search/is-vendored-or-bundled.js +93 -0
  47. package/dist/javascript/search/is-vendored-or-bundled.js.map +1 -0
  48. package/dist/javascript/templating/engine.d.ts.map +1 -1
  49. package/dist/javascript/templating/engine.js +8 -3
  50. package/dist/javascript/templating/engine.js.map +1 -1
  51. package/dist/javascript/type-mapping.d.ts +1 -0
  52. package/dist/javascript/type-mapping.d.ts.map +1 -1
  53. package/dist/javascript/type-mapping.js +18 -3
  54. package/dist/javascript/type-mapping.js.map +1 -1
  55. package/dist/print.d.ts +6 -1
  56. package/dist/print.d.ts.map +1 -1
  57. package/dist/print.js +21 -7
  58. package/dist/print.js.map +1 -1
  59. package/dist/rewrite-javascript-version.txt +1 -1
  60. package/dist/rpc/java-rpc-client.d.ts +2 -0
  61. package/dist/rpc/java-rpc-client.d.ts.map +1 -1
  62. package/dist/rpc/java-rpc-client.js +1 -0
  63. package/dist/rpc/java-rpc-client.js.map +1 -1
  64. package/dist/rpc/queue.d.ts +8 -0
  65. package/dist/rpc/queue.d.ts.map +1 -1
  66. package/dist/rpc/queue.js +45 -3
  67. package/dist/rpc/queue.js.map +1 -1
  68. package/dist/rpc/request/get-object.d.ts +4 -0
  69. package/dist/rpc/request/get-object.d.ts.map +1 -1
  70. package/dist/rpc/request/get-object.js +23 -1
  71. package/dist/rpc/request/get-object.js.map +1 -1
  72. package/dist/rpc/request/parse.d.ts.map +1 -1
  73. package/dist/rpc/request/parse.js +3 -1
  74. package/dist/rpc/request/parse.js.map +1 -1
  75. package/dist/rpc/request/print.d.ts +8 -2
  76. package/dist/rpc/request/print.d.ts.map +1 -1
  77. package/dist/rpc/request/print.js +12 -9
  78. package/dist/rpc/request/print.js.map +1 -1
  79. package/dist/rpc/rewrite-rpc.d.ts +3 -2
  80. package/dist/rpc/rewrite-rpc.d.ts.map +1 -1
  81. package/dist/rpc/rewrite-rpc.js +9 -3
  82. package/dist/rpc/rewrite-rpc.js.map +1 -1
  83. package/dist/rpc/server.d.ts.map +1 -1
  84. package/dist/rpc/server.js +19 -5
  85. package/dist/rpc/server.js.map +1 -1
  86. package/dist/test/java-rpc.d.ts.map +1 -1
  87. package/dist/test/java-rpc.js +3 -0
  88. package/dist/test/java-rpc.js.map +1 -1
  89. package/package.json +1 -1
  90. package/src/javascript/add-import.ts +3 -2
  91. package/src/javascript/amd.ts +3 -2
  92. package/src/javascript/binding.ts +3 -3
  93. package/src/javascript/comparator.ts +10 -0
  94. package/src/javascript/format/tabs-and-indents-visitor.ts +30 -3
  95. package/src/javascript/index.ts +3 -0
  96. package/src/javascript/markers.ts +34 -4
  97. package/src/javascript/migrate/es6/modernize-octal-escape-sequences.ts +28 -36
  98. package/src/javascript/node-resolution-result.ts +3 -2
  99. package/src/javascript/parser.ts +200 -91
  100. package/src/javascript/preconditions.ts +19 -1
  101. package/src/javascript/print.ts +123 -76
  102. package/src/javascript/search/index.ts +1 -0
  103. package/src/javascript/search/is-vendored-or-bundled.ts +59 -0
  104. package/src/javascript/templating/engine.ts +7 -2
  105. package/src/javascript/type-mapping.ts +19 -3
  106. package/src/print.ts +23 -8
  107. package/src/rpc/java-rpc-client.ts +3 -0
  108. package/src/rpc/queue.ts +37 -3
  109. package/src/rpc/request/get-object.ts +24 -0
  110. package/src/rpc/request/parse.ts +4 -1
  111. package/src/rpc/request/print.ts +12 -8
  112. package/src/rpc/rewrite-rpc.ts +16 -5
  113. package/src/rpc/server.ts +18 -6
  114. package/src/test/java-rpc.ts +3 -0
package/src/rpc/queue.ts CHANGED
@@ -182,6 +182,13 @@ export class RpcSendQueue {
182
182
 
183
183
  send<T>(after: T | undefined, before: T | undefined, onChange?: (() => Promise<any>)): Promise<void> {
184
184
  return saveTrace(this.trace, async () => {
185
+ // The peer has a single absent value, and an ADD that carries nothing is not one it can decode.
186
+ if (after === null) {
187
+ after = undefined;
188
+ }
189
+ if (before === null) {
190
+ before = undefined;
191
+ }
185
192
  if (before === after) {
186
193
  this.put({state: RpcObjectState.NO_CHANGE});
187
194
  } else if (before === undefined || (after !== undefined && this.typesAreDifferent(after, before))) {
@@ -372,10 +379,20 @@ export class StringInternTable {
372
379
  }
373
380
  }
374
381
 
382
+ // Java's serializer names the class and numbers the object inside the value; the kind already says the first.
383
+ function withoutSerializerKeys(value: any): any {
384
+ if (value === null || typeof value !== "object") {
385
+ return value;
386
+ }
387
+ const {"@c": _class, "@ref": _ref, ...fields} = value;
388
+ return fields;
389
+ }
390
+
375
391
  export class RpcReceiveQueue {
376
392
  private batch: RpcObjectData[] = [];
377
393
  private batchIndex = 0;
378
394
  private sinceYield = 0;
395
+ private recorded: number[] = [];
379
396
 
380
397
  constructor(private readonly refs: Map<number, any>,
381
398
  private readonly sourceFileType: string | undefined,
@@ -385,6 +402,23 @@ export class RpcReceiveQueue {
385
402
  private readonly internedStrings: StringInternTable = new StringInternTable()) {
386
403
  }
387
404
 
405
+ private record(ref: number, value: any): void {
406
+ this.refs.set(ref, value);
407
+ this.recorded.push(ref);
408
+ }
409
+
410
+ /**
411
+ * Drops the refs this transfer defined, for when it could not be read to its end and the
412
+ * sender is about to forget them too.
413
+ * @internal
414
+ */
415
+ forgetRefs(): void {
416
+ for (const ref of this.recorded) {
417
+ this.refs.delete(ref);
418
+ }
419
+ this.recorded = [];
420
+ }
421
+
388
422
  /**
389
423
  * Returns a value rather than a promise for all but the message that refills the
390
424
  * batch or yields, so the common path costs neither a promise nor an async frame.
@@ -479,7 +513,7 @@ export class RpcReceiveQueue {
479
513
  // For an object like JavaType that we will mutate in place rather than using
480
514
  // immutable updates because of its cyclic nature, the before instance will ultimately
481
515
  // be the same as the after instance below.
482
- this.refs.set(ref, before);
516
+ this.record(ref, before);
483
517
  }
484
518
  }
485
519
  // Intentional fall-through...
@@ -492,7 +526,7 @@ export class RpcReceiveQueue {
492
526
  after = await codec.rpcReceive(before, this);
493
527
  } else if (message.value !== undefined) {
494
528
  after = message.valueType ?
495
- {kind: this.internedStrings.internType(message.valueType), ...message.value} :
529
+ {kind: this.internedStrings.internType(message.valueType), ...withoutSerializerKeys(message.value)} :
496
530
  typeof message.value === "string" ? this.internedStrings.internValue(message.value) : message.value;
497
531
  } else if (message.state === RpcObjectState.ADD && message.valueType) {
498
532
  throw new Error(
@@ -504,7 +538,7 @@ export class RpcReceiveQueue {
504
538
  after = before;
505
539
  }
506
540
  if (ref !== undefined) {
507
- this.refs.set(ref, after);
541
+ this.record(ref, after);
508
542
  }
509
543
  return after;
510
544
  default:
@@ -18,6 +18,11 @@ import {RpcObjectData, RpcObjectState, RpcSendQueue} from "../queue";
18
18
  import {ReferenceMap} from "../../reference";
19
19
  import {extractSourcePath, withMetrics} from "./metrics";
20
20
 
21
+ export class AbortGetObject {
22
+ constructor(readonly id: string) {
23
+ }
24
+ }
25
+
21
26
  export class GetObject {
22
27
  constructor(private readonly id: string,
23
28
  private readonly sourceFileType?: string) {
@@ -33,6 +38,24 @@ export class GetObject {
33
38
  metricsCsv?: string,
34
39
  ): void {
35
40
  const pendingData = new Map<string, { data: (RpcObjectData | undefined)[], offset: number }>();
41
+ let latestTransfer: { id: string, refCount: number } | undefined;
42
+
43
+ // The receiver could not read a transfer to its end and has dropped what it took from it.
44
+ connection.onRequest(
45
+ new rpc.RequestType<AbortGetObject, boolean, Error>("AbortGetObject"),
46
+ request => {
47
+ pendingData.delete(request.id);
48
+ remoteObjects.delete(request.id);
49
+ if (latestTransfer?.id === request.id) {
50
+ localRefs.rollbackTo(latestTransfer.refCount);
51
+ } else {
52
+ // which refs that transfer assigned is no longer known; everything goes out whole again
53
+ localRefs.clear();
54
+ }
55
+ latestTransfer = undefined;
56
+ return true;
57
+ }
58
+ );
36
59
 
37
60
  connection.onRequest(
38
61
  new rpc.RequestType<GetObject, any, Error>("GetObject"),
@@ -75,6 +98,7 @@ export class GetObject {
75
98
  };
76
99
  pendingData.set(objId, pending);
77
100
  remoteObjects.set(objId, after);
101
+ latestTransfer = {id: objId, refCount: savedRefCount};
78
102
  } catch (e) {
79
103
  remoteObjects.delete(objId);
80
104
  localRefs.rollbackTo(savedRefCount);
@@ -67,7 +67,10 @@ export class Parse {
67
67
  relativeTo: request.relativeTo
68
68
  })!;
69
69
 
70
- const generator = parser.parse(...request.inputs);
70
+ // an input without its text names a file for the parser to read
71
+ const inputs = request.inputs.map(input =>
72
+ typeof input === 'object' && input.text == null ? input.sourcePath : input);
73
+ const generator = parser.parse(...inputs);
71
74
  const resultIds: UUID[] = [];
72
75
 
73
76
  for (let i = 0; i < request.inputs.length; i++) {
@@ -14,25 +14,31 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import * as rpc from "vscode-jsonrpc/node";
17
- import {isSourceFile, Tree} from "../../tree";
17
+ import {Cursor, isSourceFile, Tree} from "../../tree";
18
18
  import {MarkerPrinter as PrintMarkerPrinter, printer, PrintOutputCapture} from "../../print";
19
19
  import {UUID} from "../../uuid";
20
20
  import {extractSourcePath, withMetrics} from "./metrics";
21
21
 
22
22
  export const enum MarkerPrinter {
23
23
  DEFAULT = "DEFAULT",
24
+ SEARCH_MARKERS_ONLY = "SEARCH_MARKERS_ONLY",
24
25
  FENCED = "FENCED",
25
26
  SANITIZED = "SANITIZED"
26
27
  }
27
28
 
28
29
  export class Print {
30
+ /**
31
+ * @param cursor The ids of what encloses a tree that is not a source file, from its parent outward.
32
+ */
29
33
  constructor(private readonly treeId: UUID,
30
34
  private readonly sourceFileType: string,
31
- readonly markerPrinter: MarkerPrinter = MarkerPrinter.DEFAULT) {
35
+ readonly markerPrinter: MarkerPrinter = MarkerPrinter.DEFAULT,
36
+ readonly cursor?: string[]) {
32
37
  }
33
38
 
34
39
  static handle(connection: rpc.MessageConnection,
35
40
  getObject: (id: string, sourceFileType: string) => any,
41
+ getCursor: (cursorIds: string[] | undefined, sourceFileType?: string) => Promise<Cursor>,
36
42
  logger?: rpc.Logger,
37
43
  metricsCsv?: string): void {
38
44
  connection.onRequest(
@@ -46,14 +52,12 @@ export class Print {
46
52
  if (logger) {
47
53
  logger.log("Printing " + (isSourceFile(tree) ? tree.sourcePath : `tree of type ${tree.kind} in ${context.target}`));
48
54
  }
49
- const out = new PrintOutputCapture(PrintMarkerPrinter[request.markerPrinter]);
50
- let result: string;
55
+ const out = new PrintOutputCapture(PrintMarkerPrinter[request.markerPrinter ?? MarkerPrinter.DEFAULT]);
51
56
  if (isSourceFile(tree)) {
52
- result = await printer(tree).print(tree, out);
53
- } else {
54
- result = await printer(request.sourceFileType).print(tree, out);
57
+ return printer(tree).print(tree, out);
55
58
  }
56
- return result;
59
+ const cursor = request.cursor ? await getCursor(request.cursor, request.sourceFileType) : undefined;
60
+ return printer(request.sourceFileType).print(tree, out, cursor);
57
61
  }
58
62
  )
59
63
  );
@@ -22,6 +22,7 @@ import {
22
22
  DependencyTypes,
23
23
  Generate,
24
24
  GenerateResponse,
25
+ AbortGetObject,
25
26
  GetObject,
26
27
  GetMarketplace,
27
28
  GetMarketplaceResponseRow,
@@ -30,6 +31,7 @@ import {
30
31
  ParseProject,
31
32
  PrepareRecipe,
32
33
  PrepareRecipeResponse,
34
+ MarkerPrinter,
33
35
  Print,
34
36
  TraceGetObject,
35
37
  Visit,
@@ -142,7 +144,7 @@ export class RewriteRpc {
142
144
  Parse.handle(this.connection, this.localObjects, options.metricsCsv);
143
145
  ParseProject.handle(this.connection, this.localObjects, options.metricsCsv);
144
146
  DependencyTypes.handle(this.connection, options?.batchSize || 1000, options.metricsCsv);
145
- Print.handle(this.connection, getObject, options.logger, options.metricsCsv);
147
+ Print.handle(this.connection, getObject, getCursor, options.logger, options.metricsCsv);
146
148
  InstallRecipes.handle(this.connection, options.recipeInstallDir ?? ".rewrite", marketplace, recipeOrigin, options.logger, options.metricsCsv);
147
149
 
148
150
  this.connection.onRequest(
@@ -289,6 +291,15 @@ export class RewriteRpc {
289
291
  await nextPage.catch(() => {
290
292
  });
291
293
  }
294
+ // The sender still counts the object and its refs as delivered until it is told otherwise.
295
+ const rolledBack = await this.connection.sendRequest(
296
+ new rpc.RequestType<AbortGetObject, boolean, Error>("AbortGetObject"),
297
+ new AbortGetObject(id)
298
+ ).catch(() => false);
299
+ if (rolledBack) {
300
+ // a peer that could not roll back goes on sending these refs bare, so they are kept for it
301
+ q.forgetRefs();
302
+ }
292
303
  throw e;
293
304
  }
294
305
 
@@ -321,9 +332,9 @@ export class RewriteRpc {
321
332
  return parsed;
322
333
  }
323
334
 
324
- async print(tree: SourceFile): Promise<string>;
325
- async print(tree: Tree, cursor: Cursor): Promise<string>;
326
- async print(tree: Tree, cursor?: Cursor): Promise<string> {
335
+ async print(tree: SourceFile, cursor?: undefined, markerPrinter?: MarkerPrinter): Promise<string>;
336
+ async print(tree: Tree, cursor: Cursor, markerPrinter?: MarkerPrinter): Promise<string>;
337
+ async print(tree: Tree, cursor?: Cursor, markerPrinter?: MarkerPrinter): Promise<string> {
327
338
  if (!cursor && !isSourceFile(tree)) {
328
339
  throw new Error("Cursor is required for non-SourceFile trees");
329
340
  }
@@ -331,7 +342,7 @@ export class RewriteRpc {
331
342
  const sourceFile = isSourceFile(tree) ? tree : cursor!.firstEnclosing(t => isSourceFile(t))!;
332
343
  return await this.connection.sendRequest(
333
344
  new rpc.RequestType<Print, string, Error>("Print"),
334
- new Print(tree.id, sourceFile.kind)
345
+ new Print(tree.id, sourceFile.kind, markerPrinter, isSourceFile(tree) ? undefined : this.getCursorIds(cursor))
335
346
  );
336
347
  }
337
348
 
package/src/rpc/server.ts CHANGED
@@ -22,6 +22,7 @@ import * as fs from "fs";
22
22
  import {Command} from 'commander';
23
23
  import {dir} from 'tmp-promise';
24
24
  import {DependencyWorkspace} from "../javascript/dependency-workspace";
25
+ import {isMainThread, parentPort, Worker} from "worker_threads";
25
26
 
26
27
  // Include all languages you want this server to support.
27
28
  import "../text";
@@ -30,9 +31,6 @@ import "../yaml";
30
31
  import "../java";
31
32
  import "../javascript";
32
33
 
33
- // Not possible to set the stack size when executing from npx for security reasons
34
- require('v8').setFlagsFromString('--stack-size=8000');
35
-
36
34
  function initPyroscope(logger: rpc.Logger): any {
37
35
  // Strip trailing slashes: the SDK builds the ingest URL as `${serverAddress}/ingest`,
38
36
  // so a trailing slash produces `//ingest`, which the server normalizes via redirect —
@@ -126,8 +124,8 @@ async function main() {
126
124
  }
127
125
  };
128
126
 
129
- process.on('SIGINT', shutdown);
130
- process.on('SIGTERM', shutdown);
127
+ // signals are delivered to the main thread, which passes them on
128
+ parentPort!.on('message', shutdown);
131
129
 
132
130
  const log = options.logFile ? fs.createWriteStream(options.logFile, {flags: 'a'}) : undefined;
133
131
  const logger: rpc.Logger = {
@@ -191,4 +189,18 @@ async function main() {
191
189
  });
192
190
  }
193
191
 
194
- main().catch(console.error);
192
+ if (isMainThread) {
193
+ // A thread's stack is sized when it starts, and the default is too shallow for the type checker
194
+ // on long chains of inferred return types, so the server runs on a thread started with more.
195
+ const server = new Worker(__filename, {
196
+ argv: process.argv.slice(2),
197
+ stdin: true,
198
+ resourceLimits: {stackSizeMb: 8}
199
+ });
200
+ process.stdin.pipe(server.stdin!);
201
+ process.on('SIGINT', () => server.postMessage('SIGINT'));
202
+ process.on('SIGTERM', () => server.postMessage('SIGTERM'));
203
+ server.on('exit', code => process.exit(code));
204
+ } else {
205
+ main().catch(console.error);
206
+ }
@@ -39,6 +39,7 @@
39
39
  */
40
40
  import {describe, type SuiteAPI, test as base} from "vitest";
41
41
  import {findTestClasspath, JavaRpcTestServer} from "../rpc/java-rpc-client";
42
+ import {RewriteRpc} from "../rpc/rewrite-rpc";
42
43
 
43
44
  export {findTestClasspath, JavaRpcTestServer} from "../rpc/java-rpc-client";
44
45
  export type {JavaRpcOptions} from "../rpc/java-rpc-client";
@@ -76,6 +77,8 @@ export const testJavaRpc = base.extend<JavaRpcFixtures>({
76
77
  {scope: "worker"},
77
78
  ],
78
79
  javaRpc: async ({_javaRpcServer}, use) => {
80
+ // any RewriteRpc constructed in this worker since has replaced it as the active connection
81
+ RewriteRpc.set(_javaRpcServer.rpc);
79
82
  await _javaRpcServer.reset();
80
83
  await use(_javaRpcServer);
81
84
  },