@openrewrite/rewrite 8.96.4 → 8.96.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/execution.d.ts +2 -0
- package/dist/execution.d.ts.map +1 -1
- package/dist/execution.js +4 -0
- package/dist/execution.js.map +1 -1
- package/dist/heavyweight.d.ts +8 -0
- package/dist/heavyweight.d.ts.map +1 -0
- package/dist/heavyweight.js +45 -0
- package/dist/heavyweight.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/java/visitor.d.ts.map +1 -1
- package/dist/java/visitor.js +16 -2
- package/dist/java/visitor.js.map +1 -1
- package/dist/javascript/add-import.d.ts +2 -1
- package/dist/javascript/add-import.d.ts.map +1 -1
- package/dist/javascript/add-import.js +14 -2
- package/dist/javascript/add-import.js.map +1 -1
- package/dist/javascript/amd.d.ts.map +1 -1
- package/dist/javascript/amd.js +2 -1
- package/dist/javascript/amd.js.map +1 -1
- package/dist/javascript/cleanup/add-parse-int-radix.js +1 -1
- package/dist/javascript/cleanup/add-parse-int-radix.js.map +1 -1
- package/dist/javascript/format/format.d.ts +10 -0
- package/dist/javascript/format/format.d.ts.map +1 -1
- package/dist/javascript/format/format.js +10 -2
- package/dist/javascript/format/format.js.map +1 -1
- package/dist/javascript/format/tabs-and-indents-visitor.d.ts.map +1 -1
- package/dist/javascript/format/tabs-and-indents-visitor.js +4 -0
- package/dist/javascript/format/tabs-and-indents-visitor.js.map +1 -1
- package/dist/javascript/format/whitespace-reconciler.d.ts.map +1 -1
- package/dist/javascript/format/whitespace-reconciler.js +4 -0
- package/dist/javascript/format/whitespace-reconciler.js.map +1 -1
- package/dist/javascript/node-resolution-result.d.ts.map +1 -1
- package/dist/javascript/node-resolution-result.js +2 -0
- package/dist/javascript/node-resolution-result.js.map +1 -1
- package/dist/javascript/parser-utils.d.ts.map +1 -1
- package/dist/javascript/parser-utils.js +9 -6
- package/dist/javascript/parser-utils.js.map +1 -1
- package/dist/javascript/templating/engine.d.ts.map +1 -1
- package/dist/javascript/templating/engine.js +11 -6
- package/dist/javascript/templating/engine.js.map +1 -1
- package/dist/javascript/templating/pattern.d.ts.map +1 -1
- package/dist/javascript/templating/pattern.js +8 -0
- package/dist/javascript/templating/pattern.js.map +1 -1
- package/dist/javascript/templating/placeholder-replacement.d.ts.map +1 -1
- package/dist/javascript/templating/placeholder-replacement.js +15 -0
- package/dist/javascript/templating/placeholder-replacement.js.map +1 -1
- package/dist/javascript/visitor.d.ts.map +1 -1
- package/dist/javascript/visitor.js +21 -0
- package/dist/javascript/visitor.js.map +1 -1
- package/dist/recipe.d.ts +5 -0
- package/dist/recipe.d.ts.map +1 -1
- package/dist/recipe.js +5 -0
- package/dist/recipe.js.map +1 -1
- package/dist/rewrite-javascript-version.txt +1 -1
- package/dist/run.d.ts +7 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +40 -2
- package/dist/run.js.map +1 -1
- package/dist/test/accumulator-contents.d.ts +15 -0
- package/dist/test/accumulator-contents.d.ts.map +1 -0
- package/dist/test/accumulator-contents.js +185 -0
- package/dist/test/accumulator-contents.js.map +1 -0
- package/dist/test/empty-sources.d.ts +14 -0
- package/dist/test/empty-sources.d.ts.map +1 -0
- package/dist/test/empty-sources.js +98 -0
- package/dist/test/empty-sources.js.map +1 -0
- package/dist/test/formatting-scope.d.ts +18 -0
- package/dist/test/formatting-scope.d.ts.map +1 -0
- package/dist/test/formatting-scope.js +244 -0
- package/dist/test/formatting-scope.js.map +1 -0
- package/dist/test/probes.d.ts +25 -0
- package/dist/test/probes.d.ts.map +1 -0
- package/dist/test/probes.js +189 -0
- package/dist/test/probes.js.map +1 -0
- package/dist/test/rewrite-test.d.ts +27 -0
- package/dist/test/rewrite-test.d.ts.map +1 -1
- package/dist/test/rewrite-test.js +191 -21
- package/dist/test/rewrite-test.js.map +1 -1
- package/dist/test/tree-shapes.d.ts +15 -0
- package/dist/test/tree-shapes.d.ts.map +1 -0
- package/dist/test/tree-shapes.js +288 -0
- package/dist/test/tree-shapes.js.map +1 -0
- package/dist/test/unparsed-sources.d.ts +17 -0
- package/dist/test/unparsed-sources.d.ts.map +1 -0
- package/dist/test/unparsed-sources.js +113 -0
- package/dist/test/unparsed-sources.js.map +1 -0
- package/dist/tree.d.ts.map +1 -1
- package/dist/tree.js +2 -0
- package/dist/tree.js.map +1 -1
- package/dist/visitor.d.ts.map +1 -1
- package/dist/visitor.js +2 -0
- package/dist/visitor.js.map +1 -1
- package/package.json +1 -1
- package/src/execution.ts +6 -0
- package/src/heavyweight.ts +42 -0
- package/src/index.ts +1 -0
- package/src/java/visitor.ts +16 -2
- package/src/javascript/add-import.ts +11 -2
- package/src/javascript/amd.ts +4 -2
- package/src/javascript/cleanup/add-parse-int-radix.ts +2 -2
- package/src/javascript/format/format.ts +18 -0
- package/src/javascript/format/tabs-and-indents-visitor.ts +4 -0
- package/src/javascript/format/whitespace-reconciler.ts +4 -0
- package/src/javascript/node-resolution-result.ts +3 -0
- package/src/javascript/parser-utils.ts +10 -6
- package/src/javascript/templating/engine.ts +11 -6
- package/src/javascript/templating/pattern.ts +10 -0
- package/src/javascript/templating/placeholder-replacement.ts +16 -0
- package/src/javascript/visitor.ts +30 -0
- package/src/recipe.ts +5 -0
- package/src/run.ts +30 -2
- package/src/test/accumulator-contents.ts +194 -0
- package/src/test/empty-sources.ts +99 -0
- package/src/test/formatting-scope.ts +231 -0
- package/src/test/probes.ts +156 -0
- package/src/test/rewrite-test.ts +177 -24
- package/src/test/tree-shapes.ts +332 -0
- package/src/test/unparsed-sources.ts +138 -0
- package/src/tree.ts +3 -0
- package/src/visitor.ts +3 -0
package/dist/tree.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree.js","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"tree.js","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":"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"}
|
package/dist/visitor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visitor.d.ts","sourceRoot":"","sources":["../src/visitor.ts"],"names":[],"mappings":"AAeA,OAAO,EAAe,MAAM,EAAE,OAAO,EAAC,MAAM,WAAW,CAAC;AACxD,OAAO,EAAC,MAAM,EAA4B,UAAU,EAAE,IAAI,EAAC,MAAM,QAAQ,CAAC;AAC1E,OAAO,EAAS,KAAK,EAAC,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"visitor.d.ts","sourceRoot":"","sources":["../src/visitor.ts"],"names":[],"mappings":"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"}
|
package/dist/visitor.js
CHANGED
|
@@ -22,6 +22,7 @@ const markers_1 = require("./markers");
|
|
|
22
22
|
const tree_1 = require("./tree");
|
|
23
23
|
const mutative_1 = require("mutative");
|
|
24
24
|
const util_1 = require("./util");
|
|
25
|
+
const heavyweight_1 = require("./heavyweight");
|
|
25
26
|
async function produceAsync(before, recipe) {
|
|
26
27
|
const b = await before;
|
|
27
28
|
// Mutative's create(base, recipe) supports async recipes and rawReturn(undefined)
|
|
@@ -140,6 +141,7 @@ class TreeVisitor {
|
|
|
140
141
|
}
|
|
141
142
|
}
|
|
142
143
|
exports.TreeVisitor = TreeVisitor;
|
|
144
|
+
(0, heavyweight_1.registerHeavyweight)(TreeVisitor);
|
|
143
145
|
function noopVisitor() {
|
|
144
146
|
return new class extends TreeVisitor {
|
|
145
147
|
async visit(tree) {
|
package/dist/visitor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visitor.js","sourceRoot":"","sources":["../src/visitor.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"visitor.js","sourceRoot":"","sources":["../src/visitor.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/execution.ts
CHANGED
|
@@ -14,11 +14,15 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import {RpcCodec, RpcCodecs, RpcReceiveQueue, RpcSendQueue} from "./rpc";
|
|
17
|
+
import {registerHeavyweight} from "./heavyweight";
|
|
17
18
|
|
|
18
19
|
export class ExecutionContext {
|
|
19
20
|
/** Mirrors `org.openrewrite.ExecutionContext.REQUIRE_PRINT_EQUALS_INPUT`. */
|
|
20
21
|
static readonly REQUIRE_PRINT_EQUALS_INPUT = "org.openrewrite.requirePrintEqualsInput";
|
|
21
22
|
|
|
23
|
+
/** Mirrors `org.openrewrite.ExecutionContext.SCANNING_MUTATION_VALIDATION`, which the test harness sets. */
|
|
24
|
+
static readonly SCANNING_MUTATION_VALIDATION = "org.openrewrite.test.scanningMutationValidation";
|
|
25
|
+
|
|
22
26
|
readonly kind: string = "org.openrewrite.InMemoryExecutionContext"
|
|
23
27
|
|
|
24
28
|
constructor(public readonly messages: { [key: string | symbol]: any } = {}) {
|
|
@@ -45,6 +49,8 @@ export class ExecutionContext {
|
|
|
45
49
|
}
|
|
46
50
|
}
|
|
47
51
|
|
|
52
|
+
registerHeavyweight(ExecutionContext);
|
|
53
|
+
|
|
48
54
|
const executionContextCodec: RpcCodec<ExecutionContext> = {
|
|
49
55
|
rpcNew(): ExecutionContext {
|
|
50
56
|
return new ExecutionContext();
|
|
@@ -0,0 +1,42 @@
|
|
|
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 {MarkersKind} from "./markers";
|
|
17
|
+
|
|
18
|
+
const heavyweightClasses: Function[] = [];
|
|
19
|
+
const heavyweightKinds = new Set<string>();
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Registers a class, or the kind of a plain object such as a marker, as a type too expensive to keep in memory for a
|
|
23
|
+
* whole run, as in a ScanningRecipe's accumulator.
|
|
24
|
+
*/
|
|
25
|
+
export function registerHeavyweight(type: string | (abstract new (...args: any[]) => unknown)): void {
|
|
26
|
+
if (typeof type === "string") {
|
|
27
|
+
heavyweightKinds.add(type);
|
|
28
|
+
} else if (!heavyweightClasses.includes(type)) {
|
|
29
|
+
heavyweightClasses.push(type);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** The registered kind or class that `value` is of, or the kind of a tree, which is always heavyweight. */
|
|
34
|
+
export function heavyweightType(value: object): string | Function | undefined {
|
|
35
|
+
const kind = (value as { kind?: unknown }).kind;
|
|
36
|
+
// a tree has an id and markers, and so do the Markers that hold its markers
|
|
37
|
+
if (typeof kind === "string" && (heavyweightKinds.has(kind) ||
|
|
38
|
+
"id" in value && "markers" in value && kind !== MarkersKind.Markers)) {
|
|
39
|
+
return kind;
|
|
40
|
+
}
|
|
41
|
+
return heavyweightClasses.find(type => value instanceof type);
|
|
42
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -33,6 +33,7 @@ export * from "./util";
|
|
|
33
33
|
export * from "./recipe";
|
|
34
34
|
export * from "./run";
|
|
35
35
|
export * from "./marketplace";
|
|
36
|
+
export {registerHeavyweight} from "./heavyweight";
|
|
36
37
|
|
|
37
38
|
// Install all recipes in this package
|
|
38
39
|
export async function activate(marketplace: RecipeMarketplace): Promise<void> {
|
package/src/java/visitor.ts
CHANGED
|
@@ -221,6 +221,12 @@ export class JavaVisitor<P> extends TreeVisitor<J, P> {
|
|
|
221
221
|
if (!expression?.kind || expression.kind !== J.Kind.Binary) {
|
|
222
222
|
return expression;
|
|
223
223
|
}
|
|
224
|
+
const given = this.cursor;
|
|
225
|
+
if (expression !== binary && given.value === binary) {
|
|
226
|
+
// the operands are visited under the binary that holds them, where a template reads their slots
|
|
227
|
+
this.cursor = new Cursor(expression, given.parent);
|
|
228
|
+
given.messages.forEach((value, key) => this.cursor.messages.set(key, value));
|
|
229
|
+
}
|
|
224
230
|
binary = expression as J.Binary;
|
|
225
231
|
|
|
226
232
|
const updates = {
|
|
@@ -231,6 +237,11 @@ export class JavaVisitor<P> extends TreeVisitor<J, P> {
|
|
|
231
237
|
right: await this.visitDefined(binary.right, p) as Expression,
|
|
232
238
|
type: await this.visitType(binary.type, p)
|
|
233
239
|
};
|
|
240
|
+
if (this.cursor !== given) {
|
|
241
|
+
// what follows reads the cursor of the binary it was given, as for every other tree
|
|
242
|
+
this.cursor.messages.forEach((value, key) => given.messages.set(key, value));
|
|
243
|
+
this.cursor = given;
|
|
244
|
+
}
|
|
234
245
|
return updateIfChanged(binary, updates);
|
|
235
246
|
}
|
|
236
247
|
|
|
@@ -1241,9 +1252,12 @@ export class JavaVisitor<P> extends TreeVisitor<J, P> {
|
|
|
1241
1252
|
|
|
1242
1253
|
const updates: any = {
|
|
1243
1254
|
prefix: await this.visitSpace(aYield.prefix, p),
|
|
1244
|
-
markers: await this.visitMarkers(aYield.markers, p)
|
|
1245
|
-
value: await this.visitDefined(aYield.value, p) as Expression
|
|
1255
|
+
markers: await this.visitMarkers(aYield.markers, p)
|
|
1246
1256
|
};
|
|
1257
|
+
// a bare `yield` has no value
|
|
1258
|
+
if (aYield.value) {
|
|
1259
|
+
updates.value = await this.visitDefined(aYield.value, p) as Expression;
|
|
1260
|
+
}
|
|
1247
1261
|
return updateIfChanged(aYield, updates);
|
|
1248
1262
|
}
|
|
1249
1263
|
|
|
@@ -12,6 +12,7 @@ import {bindingNames, compilationUnitOf, cursorOf, declarationsOf, deconflict, i
|
|
|
12
12
|
import {create as produce, Draft} from "mutative";
|
|
13
13
|
import {autoFormat} from "./format";
|
|
14
14
|
import {getPrettierStyle} from "./format/prettier-format";
|
|
15
|
+
import ts from "typescript";
|
|
15
16
|
|
|
16
17
|
export type QuoteChar = "'" | '"';
|
|
17
18
|
|
|
@@ -562,7 +563,8 @@ function claimedName(v: unknown): string | undefined {
|
|
|
562
563
|
/**
|
|
563
564
|
* The parser lifts surrogate pairs out of `valueSource` into `unicodeEscapes` and, when it does,
|
|
564
565
|
* sets `value` to the quoted source (`parser.ts` `mapLiteral`), so neither field alone is the
|
|
565
|
-
* module name. Reuniting them and
|
|
566
|
+
* module name. Reuniting them and reading the quoted text as the language does yields it for
|
|
567
|
+
* either shape of literal.
|
|
566
568
|
*/
|
|
567
569
|
export function moduleNameOf(module: string | J.Literal): string {
|
|
568
570
|
if (typeof module === 'string') {
|
|
@@ -579,6 +581,13 @@ export function moduleNameOf(module: string | J.Literal): string {
|
|
|
579
581
|
cut = escape.valueSourceIndex;
|
|
580
582
|
}
|
|
581
583
|
restored += source.slice(cut);
|
|
584
|
+
// an escape such as `\u00dc` names the character it spells
|
|
585
|
+
const scanner = ts.createScanner(ts.ScriptTarget.Latest, false, ts.LanguageVariant.Standard, restored);
|
|
586
|
+
const token = scanner.scan();
|
|
587
|
+
if ((token === ts.SyntaxKind.StringLiteral || token === ts.SyntaxKind.NoSubstitutionTemplateLiteral) &&
|
|
588
|
+
scanner.getTokenEnd() === restored.length) {
|
|
589
|
+
return scanner.getTokenValue();
|
|
590
|
+
}
|
|
582
591
|
const quote = restored.charAt(0);
|
|
583
592
|
return (quote === "'" || quote === '"' || quote === '`') && restored.endsWith(quote) && restored.length > 1
|
|
584
593
|
? restored.slice(1, -1)
|
|
@@ -1583,7 +1592,7 @@ export class AddImport<P> extends JavaScriptVisitor<P> {
|
|
|
1583
1592
|
value: this.module,
|
|
1584
1593
|
valueSource,
|
|
1585
1594
|
unicodeEscapes: this.moduleUnicodeEscapes,
|
|
1586
|
-
type:
|
|
1595
|
+
type: Type.Primitive.String
|
|
1587
1596
|
};
|
|
1588
1597
|
}
|
|
1589
1598
|
|
package/src/javascript/amd.ts
CHANGED
|
@@ -25,7 +25,8 @@ import {
|
|
|
25
25
|
rightPadded,
|
|
26
26
|
space,
|
|
27
27
|
Statement,
|
|
28
|
-
TrailingComma
|
|
28
|
+
TrailingComma,
|
|
29
|
+
Type
|
|
29
30
|
} from "../java";
|
|
30
31
|
import {JS} from "./tree";
|
|
31
32
|
import {moduleNameOf} from "./add-import";
|
|
@@ -428,7 +429,8 @@ function dependencyLiteral(module: string, quote: string): J.Literal {
|
|
|
428
429
|
prefix: emptySpace,
|
|
429
430
|
markers: emptyMarkers,
|
|
430
431
|
value: module,
|
|
431
|
-
valueSource: `${quote}${module}${quote}
|
|
432
|
+
valueSource: `${quote}${module}${quote}`,
|
|
433
|
+
type: Type.Primitive.String
|
|
432
434
|
};
|
|
433
435
|
}
|
|
434
436
|
|
|
@@ -18,7 +18,7 @@ import {Recipe} from "../../recipe";
|
|
|
18
18
|
import {TreeVisitor} from "../../visitor";
|
|
19
19
|
import {ExecutionContext} from "../../execution";
|
|
20
20
|
import {JavaScriptVisitor} from "../visitor";
|
|
21
|
-
import {J, singleSpace} from "../../java";
|
|
21
|
+
import {J, singleSpace, Type} from "../../java";
|
|
22
22
|
import {emptyMarkers} from "../../markers";
|
|
23
23
|
import {randomId} from "../../uuid";
|
|
24
24
|
|
|
@@ -73,7 +73,7 @@ export class AddParseIntRadix extends Recipe {
|
|
|
73
73
|
value: 10,
|
|
74
74
|
valueSource: '10',
|
|
75
75
|
unicodeEscapes: undefined,
|
|
76
|
-
type:
|
|
76
|
+
type: Type.Primitive.Double
|
|
77
77
|
};
|
|
78
78
|
|
|
79
79
|
return {
|
|
@@ -26,6 +26,7 @@ import {TabsAndIndentsVisitor} from "./tabs-and-indents-visitor";
|
|
|
26
26
|
import {NormalizeWhitespaceVisitor} from "./normalize-whitespace-visitor";
|
|
27
27
|
import {MinimumViableSpacingVisitor} from "./minimum-viable-spacing-visitor";
|
|
28
28
|
import {applyPrettierFormatting, getPrettierStyle} from "./prettier-format";
|
|
29
|
+
import {AsyncLocalStorage} from "node:async_hooks";
|
|
29
30
|
|
|
30
31
|
export {TabsAndIndentsVisitor} from "./tabs-and-indents-visitor";
|
|
31
32
|
export {NormalizeWhitespaceVisitor} from "./normalize-whitespace-visitor";
|
|
@@ -56,6 +57,22 @@ export const autoIndent = async <J2 extends J, P>(j: J2, p: P, parent?: Cursor):
|
|
|
56
57
|
return await new TabsAndIndentsVisitor(style).visit(j, p, parent) as J2;
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Hears about each request to auto-format a tree made while it listens, so that a test harness can check that a
|
|
62
|
+
* recipe formats only what it changed.
|
|
63
|
+
*/
|
|
64
|
+
export interface FormattingListener {
|
|
65
|
+
/** AutoformatVisitor calls this before it formats `tree`, stopping after `stopAfter` when it is given. */
|
|
66
|
+
onFormat(tree: Tree, stopAfter: Tree | undefined, cursor: Cursor | undefined): void;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const formattingListener = new AsyncLocalStorage<FormattingListener>();
|
|
70
|
+
|
|
71
|
+
/** Runs `run`, telling `listener` about the formatting it requests. */
|
|
72
|
+
export function listenToFormatting<T>(listener: FormattingListener, run: () => Promise<T>): Promise<T> {
|
|
73
|
+
return formattingListener.run(listener, run);
|
|
74
|
+
}
|
|
75
|
+
|
|
59
76
|
/**
|
|
60
77
|
* Formats JavaScript/TypeScript code using a comprehensive set of formatting rules.
|
|
61
78
|
*
|
|
@@ -77,6 +94,7 @@ export class AutoformatVisitor<P> extends JavaScriptVisitor<P> {
|
|
|
77
94
|
}
|
|
78
95
|
|
|
79
96
|
async visit<R extends J>(tree: Tree, p: P, cursor?: Cursor): Promise<R | undefined> {
|
|
97
|
+
formattingListener.getStore()?.onFormat(tree, this.stopAfter, cursor);
|
|
80
98
|
const prettierStyle = getPrettierStyle(tree, cursor, this.styles);
|
|
81
99
|
if (prettierStyle) {
|
|
82
100
|
const formatted = await applyPrettierFormatting(tree as R, prettierStyle, p, cursor, this.stopAfter);
|
|
@@ -408,6 +408,10 @@ export class TabsAndIndentsVisitor<P> extends JavaScriptVisitor<P> {
|
|
|
408
408
|
return literal;
|
|
409
409
|
}
|
|
410
410
|
return produce(literal, draft => {
|
|
411
|
+
// JSX text is its own value, as the parser makes it
|
|
412
|
+
if (draft.value === draft.valueSource) {
|
|
413
|
+
draft.value = normalizedValueSource;
|
|
414
|
+
}
|
|
411
415
|
draft.valueSource = normalizedValueSource;
|
|
412
416
|
});
|
|
413
417
|
}
|
|
@@ -416,6 +416,10 @@ export class WhitespaceReconciler {
|
|
|
416
416
|
original: J.Identifier | J.Literal,
|
|
417
417
|
formatted: J.Identifier | J.Literal
|
|
418
418
|
): J.Identifier | J.Literal {
|
|
419
|
+
// A literal's type follows from how it is written, so an identifier's is not the literal's
|
|
420
|
+
if (isLiteral(formatted)) {
|
|
421
|
+
return formatted;
|
|
422
|
+
}
|
|
419
423
|
const result: Record<string, unknown> = { ...formatted };
|
|
420
424
|
|
|
421
425
|
// Preserve type attribution - both Identifier and Literal have `type`
|
|
@@ -19,6 +19,7 @@ import {asRef} from "../reference";
|
|
|
19
19
|
import {RpcCodecs, RpcReceiveQueue, RpcSendQueue} from "../rpc";
|
|
20
20
|
import {castDraft} from "mutative";
|
|
21
21
|
import {updateIfChanged} from "../util";
|
|
22
|
+
import {registerHeavyweight} from "../heavyweight";
|
|
22
23
|
import * as semver from "semver";
|
|
23
24
|
import * as fsp from "fs/promises";
|
|
24
25
|
import * as path from "path";
|
|
@@ -259,6 +260,8 @@ export interface NodeResolutionResult extends Marker {
|
|
|
259
260
|
readonly npmrcConfigs?: Npmrc[];
|
|
260
261
|
}
|
|
261
262
|
|
|
263
|
+
registerHeavyweight(NodeResolutionResultKind);
|
|
264
|
+
|
|
262
265
|
/**
|
|
263
266
|
* Creates a NodeResolutionResult marker from a package.json file.
|
|
264
267
|
* Should be called during parsing to attach to JS.CompilationUnit.
|
|
@@ -17,7 +17,8 @@ import * as ts from "typescript";
|
|
|
17
17
|
import {Expression, J, Statement} from "../java";
|
|
18
18
|
import {JS} from "./tree";
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
// Built on first use, since ./tree imports the visitor, which imports this module
|
|
21
|
+
const statementKinds = (): string[] => [
|
|
21
22
|
J.Kind.Assert,
|
|
22
23
|
J.Kind.Assignment,
|
|
23
24
|
J.Kind.AssignmentOperation,
|
|
@@ -78,9 +79,9 @@ const is_statements = new Set<string>([
|
|
|
78
79
|
JS.Kind.WithStatement,
|
|
79
80
|
JS.Kind.ExpressionStatement,
|
|
80
81
|
JS.Kind.StatementExpression
|
|
81
|
-
]
|
|
82
|
+
];
|
|
82
83
|
|
|
83
|
-
const
|
|
84
|
+
const expressionKinds = (): string[] => [
|
|
84
85
|
J.Kind.AnnotatedType,
|
|
85
86
|
J.Kind.Annotation,
|
|
86
87
|
J.Kind.ArrayAccess,
|
|
@@ -157,14 +158,17 @@ const is_expressions = new Set<string>([
|
|
|
157
158
|
JS.Kind.Void,
|
|
158
159
|
JS.Kind.ExpressionStatement,
|
|
159
160
|
JS.Kind.StatementExpression
|
|
160
|
-
]
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
let is_statements: Set<string> | undefined;
|
|
164
|
+
let is_expressions: Set<string> | undefined;
|
|
161
165
|
|
|
162
166
|
export function isStatement(statement: J): statement is Statement {
|
|
163
|
-
return is_statements.has(statement.kind);
|
|
167
|
+
return (is_statements ??= new Set(statementKinds())).has(statement.kind);
|
|
164
168
|
}
|
|
165
169
|
|
|
166
170
|
export function isExpression(expression: J): expression is Expression {
|
|
167
|
-
return is_expressions.has(expression.kind);
|
|
171
|
+
return (is_expressions ??= new Set(expressionKinds())).has(expression.kind);
|
|
168
172
|
}
|
|
169
173
|
|
|
170
174
|
export function getNextSibling(node: ts.Node): ts.Node | undefined {
|
|
@@ -756,14 +756,18 @@ class MarkerAttachmentVisitor extends JavaScriptVisitor<undefined> {
|
|
|
756
756
|
}
|
|
757
757
|
|
|
758
758
|
// FIXME: This is a heuristic to determine if the parent expects a statement child
|
|
759
|
-
function expectsStatement(parentTree: J): boolean {
|
|
759
|
+
function expectsStatement(parentTree: J, childId: string): boolean {
|
|
760
|
+
if (parentTree.kind === J.Kind.Case) {
|
|
761
|
+
// the labels of a case are expressions
|
|
762
|
+
return !(parentTree as J.Case).caseLabels.elements.some(label => label.element.id === childId);
|
|
763
|
+
}
|
|
760
764
|
return parentTree.kind === J.Kind.Block ||
|
|
761
|
-
parentTree.kind === J.Kind.Case ||
|
|
762
765
|
parentTree.kind === J.Kind.DoWhileLoop ||
|
|
763
766
|
parentTree.kind === J.Kind.ForEachLoop ||
|
|
764
767
|
parentTree.kind === J.Kind.ForLoop ||
|
|
765
768
|
parentTree.kind === J.Kind.If ||
|
|
766
769
|
parentTree.kind === J.Kind.IfElse ||
|
|
770
|
+
parentTree.kind === J.Kind.Label ||
|
|
767
771
|
parentTree.kind === J.Kind.WhileLoop ||
|
|
768
772
|
parentTree.kind === JS.Kind.CompilationUnit ||
|
|
769
773
|
parentTree.kind === JS.Kind.ForInLoop;
|
|
@@ -782,7 +786,7 @@ export function replacedByObjectLiteral(tree: J, cursor: Cursor): boolean {
|
|
|
782
786
|
return true;
|
|
783
787
|
}
|
|
784
788
|
const parentTree = cursor.parentTree()?.value;
|
|
785
|
-
return parentTree !== undefined && !expectsStatement(parentTree);
|
|
789
|
+
return parentTree !== undefined && !expectsStatement(parentTree, tree.id);
|
|
786
790
|
}
|
|
787
791
|
|
|
788
792
|
/**
|
|
@@ -915,7 +919,7 @@ export class TemplateApplier {
|
|
|
915
919
|
|
|
916
920
|
// Only apply wrapping logic if we have parent context
|
|
917
921
|
if (parentTree) {
|
|
918
|
-
const parentExpectsStatement = expectsStatement(parentTree);
|
|
922
|
+
const parentExpectsStatement = expectsStatement(parentTree, originalTree.id);
|
|
919
923
|
const originalIsStatement = isStatement(originalTree);
|
|
920
924
|
|
|
921
925
|
const resultIsStatement = isStatement(resultToUse);
|
|
@@ -935,8 +939,9 @@ export class TemplateApplier {
|
|
|
935
939
|
expression: { ...expression, prefix: emptySpace }
|
|
936
940
|
} as JS.ExpressionStatement;
|
|
937
941
|
}
|
|
938
|
-
} else if (!parentExpectsStatement) {
|
|
939
|
-
// Expression context: wrap in StatementExpression if result is statement-only
|
|
942
|
+
} else if (!parentExpectsStatement && isExpression(originalTree)) {
|
|
943
|
+
// Expression context: wrap in StatementExpression if result is statement-only. A slot that held
|
|
944
|
+
// a statement-only node, such as an arrow function's block body, takes one unwrapped.
|
|
940
945
|
if (resultIsStatement && !resultIsExpression) {
|
|
941
946
|
const stmt = resultToUse as Statement;
|
|
942
947
|
resultToUse = {
|
|
@@ -756,6 +756,16 @@ class Matcher {
|
|
|
756
756
|
opensWithBrace(this.pattern.templateParts) && this.ast.kind !== J.Kind.Block);
|
|
757
757
|
}
|
|
758
758
|
|
|
759
|
+
// A visit reaches what parentheses hold right after them, so seeing through them here would match it twice
|
|
760
|
+
if ((this.ast.kind === J.Kind.Parentheses || this.ast.kind === J.Kind.ControlParentheses) &&
|
|
761
|
+
this.patternAst.kind !== this.ast.kind) {
|
|
762
|
+
if (this.debugOptions.enabled) {
|
|
763
|
+
this.setExplanation('kind-mismatch', 'An expression without parentheses',
|
|
764
|
+
`Parentheses (${this.ast.kind.split('.').pop()})`,
|
|
765
|
+
'The expression the parentheses hold is matched on its own');
|
|
766
|
+
}
|
|
767
|
+
return false;
|
|
768
|
+
}
|
|
759
769
|
return this.matchNode(this.patternAst, this.ast);
|
|
760
770
|
}
|
|
761
771
|
|
|
@@ -41,6 +41,18 @@ export class SubstitutedValue implements Marker {
|
|
|
41
41
|
/** Chooses a substituted value's prefix, and says whether it is the source's own. */
|
|
42
42
|
type MergePrefix = (sourcePrefix: J.Space, templatePrefix: J.Space) => [J.Space, boolean];
|
|
43
43
|
|
|
44
|
+
/** Whether `value` is a property, method or spread of an object literal. */
|
|
45
|
+
function isObjectMember(value: unknown): value is J {
|
|
46
|
+
switch (isTree(value) && value.kind) {
|
|
47
|
+
case JS.Kind.PropertyAssignment:
|
|
48
|
+
case JS.Kind.Spread:
|
|
49
|
+
case J.Kind.MethodDeclaration:
|
|
50
|
+
case JS.Kind.ComputedPropertyMethodDeclaration:
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
|
|
44
56
|
/**
|
|
45
57
|
* Visitor that replaces placeholder nodes with actual parameter values.
|
|
46
58
|
*/
|
|
@@ -331,6 +343,10 @@ export class PlaceholderReplacementVisitor extends JavaScriptVisitor<any> {
|
|
|
331
343
|
else if (Array.isArray(param.value)) {
|
|
332
344
|
arrayToExpand = param.value as J[];
|
|
333
345
|
}
|
|
346
|
+
// One member of an object literal fills the slot of a member, not the name of a property
|
|
347
|
+
else if (element.kind === JS.Kind.PropertyAssignment && isObjectMember(param.value)) {
|
|
348
|
+
arrayToExpand = [param.value];
|
|
349
|
+
}
|
|
334
350
|
// Check if it's a CaptureValue
|
|
335
351
|
else if (param.value instanceof CaptureValue) {
|
|
336
352
|
const resolved = param.value.resolve(this.values);
|
|
@@ -16,11 +16,13 @@
|
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
18
|
import {mapAsync, updateIfChanged} from "../util";
|
|
19
|
+
import {Markers} from "../markers";
|
|
19
20
|
import {SourceFile} from "../tree";
|
|
20
21
|
import {ValidRecipeReturnType} from "../visitor";
|
|
21
22
|
import {Expression, J, JavaVisitor, NameTree, Statement, Type, TypedTree} from "../java";
|
|
22
23
|
import {create, Draft} from "mutative";
|
|
23
24
|
import {isJavaScript, JS, JSX} from "./tree";
|
|
25
|
+
import {isStatement} from "./parser-utils";
|
|
24
26
|
|
|
25
27
|
export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
26
28
|
|
|
@@ -276,6 +278,16 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
276
278
|
markers: await this.visitMarkers(expressionStatement.markers, p),
|
|
277
279
|
expression: await this.visitDefined<Expression>(expressionStatement.expression, p)
|
|
278
280
|
};
|
|
281
|
+
// Outside a `for` head the parser makes a statement the statement itself, so a visit that makes one does too
|
|
282
|
+
const visited: J | undefined = updates.expression;
|
|
283
|
+
if (visited && visited !== expressionStatement.expression && isStatement(visited) &&
|
|
284
|
+
this.cursor.parentTree()?.value.kind !== J.Kind.ForLoopControl) {
|
|
285
|
+
return {
|
|
286
|
+
...visited,
|
|
287
|
+
prefix: concatenated(updates.prefix, visited.prefix),
|
|
288
|
+
markers: withOuterMarkers(updates.markers, visited.markers)
|
|
289
|
+
};
|
|
290
|
+
}
|
|
279
291
|
return updateIfChanged(expressionStatement, updates);
|
|
280
292
|
}
|
|
281
293
|
|
|
@@ -1293,3 +1305,21 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
1293
1305
|
return super.accept(j, p);
|
|
1294
1306
|
}
|
|
1295
1307
|
}
|
|
1308
|
+
|
|
1309
|
+
/** The prefix that prints as `outer` and then `inner`. */
|
|
1310
|
+
function concatenated(outer: J.Space, inner: J.Space): J.Space {
|
|
1311
|
+
if (outer.comments.length === 0) {
|
|
1312
|
+
return {...inner, whitespace: outer.whitespace + inner.whitespace};
|
|
1313
|
+
}
|
|
1314
|
+
const last = outer.comments[outer.comments.length - 1];
|
|
1315
|
+
return {
|
|
1316
|
+
...outer,
|
|
1317
|
+
comments: [...outer.comments.slice(0, -1), {...last, suffix: last.suffix + inner.whitespace}, ...inner.comments]
|
|
1318
|
+
};
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
/** `inner`, led by each marker of `outer` it does not already hold, so they print as they did around it. */
|
|
1322
|
+
function withOuterMarkers(outer: Markers, inner: Markers): Markers {
|
|
1323
|
+
const added = outer.markers.filter(marker => !inner.markers.some(own => own.id === marker.id));
|
|
1324
|
+
return added.length === 0 ? inner : {...inner, markers: [...added, ...inner.markers]};
|
|
1325
|
+
}
|
package/src/recipe.ts
CHANGED
|
@@ -175,6 +175,11 @@ export interface OptionDescriptor {
|
|
|
175
175
|
readonly type?: string
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
+
/**
|
|
179
|
+
* @typeParam P The type of the accumulator where scanning data is held until the editing phase. It stays in memory
|
|
180
|
+
* until the cycle ends, so it should hold values such as coordinates, paths and ids, not trees or other objects of a
|
|
181
|
+
* type given to registerHeavyweight.
|
|
182
|
+
*/
|
|
178
183
|
export abstract class ScanningRecipe<P> extends Recipe {
|
|
179
184
|
private readonly recipeAccMessage = Symbol("org.openrewrite.recipe.acc");
|
|
180
185
|
|
package/src/run.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import {ExecutionContext} from "./execution";
|
|
17
|
-
import {rootCursor, SourceFile} from "./tree";
|
|
17
|
+
import {Cursor, rootCursor, SourceFile} from "./tree";
|
|
18
18
|
import {createTwoFilesPatch} from "diff";
|
|
19
19
|
import {TreePrinters} from "./print";
|
|
20
20
|
import {Recipe, ScanningRecipe} from "./recipe";
|
|
@@ -83,6 +83,25 @@ async function recursiveOnComplete(recipe: Recipe, ctx: ExecutionContext, recipe
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Under this key a test harness puts an {@link AccumulatorListener} on the execution context, which the scheduler
|
|
88
|
+
* calls with the accumulator of each scanning recipe after the scanning phase and again after the editing phase.
|
|
89
|
+
*/
|
|
90
|
+
export const ACCUMULATOR_LISTENER = "org.openrewrite.test.accumulatorListener";
|
|
91
|
+
|
|
92
|
+
export type AccumulatorListener =
|
|
93
|
+
(accumulators: Map<ScanningRecipe<any>, any>, phase: "after scanning" | "after editing") => void;
|
|
94
|
+
|
|
95
|
+
async function accumulators(recipe: Recipe, recipeLists: RecipeLists, cursor: Cursor,
|
|
96
|
+
ctx: ExecutionContext): Promise<Map<ScanningRecipe<any>, any>> {
|
|
97
|
+
return (await recurseRecipeList(recipe, new Map<ScanningRecipe<any>, any>(), recipeLists, async (r, found) => {
|
|
98
|
+
if (r instanceof ScanningRecipe && !found.has(r)) {
|
|
99
|
+
found.set(r, r.accumulator(cursor, ctx));
|
|
100
|
+
}
|
|
101
|
+
return found;
|
|
102
|
+
}))!;
|
|
103
|
+
}
|
|
104
|
+
|
|
86
105
|
export async function scheduleRun(recipe: Recipe, before: SourceFile[], ctx: ExecutionContext): Promise<RecipeRun> {
|
|
87
106
|
const changeset: Result[] = [];
|
|
88
107
|
for await (const result of scheduleRunStreaming(recipe, before, ctx)) {
|
|
@@ -135,13 +154,21 @@ export async function* scheduleRunStreaming(
|
|
|
135
154
|
// of the recipe list, leaving nested scanners unrun.
|
|
136
155
|
await recurseRecipeList(recipe, b, recipeLists, async (recipe, b2) => {
|
|
137
156
|
if (recipe instanceof ScanningRecipe) {
|
|
138
|
-
await (await recipe.scanner(recipe.accumulator(cursor, ctx))).visit(b2, ctx, cursor);
|
|
157
|
+
const scanned = await (await recipe.scanner(recipe.accumulator(cursor, ctx))).visit(b2, ctx, cursor);
|
|
158
|
+
if (scanned !== b2 && ctx.getBoolean(ExecutionContext.SCANNING_MUTATION_VALIDATION, false)) {
|
|
159
|
+
throw new Error("Record what the scanner finds in the accumulator, and make the edits in " +
|
|
160
|
+
`editorWithData(acc). ${recipe.name}'s scanner ${scanned ? "changed" : "deleted"} ` +
|
|
161
|
+
`${b2.sourcePath}, and the scanning phase discards edits. A scanner that reuses an ` +
|
|
162
|
+
"editing visitor opts out with spec.checkNoEditsInScanningPhase = false.");
|
|
163
|
+
}
|
|
139
164
|
}
|
|
140
165
|
return b2;
|
|
141
166
|
});
|
|
142
167
|
}
|
|
143
168
|
|
|
144
169
|
const totalFiles = files.length;
|
|
170
|
+
const listener: AccumulatorListener | undefined = ctx.messages[ACCUMULATOR_LISTENER];
|
|
171
|
+
listener?.(await accumulators(recipe, recipeLists, cursor, ctx), "after scanning");
|
|
145
172
|
|
|
146
173
|
// Phase 2: Collect generated files
|
|
147
174
|
const generated = (await recurseRecipeList(recipe, [] as SourceFile[], recipeLists, async (recipe, generated) => {
|
|
@@ -169,6 +196,7 @@ export async function* scheduleRunStreaming(
|
|
|
169
196
|
yield new Result(undefined, editedG);
|
|
170
197
|
}
|
|
171
198
|
}
|
|
199
|
+
listener?.(await accumulators(recipe, recipeLists, cursor, ctx), "after editing");
|
|
172
200
|
} else {
|
|
173
201
|
// For non-scanning recipes, process files immediately as they come in
|
|
174
202
|
let processCount = 0;
|