eslint-rule-forge 0.5.0 → 0.6.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.
@@ -1,7 +1,6 @@
1
1
  import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
2
2
  import * as ts from 'typescript';
3
- import { hasForeignBinding } from '../bindings.mjs';
4
- import { bindValueImports } from '../imports.mjs';
3
+ import { bindValueImportsAt } from '../imports.mjs';
5
4
  import { getArgumentText } from '../parentheses.mjs';
6
5
  import { isIdentifierNamed, skipTypeWrappers, typeHoldsAtEveryLayer, } from '../type-wrappers.mjs';
7
6
 
@@ -18,8 +17,8 @@ export const createPreferIsRecordAndHasKey = ({ moduleName, }) => ({
18
17
  fixable: 'code',
19
18
  schema: [],
20
19
  messages: {
21
- useIsRecordAndHasKey: `Replace \`{{original}}\` with \`isRecord({{objName}}) && hasKey({{objName}}, {{keyName}})\` from ${moduleName}.`,
22
- useHasKey: `Replace \`{{original}}\` with \`hasKey({{objName}}, {{keyName}})\` from ${moduleName}.`,
20
+ useIsRecordAndHasKey: `Replace \`{{original}}\` with \`{{isRecord}}({{objName}}) && {{hasKey}}({{objName}}, {{keyName}})\` from ${moduleName}.`,
21
+ useHasKey: `Replace \`{{original}}\` with \`{{hasKey}}({{objName}}, {{keyName}})\` from ${moduleName}.`,
23
22
  },
24
23
  defaultOptions: [],
25
24
  },
@@ -99,20 +98,23 @@ export const createPreferIsRecordAndHasKey = ({ moduleName, }) => ({
99
98
  });
100
99
  },
