@blumintinc/eslint-plugin-blumint 1.20.2 → 1.20.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +1 -1
- package/lib/rules/no-unnecessary-verb-suffix.js +49 -3
- package/package.json +1 -1
- package/release-manifest.json +28 -0
package/lib/index.js
CHANGED
|
@@ -166,6 +166,28 @@ function isExported(node) {
|
|
|
166
166
|
}
|
|
167
167
|
return false;
|
|
168
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Renames `identifier` to `newName` while leaving every other token inside the
|
|
171
|
+
* identifier's range intact.
|
|
172
|
+
*
|
|
173
|
+
* A TSESTree `Identifier` node's range spans the tokens that trail its name:
|
|
174
|
+
* a type annotation (`validateBy: Validator`), a definite-assignment assertion
|
|
175
|
+
* (`validateBy!: Validator`) and an optional marker (`cbBy?: Fn`). Replacing the
|
|
176
|
+
* whole node therefore deletes them, and dropping a contextual type turns
|
|
177
|
+
* inferred parameters into implicit `any` so the file no longer compiles — a
|
|
178
|
+
* silent corruption, since the rule reports nothing afterwards (#1351). The name
|
|
179
|
+
* is always the identifier's first token, so replacing that token's range alone
|
|
180
|
+
* renames the symbol and nothing else.
|
|
181
|
+
*/
|
|
182
|
+
function renameIdentifier(fixer, sourceCode, identifier, newName) {
|
|
183
|
+
const nameToken = sourceCode.getFirstToken(identifier);
|
|
184
|
+
// The token store yields the name for every real identifier; the arithmetic
|
|
185
|
+
// end keeps the range narrowed even if a token is somehow unavailable.
|
|
186
|
+
const nameEnd = nameToken
|
|
187
|
+
? nameToken.range[1]
|
|
188
|
+
: identifier.range[0] + identifier.name.length;
|
|
189
|
+
return fixer.replaceTextRange([identifier.range[0], nameEnd], newName);
|
|
190
|
+
}
|
|
169
191
|
/**
|
|
170
192
|
* Walks a scope chain upward from `scope` (inclusive) and reports whether
|
|
171
193
|
* `targetName` is bound anywhere between `scope` and `stopScope` (inclusive).
|
|
@@ -561,16 +583,40 @@ exports.noUnnecessaryVerbSuffix = (0, createRule_1.createRule)({
|
|
|
561
583
|
// Scope-tracked symbols (FunctionDeclaration, VariableDeclarator
|
|
562
584
|
// arrows/functions, named FunctionExpression): rename the
|
|
563
585
|
// declaration identifier and every in-file reference together so
|
|
564
|
-
// no call site is left pointing at the old name.
|
|
586
|
+
// no call site is left pointing at the old name. Every rewrite
|
|
587
|
+
// goes through renameIdentifier, because an identifier's range
|
|
588
|
+
// can carry trailing tokens that must survive a rename (#1351).
|
|
589
|
+
const { sourceCode } = context;
|
|
565
590
|
const fixes = [
|
|
566
|
-
fixer
|
|
591
|
+
renameIdentifier(fixer, sourceCode, declarationIdNode, suggestion),
|
|
567
592
|
];
|
|
568
593
|
if (targetVariable) {
|
|
569
594
|
for (const ref of targetVariable.references) {
|
|
570
595
|
// Skip the declaration identifier itself — already handled.
|
|
571
596
|
if (ref.identifier === declarationIdNode)
|
|
572
597
|
continue;
|
|
573
|
-
|
|
598
|
+
const refParent = ref.identifier.parent;
|
|
599
|
+
// An object-literal shorthand `{ fooBar }` desugars to
|
|
600
|
+
// `{ fooBar: fooBar }`: the one token is both the property
|
|
601
|
+
// key and its value. Renaming it would rename the KEY too,
|
|
602
|
+
// silently changing the object's shape so every
|
|
603
|
+
// `obj.fooBar` consumer reads undefined. Expand to
|
|
604
|
+
// `oldKey: newName` so only the value moves (#1352).
|
|
605
|
+
if (refParent?.type === utils_1.AST_NODE_TYPES.Property &&
|
|
606
|
+
refParent.shorthand &&
|
|
607
|
+
refParent.parent?.type === utils_1.AST_NODE_TYPES.ObjectExpression) {
|
|
608
|
+
fixes.push(fixer.replaceText(ref.identifier, `${name}: ${suggestion}`));
|
|
609
|
+
continue;
|
|
610
|
+
}
|
|
611
|
+
// A re-export specifier `export { fooBar }` binds the public
|
|
612
|
+
// export name to this identifier, a cross-file contract a
|
|
613
|
+
// single-file fixer cannot rewrite. The declaration-level
|
|
614
|
+
// export guard misses this form because the declaration
|
|
615
|
+
// itself carries no `export` keyword (#1352).
|
|
616
|
+
if (refParent?.type === utils_1.AST_NODE_TYPES.ExportSpecifier) {
|
|
617
|
+
return null;
|
|
618
|
+
}
|
|
619
|
+
fixes.push(renameIdentifier(fixer, sourceCode, ref.identifier, suggestion));
|
|
574
620
|
}
|
|
575
621
|
}
|
|
576
622
|
return fixes;
|
package/package.json
CHANGED
package/release-manifest.json
CHANGED
|
@@ -1,4 +1,32 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "1.20.4",
|
|
4
|
+
"date": "2026-07-25T03:08:45.043Z",
|
|
5
|
+
"rules": [
|
|
6
|
+
{
|
|
7
|
+
"name": "no-unnecessary-verb-suffix",
|
|
8
|
+
"changeType": "fix",
|
|
9
|
+
"issues": [
|
|
10
|
+
1352
|
|
11
|
+
],
|
|
12
|
+
"summary": "stop the rename autofix from renaming shorthand keys and re-exported names (closes #1352)"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"version": "1.20.3",
|
|
18
|
+
"date": "2026-07-25T02:54:46.197Z",
|
|
19
|
+
"rules": [
|
|
20
|
+
{
|
|
21
|
+
"name": "no-unnecessary-verb-suffix",
|
|
22
|
+
"changeType": "fix",
|
|
23
|
+
"issues": [
|
|
24
|
+
1351
|
|
25
|
+
],
|
|
26
|
+
"summary": "preserve type annotations when the rename autofix renames an identifier (closes #1351)"
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
},
|
|
2
30
|
{
|
|
3
31
|
"version": "1.20.2",
|
|
4
32
|
"date": "2026-07-25T02:42:18.863Z",
|