@openrewrite/rewrite 8.72.2 → 8.72.4
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.js +3 -16
- package/dist/execution.js.map +1 -1
- package/dist/index.js +34 -49
- package/dist/index.js.map +1 -1
- package/dist/java/markers.js +12 -29
- package/dist/java/markers.js.map +1 -1
- package/dist/java/print.js +2 -13
- package/dist/java/print.js.map +1 -1
- package/dist/java/rpc.js +1344 -1725
- package/dist/java/rpc.js.map +1 -1
- package/dist/java/type-visitor.js +143 -184
- package/dist/java/type-visitor.js.map +1 -1
- package/dist/java/visitor.js +1072 -1249
- package/dist/java/visitor.js.map +1 -1
- package/dist/javascript/add-import.js +495 -534
- package/dist/javascript/add-import.js.map +1 -1
- package/dist/javascript/autodetect.js +116 -159
- package/dist/javascript/autodetect.js.map +1 -1
- package/dist/javascript/cleanup/add-parse-int-radix.js +41 -57
- package/dist/javascript/cleanup/add-parse-int-radix.js.map +1 -1
- package/dist/javascript/cleanup/prefer-optional-chain.js +89 -105
- package/dist/javascript/cleanup/prefer-optional-chain.js.map +1 -1
- package/dist/javascript/cleanup/use-object-property-shorthand.js +74 -95
- package/dist/javascript/cleanup/use-object-property-shorthand.js.map +1 -1
- package/dist/javascript/comparator.js +815 -1167
- package/dist/javascript/comparator.js.map +1 -1
- package/dist/javascript/dependency-workspace.js +206 -219
- package/dist/javascript/dependency-workspace.js.map +1 -1
- package/dist/javascript/format/format.js +682 -908
- package/dist/javascript/format/format.js.map +1 -1
- package/dist/javascript/format/minimum-viable-spacing-visitor.js +152 -231
- package/dist/javascript/format/minimum-viable-spacing-visitor.js.map +1 -1
- package/dist/javascript/format/normalize-whitespace-visitor.js +12 -31
- package/dist/javascript/format/normalize-whitespace-visitor.js.map +1 -1
- package/dist/javascript/format/prettier-config-loader.js +134 -153
- package/dist/javascript/format/prettier-config-loader.js.map +1 -1
- package/dist/javascript/format/prettier-format.js +112 -129
- package/dist/javascript/format/prettier-format.js.map +1 -1
- package/dist/javascript/format/tabs-and-indents-visitor.js +112 -136
- package/dist/javascript/format/tabs-and-indents-visitor.js.map +1 -1
- package/dist/javascript/markers.js +59 -92
- package/dist/javascript/markers.js.map +1 -1
- package/dist/javascript/migrate/es6/modernize-octal-escape-sequences.js +39 -52
- package/dist/javascript/migrate/es6/modernize-octal-escape-sequences.js.map +1 -1
- package/dist/javascript/migrate/es6/modernize-octal-literals.js +25 -38
- package/dist/javascript/migrate/es6/modernize-octal-literals.js.map +1 -1
- package/dist/javascript/migrate/es6/remove-duplicate-object-keys.js +66 -82
- package/dist/javascript/migrate/es6/remove-duplicate-object-keys.js.map +1 -1
- package/dist/javascript/migrate/typescript/export-assignment-to-export-default.js +10 -23
- package/dist/javascript/migrate/typescript/export-assignment-to-export-default.js.map +1 -1
- package/dist/javascript/node-resolution-result.js +137 -166
- package/dist/javascript/node-resolution-result.js.map +1 -1
- package/dist/javascript/package-json-parser.js +312 -343
- package/dist/javascript/package-json-parser.js.map +1 -1
- package/dist/javascript/package-manager.js +145 -170
- package/dist/javascript/package-manager.js.map +1 -1
- package/dist/javascript/parser.d.ts.map +1 -1
- package/dist/javascript/parser.js +94 -68
- package/dist/javascript/parser.js.map +1 -1
- package/dist/javascript/print.js +1572 -1835
- package/dist/javascript/print.js.map +1 -1
- package/dist/javascript/project-parser.js +151 -172
- package/dist/javascript/project-parser.js.map +1 -1
- package/dist/javascript/recipes/add-dependency.js +140 -175
- package/dist/javascript/recipes/add-dependency.js.map +1 -1
- package/dist/javascript/recipes/async-callback-in-sync-array-method.js +20 -36
- package/dist/javascript/recipes/async-callback-in-sync-array-method.js.map +1 -1
- package/dist/javascript/recipes/auto-format.js +3 -14
- package/dist/javascript/recipes/auto-format.js.map +1 -1
- package/dist/javascript/recipes/change-import.js +447 -495
- package/dist/javascript/recipes/change-import.js.map +1 -1
- package/dist/javascript/recipes/order-imports.js +162 -175
- package/dist/javascript/recipes/order-imports.js.map +1 -1
- package/dist/javascript/recipes/upgrade-dependency-version.js +167 -197
- package/dist/javascript/recipes/upgrade-dependency-version.js.map +1 -1
- package/dist/javascript/recipes/upgrade-transitive-dependency-version.js +166 -193
- package/dist/javascript/recipes/upgrade-transitive-dependency-version.js.map +1 -1
- package/dist/javascript/remove-import.js +689 -724
- package/dist/javascript/remove-import.js.map +1 -1
- package/dist/javascript/rpc.js +1007 -1332
- package/dist/javascript/rpc.js.map +1 -1
- package/dist/javascript/search/find-dependency.js +84 -110
- package/dist/javascript/search/find-dependency.js.map +1 -1
- package/dist/javascript/search/uses-method.js +5 -19
- package/dist/javascript/search/uses-method.js.map +1 -1
- package/dist/javascript/search/uses-type.js +9 -20
- package/dist/javascript/search/uses-type.js.map +1 -1
- package/dist/javascript/templating/comparator.js +737 -822
- package/dist/javascript/templating/comparator.js.map +1 -1
- package/dist/javascript/templating/engine.js +211 -245
- package/dist/javascript/templating/engine.js.map +1 -1
- package/dist/javascript/templating/pattern.js +169 -190
- package/dist/javascript/templating/pattern.js.map +1 -1
- package/dist/javascript/templating/placeholder-replacement.js +172 -210
- package/dist/javascript/templating/placeholder-replacement.js.map +1 -1
- package/dist/javascript/templating/rewrite.js +75 -97
- package/dist/javascript/templating/rewrite.js.map +1 -1
- package/dist/javascript/templating/template.js +69 -82
- package/dist/javascript/templating/template.js.map +1 -1
- package/dist/javascript/tree-debug.js +109 -137
- package/dist/javascript/tree-debug.js.map +1 -1
- package/dist/javascript/visitor.js +1090 -1254
- package/dist/javascript/visitor.js.map +1 -1
- package/dist/json/print.js +72 -103
- package/dist/json/print.js.map +1 -1
- package/dist/json/rpc.js +120 -181
- package/dist/json/rpc.js.map +1 -1
- package/dist/json/visitor.js +69 -100
- package/dist/json/visitor.js.map +1 -1
- package/dist/marketplace.js +20 -33
- package/dist/marketplace.js.map +1 -1
- package/dist/parse-error.js +41 -62
- package/dist/parse-error.js.map +1 -1
- package/dist/parser.js +7 -18
- package/dist/parser.js.map +1 -1
- package/dist/path-utils.js +46 -59
- package/dist/path-utils.js.map +1 -1
- package/dist/preconditions.js +30 -47
- package/dist/preconditions.js.map +1 -1
- package/dist/print.js +6 -19
- package/dist/print.js.map +1 -1
- package/dist/recipe.js +42 -73
- package/dist/recipe.js.map +1 -1
- package/dist/rpc/index.js +74 -115
- package/dist/rpc/index.js.map +1 -1
- package/dist/rpc/queue.js +71 -90
- package/dist/rpc/queue.js.map +1 -1
- package/dist/rpc/recipe.js +32 -57
- package/dist/rpc/recipe.js.map +1 -1
- package/dist/rpc/request/generate.js +4 -13
- package/dist/rpc/request/generate.js.map +1 -1
- package/dist/rpc/request/get-languages.js +2 -11
- package/dist/rpc/request/get-languages.js.map +1 -1
- package/dist/rpc/request/get-marketplace.js +9 -20
- package/dist/rpc/request/get-marketplace.js.map +1 -1
- package/dist/rpc/request/get-object.js +4 -13
- package/dist/rpc/request/get-object.js.map +1 -1
- package/dist/rpc/request/install-recipes.js +25 -36
- package/dist/rpc/request/install-recipes.js.map +1 -1
- package/dist/rpc/request/metrics.js +8 -17
- package/dist/rpc/request/metrics.js.map +1 -1
- package/dist/rpc/request/parse-project.js +36 -45
- package/dist/rpc/request/parse-project.js.map +1 -1
- package/dist/rpc/request/parse.js +5 -14
- package/dist/rpc/request/parse.js.map +1 -1
- package/dist/rpc/request/prepare-recipe.js +37 -52
- package/dist/rpc/request/prepare-recipe.js.map +1 -1
- package/dist/rpc/request/print.js +5 -14
- package/dist/rpc/request/print.js.map +1 -1
- package/dist/rpc/request/visit.js +56 -71
- package/dist/rpc/request/visit.js.map +1 -1
- package/dist/rpc/rewrite-rpc.js +70 -97
- package/dist/rpc/rewrite-rpc.js.map +1 -1
- package/dist/rpc/server.js +76 -89
- package/dist/rpc/server.js.map +1 -1
- package/dist/run.js +47 -66
- package/dist/run.js.map +1 -1
- package/dist/search/is-source-file.js +8 -19
- package/dist/search/is-source-file.js.map +1 -1
- package/dist/test/rewrite-test.js +154 -188
- package/dist/test/rewrite-test.js.map +1 -1
- package/dist/text/print.js +23 -38
- package/dist/text/print.js.map +1 -1
- package/dist/text/rpc.js +29 -44
- package/dist/text/rpc.js.map +1 -1
- package/dist/text/visitor.js +16 -33
- package/dist/text/visitor.js.map +1 -1
- package/dist/util.js +13 -24
- package/dist/util.js.map +1 -1
- package/dist/version.txt +1 -1
- package/dist/visitor.js +84 -115
- package/dist/visitor.js.map +1 -1
- package/dist/yaml/index.d.ts +2 -0
- package/dist/yaml/index.d.ts.map +1 -1
- package/dist/yaml/index.js +2 -0
- package/dist/yaml/index.js.map +1 -1
- package/dist/yaml/markers.d.ts +21 -0
- package/dist/yaml/markers.d.ts.map +1 -0
- package/dist/yaml/markers.js +37 -0
- package/dist/yaml/markers.js.map +1 -0
- package/dist/yaml/parser.d.ts.map +1 -1
- package/dist/yaml/parser.js +4 -1
- package/dist/yaml/parser.js.map +1 -1
- package/dist/yaml/print.d.ts +1 -1
- package/dist/yaml/print.d.ts.map +1 -1
- package/dist/yaml/print.js +175 -208
- package/dist/yaml/print.js.map +1 -1
- package/dist/yaml/rpc.js +154 -219
- package/dist/yaml/rpc.js.map +1 -1
- package/dist/yaml/visitor.js +78 -113
- package/dist/yaml/visitor.js.map +1 -1
- package/package.json +1 -1
- package/src/javascript/parser.ts +56 -14
- package/src/yaml/index.ts +2 -0
- package/src/yaml/markers.ts +70 -0
- package/src/yaml/parser.ts +5 -1
- package/src/yaml/print.ts +5 -2
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
exports.RemoveImport = void 0;
|
|
13
4
|
exports.maybeRemoveImport = maybeRemoveImport;
|
|
@@ -71,318 +62,308 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
|
|
|
71
62
|
* first remaining element to maintain proper spacing. Also preserves trailing space
|
|
72
63
|
* from the last element if it's removed.
|
|
73
64
|
*/
|
|
74
|
-
filterElementsWithPrefixPreservation(elements, shouldKeep, updatePrefix, _p) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
removedPrefix = undefined;
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
filtered.push(elem);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
else if (elem.element) {
|
|
95
|
-
// Store the prefix of the first removed element
|
|
96
|
-
if (filtered.length === 0 && !removedPrefix) {
|
|
97
|
-
removedPrefix = elem.element.prefix;
|
|
98
|
-
}
|
|
65
|
+
async filterElementsWithPrefixPreservation(elements, shouldKeep, updatePrefix, _p) {
|
|
66
|
+
const filtered = [];
|
|
67
|
+
let removedPrefix;
|
|
68
|
+
// Track the trailing space of the original last element
|
|
69
|
+
const originalLastElement = elements[elements.length - 1];
|
|
70
|
+
const originalTrailingSpace = originalLastElement === null || originalLastElement === void 0 ? void 0 : originalLastElement.after;
|
|
71
|
+
for (const elem of elements) {
|
|
72
|
+
if (elem.element && shouldKeep(elem.element)) {
|
|
73
|
+
// If we removed the previous element and this is the first kept element,
|
|
74
|
+
// apply the removed element's prefix to maintain formatting
|
|
75
|
+
if (removedPrefix && filtered.length === 0) {
|
|
76
|
+
const updatedElement = await updatePrefix(elem.element, removedPrefix);
|
|
77
|
+
filtered.push(Object.assign(Object.assign({}, elem), { element: updatedElement }));
|
|
78
|
+
removedPrefix = undefined;
|
|
99
79
|
}
|
|
100
80
|
else {
|
|
101
|
-
// Keep non-element entries (shouldn't happen but be safe)
|
|
102
81
|
filtered.push(elem);
|
|
103
82
|
}
|
|
104
83
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
84
|
+
else if (elem.element) {
|
|
85
|
+
// Store the prefix of the first removed element
|
|
86
|
+
if (filtered.length === 0 && !removedPrefix) {
|
|
87
|
+
removedPrefix = elem.element.prefix;
|
|
88
|
+
}
|
|
110
89
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
}
|
|
90
|
+
else {
|
|
91
|
+
// Keep non-element entries (shouldn't happen but be safe)
|
|
92
|
+
filtered.push(elem);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// If the original last element was removed and we have remaining elements,
|
|
96
|
+
// transfer its trailing space to the new last element
|
|
97
|
+
if (filtered.length > 0 && (originalLastElement === null || originalLastElement === void 0 ? void 0 : originalLastElement.element) && !shouldKeep(originalLastElement.element)) {
|
|
98
|
+
const lastIdx = filtered.length - 1;
|
|
99
|
+
filtered[lastIdx] = Object.assign(Object.assign({}, filtered[lastIdx]), { after: originalTrailingSpace });
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
filtered,
|
|
103
|
+
allRemoved: filtered.length === 0
|
|
104
|
+
};
|
|
116
105
|
}
|
|
117
106
|
/**
|
|
118
107
|
* Helper to update an import clause by removing specific bindings
|
|
119
108
|
*/
|
|
120
|
-
updateImportClause(jsImport, importClause, updateFn, p) {
|
|
121
|
-
return
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
}));
|
|
109
|
+
async updateImportClause(jsImport, importClause, updateFn, p) {
|
|
110
|
+
return this.produceJavaScript(jsImport, p, async (draft) => {
|
|
111
|
+
if (draft.importClause) {
|
|
112
|
+
draft.importClause = await this.produceJavaScript(importClause, p, async (clauseDraft) => await updateFn(clauseDraft));
|
|
113
|
+
}
|
|
127
114
|
});
|
|
128
115
|
}
|
|
129
|
-
visitJsCompilationUnit(compilationUnit, p) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
varFormatter.markRemoved(varDecl);
|
|
179
|
-
}
|
|
180
|
-
else {
|
|
181
|
-
const formattedVarDecl = varFormatter.processKept(result);
|
|
182
|
-
filteredVariables.push(Object.assign(Object.assign({}, v), { element: formattedVarDecl }));
|
|
183
|
-
}
|
|
116
|
+
async visitJsCompilationUnit(compilationUnit, p) {
|
|
117
|
+
// First, collect all used identifiers in the file
|
|
118
|
+
const usedIdentifiers = new Set();
|
|
119
|
+
const usedTypes = new Set();
|
|
120
|
+
// Traverse the AST to collect used identifiers
|
|
121
|
+
await this.collectUsedIdentifiers(compilationUnit, usedIdentifiers, usedTypes);
|
|
122
|
+
// Now process imports with knowledge of what's used
|
|
123
|
+
return this.produceJavaScript(compilationUnit, p, async (draft) => {
|
|
124
|
+
const formatter = new java_2.ElementRemovalFormatter(true); // Preserve file headers from first import
|
|
125
|
+
draft.statements = await (0, util_1.mapAsync)(compilationUnit.statements, async (stmt) => {
|
|
126
|
+
const statement = stmt.element;
|
|
127
|
+
// Handle ES6 imports
|
|
128
|
+
if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
|
|
129
|
+
const jsImport = statement;
|
|
130
|
+
const result = await this.processImport(jsImport, usedIdentifiers, usedTypes, p);
|
|
131
|
+
if (result === undefined) {
|
|
132
|
+
formatter.markRemoved(statement);
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
const finalResult = formatter.processKept(result);
|
|
136
|
+
return Object.assign(Object.assign({}, stmt), { element: finalResult });
|
|
137
|
+
}
|
|
138
|
+
// Handle CommonJS require statements
|
|
139
|
+
// Note: const fs = require() comes as J.VariableDeclarations
|
|
140
|
+
// Multi-variable declarations might come as JS.ScopedVariableDeclarations
|
|
141
|
+
if ((statement === null || statement === void 0 ? void 0 : statement.kind) === java_1.J.Kind.VariableDeclarations) {
|
|
142
|
+
const varDecl = statement;
|
|
143
|
+
const result = await this.processRequireFromVarDecls(varDecl, usedIdentifiers, p);
|
|
144
|
+
if (result === undefined) {
|
|
145
|
+
formatter.markRemoved(statement);
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
const finalResult = formatter.processKept(result);
|
|
149
|
+
return Object.assign(Object.assign({}, stmt), { element: finalResult });
|
|
150
|
+
}
|
|
151
|
+
// Handle JS.ScopedVariableDeclarations (multi-variable var/let/const)
|
|
152
|
+
if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.ScopedVariableDeclarations) {
|
|
153
|
+
const scopedVarDecl = statement;
|
|
154
|
+
// Scoped variable declarations contain a variables array where each element is a single-variable J.VariableDeclarations
|
|
155
|
+
const filteredVariables = [];
|
|
156
|
+
let hasChanges = false;
|
|
157
|
+
const varFormatter = new java_2.ElementRemovalFormatter(true); // Preserve file headers
|
|
158
|
+
for (const v of scopedVarDecl.variables) {
|
|
159
|
+
const varDecl = v.element;
|
|
160
|
+
if ((varDecl === null || varDecl === void 0 ? void 0 : varDecl.kind) === java_1.J.Kind.VariableDeclarations) {
|
|
161
|
+
const result = await this.processRequireFromVarDecls(varDecl, usedIdentifiers, p);
|
|
162
|
+
if (result === undefined) {
|
|
163
|
+
hasChanges = true;
|
|
164
|
+
varFormatter.markRemoved(varDecl);
|
|
184
165
|
}
|
|
185
166
|
else {
|
|
186
|
-
|
|
167
|
+
const formattedVarDecl = varFormatter.processKept(result);
|
|
168
|
+
filteredVariables.push(Object.assign(Object.assign({}, v), { element: formattedVarDecl }));
|
|
187
169
|
}
|
|
188
170
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
return undefined;
|
|
171
|
+
else {
|
|
172
|
+
filteredVariables.push(v);
|
|
192
173
|
}
|
|
193
|
-
const finalElement = hasChanges
|
|
194
|
-
? formatter.processKept(Object.assign(Object.assign({}, scopedVarDecl), { variables: filteredVariables }))
|
|
195
|
-
: formatter.processKept(statement);
|
|
196
|
-
return Object.assign(Object.assign({}, stmt), { element: finalElement });
|
|
197
|
-
}
|
|
198
|
-
// For any other statement type, apply prefix from removed elements
|
|
199
|
-
if (statement) {
|
|
200
|
-
const finalStatement = formatter.processKept(statement);
|
|
201
|
-
return Object.assign(Object.assign({}, stmt), { element: finalStatement });
|
|
202
174
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
175
|
+
if (filteredVariables.length === 0) {
|
|
176
|
+
formatter.markRemoved(statement);
|
|
177
|
+
return undefined;
|
|
178
|
+
}
|
|
179
|
+
const finalElement = hasChanges
|
|
180
|
+
? formatter.processKept(Object.assign(Object.assign({}, scopedVarDecl), { variables: filteredVariables }))
|
|
181
|
+
: formatter.processKept(statement);
|
|
182
|
+
return Object.assign(Object.assign({}, stmt), { element: finalElement });
|
|
183
|
+
}
|
|
184
|
+
// For any other statement type, apply prefix from removed elements
|
|
185
|
+
if (statement) {
|
|
186
|
+
const finalStatement = formatter.processKept(statement);
|
|
187
|
+
return Object.assign(Object.assign({}, stmt), { element: finalStatement });
|
|
188
|
+
}
|
|
189
|
+
return stmt;
|
|
190
|
+
});
|
|
191
|
+
// Filter out undefined (removed) statements
|
|
192
|
+
draft.statements = draft.statements.filter(s => s !== undefined);
|
|
193
|
+
draft.eof = await this.visitSpace(compilationUnit.eof, p);
|
|
209
194
|
});
|
|
210
195
|
}
|
|
211
|
-
processImport(jsImport, usedIdentifiers, usedTypes, p) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
196
|
+
async processImport(jsImport, usedIdentifiers, usedTypes, p) {
|
|
197
|
+
// Handle import-equals-require syntax: import util = require("util");
|
|
198
|
+
if (jsImport.initializer) {
|
|
199
|
+
return this.processImportEqualsRequire(jsImport, usedIdentifiers, usedTypes, p);
|
|
200
|
+
}
|
|
201
|
+
// Check if this import is from the target module
|
|
202
|
+
if (!this.isTargetModule(jsImport)) {
|
|
203
|
+
return jsImport;
|
|
204
|
+
}
|
|
205
|
+
const importClause = jsImport.importClause;
|
|
206
|
+
if (!importClause) {
|
|
207
|
+
// Side-effect import like: import 'module'
|
|
208
|
+
if (this.member === '*') {
|
|
209
|
+
return undefined; // Remove the entire import
|
|
210
|
+
}
|
|
211
|
+
return jsImport;
|
|
212
|
+
}
|
|
213
|
+
// Process default import
|
|
214
|
+
if (importClause.name) {
|
|
215
|
+
const defaultName = importClause.name.element;
|
|
216
|
+
if (defaultName && defaultName.kind === java_1.J.Kind.Identifier) {
|
|
217
|
+
const identifier = defaultName;
|
|
218
|
+
const name = identifier.simpleName;
|
|
219
|
+
// Check if we should remove this default import
|
|
220
|
+
let shouldRemove;
|
|
221
|
+
if (this.member === 'default') {
|
|
222
|
+
// Special case: member 'default' means remove any default import from the target module if unused
|
|
223
|
+
shouldRemove = !usedIdentifiers.has(name) && !usedTypes.has(name);
|
|
226
224
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
// If there are no named imports, remove the entire import
|
|
247
|
-
if (!importClause.namedBindings) {
|
|
248
|
-
return undefined;
|
|
225
|
+
else {
|
|
226
|
+
// Regular case: check if the import name matches the removal criteria
|
|
227
|
+
shouldRemove = this.shouldRemoveImport(name, usedIdentifiers, usedTypes);
|
|
228
|
+
}
|
|
229
|
+
if (shouldRemove) {
|
|
230
|
+
// If there are no named imports, remove the entire import
|
|
231
|
+
if (!importClause.namedBindings) {
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
// Otherwise, just remove the default import and fix spacing
|
|
235
|
+
return this.updateImportClause(jsImport, importClause, async (draft) => {
|
|
236
|
+
var _a;
|
|
237
|
+
draft.name = undefined;
|
|
238
|
+
// When removing the default import, we need to transfer its prefix to namedBindings
|
|
239
|
+
// to maintain proper spacing (the default import's prefix is typically empty)
|
|
240
|
+
if (draft.namedBindings && ((_a = importClause.name) === null || _a === void 0 ? void 0 : _a.element)) {
|
|
241
|
+
draft.namedBindings = await this.produceJava(draft.namedBindings, p, async (bindingsDraft) => {
|
|
242
|
+
bindingsDraft.prefix = importClause.name.element.prefix;
|
|
243
|
+
});
|
|
249
244
|
}
|
|
250
|
-
|
|
251
|
-
return this.updateImportClause(jsImport, importClause, (draft) => __awaiter(this, void 0, void 0, function* () {
|
|
252
|
-
var _a;
|
|
253
|
-
draft.name = undefined;
|
|
254
|
-
// When removing the default import, we need to transfer its prefix to namedBindings
|
|
255
|
-
// to maintain proper spacing (the default import's prefix is typically empty)
|
|
256
|
-
if (draft.namedBindings && ((_a = importClause.name) === null || _a === void 0 ? void 0 : _a.element)) {
|
|
257
|
-
draft.namedBindings = yield this.produceJava(draft.namedBindings, p, (bindingsDraft) => __awaiter(this, void 0, void 0, function* () {
|
|
258
|
-
bindingsDraft.prefix = importClause.name.element.prefix;
|
|
259
|
-
}));
|
|
260
|
-
}
|
|
261
|
-
}), p);
|
|
262
|
-
}
|
|
245
|
+
}, p);
|
|
263
246
|
}
|
|
264
247
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
return undefined;
|
|
281
|
-
}
|
|
282
|
-
return this.updateImportClause(jsImport, importClause, draft => {
|
|
283
|
-
draft.namedBindings = undefined;
|
|
284
|
-
}, p);
|
|
285
|
-
}
|
|
286
|
-
// Namespace is used, we can't remove individual members from it
|
|
287
|
-
}
|
|
288
|
-
else if (this.shouldRemoveImport(name, usedIdentifiers, usedTypes)) {
|
|
289
|
-
// If there's no default import, remove the entire import
|
|
248
|
+
}
|
|
249
|
+
// Process named imports
|
|
250
|
+
if (importClause.namedBindings) {
|
|
251
|
+
const namedBindings = importClause.namedBindings;
|
|
252
|
+
// Handle namespace import: import * as X from 'module'
|
|
253
|
+
if (namedBindings.kind === java_1.J.Kind.Identifier) {
|
|
254
|
+
const identifier = namedBindings;
|
|
255
|
+
const name = identifier.simpleName;
|
|
256
|
+
// When removing a specific member from a namespace import,
|
|
257
|
+
// we can only remove the entire namespace if it's not used
|
|
258
|
+
if (this.member !== undefined) {
|
|
259
|
+
// We're trying to remove a specific member from this namespace
|
|
260
|
+
// Check if the namespace itself is used
|
|
261
|
+
if (!usedIdentifiers.has(name) && !usedTypes.has(name)) {
|
|
262
|
+
// Namespace is not used, remove the entire import
|
|
290
263
|
if (!importClause.name) {
|
|
291
264
|
return undefined;
|
|
292
265
|
}
|
|
293
|
-
// Otherwise, just remove the namespace import
|
|
294
266
|
return this.updateImportClause(jsImport, importClause, draft => {
|
|
295
267
|
draft.namedBindings = undefined;
|
|
296
268
|
}, p);
|
|
297
269
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
270
|
+
// Namespace is used, we can't remove individual members from it
|
|
271
|
+
}
|
|
272
|
+
else if (this.shouldRemoveImport(name, usedIdentifiers, usedTypes)) {
|
|
273
|
+
// If there's no default import, remove the entire import
|
|
274
|
+
if (!importClause.name) {
|
|
275
|
+
return undefined;
|
|
276
|
+
}
|
|
277
|
+
// Otherwise, just remove the namespace import
|
|
278
|
+
return this.updateImportClause(jsImport, importClause, draft => {
|
|
279
|
+
draft.namedBindings = undefined;
|
|
280
|
+
}, p);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
else if (namedBindings.kind === tree_1.JS.Kind.Alias) {
|
|
284
|
+
// Handle import * as X from 'module' - represented as Alias with propertyName = "*"
|
|
285
|
+
const alias = namedBindings;
|
|
286
|
+
const aliasName = alias.alias.simpleName;
|
|
287
|
+
// When removing a specific member from a namespace import,
|
|
288
|
+
// we can only remove the entire namespace if it's not used
|
|
289
|
+
if (this.member !== undefined) {
|
|
290
|
+
// We're trying to remove a specific member from this namespace
|
|
291
|
+
// Check if the namespace itself is used
|
|
292
|
+
if (!usedIdentifiers.has(aliasName) && !usedTypes.has(aliasName)) {
|
|
293
|
+
// Namespace is not used, remove the entire import
|
|
321
294
|
if (!importClause.name) {
|
|
322
295
|
return undefined;
|
|
323
296
|
}
|
|
324
|
-
// Otherwise, just remove the namespace import
|
|
325
297
|
return this.updateImportClause(jsImport, importClause, draft => {
|
|
326
298
|
draft.namedBindings = undefined;
|
|
327
299
|
}, p);
|
|
328
300
|
}
|
|
301
|
+
// Namespace is used, we can't remove individual members from it
|
|
329
302
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if (updatedImports === undefined) {
|
|
335
|
-
// All named imports were removed
|
|
336
|
-
if (!importClause.name) {
|
|
337
|
-
// No default import either, remove the entire import
|
|
338
|
-
return undefined;
|
|
339
|
-
}
|
|
340
|
-
// Keep the import with just the default import
|
|
341
|
-
return this.updateImportClause(jsImport, importClause, draft => {
|
|
342
|
-
draft.namedBindings = undefined;
|
|
343
|
-
}, p);
|
|
303
|
+
else if (this.shouldRemoveImport(aliasName, usedIdentifiers, usedTypes)) {
|
|
304
|
+
// If there's no default import, remove the entire import
|
|
305
|
+
if (!importClause.name) {
|
|
306
|
+
return undefined;
|
|
344
307
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
308
|
+
// Otherwise, just remove the namespace import
|
|
309
|
+
return this.updateImportClause(jsImport, importClause, draft => {
|
|
310
|
+
draft.namedBindings = undefined;
|
|
311
|
+
}, p);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
// Handle named imports: import { a, b } from 'module'
|
|
315
|
+
if (namedBindings.kind === tree_1.JS.Kind.NamedImports) {
|
|
316
|
+
const namedImports = namedBindings;
|
|
317
|
+
const updatedImports = await this.processNamedImports(namedImports, usedIdentifiers, usedTypes, p);
|
|
318
|
+
if (updatedImports === undefined) {
|
|
319
|
+
// All named imports were removed
|
|
320
|
+
if (!importClause.name) {
|
|
321
|
+
// No default import either, remove the entire import
|
|
322
|
+
return undefined;
|
|
350
323
|
}
|
|
324
|
+
// Keep the import with just the default import
|
|
325
|
+
return this.updateImportClause(jsImport, importClause, draft => {
|
|
326
|
+
draft.namedBindings = undefined;
|
|
327
|
+
}, p);
|
|
328
|
+
}
|
|
329
|
+
else if (updatedImports !== namedImports) {
|
|
330
|
+
// Some named imports were removed
|
|
331
|
+
return this.updateImportClause(jsImport, importClause, draft => {
|
|
332
|
+
draft.namedBindings = updatedImports;
|
|
333
|
+
}, p);
|
|
351
334
|
}
|
|
352
335
|
}
|
|
353
|
-
|
|
354
|
-
|
|
336
|
+
}
|
|
337
|
+
return jsImport;
|
|
355
338
|
}
|
|
356
339
|
/**
|
|
357
340
|
* Process TypeScript import-equals-require syntax: import util = require("util");
|
|
358
341
|
* This is represented as a JS.Import with an initializer containing the require() call.
|
|
359
342
|
*/
|
|
360
|
-
processImportEqualsRequire(jsImport, usedIdentifiers, usedTypes, p) {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
if (!initializer || !this.isRequireCall(initializer)) {
|
|
365
|
-
return jsImport;
|
|
366
|
-
}
|
|
367
|
-
const methodInv = initializer;
|
|
368
|
-
const moduleName = this.getModuleNameFromRequire(methodInv);
|
|
369
|
-
if (!moduleName || !this.matchesTargetModule(moduleName)) {
|
|
370
|
-
return jsImport;
|
|
371
|
-
}
|
|
372
|
-
// Get the import name from the importClause
|
|
373
|
-
const importClause = jsImport.importClause;
|
|
374
|
-
if (!importClause || !importClause.name) {
|
|
375
|
-
// No name, this is unusual for import-equals-require
|
|
376
|
-
return jsImport;
|
|
377
|
-
}
|
|
378
|
-
const importedName = importClause.name.element.simpleName;
|
|
379
|
-
// For import-equals-require, we can only remove the entire import since
|
|
380
|
-
// it imports the whole module as a single identifier
|
|
381
|
-
if (this.shouldRemoveIdentifier(importedName, usedIdentifiers, usedTypes)) {
|
|
382
|
-
return undefined;
|
|
383
|
-
}
|
|
343
|
+
async processImportEqualsRequire(jsImport, usedIdentifiers, usedTypes, p) {
|
|
344
|
+
var _a;
|
|
345
|
+
const initializer = (_a = jsImport.initializer) === null || _a === void 0 ? void 0 : _a.element;
|
|
346
|
+
if (!initializer || !this.isRequireCall(initializer)) {
|
|
384
347
|
return jsImport;
|
|
385
|
-
}
|
|
348
|
+
}
|
|
349
|
+
const methodInv = initializer;
|
|
350
|
+
const moduleName = this.getModuleNameFromRequire(methodInv);
|
|
351
|
+
if (!moduleName || !this.matchesTargetModule(moduleName)) {
|
|
352
|
+
return jsImport;
|
|
353
|
+
}
|
|
354
|
+
// Get the import name from the importClause
|
|
355
|
+
const importClause = jsImport.importClause;
|
|
356
|
+
if (!importClause || !importClause.name) {
|
|
357
|
+
// No name, this is unusual for import-equals-require
|
|
358
|
+
return jsImport;
|
|
359
|
+
}
|
|
360
|
+
const importedName = importClause.name.element.simpleName;
|
|
361
|
+
// For import-equals-require, we can only remove the entire import since
|
|
362
|
+
// it imports the whole module as a single identifier
|
|
363
|
+
if (this.shouldRemoveIdentifier(importedName, usedIdentifiers, usedTypes)) {
|
|
364
|
+
return undefined;
|
|
365
|
+
}
|
|
366
|
+
return jsImport;
|
|
386
367
|
}
|
|
387
368
|
/**
|
|
388
369
|
* Check if a node is a require() method invocation
|
|
@@ -411,100 +392,96 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
|
|
|
411
392
|
// or we're checking if a specific binding is used)
|
|
412
393
|
return !usedIdentifiers.has(name) && !usedTypes.has(name);
|
|
413
394
|
}
|
|
414
|
-
processNamedImports(namedImports, usedIdentifiers, usedTypes, p) {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
return true; // Keep imports that don't match the member
|
|
432
|
-
}
|
|
433
|
-
else {
|
|
434
|
-
// We're removing based on the import name itself
|
|
435
|
-
return !this.shouldRemoveImport(importName, usedIdentifiers, usedTypes);
|
|
436
|
-
}
|
|
395
|
+
async processNamedImports(namedImports, usedIdentifiers, usedTypes, p) {
|
|
396
|
+
const { filtered, allRemoved } = await this.filterElementsWithPrefixPreservation(namedImports.elements.elements, (elem) => {
|
|
397
|
+
if (elem.kind === tree_1.JS.Kind.ImportSpecifier) {
|
|
398
|
+
const specifier = elem;
|
|
399
|
+
const importName = this.getImportName(specifier);
|
|
400
|
+
const aliasName = this.getImportAlias(specifier);
|
|
401
|
+
// For aliased imports, check if the alias is used
|
|
402
|
+
// For non-aliased imports, check if the import name is used
|
|
403
|
+
const nameToCheck = aliasName || importName;
|
|
404
|
+
// Check if we should remove this import
|
|
405
|
+
if (this.member !== undefined) {
|
|
406
|
+
// We're removing a specific member - check if this matches
|
|
407
|
+
if (this.member === importName) {
|
|
408
|
+
// This is the member we want to remove - check if it's used
|
|
409
|
+
return usedIdentifiers.has(nameToCheck) || usedTypes.has(nameToCheck);
|
|
410
|
+
}
|
|
411
|
+
return true; // Keep imports that don't match the member
|
|
437
412
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
return this.produceJavaScript(elem, p, (draft) => __awaiter(this, void 0, void 0, function* () {
|
|
442
|
-
draft.prefix = prefix;
|
|
443
|
-
}));
|
|
413
|
+
else {
|
|
414
|
+
// We're removing based on the import name itself
|
|
415
|
+
return !this.shouldRemoveImport(importName, usedIdentifiers, usedTypes);
|
|
444
416
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
417
|
+
}
|
|
418
|
+
return true; // Keep non-ImportSpecifier elements
|
|
419
|
+
}, async (elem, prefix) => {
|
|
420
|
+
if (elem.kind === tree_1.JS.Kind.ImportSpecifier) {
|
|
421
|
+
return this.produceJavaScript(elem, p, async (draft) => {
|
|
422
|
+
draft.prefix = prefix;
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
return elem;
|
|
426
|
+
}, p);
|
|
427
|
+
if (allRemoved) {
|
|
428
|
+
return undefined;
|
|
429
|
+
}
|
|
430
|
+
if (filtered.length === namedImports.elements.elements.length) {
|
|
431
|
+
return namedImports; // No changes
|
|
432
|
+
}
|
|
433
|
+
// Create updated named imports with filtered elements
|
|
434
|
+
return this.produceJavaScript(namedImports, p, async (draft) => {
|
|
435
|
+
draft.elements = Object.assign(Object.assign({}, namedImports.elements), { elements: filtered });
|
|
457
436
|
});
|
|
458
437
|
}
|
|
459
|
-
processRequireFromVarDecls(varDecls, usedIdentifiers, p) {
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
return undefined; // Remove the entire require statement
|
|
487
|
-
}
|
|
438
|
+
async processRequireFromVarDecls(varDecls, usedIdentifiers, p) {
|
|
439
|
+
var _a;
|
|
440
|
+
// Check if this is a require() call
|
|
441
|
+
if (varDecls.variables.length !== 1) {
|
|
442
|
+
return varDecls;
|
|
443
|
+
}
|
|
444
|
+
const namedVar = varDecls.variables[0].element;
|
|
445
|
+
if (!namedVar) {
|
|
446
|
+
return varDecls;
|
|
447
|
+
}
|
|
448
|
+
const initializer = (_a = namedVar.initializer) === null || _a === void 0 ? void 0 : _a.element;
|
|
449
|
+
if (!initializer || !this.isRequireCall(initializer)) {
|
|
450
|
+
return varDecls;
|
|
451
|
+
}
|
|
452
|
+
const methodInv = initializer;
|
|
453
|
+
// This is a require() statement
|
|
454
|
+
const pattern = namedVar.name;
|
|
455
|
+
if (!pattern) {
|
|
456
|
+
return varDecls;
|
|
457
|
+
}
|
|
458
|
+
// Handle: const fs = require('fs')
|
|
459
|
+
if (pattern.kind === java_1.J.Kind.Identifier) {
|
|
460
|
+
const varName = pattern.simpleName;
|
|
461
|
+
// For require() statements, check the module name from the require call
|
|
462
|
+
const moduleName = this.getModuleNameFromRequire(methodInv);
|
|
463
|
+
if (moduleName && this.matchesTargetModule(moduleName) && !usedIdentifiers.has(varName)) {
|
|
464
|
+
return undefined; // Remove the entire require statement
|
|
488
465
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
}));
|
|
504
|
-
}
|
|
466
|
+
}
|
|
467
|
+
// Handle: const { readFile } = require('fs')
|
|
468
|
+
if (pattern.kind === tree_1.JS.Kind.ObjectBindingPattern && this.member !== undefined) {
|
|
469
|
+
const objectPattern = pattern;
|
|
470
|
+
const updatedPattern = await this.processObjectBindingPattern(objectPattern, usedIdentifiers, p);
|
|
471
|
+
if (updatedPattern === undefined) {
|
|
472
|
+
return undefined; // Remove entire require
|
|
473
|
+
}
|
|
474
|
+
else if (updatedPattern !== objectPattern) {
|
|
475
|
+
// Update with filtered bindings
|
|
476
|
+
return this.produceJava(varDecls, p, async (draft) => {
|
|
477
|
+
const updatedNamedVar = await this.produceJava(namedVar, p, async (namedDraft) => {
|
|
478
|
+
namedDraft.name = updatedPattern;
|
|
479
|
+
});
|
|
480
|
+
draft.variables = [Object.assign(Object.assign({}, varDecls.variables[0]), { element: updatedNamedVar })];
|
|
481
|
+
});
|
|
505
482
|
}
|
|
506
|
-
|
|
507
|
-
|
|
483
|
+
}
|
|
484
|
+
return varDecls;
|
|
508
485
|
}
|
|
509
486
|
/**
|
|
510
487
|
* Get the module name from a require() call
|
|
@@ -521,40 +498,38 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
|
|
|
521
498
|
}
|
|
522
499
|
return (_b = firstArg.value) === null || _b === void 0 ? void 0 : _b.toString();
|
|
523
500
|
}
|
|
524
|
-
processObjectBindingPattern(pattern, usedIdentifiers, p) {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
draft.bindings = Object.assign(Object.assign({}, pattern.bindings), { elements: filtered });
|
|
557
|
-
}));
|
|
501
|
+
async processObjectBindingPattern(pattern, usedIdentifiers, p) {
|
|
502
|
+
const { filtered, allRemoved } = await this.filterElementsWithPrefixPreservation(pattern.bindings.elements, (elem) => {
|
|
503
|
+
if (elem.kind === tree_1.JS.Kind.BindingElement) {
|
|
504
|
+
const name = this.getBindingElementName(elem);
|
|
505
|
+
return !this.shouldRemoveImport(name, usedIdentifiers, new Set());
|
|
506
|
+
}
|
|
507
|
+
else if (elem.kind === java_1.J.Kind.Identifier) {
|
|
508
|
+
const name = elem.simpleName;
|
|
509
|
+
return !this.shouldRemoveImport(name, usedIdentifiers, new Set());
|
|
510
|
+
}
|
|
511
|
+
return true; // Keep other element types
|
|
512
|
+
}, async (elem, prefix) => {
|
|
513
|
+
if (elem.kind === java_1.J.Kind.Identifier) {
|
|
514
|
+
return this.produceJava(elem, p, async (draft) => {
|
|
515
|
+
draft.prefix = prefix;
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
else if (elem.kind === tree_1.JS.Kind.BindingElement) {
|
|
519
|
+
return this.produceJavaScript(elem, p, async (draft) => {
|
|
520
|
+
draft.prefix = prefix;
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
return elem;
|
|
524
|
+
}, p);
|
|
525
|
+
if (allRemoved) {
|
|
526
|
+
return undefined;
|
|
527
|
+
}
|
|
528
|
+
if (filtered.length === pattern.bindings.elements.length) {
|
|
529
|
+
return pattern;
|
|
530
|
+
}
|
|
531
|
+
return this.produceJavaScript(pattern, p, async (draft) => {
|
|
532
|
+
draft.bindings = Object.assign(Object.assign({}, pattern.bindings), { elements: filtered });
|
|
558
533
|
});
|
|
559
534
|
}
|
|
560
535
|
getImportName(specifier) {
|
|
@@ -623,405 +598,395 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
|
|
|
623
598
|
/**
|
|
624
599
|
* Helper to traverse parameters from various node types
|
|
625
600
|
*/
|
|
626
|
-
traverseParameters(params, usedIdentifiers, usedTypes) {
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
yield this.collectUsedIdentifiers(elem, usedIdentifiers, usedTypes);
|
|
635
|
-
}
|
|
601
|
+
async traverseParameters(params, usedIdentifiers, usedTypes) {
|
|
602
|
+
if (!params || typeof params !== 'object')
|
|
603
|
+
return;
|
|
604
|
+
if (Array.isArray(params)) {
|
|
605
|
+
for (const p of params) {
|
|
606
|
+
// Array elements might be RightPadded, so unwrap them
|
|
607
|
+
const elem = p.element || p;
|
|
608
|
+
await this.collectUsedIdentifiers(elem, usedIdentifiers, usedTypes);
|
|
636
609
|
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
610
|
+
}
|
|
611
|
+
else if (params.elements) {
|
|
612
|
+
for (const p of params.elements) {
|
|
613
|
+
if (p.element) {
|
|
614
|
+
await this.collectUsedIdentifiers(p.element, usedIdentifiers, usedTypes);
|
|
642
615
|
}
|
|
643
616
|
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
617
|
+
}
|
|
618
|
+
else if (params.parameters) {
|
|
619
|
+
for (const p of params.parameters) {
|
|
620
|
+
const elem = p.element || p;
|
|
621
|
+
await this.collectUsedIdentifiers(elem, usedIdentifiers, usedTypes);
|
|
649
622
|
}
|
|
650
|
-
}
|
|
623
|
+
}
|
|
651
624
|
}
|
|
652
625
|
/**
|
|
653
626
|
* Helper to traverse statements from various node types
|
|
654
627
|
*/
|
|
655
|
-
traverseStatements(statements, usedIdentifiers, usedTypes) {
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
yield this.collectUsedIdentifiers(element, usedIdentifiers, usedTypes);
|
|
664
|
-
}
|
|
628
|
+
async traverseStatements(statements, usedIdentifiers, usedTypes) {
|
|
629
|
+
if (!statements)
|
|
630
|
+
return;
|
|
631
|
+
if (Array.isArray(statements)) {
|
|
632
|
+
for (const stmt of statements) {
|
|
633
|
+
const element = stmt.element || stmt;
|
|
634
|
+
if (element) {
|
|
635
|
+
await this.collectUsedIdentifiers(element, usedIdentifiers, usedTypes);
|
|
665
636
|
}
|
|
666
637
|
}
|
|
667
|
-
}
|
|
638
|
+
}
|
|
668
639
|
}
|
|
669
640
|
/**
|
|
670
641
|
* Helper to check for type expressions and collect type usage
|
|
671
642
|
*/
|
|
672
|
-
checkTypeExpression(node, usedTypes) {
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
}
|
|
677
|
-
});
|
|
643
|
+
async checkTypeExpression(node, usedTypes) {
|
|
644
|
+
if (node.typeExpression) {
|
|
645
|
+
await this.collectTypeUsage(node.typeExpression, usedTypes);
|
|
646
|
+
}
|
|
678
647
|
}
|
|
679
|
-
collectUsedIdentifiers(node, usedIdentifiers, usedTypes) {
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
yield this.collectUsedIdentifiers(v.element.initializer.element, usedIdentifiers, usedTypes);
|
|
697
|
-
}
|
|
648
|
+
async collectUsedIdentifiers(node, usedIdentifiers, usedTypes) {
|
|
649
|
+
// This is a simplified version - in a real implementation,
|
|
650
|
+
// we'd need to traverse the entire AST and collect all identifier usages
|
|
651
|
+
// For now, we'll implement a basic traversal
|
|
652
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _q, _r;
|
|
653
|
+
if (node.kind === java_1.J.Kind.Identifier) {
|
|
654
|
+
const identifier = node;
|
|
655
|
+
usedIdentifiers.add(identifier.simpleName);
|
|
656
|
+
}
|
|
657
|
+
else if (node.kind === java_1.J.Kind.VariableDeclarations) {
|
|
658
|
+
const varDecls = node;
|
|
659
|
+
// Check the type expression on the VariableDeclarations itself
|
|
660
|
+
await this.checkTypeExpression(varDecls, usedTypes);
|
|
661
|
+
for (const v of varDecls.variables) {
|
|
662
|
+
// Check the initializer
|
|
663
|
+
if ((_a = v.element.initializer) === null || _a === void 0 ? void 0 : _a.element) {
|
|
664
|
+
await this.collectUsedIdentifiers(v.element.initializer.element, usedIdentifiers, usedTypes);
|
|
698
665
|
}
|
|
699
666
|
}
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
}
|
|
709
|
-
else if (((_f = (_e = methodInv.select) === null || _e === void 0 ? void 0 : _e.element) === null || _f === void 0 ? void 0 : _f.kind) === java_1.J.Kind.Identifier) {
|
|
710
|
-
// Direct identifier like fs in fs.method() - though this is rare
|
|
711
|
-
usedIdentifiers.add(methodInv.select.element.simpleName);
|
|
667
|
+
}
|
|
668
|
+
else if (node.kind === java_1.J.Kind.MethodInvocation) {
|
|
669
|
+
const methodInv = node;
|
|
670
|
+
// Check if this is a member access pattern like fs.readFileSync
|
|
671
|
+
if (((_c = (_b = methodInv.select) === null || _b === void 0 ? void 0 : _b.element) === null || _c === void 0 ? void 0 : _c.kind) === java_1.J.Kind.FieldAccess) {
|
|
672
|
+
const fieldAccess = methodInv.select.element;
|
|
673
|
+
if (((_d = fieldAccess.target) === null || _d === void 0 ? void 0 : _d.kind) === java_1.J.Kind.Identifier) {
|
|
674
|
+
usedIdentifiers.add(fieldAccess.target.simpleName);
|
|
712
675
|
}
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
676
|
+
}
|
|
677
|
+
else if (((_f = (_e = methodInv.select) === null || _e === void 0 ? void 0 : _e.element) === null || _f === void 0 ? void 0 : _f.kind) === java_1.J.Kind.Identifier) {
|
|
678
|
+
// Direct identifier like fs in fs.method() - though this is rare
|
|
679
|
+
usedIdentifiers.add(methodInv.select.element.simpleName);
|
|
680
|
+
}
|
|
681
|
+
else if (!methodInv.select) {
|
|
682
|
+
// No select means this is a direct function call like isArray()
|
|
683
|
+
// Only in this case should we add the method name as a used identifier
|
|
684
|
+
if (methodInv.name && methodInv.name.kind === java_1.J.Kind.Identifier) {
|
|
685
|
+
usedIdentifiers.add(methodInv.name.simpleName);
|
|
719
686
|
}
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
687
|
+
}
|
|
688
|
+
// Note: We don't add method names for calls like Array.isArray() or obj.method()
|
|
689
|
+
// because those are methods on objects, not standalone imported functions
|
|
690
|
+
// Recursively check arguments
|
|
691
|
+
if (methodInv.arguments) {
|
|
692
|
+
for (const arg of methodInv.arguments.elements) {
|
|
693
|
+
if (arg.element) {
|
|
694
|
+
await this.collectUsedIdentifiers(arg.element, usedIdentifiers, usedTypes);
|
|
728
695
|
}
|
|
729
696
|
}
|
|
730
|
-
// Check select (object being called on)
|
|
731
|
-
if ((_g = methodInv.select) === null || _g === void 0 ? void 0 : _g.element) {
|
|
732
|
-
yield this.collectUsedIdentifiers(methodInv.select.element, usedIdentifiers, usedTypes);
|
|
733
|
-
}
|
|
734
697
|
}
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
usedIdentifiers.add(memberRef.containing.element.simpleName);
|
|
739
|
-
}
|
|
698
|
+
// Check select (object being called on)
|
|
699
|
+
if ((_g = methodInv.select) === null || _g === void 0 ? void 0 : _g.element) {
|
|
700
|
+
await this.collectUsedIdentifiers(methodInv.select.element, usedIdentifiers, usedTypes);
|
|
740
701
|
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
702
|
+
}
|
|
703
|
+
else if (node.kind === java_1.J.Kind.MemberReference) {
|
|
704
|
+
const memberRef = node;
|
|
705
|
+
if (memberRef.containing && ((_h = memberRef.containing.element) === null || _h === void 0 ? void 0 : _h.kind) === java_1.J.Kind.Identifier) {
|
|
706
|
+
usedIdentifiers.add(memberRef.containing.element.simpleName);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
else if (node.kind === java_1.J.Kind.FieldAccess) {
|
|
710
|
+
// Handle field access like fs.readFileSync
|
|
711
|
+
const fieldAccess = node;
|
|
712
|
+
if (((_j = fieldAccess.target) === null || _j === void 0 ? void 0 : _j.kind) === java_1.J.Kind.Identifier) {
|
|
713
|
+
usedIdentifiers.add(fieldAccess.target.simpleName);
|
|
751
714
|
}
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
715
|
+
// Recursively check the target
|
|
716
|
+
if (fieldAccess.target) {
|
|
717
|
+
await this.collectUsedIdentifiers(fieldAccess.target, usedIdentifiers, usedTypes);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
else if (node.kind === tree_1.JS.Kind.CompilationUnit) {
|
|
721
|
+
const cu = node;
|
|
722
|
+
for (const stmt of cu.statements) {
|
|
723
|
+
if (stmt.element && stmt.element.kind !== tree_1.JS.Kind.Import) {
|
|
724
|
+
// Skip require() statements at the top level
|
|
725
|
+
if (stmt.element.kind === java_1.J.Kind.VariableDeclarations) {
|
|
726
|
+
const varDecls = stmt.element;
|
|
727
|
+
// Check if this is a require() statement
|
|
728
|
+
let isRequire = false;
|
|
729
|
+
for (const v of varDecls.variables) {
|
|
730
|
+
const namedVar = v.element;
|
|
731
|
+
if (((_l = (_k = namedVar === null || namedVar === void 0 ? void 0 : namedVar.initializer) === null || _k === void 0 ? void 0 : _k.element) === null || _l === void 0 ? void 0 : _l.kind) === java_1.J.Kind.MethodInvocation) {
|
|
732
|
+
const methodInv = namedVar.initializer.element;
|
|
733
|
+
if (((_m = methodInv.name) === null || _m === void 0 ? void 0 : _m.kind) === java_1.J.Kind.Identifier &&
|
|
734
|
+
methodInv.name.simpleName === 'require') {
|
|
735
|
+
isRequire = true;
|
|
736
|
+
break;
|
|
770
737
|
}
|
|
771
738
|
}
|
|
772
|
-
if (!isRequire) {
|
|
773
|
-
// Not a require statement, process normally
|
|
774
|
-
yield this.collectUsedIdentifiers(stmt.element, usedIdentifiers, usedTypes);
|
|
775
|
-
}
|
|
776
739
|
}
|
|
777
|
-
|
|
778
|
-
//
|
|
779
|
-
|
|
740
|
+
if (!isRequire) {
|
|
741
|
+
// Not a require statement, process normally
|
|
742
|
+
await this.collectUsedIdentifiers(stmt.element, usedIdentifiers, usedTypes);
|
|
780
743
|
}
|
|
781
744
|
}
|
|
745
|
+
else if (stmt.element.kind !== tree_1.JS.Kind.ScopedVariableDeclarations) {
|
|
746
|
+
// Process other non-import, non-require statements normally
|
|
747
|
+
await this.collectUsedIdentifiers(stmt.element, usedIdentifiers, usedTypes);
|
|
748
|
+
}
|
|
782
749
|
}
|
|
783
750
|
}
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
751
|
+
}
|
|
752
|
+
else if (node.kind === java_1.J.Kind.Return) {
|
|
753
|
+
// Handle return statements
|
|
754
|
+
const returnStmt = node;
|
|
755
|
+
if (returnStmt.expression) {
|
|
756
|
+
await this.collectUsedIdentifiers(returnStmt.expression, usedIdentifiers, usedTypes);
|
|
790
757
|
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
758
|
+
}
|
|
759
|
+
else if (node.kind === java_1.J.Kind.Block) {
|
|
760
|
+
const block = node;
|
|
761
|
+
for (const stmt of block.statements) {
|
|
762
|
+
if (stmt.element) {
|
|
763
|
+
await this.collectUsedIdentifiers(stmt.element, usedIdentifiers, usedTypes);
|
|
797
764
|
}
|
|
798
765
|
}
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
766
|
+
}
|
|
767
|
+
else if (node.kind === java_1.J.Kind.MethodDeclaration) {
|
|
768
|
+
const method = node;
|
|
769
|
+
// Check parameters for type usage
|
|
770
|
+
if (method.parameters) {
|
|
771
|
+
for (const param of method.parameters.elements) {
|
|
772
|
+
// Parameters can be various types, handle them recursively
|
|
773
|
+
if (param.element) {
|
|
774
|
+
await this.collectUsedIdentifiers(param.element, usedIdentifiers, usedTypes);
|
|
808
775
|
}
|
|
809
776
|
}
|
|
810
|
-
// Check body
|
|
811
|
-
if (method.body) {
|
|
812
|
-
yield this.collectUsedIdentifiers(method.body, usedIdentifiers, usedTypes);
|
|
813
|
-
}
|
|
814
777
|
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
if (typeOf.expression) {
|
|
819
|
-
yield this.collectUsedIdentifiers(typeOf.expression, usedIdentifiers, usedTypes);
|
|
820
|
-
}
|
|
778
|
+
// Check body
|
|
779
|
+
if (method.body) {
|
|
780
|
+
await this.collectUsedIdentifiers(method.body, usedIdentifiers, usedTypes);
|
|
821
781
|
}
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
782
|
+
}
|
|
783
|
+
else if (node.kind === tree_1.JS.Kind.TypeOf) {
|
|
784
|
+
// Handle typeof expressions like: typeof util
|
|
785
|
+
const typeOf = node;
|
|
786
|
+
if (typeOf.expression) {
|
|
787
|
+
await this.collectUsedIdentifiers(typeOf.expression, usedIdentifiers, usedTypes);
|
|
828
788
|
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
}
|
|
836
|
-
if (node.initializer) {
|
|
837
|
-
yield this.collectUsedIdentifiers(node.initializer, usedIdentifiers, usedTypes);
|
|
838
|
-
}
|
|
789
|
+
}
|
|
790
|
+
else if (node.kind === tree_1.JS.Kind.TypeQuery) {
|
|
791
|
+
// Handle typeof type queries like: const x: typeof util
|
|
792
|
+
const typeQuery = node;
|
|
793
|
+
if (typeQuery.typeExpression) {
|
|
794
|
+
await this.collectUsedIdentifiers(typeQuery.typeExpression, usedIdentifiers, usedTypes);
|
|
839
795
|
}
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
yield this.collectUsedIdentifiers(func.lambda, usedIdentifiers, usedTypes);
|
|
848
|
-
}
|
|
849
|
-
if (func.body) {
|
|
850
|
-
yield this.collectUsedIdentifiers(func.body, usedIdentifiers, usedTypes);
|
|
851
|
-
}
|
|
796
|
+
}
|
|
797
|
+
else if (node.typeExpression) {
|
|
798
|
+
// Handle nodes with type expressions (parameters, variables, etc.)
|
|
799
|
+
await this.checkTypeExpression(node, usedTypes);
|
|
800
|
+
// Continue traversing other parts
|
|
801
|
+
if (node.name) {
|
|
802
|
+
await this.collectUsedIdentifiers(node.name, usedIdentifiers, usedTypes);
|
|
852
803
|
}
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
if ((_o = lambda.parameters) === null || _o === void 0 ? void 0 : _o.parameters) {
|
|
856
|
-
for (const param of lambda.parameters.parameters) {
|
|
857
|
-
if (param.element) {
|
|
858
|
-
yield this.collectUsedIdentifiers(param.element, usedIdentifiers, usedTypes);
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
if (lambda.body) {
|
|
863
|
-
yield this.collectUsedIdentifiers(lambda.body, usedIdentifiers, usedTypes);
|
|
864
|
-
}
|
|
804
|
+
if (node.initializer) {
|
|
805
|
+
await this.collectUsedIdentifiers(node.initializer, usedIdentifiers, usedTypes);
|
|
865
806
|
}
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
807
|
+
}
|
|
808
|
+
else if (node.kind === tree_1.JS.Kind.ArrowFunction || node.kind === java_1.J.Kind.Lambda) {
|
|
809
|
+
// Handle arrow functions and lambdas
|
|
810
|
+
const func = node;
|
|
811
|
+
if (func.parameters) {
|
|
812
|
+
await this.collectUsedIdentifiers(func.parameters, usedIdentifiers, usedTypes);
|
|
813
|
+
}
|
|
814
|
+
if (func.lambda) {
|
|
815
|
+
await this.collectUsedIdentifiers(func.lambda, usedIdentifiers, usedTypes);
|
|
816
|
+
}
|
|
817
|
+
if (func.body) {
|
|
818
|
+
await this.collectUsedIdentifiers(func.body, usedIdentifiers, usedTypes);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
else if (node.kind === java_1.J.Kind.Lambda) {
|
|
822
|
+
const lambda = node;
|
|
823
|
+
if ((_o = lambda.parameters) === null || _o === void 0 ? void 0 : _o.parameters) {
|
|
824
|
+
for (const param of lambda.parameters.parameters) {
|
|
825
|
+
if (param.element) {
|
|
826
|
+
await this.collectUsedIdentifiers(param.element, usedIdentifiers, usedTypes);
|
|
883
827
|
}
|
|
884
828
|
}
|
|
885
829
|
}
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
const embedded = node;
|
|
889
|
-
// The expression is wrapped in RightPadded, so unwrap it
|
|
890
|
-
const expr = ((_q = embedded.expression) === null || _q === void 0 ? void 0 : _q.element) || embedded.expression;
|
|
891
|
-
if (expr) {
|
|
892
|
-
yield this.collectUsedIdentifiers(expr, usedIdentifiers, usedTypes);
|
|
893
|
-
}
|
|
830
|
+
if (lambda.body) {
|
|
831
|
+
await this.collectUsedIdentifiers(lambda.body, usedIdentifiers, usedTypes);
|
|
894
832
|
}
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
833
|
+
}
|
|
834
|
+
else if (node.kind === tree_1.JS.Kind.JsxTag) {
|
|
835
|
+
// Handle JSX tags like <div>content</div>
|
|
836
|
+
const jsxTag = node;
|
|
837
|
+
// Check attributes
|
|
838
|
+
if (jsxTag.attributes) {
|
|
839
|
+
for (const attr of jsxTag.attributes) {
|
|
840
|
+
if (attr.element) {
|
|
841
|
+
await this.collectUsedIdentifiers(attr.element, usedIdentifiers, usedTypes);
|
|
842
|
+
}
|
|
900
843
|
}
|
|
901
844
|
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
const
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
845
|
+
// Check children
|
|
846
|
+
if (jsxTag.children) {
|
|
847
|
+
for (const child of jsxTag.children) {
|
|
848
|
+
if (child) {
|
|
849
|
+
await this.collectUsedIdentifiers(child, usedIdentifiers, usedTypes);
|
|
850
|
+
}
|
|
908
851
|
}
|
|
909
852
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
853
|
+
}
|
|
854
|
+
else if (node.kind === tree_1.JS.Kind.JsxEmbeddedExpression) {
|
|
855
|
+
// Handle JSX embedded expressions like {React.version}
|
|
856
|
+
const embedded = node;
|
|
857
|
+
// The expression is wrapped in RightPadded, so unwrap it
|
|
858
|
+
const expr = ((_q = embedded.expression) === null || _q === void 0 ? void 0 : _q.element) || embedded.expression;
|
|
859
|
+
if (expr) {
|
|
860
|
+
await this.collectUsedIdentifiers(expr, usedIdentifiers, usedTypes);
|
|
913
861
|
}
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
862
|
+
}
|
|
863
|
+
else if (node.kind === tree_1.JS.Kind.JsxAttribute) {
|
|
864
|
+
// Handle JSX attributes like onClick={handler}
|
|
865
|
+
const jsxAttr = node;
|
|
866
|
+
if (jsxAttr.value) {
|
|
867
|
+
await this.collectUsedIdentifiers(jsxAttr.value, usedIdentifiers, usedTypes);
|
|
917
868
|
}
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
869
|
+
}
|
|
870
|
+
else if (node.kind === tree_1.JS.Kind.TypeDeclaration) {
|
|
871
|
+
// Handle type alias declarations like: type Props = { children: React.ReactNode }
|
|
872
|
+
const typeDecl = node;
|
|
873
|
+
// The initializer contains the type expression (the right side of the =)
|
|
874
|
+
if ((_r = typeDecl.initializer) === null || _r === void 0 ? void 0 : _r.element) {
|
|
875
|
+
await this.collectTypeUsage(typeDecl.initializer.element, usedTypes);
|
|
925
876
|
}
|
|
926
|
-
}
|
|
877
|
+
}
|
|
878
|
+
else if (node.statements) {
|
|
879
|
+
// Generic handler for nodes with statements
|
|
880
|
+
await this.traverseStatements(node.statements, usedIdentifiers, usedTypes);
|
|
881
|
+
}
|
|
882
|
+
else if (node.body) {
|
|
883
|
+
// Generic handler for nodes with body
|
|
884
|
+
await this.collectUsedIdentifiers(node.body, usedIdentifiers, usedTypes);
|
|
885
|
+
}
|
|
886
|
+
else if (node.parameters) {
|
|
887
|
+
// Handle anything with parameters (functions, methods, etc.)
|
|
888
|
+
await this.traverseParameters(node.parameters, usedIdentifiers, usedTypes);
|
|
889
|
+
// Continue with the body if it exists
|
|
890
|
+
if (node.body) {
|
|
891
|
+
await this.collectUsedIdentifiers(node.body, usedIdentifiers, usedTypes);
|
|
892
|
+
}
|
|
893
|
+
}
|
|
927
894
|
}
|
|
928
|
-
collectTypeUsage(typeExpr, usedTypes) {
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
yield this.collectTypeUsage(typeParam.element, usedTypes);
|
|
945
|
-
}
|
|
895
|
+
async collectTypeUsage(typeExpr, usedTypes) {
|
|
896
|
+
var _a;
|
|
897
|
+
if (typeExpr.kind === java_1.J.Kind.Identifier) {
|
|
898
|
+
usedTypes.add(typeExpr.simpleName);
|
|
899
|
+
}
|
|
900
|
+
else if (typeExpr.kind === java_1.J.Kind.ParameterizedType) {
|
|
901
|
+
const paramType = typeExpr;
|
|
902
|
+
// First, collect usage from the base type (e.g., React.Ref from React.Ref<T>)
|
|
903
|
+
if (paramType.class) {
|
|
904
|
+
await this.collectTypeUsage(paramType.class, usedTypes);
|
|
905
|
+
}
|
|
906
|
+
// Then collect usage from type parameters (e.g., HTMLButtonElement from React.Ref<HTMLButtonElement>)
|
|
907
|
+
if (paramType.typeParameters) {
|
|
908
|
+
for (const typeParam of paramType.typeParameters.elements) {
|
|
909
|
+
if (typeParam.element) {
|
|
910
|
+
await this.collectTypeUsage(typeParam.element, usedTypes);
|
|
946
911
|
}
|
|
947
912
|
}
|
|
948
913
|
}
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
else if (fieldAccess.target) {
|
|
956
|
-
// Recursively handle nested field accesses
|
|
957
|
-
yield this.collectTypeUsage(fieldAccess.target, usedTypes);
|
|
958
|
-
}
|
|
914
|
+
}
|
|
915
|
+
else if (typeExpr.kind === java_1.J.Kind.FieldAccess) {
|
|
916
|
+
// Handle qualified names in type positions like React.Ref
|
|
917
|
+
const fieldAccess = typeExpr;
|
|
918
|
+
if (((_a = fieldAccess.target) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.Identifier) {
|
|
919
|
+
usedTypes.add(fieldAccess.target.simpleName);
|
|
959
920
|
}
|
|
960
|
-
else if (
|
|
961
|
-
//
|
|
962
|
-
|
|
963
|
-
for (const typeElem of intersection.types) {
|
|
964
|
-
if (typeElem.element) {
|
|
965
|
-
yield this.collectTypeUsage(typeElem.element, usedTypes);
|
|
966
|
-
}
|
|
967
|
-
}
|
|
921
|
+
else if (fieldAccess.target) {
|
|
922
|
+
// Recursively handle nested field accesses
|
|
923
|
+
await this.collectTypeUsage(fieldAccess.target, usedTypes);
|
|
968
924
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
yield this.collectUsedIdentifiers(stmt.element, new Set(), usedTypes);
|
|
977
|
-
}
|
|
925
|
+
}
|
|
926
|
+
else if (typeExpr.kind === tree_1.JS.Kind.Intersection) {
|
|
927
|
+
// Handle intersection types like ButtonProps & { ref?: React.Ref<HTMLButtonElement> }
|
|
928
|
+
const intersection = typeExpr;
|
|
929
|
+
for (const typeElem of intersection.types) {
|
|
930
|
+
if (typeElem.element) {
|
|
931
|
+
await this.collectTypeUsage(typeElem.element, usedTypes);
|
|
978
932
|
}
|
|
979
933
|
}
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
934
|
+
}
|
|
935
|
+
else if (typeExpr.kind === tree_1.JS.Kind.TypeLiteral) {
|
|
936
|
+
// Handle type literals like { ref?: React.Ref<HTMLButtonElement> }
|
|
937
|
+
const typeLiteral = typeExpr;
|
|
938
|
+
// TypeLiteral members are in a Block, which contains statements
|
|
939
|
+
for (const stmt of typeLiteral.members.statements) {
|
|
940
|
+
if (stmt.element) {
|
|
941
|
+
// Each statement is typically a VariableDeclarations representing a property
|
|
942
|
+
await this.collectUsedIdentifiers(stmt.element, new Set(), usedTypes);
|
|
985
943
|
}
|
|
986
944
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
if (typeOf.expression.kind === java_1.J.Kind.Identifier) {
|
|
994
|
-
usedTypes.add(typeOf.expression.simpleName);
|
|
995
|
-
}
|
|
996
|
-
else {
|
|
997
|
-
yield this.collectTypeUsage(typeOf.expression, usedTypes);
|
|
998
|
-
}
|
|
999
|
-
}
|
|
945
|
+
}
|
|
946
|
+
else if (typeExpr.kind === tree_1.JS.Kind.TypeQuery) {
|
|
947
|
+
// Handle typeof type queries like: const x: typeof util
|
|
948
|
+
const typeQuery = typeExpr;
|
|
949
|
+
if (typeQuery.typeExpression) {
|
|
950
|
+
await this.collectTypeUsage(typeQuery.typeExpression, usedTypes);
|
|
1000
951
|
}
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
952
|
+
}
|
|
953
|
+
else if (typeExpr.kind === tree_1.JS.Kind.TypeOf) {
|
|
954
|
+
// Handle typeof expressions in types
|
|
955
|
+
const typeOf = typeExpr;
|
|
956
|
+
if (typeOf.expression) {
|
|
957
|
+
// For typeof expressions, the expression contains the identifier
|
|
958
|
+
// Add it to usedTypes since it's used in a type context
|
|
959
|
+
if (typeOf.expression.kind === java_1.J.Kind.Identifier) {
|
|
960
|
+
usedTypes.add(typeOf.expression.simpleName);
|
|
1006
961
|
}
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
// Handle TypeInfo which contains type identifiers
|
|
1010
|
-
const typeInfo = typeExpr;
|
|
1011
|
-
if (typeInfo.typeIdentifier) {
|
|
1012
|
-
yield this.collectTypeUsage(typeInfo.typeIdentifier, usedTypes);
|
|
962
|
+
else {
|
|
963
|
+
await this.collectTypeUsage(typeOf.expression, usedTypes);
|
|
1013
964
|
}
|
|
1014
965
|
}
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
966
|
+
}
|
|
967
|
+
else if (typeExpr.kind === tree_1.JS.Kind.TypeTreeExpression) {
|
|
968
|
+
// Handle TypeTreeExpression which wraps type identifiers
|
|
969
|
+
const typeTree = typeExpr;
|
|
970
|
+
if (typeTree.expression) {
|
|
971
|
+
await this.collectTypeUsage(typeTree.expression, usedTypes);
|
|
1018
972
|
}
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
973
|
+
}
|
|
974
|
+
else if (typeExpr.kind === tree_1.JS.Kind.TypeInfo) {
|
|
975
|
+
// Handle TypeInfo which contains type identifiers
|
|
976
|
+
const typeInfo = typeExpr;
|
|
977
|
+
if (typeInfo.typeIdentifier) {
|
|
978
|
+
await this.collectTypeUsage(typeInfo.typeIdentifier, usedTypes);
|
|
1022
979
|
}
|
|
1023
|
-
|
|
1024
|
-
|
|
980
|
+
}
|
|
981
|
+
else if (typeExpr.expression) {
|
|
982
|
+
// Generic handler for nodes with expression property
|
|
983
|
+
await this.collectTypeUsage(typeExpr.expression, usedTypes);
|
|
984
|
+
}
|
|
985
|
+
else if (typeExpr.typeIdentifier) {
|
|
986
|
+
// Generic handler for nodes with typeIdentifier property
|
|
987
|
+
await this.collectTypeUsage(typeExpr.typeIdentifier, usedTypes);
|
|
988
|
+
}
|
|
989
|
+
// Add more type expression handlers as needed
|
|
1025
990
|
}
|
|
1026
991
|
}
|
|
1027
992
|
exports.RemoveImport = RemoveImport;
|