fix: no-unused-modules correctly handles export { X as default } syntax - #3244
whatfontisthis wants to merge 1 commit into
Conversation
…syntax
In updateExportUsage, specifiers exported as "default" were added to
newExportIdentifiers using the raw string "default", but the exports map
stores default exports under the IMPORT_DEFAULT_SPECIFIER key
("ImportDefaultSpecifier"). This mismatch caused the whereUsed data to
be lost on the first lint pass, making the rule incorrectly report the
default export as unused on subsequent lints.
Fixes import-js#3216
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3244 +/- ##
==========================================
+ Coverage 95.50% 95.52% +0.02%
==========================================
Files 83 83
Lines 3690 3690
Branches 1333 1333
==========================================
+ Hits 3524 3525 +1
+ Misses 166 165 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Note on the |
|
Can we please get this merged? I am getting this problem on non default module exports as well. No amount of configuration or testing could get it to work. |
nrps9909
left a comment
There was a problem hiding this comment.
Reviewed 5a6c4b0e1f52c883d688586e783a49631651fbd4. Normalizing the exported default name to the same map key used during preparation preserves whereUsed across repeated lint passes. I reproduced the new regression on base 3a99e4c8d3bfd2cd466353d11784eb06dad9b166 (152 passing, 1 pending, 1 failing); the focused head run passes 153 tests, with 1 pending.
An independent Linter probe passes all 13 observations on head, versus 6 failures on base: three consecutive lint passes for a used default export, an unused named export beside a used default, an unused default beside a used named export, and a quoted "default" specifier. Removing the consumer import also correctly makes the default export unused. This supports the scoped default-export cache fix; it does not establish that every named-export report in the linked issue is resolved.
With ESLint 8.57.1, npm test passes 3,015 tests (1 pending), including posttest lint, generated documentation checks, markdownlint and build. With ESLint 9.39.5, the test phase passes 3,011 tests (1 pending); its posttest is blocked by the repository's legacy lint configuration/development plugin compatibility.
The upstream check list still contains two failed old-ESLint matrix jobs and cancelled Windows jobs. Their run log endpoint returns HTTP 410, so I have not established their causes and am not claiming an entirely green CI matrix.
Review and local validation performed with Codex.
Summary
Fixes #3216.
When a file uses
export { testHandler as default }syntax (exporting a local binding as the default export), theno-unused-modulesrule incorrectly flagged the default export as unused even when it was imported correctly viaimport handler from './module'in another file.updateExportUsage, when scanningExportNamedDeclarationspecifiers, the raw exported name"default"was added tonewExportIdentifiers. However, the exports map usesIMPORT_DEFAULT_SPECIFIER("ImportDefaultSpecifier") as the key for default exports. This mismatch meant the existingwhereUseddata (populated duringdoPreparation) was dropped from the map on the first lint pass, and the export was stored under the wrong key"default". On the next lint of the same file,checkUsagelooked upIMPORT_DEFAULT_SPECIFIERand found nothing, incorrectly reporting the export as unused."default"→IMPORT_DEFAULT_SPECIFIERwhen buildingnewExportIdentifiersinupdateExportUsage, consistent with howEXPORT_DEFAULT_DECLARATIONis already handled on the line above.Changes
src/rules/no-unused-modules.js: Normalize"default"exported specifier name toIMPORT_DEFAULT_SPECIFIERinupdateExportUsage.tests/src/rules/no-unused-modules.js: Add regression test that lints the file twice (second lint triggers the bug —doPreparationis skipped due to caching, exposing the corrupted export map).tests/files/no-unused-modules/export-as-default/: New fixture files (test-export.js,usage.js) for the test.Test plan
no-unused-modulestest suite passes:BABEL_ENV=test node_modules/.bin/nyc node_modules/.bin/mocha tests/src/rules/no-unused-modules.js→ 157 passing, 1 pending, 0 failing🤖 Generated with Claude Code