Repository navigation
fix: honor an excluded tag on an entry re-export - #2062
Conversation
With includeEntryExports, an export that an entry file re-exports is skipped when the re-export carries @public, @beta or @alias. An excluded custom tag such as @lintignore on the same re-export hid only the re-export itself, and the original export was still reported. The entry re-export check now also skips the export when the re-export has an excluded tag. Included tags are not checked here, because an untagged re-export would then hide every export in +tag mode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit: |
webpro
left a comment
There was a problem hiding this comment.
Thanks for the pull request, and for the clear before and after table! The entry re-export check honored custom tags when it was added in 9ccefb3 and lost them when 78255fc moved custom tags out of getShouldIgnoreHandler for tag hints, so this restores that behavior for excluded tags. It also matters for --fix: with --include-entry-exports, main removes the export from module.ts while the tagged re-export still points to it, and the code no longer compiles. The new test fails on main and passes here. Specifier-level tags, barrels in between, type and default re-exports, and mixed +/- tags behave as expected, and leaving included tags out is the right call. One optional note inline.
| @@ -217,7 +217,11 @@ export const analyze = async ({ | |||
| // Skip exports if re-exported from entry file and tagged | |||
| if (!isReferenced) { | |||
| const reExportedItem = graph.get(reExportingEntryFile)?.exports.get(identifier); | |||
There was a problem hiding this comment.
Optional, and not introduced here: this lookup uses the export name from the origin file, so it only finds the entry export when the re-export keeps that name. With this change, excluded tags also share a side effect that @public already has on main, where an unrelated tagged export with the same name in the entry hides the origin:
// index.ts (entry)
export { default as Button } from './button.js';
/** @lintignore */
export default function App() {}Button is still reported in index.ts, but default in button.ts is not. In the other direction, a tag on export { apple as green } from './module.js' has no effect on apple. Looking up the name the entry exports it under, which isReferenced already has when it reaches the entry, would fix both, for every tag.
There was a problem hiding this comment.
Done in #2069. The check now reads every name that the entry re-exports the export under. Both examples above are fixed, for every tag.
One case needs the full set of names: /** @public */ export { pear } next to an untagged export { pear as fruit }. Main handles it, and a check that reads only the first name breaks it. The re-exports/public fixture now covers it.
|
🚀 This pull request is included in v6.39.0. See Release 6.39.0 for release notes. Using Knip in a commercial project? Please consider becoming a sponsor. |
With
includeEntryExports, an export that an entry file re-exports is skipped when the re-export has@public. An excluded custom tag on the same re-export does not do this. It hides the re-export in the entry file, but the original export is still reported.With
tags: ["-lintignore"]and--include-entry-exports, main reportssomethingToIgnoreinmodule.ts. The same re-export with@publicreports nothing.The check in
analyze.tsthat skips an entry re-export reads onlyshouldIgnore, which covers@public,@beta,@aliasand@internalin production mode:It now also skips the export when the re-export has an excluded tag (
options.tags[1]).hasTaginutil/tag.tsis now exported for this.Included tags (
+tag) are not checked here on purpose. In+tagmode,shouldIgnoreTagsis true for every untagged export, so an untagged re-export would hide the export it points to. The+lintignoreoutput of the new fixture is the same on main and on this branch.The new fixture
fixtures/re-exports/excluded-tagsits next tofixtures/re-exports/public. It has one tagged re-export and one untagged re-export as a control:somethingToIgnoreinmodule.tssomethingUnusedinindex.tssomethingUnusedinmodule.tsVerified: