@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.
Files changed (123) hide show
  1. package/dist/execution.d.ts +2 -0
  2. package/dist/execution.d.ts.map +1 -1
  3. package/dist/execution.js +4 -0
  4. package/dist/execution.js.map +1 -1
  5. package/dist/heavyweight.d.ts +8 -0
  6. package/dist/heavyweight.d.ts.map +1 -0
  7. package/dist/heavyweight.js +45 -0
  8. package/dist/heavyweight.js.map +1 -0
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +3 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/java/visitor.d.ts.map +1 -1
  14. package/dist/java/visitor.js +16 -2
  15. package/dist/java/visitor.js.map +1 -1
  16. package/dist/javascript/add-import.d.ts +2 -1
  17. package/dist/javascript/add-import.d.ts.map +1 -1
  18. package/dist/javascript/add-import.js +14 -2
  19. package/dist/javascript/add-import.js.map +1 -1
  20. package/dist/javascript/amd.d.ts.map +1 -1
  21. package/dist/javascript/amd.js +2 -1
  22. package/dist/javascript/amd.js.map +1 -1
  23. package/dist/javascript/cleanup/add-parse-int-radix.js +1 -1
  24. package/dist/javascript/cleanup/add-parse-int-radix.js.map +1 -1
  25. package/dist/javascript/format/format.d.ts +10 -0
  26. package/dist/javascript/format/format.d.ts.map +1 -1
  27. package/dist/javascript/format/format.js +10 -2
  28. package/dist/javascript/format/format.js.map +1 -1
  29. package/dist/javascript/format/tabs-and-indents-visitor.d.ts.map +1 -1
  30. package/dist/javascript/format/tabs-and-indents-visitor.js +4 -0
  31. package/dist/javascript/format/tabs-and-indents-visitor.js.map +1 -1
  32. package/dist/javascript/format/whitespace-reconciler.d.ts.map +1 -1
  33. package/dist/javascript/format/whitespace-reconciler.js +4 -0
  34. package/dist/javascript/format/whitespace-reconciler.js.map +1 -1
  35. package/dist/javascript/node-resolution-result.d.ts.map +1 -1
  36. package/dist/javascript/node-resolution-result.js +2 -0
  37. package/dist/javascript/node-resolution-result.js.map +1 -1
  38. package/dist/javascript/parser-utils.d.ts.map +1 -1
  39. package/dist/javascript/parser-utils.js +9 -6
  40. package/dist/javascript/parser-utils.js.map +1 -1
  41. package/dist/javascript/templating/engine.d.ts.map +1 -1
  42. package/dist/javascript/templating/engine.js +11 -6
  43. package/dist/javascript/templating/engine.js.map +1 -1
  44. package/dist/javascript/templating/pattern.d.ts.map +1 -1
  45. package/dist/javascript/templating/pattern.js +8 -0
  46. package/dist/javascript/templating/pattern.js.map +1 -1
  47. package/dist/javascript/templating/placeholder-replacement.d.ts.map +1 -1
  48. package/dist/javascript/templating/placeholder-replacement.js +15 -0
  49. package/dist/javascript/templating/placeholder-replacement.js.map +1 -1
  50. package/dist/javascript/visitor.d.ts.map +1 -1
  51. package/dist/javascript/visitor.js +21 -0
  52. package/dist/javascript/visitor.js.map +1 -1
  53. package/dist/recipe.d.ts +5 -0
  54. package/dist/recipe.d.ts.map +1 -1
  55. package/dist/recipe.js +5 -0
  56. package/dist/recipe.js.map +1 -1
  57. package/dist/rewrite-javascript-version.txt +1 -1
  58. package/dist/run.d.ts +7 -1
  59. package/dist/run.d.ts.map +1 -1
  60. package/dist/run.js +40 -2
  61. package/dist/run.js.map +1 -1
  62. package/dist/test/accumulator-contents.d.ts +15 -0
  63. package/dist/test/accumulator-contents.d.ts.map +1 -0
  64. package/dist/test/accumulator-contents.js +185 -0
  65. package/dist/test/accumulator-contents.js.map +1 -0
  66. package/dist/test/empty-sources.d.ts +14 -0
  67. package/dist/test/empty-sources.d.ts.map +1 -0
  68. package/dist/test/empty-sources.js +98 -0
  69. package/dist/test/empty-sources.js.map +1 -0
  70. package/dist/test/formatting-scope.d.ts +18 -0
  71. package/dist/test/formatting-scope.d.ts.map +1 -0
  72. package/dist/test/formatting-scope.js +244 -0
  73. package/dist/test/formatting-scope.js.map +1 -0
  74. package/dist/test/probes.d.ts +25 -0
  75. package/dist/test/probes.d.ts.map +1 -0
  76. package/dist/test/probes.js +189 -0
  77. package/dist/test/probes.js.map +1 -0
  78. package/dist/test/rewrite-test.d.ts +27 -0
  79. package/dist/test/rewrite-test.d.ts.map +1 -1
  80. package/dist/test/rewrite-test.js +191 -21
  81. package/dist/test/rewrite-test.js.map +1 -1
  82. package/dist/test/tree-shapes.d.ts +15 -0
  83. package/dist/test/tree-shapes.d.ts.map +1 -0
  84. package/dist/test/tree-shapes.js +288 -0
  85. package/dist/test/tree-shapes.js.map +1 -0
  86. package/dist/test/unparsed-sources.d.ts +17 -0
  87. package/dist/test/unparsed-sources.d.ts.map +1 -0
  88. package/dist/test/unparsed-sources.js +113 -0
  89. package/dist/test/unparsed-sources.js.map +1 -0
  90. package/dist/tree.d.ts.map +1 -1
  91. package/dist/tree.js +2 -0
  92. package/dist/tree.js.map +1 -1
  93. package/dist/visitor.d.ts.map +1 -1
  94. package/dist/visitor.js +2 -0
  95. package/dist/visitor.js.map +1 -1
  96. package/package.json +1 -1
  97. package/src/execution.ts +6 -0
  98. package/src/heavyweight.ts +42 -0
  99. package/src/index.ts +1 -0
  100. package/src/java/visitor.ts +16 -2
  101. package/src/javascript/add-import.ts +11 -2
  102. package/src/javascript/amd.ts +4 -2
  103. package/src/javascript/cleanup/add-parse-int-radix.ts +2 -2
  104. package/src/javascript/format/format.ts +18 -0
  105. package/src/javascript/format/tabs-and-indents-visitor.ts +4 -0
  106. package/src/javascript/format/whitespace-reconciler.ts +4 -0
  107. package/src/javascript/node-resolution-result.ts +3 -0
  108. package/src/javascript/parser-utils.ts +10 -6
  109. package/src/javascript/templating/engine.ts +11 -6
  110. package/src/javascript/templating/pattern.ts +10 -0
  111. package/src/javascript/templating/placeholder-replacement.ts +16 -0
  112. package/src/javascript/visitor.ts +30 -0
  113. package/src/recipe.ts +5 -0
  114. package/src/run.ts +30 -2
  115. package/src/test/accumulator-contents.ts +194 -0
  116. package/src/test/empty-sources.ts +99 -0
  117. package/src/test/formatting-scope.ts +231 -0
  118. package/src/test/probes.ts +156 -0
  119. package/src/test/rewrite-test.ts +177 -24
  120. package/src/test/tree-shapes.ts +332 -0
  121. package/src/test/unparsed-sources.ts +138 -0
  122. package/src/tree.ts +3 -0
  123. package/src/visitor.ts +3 -0
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.probeOnce = probeOnce;
37
+ exports.charge = charge;
38
+ exports.thrownBy = thrownBy;
39
+ exports.describeThrown = describeThrown;
40
+ exports.withMarkersOf = withMarkersOf;
41
+ exports.typeName = typeName;
42
+ /*
43
+ * Copyright 2025 the original author or authors.
44
+ * <p>
45
+ * Licensed under the Moderne Source Available License (the "License");
46
+ * you may not use this file except in compliance with the License.
47
+ * You may obtain a copy of the License at
48
+ * <p>
49
+ * https://docs.moderne.io/licensing/moderne-source-available-license
50
+ * <p>
51
+ * Unless required by applicable law or agreed to in writing, software
52
+ * distributed under the License is distributed on an "AS IS" BASIS,
53
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
54
+ * See the License for the specific language governing permissions and
55
+ * limitations under the License.
56
+ */
57
+ const path = __importStar(require("path"));
58
+ const execution_1 = require("../execution");
59
+ const run_1 = require("../run");
60
+ const visitor_1 = require("../visitor");
61
+ const data_table_1 = require("../data-table");
62
+ /** Messages that belong to the test's own run. */
63
+ const NOT_COPIED = new Set([data_table_1.DATA_TABLE_STORE, run_1.ACCUMULATOR_LISTENER]);
64
+ /**
65
+ * Probes of recipes that resolve dependencies take seconds each, so a recipe stops being probed in this process once
66
+ * its probes have taken this long.
67
+ */
68
+ const TIME_CAP_MS = 20000;
69
+ /** How long each recipe's probes have taken in this process, by {@link timeCapKey}. */
70
+ const PROBE_MS = new Map();
71
+ /** The probes each recipe class ran, which a process runs once whether they pass or fail. */
72
+ const PROBED = new WeakMap();
73
+ /**
74
+ * Runs `run`, a probe of the recipe on what `probe` names, unless this process ran that probe before or the recipe's
75
+ * probes have taken the time cap, and charges the recipe the time it takes.
76
+ */
77
+ async function probeOnce(recipe, probe, run) {
78
+ var _a;
79
+ if (((_a = PROBE_MS.get(await timeCapKey(recipe))) !== null && _a !== void 0 ? _a : 0) > TIME_CAP_MS) {
80
+ return;
81
+ }
82
+ let probed = PROBED.get(recipe.constructor);
83
+ if (!probed) {
84
+ PROBED.set(recipe.constructor, probed = new Set());
85
+ }
86
+ const key = await probeKey(recipe, probe);
87
+ if (probed.has(key)) {
88
+ return;
89
+ }
90
+ probed.add(key);
91
+ const start = performance.now();
92
+ try {
93
+ await run();
94
+ }
95
+ finally {
96
+ await charge(recipe, performance.now() - start);
97
+ }
98
+ }
99
+ /** Adds `ms` to the time the recipe's probes have taken in this process. */
100
+ async function charge(recipe, ms) {
101
+ var _a;
102
+ const key = await timeCapKey(recipe);
103
+ PROBE_MS.set(key, ((_a = PROBE_MS.get(key)) !== null && _a !== void 0 ? _a : 0) + ms);
104
+ }
105
+ /**
106
+ * What a recipe's probes share a time cap by: its name, and for a recipe with a recipe list its children's keys too,
107
+ * since a composite a test declares has one name whatever it runs.
108
+ */
109
+ async function timeCapKey(recipe) {
110
+ let children;
111
+ try {
112
+ children = await recipe.recipeList();
113
+ }
114
+ catch (_a) {
115
+ return recipe.name;
116
+ }
117
+ const keys = [];
118
+ for (const child of children) {
119
+ keys.push(await timeCapKey(child));
120
+ }
121
+ return keys.length === 0 ? recipe.name : `${recipe.name}[${keys.join(",")}]`;
122
+ }
123
+ async function probeKey(recipe, probe) {
124
+ try {
125
+ return `${JSON.stringify(await recipe.descriptor())}\0${probe}`;
126
+ }
127
+ catch (_a) {
128
+ return `${recipe.name}\0${probe}`;
129
+ }
130
+ }
131
+ /** The error the recipe threw when run on `sources` for up to `cycles` cycles, if it threw. */
132
+ async function thrownBy(recipe, sources, recipeCtx, cycles) {
133
+ const messages = {};
134
+ for (const key of Reflect.ownKeys(recipeCtx.messages)) {
135
+ if (!NOT_COPIED.has(key)) {
136
+ messages[key] = recipeCtx.messages[key];
137
+ }
138
+ }
139
+ const ctx = new execution_1.ExecutionContext(messages);
140
+ let current = sources;
141
+ try {
142
+ for (let cycle = 1; cycle <= cycles; cycle++) {
143
+ const changeset = (await (0, run_1.scheduleRun)(recipe, current, ctx)).changeset;
144
+ if (changeset.every(r => r.before === r.after)) {
145
+ break;
146
+ }
147
+ current = changeset.filter(r => r.after).map(r => r.after);
148
+ }
149
+ }
150
+ catch (error) {
151
+ return { error };
152
+ }
153
+ return undefined;
154
+ }
155
+ /**
156
+ * The error the recipe threw, with the first line of its message and the first frame of its stack, and when that
157
+ * frame is in a dependency, the first frame that isn't.
158
+ */
159
+ function describeThrown(thrown, indent) {
160
+ var _a;
161
+ const cause = thrown instanceof visitor_1.RecipeRunError ? thrown.cause : thrown;
162
+ if (!(cause instanceof Error)) {
163
+ return `${indent}${String(cause)}`;
164
+ }
165
+ const firstLine = cause.message.trim().split("\n")[0];
166
+ let description = `${indent}${cause.name}${firstLine ? `: ${firstLine.length > 200 ?
167
+ `${firstLine.substring(0, 200)}...` : firstLine}` : ""}`;
168
+ const frames = ((_a = cause.stack) !== null && _a !== void 0 ? _a : "").split("\n").map(line => line.trim())
169
+ .filter(line => line.startsWith("at ") && !/\(node:|^at node:|<anonymous>/.test(line))
170
+ .map(line => line.split(process.cwd() + path.sep).join(""));
171
+ if (frames.length > 0) {
172
+ description += `\n${indent} ${frames[0]}`;
173
+ const own = frames.find(frame => !frame.includes("node_modules"));
174
+ if (own && own !== frames[0]) {
175
+ description += `\n${indent} ${own}`;
176
+ }
177
+ }
178
+ return description;
179
+ }
180
+ /** Reads as " with the markers of the test's source (Autodetect, PrettierStyle)", or as nothing. */
181
+ function withMarkersOf(markers) {
182
+ const kinds = [...new Set(markers.map(m => typeName(m.kind)))];
183
+ return kinds.length === 0 ? "" : ` with the markers of the test's source (${kinds.join(", ")})`;
184
+ }
185
+ /** Reads as "PlainText" or "JS.CompilationUnit". */
186
+ function typeName(kind) {
187
+ return kind.replace(/^.*\./, "").replace(/\$/g, ".");
188
+ }
189
+ //# sourceMappingURL=probes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probes.js","sourceRoot":"","sources":["../../src/test/probes.ts"],"names":[],"mappings":"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"}
@@ -21,6 +21,28 @@ export declare class RecipeSpec {
21
21
  * its output carry.
22
22
  */
23
23
  checkReportingMarkersOnly: boolean;
24
+ /**
25
+ * Fails a run whose recipe puts a message on the execution context, which every recipe and source file in a run
26
+ * shares.
27
+ */
28
+ checkExecutionContextUnchanged: boolean;
29
+ /** Fails a run whose ScanningRecipe's scanner edits a tree, which the scanning phase discards. */
30
+ checkNoEditsInScanningPhase: boolean;
31
+ /**
32
+ * Fails a run whose ScanningRecipe's accumulator keeps a tree, cursor, visitor, execution context, dependency model
33
+ * or other type given to registerHeavyweight, which would stay in memory all cycle.
34
+ */
35
+ checkLightweightAccumulators: boolean;
36
+ /**
37
+ * Fails a run whose output holds a node that the source's parser builds differently from the text it prints, such
38
+ * as a J.Identifier where the parser makes a J.Literal of `null`.
39
+ */
40
+ checkParserShapedTrees: boolean;
41
+ /**
42
+ * Fails a run whose recipe auto-formats a whole source file or class that existed before the run, instead of only
43
+ * what it changed.
44
+ */
45
+ checkMinimalFormatting: boolean;
24
46
  /**
25
47
  * The cycles to run, by default one more than {@link expectedCyclesThatMakeChanges} and at least two. The
26
48
  * cycles after the expected ones, and a run on a fresh parse of the output, fail the test if they change
@@ -71,6 +93,11 @@ export declare class RecipeSpec {
71
93
  /** Data tables are written by the first cycle only, as in Java. */
72
94
  private laterRunContext;
73
95
  private expectNoFurtherChanges;
96
+ /**
97
+ * A fresh parse, by the parser of its spec, of the text each source the recipe left prints, parsing the sources
98
+ * of one kind together so that they can refer to one another. A parser that throws leaves its sources out.
99
+ */
100
+ private freshParse;
74
101
  /**
75
102
  * Code that the next run reads is parsed from the printed output, not the LST this run produced, and a
76
103
  * recipe that recognizes its own output only by the shape of that LST changes it again.
@@ -1 +1 @@
1
- {"version":3,"file":"rewrite-test.d.ts","sourceRoot":"","sources":["../../src/test/rewrite-test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rewrite-test.d.ts","sourceRoot":"","sources":["../../src/test/rewrite-test.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __asyncValues = (this && this.__asyncValues) || function (o) {
3
36
  if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
4
37
  var m = o[Symbol.asyncIterator], i;
@@ -37,9 +70,18 @@ const parse_error_1 = require("../parse-error");
37
70
  const markers_1 = require("../markers");
38
71
  const style_1 = require("../style");
39
72
  const javascript_1 = require("../javascript");
73
+ const format_1 = require("../javascript/format");
40
74
  const type_report_1 = require("../javascript/type-report");
41
75
  const java_1 = require("../java");
42
76
  const data_table_1 = require("../data-table");
77
+ const path = __importStar(require("path"));
78
+ const accumulator_contents_1 = require("./accumulator-contents");
79
+ const empty_sources_1 = require("./empty-sources");
80
+ const unparsed_sources_1 = require("./unparsed-sources");
81
+ const tree_shapes_1 = require("./tree-shapes");
82
+ const formatting_scope_1 = require("./formatting-scope");
83
+ const recipe_2 = require("../rpc/recipe");
84
+ const java_recipe_1 = require("../rpc/java-recipe");
43
85
  class RecipeSpec {
44
86
  constructor() {
45
87
  var _a;
@@ -50,6 +92,28 @@ class RecipeSpec {
50
92
  * its output carry.
51
93
  */
52
94
  this.checkReportingMarkersOnly = true;
95
+ /**
96
+ * Fails a run whose recipe puts a message on the execution context, which every recipe and source file in a run
97
+ * shares.
98
+ */
99
+ this.checkExecutionContextUnchanged = true;
100
+ /** Fails a run whose ScanningRecipe's scanner edits a tree, which the scanning phase discards. */
101
+ this.checkNoEditsInScanningPhase = true;
102
+ /**
103
+ * Fails a run whose ScanningRecipe's accumulator keeps a tree, cursor, visitor, execution context, dependency model
104
+ * or other type given to registerHeavyweight, which would stay in memory all cycle.
105
+ */
106
+ this.checkLightweightAccumulators = true;
107
+ /**
108
+ * Fails a run whose output holds a node that the source's parser builds differently from the text it prints, such
109
+ * as a J.Identifier where the parser makes a J.Literal of `null`.
110
+ */
111
+ this.checkParserShapedTrees = true;
112
+ /**
113
+ * Fails a run whose recipe auto-formats a whole source file or class that existed before the run, instead of only
114
+ * what it changed.
115
+ */
116
+ this.checkMinimalFormatting = true;
53
117
  this.recipe = new NoopRecipe();
54
118
  /**
55
119
  * Used for both parsing and recipe execution unless an alternative recipe execution context is set with
@@ -75,6 +139,11 @@ class RecipeSpec {
75
139
  checkParsePrintIdempotence: this.checkParsePrintIdempotence,
76
140
  allowEmptyDiff: this.allowEmptyDiff,
77
141
  checkReportingMarkersOnly: this.checkReportingMarkersOnly,
142
+ checkExecutionContextUnchanged: this.checkExecutionContextUnchanged,
143
+ checkNoEditsInScanningPhase: this.checkNoEditsInScanningPhase,
144
+ checkLightweightAccumulators: this.checkLightweightAccumulators,
145
+ checkParserShapedTrees: this.checkParserShapedTrees,
146
+ checkMinimalFormatting: this.checkMinimalFormatting,
78
147
  cycles: this.cycles,
79
148
  expectedCyclesThatMakeChanges: this.expectedCyclesThatMakeChanges,
80
149
  recipe: this.recipe,
@@ -188,18 +257,40 @@ class RecipeSpec {
188
257
  }
189
258
  }
190
259
  this.recipeExecutionContext.messages[data_table_1.DATA_TABLE_STORE] = new data_table_1.InMemoryDataTableStore();
260
+ this.recipeExecutionContext.messages[execution_1.ExecutionContext.SCANNING_MUTATION_VALIDATION] =
261
+ this.checkNoEditsInScanningPhase;
262
+ const accumulatorContents = this.checkLightweightAccumulators ? new accumulator_contents_1.AccumulatorContents() : undefined;
263
+ this.recipeExecutionContext.messages[run_1.ACCUMULATOR_LISTENER] = accumulatorContents === null || accumulatorContents === void 0 ? void 0 : accumulatorContents.listener;
264
+ const contextWrites = this.checkExecutionContextUnchanged ? new ExecutionContextWrites() : undefined;
265
+ const runContext = (ctx) => { var _a; return (_a = contextWrites === null || contextWrites === void 0 ? void 0 : contextWrites.watch(ctx)) !== null && _a !== void 0 ? _a : ctx; };
191
266
  const expectedCycles = (_d = this.expectedCyclesThatMakeChanges) !== null && _d !== void 0 ? _d : 1;
192
267
  const cycles = (_e = this.cycles) !== null && _e !== void 0 ? _e : Math.max(2, expectedCycles + 1);
193
- const { changeset, unsettled } = await this.runCycles(allParsed.map(([_, sourceFile]) => sourceFile), cycles, expectedCycles);
268
+ const formattingScope = this.checkMinimalFormatting ? new formatting_scope_1.FormattingScope(this.recipe) : undefined;
269
+ const run = () => this.runCycles(allParsed.map(([_, sourceFile]) => sourceFile), cycles, expectedCycles, runContext);
270
+ const { changeset, unsettled } = formattingScope ? await (0, format_1.listenToFormatting)(formattingScope, run) : await run();
271
+ contextWrites === null || contextWrites === void 0 ? void 0 : contextWrites.assertNone(this.recipe);
194
272
  this.expectNoUnexpectedGeneratedFiles(flattenedSpecs, changeset);
195
273
  this.checkReportingMarkersOnly && await this.expectNoAddedMarkers(flattenedSpecs, allParsed, changeset);
274
+ accumulatorContents === null || accumulatorContents === void 0 ? void 0 : accumulatorContents.assertNoneFound();
196
275
  await this.expectResultsToMatchAfter(flattenedSpecs, changeset, allParsed);
197
276
  await this.expectGeneratedFiles(flattenedSpecs, changeset);
198
277
  if (unsettled) {
199
278
  await this.expectNoFurtherChanges(unsettled.changes, `Expected recipe to complete in ${pluralCycles(expectedCycles)}, but cycle ${unsettled.cycle} changed`);
200
279
  }
201
- cycles > expectedCycles && await this.expectStableOnFreshParse(flattenedSpecs, allParsed, changeset);
280
+ await (formattingScope === null || formattingScope === void 0 ? void 0 : formattingScope.assertFormattedOnlyWhatChanged(changeset));
281
+ const changed = changeset.some(r => r.before !== r.after);
282
+ const freshParse = changed && (cycles > expectedCycles || this.checkParserShapedTrees) ?
283
+ await this.freshParse(flattenedSpecs, allParsed, changeset) : new Map();
284
+ this.checkParserShapedTrees && await new tree_shapes_1.TreeShapes(this.recipe).assertParserShaped(changeset, freshParse);
285
+ cycles > expectedCycles && await this.expectStableOnFreshParse(changeset, freshParse, runContext);
286
+ contextWrites === null || contextWrites === void 0 ? void 0 : contextWrites.assertNone(this.recipe);
202
287
  await this.expectDataTables();
288
+ if (changeset.some(r => r.before && r.after !== r.before) && await isProbed(this.recipe)) {
289
+ await new empty_sources_1.EmptySources(this.recipe, changeset)
290
+ .assertNoneThrow(allParsed, this.executionContext, this.recipeExecutionContext, cycles);
291
+ await new unparsed_sources_1.UnparsedSources(this.recipe, changeset)
292
+ .assertNoneThrow(allParsed.map(([_, sourceFile]) => sourceFile), this.recipeExecutionContext, cycles);
293
+ }
203
294
  }
204
295
  async expectDataTables() {
205
296
  const store = this.recipeExecutionContext.messages[data_table_1.DATA_TABLE_STORE];
@@ -213,14 +304,14 @@ class RecipeSpec {
213
304
  await assertion(store.getRows(name, dataTable.group));
214
305
  }
215
306
  }
216
- async runCycles(sources, cycles, expectedCycles) {
307
+ async runCycles(sources, cycles, expectedCycles, runContext) {
217
308
  const lineages = sources.map(s => ({ origin: s, latest: s }));
218
309
  const changesetOf = () => lineages.map(({ origin, latest }) => new run_1.Result(origin, latest));
219
310
  let changeset;
220
311
  let cyclesThatMadeChanges = 0;
221
312
  for (let cycle = 1; cycle <= cycles; cycle++) {
222
313
  const live = lineages.filter(l => l.latest).map(l => l.latest);
223
- const ctx = cycle === 1 ? this.recipeExecutionContext : this.laterRunContext();
314
+ const ctx = runContext(cycle === 1 ? this.recipeExecutionContext : this.laterRunContext());
224
315
  const changes = (await (0, run_1.scheduleRun)(this.recipe, live, ctx)).changeset.filter(r => r.before !== r.after);
225
316
  if (changes.length === 0) {
226
317
  break;
@@ -285,14 +376,11 @@ class RecipeSpec {
285
376
  }
286
377
  }
287
378
  /**
288
- * Code that the next run reads is parsed from the printed output, not the LST this run produced, and a
289
- * recipe that recognizes its own output only by the shape of that LST changes it again.
379
+ * A fresh parse, by the parser of its spec, of the text each source the recipe left prints, parsing the sources
380
+ * of one kind together so that they can refer to one another. A parser that throws leaves its sources out.
290
381
  */
291
- async expectStableOnFreshParse(specs, parsed, changeset) {
382
+ async freshParse(specs, parsed, changeset) {
292
383
  var _a, e_2, _b, _c;
293
- if (!changeset.some(r => r.before !== r.after)) {
294
- return;
295
- }
296
384
  const finals = changeset.filter(r => r.after).map(({ before, after }) => {
297
385
  var _a;
298
386
  return [
@@ -316,11 +404,7 @@ class RecipeSpec {
316
404
  _c = _f.value;
317
405
  _d = false;
318
406
  const reparsed = _c;
319
- if (!(0, parse_error_1.isParseError)(reparsed) && await printSanitized(reparsed) === inputs[i].text) {
320
- // What the source file carries, like its styles, comes from outside its text
321
- reparsedByFinal.set(group[i][1], Object.assign(Object.assign({}, reparsed), { markers: group[i][1].markers }));
322
- }
323
- i++;
407
+ reparsedByFinal.set(group[i++][1], reparsed);
324
408
  }
325
409
  }
326
410
  catch (e_2_1) { e_2 = { error: e_2_1 }; }
@@ -332,14 +416,34 @@ class RecipeSpec {
332
416
  }
333
417
  }
334
418
  catch (_g) {
419
+ // the sources it didn't get to are left out
420
+ }
421
+ }
422
+ return reparsedByFinal;
423
+ }
424
+ /**
425
+ * Code that the next run reads is parsed from the printed output, not the LST this run produced, and a
426
+ * recipe that recognizes its own output only by the shape of that LST changes it again.
427
+ */
428
+ async expectStableOnFreshParse(changeset, freshParse, runContext) {
429
+ let reparsedAny = false;
430
+ const sources = [];
431
+ for (const after of changeset.filter(r => r.after).map(r => r.after)) {
432
+ const reparsed = freshParse.get(after);
433
+ if (reparsed && !(0, parse_error_1.isParseError)(reparsed) && await printSanitized(reparsed) === await printSanitized(after)) {
434
+ // What the source file carries, like its styles, comes from outside its text
435
+ sources.push(Object.assign(Object.assign({}, reparsed), { markers: after.markers }));
436
+ reparsedAny = true;
437
+ }
438
+ else {
335
439
  // files that do not parse again keep the LST the recipe produced
440
+ sources.push(after);
336
441
  }
337
442
  }
338
- if (reparsedByFinal.size === 0) {
443
+ if (!reparsedAny) {
339
444
  return;
340
445
  }
341
- const sources = finals.map(([_, sourceFile]) => { var _a; return (_a = reparsedByFinal.get(sourceFile)) !== null && _a !== void 0 ? _a : sourceFile; });
342
- const changes = (await (0, run_1.scheduleRun)(this.recipe, sources, this.laterRunContext())).changeset
446
+ const changes = (await (0, run_1.scheduleRun)(this.recipe, sources, runContext(this.laterRunContext()))).changeset
343
447
  .filter(r => r.before !== r.after);
344
448
  await this.expectNoFurtherChanges(changes, "Running the recipe on a fresh parse of its output changed", true);
345
449
  }
@@ -469,7 +573,7 @@ class RecipeSpec {
469
573
  }
470
574
  async expectGeneratedFiles(specs, changeset) {
471
575
  for (const spec of specs) {
472
- if (spec.before) {
576
+ if (spec.before !== null) {
473
577
  continue;
474
578
  }
475
579
  if (!spec.after) {
@@ -480,7 +584,7 @@ class RecipeSpec {
480
584
  }
481
585
  }
482
586
  expectNoUnexpectedGeneratedFiles(specs, changeset) {
483
- const expectedPaths = new Set(specs.filter(spec => !spec.before).map(spec => spec.path));
587
+ const expectedPaths = new Set(specs.filter(spec => spec.before === null).map(spec => spec.path));
484
588
  const unexpected = changeset.filter(c => !c.before && c.after && !expectedPaths.has(c.after.sourcePath));
485
589
  if (unexpected.length > 0) {
486
590
  throw new Error([
@@ -518,7 +622,7 @@ class RecipeSpec {
518
622
  let unnamed = 0;
519
623
  const before = [];
520
624
  for (const spec of specs) {
521
- if (spec.before) {
625
+ if (spec.before !== null) {
522
626
  const sourcePath = spec.path || `source-${unnamed++}.${spec.ext}`;
523
627
  before.push([spec, { text: dedent(spec.before), sourcePath: sourcePath }]);
524
628
  }
@@ -559,6 +663,72 @@ class ValidateWhitespaceVisitor extends javascript_1.JavaScriptVisitor {
559
663
  return ret;
560
664
  }
561
665
  }
666
+ /** Whether the framework puts `key` on the execution context of a run itself. */
667
+ function isFrameworkMessage(key) {
668
+ return key === data_table_1.DATA_TABLE_STORE || key === execution_1.ExecutionContext.REQUIRE_PRINT_EQUALS_INPUT;
669
+ }
670
+ /** Records the messages that a recipe puts on the execution context of its run, with the code that put each. */
671
+ class ExecutionContextWrites {
672
+ constructor() {
673
+ this.writes = new Map();
674
+ }
675
+ /** A view of `ctx` whose messages record what is put on them, and that otherwise acts as `ctx`. */
676
+ watch(ctx) {
677
+ const record = (key) => {
678
+ if (!isFrameworkMessage(key) && !this.writes.has(key)) {
679
+ this.writes.set(key, callerFrame());
680
+ }
681
+ };
682
+ const messages = new Proxy(ctx.messages, {
683
+ set(target, key, value) {
684
+ record(key);
685
+ return Reflect.set(target, key, value);
686
+ },
687
+ defineProperty(target, key, attributes) {
688
+ record(key);
689
+ return Reflect.defineProperty(target, key, attributes);
690
+ }
691
+ });
692
+ return Object.create(ctx, { messages: { value: messages, enumerable: true, writable: true } });
693
+ }
694
+ assertNone(recipe) {
695
+ if (this.writes.size === 0) {
696
+ return;
697
+ }
698
+ throw new Error([
699
+ "Keep state that spans source files in a ScanningRecipe's accumulator, and state within one source file " +
700
+ "in cursor messages, with this.cursor.messages.set(key, value). " +
701
+ `${recipe.name} put messages on the ExecutionContext, which every recipe and source file in a run ` +
702
+ "shares, so what it keeps there leaks into the others:",
703
+ ...[...this.writes].map(([key, frame]) => ` ${typeof key === "symbol" ? key.toString() : JSON.stringify(key)}${frame ? ` at ${frame}` : ""}`),
704
+ "A recipe that must change the ExecutionContext opts out with spec.checkExecutionContextUnchanged = false."
705
+ ].join("\n"));
706
+ }
707
+ }
708
+ /** The first frame of the stack outside the harness and the runtime, relative to the working directory. */
709
+ function callerFrame() {
710
+ var _a;
711
+ const frame = ((_a = new Error().stack) !== null && _a !== void 0 ? _a : "").split("\n").slice(1)
712
+ .map(line => line.trim().replace(/^at (async )?/, ""))
713
+ .find(line => !/[\\/]test[\\/]rewrite-test\.[jt]s:|<anonymous>|^node:/.test(line));
714
+ return frame === null || frame === void 0 ? void 0 : frame.split(process.cwd() + path.sep).join("");
715
+ }
716
+ /**
717
+ * Whether the recipe is run on sources the test doesn't give it, which a recipe isn't when it or one in its recipe list
718
+ * is the harness's stand-in for a visitor, or runs in Java, whose harness probes it.
719
+ */
720
+ async function isProbed(recipe) {
721
+ if (recipe instanceof NoopRecipe || recipe instanceof AdHocRecipe || recipe instanceof recipe_2.RpcRecipe ||
722
+ recipe instanceof java_recipe_1.DelegatingRecipe) {
723
+ return false;
724
+ }
725
+ for (const child of await recipe.recipeList()) {
726
+ if (!await isProbed(child)) {
727
+ return false;
728
+ }
729
+ }
730
+ return true;
731
+ }
562
732
  /** Without the comments that search results and markup print as. */
563
733
  function printSanitized(sourceFile) {
564
734
  return print_1.TreePrinters.printer(sourceFile).print(sourceFile, new print_1.PrintOutputCapture(print_1.MarkerPrinter.SANITIZED));