@blumintinc/eslint-plugin-blumint 1.20.188 → 1.20.189
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
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TSESLint } from '@typescript-eslint/utils';
|
|
1
2
|
type MessageIds = 'avoidEntireObject' | 'removeUnusedDependency';
|
|
2
|
-
export declare const noEntireObjectHookDeps:
|
|
3
|
+
export declare const noEntireObjectHookDeps: TSESLint.RuleModule<MessageIds, [], TSESLint.RuleListener>;
|
|
3
4
|
export {};
|
|
@@ -1167,6 +1167,48 @@ function getObjectUsagesInHook(hookBody, objectName, typeInfo, bodyIsDeferred =
|
|
|
1167
1167
|
notUsed,
|
|
1168
1168
|
};
|
|
1169
1169
|
}
|
|
1170
|
+
/** The run of spaces/tabs opening the line that `offset` sits on. */
|
|
1171
|
+
function indentAt(text, offset) {
|
|
1172
|
+
const lineStart = text.lastIndexOf('\n', offset - 1) + 1;
|
|
1173
|
+
return /^[ \t]*/.exec(text.slice(lineStart, offset))?.[0] ?? '';
|
|
1174
|
+
}
|
|
1175
|
+
/**
|
|
1176
|
+
* Drop `span`, but re-emit any comment standing inside it.
|
|
1177
|
+
*
|
|
1178
|
+
* Removing a dependency means removing its separator too, so the span reaches
|
|
1179
|
+
* to a NEIGHBOURING element and therefore covers the margin between the two.
|
|
1180
|
+
* That margin is not the fixer's to delete: it can hold an
|
|
1181
|
+
* `eslint-disable-next-line` protecting the dependency that survives, and
|
|
1182
|
+
* dropping that directive silently re-enables another rule (#2208). Declining
|
|
1183
|
+
* the fix instead would only trade the lost comment for a transform that a
|
|
1184
|
+
* comment decides (#1877), so the comment is carried rather than obeyed.
|
|
1185
|
+
*
|
|
1186
|
+
* Each carried comment is re-emitted on a line of its own: a `//` comment
|
|
1187
|
+
* swallows whatever follows it on the same line, so folding one inline would
|
|
1188
|
+
* comment out the dependency that was meant to survive.
|
|
1189
|
+
*/
|
|
1190
|
+
function removeCarryingComments(fixer, sourceCode, span, anchor) {
|
|
1191
|
+
const carried = sourceCode
|
|
1192
|
+
.getAllComments()
|
|
1193
|
+
.filter((comment) => comment.range[0] >= span[0] && comment.range[1] <= span[1]);
|
|
1194
|
+
// With nothing to preserve the span is pure separator and whitespace, so the
|
|
1195
|
+
// plain removal keeps the comment-free output exactly as it has always been.
|
|
1196
|
+
if (carried.length === 0) {
|
|
1197
|
+
return fixer.removeRange(span);
|
|
1198
|
+
}
|
|
1199
|
+
const text = sourceCode.getText();
|
|
1200
|
+
// Anchor the indentation on the end the surviving code sits against.
|
|
1201
|
+
const indent = indentAt(text, anchor === 'toNextElement' ? span[1] : carried[0].range[0]);
|
|
1202
|
+
const body = carried
|
|
1203
|
+
.map((comment) => text.slice(comment.range[0], comment.range[1]))
|
|
1204
|
+
.join(`\n${indent}`);
|
|
1205
|
+
// Both spellings close on a fresh line: whatever the span abutted — the next
|
|
1206
|
+
// dependency, or the separator trailing the last one — would otherwise land
|
|
1207
|
+
// on the final carried comment's line and be commented out.
|
|
1208
|
+
return fixer.replaceTextRange(span, anchor === 'toNextElement'
|
|
1209
|
+
? `${body}\n${indent}`
|
|
1210
|
+
: `\n${indent}${body}\n${indent}`);
|
|
1211
|
+
}
|
|
1170
1212
|
exports.noEntireObjectHookDeps = (0, createRule_1.createRule)({
|
|
1171
1213
|
name: 'no-entire-object-hook-deps',
|
|
1172
1214
|
meta: {
|
|
@@ -1339,21 +1381,19 @@ exports.noEntireObjectHookDeps = (0, createRule_1.createRule)({
|
|
|
1339
1381
|
if (elementIndex === depsArg.elements.length - 1) {
|
|
1340
1382
|
const prevElement = depsArg.elements[elementIndex - 1];
|
|
1341
1383
|
if (prevElement) {
|
|
1342
|
-
|
|
1384
|
+
return removeCarryingComments(fixer, sourceCode, [
|
|
1343
1385
|
prevElement.range[1],
|
|
1344
1386
|
element.range[1],
|
|
1345
|
-
];
|
|
1346
|
-
return fixer.removeRange(range);
|
|
1387
|
+
], 'fromPrevElement');
|
|
1347
1388
|
}
|
|
1348
1389
|
}
|
|
1349
1390
|
// Otherwise, remove the element and the following comma
|
|
1350
1391
|
const nextElement = depsArg.elements[elementIndex + 1];
|
|
1351
1392
|
if (nextElement) {
|
|
1352
|
-
|
|
1393
|
+
return removeCarryingComments(fixer, sourceCode, [
|
|
1353
1394
|
element.range[0],
|
|
1354
1395
|
nextElement.range[0],
|
|
1355
|
-
];
|
|
1356
|
-
return fixer.removeRange(range);
|
|
1396
|
+
], 'toNextElement');
|
|
1357
1397
|
}
|
|
1358
1398
|
// Fallback to just removing the element
|
|
1359
1399
|
return fixer.remove(element);
|
package/package.json
CHANGED
package/release-manifest.json
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "1.20.189",
|
|
4
|
+
"date": "2026-08-29T11:57:05.586Z",
|
|
5
|
+
"rules": [
|
|
6
|
+
{
|
|
7
|
+
"name": "no-entire-object-hook-deps",
|
|
8
|
+
"changeType": "fix",
|
|
9
|
+
"issues": [
|
|
10
|
+
2208
|
|
11
|
+
],
|
|
12
|
+
"summary": "carry comments in the removed dep's margin (closes #2208)"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
},
|
|
2
16
|
{
|
|
3
17
|
"version": "1.20.188",
|
|
4
18
|
"date": "2026-08-29T07:11:55.294Z",
|