miniread 1.117.0 → 1.118.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/README.md +16 -0
- package/dist/transforms/preset-stats.json +2 -2
- package/dist/transforms-by-id/rename-add-event-listener-parameters/is-add-event-listener-key.d.ts +2 -2
- package/dist/transforms-by-id/rename-add-event-listener-parameters/manifest.json +3 -3
- package/dist/transforms-by-id/rename-add-event-listener-parameters/rename-add-event-listener-parameters-transform.js +18 -0
- package/dist/transforms-by-id/rename-catch-parameters/manifest.json +7 -7
- package/dist/transforms-by-id/rename-catch-parameters/rename-catch-parameters-transform.js +25 -16
- package/dist/transforms-by-id/rename-comparison-flags-v2/get-comparison-flag-base-name.d.ts +6 -0
- package/dist/transforms-by-id/rename-comparison-flags-v2/get-comparison-flag-base-name.js +93 -0
- package/dist/transforms-by-id/rename-comparison-flags-v2/get-string-comparison-details.d.ts +7 -0
- package/dist/transforms-by-id/rename-comparison-flags-v2/get-string-comparison-details.js +37 -0
- package/dist/transforms-by-id/rename-comparison-flags-v2/manifest.json +5 -5
- package/dist/transforms-by-id/rename-comparison-flags-v2/rename-comparison-flags-v2-transform.js +6 -73
- package/dist/transforms-by-id/rename-promise-catch-parameters/get-function-callback-from-identifier.d.ts +7 -0
- package/dist/transforms-by-id/rename-promise-catch-parameters/get-function-callback-from-identifier.js +78 -0
- package/dist/transforms-by-id/rename-promise-catch-parameters/get-promise-handler-callback-parameter-path.d.ts +6 -0
- package/dist/transforms-by-id/rename-promise-catch-parameters/get-promise-handler-callback-parameter-path.js +73 -0
- package/dist/transforms-by-id/rename-promise-catch-parameters/get-this-property-callback-path.d.ts +5 -0
- package/dist/transforms-by-id/rename-promise-catch-parameters/get-this-property-callback-path.js +75 -0
- package/dist/transforms-by-id/rename-promise-catch-parameters/manifest.json +6 -6
- package/dist/transforms-by-id/rename-promise-catch-parameters/rename-promise-catch-parameters-transform.js +1 -81
- package/dist/transforms-by-id/rename-promise-catch-parameters/unwrap-expression-path.d.ts +2 -0
- package/dist/transforms-by-id/rename-promise-catch-parameters/unwrap-expression-path.js +30 -0
- package/dist/transforms-by-id/rename-range-parameters/get-explicit-start-count-method-usage.js +16 -4
- package/dist/transforms-by-id/rename-range-parameters/get-range-parameter-names.js +1 -4
- package/dist/transforms-by-id/rename-range-parameters/get-range-parameters-from-pair.js +2 -4
- package/dist/transforms-by-id/rename-range-parameters/manifest.json +2 -2
- package/dist/transforms-by-id/rename-regex-builders/is-regex-builder-object.js +30 -13
- package/dist/transforms-by-id/rename-rest-pop-callbacks/manifest.json +6 -6
- package/dist/transforms-by-id/rename-rest-pop-callbacks/rename-rest-pop-callbacks-transform.js +26 -53
- package/dist/transforms-by-id/rename-worker-handles/manifest.json +6 -6
- package/dist/transforms-by-id/rename-worker-handles/rename-worker-handles-transform.js +28 -5
- package/dist/transforms-by-id/rename-zod-check-parameters/has-zod-check-context-signals.d.ts +2 -0
- package/dist/transforms-by-id/rename-zod-check-parameters/has-zod-check-context-signals.js +71 -0
- package/dist/transforms-by-id/rename-zod-check-parameters/is-zod-check-member.d.ts +3 -0
- package/dist/transforms-by-id/rename-zod-check-parameters/is-zod-check-member.js +16 -0
- package/dist/transforms-by-id/rename-zod-check-parameters/manifest.json +6 -6
- package/dist/transforms-by-id/rename-zod-check-parameters/rename-zod-check-parameters-transform.js +50 -15
- package/dist/transforms-by-id/simplify-string-trim/manifest.json +6 -6
- package/dist/transforms-by-id/simplify-string-trim/simplify-string-trim-transform.js +38 -6
- package/dist/transforms-by-id/split-variable-declarations/is-safe-to-split-variable-declaration.js +9 -2
- package/dist/transforms-by-id/split-variable-declarations/manifest.json +6 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -109,6 +109,22 @@ Development workflow/tooling documentation lives under `development-workflows/`:
|
|
|
109
109
|
- `development-workflows/improve-transform-performance.md` — runtime performance optimization workflow
|
|
110
110
|
- `development-workflows/improve-transform-coverage.md` — coverage improvement workflow
|
|
111
111
|
|
|
112
|
+
When you update transforms and want fresh recommended preset metrics, rerun the
|
|
113
|
+
recommended-preset evaluation:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
pnpm run miniread-evaluate -- --compare claude-code-2.1.10:claude-code-2.1.11 --baseline none --test recommended --update-manifest
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
This updates `src/transforms/preset-stats.json` (look for
|
|
120
|
+
`Updated preset-stats.json` in CLI output).
|
|
121
|
+
|
|
122
|
+
Optional verification:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
git diff -- src/transforms/preset-stats.json
|
|
126
|
+
```
|
|
127
|
+
|
|
112
128
|
## License
|
|
113
129
|
|
|
114
130
|
MIT
|
package/dist/transforms-by-id/rename-add-event-listener-parameters/is-add-event-listener-key.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { NodePath } from "@babel/traverse";
|
|
2
|
-
import type { ObjectMethod, ObjectProperty } from "@babel/types";
|
|
3
|
-
export declare const isAddEventListenerKey: (path: NodePath<ObjectMethod | ObjectProperty>) => boolean;
|
|
2
|
+
import type { ClassMethod, ClassProperty, ObjectMethod, ObjectProperty } from "@babel/types";
|
|
3
|
+
export declare const isAddEventListenerKey: (path: NodePath<ClassMethod | ClassProperty | ObjectMethod | ObjectProperty>) => boolean;
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"evaluations": {
|
|
3
3
|
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
4
4
|
"diffSizePercent": 100,
|
|
5
|
-
"evaluatedAt": "2026-02-
|
|
6
|
-
"changedLines":
|
|
7
|
-
"durationSeconds":
|
|
5
|
+
"evaluatedAt": "2026-02-21T17:39:30.353Z",
|
|
6
|
+
"changedLines": 44,
|
|
7
|
+
"durationSeconds": 145.734591643,
|
|
8
8
|
"stableNames": 1359
|
|
9
9
|
}
|
|
10
10
|
},
|
|
@@ -67,6 +67,24 @@ export const renameAddEventListenerParametersTransform = {
|
|
|
67
67
|
for (const fileInfo of getFilesToProcess(context)) {
|
|
68
68
|
const group = new RenameGroup();
|
|
69
69
|
traverse(fileInfo.ast, {
|
|
70
|
+
ClassMethod(path) {
|
|
71
|
+
nodesVisited++;
|
|
72
|
+
if (!isAddEventListenerKey(path))
|
|
73
|
+
return;
|
|
74
|
+
collectAddEventListenerRename(path, group);
|
|
75
|
+
},
|
|
76
|
+
ClassProperty(path) {
|
|
77
|
+
nodesVisited++;
|
|
78
|
+
if (!isAddEventListenerKey(path))
|
|
79
|
+
return;
|
|
80
|
+
const valuePath = path.get("value");
|
|
81
|
+
if (valuePath.isFunctionExpression()) {
|
|
82
|
+
collectAddEventListenerRename(valuePath, group);
|
|
83
|
+
}
|
|
84
|
+
else if (valuePath.isArrowFunctionExpression()) {
|
|
85
|
+
collectAddEventListenerRename(valuePath, group);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
70
88
|
ObjectMethod(path) {
|
|
71
89
|
nodesVisited++;
|
|
72
90
|
if (!isAddEventListenerKey(path))
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
-
"recommended": true,
|
|
3
|
-
"recommendedOrder": 100,
|
|
4
2
|
"notes": "Auto-added by evaluation script.",
|
|
5
3
|
"evaluations": {
|
|
6
4
|
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
7
|
-
"diffSizePercent": 99.
|
|
8
|
-
"evaluatedAt": "2026-02-
|
|
9
|
-
"changedLines":
|
|
10
|
-
"durationSeconds":
|
|
5
|
+
"diffSizePercent": 99.91495634425672,
|
|
6
|
+
"evaluatedAt": "2026-02-21T18:42:32.506Z",
|
|
7
|
+
"changedLines": 8006,
|
|
8
|
+
"durationSeconds": 57.912832917,
|
|
11
9
|
"stableNames": 1359
|
|
12
10
|
}
|
|
13
|
-
}
|
|
11
|
+
},
|
|
12
|
+
"recommended": true,
|
|
13
|
+
"recommendedOrder": 100
|
|
14
14
|
}
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
+
import { getBindingIdentifiers, isIdentifier } from "@babel/types";
|
|
2
3
|
import { isStableRenamed, RenameGroup } from "../../core/stable-naming.js";
|
|
3
4
|
import { getFilesToProcess, } from "../../core/types.js";
|
|
5
|
+
import { renamePromiseCatchParametersTransform } from "../rename-promise-catch-parameters/rename-promise-catch-parameters-transform.js";
|
|
4
6
|
const require = createRequire(import.meta.url);
|
|
5
7
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
6
8
|
const traverse = require("@babel/traverse").default;
|
|
7
9
|
const BASE_NAME = "caughtError";
|
|
10
|
+
const getCatchParameterBindingIdentifiers = (parameter) => {
|
|
11
|
+
if (isIdentifier(parameter))
|
|
12
|
+
return [parameter];
|
|
13
|
+
return Object.values(getBindingIdentifiers(parameter));
|
|
14
|
+
};
|
|
8
15
|
export const renameCatchParametersTransform = {
|
|
9
16
|
id: "rename-catch-parameters",
|
|
10
17
|
description: "Renames catch clause parameters to $caughtError/$caughtError2/...",
|
|
11
18
|
scope: "file",
|
|
12
19
|
parallelizable: true,
|
|
13
|
-
transform(context) {
|
|
20
|
+
async transform(context) {
|
|
14
21
|
let nodesVisited = 0;
|
|
15
22
|
let transformationsApplied = 0;
|
|
16
23
|
for (const fileInfo of getFilesToProcess(context)) {
|
|
@@ -21,24 +28,26 @@ export const renameCatchParametersTransform = {
|
|
|
21
28
|
const parameter = path.node.param;
|
|
22
29
|
if (!parameter)
|
|
23
30
|
return;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
const parameterIdentifiers = getCatchParameterBindingIdentifiers(parameter);
|
|
32
|
+
for (const parameterIdentifier of parameterIdentifiers) {
|
|
33
|
+
const currentName = parameterIdentifier.name;
|
|
34
|
+
// Skip already-stable names
|
|
35
|
+
if (isStableRenamed(currentName))
|
|
36
|
+
continue;
|
|
37
|
+
group.add({
|
|
38
|
+
scope: path.scope,
|
|
39
|
+
currentName,
|
|
40
|
+
baseName: BASE_NAME,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
35
43
|
},
|
|
36
44
|
});
|
|
37
45
|
transformationsApplied += group.apply();
|
|
38
46
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
47
|
+
const promiseCatchStats = await renamePromiseCatchParametersTransform.transform(context);
|
|
48
|
+
return {
|
|
49
|
+
nodesVisited: nodesVisited + promiseCatchStats.nodesVisited,
|
|
50
|
+
transformationsApplied: transformationsApplied + promiseCatchStats.transformationsApplied,
|
|
51
|
+
};
|
|
43
52
|
},
|
|
44
53
|
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { getStringComparisonDetails, } from "./get-string-comparison-details.js";
|
|
2
|
+
const toCapitalizedComparisonValue = (stringValue) => {
|
|
3
|
+
const parts = stringValue.split(/[^\dA-Za-z]+/u).filter(Boolean);
|
|
4
|
+
if (parts.length === 0) {
|
|
5
|
+
return stringValue === "" ? "EmptyString" : "Flag";
|
|
6
|
+
}
|
|
7
|
+
return parts
|
|
8
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
9
|
+
.join("");
|
|
10
|
+
};
|
|
11
|
+
const getSpecificComparisonBaseName = (comparison) => {
|
|
12
|
+
const capitalizedValue = toCapitalizedComparisonValue(comparison.stringValue);
|
|
13
|
+
switch (comparison.operator) {
|
|
14
|
+
case "===": {
|
|
15
|
+
return `is${capitalizedValue}`;
|
|
16
|
+
}
|
|
17
|
+
case "!==": {
|
|
18
|
+
return `isNot${capitalizedValue}`;
|
|
19
|
+
}
|
|
20
|
+
case "==": {
|
|
21
|
+
return `equals${capitalizedValue}`;
|
|
22
|
+
}
|
|
23
|
+
case "!=": {
|
|
24
|
+
return `notEquals${capitalizedValue}`;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const collectComparisonWrites = (binding, initialComparison) => {
|
|
29
|
+
const comparisonWrites = [initialComparison];
|
|
30
|
+
if (binding.constant) {
|
|
31
|
+
return comparisonWrites;
|
|
32
|
+
}
|
|
33
|
+
for (const violationPath of binding.constantViolations) {
|
|
34
|
+
if (!violationPath.isAssignmentExpression()) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
const assignment = violationPath.node;
|
|
38
|
+
if (assignment.operator !== "=" ||
|
|
39
|
+
assignment.left.type !== "Identifier" ||
|
|
40
|
+
assignment.left.name !== binding.identifier.name) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
const reassignmentComparison = getStringComparisonDetails(assignment.right);
|
|
44
|
+
if (!reassignmentComparison) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
comparisonWrites.push(reassignmentComparison);
|
|
48
|
+
}
|
|
49
|
+
return comparisonWrites;
|
|
50
|
+
};
|
|
51
|
+
const getBaseNameForComparisonWrites = (comparisonWrites) => {
|
|
52
|
+
const firstWrite = comparisonWrites[0];
|
|
53
|
+
if (!firstWrite) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
if (comparisonWrites.every((comparison) => comparison.operator === firstWrite.operator &&
|
|
57
|
+
comparison.stringValue === firstWrite.stringValue)) {
|
|
58
|
+
// Keep name derivation aligned with rename-comparison-flags so v1/v2
|
|
59
|
+
// produce identical flag names for equivalent comparisons.
|
|
60
|
+
return getSpecificComparisonBaseName(firstWrite);
|
|
61
|
+
}
|
|
62
|
+
const allEqualityComparisons = comparisonWrites.every((comparison) => comparison.operator === "===" || comparison.operator === "==");
|
|
63
|
+
const allInequalityComparisons = comparisonWrites.every((comparison) => comparison.operator === "!==" || comparison.operator === "!=");
|
|
64
|
+
if (!allEqualityComparisons && !allInequalityComparisons) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
const singleStringValue = comparisonWrites.every((comparison) => comparison.stringValue === firstWrite.stringValue);
|
|
68
|
+
if (singleStringValue) {
|
|
69
|
+
const capitalizedValue = toCapitalizedComparisonValue(firstWrite.stringValue);
|
|
70
|
+
if (allEqualityComparisons) {
|
|
71
|
+
return `matches${capitalizedValue}`;
|
|
72
|
+
}
|
|
73
|
+
return `doesNotMatch${capitalizedValue}`;
|
|
74
|
+
}
|
|
75
|
+
if (allEqualityComparisons) {
|
|
76
|
+
return "matchesString";
|
|
77
|
+
}
|
|
78
|
+
return "doesNotMatchString";
|
|
79
|
+
};
|
|
80
|
+
export const getComparisonFlagBaseName = (options) => {
|
|
81
|
+
const { binding, init } = options;
|
|
82
|
+
const comparisonDetails = getStringComparisonDetails(init);
|
|
83
|
+
if (!comparisonDetails) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
if (binding.constant) {
|
|
87
|
+
return getSpecificComparisonBaseName(comparisonDetails);
|
|
88
|
+
}
|
|
89
|
+
const comparisonWrites = collectComparisonWrites(binding, comparisonDetails);
|
|
90
|
+
return comparisonWrites
|
|
91
|
+
? (getBaseNameForComparisonWrites(comparisonWrites) ?? "comparisonResult")
|
|
92
|
+
: "comparisonResult";
|
|
93
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Expression } from "@babel/types";
|
|
2
|
+
export type ComparisonOperator = "===" | "!==" | "==" | "!=";
|
|
3
|
+
export type StringComparisonDetails = {
|
|
4
|
+
operator: ComparisonOperator;
|
|
5
|
+
stringValue: string;
|
|
6
|
+
};
|
|
7
|
+
export declare const getStringComparisonDetails: (expression: Expression) => StringComparisonDetails | undefined;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const isSupportedComparisonSide = (expression) => {
|
|
2
|
+
if (expression.type === "PrivateName") {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
if (expression.type === "TemplateLiteral") {
|
|
6
|
+
return expression.expressions.length > 0;
|
|
7
|
+
}
|
|
8
|
+
if (expression.type.endsWith("Literal")) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
return true;
|
|
12
|
+
};
|
|
13
|
+
export const getStringComparisonDetails = (expression) => {
|
|
14
|
+
if (expression.type !== "BinaryExpression") {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
const operator = expression.operator;
|
|
18
|
+
if (operator !== "===" &&
|
|
19
|
+
operator !== "!==" &&
|
|
20
|
+
operator !== "==" &&
|
|
21
|
+
operator !== "!=") {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
const leftValue = expression.left.type === "StringLiteral"
|
|
25
|
+
? expression.left.value
|
|
26
|
+
: undefined;
|
|
27
|
+
const rightValue = expression.right.type === "StringLiteral"
|
|
28
|
+
? expression.right.value
|
|
29
|
+
: undefined;
|
|
30
|
+
if (leftValue !== undefined && isSupportedComparisonSide(expression.right)) {
|
|
31
|
+
return { operator, stringValue: leftValue };
|
|
32
|
+
}
|
|
33
|
+
if (rightValue !== undefined && isSupportedComparisonSide(expression.left)) {
|
|
34
|
+
return { operator, stringValue: rightValue };
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
};
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
"notes": "Supersedes rename-comparison-flags in the recommended preset and extends comparison flag renaming to member expressions like 'client.config.type === \"sse\"'.",
|
|
3
3
|
"evaluations": {
|
|
4
4
|
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
5
|
-
"diffSizePercent": 99.
|
|
6
|
-
"evaluatedAt": "2026-02-
|
|
7
|
-
"changedLines":
|
|
8
|
-
"durationSeconds":
|
|
9
|
-
"stableNames":
|
|
5
|
+
"diffSizePercent": 99.98299126885134,
|
|
6
|
+
"evaluatedAt": "2026-02-21T18:28:53.452Z",
|
|
7
|
+
"changedLines": 810,
|
|
8
|
+
"durationSeconds": 41.915363875,
|
|
9
|
+
"stableNames": 1429
|
|
10
10
|
}
|
|
11
11
|
},
|
|
12
12
|
"recommended": true,
|
package/dist/transforms-by-id/rename-comparison-flags-v2/rename-comparison-flags-v2-transform.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { RenameGroup, isStableRenamed } from "../../core/stable-naming.js";
|
|
3
3
|
import { getFilesToProcess } from "../../core/types.js";
|
|
4
|
+
import { getComparisonFlagBaseName } from "./get-comparison-flag-base-name.js";
|
|
4
5
|
const require = createRequire(import.meta.url);
|
|
5
6
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
6
7
|
const traverse = require("@babel/traverse").default;
|
|
@@ -21,86 +22,18 @@ export const renameComparisonFlagsV2Transform = {
|
|
|
21
22
|
if (!init || id.type !== "Identifier") {
|
|
22
23
|
return;
|
|
23
24
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
init.operator !== "!==" &&
|
|
27
|
-
init.operator !== "==" &&
|
|
28
|
-
init.operator !== "!=")) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
let stringValue;
|
|
32
|
-
let otherSide;
|
|
33
|
-
if (init.left.type === "StringLiteral") {
|
|
34
|
-
stringValue = init.left.value;
|
|
35
|
-
otherSide = init.right;
|
|
36
|
-
}
|
|
37
|
-
else if (init.right.type === "StringLiteral") {
|
|
38
|
-
stringValue = init.right.value;
|
|
39
|
-
otherSide = init.left;
|
|
40
|
-
}
|
|
41
|
-
if (!otherSide || stringValue === undefined) {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
let isSupportedComparisonSide = false;
|
|
45
|
-
if (otherSide.type === "Identifier") {
|
|
46
|
-
isSupportedComparisonSide = true;
|
|
47
|
-
}
|
|
48
|
-
else if (otherSide.type === "MemberExpression" ||
|
|
49
|
-
otherSide.type === "OptionalMemberExpression") {
|
|
50
|
-
const hasLiteralComputedProperty = otherSide.computed &&
|
|
51
|
-
(otherSide.property.type === "StringLiteral" ||
|
|
52
|
-
otherSide.property.type === "NumericLiteral");
|
|
53
|
-
isSupportedComparisonSide =
|
|
54
|
-
// Allow dot access and literal bracket access (e.g. obj["type"]).
|
|
55
|
-
!otherSide.computed || hasLiteralComputedProperty;
|
|
56
|
-
}
|
|
57
|
-
// Also excludes constant string-vs-string comparisons (e.g. "a" === "b"),
|
|
58
|
-
// which are not variable flag checks.
|
|
59
|
-
if (!isSupportedComparisonSide) {
|
|
25
|
+
const currentName = id.name;
|
|
26
|
+
if (isStableRenamed(currentName)) {
|
|
60
27
|
return;
|
|
61
28
|
}
|
|
62
|
-
const currentName = id.name;
|
|
63
29
|
const binding = path.scope.getBinding(currentName);
|
|
64
|
-
|
|
65
|
-
// can later hold unrelated values, making semantic renames misleading.
|
|
66
|
-
if (!binding?.constant) {
|
|
30
|
+
if (!binding) {
|
|
67
31
|
return;
|
|
68
32
|
}
|
|
69
|
-
|
|
33
|
+
const baseName = getComparisonFlagBaseName({ binding, init });
|
|
34
|
+
if (!baseName) {
|
|
70
35
|
return;
|
|
71
36
|
}
|
|
72
|
-
const operator = init.operator;
|
|
73
|
-
// Keep name derivation aligned with rename-comparison-flags so v1/v2
|
|
74
|
-
// produce identical flag names for equivalent comparisons.
|
|
75
|
-
const parts = stringValue
|
|
76
|
-
.split(/[^\dA-Za-z]+/u)
|
|
77
|
-
.filter(Boolean);
|
|
78
|
-
const capitalizedValue = parts.length === 0
|
|
79
|
-
? stringValue === ""
|
|
80
|
-
? "EmptyString"
|
|
81
|
-
: "Flag"
|
|
82
|
-
: parts
|
|
83
|
-
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
84
|
-
.join("");
|
|
85
|
-
let baseName;
|
|
86
|
-
switch (operator) {
|
|
87
|
-
case "===": {
|
|
88
|
-
baseName = `is${capitalizedValue}`;
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
case "!==": {
|
|
92
|
-
baseName = `isNot${capitalizedValue}`;
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
case "==": {
|
|
96
|
-
baseName = `equals${capitalizedValue}`;
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
99
|
-
case "!=": {
|
|
100
|
-
baseName = `notEquals${capitalizedValue}`;
|
|
101
|
-
break;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
37
|
renameGroup.add({
|
|
105
38
|
scope: binding.scope,
|
|
106
39
|
currentName,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { NodePath } from "@babel/traverse";
|
|
2
|
+
import type { ArrowFunctionExpression, FunctionDeclaration, FunctionExpression, Identifier } from "@babel/types";
|
|
3
|
+
type FunctionCallbackPath = NodePath<FunctionDeclaration | FunctionExpression | ArrowFunctionExpression>;
|
|
4
|
+
type IdentifierPath = NodePath<Identifier>;
|
|
5
|
+
type VisitedNames = Set<string>;
|
|
6
|
+
export declare const getFunctionCallbackFromIdentifier: (argumentPath: IdentifierPath, callSiteStart?: number, visitedNames?: VisitedNames) => FunctionCallbackPath | undefined;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { unwrapExpressionPath } from "./unwrap-expression-path.js";
|
|
2
|
+
const getFunctionCallbackFromAssignment = (assignmentPath, identifierName, callSiteStart, visitedNames) => {
|
|
3
|
+
if (assignmentPath.node.operator !== "=")
|
|
4
|
+
return;
|
|
5
|
+
const leftPath = assignmentPath.get("left");
|
|
6
|
+
if (Array.isArray(leftPath))
|
|
7
|
+
return;
|
|
8
|
+
if (!leftPath.isIdentifier({ name: identifierName }))
|
|
9
|
+
return;
|
|
10
|
+
const rightPath = assignmentPath.get("right");
|
|
11
|
+
if (Array.isArray(rightPath))
|
|
12
|
+
return;
|
|
13
|
+
const callbackPath = unwrapExpressionPath(rightPath);
|
|
14
|
+
if (!callbackPath)
|
|
15
|
+
return;
|
|
16
|
+
if (!callbackPath.isFunctionExpression() &&
|
|
17
|
+
!callbackPath.isArrowFunctionExpression()) {
|
|
18
|
+
if (!callbackPath.isIdentifier())
|
|
19
|
+
return;
|
|
20
|
+
return getFunctionCallbackFromIdentifier(callbackPath, callSiteStart, visitedNames);
|
|
21
|
+
}
|
|
22
|
+
return callbackPath;
|
|
23
|
+
};
|
|
24
|
+
const isIdentifierReassignment = (assignmentPath, identifierName) => {
|
|
25
|
+
if (assignmentPath.node.operator !== "=")
|
|
26
|
+
return false;
|
|
27
|
+
const leftPath = assignmentPath.get("left");
|
|
28
|
+
if (Array.isArray(leftPath))
|
|
29
|
+
return false;
|
|
30
|
+
return leftPath.isIdentifier({ name: identifierName });
|
|
31
|
+
};
|
|
32
|
+
export const getFunctionCallbackFromIdentifier = (argumentPath, callSiteStart, visitedNames = new Set()) => {
|
|
33
|
+
const identifierName = argumentPath.node.name;
|
|
34
|
+
if (visitedNames.has(identifierName))
|
|
35
|
+
return;
|
|
36
|
+
const nextVisitedNames = new Set(visitedNames);
|
|
37
|
+
nextVisitedNames.add(identifierName);
|
|
38
|
+
const binding = argumentPath.scope.getBinding(argumentPath.node.name);
|
|
39
|
+
if (!binding)
|
|
40
|
+
return;
|
|
41
|
+
const bindingPath = binding.path;
|
|
42
|
+
if (bindingPath.isFunctionDeclaration()) {
|
|
43
|
+
return bindingPath;
|
|
44
|
+
}
|
|
45
|
+
if (!bindingPath.isVariableDeclarator())
|
|
46
|
+
return;
|
|
47
|
+
const initPath = bindingPath.get("init");
|
|
48
|
+
if (Array.isArray(initPath))
|
|
49
|
+
return;
|
|
50
|
+
let candidateCallbackPath;
|
|
51
|
+
const initCallbackPath = unwrapExpressionPath(initPath);
|
|
52
|
+
if (initCallbackPath &&
|
|
53
|
+
(initCallbackPath.isFunctionExpression() ||
|
|
54
|
+
initCallbackPath.isArrowFunctionExpression())) {
|
|
55
|
+
const initStart = initCallbackPath.node.start;
|
|
56
|
+
if (typeof callSiteStart !== "number" ||
|
|
57
|
+
typeof initStart !== "number" ||
|
|
58
|
+
initStart < callSiteStart) {
|
|
59
|
+
candidateCallbackPath = initCallbackPath;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
for (const violationPath of binding.constantViolations) {
|
|
63
|
+
if (!violationPath.isAssignmentExpression())
|
|
64
|
+
continue;
|
|
65
|
+
const violationStart = violationPath.node.start;
|
|
66
|
+
if (typeof callSiteStart === "number" &&
|
|
67
|
+
typeof violationStart === "number" &&
|
|
68
|
+
violationStart >= callSiteStart) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (!isIdentifierReassignment(violationPath, argumentPath.node.name)) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const assignedCallbackPath = getFunctionCallbackFromAssignment(violationPath, argumentPath.node.name, violationStart ?? callSiteStart, nextVisitedNames);
|
|
75
|
+
candidateCallbackPath = assignedCallbackPath;
|
|
76
|
+
}
|
|
77
|
+
return candidateCallbackPath;
|
|
78
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { NodePath } from "@babel/traverse";
|
|
2
|
+
import type { CallExpression, Identifier, OptionalCallExpression } from "@babel/types";
|
|
3
|
+
type IdentifierPath = NodePath<Identifier>;
|
|
4
|
+
type CatchCallPath = NodePath<CallExpression> | NodePath<OptionalCallExpression>;
|
|
5
|
+
export declare const getPromiseHandlerCallbackParameterPath: (path: CatchCallPath) => IdentifierPath | undefined;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { getFunctionCallbackFromIdentifier } from "./get-function-callback-from-identifier.js";
|
|
2
|
+
import { getThisPropertyCallbackPath } from "./get-this-property-callback-path.js";
|
|
3
|
+
import { unwrapExpressionPath } from "./unwrap-expression-path.js";
|
|
4
|
+
const getPromiseHandlerName = (callee) => {
|
|
5
|
+
if (callee.type !== "MemberExpression" &&
|
|
6
|
+
callee.type !== "OptionalMemberExpression") {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const property = callee.property;
|
|
10
|
+
if (callee.computed) {
|
|
11
|
+
if (property.type !== "StringLiteral")
|
|
12
|
+
return;
|
|
13
|
+
if (property.value === "catch" || property.value === "then") {
|
|
14
|
+
return property.value;
|
|
15
|
+
}
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (property.type !== "Identifier")
|
|
19
|
+
return;
|
|
20
|
+
if (property.name === "catch" || property.name === "then") {
|
|
21
|
+
return property.name;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const getFirstCallbackParameterPath = (callbackPath) => {
|
|
25
|
+
if (callbackPath.node.params.length === 0)
|
|
26
|
+
return;
|
|
27
|
+
const parameterPath = callbackPath.get("params.0");
|
|
28
|
+
if (Array.isArray(parameterPath))
|
|
29
|
+
return;
|
|
30
|
+
if (parameterPath.isIdentifier()) {
|
|
31
|
+
return parameterPath;
|
|
32
|
+
}
|
|
33
|
+
if (!parameterPath.isAssignmentPattern())
|
|
34
|
+
return;
|
|
35
|
+
const leftPath = parameterPath.get("left");
|
|
36
|
+
if (Array.isArray(leftPath))
|
|
37
|
+
return;
|
|
38
|
+
if (!leftPath.isIdentifier())
|
|
39
|
+
return;
|
|
40
|
+
return leftPath;
|
|
41
|
+
};
|
|
42
|
+
export const getPromiseHandlerCallbackParameterPath = (path) => {
|
|
43
|
+
const handlerName = getPromiseHandlerName(path.node.callee);
|
|
44
|
+
if (!handlerName)
|
|
45
|
+
return;
|
|
46
|
+
const argumentIndex = handlerName === "catch" ? 0 : 1;
|
|
47
|
+
const argument = path.node.arguments[argumentIndex];
|
|
48
|
+
if (!argument)
|
|
49
|
+
return;
|
|
50
|
+
const argumentPath = path.get(`arguments.${argumentIndex}`);
|
|
51
|
+
if (Array.isArray(argumentPath))
|
|
52
|
+
return;
|
|
53
|
+
const callbackPath = unwrapExpressionPath(argumentPath);
|
|
54
|
+
if (!callbackPath)
|
|
55
|
+
return;
|
|
56
|
+
if (callbackPath.isFunctionExpression() ||
|
|
57
|
+
callbackPath.isArrowFunctionExpression()) {
|
|
58
|
+
return getFirstCallbackParameterPath(callbackPath);
|
|
59
|
+
}
|
|
60
|
+
const callSiteStart = path.node.start ?? undefined;
|
|
61
|
+
if (callbackPath.isIdentifier()) {
|
|
62
|
+
const referencedCallbackPath = getFunctionCallbackFromIdentifier(callbackPath, callSiteStart);
|
|
63
|
+
if (!referencedCallbackPath)
|
|
64
|
+
return;
|
|
65
|
+
return getFirstCallbackParameterPath(referencedCallbackPath);
|
|
66
|
+
}
|
|
67
|
+
if (!callbackPath.isMemberExpression())
|
|
68
|
+
return;
|
|
69
|
+
const thisPropertyCallbackPath = getThisPropertyCallbackPath(callbackPath, callSiteStart);
|
|
70
|
+
if (!thisPropertyCallbackPath)
|
|
71
|
+
return;
|
|
72
|
+
return getFirstCallbackParameterPath(thisPropertyCallbackPath);
|
|
73
|
+
};
|
package/dist/transforms-by-id/rename-promise-catch-parameters/get-this-property-callback-path.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { NodePath } from "@babel/traverse";
|
|
2
|
+
import type { ArrowFunctionExpression, FunctionDeclaration, FunctionExpression, MemberExpression } from "@babel/types";
|
|
3
|
+
type FunctionCallbackPath = NodePath<FunctionDeclaration | FunctionExpression | ArrowFunctionExpression>;
|
|
4
|
+
export declare const getThisPropertyCallbackPath: (argumentPath: NodePath<MemberExpression>, callSiteStart?: number) => FunctionCallbackPath | undefined;
|
|
5
|
+
export {};
|