@openrewrite/rewrite 8.91.3 → 8.91.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/javascript/index.d.ts +1 -1
- package/dist/javascript/index.d.ts.map +1 -1
- package/dist/javascript/index.js +2 -1
- package/dist/javascript/index.js.map +1 -1
- package/dist/javascript/parser.d.ts +3 -2
- package/dist/javascript/parser.d.ts.map +1 -1
- package/dist/javascript/parser.js +154 -114
- package/dist/javascript/parser.js.map +1 -1
- package/dist/javascript/remove-import.d.ts +0 -18
- package/dist/javascript/remove-import.d.ts.map +1 -1
- package/dist/javascript/remove-import.js +50 -438
- package/dist/javascript/remove-import.js.map +1 -1
- package/dist/javascript/scope.d.ts +6 -0
- package/dist/javascript/scope.d.ts.map +1 -1
- package/dist/javascript/scope.js +87 -7
- package/dist/javascript/scope.js.map +1 -1
- package/dist/javascript/tsconfig.d.ts +32 -0
- package/dist/javascript/tsconfig.d.ts.map +1 -0
- package/dist/javascript/tsconfig.js +205 -0
- package/dist/javascript/tsconfig.js.map +1 -0
- package/dist/rewrite-javascript-version.txt +1 -1
- package/dist/rpc/index.d.ts +1 -1
- package/dist/rpc/index.d.ts.map +1 -1
- package/dist/rpc/index.js +2 -1
- package/dist/rpc/index.js.map +1 -1
- package/dist/rpc/java-recipe.d.ts +32 -22
- package/dist/rpc/java-recipe.d.ts.map +1 -1
- package/dist/rpc/java-recipe.js +91 -30
- package/dist/rpc/java-recipe.js.map +1 -1
- package/dist/rpc/request/prepare-recipe.d.ts +10 -14
- package/dist/rpc/request/prepare-recipe.d.ts.map +1 -1
- package/dist/rpc/request/prepare-recipe.js +53 -88
- package/dist/rpc/request/prepare-recipe.js.map +1 -1
- package/dist/rpc/rewrite-rpc.d.ts +5 -12
- package/dist/rpc/rewrite-rpc.d.ts.map +1 -1
- package/dist/rpc/rewrite-rpc.js +5 -12
- package/dist/rpc/rewrite-rpc.js.map +1 -1
- package/package.json +1 -1
- package/src/javascript/index.ts +1 -1
- package/src/javascript/parser.ts +104 -58
- package/src/javascript/remove-import.ts +50 -424
- package/src/javascript/scope.ts +103 -7
- package/src/javascript/tsconfig.ts +177 -0
- package/src/rpc/index.ts +1 -1
- package/src/rpc/java-recipe.ts +107 -33
- package/src/rpc/request/prepare-recipe.ts +55 -90
- package/src/rpc/rewrite-rpc.ts +5 -12
|
@@ -19,6 +19,7 @@ import {Recipe, RecipeDescriptor, ScanningRecipe} from "../../recipe";
|
|
|
19
19
|
import {SnowflakeId} from "@akashrajpurohit/snowflake-id";
|
|
20
20
|
import {Check, CheckArg, CompositePrecondition, RecipeRef} from "../../preconditions";
|
|
21
21
|
import {RpcRecipe} from "../recipe";
|
|
22
|
+
import {DelegatingRecipe} from "../java-recipe";
|
|
22
23
|
import {TreeVisitor} from "../../visitor";
|
|
23
24
|
import {ExecutionContext} from "../../execution";
|
|
24
25
|
import {withMetrics} from "./metrics";
|
|
@@ -42,22 +43,10 @@ export class PrepareRecipe {
|
|
|
42
43
|
context.target = request.id;
|
|
43
44
|
const recipeCtor = marketplace.findRecipe(request.id);
|
|
44
45
|
if (!recipeCtor) {
|
|
45
|
-
// A miss means the host owns this recipe (e.g. a
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const id = snowflake.generate();
|
|
50
|
-
return {
|
|
51
|
-
id: id,
|
|
52
|
-
descriptor: PrepareRecipe.delegateDescriptor(request.id),
|
|
53
|
-
editVisitor: `edit:${id}`,
|
|
54
|
-
editPreconditions: [],
|
|
55
|
-
scanPreconditions: [],
|
|
56
|
-
delegatesTo: {
|
|
57
|
-
recipeName: request.id,
|
|
58
|
-
options: request.options ?? {}
|
|
59
|
-
}
|
|
60
|
-
};
|
|
46
|
+
// A miss means the host owns this recipe (e.g. a Java-delegate child a host
|
|
47
|
+
// re-prepares by name), so answer with a delegatesTo stand-in for it to resolve.
|
|
48
|
+
return await PrepareRecipe.prepareInstance(new DelegatingRecipe(request.id, request.options ?? {}),
|
|
49
|
+
snowflake, preparedRecipes, marketplace);
|
|
61
50
|
}
|
|
62
51
|
if (!recipeCtor[1]) {
|
|
63
52
|
throw new Error(`Recipe ${request.id} was installed without a constructor`);
|
|
@@ -70,44 +59,30 @@ export class PrepareRecipe {
|
|
|
70
59
|
}
|
|
71
60
|
|
|
72
61
|
/**
|
|
73
|
-
*
|
|
74
|
-
* {@
|
|
75
|
-
*
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return {
|
|
79
|
-
name: name,
|
|
80
|
-
displayName: name,
|
|
81
|
-
instanceName: name,
|
|
82
|
-
description: "",
|
|
83
|
-
tags: [],
|
|
84
|
-
estimatedEffortPerOccurrence: 5,
|
|
85
|
-
options: [],
|
|
86
|
-
preconditions: [],
|
|
87
|
-
recipeList: [],
|
|
88
|
-
dataTables: [],
|
|
89
|
-
maintainers: [],
|
|
90
|
-
contributors: [],
|
|
91
|
-
examples: []
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Prepares a recipe instance and recursively its whole child tree, registering every node in
|
|
97
|
-
* {@code preparedRecipes} and returning the prepared response with {@code recipeList} populated,
|
|
98
|
-
* so the host builds the tree locally instead of a PrepareRecipe round-trip per child.
|
|
99
|
-
*
|
|
100
|
-
* Mirrors the C# server's PrepareInstance. Required options are validated as each node is
|
|
101
|
-
* prepared (covering the whole tree). A child hosted on the peer (an {@link RpcRecipe}, e.g. from
|
|
102
|
-
* prepareJavaRecipe) carries only {@code delegatesTo} for the host to resolve locally; every other
|
|
103
|
-
* child carries its own {@code recipeList}. Delegating recipes forward validation to the recipe
|
|
104
|
-
* they delegate to, so they are not validated here.
|
|
62
|
+
* Prepares a recipe and, recursively, its whole child tree, registering every node in
|
|
63
|
+
* {@code preparedRecipes}; the response carries {@code recipeList} so the host builds the tree
|
|
64
|
+
* without a PrepareRecipe round-trip per child (mirrors the C# server's PrepareInstance).
|
|
65
|
+
* Required options are validated per node. A stand-in for a host recipe (see {@link #delegatesTo})
|
|
66
|
+
* carries only {@code delegatesTo} and leaves validation to the host.
|
|
105
67
|
*/
|
|
106
68
|
private static async prepareInstance(recipe: Recipe,
|
|
107
69
|
snowflake: ReturnType<typeof SnowflakeId>,
|
|
108
70
|
preparedRecipes: Map<String, Recipe>,
|
|
109
71
|
marketplace: RecipeMarketplace): Promise<PrepareRecipeResponse> {
|
|
110
72
|
const id = snowflake.generate();
|
|
73
|
+
const delegatesTo = PrepareRecipe.delegatesTo(recipe);
|
|
74
|
+
if (delegatesTo) {
|
|
75
|
+
// Registered so a peer that visits `edit:<id>` instead of honouring delegatesTo reaches it.
|
|
76
|
+
preparedRecipes.set(id, recipe);
|
|
77
|
+
return {
|
|
78
|
+
id: id,
|
|
79
|
+
descriptor: await recipe.descriptor(),
|
|
80
|
+
editVisitor: `edit:${id}`,
|
|
81
|
+
editPreconditions: [],
|
|
82
|
+
scanPreconditions: [],
|
|
83
|
+
delegatesTo
|
|
84
|
+
};
|
|
85
|
+
}
|
|
111
86
|
|
|
112
87
|
const editPreconditions: Precondition[] = [];
|
|
113
88
|
recipe = await PrepareRecipe.optimizePreconditions(recipe, "edit", editPreconditions);
|
|
@@ -117,13 +92,9 @@ export class PrepareRecipe {
|
|
|
117
92
|
preparedRecipes.set(id, recipe);
|
|
118
93
|
|
|
119
94
|
const descriptor = await recipe.descriptor();
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
for (const option of descriptor.options) {
|
|
124
|
-
if ((option.required ?? true) && option.value == null) {
|
|
125
|
-
throw new Error(`Missing required option \`${option.name}\` for recipe \`${descriptor.name}\`.`);
|
|
126
|
-
}
|
|
95
|
+
for (const option of descriptor.options) {
|
|
96
|
+
if ((option.required ?? true) && option.value == null) {
|
|
97
|
+
throw new Error(`Missing required option \`${option.name}\` for recipe \`${descriptor.name}\`.`);
|
|
127
98
|
}
|
|
128
99
|
}
|
|
129
100
|
|
|
@@ -136,49 +107,43 @@ export class PrepareRecipe {
|
|
|
136
107
|
scanPreconditions: scanPreconditions
|
|
137
108
|
};
|
|
138
109
|
|
|
139
|
-
if (isDelegating) {
|
|
140
|
-
response.delegatesTo = {
|
|
141
|
-
recipeName: (recipe as any).javaRecipeName,
|
|
142
|
-
options: (recipe as any).delegatesToOptions ?? {}
|
|
143
|
-
};
|
|
144
|
-
return response;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
110
|
const childResponses: PrepareRecipeResponse[] = [];
|
|
148
111
|
for (const child of await recipe.recipeList()) {
|
|
149
112
|
if (child instanceof RpcRecipe) {
|
|
150
|
-
//
|
|
151
|
-
// host resolves it locally, matching how the by-name fallback used to resolve it.
|
|
152
|
-
const childId = snowflake.generate();
|
|
153
|
-
const childDescriptor = await child.descriptor();
|
|
113
|
+
// Already prepared on the host: hand it back by name with the options its parent set.
|
|
154
114
|
const options: Record<string, any> = {};
|
|
155
|
-
for (const option of
|
|
115
|
+
for (const option of (await child.descriptor()).options) {
|
|
156
116
|
if (option.value != null) {
|
|
157
117
|
options[option.name] = option.value;
|
|
158
118
|
}
|
|
159
119
|
}
|
|
160
|
-
childResponses.push(
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
editVisitor: `edit:${childId}`,
|
|
164
|
-
editPreconditions: [],
|
|
165
|
-
scanPreconditions: [],
|
|
166
|
-
delegatesTo: {recipeName: child.name, options}
|
|
167
|
-
});
|
|
168
|
-
} else {
|
|
169
|
-
// Register a child that was instantiated in recipeList() but never installed, so a peer
|
|
170
|
-
// that re-prepares children by name (rather than consuming recipeList) can still find it.
|
|
171
|
-
if (!marketplace.findRecipe(child.name)) {
|
|
172
|
-
await marketplace.install(child.constructor as any, []);
|
|
173
|
-
}
|
|
174
|
-
childResponses.push(await PrepareRecipe.prepareInstance(child, snowflake, preparedRecipes, marketplace));
|
|
120
|
+
childResponses.push(await PrepareRecipe.prepareInstance(new DelegatingRecipe(child.name, options),
|
|
121
|
+
snowflake, preparedRecipes, marketplace));
|
|
122
|
+
continue;
|
|
175
123
|
}
|
|
124
|
+
// Register a child that was instantiated in recipeList() but never installed, so a peer
|
|
125
|
+
// that re-prepares children by name (rather than consuming recipeList) can still find it.
|
|
126
|
+
if (!PrepareRecipe.delegatesTo(child) && !marketplace.findRecipe(child.name)) {
|
|
127
|
+
await marketplace.install(child.constructor as any, []);
|
|
128
|
+
}
|
|
129
|
+
childResponses.push(await PrepareRecipe.prepareInstance(child, snowflake, preparedRecipes, marketplace));
|
|
176
130
|
}
|
|
177
131
|
response.recipeList = childResponses;
|
|
178
132
|
|
|
179
133
|
return response;
|
|
180
134
|
}
|
|
181
135
|
|
|
136
|
+
/**
|
|
137
|
+
* The Java recipe {@code recipe} stands in for, or {@code undefined} for a recipe this process
|
|
138
|
+
* runs itself. Duck-typed on the fields {@link DelegatingRecipe} declares, so a recipe package
|
|
139
|
+
* that loaded its own copy of this module is recognised too.
|
|
140
|
+
*/
|
|
141
|
+
private static delegatesTo(recipe: any): {recipeName: string, options: Record<string, any>} | undefined {
|
|
142
|
+
return recipe != null && typeof recipe.javaRecipeName === "string" ?
|
|
143
|
+
{recipeName: recipe.javaRecipeName, options: {...(recipe.delegatesToOptions ?? {})}} :
|
|
144
|
+
undefined;
|
|
145
|
+
}
|
|
146
|
+
|
|
182
147
|
/**
|
|
183
148
|
* For preconditions that can be evaluated on the remote peer, let the remote peer
|
|
184
149
|
* evaluate them and know that we will only have to do the visit work if the
|
|
@@ -246,13 +211,13 @@ export class PrepareRecipe {
|
|
|
246
211
|
}
|
|
247
212
|
return {op: condition.op, operands};
|
|
248
213
|
}
|
|
249
|
-
// Common case:
|
|
250
|
-
//
|
|
251
|
-
// firing an RPC at editor() time. The Java host's
|
|
252
|
-
//
|
|
253
|
-
|
|
254
|
-
if (
|
|
255
|
-
return {visitorName:
|
|
214
|
+
// Common case: usesMethod / usesType return a lightweight RecipeRef, and
|
|
215
|
+
// prepareJavaRecipe a DelegatingRecipe, so a precondition is declared without
|
|
216
|
+
// firing an RPC at editor() time. The Java host's PreparedRecipeCache
|
|
217
|
+
// .instantiateVisitor constructs the named recipe via Jackson and uses its visitor.
|
|
218
|
+
const ref = condition instanceof RecipeRef ? condition : PrepareRecipe.delegatesTo(condition);
|
|
219
|
+
if (ref) {
|
|
220
|
+
return {visitorName: ref.recipeName, visitorOptions: {...ref.options}};
|
|
256
221
|
}
|
|
257
222
|
if (condition instanceof RpcRecipe) {
|
|
258
223
|
return {visitorName: phase === "edit" ? condition.editVisitor : condition.scanVisitor!};
|
package/src/rpc/rewrite-rpc.ts
CHANGED
|
@@ -50,18 +50,11 @@ import {GetLanguages} from "./request/get-languages";
|
|
|
50
50
|
|
|
51
51
|
export class RewriteRpc {
|
|
52
52
|
/**
|
|
53
|
-
* Key for the active {@link RewriteRpc} connection on {@link globalThis}.
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* own class object and therefore its own statics. A `static` field set by
|
|
59
|
-
* the host would be invisible to such a copy, so `RewriteRpc.get()` (e.g.
|
|
60
|
-
* via `prepareJavaRecipe`) would return `undefined` and throw "no active
|
|
61
|
-
* RewriteRpc connection" — surfacing during `InstallRecipes` as the
|
|
62
|
-
* misleading "Ensure the constructor can be called without any arguments".
|
|
63
|
-
* {@link Symbol.for} resolves to the same symbol across every module copy,
|
|
64
|
-
* so all copies share the one active connection. See gh-7968.
|
|
53
|
+
* Key for the active {@link RewriteRpc} connection on {@link globalThis}. A recipe package that
|
|
54
|
+
* bundles `@openrewrite/rewrite` or resolves it from its own `node_modules` loads a separate copy
|
|
55
|
+
* of this module with its own class object and statics, so a `static` field set by the host would
|
|
56
|
+
* be invisible to it; {@link Symbol.for} resolves to the same symbol across every module copy, so
|
|
57
|
+
* all copies share the one active connection. See gh-7968.
|
|
65
58
|
*/
|
|
66
59
|
private static readonly GLOBAL_KEY: symbol = Symbol.for("org.openrewrite.rpc.RewriteRpc.global");
|
|
67
60
|
|