exadev-eslint-config 2.1.1 → 2.1.2

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/README.md CHANGED
@@ -111,7 +111,7 @@ export default tseslint.config(
111
111
  | `no-non-barrel-reexport` | ✓ | Re-exports belong only in a barrel. Catches the split form across two statements (`import { x } from './y'; export { x };` or `export default x;`) which no AST selector alone can match. Autofix deletes the export and the now-pointless import when it was the import's only use. Self-scopes away from any index file. |
112
112
  | `no-side-effects-in-index` | | A barrel file may contain only re-export statements -- nothing that could execute at import time. Self-scopes to any index file. |
113
113
  | `barrel-direct-siblings-only` | | A barrel may re-export only from a direct sibling (`./module`), never a nested path, parent, or bare package specifier (mode 3). |
114
- | `no-pointless-reassignment` | ✓ | `const foo = bar` where both sides are plain identifiers and the alias adds no transformation. |
114
+ | `no-pointless-reassignment` | ✓ | `const foo = bar` where both sides are plain identifiers and the alias adds no transformation. Autofix rewrites every read to the original name and deletes the declaration (including its `export` keyword, when exported). Still reported but deliberately not auto-fixable where collapsing the alias would change meaning: an explicit type annotation (`const exhaustive: never = item` -- the annotation is the point), a read where the original name is shadowed, a read as a shorthand object property, more than one declarator in the statement, or a source that is written to anywhere. |
115
115
 
116
116
  ## Barrel policy
117
117
 
package/dist/index.cjs CHANGED
@@ -28,7 +28,7 @@ let typescript_eslint = require("typescript-eslint");
28
28
  typescript_eslint = __toESM(typescript_eslint, 1);
29
29
  let node_path = require("node:path");
30
30
  //#region package.json
31
- var version = "2.1.1";
31
+ var version = "2.1.2";
32
32
  //#endregion
33
33
  //#region src/rules/barrel-helpers.ts
34
34
  const INDEX_BASENAME$1 = /^index\.[cm]?[tj]sx?$/;
@@ -375,6 +375,15 @@ const noNonBarrelReexport = {
375
375
  function isIdentifierReference(reference) {
376
376
  return reference.identifier.type === "Identifier";
377
377
  }
378
+ function hasTypeAnnotation(id) {
379
+ return "typeAnnotation" in id && id.typeAnnotation !== void 0 && id.typeAnnotation !== null;
380
+ }
381
+ function resolveFrom(scope, name) {
382
+ for (let current = scope; current; current = current.upper) {
383
+ const found = current.set.get(name);
384
+ if (found) return found;
385
+ }
386
+ }
378
387
  //#endregion
379
388
  //#region src/plugin.ts
380
389
  const plugin = {
@@ -405,6 +414,7 @@ const plugin = {
405
414
  if (!sourceVariable || sourceVariable.references.some((reference) => reference.isWrite() && !reference.init)) return;
406
415
  const aliasName = node.id.name;
407
416
  const originalName = node.init.name;
417
+ const aliasIsAnnotated = hasTypeAnnotation(node.id);
408
418
  context.report({
409
419
  node,
410
420
  messageId: "pointlessReassignment",
@@ -415,6 +425,7 @@ const plugin = {
415
425
  fix(fixer) {
416
426
  const variable = scope.set.get(aliasName);
417
427
  if (!variable) return null;
428
+ if (aliasIsAnnotated) return null;
418
429
  if (variable.references.filter((reference) => reference.isWrite() && reference.identifier !== node.id).length > 0) return null;
419
430
  const readRefs = variable.references.filter((reference) => reference.isRead() && isIdentifierReference(reference));
420
431
  if (readRefs.some((reference) => {
@@ -430,10 +441,11 @@ const plugin = {
430
441
  }
431
442
  return false;
432
443
  })) return null;
444
+ if (readRefs.some((reference) => resolveFrom(reference.from, originalName) !== sourceVariable)) return null;
433
445
  const fixes = readRefs.map((reference) => fixer.replaceText(reference.identifier, originalName));
434
446
  const declaration = node.parent;
435
447
  if (declaration.type !== "VariableDeclaration" || declaration.declarations.length !== 1) return null;
436
- fixes.push(fixer.remove(declaration));
448
+ fixes.push(fixer.remove(declaration.parent.type === "ExportNamedDeclaration" ? declaration.parent : declaration));
437
449
  return fixes;
438
450
  }
439
451
  });
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import tseslint from "typescript-eslint";
2
2
  import { posix } from "node:path";
3
3
  //#region package.json
4
- var version = "2.1.1";
4
+ var version = "2.1.2";
5
5
  //#endregion
6
6
  //#region src/rules/barrel-helpers.ts
7
7
  const INDEX_BASENAME$1 = /^index\.[cm]?[tj]sx?$/;
@@ -348,6 +348,15 @@ const noNonBarrelReexport = {
348
348
  function isIdentifierReference(reference) {
349
349
  return reference.identifier.type === "Identifier";
350
350
  }
351
+ function hasTypeAnnotation(id) {
352
+ return "typeAnnotation" in id && id.typeAnnotation !== void 0 && id.typeAnnotation !== null;
353
+ }
354
+ function resolveFrom(scope, name) {
355
+ for (let current = scope; current; current = current.upper) {
356
+ const found = current.set.get(name);
357
+ if (found) return found;
358
+ }
359
+ }
351
360
  //#endregion
352
361
  //#region src/plugin.ts
353
362
  const plugin = {
@@ -378,6 +387,7 @@ const plugin = {
378
387
  if (!sourceVariable || sourceVariable.references.some((reference) => reference.isWrite() && !reference.init)) return;
379
388
  const aliasName = node.id.name;
380
389
  const originalName = node.init.name;
390
+ const aliasIsAnnotated = hasTypeAnnotation(node.id);
381
391
  context.report({
382
392
  node,
383
393
  messageId: "pointlessReassignment",
@@ -388,6 +398,7 @@ const plugin = {
388
398
  fix(fixer) {
389
399
  const variable = scope.set.get(aliasName);
390
400
  if (!variable) return null;
401
+ if (aliasIsAnnotated) return null;
391
402
  if (variable.references.filter((reference) => reference.isWrite() && reference.identifier !== node.id).length > 0) return null;
392
403
  const readRefs = variable.references.filter((reference) => reference.isRead() && isIdentifierReference(reference));
393
404
  if (readRefs.some((reference) => {
@@ -403,10 +414,11 @@ const plugin = {
403
414
  }
404
415
  return false;
405
416
  })) return null;
417
+ if (readRefs.some((reference) => resolveFrom(reference.from, originalName) !== sourceVariable)) return null;
406
418
  const fixes = readRefs.map((reference) => fixer.replaceText(reference.identifier, originalName));
407
419
  const declaration = node.parent;
408
420
  if (declaration.type !== "VariableDeclaration" || declaration.declarations.length !== 1) return null;
409
- fixes.push(fixer.remove(declaration));
421
+ fixes.push(fixer.remove(declaration.parent.type === "ExportNamedDeclaration" ? declaration.parent : declaration));
410
422
  return fixes;
411
423
  }
412
424
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "exadev-eslint-config",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "description": "Shared custom ESLint rules and plugin for ExaDev projects",
5
5
  "type": "module",
6
6
  "sideEffects": false,