eslint-plugin-ts-type-forge 0.8.14 → 0.8.16

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,8 +1,7 @@
1
1
  import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
2
- import { buildNamedImportFix } from 'eslint-rule-forge';
3
2
  import { Arr } from 'ts-data-forge';
4
- import { TS_TYPE_FORGE_MODULE } from './constants.mjs';
5
3
  import { resolveTypeName, type ImportStyle } from './import-style.mjs';
4
+ import { buildTypeImportFix } from './import-utils.mjs';
6
5
 
7
6
  /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
8
7
 
@@ -15,13 +14,14 @@ export type TypeRewrite = Readonly<{
15
14
  }>;
16
15
 
17
16
  /**
18
- * Emits one report per rewrite, resolving each target name and attaching every
19
- * required import to the *first* report.
20
- *
21
- * All import fixes must live on a single report: `insertTextBefore(program, …)`
22
- * produces overlapping ranges, and ESLint merges each report's fixes into one
23
- * span — so spreading them across reports makes the fixes conflict and only one
24
- * survives per pass.
17
+ * Emits one report per rewrite, resolving each target name. Every fix imports
18
+ * the name it writes when the file does not import it yet
19
+ * ({@link buildTypeImportFix}), so that one applied alone is complete, and the
20
+ * first of those imports every name the reports need: the import edits
21
+ * overlap, so `--fix` applies one fix per pass, and when that is the batching
22
+ * fix the second pass applies the rest. (With nested rewrites an inner fix,
23
+ * whose range ends first, can win the pass instead; that costs a pass, not a
24
+ * fix.) A report that needs no import has no import edit.
25
25
  */
26
26
  export const reportTypeRewrites = <MessageIds extends string>(
27
27
  context: TSESLint.RuleContext<MessageIds, readonly unknown[]>,
@@ -55,6 +55,9 @@ export const reportTypeRewrites = <MessageIds extends string>(
55
55
  .map(({ rewrite }) => rewrite.canonicalName),
56
56
  );
57
57
 
58
+ // The fix that imports them all: the first that needs an import at all.
59
+ const batchIndex = resolved.findIndex(({ target }) => target.needsImport);
60
+
58
61
  for (const [index, { rewrite, target }] of resolved.entries()) {
59
62
  const replacement = `${target.localName}<${rewrite.typeArgs}>`;
60
63
 
@@ -64,13 +67,15 @@ export const reportTypeRewrites = <MessageIds extends string>(
64
67
  data: { original: sourceCode.getText(rewrite.node), replacement },
65
68
  fix: (fixer) =>
66
69
  Arr.toPushed(
67
- index === 0
68
- ? importNames.flatMap((name) =>
69
- buildNamedImportFix(fixer, program, TS_TYPE_FORGE_MODULE, [
70
- `type ${name}`,
71
- ]),
72
- )
73
- : [],
70
+ buildTypeImportFix(
71
+ fixer,
72
+ sourceCode,
73
+ index === batchIndex
74
+ ? importNames
75
+ : target.needsImport
76
+ ? [rewrite.canonicalName]
77
+ : [],
78
+ ),
74
79
  fixer.replaceText(rewrite.node, replacement),
75
80
  ),
76
81
  });
@@ -3,10 +3,10 @@ import {
3
3
  type TSESLint,
4
4
  type TSESTree,
5
5
  } from '@typescript-eslint/utils';
6
- import { buildNamedImportFix, isLocallyBound } from 'eslint-rule-forge';
6
+ import { isLocallyBound } from 'eslint-rule-forge';
7
7
  import { Arr } from 'ts-data-forge';
8
- import { TS_TYPE_FORGE_MODULE } from './constants.mjs';
9
8
  import { resolveTypeName, type ImportStyle } from './import-style.mjs';
9
+ import { buildTypeImportFix } from './import-utils.mjs';
10
10
 
11
11
  /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
12
12
 
@@ -73,9 +73,7 @@ export const reportStdTypeReference = <MessageIds extends string>(
73
73
  fix: (fixer: TSESLint.RuleFixer): readonly TSESLint.RuleFix[] =>
74
74
  Arr.toPushed(
75
75
  target.needsImport
76
- ? buildNamedImportFix(fixer, program, TS_TYPE_FORGE_MODULE, [
77
- `type ${candidate}`,
78
- ])
76
+ ? buildTypeImportFix(fixer, context.sourceCode, [candidate])
79
77
  : [],
80
78
  fixer.replaceText(typeName, target.localName),
81
79
  ),