@openrewrite/rewrite 8.96.3 → 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/tree.d.ts +11 -11
- package/dist/java/tree.d.ts.map +1 -1
- package/dist/java/visitor.d.ts.map +1 -1
- package/dist/java/visitor.js +46 -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 +12 -0
- package/dist/javascript/format/format.d.ts.map +1 -1
- package/dist/javascript/format/format.js +17 -3
- 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 +16 -5
- 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/templating/precedence.js +1 -1
- package/dist/javascript/templating/precedence.js.map +1 -1
- package/dist/javascript/tree.d.ts +12 -12
- package/dist/javascript/tree.d.ts.map +1 -1
- package/dist/javascript/visitor.d.ts.map +1 -1
- package/dist/javascript/visitor.js +96 -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/node_modules/picomatch/LICENSE +21 -0
- package/node_modules/picomatch/README.md +743 -0
- package/node_modules/picomatch/index.js +17 -0
- package/node_modules/picomatch/lib/constants.js +184 -0
- package/node_modules/picomatch/lib/parse.js +1506 -0
- package/node_modules/picomatch/lib/picomatch.js +361 -0
- package/node_modules/picomatch/lib/scan.js +403 -0
- package/node_modules/picomatch/lib/utils.js +72 -0
- package/node_modules/picomatch/package.json +83 -0
- package/node_modules/picomatch/posix.js +3 -0
- package/package.json +88 -90
- package/src/execution.ts +6 -0
- package/src/heavyweight.ts +42 -0
- package/src/index.ts +1 -0
- package/src/java/tree.ts +11 -11
- package/src/java/visitor.ts +52 -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 +25 -1
- 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 +19 -7
- 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/templating/precedence.ts +1 -1
- package/src/javascript/tree.ts +12 -12
- package/src/javascript/visitor.ts +120 -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
|
@@ -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,
|
|
@@ -55,7 +56,6 @@ const is_statements: string[] = [
|
|
|
55
56
|
JS.Kind.ArrowFunction,
|
|
56
57
|
JS.Kind.BindingElement,
|
|
57
58
|
JS.Kind.Delete,
|
|
58
|
-
JS.Kind.Export,
|
|
59
59
|
JS.Kind.ExportAssignment,
|
|
60
60
|
JS.Kind.ExportDeclaration,
|
|
61
61
|
JS.Kind.ForInLoop,
|
|
@@ -70,6 +70,8 @@ const is_statements: string[] = [
|
|
|
70
70
|
JS.Kind.NamespaceDeclaration,
|
|
71
71
|
JS.Kind.PropertyAssignment,
|
|
72
72
|
JS.Kind.ScopedVariableDeclarations,
|
|
73
|
+
JS.Kind.Shebang,
|
|
74
|
+
JS.Kind.Spread,
|
|
73
75
|
JS.Kind.TaggedTemplateExpression,
|
|
74
76
|
JS.Kind.TemplateExpression,
|
|
75
77
|
JS.Kind.TypeDeclaration,
|
|
@@ -77,9 +79,9 @@ const is_statements: string[] = [
|
|
|
77
79
|
JS.Kind.WithStatement,
|
|
78
80
|
JS.Kind.ExpressionStatement,
|
|
79
81
|
JS.Kind.StatementExpression
|
|
80
|
-
]
|
|
82
|
+
];
|
|
81
83
|
|
|
82
|
-
const
|
|
84
|
+
const expressionKinds = (): string[] => [
|
|
83
85
|
J.Kind.AnnotatedType,
|
|
84
86
|
J.Kind.Annotation,
|
|
85
87
|
J.Kind.ArrayAccess,
|
|
@@ -88,6 +90,7 @@ const is_expressions: string[] = [
|
|
|
88
90
|
J.Kind.AssignmentOperation,
|
|
89
91
|
J.Kind.Binary,
|
|
90
92
|
J.Kind.ControlParentheses,
|
|
93
|
+
J.Kind.DeconstructionPattern,
|
|
91
94
|
J.Kind.Empty,
|
|
92
95
|
J.Kind.Erroneous,
|
|
93
96
|
J.Kind.FieldAccess,
|
|
@@ -114,18 +117,23 @@ const is_expressions: string[] = [
|
|
|
114
117
|
JS.Kind.Alias,
|
|
115
118
|
JS.Kind.ArrayBindingPattern,
|
|
116
119
|
JS.Kind.ArrowFunction,
|
|
120
|
+
JS.Kind.As,
|
|
117
121
|
JS.Kind.Await,
|
|
118
122
|
JS.Kind.BindingElement,
|
|
123
|
+
JS.Kind.ComputedPropertyName,
|
|
119
124
|
JS.Kind.ConditionalType,
|
|
120
125
|
JS.Kind.Delete,
|
|
121
126
|
JS.Kind.ExportSpecifier,
|
|
122
127
|
JS.Kind.ExpressionWithTypeArguments,
|
|
128
|
+
JS.Kind.FunctionCall,
|
|
123
129
|
JS.Kind.FunctionType,
|
|
124
130
|
JS.Kind.ImportType,
|
|
125
131
|
JS.Kind.IndexedAccessType,
|
|
126
132
|
JS.Kind.IndexedAccessTypeIndexType,
|
|
127
133
|
JS.Kind.InferType,
|
|
128
134
|
JS.Kind.Intersection,
|
|
135
|
+
JS.Kind.JsxEmbeddedExpression,
|
|
136
|
+
JS.Kind.JsxTag,
|
|
129
137
|
JS.Kind.AssignmentOperation,
|
|
130
138
|
JS.Kind.Binary,
|
|
131
139
|
JS.Kind.ImportSpecifier,
|
|
@@ -135,6 +143,7 @@ const is_expressions: string[] = [
|
|
|
135
143
|
JS.Kind.NamedImports,
|
|
136
144
|
JS.Kind.ObjectBindingPattern,
|
|
137
145
|
JS.Kind.SatisfiesExpression,
|
|
146
|
+
JS.Kind.Spread,
|
|
138
147
|
JS.Kind.TaggedTemplateExpression,
|
|
139
148
|
JS.Kind.TemplateExpression,
|
|
140
149
|
JS.Kind.Tuple,
|
|
@@ -149,14 +158,17 @@ const is_expressions: string[] = [
|
|
|
149
158
|
JS.Kind.Void,
|
|
150
159
|
JS.Kind.ExpressionStatement,
|
|
151
160
|
JS.Kind.StatementExpression
|
|
152
|
-
]
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
let is_statements: Set<string> | undefined;
|
|
164
|
+
let is_expressions: Set<string> | undefined;
|
|
153
165
|
|
|
154
166
|
export function isStatement(statement: J): statement is Statement {
|
|
155
|
-
return is_statements.
|
|
167
|
+
return (is_statements ??= new Set(statementKinds())).has(statement.kind);
|
|
156
168
|
}
|
|
157
169
|
|
|
158
170
|
export function isExpression(expression: J): expression is Expression {
|
|
159
|
-
return is_expressions.
|
|
171
|
+
return (is_expressions ??= new Set(expressionKinds())).has(expression.kind);
|
|
160
172
|
}
|
|
161
173
|
|
|
162
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);
|
|
@@ -305,7 +305,7 @@ function slotConstraints(parent: J, childId: string): SlotConstraints | undefine
|
|
|
305
305
|
case J.Kind.ClassDeclaration:
|
|
306
306
|
// `class A extends B {}` takes a LeftHandSideExpression
|
|
307
307
|
return (parent as J.ClassDeclaration).extends?.element?.id === childId ?
|
|
308
|
-
{precedence: Precedence.Call} : undefined;
|
|
308
|
+
{precedence: Precedence.Call, typeTree: true} : undefined;
|
|
309
309
|
|
|
310
310
|
case JS.Kind.ExpressionStatement:
|
|
311
311
|
return (parent as JS.ExpressionStatement).expression?.id === childId ?
|
package/src/javascript/tree.ts
CHANGED
|
@@ -602,7 +602,7 @@ export namespace JS {
|
|
|
602
602
|
* Represents the index type in an indexed access.
|
|
603
603
|
* @example 'key'
|
|
604
604
|
*/
|
|
605
|
-
export interface IndexType extends JS {
|
|
605
|
+
export interface IndexType extends JS, Expression, TypeTree {
|
|
606
606
|
readonly kind: typeof Kind.IndexedAccessTypeIndexType;
|
|
607
607
|
readonly element: J.RightPadded<TypeTree>;
|
|
608
608
|
readonly type?: Type;
|
|
@@ -633,7 +633,7 @@ export namespace JS {
|
|
|
633
633
|
* Represents TypeScript computed property name.
|
|
634
634
|
* @example { [key]: value }
|
|
635
635
|
*/
|
|
636
|
-
export interface ComputedPropertyName extends JS, Expression,
|
|
636
|
+
export interface ComputedPropertyName extends JS, Expression, TypeTree, VariableDeclarator {
|
|
637
637
|
readonly kind: typeof Kind.ComputedPropertyName;
|
|
638
638
|
readonly expression: J.RightPadded<Expression>;
|
|
639
639
|
}
|
|
@@ -695,7 +695,7 @@ export namespace JS {
|
|
|
695
695
|
* @example data["key"](5, 0, 4)
|
|
696
696
|
* @example (() => { return 3 + 5 })()
|
|
697
697
|
*/
|
|
698
|
-
export interface FunctionCall extends JS, MethodCall {
|
|
698
|
+
export interface FunctionCall extends JS, TypedTree, MethodCall {
|
|
699
699
|
readonly kind: typeof Kind.FunctionCall;
|
|
700
700
|
readonly function?: J.RightPadded<Expression>;
|
|
701
701
|
readonly typeParameters?: J.Container<Expression>;
|
|
@@ -706,7 +706,7 @@ export namespace JS {
|
|
|
706
706
|
* Represents the `void` operator.
|
|
707
707
|
* @example void 0;
|
|
708
708
|
*/
|
|
709
|
-
export interface Void extends JS, Expression {
|
|
709
|
+
export interface Void extends JS, Expression, Statement {
|
|
710
710
|
readonly kind: typeof Kind.Void;
|
|
711
711
|
readonly expression: Expression;
|
|
712
712
|
}
|
|
@@ -737,7 +737,7 @@ export namespace JS {
|
|
|
737
737
|
* Represents a method declaration in classes or objects.
|
|
738
738
|
* @example class A { [Symbol.asyncIterator]() { ... } }
|
|
739
739
|
*/
|
|
740
|
-
export interface ComputedPropertyMethodDeclaration extends JS, Statement {
|
|
740
|
+
export interface ComputedPropertyMethodDeclaration extends JS, Statement, TypedTree {
|
|
741
741
|
readonly kind: typeof Kind.ComputedPropertyMethodDeclaration;
|
|
742
742
|
readonly leadingAnnotations: J.Annotation[];
|
|
743
743
|
readonly modifiers: J.Modifier[];
|
|
@@ -754,7 +754,7 @@ export namespace JS {
|
|
|
754
754
|
* @example for (const x of arr) { }
|
|
755
755
|
* @example for await (const x of arr) { }
|
|
756
756
|
*/
|
|
757
|
-
export interface ForOfLoop extends JS {
|
|
757
|
+
export interface ForOfLoop extends JS, Statement {
|
|
758
758
|
readonly kind: typeof Kind.ForOfLoop;
|
|
759
759
|
readonly await?: J.Space;
|
|
760
760
|
readonly loop: J.ForEachLoop;
|
|
@@ -768,7 +768,7 @@ export namespace JS {
|
|
|
768
768
|
* Represents a for-in loop.
|
|
769
769
|
* @example for (let key in obj) { }
|
|
770
770
|
*/
|
|
771
|
-
export interface ForInLoop extends JS {
|
|
771
|
+
export interface ForInLoop extends JS, Statement {
|
|
772
772
|
readonly kind: typeof Kind.ForInLoop;
|
|
773
773
|
readonly control: ForInLoop.Control;
|
|
774
774
|
readonly body: J.RightPadded<Statement>;
|
|
@@ -802,7 +802,7 @@ export namespace JS {
|
|
|
802
802
|
* Represents a literal type object in TypeScript.
|
|
803
803
|
* @example type T = { a: number };
|
|
804
804
|
*/
|
|
805
|
-
export interface TypeLiteral extends JS, TypeTree {
|
|
805
|
+
export interface TypeLiteral extends JS, Expression, TypeTree {
|
|
806
806
|
readonly kind: typeof Kind.TypeLiteral;
|
|
807
807
|
readonly members: J.Block;
|
|
808
808
|
readonly type?: Type;
|
|
@@ -812,7 +812,7 @@ export namespace JS {
|
|
|
812
812
|
* Represents an array destructuring pattern.
|
|
813
813
|
* @example const [a, b] = arr;
|
|
814
814
|
*/
|
|
815
|
-
export interface ArrayBindingPattern extends JS, TypedTree, VariableDeclarator {
|
|
815
|
+
export interface ArrayBindingPattern extends JS, Expression, TypedTree, VariableDeclarator {
|
|
816
816
|
readonly kind: typeof Kind.ArrayBindingPattern;
|
|
817
817
|
readonly elements: J.Container<Expression>;
|
|
818
818
|
readonly type?: Type;
|
|
@@ -822,7 +822,7 @@ export namespace JS {
|
|
|
822
822
|
* Represents a named element in a binding pattern.
|
|
823
823
|
* @example const { x: alias } = obj;
|
|
824
824
|
*/
|
|
825
|
-
export interface BindingElement extends JS, Statement, TypeTree {
|
|
825
|
+
export interface BindingElement extends JS, Statement, Expression, TypeTree {
|
|
826
826
|
readonly kind: typeof Kind.BindingElement;
|
|
827
827
|
readonly propertyName?: J.RightPadded<Expression>;
|
|
828
828
|
readonly name: TypedTree;
|
|
@@ -858,7 +858,7 @@ export namespace JS {
|
|
|
858
858
|
* Represents named exports in an export declaration.
|
|
859
859
|
* @example export { a, b };
|
|
860
860
|
*/
|
|
861
|
-
export interface NamedExports extends JS {
|
|
861
|
+
export interface NamedExports extends JS, Expression {
|
|
862
862
|
readonly kind: typeof Kind.NamedExports;
|
|
863
863
|
readonly elements: J.Container<Expression>;
|
|
864
864
|
readonly type?: Type;
|
|
@@ -868,7 +868,7 @@ export namespace JS {
|
|
|
868
868
|
* Represents a specifier in a named export.
|
|
869
869
|
* @example export { foo as bar };
|
|
870
870
|
*/
|
|
871
|
-
export interface ExportSpecifier extends JS {
|
|
871
|
+
export interface ExportSpecifier extends JS, Expression, TypedTree {
|
|
872
872
|
readonly kind: typeof Kind.ExportSpecifier;
|
|
873
873
|
readonly typeOnly: J.LeftPadded<boolean>;
|
|
874
874
|
readonly specifier: Expression;
|
|
@@ -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
|
|
|
@@ -111,6 +113,12 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
111
113
|
}
|
|
112
114
|
|
|
113
115
|
protected async visitAs(as_: JS.As, p: P): Promise<J | undefined> {
|
|
116
|
+
const expression = await this.visitExpression(as_, p);
|
|
117
|
+
if (!expression?.kind || expression.kind !== JS.Kind.As) {
|
|
118
|
+
return expression;
|
|
119
|
+
}
|
|
120
|
+
as_ = expression as JS.As;
|
|
121
|
+
|
|
114
122
|
const updates: any = {
|
|
115
123
|
prefix: await this.visitSpace(as_.prefix, p),
|
|
116
124
|
markers: await this.visitMarkers(as_.markers, p),
|
|
@@ -138,6 +146,12 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
138
146
|
}
|
|
139
147
|
|
|
140
148
|
protected async visitJsxTag(element: JSX.Tag, p: P): Promise<J | undefined> {
|
|
149
|
+
const expression = await this.visitExpression(element, p);
|
|
150
|
+
if (!expression?.kind || expression.kind !== JS.Kind.JsxTag) {
|
|
151
|
+
return expression;
|
|
152
|
+
}
|
|
153
|
+
element = expression as JSX.Tag;
|
|
154
|
+
|
|
141
155
|
const updates: any = {
|
|
142
156
|
prefix: await this.visitSpace(element.prefix, p),
|
|
143
157
|
markers: await this.visitMarkers(element.markers, p),
|
|
@@ -174,6 +188,12 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
174
188
|
}
|
|
175
189
|
|
|
176
190
|
protected async visitJsxEmbeddedExpression(expr: JSX.EmbeddedExpression, p: P): Promise<J | undefined> {
|
|
191
|
+
const expression = await this.visitExpression(expr, p);
|
|
192
|
+
if (!expression?.kind || expression.kind !== JS.Kind.JsxEmbeddedExpression) {
|
|
193
|
+
return expression;
|
|
194
|
+
}
|
|
195
|
+
expr = expression as JSX.EmbeddedExpression;
|
|
196
|
+
|
|
177
197
|
const updates: any = {
|
|
178
198
|
prefix: await this.visitSpace(expr.prefix, p),
|
|
179
199
|
markers: await this.visitMarkers(expr.markers, p),
|
|
@@ -258,6 +278,16 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
258
278
|
markers: await this.visitMarkers(expressionStatement.markers, p),
|
|
259
279
|
expression: await this.visitDefined<Expression>(expressionStatement.expression, p)
|
|
260
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
|
+
}
|
|
261
291
|
return updateIfChanged(expressionStatement, updates);
|
|
262
292
|
}
|
|
263
293
|
|
|
@@ -455,6 +485,12 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
455
485
|
}
|
|
456
486
|
|
|
457
487
|
protected async visitBinaryExtensions(jsBinary: JS.Binary, p: P): Promise<J | undefined> {
|
|
488
|
+
const expression = await this.visitExpression(jsBinary, p);
|
|
489
|
+
if (!expression?.kind || expression.kind !== JS.Kind.Binary) {
|
|
490
|
+
return expression;
|
|
491
|
+
}
|
|
492
|
+
jsBinary = expression as JS.Binary;
|
|
493
|
+
|
|
458
494
|
const updates: any = {
|
|
459
495
|
prefix: await this.visitSpace(jsBinary.prefix, p),
|
|
460
496
|
markers: await this.visitMarkers(jsBinary.markers, p),
|
|
@@ -504,6 +540,12 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
504
540
|
}
|
|
505
541
|
|
|
506
542
|
protected async visitMappedTypeKeysRemapping(keysRemapping: JS.MappedType.KeysRemapping, p: P): Promise<J | undefined> {
|
|
543
|
+
const statement = await this.visitStatement(keysRemapping, p);
|
|
544
|
+
if (!statement?.kind || statement.kind !== JS.Kind.MappedTypeKeysRemapping) {
|
|
545
|
+
return statement;
|
|
546
|
+
}
|
|
547
|
+
keysRemapping = statement as JS.MappedType.KeysRemapping;
|
|
548
|
+
|
|
507
549
|
const updates: any = {
|
|
508
550
|
prefix: await this.visitSpace(keysRemapping.prefix, p),
|
|
509
551
|
markers: await this.visitMarkers(keysRemapping.markers, p),
|
|
@@ -514,6 +556,12 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
514
556
|
}
|
|
515
557
|
|
|
516
558
|
protected async visitMappedTypeParameter(mappedTypeParameter: JS.MappedType.Parameter, p: P): Promise<J | undefined> {
|
|
559
|
+
const statement = await this.visitStatement(mappedTypeParameter, p);
|
|
560
|
+
if (!statement?.kind || statement.kind !== JS.Kind.MappedTypeParameter) {
|
|
561
|
+
return statement;
|
|
562
|
+
}
|
|
563
|
+
mappedTypeParameter = statement as JS.MappedType.Parameter;
|
|
564
|
+
|
|
517
565
|
const updates: any = {
|
|
518
566
|
prefix: await this.visitSpace(mappedTypeParameter.prefix, p),
|
|
519
567
|
markers: await this.visitMarkers(mappedTypeParameter.markers, p),
|
|
@@ -767,6 +815,18 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
767
815
|
}
|
|
768
816
|
|
|
769
817
|
protected async visitAssignmentOperationExtensions(assignmentOperation: JS.AssignmentOperation, p: P): Promise<J | undefined> {
|
|
818
|
+
const expression = await this.visitExpression(assignmentOperation, p);
|
|
819
|
+
if (!expression?.kind || expression.kind !== JS.Kind.AssignmentOperation) {
|
|
820
|
+
return expression;
|
|
821
|
+
}
|
|
822
|
+
assignmentOperation = expression as JS.AssignmentOperation;
|
|
823
|
+
|
|
824
|
+
const statement = await this.visitStatement(assignmentOperation, p);
|
|
825
|
+
if (!statement?.kind || statement.kind !== JS.Kind.AssignmentOperation) {
|
|
826
|
+
return statement;
|
|
827
|
+
}
|
|
828
|
+
assignmentOperation = statement as JS.AssignmentOperation;
|
|
829
|
+
|
|
770
830
|
const updates: any = {
|
|
771
831
|
prefix: await this.visitSpace(assignmentOperation.prefix, p),
|
|
772
832
|
markers: await this.visitMarkers(assignmentOperation.markers, p),
|
|
@@ -796,6 +856,12 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
796
856
|
}
|
|
797
857
|
|
|
798
858
|
protected async visitIndexedAccessTypeIndexType(indexType: JS.IndexedAccessType.IndexType, p: P): Promise<J | undefined> {
|
|
859
|
+
const expression = await this.visitExpression(indexType, p);
|
|
860
|
+
if (!expression?.kind || expression.kind !== JS.Kind.IndexedAccessTypeIndexType) {
|
|
861
|
+
return expression;
|
|
862
|
+
}
|
|
863
|
+
indexType = expression as JS.IndexedAccessType.IndexType;
|
|
864
|
+
|
|
799
865
|
const updates: any = {
|
|
800
866
|
prefix: await this.visitSpace(indexType.prefix, p),
|
|
801
867
|
markers: await this.visitMarkers(indexType.markers, p),
|
|
@@ -989,6 +1055,12 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
989
1055
|
}
|
|
990
1056
|
|
|
991
1057
|
protected async visitForOfLoop(forOfLoop: JS.ForOfLoop, p: P): Promise<J | undefined> {
|
|
1058
|
+
const statement = await this.visitStatement(forOfLoop, p);
|
|
1059
|
+
if (!statement?.kind || statement.kind !== JS.Kind.ForOfLoop) {
|
|
1060
|
+
return statement;
|
|
1061
|
+
}
|
|
1062
|
+
forOfLoop = statement as JS.ForOfLoop;
|
|
1063
|
+
|
|
992
1064
|
const updates: any = {
|
|
993
1065
|
prefix: await this.visitSpace(forOfLoop.prefix, p),
|
|
994
1066
|
markers: await this.visitMarkers(forOfLoop.markers, p),
|
|
@@ -999,6 +1071,12 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
999
1071
|
}
|
|
1000
1072
|
|
|
1001
1073
|
protected async visitForInLoop(forInLoop: JS.ForInLoop, p: P): Promise<J | undefined> {
|
|
1074
|
+
const statement = await this.visitStatement(forInLoop, p);
|
|
1075
|
+
if (!statement?.kind || statement.kind !== JS.Kind.ForInLoop) {
|
|
1076
|
+
return statement;
|
|
1077
|
+
}
|
|
1078
|
+
forInLoop = statement as JS.ForInLoop;
|
|
1079
|
+
|
|
1002
1080
|
const updates: any = {
|
|
1003
1081
|
prefix: await this.visitSpace(forInLoop.prefix, p),
|
|
1004
1082
|
markers: await this.visitMarkers(forInLoop.markers, p),
|
|
@@ -1027,6 +1105,12 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
1027
1105
|
}
|
|
1028
1106
|
|
|
1029
1107
|
protected async visitTypeLiteral(typeLiteral: JS.TypeLiteral, p: P): Promise<J | undefined> {
|
|
1108
|
+
const expression = await this.visitExpression(typeLiteral, p);
|
|
1109
|
+
if (!expression?.kind || expression.kind !== JS.Kind.TypeLiteral) {
|
|
1110
|
+
return expression;
|
|
1111
|
+
}
|
|
1112
|
+
typeLiteral = expression as JS.TypeLiteral;
|
|
1113
|
+
|
|
1030
1114
|
const updates: any = {
|
|
1031
1115
|
prefix: await this.visitSpace(typeLiteral.prefix, p),
|
|
1032
1116
|
markers: await this.visitMarkers(typeLiteral.markers, p),
|
|
@@ -1037,6 +1121,12 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
1037
1121
|
}
|
|
1038
1122
|
|
|
1039
1123
|
protected async visitArrayBindingPattern(arrayBindingPattern: JS.ArrayBindingPattern, p: P): Promise<J | undefined> {
|
|
1124
|
+
const expression = await this.visitExpression(arrayBindingPattern, p);
|
|
1125
|
+
if (!expression?.kind || expression.kind !== JS.Kind.ArrayBindingPattern) {
|
|
1126
|
+
return expression;
|
|
1127
|
+
}
|
|
1128
|
+
arrayBindingPattern = expression as JS.ArrayBindingPattern;
|
|
1129
|
+
|
|
1040
1130
|
const updates: any = {
|
|
1041
1131
|
prefix: await this.visitSpace(arrayBindingPattern.prefix, p),
|
|
1042
1132
|
markers: await this.visitMarkers(arrayBindingPattern.markers, p),
|
|
@@ -1099,6 +1189,12 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
1099
1189
|
}
|
|
1100
1190
|
|
|
1101
1191
|
protected async visitNamedExports(namedExports: JS.NamedExports, p: P): Promise<J | undefined> {
|
|
1192
|
+
const expression = await this.visitExpression(namedExports, p);
|
|
1193
|
+
if (!expression?.kind || expression.kind !== JS.Kind.NamedExports) {
|
|
1194
|
+
return expression;
|
|
1195
|
+
}
|
|
1196
|
+
namedExports = expression as JS.NamedExports;
|
|
1197
|
+
|
|
1102
1198
|
const updates: any = {
|
|
1103
1199
|
prefix: await this.visitSpace(namedExports.prefix, p),
|
|
1104
1200
|
markers: await this.visitMarkers(namedExports.markers, p),
|
|
@@ -1109,6 +1205,12 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
1109
1205
|
}
|
|
1110
1206
|
|
|
1111
1207
|
protected async visitExportSpecifier(exportSpecifier: JS.ExportSpecifier, p: P): Promise<J | undefined> {
|
|
1208
|
+
const expression = await this.visitExpression(exportSpecifier, p);
|
|
1209
|
+
if (!expression?.kind || expression.kind !== JS.Kind.ExportSpecifier) {
|
|
1210
|
+
return expression;
|
|
1211
|
+
}
|
|
1212
|
+
exportSpecifier = expression as JS.ExportSpecifier;
|
|
1213
|
+
|
|
1112
1214
|
const updates: any = {
|
|
1113
1215
|
prefix: await this.visitSpace(exportSpecifier.prefix, p),
|
|
1114
1216
|
markers: await this.visitMarkers(exportSpecifier.markers, p),
|
|
@@ -1203,3 +1305,21 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
|
|
|
1203
1305
|
return super.accept(j, p);
|
|
1204
1306
|
}
|
|
1205
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;
|