miniread 1.84.0 → 1.85.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/manifest.js +11 -0
- package/dist/transforms/_generated/registry.js +4 -0
- package/dist/transforms/recommended-transform-order.d.ts +1 -1
- package/dist/transforms/recommended-transform-order.js +2 -0
- package/dist/transforms/rename-object-entries-parameters/is-object-entries-consumer-call.d.ts +4 -0
- package/dist/transforms/rename-object-entries-parameters/is-object-entries-consumer-call.js +95 -0
- package/dist/transforms/rename-object-entries-parameters/manifest.json +12 -0
- package/dist/transforms/rename-object-entries-parameters/rename-object-entries-parameters-transform.d.ts +2 -0
- package/dist/transforms/rename-object-entries-parameters/rename-object-entries-parameters-transform.js +86 -0
- package/dist/transforms/rename-setstate-updater-parameters/get-updater-function-path.d.ts +6 -0
- package/dist/transforms/rename-setstate-updater-parameters/get-updater-function-path.js +81 -0
- package/dist/transforms/rename-setstate-updater-parameters/manifest.json +13 -0
- package/dist/transforms/rename-setstate-updater-parameters/rename-setstate-updater-parameters-transform.d.ts +2 -0
- package/dist/transforms/rename-setstate-updater-parameters/rename-setstate-updater-parameters-transform.js +83 -0
- package/package.json +1 -1
|
@@ -212,6 +212,10 @@ const manifestData = {
|
|
|
212
212
|
notes: "Measured with baseline none: 0.00%.",
|
|
213
213
|
evaluations: { "legacy:evaluation": { "evaluatedAt": "2026-01-25T20:05:17.827Z", "changedLines": 208, "durationSeconds": 0, "stableNames": 0, "diffSizePercent": 100 }, "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-01-25T23:22:33.139Z", "changedLines": 208, "durationSeconds": 54.654894917, "stableNames": 1358 } },
|
|
214
214
|
},
|
|
215
|
+
"rename-object-entries-parameters": {
|
|
216
|
+
recommended: true,
|
|
217
|
+
evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-02-06T17:39:17.299Z", "changedLines": 248, "durationSeconds": 215.530500649, "stableNames": 1358 } },
|
|
218
|
+
},
|
|
215
219
|
"rename-object-keys-iterator-variables": {
|
|
216
220
|
recommended: true,
|
|
217
221
|
evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-02-04T12:47:49.357Z", "changedLines": 606, "durationSeconds": 152.335242224, "stableNames": 1359 } },
|
|
@@ -302,6 +306,11 @@ const manifestData = {
|
|
|
302
306
|
notes: "Measured with baseline none: 100.00% of original diff. Added to recommended for readability.",
|
|
303
307
|
evaluations: { "legacy:evaluation": { "diffSizePercent": 100, "evaluatedAt": "2026-01-25T09:49:29.000Z", "changedLines": 0, "durationSeconds": 0, "stableNames": 0 }, "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-01-26T07:05:01.592Z", "changedLines": 32, "durationSeconds": 54.402595083, "stableNames": 1358 } },
|
|
304
308
|
},
|
|
309
|
+
"rename-setstate-updater-parameters": {
|
|
310
|
+
recommended: true,
|
|
311
|
+
notes: "Added to recommended for readability.",
|
|
312
|
+
evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-02-06T14:45:47.110Z", "changedLines": 44, "durationSeconds": 167.840422062, "stableNames": 1358 } },
|
|
313
|
+
},
|
|
305
314
|
"rename-string-split-variables": {
|
|
306
315
|
recommended: true,
|
|
307
316
|
notes: "Measured with baseline none: 0.00%. Added to recommended for readability.",
|
|
@@ -496,6 +505,7 @@ export const recommendedTransformIds = [
|
|
|
496
505
|
"rename-object-keys-variables",
|
|
497
506
|
"rename-object-keys-iterator-variables",
|
|
498
507
|
"rename-object-keys-reducer-parameters",
|
|
508
|
+
"rename-object-entries-parameters",
|
|
499
509
|
"rename-parameters-to-match-properties-v2",
|
|
500
510
|
"rename-invalid-parameter-arguments",
|
|
501
511
|
"rename-promise-executor-parameters-v2",
|
|
@@ -504,6 +514,7 @@ export const recommendedTransformIds = [
|
|
|
504
514
|
"rename-regex-builders",
|
|
505
515
|
"rename-regex-source-parameters",
|
|
506
516
|
"rename-search-parameters-variables",
|
|
517
|
+
"rename-setstate-updater-parameters",
|
|
507
518
|
"rename-file-extension-variables",
|
|
508
519
|
"rename-string-split-variables",
|
|
509
520
|
"rename-this-aliases",
|
|
@@ -43,6 +43,7 @@ import { renameLoopIndexVariablesTransform } from "../rename-loop-index-variable
|
|
|
43
43
|
import { renameLoopIndexVariablesV2Transform } from "../rename-loop-index-variables-v2/rename-loop-index-variables-v2-transform.js";
|
|
44
44
|
import { renameLoopIndexVariablesV3Transform } from "../rename-loop-index-variables-v3/rename-loop-index-variables-v3-transform.js";
|
|
45
45
|
import { renameLoopLengthVariablesTransform } from "../rename-loop-length-variables/rename-loop-length-variables-transform.js";
|
|
46
|
+
import { renameObjectEntriesParametersTransform } from "../rename-object-entries-parameters/rename-object-entries-parameters-transform.js";
|
|
46
47
|
import { renameObjectKeysIteratorVariablesTransform } from "../rename-object-keys-iterator-variables/rename-object-keys-iterator-variables-transform.js";
|
|
47
48
|
import { renameObjectKeysReducerParametersTransform } from "../rename-object-keys-reducer-parameters/rename-object-keys-reducer-parameters-transform.js";
|
|
48
49
|
import { renameObjectKeysVariablesTransform } from "../rename-object-keys-variables/rename-object-keys-variables-transform.js";
|
|
@@ -62,6 +63,7 @@ import { renameRestParametersTransform } from "../rename-rest-parameters/rename-
|
|
|
62
63
|
import { renameRestPopCallbacksTransform } from "../rename-rest-pop-callbacks/rename-rest-pop-callbacks-transform.js";
|
|
63
64
|
import { renameSafePropertyAccessorParametersTransform } from "../rename-safe-property-accessor-parameters/rename-safe-property-accessor-parameters-transform.js";
|
|
64
65
|
import { renameSearchParametersVariablesTransform } from "../rename-search-parameters-variables/rename-search-parameters-variables-transform.js";
|
|
66
|
+
import { renameSetstateUpdaterParametersTransform } from "../rename-setstate-updater-parameters/rename-setstate-updater-parameters-transform.js";
|
|
65
67
|
import { renameStringSplitVariablesTransform } from "../rename-string-split-variables/rename-string-split-variables-transform.js";
|
|
66
68
|
import { renameThisAliasesTransform } from "../rename-this-aliases/rename-this-aliases-transform.js";
|
|
67
69
|
import { renameTimeoutDurationParametersTransform } from "../rename-timeout-duration-parameters/rename-timeout-duration-parameters-transform.js";
|
|
@@ -133,6 +135,7 @@ export const transformRegistry = {
|
|
|
133
135
|
[renameLoopIndexVariablesV2Transform.id]: renameLoopIndexVariablesV2Transform,
|
|
134
136
|
[renameLoopIndexVariablesV3Transform.id]: renameLoopIndexVariablesV3Transform,
|
|
135
137
|
[renameLoopLengthVariablesTransform.id]: renameLoopLengthVariablesTransform,
|
|
138
|
+
[renameObjectEntriesParametersTransform.id]: renameObjectEntriesParametersTransform,
|
|
136
139
|
[renameObjectKeysIteratorVariablesTransform.id]: renameObjectKeysIteratorVariablesTransform,
|
|
137
140
|
[renameObjectKeysReducerParametersTransform.id]: renameObjectKeysReducerParametersTransform,
|
|
138
141
|
[renameObjectKeysVariablesTransform.id]: renameObjectKeysVariablesTransform,
|
|
@@ -152,6 +155,7 @@ export const transformRegistry = {
|
|
|
152
155
|
[renameRestPopCallbacksTransform.id]: renameRestPopCallbacksTransform,
|
|
153
156
|
[renameSafePropertyAccessorParametersTransform.id]: renameSafePropertyAccessorParametersTransform,
|
|
154
157
|
[renameSearchParametersVariablesTransform.id]: renameSearchParametersVariablesTransform,
|
|
158
|
+
[renameSetstateUpdaterParametersTransform.id]: renameSetstateUpdaterParametersTransform,
|
|
155
159
|
[renameStringSplitVariablesTransform.id]: renameStringSplitVariablesTransform,
|
|
156
160
|
[renameThisAliasesTransform.id]: renameThisAliasesTransform,
|
|
157
161
|
[renameTimeoutDurationParametersTransform.id]: renameTimeoutDurationParametersTransform,
|
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
* This lets us tune transform interactions intentionally instead of relying on
|
|
5
5
|
* alphabetical ID sorting.
|
|
6
6
|
*/
|
|
7
|
-
export declare const recommendedTransformOrder: readonly ["stabilize-top-level-bindings", "stabilize-nested-bindings", "stabilize-deferred-top-level-bindings", "stabilize-deferred-stable-rhs", "expand-boolean-literals", "expand-sequence-expressions-v5", "expand-special-number-literals", "expand-typeof-undefined-comparisons", "expand-undefined-literals", "remove-redundant-else", "rename-arguments-length-flags", "rename-asap-wrappers", "rename-awaiter-parameters", "rename-awaiter-helper-functions", "rename-buffer-variables", "rename-to-buffer-results", "rename-catch-parameters", "rename-promise-catch-parameters", "rename-char-code-at", "rename-charcode-variables-v2", "rename-client-aliases", "rename-comparison-flags", "rename-platform-win32-flags", "rename-date-now-start-times", "rename-default-options-parameters-v2", "rename-deferred-resolve-parameters", "rename-deferred-resolve-parameters-v2", "rename-destructured-aliases", "rename-rest-parameters", "rename-rest-pop-callbacks", "rename-execfile-arguments", "rename-file-reader-variables", "rename-error-first-callback-parameters", "rename-error-first-callback-parameters-v2", "rename-error-variables", "rename-event-parameters", "rename-add-event-listener-parameters", "rename-http-server-parameters", "rename-fs-sync-variables", "rename-http-method-parameters", "rename-interval-ids", "rename-indexeddb-request-variables", "rename-loop-index-variables-v3", "rename-loop-length-variables", "rename-document-fragment-variables", "rename-object-keys-variables", "rename-object-keys-iterator-variables", "rename-object-keys-reducer-parameters", "rename-parameters-to-match-properties-v2", "rename-invalid-parameter-arguments", "rename-promise-executor-parameters-v2", "rename-range-parameters", "rename-read-file-lines", "rename-regex-builders", "rename-regex-source-parameters", "rename-search-parameters-variables", "rename-file-extension-variables", "rename-string-split-variables", "rename-this-aliases", "rename-timeout-promises", "rename-timeout-ids", "rename-typeof-variables", "rename-typescript-helper-aliases", "rename-uint8array-concat-variables", "rename-url-parameters", "rename-url-variables", "rename-use-reference-guards-v2", "rename-use-reference-sets", "rename-worker-handles", "rename-zod-check-parameters", "simplify-boolean-negations", "simplify-string-trim", "split-variable-declarations", "use-optional-chaining", "use-object-property-shorthand", "use-object-shorthand", "replace-dynamic-require-eval"];
|
|
7
|
+
export declare const recommendedTransformOrder: readonly ["stabilize-top-level-bindings", "stabilize-nested-bindings", "stabilize-deferred-top-level-bindings", "stabilize-deferred-stable-rhs", "expand-boolean-literals", "expand-sequence-expressions-v5", "expand-special-number-literals", "expand-typeof-undefined-comparisons", "expand-undefined-literals", "remove-redundant-else", "rename-arguments-length-flags", "rename-asap-wrappers", "rename-awaiter-parameters", "rename-awaiter-helper-functions", "rename-buffer-variables", "rename-to-buffer-results", "rename-catch-parameters", "rename-promise-catch-parameters", "rename-char-code-at", "rename-charcode-variables-v2", "rename-client-aliases", "rename-comparison-flags", "rename-platform-win32-flags", "rename-date-now-start-times", "rename-default-options-parameters-v2", "rename-deferred-resolve-parameters", "rename-deferred-resolve-parameters-v2", "rename-destructured-aliases", "rename-rest-parameters", "rename-rest-pop-callbacks", "rename-execfile-arguments", "rename-file-reader-variables", "rename-error-first-callback-parameters", "rename-error-first-callback-parameters-v2", "rename-error-variables", "rename-event-parameters", "rename-add-event-listener-parameters", "rename-http-server-parameters", "rename-fs-sync-variables", "rename-http-method-parameters", "rename-interval-ids", "rename-indexeddb-request-variables", "rename-loop-index-variables-v3", "rename-loop-length-variables", "rename-document-fragment-variables", "rename-object-keys-variables", "rename-object-keys-iterator-variables", "rename-object-keys-reducer-parameters", "rename-object-entries-parameters", "rename-parameters-to-match-properties-v2", "rename-invalid-parameter-arguments", "rename-promise-executor-parameters-v2", "rename-range-parameters", "rename-read-file-lines", "rename-regex-builders", "rename-regex-source-parameters", "rename-search-parameters-variables", "rename-setstate-updater-parameters", "rename-file-extension-variables", "rename-string-split-variables", "rename-this-aliases", "rename-timeout-promises", "rename-timeout-ids", "rename-typeof-variables", "rename-typescript-helper-aliases", "rename-uint8array-concat-variables", "rename-url-parameters", "rename-url-variables", "rename-use-reference-guards-v2", "rename-use-reference-sets", "rename-worker-handles", "rename-zod-check-parameters", "simplify-boolean-negations", "simplify-string-trim", "split-variable-declarations", "use-optional-chaining", "use-object-property-shorthand", "use-object-shorthand", "replace-dynamic-require-eval"];
|
|
@@ -65,6 +65,7 @@ export const recommendedTransformOrder = [
|
|
|
65
65
|
"rename-object-keys-variables",
|
|
66
66
|
"rename-object-keys-iterator-variables",
|
|
67
67
|
"rename-object-keys-reducer-parameters",
|
|
68
|
+
"rename-object-entries-parameters",
|
|
68
69
|
"rename-parameters-to-match-properties-v2",
|
|
69
70
|
"rename-invalid-parameter-arguments",
|
|
70
71
|
"rename-promise-executor-parameters-v2",
|
|
@@ -73,6 +74,7 @@ export const recommendedTransformOrder = [
|
|
|
73
74
|
"rename-regex-builders",
|
|
74
75
|
"rename-regex-source-parameters",
|
|
75
76
|
"rename-search-parameters-variables",
|
|
77
|
+
"rename-setstate-updater-parameters",
|
|
76
78
|
"rename-file-extension-variables",
|
|
77
79
|
"rename-string-split-variables",
|
|
78
80
|
"rename-this-aliases",
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { NodePath } from "@babel/traverse";
|
|
2
|
+
import type { CallExpression, OptionalCallExpression } from "@babel/types";
|
|
3
|
+
export type EntriesConsumerCall = CallExpression | OptionalCallExpression;
|
|
4
|
+
export declare const isObjectEntriesConsumerCall: (path: NodePath<EntriesConsumerCall>) => boolean;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
import { isRuntimeBindingInScope } from "../is-runtime-binding-in-scope.js";
|
|
3
|
+
const ARRAY_METHODS = new Set([
|
|
4
|
+
"filter",
|
|
5
|
+
"map",
|
|
6
|
+
"flatMap",
|
|
7
|
+
"forEach",
|
|
8
|
+
"some",
|
|
9
|
+
"every",
|
|
10
|
+
"find",
|
|
11
|
+
"findIndex",
|
|
12
|
+
]);
|
|
13
|
+
const SHAPE_PRESERVING_CHAIN_METHODS = new Set(["filter"]);
|
|
14
|
+
const getMemberPropertyName = (member) => {
|
|
15
|
+
if (!member.computed && member.property.type === "Identifier") {
|
|
16
|
+
return member.property.name;
|
|
17
|
+
}
|
|
18
|
+
if (member.computed && t.isStringLiteral(member.property)) {
|
|
19
|
+
return member.property.value;
|
|
20
|
+
}
|
|
21
|
+
if (member.computed &&
|
|
22
|
+
t.isTemplateLiteral(member.property) &&
|
|
23
|
+
member.property.expressions.length === 0) {
|
|
24
|
+
const quasi = member.property.quasis[0];
|
|
25
|
+
const cooked = quasi?.value.cooked;
|
|
26
|
+
return cooked ?? quasi?.value.raw;
|
|
27
|
+
}
|
|
28
|
+
return undefined;
|
|
29
|
+
};
|
|
30
|
+
const isObjectEntriesCall = (path) => {
|
|
31
|
+
const callee = path.node.callee;
|
|
32
|
+
if (!t.isMemberExpression(callee) && !t.isOptionalMemberExpression(callee)) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
if (!t.isIdentifier(callee.object) || callee.object.name !== "Object") {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
const propertyName = getMemberPropertyName(callee);
|
|
39
|
+
if (propertyName !== "entries")
|
|
40
|
+
return false;
|
|
41
|
+
if (isRuntimeBindingInScope(path.scope, "Object"))
|
|
42
|
+
return false;
|
|
43
|
+
return path.node.arguments.length > 0;
|
|
44
|
+
};
|
|
45
|
+
const getArrayMethodName = (path) => {
|
|
46
|
+
const callee = path.node.callee;
|
|
47
|
+
if (!t.isMemberExpression(callee) && !t.isOptionalMemberExpression(callee)) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
const propertyName = getMemberPropertyName(callee);
|
|
51
|
+
if (!propertyName || !ARRAY_METHODS.has(propertyName))
|
|
52
|
+
return undefined;
|
|
53
|
+
return propertyName;
|
|
54
|
+
};
|
|
55
|
+
const getReceiverCallPath = (path) => {
|
|
56
|
+
const objectPath = path.get("callee.object");
|
|
57
|
+
if (objectPath.isCallExpression() || objectPath.isOptionalCallExpression()) {
|
|
58
|
+
return objectPath;
|
|
59
|
+
}
|
|
60
|
+
// Optional member calls like `Object.entries(data).map?.(...)` produce a
|
|
61
|
+
// member-expression receiver whose object is the actual call-chain source.
|
|
62
|
+
if (!objectPath.isMemberExpression() &&
|
|
63
|
+
!objectPath.isOptionalMemberExpression()) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
const memberObjectPath = objectPath;
|
|
67
|
+
const nestedObjectPath = memberObjectPath.get("object");
|
|
68
|
+
if (nestedObjectPath.isCallExpression() ||
|
|
69
|
+
nestedObjectPath.isOptionalCallExpression()) {
|
|
70
|
+
return nestedObjectPath;
|
|
71
|
+
}
|
|
72
|
+
return undefined;
|
|
73
|
+
};
|
|
74
|
+
export const isObjectEntriesConsumerCall = (path) => {
|
|
75
|
+
if (!getArrayMethodName(path))
|
|
76
|
+
return false;
|
|
77
|
+
let receiverPath = getReceiverCallPath(path);
|
|
78
|
+
if (!receiverPath)
|
|
79
|
+
return false;
|
|
80
|
+
// Rename callbacks for direct Object.entries consumers and for downstream
|
|
81
|
+
// calls whose intermediate chain is known to preserve entry tuple shape.
|
|
82
|
+
for (;;) {
|
|
83
|
+
if (isObjectEntriesCall(receiverPath))
|
|
84
|
+
return true;
|
|
85
|
+
const receiverMethodName = getArrayMethodName(receiverPath);
|
|
86
|
+
if (!receiverMethodName ||
|
|
87
|
+
!SHAPE_PRESERVING_CHAIN_METHODS.has(receiverMethodName)) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
const nextReceiverPath = getReceiverCallPath(receiverPath);
|
|
91
|
+
if (!nextReceiverPath)
|
|
92
|
+
return false;
|
|
93
|
+
receiverPath = nextReceiverPath;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { isStableRenamed, RenameGroup } from "../../core/stable-naming.js";
|
|
3
|
+
import { getFilesToProcess, } from "../../core/types.js";
|
|
4
|
+
import { hasDynamicNameLookup } from "../has-dynamic-name-lookup.js";
|
|
5
|
+
import { isObjectEntriesConsumerCall, } from "./is-object-entries-consumer-call.js";
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
8
|
+
const traverse = require("@babel/traverse").default;
|
|
9
|
+
const getEntryArrayPattern = (functionPath) => {
|
|
10
|
+
const parameters = functionPath.get("params");
|
|
11
|
+
const firstParameter = parameters[0];
|
|
12
|
+
if (!firstParameter?.isArrayPattern())
|
|
13
|
+
return undefined;
|
|
14
|
+
const elements = firstParameter.get("elements");
|
|
15
|
+
if (elements.length !== 2)
|
|
16
|
+
return undefined;
|
|
17
|
+
const keyParameter = elements[0];
|
|
18
|
+
const valueParameter = elements[1];
|
|
19
|
+
if (!keyParameter?.isIdentifier() || !valueParameter?.isIdentifier()) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
return firstParameter;
|
|
23
|
+
};
|
|
24
|
+
const addEntryRenames = (group, patternPath) => {
|
|
25
|
+
const elements = patternPath.get("elements");
|
|
26
|
+
const keyParameter = elements[0];
|
|
27
|
+
const valueParameter = elements[1];
|
|
28
|
+
if (!keyParameter?.isIdentifier() || !valueParameter?.isIdentifier())
|
|
29
|
+
return;
|
|
30
|
+
const keyName = keyParameter.node.name;
|
|
31
|
+
const valueName = valueParameter.node.name;
|
|
32
|
+
// Keep destructured pairs visually consistent: if either side is already
|
|
33
|
+
// stable-renamed, leave the pair untouched instead of producing mixed names.
|
|
34
|
+
if (isStableRenamed(keyName) || isStableRenamed(valueName))
|
|
35
|
+
return;
|
|
36
|
+
group.add({
|
|
37
|
+
scope: keyParameter.scope,
|
|
38
|
+
currentName: keyName,
|
|
39
|
+
baseName: "key",
|
|
40
|
+
});
|
|
41
|
+
group.add({
|
|
42
|
+
scope: valueParameter.scope,
|
|
43
|
+
currentName: valueName,
|
|
44
|
+
baseName: "value",
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
const collectEntriesConsumerRenames = (path, group) => {
|
|
48
|
+
if (!isObjectEntriesConsumerCall(path))
|
|
49
|
+
return;
|
|
50
|
+
const callbackPath = path.get("arguments.0");
|
|
51
|
+
if (!callbackPath.isFunctionExpression() &&
|
|
52
|
+
!callbackPath.isArrowFunctionExpression()) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const patternPath = getEntryArrayPattern(callbackPath);
|
|
56
|
+
if (!patternPath)
|
|
57
|
+
return;
|
|
58
|
+
addEntryRenames(group, patternPath);
|
|
59
|
+
};
|
|
60
|
+
export const renameObjectEntriesParametersTransform = {
|
|
61
|
+
id: "rename-object-entries-parameters",
|
|
62
|
+
description: "Renames Object.entries callback parameters to $key/$value when safe, with stable/readable fallback managed by RenameGroup",
|
|
63
|
+
scope: "file",
|
|
64
|
+
parallelizable: true,
|
|
65
|
+
transform(context) {
|
|
66
|
+
let nodesVisited = 0;
|
|
67
|
+
let transformationsApplied = 0;
|
|
68
|
+
for (const fileInfo of getFilesToProcess(context)) {
|
|
69
|
+
if (hasDynamicNameLookup(fileInfo.ast))
|
|
70
|
+
continue;
|
|
71
|
+
const group = new RenameGroup();
|
|
72
|
+
traverse(fileInfo.ast, {
|
|
73
|
+
CallExpression(path) {
|
|
74
|
+
nodesVisited++;
|
|
75
|
+
collectEntriesConsumerRenames(path, group);
|
|
76
|
+
},
|
|
77
|
+
OptionalCallExpression(path) {
|
|
78
|
+
nodesVisited++;
|
|
79
|
+
collectEntriesConsumerRenames(path, group);
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
transformationsApplied += group.apply();
|
|
83
|
+
}
|
|
84
|
+
return Promise.resolve({ nodesVisited, transformationsApplied });
|
|
85
|
+
},
|
|
86
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { NodePath } from "@babel/traverse";
|
|
2
|
+
import type { ArrowFunctionExpression, CallExpression, FunctionExpression, OptionalCallExpression } from "@babel/types";
|
|
3
|
+
export type UpdaterFunctionPath = NodePath<ArrowFunctionExpression | FunctionExpression>;
|
|
4
|
+
type SetStateCallPath = NodePath<CallExpression | OptionalCallExpression>;
|
|
5
|
+
export declare const getUpdaterFunctionPath: (path: SetStateCallPath) => UpdaterFunctionPath | undefined;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
const isSetStateMemberExpression = (member) => {
|
|
2
|
+
if (member.computed) {
|
|
3
|
+
return member.property.type === "StringLiteral"
|
|
4
|
+
? member.property.value === "setState"
|
|
5
|
+
: false;
|
|
6
|
+
}
|
|
7
|
+
return member.property.type === "Identifier"
|
|
8
|
+
? member.property.name === "setState"
|
|
9
|
+
: false;
|
|
10
|
+
};
|
|
11
|
+
const isThisAliasIdentifier = (scope, name) => {
|
|
12
|
+
const binding = scope.getBinding(name);
|
|
13
|
+
if (!binding)
|
|
14
|
+
return false;
|
|
15
|
+
if (!binding.constant)
|
|
16
|
+
return false;
|
|
17
|
+
if (!binding.path.isVariableDeclarator())
|
|
18
|
+
return false;
|
|
19
|
+
const init = binding.path.node.init;
|
|
20
|
+
if (!init)
|
|
21
|
+
return false;
|
|
22
|
+
return unwrapExpression(init).type === "ThisExpression";
|
|
23
|
+
};
|
|
24
|
+
const unwrapExpression = (expression) => {
|
|
25
|
+
let current = expression;
|
|
26
|
+
for (;;) {
|
|
27
|
+
if (current.type === "TSNonNullExpression") {
|
|
28
|
+
current = current.expression;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (current.type === "TSAsExpression") {
|
|
32
|
+
current = current.expression;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (current.type === "TSSatisfiesExpression") {
|
|
36
|
+
current = current.expression;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (current.type === "TSTypeAssertion") {
|
|
40
|
+
current = current.expression;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (current.type === "ParenthesizedExpression") {
|
|
44
|
+
current = current.expression;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
return current;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const isThisSetStateReceiver = (scope, object) => {
|
|
51
|
+
if (object.type === "Super")
|
|
52
|
+
return false;
|
|
53
|
+
const unwrapped = unwrapExpression(object);
|
|
54
|
+
if (unwrapped.type === "ThisExpression")
|
|
55
|
+
return true;
|
|
56
|
+
if (unwrapped.type !== "Identifier")
|
|
57
|
+
return false;
|
|
58
|
+
return isThisAliasIdentifier(scope, unwrapped.name);
|
|
59
|
+
};
|
|
60
|
+
export const getUpdaterFunctionPath = (path) => {
|
|
61
|
+
const callee = path.node.callee;
|
|
62
|
+
if (callee.type !== "MemberExpression" &&
|
|
63
|
+
callee.type !== "OptionalMemberExpression") {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
if (!isSetStateMemberExpression(callee))
|
|
67
|
+
return undefined;
|
|
68
|
+
if (!isThisSetStateReceiver(path.scope, callee.object))
|
|
69
|
+
return undefined;
|
|
70
|
+
const argumentPaths = path.get("arguments");
|
|
71
|
+
if (!Array.isArray(argumentPaths))
|
|
72
|
+
return undefined;
|
|
73
|
+
const updaterPath = argumentPaths.at(0);
|
|
74
|
+
if (updaterPath === undefined)
|
|
75
|
+
return undefined;
|
|
76
|
+
if (!updaterPath.isArrowFunctionExpression() &&
|
|
77
|
+
!updaterPath.isFunctionExpression()) {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
return updaterPath;
|
|
81
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"recommended": true,
|
|
3
|
+
"evaluations": {
|
|
4
|
+
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
5
|
+
"diffSizePercent": 100,
|
|
6
|
+
"evaluatedAt": "2026-02-06T14:45:47.110Z",
|
|
7
|
+
"changedLines": 44,
|
|
8
|
+
"durationSeconds": 167.840422062,
|
|
9
|
+
"stableNames": 1358
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"notes": "Added to recommended for readability."
|
|
13
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { isIdentifierName, isKeyword, isStrictBindReservedWord, } from "@babel/helper-validator-identifier";
|
|
3
|
+
import { RenameGroup, isStableRenamed } from "../../core/stable-naming.js";
|
|
4
|
+
import { getFilesToProcess, } from "../../core/types.js";
|
|
5
|
+
import { hasDynamicNameLookup } from "../stabilize-nested-bindings/has-dynamic-name-lookup.js";
|
|
6
|
+
import { getUpdaterFunctionPath, } from "./get-updater-function-path.js";
|
|
7
|
+
const BASE_NAME = "prevState";
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
10
|
+
const traverse = require("@babel/traverse").default;
|
|
11
|
+
const isSafeIdentifierName = (name) => {
|
|
12
|
+
if (!isIdentifierName(name))
|
|
13
|
+
return false;
|
|
14
|
+
if (isKeyword(name))
|
|
15
|
+
return false;
|
|
16
|
+
if (isStrictBindReservedWord(name, true))
|
|
17
|
+
return false;
|
|
18
|
+
return true;
|
|
19
|
+
};
|
|
20
|
+
const getUpdaterParameter = (path) => {
|
|
21
|
+
const parameter = path.node.params[0];
|
|
22
|
+
if (!parameter)
|
|
23
|
+
return undefined;
|
|
24
|
+
if (parameter.type !== "Identifier")
|
|
25
|
+
return undefined;
|
|
26
|
+
return parameter;
|
|
27
|
+
};
|
|
28
|
+
const addRenameCandidate = (path, renameGroup) => {
|
|
29
|
+
if (hasDynamicNameLookup(path))
|
|
30
|
+
return;
|
|
31
|
+
const parameter = getUpdaterParameter(path);
|
|
32
|
+
if (!parameter)
|
|
33
|
+
return;
|
|
34
|
+
if (isStableRenamed(parameter.name))
|
|
35
|
+
return;
|
|
36
|
+
const binding = path.scope.getBinding(parameter.name);
|
|
37
|
+
if (!binding)
|
|
38
|
+
return;
|
|
39
|
+
if (!binding.constant)
|
|
40
|
+
return;
|
|
41
|
+
// Skip unused updater parameters to avoid adding semantic noise.
|
|
42
|
+
if (binding.referencePaths.length === 0)
|
|
43
|
+
return;
|
|
44
|
+
renameGroup.add({
|
|
45
|
+
scope: path.scope,
|
|
46
|
+
currentName: parameter.name,
|
|
47
|
+
baseName: BASE_NAME,
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
export const renameSetstateUpdaterParametersTransform = {
|
|
51
|
+
id: "rename-setstate-updater-parameters",
|
|
52
|
+
description: "Renames updater parameters from this.setState calls to $prevState",
|
|
53
|
+
scope: "file",
|
|
54
|
+
parallelizable: true,
|
|
55
|
+
transform(context) {
|
|
56
|
+
let nodesVisited = 0;
|
|
57
|
+
let transformationsApplied = 0;
|
|
58
|
+
if (!isSafeIdentifierName(`$${BASE_NAME}`)) {
|
|
59
|
+
return Promise.resolve({ nodesVisited, transformationsApplied });
|
|
60
|
+
}
|
|
61
|
+
for (const fileInfo of getFilesToProcess(context)) {
|
|
62
|
+
const renameGroup = new RenameGroup();
|
|
63
|
+
traverse(fileInfo.ast, {
|
|
64
|
+
CallExpression(path) {
|
|
65
|
+
nodesVisited++;
|
|
66
|
+
const updaterPath = getUpdaterFunctionPath(path);
|
|
67
|
+
if (!updaterPath)
|
|
68
|
+
return;
|
|
69
|
+
addRenameCandidate(updaterPath, renameGroup);
|
|
70
|
+
},
|
|
71
|
+
OptionalCallExpression(path) {
|
|
72
|
+
nodesVisited++;
|
|
73
|
+
const updaterPath = getUpdaterFunctionPath(path);
|
|
74
|
+
if (!updaterPath)
|
|
75
|
+
return;
|
|
76
|
+
addRenameCandidate(updaterPath, renameGroup);
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
transformationsApplied += renameGroup.apply();
|
|
80
|
+
}
|
|
81
|
+
return Promise.resolve({ nodesVisited, transformationsApplied });
|
|
82
|
+
},
|
|
83
|
+
};
|
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.85.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",
|