101
100
  'Program:exit': () => {
101
+ if (mut_nodesToFix.length === 0) {
102
+ return;
103
+ }
102
104
 
103
105
 
104
- const withIsRecord = bindValueImports(sourceCode, moduleName, [
106
+ const withIsRecordAt = bindValueImportsAt(sourceCode, moduleName, [
105
107
  'isRecord',
106
108
  'hasKey',
107
109
  ]);
108
- const hasKeyOnly = bindValueImports(sourceCode, moduleName, [
110
+ const hasKeyOnlyAt = bindValueImportsAt(sourceCode, moduleName, [
109
111
  'hasKey',
110
112
  ]);
111
113
  for (const { node, objExpression, keyExpression } of mut_nodesToFix) {
112
114
 
113
115
 
114
116
  const needsIsRecord = !isKnownRecord(objExpression);
115
- const binding = needsIsRecord ? withIsRecord : hasKeyOnly;
117
+ const binding = (needsIsRecord ? withIsRecordAt : hasKeyOnlyAt)(node);
116
118
  const hasKeyName = binding?.localNames.at(-1);
117
119
  const isRecordName = needsIsRecord
118
120
  ? binding?.localNames[0]
@@ -123,8 +125,7 @@ export const createPreferIsRecordAndHasKey = ({ moduleName, }) => ({
123
125
  hasKeyName !== undefined &&
124
126
  (!needsIsRecord || isRecordName !== undefined) &&
125
127
 
126
- (!needsIsRecord || isSideEffectFree(objExpression)) &&
127
- binding.localNames.every((name) => !hasForeignBinding(sourceCode, node, name, moduleName));
128
+ (!needsIsRecord || isSideEffectFree(objExpression));
128
129
  context.report({
129
130
  node,
130
131
  messageId: needsIsRecord ? 'useIsRecordAndHasKey' : 'useHasKey',
@@ -132,6 +133,10 @@ export const createPreferIsRecordAndHasKey = ({ moduleName, }) => ({
132
133
  original: sourceCode.getText(node),
133
134
  objName: objText,
134
135
  keyName: keyText,
136
+
137
+
138
+ isRecord: isRecordName ?? 'isRecord',
139
+ hasKey: hasKeyName ?? 'hasKey',
135
140
  },
136
141
  fix: fixable
137
142
  ? (fixer) => [
@@ -1 +1 @@
1
- {"version":3,"file":"prefer-is-record-and-has-key.mjs","sourceRoot":"","sources":["../../src/rules/prefer-is-record-and-has-key.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prefer-is-record-and-has-key.mjs","sourceRoot":"","sources":["../../src/rules/prefer-is-record-and-has-key.mts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"prefer-safe-parse.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-safe-parse.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAYlC,yEAAyE;AACzE,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;IAEnB,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,WAC3B,mBAAmB,KAC1B,QAAQ,CAAC,UAAU,CACpB,iBAAiB,GAAG,sBAAsB,EAC1C,SAAS,EAAE,CAuBT,CAAC;AAEL;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,WAC7B,mBAAmB,KAC1B,QAAQ,CAAC,UAAU,CACpB,mBAAmB,GAAG,sBAAsB,EAC5C,SAAS,EAAE,CAWT,CAAC"}
1
+ {"version":3,"file":"prefer-safe-parse.d.mts","sourceRoot":"","sources":["../../src/rules/prefer-safe-parse.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAWlC,yEAAyE;AACzE,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;IAEnB,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,WAC3B,mBAAmB,KAC1B,QAAQ,CAAC,UAAU,CACpB,iBAAiB,GAAG,sBAAsB,EAC1C,SAAS,EAAE,CAuBT,CAAC;AAEL;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,WAC7B,mBAAmB,KAC1B,QAAQ,CAAC,UAAU,CACpB,mBAAmB,GAAG,sBAAsB,EAC5C,SAAS,EAAE,CAWT,CAAC"}
@@ -1,7 +1,6 @@
1
1
  import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
2
2
  import * as ts from 'typescript';
3
- import { hasForeignBinding } from '../bindings.mjs';
4
- import { bindValueImports } from '../imports.mjs';
3
+ import { bindValueImportsAt } from '../imports.mjs';
5
4
  import { getArgumentText } from '../parentheses.mjs';
6
5
  import { isIdentifierNamed, skipTypeWrappers, typeHoldsAtEveryLayer, } from '../type-wrappers.mjs';
7
6
 
@@ -68,7 +67,7 @@ const createSafeParseRule = ({ moduleName, namespace, method }, messageId, { mes
68
67
  schema: [],
69
68
  messages: {
70
69
  ...messages,
71
- replaceWithSafeParse: `Replace with \`Result.unwrapOkOr(${namespace}.${method}({{argName}}), Number.NaN)\`.`,
70
+ replaceWithSafeParse: `Replace with \`{{resultName}}.unwrapOkOr({{namespaceName}}.${method}({{argName}}), Number.NaN)\`.`,
72
71
  },
73
72
  defaultOptions: [],
74
73
  },
@@ -99,20 +98,27 @@ const createSafeParseRule = ({ moduleName, namespace, method }, messageId, { mes
99
98
  mut_reports.push({ node, argExpression: firstArg });
100
99
  },
101
100
  'Program:exit': () => {
102
- const binding = bindValueImports(sourceCode, moduleName, requiredImports);
103
- const localNameOf = (name) => binding?.localNames[requiredImports.indexOf(name)];
104
- const namespaceName = localNameOf(namespace);
105
- const resultName = localNameOf('Result');
101
+ if (mut_reports.length === 0) {
102
+ return;
103
+ }
104
+ const bindingAt = bindValueImportsAt(sourceCode, moduleName, requiredImports);
106
105
 
107
106
 
108
107
 
109
108
 
110
109
 
111
110
  for (const { node, argExpression } of mut_reports) {
111
+ const binding = bindingAt(node);
112
+ const localNameOf = (name) => binding?.localNames[requiredImports.indexOf(name)];
113
+ const namespaceName = localNameOf(namespace);
114
+ const resultName = localNameOf('Result');
112
115
  const argText = getArgumentText(sourceCode, argExpression);
113
116
  const data = {
114
117
  original: sourceCode.getText(node),
115
118
  argName: argText,
119
+
120
+ namespaceName: namespaceName ?? namespace,
121
+ resultName: resultName ?? 'Result',
116
122
  };
117
123
  context.report({
118
124
  node,
@@ -120,8 +126,7 @@ const createSafeParseRule = ({ moduleName, namespace, method }, messageId, { mes
120
126
  data,
121
127
  suggest: binding === undefined ||
122
128
  namespaceName === undefined ||
123
- resultName === undefined ||
124
- [namespaceName, resultName].some((name) => hasForeignBinding(sourceCode, node, name, moduleName))
129
+ resultName === undefined
125
130
  ? []
126
131
  : [
127
132
  {
@@ -140,7 +145,11 @@ const createSafeParseRule = ({ moduleName, namespace, method }, messageId, { mes
140
145
  },
141
146
  };
142
147
  };
143
- const messageText = ({ moduleName, namespace, method, }) => `Replace \`{{original}}\` with \`Result.unwrapOkOr(${namespace}.${method}({{argName}}), Number.NaN)\` from ${moduleName}. It parses some strings differently from the call it replaces, so check the input before applying it.`;
148
+
149
+
150
+
151
+
152
+ const messageText = ({ moduleName, method }) => `Replace \`{{original}}\` with \`{{resultName}}.unwrapOkOr({{namespaceName}}.${method}({{argName}}), Number.NaN)\` from ${moduleName}. It parses some strings differently from the call it replaces, so check the input before applying it.`;
144
153
 
145
154
  const isGlobalCall = (callee, name) => callee.type === AST_NODE_TYPES.Identifier && callee.name === name;
146
155
 
@@ -1 +1 @@
1
- {"version":3,"file":"prefer-safe-parse.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-parse.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prefer-safe-parse.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-parse.mts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-rule-forge",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "private": false,
5
5
  "description": "Helpers for writing typescript-eslint rules that see through type wrappers and parentheses, and resolve what a file imports.",
6
6
  "keywords": [
@@ -41,14 +41,14 @@
41
41
  "@typescript-eslint/rule-tester": "8.72.0",
42
42
  "dedent": "1.7.2",
43
43
  "eslint": "10.13.0",
44
- "eslint-config-typed": "7.3.0",
45
- "eslint-plugin-ts-fortress": "1.3.12",
46
- "eslint-plugin-ts-type-forge": "0.8.17",
44
+ "eslint-config-typed": "7.5.0",
45
+ "eslint-plugin-ts-fortress": "1.3.14",
46
+ "eslint-plugin-ts-type-forge": "0.8.19",
47
47
  "prettier": "3.9.10",
48
48
  "prettier-plugin-organize-imports": "4.3.0",
49
49
  "prettier-plugin-packagejson": "3.0.2",
50
- "ts-data-forge": "14.10.1",
51
- "ts-repo-utils": "10.7.1"
50
+ "ts-data-forge": "14.11.0",
51
+ "ts-repo-utils": "10.7.3"
52
52
  },
53
53
  "peerDependencies": {
54
54
  "eslint": ">=9.0.0",
package/src/bindings.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  AST_NODE_TYPES,
3
3
  ASTUtils,
4
- type TSESLint,
4
+ TSESLint,
5
5
  type TSESTree,
6
6
  } from '@typescript-eslint/utils';
7
7
 
@@ -33,7 +33,13 @@ export const isLocallyBound = (
33
33
  * has to give up then, because the name would refer to that binding instead.
34
34
  *
35
35
  * The innermost binding decides: an import from `moduleName` at the top of the
36
- * file does not help a name a function shadows around `node`.
36
+ * file does not help a name a function shadows around `node`. A binding with no
37
+ * value meaning inside the file — a type parameter, a local type alias or
38
+ * interface — is passed over, since a type does not shadow a value or the head
39
+ * of a qualified name. At the top of the file it still counts: the import a fix
40
+ * adds there conflicts with it when the export has a type meaning too. A fix
41
+ * that writes the name alone in a type position, where such a binding does
42
+ * capture it, has to check for one itself.
37
43
  */
38
44
  export const hasForeignBinding = (
39
45
  sourceCode: TSESLint.SourceCode,
@@ -41,11 +47,45 @@ export const hasForeignBinding = (
41
47
  name: string,
42
48
  moduleName: string,
43
49
  ): boolean => {
44
- const variable = ASTUtils.findVariable(sourceCode.getScope(node), name);
50
+ const variable = findShadowingVariable(sourceCode.getScope(node), name);
45
51
 
46
52
  return variable?.defs.some((def) => !isImportFrom(def, moduleName)) ?? false;
47
53
  };
48
54
 
55
+ /**
56
+ * Whether every definition of `variable` is a type parameter, type alias or
57
+ * interface. Read from `def.type` rather than `isValueVariable`, which ESLint's
58
+ * own scope manager, used with its default parser, does not have.
59
+ */
60
+ const isTypeOnly = (variable: TSESLint.Scope.Variable): boolean =>
61
+ variable.defs.length > 0 &&
62
+ variable.defs.every((def) => def.type === TSESLint.Scope.DefinitionType.Type);
63
+
64
+ /**
65
+ * Whether `scope` is the file's own, where an added import lands: the module or
66
+ * global scope, or the function scope a CommonJS file wraps around them.
67
+ */
68
+ const isTopLevel = (scope: TSESLint.Scope.Scope): boolean =>
69
+ scope.block.type === AST_NODE_TYPES.Program;
70
+
71
+ /**
72
+ * The innermost variable named `name` from `scope` outwards that a value of
73
+ * that name written in `scope` would meet: one with a value meaning, or any at
74
+ * the top of the file.
75
+ */
76
+ const findShadowingVariable = (
77
+ scope: TSESLint.Scope.Scope,
78
+ name: string,
79
+ ): TSESLint.Scope.Variable | undefined => {
80
+ const variable = scope.set.get(name);
81
+
82
+ return variable !== undefined && (!isTypeOnly(variable) || isTopLevel(scope))
83
+ ? variable
84
+ : scope.upper === null
85
+ ? undefined
86
+ : findShadowingVariable(scope.upper, name);
87
+ };
88
+
49
89
  /**
50
90
  * Whether `def` is a binding an `import … from '<moduleName>'` declaration
51
91
  * introduces.
package/src/imports.mts CHANGED
@@ -4,6 +4,7 @@ import {
4
4
  type TSESTree,
5
5
  } from '@typescript-eslint/utils';
6
6
  import type { DeepReadonly } from 'ts-type-forge';
7
+ import { hasForeignBinding } from './bindings.mjs';
7
8
  import { isTypeWrapper, skipTypeWrappers } from './type-wrappers.mjs';
8
9
 
9
10
  /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
@@ -224,47 +225,60 @@ export const bindValueImports = (
224
225
  sourceCode: TSESLint.SourceCode,
225
226
  moduleName: string,
226
227
  exportNames: readonly string[],
227
- ): ValueImportBinding | undefined => {
228
- const program = sourceCode.ast;
229
-
230
- const allImports = program.body.filter(
231
- (node): node is TSESTree.ImportDeclaration =>
232
- node.type === AST_NODE_TYPES.ImportDeclaration,
233
- );
234
-
235
- const declarations = getImportDeclarations(program, moduleName);
236
-
237
- const named = declarations.flatMap((declaration) =>
238
- declaration.specifiers.flatMap((specifier) =>
239
- specifier.type === AST_NODE_TYPES.ImportSpecifier
240
- ? [{ declaration, specifier }]
241
- : [],
242
- ),
243
- );
228
+ ): ValueImportBinding | undefined =>
229
+ bindNames(sourceCode, moduleName, exportNames, undefined);
244
230
 
245
- const bindings = exportNames.map((exportName) =>
246
- bindingOf(sourceCode, allImports, named, exportName),
247
- );
248
-
249
- if (bindings.includes(undefined)) {
250
- return undefined;
251
- }
252
-
253
- const defined = bindings.filter((b) => b !== undefined);
254
-
255
- const toAdd = defined.flatMap((b) => (b.isAdded ? [b.localName] : []));
256
-
257
- const hosts = hostsFor(declarations);
231
+ /**
232
+ * {@link bindValueImports} for the code at a node, which writes an export
233
+ * through a namespace import of the module (`ns.f` after
234
+ * `import * as ns from '<moduleName>'`) rather than importing it by name beside
235
+ * the namespace. Gives, for a node, what a fix there writes, or `undefined`
236
+ * when no fix can: an import binds a name to something else, or something other
237
+ * than an import from the module takes a name the fix writes where the node is
238
+ * ({@link hasForeignBinding}).
239
+ *
240
+ * - An export imported as a value is written by its local name, as
241
+ * {@link bindValueImports} writes it.
242
+ * - Any other, one imported only by `import { type x }` included, goes through
243
+ * the first namespace import that is not `import type * as`, with no edit.
244
+ * - Where a local binding shadows the namespace's name, every export is bound
245
+ * as {@link bindValueImports} binds it instead.
246
+ *
247
+ * Each choice is worked out once, however many nodes ask.
248
+ */
249
+ export const bindValueImportsAt = (
250
+ sourceCode: TSESLint.SourceCode,
251
+ moduleName: string,
252
+ exportNames: readonly string[],
253
+ ): ((node: TSESTree.Node) => ValueImportBinding | undefined) => {
254
+ const namespaceName = getImportDeclarations(sourceCode.ast, moduleName)
255
+ .filter((declaration) => !isTypeOnlyDeclaration(declaration))
256
+ .flatMap((declaration) => declaration.specifiers)
257
+ .find(
258
+ (specifier) => specifier.type === AST_NODE_TYPES.ImportNamespaceSpecifier,
259
+ )?.local.name;
258
260
 
259
- return {
260
- localNames: defined.map((b) => b.localName),
261
- edits: (fixer) => [
262
- ...defined.flatMap((b) => b.edits(fixer)),
263
- ...(toAdd.length === 0
264
- ? []
265
- : addToFirstHost(fixer, sourceCode, moduleName, hosts, toAdd)),
266
- ],
267
- };
261
+ const viaNamespace =
262
+ namespaceName === undefined
263
+ ? undefined
264
+ : bindNames(sourceCode, moduleName, exportNames, namespaceName);
265
+
266
+ const byName = bindNames(sourceCode, moduleName, exportNames, undefined);
267
+
268
+ const holdsAt = (
269
+ binding: BoundNames | undefined,
270
+ node: TSESTree.Node,
271
+ ): binding is BoundNames =>
272
+ binding?.boundNames.every(
273
+ (name) => !hasForeignBinding(sourceCode, node, name, moduleName),
274
+ ) ?? false;
275
+
276
+ return (node) =>
277
+ holdsAt(viaNamespace, node)
278
+ ? viaNamespace
279
+ : holdsAt(byName, node)
280
+ ? byName
281
+ : undefined;
268
282
  };
269
283
 
270
284
  /**
@@ -400,20 +414,6 @@ const addToFirstHost = (
400
414
  : buildNamedImportFix(fixer, sourceCode.ast, moduleName, specifiers);
401
415
  };
402
416
 
403
- /** What {@link bindValueImports} gives. */
404
- export type ValueImportBinding = Readonly<{
405
- /** The names to write, in the order of the export names asked for. */
406
- localNames: readonly string[];
407
-
408
- /** The edits that bring every one of them into scope. */
409
- edits: (fixer: TSESLint.RuleFixer) => readonly TSESLint.RuleFix[];
410
- }>;
411
-
412
- type NamedSpecifier = Readonly<{
413
- declaration: TSESTree.ImportDeclaration;
414
- specifier: TSESTree.ImportSpecifier;
415
- }>;
416
-
417
417
  /** `import type …`. */
418
418
  const isTypeOnlyDeclaration = (
419
419
  declaration: TSESTree.ImportDeclaration,
@@ -460,9 +460,11 @@ const bindingOf = (
460
460
  allImports: readonly TSESTree.ImportDeclaration[],
461
461
  named: readonly NamedSpecifier[],
462
462
  exportName: string,
463
+ namespaceName: string | undefined,
463
464
  ):
464
465
  | Readonly<{
465
466
  localName: string;
467
+ boundName: string;
466
468
  isAdded: boolean;
467
469
  edits: (fixer: TSESLint.RuleFixer) => readonly TSESLint.RuleFix[];
468
470
  }>
@@ -476,6 +478,16 @@ const bindingOf = (
476
478
  if (value !== undefined) {
477
479
  return {
478
480
  localName: value.specifier.local.name,
481
+ boundName: value.specifier.local.name,
482
+ isAdded: false,
483
+ edits: () => [],
484
+ };
485
+ }
486
+
487
+ if (namespaceName !== undefined) {
488
+ return {
489
+ localName: `${namespaceName}.${exportName}`,
490
+ boundName: namespaceName,
479
491
  isAdded: false,
480
492
  edits: () => [],
481
493
  };
@@ -497,6 +509,7 @@ const bindingOf = (
497
509
  ? undefined
498
510
  : {
499
511
  localName: inlineType.local.name,
512
+ boundName: inlineType.local.name,
500
513
  isAdded: false,
501
514
  edits: (fixer) => [
502
515
  fixer.removeRange([typeKeyword.range[0], next.range[0]]),
@@ -512,5 +525,89 @@ const bindingOf = (
512
525
 
513
526
  return isTaken
514
527
  ? undefined
515
- : { localName: exportName, isAdded: true, edits: () => [] };
528
+ : {
529
+ localName: exportName,
530
+ boundName: exportName,
531
+ isAdded: true,
532
+ edits: () => [],
533
+ };
534
+ };
535
+
536
+ /**
537
+ * {@link bindValueImports}, writing an export no value import binds through the
538
+ * namespace import `namespaceName` when there is one. `boundNames` are the
539
+ * names the written text starts with, which something at the node must not
540
+ * shadow.
541
+ */
542
+ const bindNames = (
543
+ sourceCode: TSESLint.SourceCode,
544
+ moduleName: string,
545
+ exportNames: readonly string[],
546
+ namespaceName: string | undefined,
547
+ ): BoundNames | undefined => {
548
+ const program = sourceCode.ast;
549
+
550
+ const allImports = program.body.filter(
551
+ (node): node is TSESTree.ImportDeclaration =>
552
+ node.type === AST_NODE_TYPES.ImportDeclaration,
553
+ );
554
+
555
+ const declarations = getImportDeclarations(program, moduleName);
556
+
557
+ const named = declarations.flatMap((declaration) =>
558
+ declaration.specifiers.flatMap((specifier) =>
559
+ specifier.type === AST_NODE_TYPES.ImportSpecifier
560
+ ? [{ declaration, specifier }]
561
+ : [],
562
+ ),
563
+ );
564
+
565
+ const bindings = exportNames.map((exportName) =>
566
+ bindingOf(sourceCode, allImports, named, exportName, namespaceName),
567
+ );
568
+
569
+ if (bindings.includes(undefined)) {
570
+ return undefined;
571
+ }
572
+
573
+ const defined = bindings.filter((b) => b !== undefined);
574
+
575
+ const toAdd = defined.flatMap((b) => (b.isAdded ? [b.localName] : []));
576
+
577
+ const hosts = hostsFor(declarations);
578
+
579
+ return {
580
+ localNames: defined.map((b) => b.localName),
581
+ boundNames: defined.map((b) => b.boundName),
582
+ edits: (fixer) => [
583
+ ...defined.flatMap((b) => b.edits(fixer)),
584
+ ...(toAdd.length === 0
585
+ ? []
586
+ : addToFirstHost(fixer, sourceCode, moduleName, hosts, toAdd)),
587
+ ],
588
+ };
516
589
  };
590
+
591
+ /** What {@link bindValueImports} and {@link bindValueImportsAt} give. */
592
+ export type ValueImportBinding = Readonly<{
593
+ /**
594
+ * What to write for each export, in the order of the export names asked for:
595
+ * a local name, or `ns.x` through a namespace import.
596
+ */
597
+ localNames: readonly string[];
598
+
599
+ /** The edits that bring every one of them into scope. */
600
+ edits: (fixer: TSESLint.RuleFixer) => readonly TSESLint.RuleFix[];
601
+ }>;
602
+
603
+ /** What {@link bindNames} gives. */
604
+ type BoundNames = ValueImportBinding &
605
+ Readonly<{
606
+ /** The name each of `localNames` starts with. */
607
+ boundNames: readonly string[];
608
+ }>;
609
+
610
+ type NamedSpecifier = Readonly<{
611
+ declaration: TSESTree.ImportDeclaration;
612
+ specifier: TSESTree.ImportSpecifier;
613
+ }>;
@@ -3,8 +3,7 @@ import {
3
3
  type TSESLint,
4
4
  type TSESTree,
5
5
  } from '@typescript-eslint/utils';
6
- import { hasForeignBinding } from '../bindings.mjs';
7
- import { bindValueImports } from '../imports.mjs';
6
+ import { bindValueImportsAt } from '../imports.mjs';
8
7
  import { getRangeWithParens } from '../parentheses.mjs';
9
8
  import { isIdentifierNamed, skipTypeWrappers } from '../type-wrappers.mjs';
10
9
 
@@ -22,19 +21,18 @@ export const createPreferArrayIsArray = ({
22
21
 
23
22
  /** The exported namespace whose `isArray` replaces `Array.isArray`. */
24
23
  namespace: string;
25
- }>): TSESLint.RuleModule<'useIsArray', readonly []> => {
26
- const replacement = `${namespace}.isArray` as const;
27
-
28
- const text =
29
- `Replace \`Array.isArray\` with \`${replacement}\` from ${moduleName}.` as const;
30
-
31
- return {
24
+ }>): TSESLint.RuleModule<'useIsArray', readonly []> =>
25
+ ({
32
26
  meta: {
33
27
  type: 'suggestion',
34
- docs: { description: text },
28
+ docs: {
29
+ description: `Replace \`Array.isArray\` with \`${namespace}.isArray\` from ${moduleName}.`,
30
+ },
35
31
  fixable: 'code',
36
32
  schema: [],
37
- messages: { useIsArray: text },
33
+ messages: {
34
+ useIsArray: `Replace \`Array.isArray\` with \`{{replacement}}\` from ${moduleName}.`,
35
+ },
38
36
  defaultOptions: [],
39
37
  },
40
38
 
@@ -52,20 +50,30 @@ export const createPreferArrayIsArray = ({
52
50
  mut_nodesToFix.push(node);
53
51
  },
54
52
  'Program:exit': () => {
55
- const binding = bindValueImports(sourceCode, moduleName, [namespace]);
53
+ if (mut_nodesToFix.length === 0) {
54
+ return;
55
+ }
56
56
 
57
- const localName = binding?.localNames[0];
57
+ const bindingAt = bindValueImportsAt(sourceCode, moduleName, [
58
+ namespace,
59
+ ]);
58
60
 
59
61
  // Every fix brings the namespace into scope itself, so that one
60
62
  // applied alone (an editor's quick fix) is complete.
61
63
  for (const node of mut_nodesToFix) {
64
+ const binding = bindingAt(node);
65
+
66
+ const localName = binding?.localNames[0];
67
+
62
68
  context.report({
63
69
  node,
64
70
  messageId: 'useIsArray',
71
+ data: {
72
+ // The name the fix writes; with no fix, the export's own.
73
+ replacement: `${localName ?? namespace}.isArray`,
74
+ },
65
75
  fix:
66
- binding === undefined ||
67
- localName === undefined ||
68
- hasForeignBinding(sourceCode, node, localName, moduleName)
76
+ binding === undefined || localName === undefined
69
77
  ? null
70
78
  : (fixer) => [
71
79
  ...binding.edits(fixer),
@@ -82,8 +90,7 @@ export const createPreferArrayIsArray = ({
82
90
  },
83
91
  };
84
92
  },
85
- } as const;
86
- };
93
+ }) as const;
87
94
 
88
95
  /**
89
96
  * Whether `node` calls `Array.isArray`, the callee and `Array` both read