miniread 1.111.1 → 1.112.0
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/transforms/_generated/catalog.js +7 -7
- package/dist/transforms-by-id/rename-collection-constructor-variables/manifest.json +3 -3
- package/dist/transforms-by-id/rename-constructor-variables/get-constructor-base-name-from-expression.d.ts +3 -0
- package/dist/transforms-by-id/rename-constructor-variables/get-constructor-base-name-from-expression.js +30 -0
- package/dist/transforms-by-id/rename-constructor-variables/manifest.json +14 -0
- package/dist/transforms-by-id/rename-constructor-variables/rename-constructor-variables-transform.d.ts +2 -0
- package/dist/transforms-by-id/rename-constructor-variables/rename-constructor-variables-transform.js +74 -0
- package/dist/transforms-by-id/rename-constructor-variables/resolve-constructor-name-from-expression.d.ts +3 -0
- package/dist/transforms-by-id/rename-constructor-variables/resolve-constructor-name-from-expression.js +77 -0
- package/dist/transforms-by-id/rename-constructor-variables/unwrap-transparent-expression.d.ts +3 -0
- package/dist/transforms-by-id/rename-constructor-variables/unwrap-transparent-expression.js +29 -0
- package/dist/transforms-by-id/rename-file-reader-variables/manifest.json +6 -5
- package/dist/transforms-by-id/rename-file-reader-variables/rename-file-reader-variables-transform.js +53 -35
- package/package.json +1 -1
- package/dist/transforms-by-id/rename-file-reader-variables/is-file-reader-constructor.d.ts +0 -3
- package/dist/transforms-by-id/rename-file-reader-variables/is-file-reader-constructor.js +0 -90
- package/dist/transforms-by-id/rename-file-reader-variables/queue-file-reader-rename.d.ts +0 -12
- package/dist/transforms-by-id/rename-file-reader-variables/queue-file-reader-rename.js +0 -25
- package/dist/transforms-by-id/rename-search-parameters-variables/get-member-expression-property-name.d.ts +0 -2
- package/dist/transforms-by-id/rename-search-parameters-variables/get-member-expression-property-name.js +0 -20
- package/dist/transforms-by-id/rename-search-parameters-variables/get-search-parameters-member-expression.d.ts +0 -3
- package/dist/transforms-by-id/rename-search-parameters-variables/get-search-parameters-member-expression.js +0 -26
- package/dist/transforms-by-id/rename-search-parameters-variables/is-search-parameters-destructure-usage.d.ts +0 -2
- package/dist/transforms-by-id/rename-search-parameters-variables/is-search-parameters-destructure-usage.js +0 -74
- package/dist/transforms-by-id/rename-search-parameters-variables/is-search-parameters-for-of-usage.d.ts +0 -2
- package/dist/transforms-by-id/rename-search-parameters-variables/is-search-parameters-for-of-usage.js +0 -18
- package/dist/transforms-by-id/rename-search-parameters-variables/is-search-parameters-property-access.d.ts +0 -2
- package/dist/transforms-by-id/rename-search-parameters-variables/is-search-parameters-property-access.js +0 -30
- package/dist/transforms-by-id/rename-search-parameters-variables/is-search-parameters-spread-usage.d.ts +0 -2
- package/dist/transforms-by-id/rename-search-parameters-variables/is-search-parameters-spread-usage.js +0 -34
- package/dist/transforms-by-id/rename-search-parameters-variables/manifest.json +0 -14
- package/dist/transforms-by-id/rename-search-parameters-variables/rename-search-parameters-variables-transform.d.ts +0 -2
- package/dist/transforms-by-id/rename-search-parameters-variables/rename-search-parameters-variables-transform.js +0 -89
- package/dist/transforms-by-id/rename-search-parameters-variables/search-parameters-property-names.d.ts +0 -1
- package/dist/transforms-by-id/rename-search-parameters-variables/search-parameters-property-names.js +0 -15
|
@@ -44,6 +44,8 @@ import { renameComparisonFlagsTransform } from "../../transforms-by-id/rename-co
|
|
|
44
44
|
import renameComparisonFlagsManifest from "../../transforms-by-id/rename-comparison-flags/manifest.json" with { type: "json" };
|
|
45
45
|
import { renameComparisonFlagsV2Transform } from "../../transforms-by-id/rename-comparison-flags-v2/rename-comparison-flags-v2-transform.js";
|
|
46
46
|
import renameComparisonFlagsV2Manifest from "../../transforms-by-id/rename-comparison-flags-v2/manifest.json" with { type: "json" };
|
|
47
|
+
import { renameConstructorVariablesTransform } from "../../transforms-by-id/rename-constructor-variables/rename-constructor-variables-transform.js";
|
|
48
|
+
import renameConstructorVariablesManifest from "../../transforms-by-id/rename-constructor-variables/manifest.json" with { type: "json" };
|
|
47
49
|
import { renameDateNowStartTimesTransform } from "../../transforms-by-id/rename-date-now-start-times/rename-date-now-start-times-transform.js";
|
|
48
50
|
import renameDateNowStartTimesManifest from "../../transforms-by-id/rename-date-now-start-times/manifest.json" with { type: "json" };
|
|
49
51
|
import { renameDefaultOptionsParametersV3Transform } from "../../transforms-by-id/rename-default-options-parameters-v3/rename-default-options-parameters-v3-transform.js";
|
|
@@ -134,8 +136,6 @@ import { renameReturnObjectBindingsTransform } from "../../transforms-by-id/rena
|
|
|
134
136
|
import renameReturnObjectBindingsManifest from "../../transforms-by-id/rename-return-object-bindings/manifest.json" with { type: "json" };
|
|
135
137
|
import { renameSanitizedStringVariablesTransform } from "../../transforms-by-id/rename-sanitized-string-variables/rename-sanitized-string-variables-transform.js";
|
|
136
138
|
import renameSanitizedStringVariablesManifest from "../../transforms-by-id/rename-sanitized-string-variables/manifest.json" with { type: "json" };
|
|
137
|
-
import { renameSearchParametersVariablesTransform } from "../../transforms-by-id/rename-search-parameters-variables/rename-search-parameters-variables-transform.js";
|
|
138
|
-
import renameSearchParametersVariablesManifest from "../../transforms-by-id/rename-search-parameters-variables/manifest.json" with { type: "json" };
|
|
139
139
|
import { renameSetstateUpdaterParametersTransform } from "../../transforms-by-id/rename-setstate-updater-parameters/rename-setstate-updater-parameters-transform.js";
|
|
140
140
|
import renameSetstateUpdaterParametersManifest from "../../transforms-by-id/rename-setstate-updater-parameters/manifest.json" with { type: "json" };
|
|
141
141
|
import { renameStreamDataChunksTransform } from "../../transforms-by-id/rename-stream-data-chunks/rename-stream-data-chunks-transform.js";
|
|
@@ -305,6 +305,11 @@ export const generatedTransformCatalog = [
|
|
|
305
305
|
transform: renameComparisonFlagsV2Transform,
|
|
306
306
|
manifest: renameComparisonFlagsV2Manifest,
|
|
307
307
|
},
|
|
308
|
+
{
|
|
309
|
+
id: renameConstructorVariablesTransform.id,
|
|
310
|
+
transform: renameConstructorVariablesTransform,
|
|
311
|
+
manifest: renameConstructorVariablesManifest,
|
|
312
|
+
},
|
|
308
313
|
{
|
|
309
314
|
id: renameDateNowStartTimesTransform.id,
|
|
310
315
|
transform: renameDateNowStartTimesTransform,
|
|
@@ -530,11 +535,6 @@ export const generatedTransformCatalog = [
|
|
|
530
535
|
transform: renameSanitizedStringVariablesTransform,
|
|
531
536
|
manifest: renameSanitizedStringVariablesManifest,
|
|
532
537
|
},
|
|
533
|
-
{
|
|
534
|
-
id: renameSearchParametersVariablesTransform.id,
|
|
535
|
-
transform: renameSearchParametersVariablesTransform,
|
|
536
|
-
manifest: renameSearchParametersVariablesManifest,
|
|
537
|
-
},
|
|
538
538
|
{
|
|
539
539
|
id: renameSetstateUpdaterParametersTransform.id,
|
|
540
540
|
transform: renameSetstateUpdaterParametersTransform,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"notes": "
|
|
2
|
+
"notes": "Superseded by rename-constructor-variables for constructor-derived variable naming coverage.",
|
|
3
|
+
"supersededBy": "rename-constructor-variables",
|
|
3
4
|
"evaluations": {
|
|
4
5
|
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
5
6
|
"diffSizePercent": 99.96976225573572,
|
|
@@ -9,6 +10,5 @@
|
|
|
9
10
|
"stableNames": 1364
|
|
10
11
|
}
|
|
11
12
|
},
|
|
12
|
-
"recommended":
|
|
13
|
-
"recommendedOrder": 101
|
|
13
|
+
"recommended": false
|
|
14
14
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
import { isValidBindingIdentifier } from "../../transforms/shared/is-valid-binding-identifier.js";
|
|
3
|
+
import { resolveConstructorNameFromExpression } from "./resolve-constructor-name-from-expression.js";
|
|
4
|
+
import { unwrapTransparentExpression } from "./unwrap-transparent-expression.js";
|
|
5
|
+
const toCamelCaseBaseName = (constructorName) => {
|
|
6
|
+
const uppercasePrefixMatch = constructorName.match(/^[A-Z]+(?=[A-Z][a-z]|[0-9]|$)/u);
|
|
7
|
+
if (!uppercasePrefixMatch) {
|
|
8
|
+
const [firstCharacter = "", ...rest] = constructorName;
|
|
9
|
+
return `${firstCharacter.toLowerCase()}${rest.join("")}`;
|
|
10
|
+
}
|
|
11
|
+
const uppercasePrefix = uppercasePrefixMatch[0];
|
|
12
|
+
return (uppercasePrefix.toLowerCase() +
|
|
13
|
+
constructorName.slice(uppercasePrefix.length));
|
|
14
|
+
};
|
|
15
|
+
export const getConstructorBaseNameFromExpression = (scope, expression) => {
|
|
16
|
+
if (!expression)
|
|
17
|
+
return undefined;
|
|
18
|
+
const unwrappedExpression = unwrapTransparentExpression(expression);
|
|
19
|
+
if (!t.isNewExpression(unwrappedExpression))
|
|
20
|
+
return undefined;
|
|
21
|
+
if (!t.isExpression(unwrappedExpression.callee))
|
|
22
|
+
return undefined;
|
|
23
|
+
const constructorName = resolveConstructorNameFromExpression(scope, unwrappedExpression.callee);
|
|
24
|
+
if (!constructorName)
|
|
25
|
+
return undefined;
|
|
26
|
+
const baseName = toCamelCaseBaseName(constructorName);
|
|
27
|
+
if (!isValidBindingIdentifier(baseName))
|
|
28
|
+
return undefined;
|
|
29
|
+
return baseName;
|
|
30
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"notes": "Renames constructor-initialized or constructor-assigned variables by deriving camelCase names from constructor identifiers, member constructors, and local constructor aliases.",
|
|
3
|
+
"evaluations": {
|
|
4
|
+
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
5
|
+
"diffSizePercent": 100.3269456098575,
|
|
6
|
+
"evaluatedAt": "2026-02-13T08:51:30.726Z",
|
|
7
|
+
"changedLines": 15609,
|
|
8
|
+
"durationSeconds": 367.642214666,
|
|
9
|
+
"stableNames": 1804
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"recommended": true,
|
|
13
|
+
"recommendedOrder": 201
|
|
14
|
+
}
|
package/dist/transforms-by-id/rename-constructor-variables/rename-constructor-variables-transform.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { isStableRenamed, RenameGroup } from "../../core/stable-naming.js";
|
|
3
|
+
import { getFilesToProcess, } from "../../core/types.js";
|
|
4
|
+
import { getConstructorBaseNameFromExpression } from "./get-constructor-base-name-from-expression.js";
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
7
|
+
const traverse = require("@babel/traverse").default;
|
|
8
|
+
const queueConstructorRename = (options) => {
|
|
9
|
+
const { scope, currentName, baseName, group, queuedBindings } = options;
|
|
10
|
+
if (isStableRenamed(currentName))
|
|
11
|
+
return;
|
|
12
|
+
const binding = scope.getBinding(currentName);
|
|
13
|
+
if (!binding)
|
|
14
|
+
return;
|
|
15
|
+
if (queuedBindings.has(binding))
|
|
16
|
+
return;
|
|
17
|
+
queuedBindings.add(binding);
|
|
18
|
+
group.add({
|
|
19
|
+
scope: binding.scope,
|
|
20
|
+
currentName,
|
|
21
|
+
baseName,
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
export const renameConstructorVariablesTransform = {
|
|
25
|
+
id: "rename-constructor-variables",
|
|
26
|
+
description: "Renames variables initialized or assigned from constructor calls to constructor-derived names like $dataView and $fooBar",
|
|
27
|
+
scope: "file",
|
|
28
|
+
parallelizable: true,
|
|
29
|
+
transform(context) {
|
|
30
|
+
let nodesVisited = 0;
|
|
31
|
+
let transformationsApplied = 0;
|
|
32
|
+
for (const fileInfo of getFilesToProcess(context)) {
|
|
33
|
+
const group = new RenameGroup();
|
|
34
|
+
const queuedBindings = new Set();
|
|
35
|
+
traverse(fileInfo.ast, {
|
|
36
|
+
VariableDeclarator(path) {
|
|
37
|
+
nodesVisited++;
|
|
38
|
+
const { id } = path.node;
|
|
39
|
+
if (id.type !== "Identifier")
|
|
40
|
+
return;
|
|
41
|
+
const baseName = getConstructorBaseNameFromExpression(path.scope, path.node.init);
|
|
42
|
+
if (!baseName)
|
|
43
|
+
return;
|
|
44
|
+
queueConstructorRename({
|
|
45
|
+
scope: path.scope,
|
|
46
|
+
currentName: id.name,
|
|
47
|
+
baseName,
|
|
48
|
+
group,
|
|
49
|
+
queuedBindings,
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
AssignmentExpression(path) {
|
|
53
|
+
nodesVisited++;
|
|
54
|
+
if (path.node.operator !== "=")
|
|
55
|
+
return;
|
|
56
|
+
if (path.node.left.type !== "Identifier")
|
|
57
|
+
return;
|
|
58
|
+
const baseName = getConstructorBaseNameFromExpression(path.scope, path.node.right);
|
|
59
|
+
if (!baseName)
|
|
60
|
+
return;
|
|
61
|
+
queueConstructorRename({
|
|
62
|
+
scope: path.scope,
|
|
63
|
+
currentName: path.node.left.name,
|
|
64
|
+
baseName,
|
|
65
|
+
group,
|
|
66
|
+
queuedBindings,
|
|
67
|
+
});
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
transformationsApplied += group.apply();
|
|
71
|
+
}
|
|
72
|
+
return Promise.resolve({ nodesVisited, transformationsApplied });
|
|
73
|
+
},
|
|
74
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
import { MAX_ALIAS_RESOLUTION_DEPTH, unwrapTransparentExpression, } from "./unwrap-transparent-expression.js";
|
|
3
|
+
const UPPERCASE_CONSTRUCTOR_PATTERN = /^[A-Z][A-Za-z0-9_$]*$/u;
|
|
4
|
+
const getMemberPropertyName = (memberExpression) => {
|
|
5
|
+
if (!memberExpression.computed) {
|
|
6
|
+
if (!t.isIdentifier(memberExpression.property))
|
|
7
|
+
return undefined;
|
|
8
|
+
return memberExpression.property.name;
|
|
9
|
+
}
|
|
10
|
+
if (t.isStringLiteral(memberExpression.property)) {
|
|
11
|
+
return memberExpression.property.value;
|
|
12
|
+
}
|
|
13
|
+
if (t.isTemplateLiteral(memberExpression.property) &&
|
|
14
|
+
memberExpression.property.expressions.length === 0 &&
|
|
15
|
+
memberExpression.property.quasis.length === 1) {
|
|
16
|
+
return memberExpression.property.quasis[0]?.value.cooked ?? undefined;
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
};
|
|
20
|
+
const resolveFromBinding = (binding, visitedBindings, depth) => {
|
|
21
|
+
if (depth > MAX_ALIAS_RESOLUTION_DEPTH)
|
|
22
|
+
return undefined;
|
|
23
|
+
const bindingPath = binding.path;
|
|
24
|
+
if (bindingPath.isClassDeclaration() || bindingPath.isFunctionDeclaration()) {
|
|
25
|
+
return binding.identifier.name;
|
|
26
|
+
}
|
|
27
|
+
if (!bindingPath.isVariableDeclarator() || !binding.constant) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
const { init, id } = bindingPath.node;
|
|
31
|
+
if (!init)
|
|
32
|
+
return undefined;
|
|
33
|
+
const unwrappedInit = unwrapTransparentExpression(init);
|
|
34
|
+
if (t.isClassExpression(unwrappedInit) ||
|
|
35
|
+
t.isFunctionExpression(unwrappedInit)) {
|
|
36
|
+
if (unwrappedInit.id?.name)
|
|
37
|
+
return unwrappedInit.id.name;
|
|
38
|
+
return t.isIdentifier(id) ? id.name : undefined;
|
|
39
|
+
}
|
|
40
|
+
return resolveFromExpression(bindingPath.scope, unwrappedInit, visitedBindings, depth + 1);
|
|
41
|
+
};
|
|
42
|
+
const resolveFromIdentifier = (scope, identifierName, visitedBindings, depth) => {
|
|
43
|
+
if (depth > MAX_ALIAS_RESOLUTION_DEPTH)
|
|
44
|
+
return undefined;
|
|
45
|
+
const binding = scope.getBinding(identifierName);
|
|
46
|
+
if (binding) {
|
|
47
|
+
if (visitedBindings.has(binding))
|
|
48
|
+
return undefined;
|
|
49
|
+
visitedBindings.add(binding);
|
|
50
|
+
const resolvedFromBinding = resolveFromBinding(binding, visitedBindings, depth + 1);
|
|
51
|
+
if (resolvedFromBinding)
|
|
52
|
+
return resolvedFromBinding;
|
|
53
|
+
}
|
|
54
|
+
return UPPERCASE_CONSTRUCTOR_PATTERN.test(identifierName)
|
|
55
|
+
? identifierName
|
|
56
|
+
: undefined;
|
|
57
|
+
};
|
|
58
|
+
const resolveFromExpression = (scope, expression, visitedBindings, depth) => {
|
|
59
|
+
if (depth > MAX_ALIAS_RESOLUTION_DEPTH)
|
|
60
|
+
return undefined;
|
|
61
|
+
const unwrappedExpression = unwrapTransparentExpression(expression);
|
|
62
|
+
if (t.isIdentifier(unwrappedExpression)) {
|
|
63
|
+
return resolveFromIdentifier(scope, unwrappedExpression.name, visitedBindings, depth + 1);
|
|
64
|
+
}
|
|
65
|
+
if (t.isMemberExpression(unwrappedExpression) ||
|
|
66
|
+
t.isOptionalMemberExpression(unwrappedExpression)) {
|
|
67
|
+
return getMemberPropertyName(unwrappedExpression);
|
|
68
|
+
}
|
|
69
|
+
if (t.isClassExpression(unwrappedExpression) ||
|
|
70
|
+
t.isFunctionExpression(unwrappedExpression)) {
|
|
71
|
+
return unwrappedExpression.id?.name;
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
};
|
|
75
|
+
export const resolveConstructorNameFromExpression = (scope, expression) => {
|
|
76
|
+
return resolveFromExpression(scope, expression, new Set(), 0);
|
|
77
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
export const MAX_ALIAS_RESOLUTION_DEPTH = 8;
|
|
3
|
+
const unwrapSingleTransparentExpression = (expression) => {
|
|
4
|
+
if (t.isParenthesizedExpression(expression))
|
|
5
|
+
return expression.expression;
|
|
6
|
+
if (t.isTSAsExpression(expression))
|
|
7
|
+
return expression.expression;
|
|
8
|
+
if (t.isTSSatisfiesExpression(expression))
|
|
9
|
+
return expression.expression;
|
|
10
|
+
if (t.isTSTypeAssertion(expression))
|
|
11
|
+
return expression.expression;
|
|
12
|
+
if (t.isTSNonNullExpression(expression))
|
|
13
|
+
return expression.expression;
|
|
14
|
+
if (t.isTypeCastExpression(expression))
|
|
15
|
+
return expression.expression;
|
|
16
|
+
if (t.isSequenceExpression(expression))
|
|
17
|
+
return expression.expressions.at(-1);
|
|
18
|
+
return undefined;
|
|
19
|
+
};
|
|
20
|
+
export const unwrapTransparentExpression = (expression) => {
|
|
21
|
+
let currentExpression = expression;
|
|
22
|
+
for (let depth = 0; depth < MAX_ALIAS_RESOLUTION_DEPTH; depth += 1) {
|
|
23
|
+
const nextExpression = unwrapSingleTransparentExpression(currentExpression);
|
|
24
|
+
if (!nextExpression)
|
|
25
|
+
return currentExpression;
|
|
26
|
+
currentExpression = nextExpression;
|
|
27
|
+
}
|
|
28
|
+
return currentExpression;
|
|
29
|
+
};
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
+
"notes": "Post-pass behavior after rename-constructor-variables: focuses on FileReader event-handler parameter naming for fileReader-like bindings.",
|
|
2
3
|
"evaluations": {
|
|
3
4
|
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
4
5
|
"diffSizePercent": 100,
|
|
5
|
-
"evaluatedAt": "2026-02-
|
|
6
|
-
"changedLines":
|
|
7
|
-
"durationSeconds":
|
|
8
|
-
"stableNames":
|
|
6
|
+
"evaluatedAt": "2026-02-14T07:23:12.948Z",
|
|
7
|
+
"changedLines": 0,
|
|
8
|
+
"durationSeconds": 25.987191208,
|
|
9
|
+
"stableNames": 1357
|
|
9
10
|
}
|
|
10
11
|
},
|
|
11
12
|
"recommended": true,
|
|
12
|
-
"recommendedOrder":
|
|
13
|
+
"recommendedOrder": 211
|
|
13
14
|
}
|
package/dist/transforms-by-id/rename-file-reader-variables/rename-file-reader-variables-transform.js
CHANGED
|
@@ -1,16 +1,51 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
-
import
|
|
2
|
+
import * as t from "@babel/types";
|
|
3
3
|
import { RenameGroup } from "../../core/stable-naming.js";
|
|
4
4
|
import { getFilesToProcess, } from "../../core/types.js";
|
|
5
|
-
import { isFileReaderConstructor } from "./is-file-reader-constructor.js";
|
|
6
5
|
import { queueFileReaderEventRename } from "./queue-file-reader-event-rename.js";
|
|
7
|
-
import { queueFileReaderRename } from "./queue-file-reader-rename.js";
|
|
8
6
|
const require = createRequire(import.meta.url);
|
|
9
7
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
10
8
|
const traverse = require("@babel/traverse").default;
|
|
9
|
+
const FILE_READER_BINDING_PATTERN = /^\$?fileReader(?:Instance)?\d*$/u;
|
|
10
|
+
const isTrackedFileReaderBindingName = (name) => FILE_READER_BINDING_PATTERN.test(name);
|
|
11
|
+
const getMemberPropertyName = (memberExpression) => {
|
|
12
|
+
if (!memberExpression.computed) {
|
|
13
|
+
if (!t.isIdentifier(memberExpression.property))
|
|
14
|
+
return undefined;
|
|
15
|
+
return memberExpression.property.name;
|
|
16
|
+
}
|
|
17
|
+
if (t.isStringLiteral(memberExpression.property)) {
|
|
18
|
+
return memberExpression.property.value;
|
|
19
|
+
}
|
|
20
|
+
if (t.isTemplateLiteral(memberExpression.property) &&
|
|
21
|
+
memberExpression.property.expressions.length === 0 &&
|
|
22
|
+
memberExpression.property.quasis.length === 1) {
|
|
23
|
+
return memberExpression.property.quasis[0]?.value.cooked ?? undefined;
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
};
|
|
27
|
+
const isFileReaderConstructorExpression = (expression) => {
|
|
28
|
+
if (!t.isNewExpression(expression))
|
|
29
|
+
return false;
|
|
30
|
+
const callee = expression.callee;
|
|
31
|
+
if (t.isIdentifier(callee)) {
|
|
32
|
+
return callee.name === "FileReader";
|
|
33
|
+
}
|
|
34
|
+
if (!t.isMemberExpression(callee) && !t.isOptionalMemberExpression(callee)) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
const propertyName = getMemberPropertyName(callee);
|
|
38
|
+
if (propertyName !== "FileReader")
|
|
39
|
+
return false;
|
|
40
|
+
if (!t.isIdentifier(callee.object))
|
|
41
|
+
return false;
|
|
42
|
+
return (callee.object.name === "globalThis" ||
|
|
43
|
+
callee.object.name === "window" ||
|
|
44
|
+
callee.object.name === "self");
|
|
45
|
+
};
|
|
11
46
|
export const renameFileReaderVariablesTransform = {
|
|
12
47
|
id: "rename-file-reader-variables",
|
|
13
|
-
description: "
|
|
48
|
+
description: "Post-pass: renames FileReader event-handler parameters for fileReader-like bindings",
|
|
14
49
|
scope: "file",
|
|
15
50
|
parallelizable: true,
|
|
16
51
|
transform(context) {
|
|
@@ -18,33 +53,20 @@ export const renameFileReaderVariablesTransform = {
|
|
|
18
53
|
let transformationsApplied = 0;
|
|
19
54
|
for (const fileInfo of getFilesToProcess(context)) {
|
|
20
55
|
const renameGroup = new RenameGroup();
|
|
21
|
-
const exportedNames = collectExportedNames(fileInfo.ast.program);
|
|
22
|
-
const queuedBindings = new Set();
|
|
23
56
|
const queuedEventBindings = new Set();
|
|
24
57
|
const fileReaderBindings = new Set();
|
|
25
58
|
let directTransformationsApplied = 0;
|
|
26
59
|
traverse(fileInfo.ast, {
|
|
27
60
|
VariableDeclarator(path) {
|
|
28
61
|
nodesVisited++;
|
|
29
|
-
|
|
30
|
-
if (id.type !== "Identifier") {
|
|
62
|
+
if (path.node.id.type !== "Identifier")
|
|
31
63
|
return;
|
|
32
|
-
|
|
33
|
-
const initPath = path.get("init");
|
|
34
|
-
if (Array.isArray(initPath) || !initPath.isNewExpression()) {
|
|
64
|
+
if (!isTrackedFileReaderBindingName(path.node.id.name))
|
|
35
65
|
return;
|
|
36
|
-
|
|
37
|
-
if (!
|
|
66
|
+
const binding = path.scope.getBinding(path.node.id.name);
|
|
67
|
+
if (!binding)
|
|
38
68
|
return;
|
|
39
|
-
|
|
40
|
-
queueFileReaderRename({
|
|
41
|
-
scope: path.scope,
|
|
42
|
-
currentName: id.name,
|
|
43
|
-
renameGroup,
|
|
44
|
-
exportedNames,
|
|
45
|
-
queuedBindings,
|
|
46
|
-
fileReaderBindings,
|
|
47
|
-
});
|
|
69
|
+
fileReaderBindings.add(binding);
|
|
48
70
|
},
|
|
49
71
|
AssignmentExpression(path) {
|
|
50
72
|
nodesVisited++;
|
|
@@ -54,22 +76,18 @@ export const renameFileReaderVariablesTransform = {
|
|
|
54
76
|
if (!binding) {
|
|
55
77
|
return;
|
|
56
78
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
!isFileReaderConstructor(rightPath)) {
|
|
79
|
+
if (!isTrackedFileReaderBindingName(binding.identifier.name)) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (operator !== "=") {
|
|
62
83
|
fileReaderBindings.delete(binding);
|
|
63
84
|
return;
|
|
64
85
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
queuedBindings,
|
|
71
|
-
fileReaderBindings,
|
|
72
|
-
});
|
|
86
|
+
if (isFileReaderConstructorExpression(path.node.right)) {
|
|
87
|
+
fileReaderBindings.add(binding);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
fileReaderBindings.delete(binding);
|
|
73
91
|
return;
|
|
74
92
|
}
|
|
75
93
|
directTransformationsApplied += queueFileReaderEventRename({
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "miniread",
|
|
3
3
|
"author": "Łukasz Jerciński",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.112.0",
|
|
6
6
|
"description": "Transform minified JavaScript/TypeScript into a more readable form using deterministic AST-based transforms.",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
const GLOBAL_FILE_READER_OBJECTS = new Set(["globalThis", "window", "self"]);
|
|
2
|
-
const isTypeOnlyImportSpecifier = (binding, node) => {
|
|
3
|
-
const declaration = binding.path.parent;
|
|
4
|
-
if (declaration.type !== "ImportDeclaration") {
|
|
5
|
-
return false;
|
|
6
|
-
}
|
|
7
|
-
if (node.type === "ImportSpecifier" && node.importKind === "type") {
|
|
8
|
-
return true;
|
|
9
|
-
}
|
|
10
|
-
return declaration.importKind === "type";
|
|
11
|
-
};
|
|
12
|
-
const isTypeOnlyFileReaderBinding = (binding) => {
|
|
13
|
-
const node = binding.path.node;
|
|
14
|
-
const declaration = binding.path.parent;
|
|
15
|
-
if (node.type === "ImportSpecifier" ||
|
|
16
|
-
node.type === "ImportDefaultSpecifier") {
|
|
17
|
-
return isTypeOnlyImportSpecifier(binding, node);
|
|
18
|
-
}
|
|
19
|
-
if (declaration.type === "VariableDeclaration" && declaration.declare) {
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
if (node.type === "TSDeclareFunction" ||
|
|
23
|
-
(node.type === "ClassDeclaration" && node.declare === true) ||
|
|
24
|
-
(node.type === "FunctionDeclaration" && node.declare === true)) {
|
|
25
|
-
return true;
|
|
26
|
-
}
|
|
27
|
-
return (node.type === "TSTypeAliasDeclaration" ||
|
|
28
|
-
node.type === "TSInterfaceDeclaration");
|
|
29
|
-
};
|
|
30
|
-
const hasRuntimeFileReaderShadowing = (path) => {
|
|
31
|
-
const binding = path.scope.getBinding("FileReader");
|
|
32
|
-
// Ambient declarations like `declare class FileReader` typically do not
|
|
33
|
-
// produce bindings in Babel's TS scope model, so `binding` is often absent.
|
|
34
|
-
if (!binding) {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
// Keep using getBinding so we can inspect and ignore type-only TS bindings.
|
|
38
|
-
if (isTypeOnlyFileReaderBinding(binding)) {
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
return true;
|
|
42
|
-
};
|
|
43
|
-
const isGlobalFileReaderMemberExpression = (path) => {
|
|
44
|
-
const { callee } = path.node;
|
|
45
|
-
if (callee.type !== "MemberExpression") {
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
if (callee.computed) {
|
|
49
|
-
if (callee.property.type === "StringLiteral" &&
|
|
50
|
-
callee.property.value !== "FileReader") {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
if (callee.property.type === "TemplateLiteral" &&
|
|
54
|
-
(callee.property.expressions.length > 0 ||
|
|
55
|
-
callee.property.quasis[0]?.value.cooked !== "FileReader")) {
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
if (callee.property.type !== "StringLiteral" &&
|
|
59
|
-
callee.property.type !== "TemplateLiteral") {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
if (callee.property.type !== "Identifier" ||
|
|
65
|
-
callee.property.name !== "FileReader") {
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
if (callee.object.type !== "Identifier") {
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
if (!GLOBAL_FILE_READER_OBJECTS.has(callee.object.name)) {
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
if (path.scope.hasBinding(callee.object.name, true)) {
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
return true;
|
|
79
|
-
};
|
|
80
|
-
export const isFileReaderConstructor = (path) => {
|
|
81
|
-
const { callee } = path.node;
|
|
82
|
-
if (callee.type === "Identifier") {
|
|
83
|
-
if (callee.name !== "FileReader")
|
|
84
|
-
return false;
|
|
85
|
-
if (hasRuntimeFileReaderShadowing(path))
|
|
86
|
-
return false;
|
|
87
|
-
return true;
|
|
88
|
-
}
|
|
89
|
-
return isGlobalFileReaderMemberExpression(path);
|
|
90
|
-
};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { Binding, NodePath } from "@babel/traverse";
|
|
2
|
-
import type { RenameGroup } from "../../core/stable-naming.js";
|
|
3
|
-
type QueueFileReaderRenameParameters = {
|
|
4
|
-
scope: NodePath["scope"];
|
|
5
|
-
currentName: string;
|
|
6
|
-
renameGroup: RenameGroup;
|
|
7
|
-
exportedNames: Set<string>;
|
|
8
|
-
queuedBindings: Set<Binding>;
|
|
9
|
-
fileReaderBindings: Set<Binding>;
|
|
10
|
-
};
|
|
11
|
-
export declare const queueFileReaderRename: ({ scope, currentName, renameGroup, exportedNames, queuedBindings, fileReaderBindings, }: QueueFileReaderRenameParameters) => void;
|
|
12
|
-
export {};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { isStableRenamed } from "../../core/stable-naming.js";
|
|
2
|
-
const FILE_READER_BASE_NAME = "fileReaderInstance";
|
|
3
|
-
export const queueFileReaderRename = ({ scope, currentName, renameGroup, exportedNames, queuedBindings, fileReaderBindings, }) => {
|
|
4
|
-
if (isStableRenamed(currentName)) {
|
|
5
|
-
return;
|
|
6
|
-
}
|
|
7
|
-
const binding = scope.getBinding(currentName);
|
|
8
|
-
if (!binding) {
|
|
9
|
-
return;
|
|
10
|
-
}
|
|
11
|
-
if (queuedBindings.has(binding)) {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
if (binding.scope.block.type === "Program" &&
|
|
15
|
-
exportedNames.has(currentName)) {
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
queuedBindings.add(binding);
|
|
19
|
-
fileReaderBindings.add(binding);
|
|
20
|
-
renameGroup.add({
|
|
21
|
-
scope: binding.scope,
|
|
22
|
-
currentName,
|
|
23
|
-
baseName: FILE_READER_BASE_NAME,
|
|
24
|
-
});
|
|
25
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export const getMemberExpressionPropertyName = (expression) => {
|
|
2
|
-
const key = expression.property;
|
|
3
|
-
if (!expression.computed) {
|
|
4
|
-
if (key.type === "Identifier")
|
|
5
|
-
return key.name;
|
|
6
|
-
if (key.type === "StringLiteral")
|
|
7
|
-
return key.value;
|
|
8
|
-
return undefined;
|
|
9
|
-
}
|
|
10
|
-
if (key.type === "StringLiteral")
|
|
11
|
-
return key.value;
|
|
12
|
-
if (key.type === "TemplateLiteral" &&
|
|
13
|
-
key.expressions.length === 0 &&
|
|
14
|
-
key.quasis.length === 1) {
|
|
15
|
-
const quasi = key.quasis[0];
|
|
16
|
-
const cooked = quasi?.value.cooked;
|
|
17
|
-
return cooked ?? quasi?.value.raw;
|
|
18
|
-
}
|
|
19
|
-
return undefined;
|
|
20
|
-
};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import type { NodePath } from "@babel/traverse";
|
|
2
|
-
import type { MemberExpression, OptionalMemberExpression } from "@babel/types";
|
|
3
|
-
export declare const getSearchParametersMemberExpression: (referencePath: NodePath) => NodePath<MemberExpression | OptionalMemberExpression> | undefined;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export const getSearchParametersMemberExpression = (referencePath) => {
|
|
2
|
-
const parent = referencePath.parentPath;
|
|
3
|
-
if (!parent)
|
|
4
|
-
return;
|
|
5
|
-
if (parent.isMemberExpression() &&
|
|
6
|
-
parent.node.object === referencePath.node) {
|
|
7
|
-
return parent;
|
|
8
|
-
}
|
|
9
|
-
if (parent.isOptionalMemberExpression() &&
|
|
10
|
-
parent.node.object === referencePath.node) {
|
|
11
|
-
return parent;
|
|
12
|
-
}
|
|
13
|
-
if (parent.isTSNonNullExpression() &&
|
|
14
|
-
parent.node.expression === referencePath.node) {
|
|
15
|
-
const outer = parent.parentPath;
|
|
16
|
-
if (!outer)
|
|
17
|
-
return;
|
|
18
|
-
if (outer.isMemberExpression() && outer.node.object === parent.node) {
|
|
19
|
-
return outer;
|
|
20
|
-
}
|
|
21
|
-
if (outer.isOptionalMemberExpression() &&
|
|
22
|
-
outer.node.object === parent.node) {
|
|
23
|
-
return outer;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
};
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { searchParametersPropertyNames } from "./search-parameters-property-names.js";
|
|
2
|
-
export const isSearchParametersDestructureUsage = (referencePath) => {
|
|
3
|
-
const parent = referencePath.parentPath;
|
|
4
|
-
if (parent?.isTSNonNullExpression() &&
|
|
5
|
-
parent.node.expression === referencePath.node) {
|
|
6
|
-
const outer = parent.parentPath;
|
|
7
|
-
if (!outer)
|
|
8
|
-
return false;
|
|
9
|
-
if (outer.isVariableDeclarator()) {
|
|
10
|
-
if (outer.node.init !== parent.node)
|
|
11
|
-
return false;
|
|
12
|
-
const id = outer.node.id;
|
|
13
|
-
if (id.type !== "ObjectPattern")
|
|
14
|
-
return false;
|
|
15
|
-
return isSearchParametersDestructurePattern(id);
|
|
16
|
-
}
|
|
17
|
-
if (outer.isAssignmentExpression()) {
|
|
18
|
-
if (outer.node.operator !== "=")
|
|
19
|
-
return false;
|
|
20
|
-
if (outer.node.right !== parent.node)
|
|
21
|
-
return false;
|
|
22
|
-
const left = outer.node.left;
|
|
23
|
-
if (left.type !== "ObjectPattern")
|
|
24
|
-
return false;
|
|
25
|
-
return isSearchParametersDestructurePattern(left);
|
|
26
|
-
}
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
if (parent?.isVariableDeclarator()) {
|
|
30
|
-
if (parent.node.init !== referencePath.node)
|
|
31
|
-
return false;
|
|
32
|
-
const id = parent.node.id;
|
|
33
|
-
if (id.type !== "ObjectPattern")
|
|
34
|
-
return false;
|
|
35
|
-
return isSearchParametersDestructurePattern(id);
|
|
36
|
-
}
|
|
37
|
-
if (parent?.isAssignmentExpression()) {
|
|
38
|
-
if (parent.node.operator !== "=")
|
|
39
|
-
return false;
|
|
40
|
-
if (parent.node.right !== referencePath.node)
|
|
41
|
-
return false;
|
|
42
|
-
const left = parent.node.left;
|
|
43
|
-
if (left.type !== "ObjectPattern")
|
|
44
|
-
return false;
|
|
45
|
-
return isSearchParametersDestructurePattern(left);
|
|
46
|
-
}
|
|
47
|
-
return false;
|
|
48
|
-
};
|
|
49
|
-
const isSearchParametersDestructurePattern = (pattern) => {
|
|
50
|
-
if (pattern.properties.length === 0)
|
|
51
|
-
return false;
|
|
52
|
-
for (const property of pattern.properties) {
|
|
53
|
-
// Rest properties suggest generic object destructuring, so we stay
|
|
54
|
-
// conservative and don't treat it as URLSearchParams usage evidence.
|
|
55
|
-
if (property.type === "RestElement")
|
|
56
|
-
return false;
|
|
57
|
-
const keyName = property.computed
|
|
58
|
-
? property.key.type === "StringLiteral"
|
|
59
|
-
? property.key.value
|
|
60
|
-
: undefined
|
|
61
|
-
: property.key.type === "Identifier"
|
|
62
|
-
? property.key.name
|
|
63
|
-
: property.key.type === "StringLiteral"
|
|
64
|
-
? property.key.value
|
|
65
|
-
: undefined;
|
|
66
|
-
if (!keyName)
|
|
67
|
-
return false;
|
|
68
|
-
// Be strict: `URLSearchParams` method names overlap with many other APIs, so
|
|
69
|
-
// we only treat destructuring as usage evidence when *every* key matches.
|
|
70
|
-
if (!searchParametersPropertyNames.has(keyName))
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
return true;
|
|
74
|
-
};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export const isSearchParametersForOfUsage = (referencePath) => {
|
|
2
|
-
const parent = referencePath.parentPath;
|
|
3
|
-
if (!parent)
|
|
4
|
-
return false;
|
|
5
|
-
if (parent.isForOfStatement()) {
|
|
6
|
-
return parent.node.right === referencePath.node;
|
|
7
|
-
}
|
|
8
|
-
if (parent.isTSNonNullExpression() &&
|
|
9
|
-
parent.node.expression === referencePath.node) {
|
|
10
|
-
const forOf = parent.parentPath;
|
|
11
|
-
if (!forOf)
|
|
12
|
-
return false;
|
|
13
|
-
if (!forOf.isForOfStatement())
|
|
14
|
-
return false;
|
|
15
|
-
return forOf.node.right === parent.node;
|
|
16
|
-
}
|
|
17
|
-
return false;
|
|
18
|
-
};
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { getMemberExpressionPropertyName } from "./get-member-expression-property-name.js";
|
|
2
|
-
import { getSearchParametersMemberExpression } from "./get-search-parameters-member-expression.js";
|
|
3
|
-
import { searchParametersPropertyNames } from "./search-parameters-property-names.js";
|
|
4
|
-
export const isSearchParametersPropertyAccess = (referencePath) => {
|
|
5
|
-
const memberExpression = getSearchParametersMemberExpression(referencePath);
|
|
6
|
-
if (!memberExpression)
|
|
7
|
-
return false;
|
|
8
|
-
const keyName = getMemberExpressionPropertyName(memberExpression.node);
|
|
9
|
-
if (!keyName)
|
|
10
|
-
return isSymbolIteratorAccess(memberExpression.node);
|
|
11
|
-
return searchParametersPropertyNames.has(keyName);
|
|
12
|
-
};
|
|
13
|
-
const isSymbolIteratorAccess = (expression) => {
|
|
14
|
-
if (!expression.computed)
|
|
15
|
-
return false;
|
|
16
|
-
const property = expression.property;
|
|
17
|
-
if (property.type !== "MemberExpression" &&
|
|
18
|
-
property.type !== "OptionalMemberExpression") {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
if (property.computed)
|
|
22
|
-
return false;
|
|
23
|
-
if (property.object.type !== "Identifier")
|
|
24
|
-
return false;
|
|
25
|
-
if (property.object.name !== "Symbol")
|
|
26
|
-
return false;
|
|
27
|
-
if (property.property.type !== "Identifier")
|
|
28
|
-
return false;
|
|
29
|
-
return property.property.name === "iterator";
|
|
30
|
-
};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
export const isSearchParametersSpreadUsage = (referencePath) => {
|
|
2
|
-
const parent = referencePath.parentPath;
|
|
3
|
-
if (!parent)
|
|
4
|
-
return false;
|
|
5
|
-
if (parent.isSpreadElement()) {
|
|
6
|
-
const container = parent.parentPath;
|
|
7
|
-
if (!container)
|
|
8
|
-
return false;
|
|
9
|
-
if (!container.isArrayExpression() &&
|
|
10
|
-
!container.isCallExpression() &&
|
|
11
|
-
!container.isNewExpression()) {
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
14
|
-
return parent.node.argument === referencePath.node;
|
|
15
|
-
}
|
|
16
|
-
if (parent.isTSNonNullExpression() &&
|
|
17
|
-
parent.node.expression === referencePath.node) {
|
|
18
|
-
const spread = parent.parentPath;
|
|
19
|
-
if (!spread)
|
|
20
|
-
return false;
|
|
21
|
-
if (!spread.isSpreadElement())
|
|
22
|
-
return false;
|
|
23
|
-
const container = spread.parentPath;
|
|
24
|
-
if (!container)
|
|
25
|
-
return false;
|
|
26
|
-
if (!container.isArrayExpression() &&
|
|
27
|
-
!container.isCallExpression() &&
|
|
28
|
-
!container.isNewExpression()) {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
return spread.node.argument === parent.node;
|
|
32
|
-
}
|
|
33
|
-
return false;
|
|
34
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"notes": "Measured with baseline none: 100.00% of original diff. Added to recommended for readability.",
|
|
3
|
-
"evaluations": {
|
|
4
|
-
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
5
|
-
"diffSizePercent": 100,
|
|
6
|
-
"evaluatedAt": "2026-02-10T06:09:20.069Z",
|
|
7
|
-
"changedLines": 40,
|
|
8
|
-
"durationSeconds": 37.640948791999996,
|
|
9
|
-
"stableNames": 1358
|
|
10
|
-
}
|
|
11
|
-
},
|
|
12
|
-
"recommended": true,
|
|
13
|
-
"recommendedOrder": 100
|
|
14
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
|
-
import { isStableRenamed, RenameGroup } from "../../core/stable-naming.js";
|
|
3
|
-
import { getFilesToProcess, } from "../../core/types.js";
|
|
4
|
-
import { getUrlConstructionKind } from "../../transforms/get-url-construction-kind.js";
|
|
5
|
-
import { isAllowedUrlConstructorInScope } from "../../transforms/is-allowed-url-constructor-in-scope.js";
|
|
6
|
-
import { isSearchParametersDestructureUsage } from "./is-search-parameters-destructure-usage.js";
|
|
7
|
-
import { isSearchParametersForOfUsage } from "./is-search-parameters-for-of-usage.js";
|
|
8
|
-
import { isSearchParametersPropertyAccess } from "./is-search-parameters-property-access.js";
|
|
9
|
-
import { isSearchParametersSpreadUsage } from "./is-search-parameters-spread-usage.js";
|
|
10
|
-
const require = createRequire(import.meta.url);
|
|
11
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
12
|
-
const traverse = require("@babel/traverse").default;
|
|
13
|
-
const hasSearchParametersUsage = (binding) => {
|
|
14
|
-
for (const referencePath of binding.referencePaths) {
|
|
15
|
-
if (isSearchParametersPropertyAccess(referencePath) ||
|
|
16
|
-
isSearchParametersForOfUsage(referencePath) ||
|
|
17
|
-
isSearchParametersSpreadUsage(referencePath) ||
|
|
18
|
-
isSearchParametersDestructureUsage(referencePath)) {
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return false;
|
|
23
|
-
};
|
|
24
|
-
export const renameSearchParametersVariablesTransform = {
|
|
25
|
-
id: "rename-search-parameters-variables",
|
|
26
|
-
description: "Renames variables initialized with new URLSearchParams(...) to stable search parameter identifiers",
|
|
27
|
-
scope: "file",
|
|
28
|
-
parallelizable: true,
|
|
29
|
-
transform(context) {
|
|
30
|
-
let nodesVisited = 0;
|
|
31
|
-
let transformationsApplied = 0;
|
|
32
|
-
for (const fileInfo of getFilesToProcess(context)) {
|
|
33
|
-
const group = new RenameGroup();
|
|
34
|
-
const candidatesByScope = new Map();
|
|
35
|
-
traverse(fileInfo.ast, {
|
|
36
|
-
VariableDeclarator(path) {
|
|
37
|
-
nodesVisited += 1;
|
|
38
|
-
// Only rename actual bindings. Patterns don't create a stable
|
|
39
|
-
// `URLSearchParams` variable to rename, and `URLSearchParams` is
|
|
40
|
-
// iterable (not a plain object), so destructuring doesn't map cleanly.
|
|
41
|
-
if (path.node.id.type !== "Identifier")
|
|
42
|
-
return;
|
|
43
|
-
const constructionKind = getUrlConstructionKind(path.scope, path.node.init, "URLSearchParams");
|
|
44
|
-
if (!constructionKind)
|
|
45
|
-
return;
|
|
46
|
-
if (constructionKind === "identifier" &&
|
|
47
|
-
!isAllowedUrlConstructorInScope(path.scope, "URLSearchParams")) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
const currentName = path.node.id.name;
|
|
51
|
-
if (isStableRenamed(currentName))
|
|
52
|
-
return;
|
|
53
|
-
const binding = path.scope.getBinding(currentName);
|
|
54
|
-
if (!binding)
|
|
55
|
-
return;
|
|
56
|
-
if (!binding.constant)
|
|
57
|
-
return;
|
|
58
|
-
const candidateName = "searchParameters";
|
|
59
|
-
if (candidateName === currentName)
|
|
60
|
-
return;
|
|
61
|
-
const scopeCandidates = candidatesByScope.get(path.scope) ?? [];
|
|
62
|
-
scopeCandidates.push({
|
|
63
|
-
scope: path.scope,
|
|
64
|
-
currentName,
|
|
65
|
-
hasUsage: hasSearchParametersUsage(binding),
|
|
66
|
-
});
|
|
67
|
-
candidatesByScope.set(path.scope, scopeCandidates);
|
|
68
|
-
},
|
|
69
|
-
});
|
|
70
|
-
for (const scopeCandidates of candidatesByScope.values()) {
|
|
71
|
-
const requiresUsageEvidence = scopeCandidates.length > 1;
|
|
72
|
-
for (const candidate of scopeCandidates) {
|
|
73
|
-
if (requiresUsageEvidence && !candidate.hasUsage)
|
|
74
|
-
continue;
|
|
75
|
-
group.add({
|
|
76
|
-
scope: candidate.scope,
|
|
77
|
-
currentName: candidate.currentName,
|
|
78
|
-
baseName: "searchParameters",
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
transformationsApplied += group.apply();
|
|
83
|
-
}
|
|
84
|
-
return Promise.resolve({
|
|
85
|
-
nodesVisited,
|
|
86
|
-
transformationsApplied,
|
|
87
|
-
});
|
|
88
|
-
},
|
|
89
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const searchParametersPropertyNames: Set<string>;
|