Skip to content

Commit dd1caed

Browse files
committed
Flag stale @internal tags in production mode (resolve #1658)
1 parent 767ebaf commit dd1caed

14 files changed

Lines changed: 89 additions & 15 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { usedInProdInternal } from './module';
2+
3+
usedInProdInternal();
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { test } from 'node:test';
2+
import { usedInTestInternal } from './module';
3+
4+
test('used in test', () => {
5+
usedInTestInternal();
6+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/** @internal */
2+
export const usedInProdInternal = () => {};
3+
4+
/** @internal */
5+
export const usedInTestInternal = () => {};
6+
7+
/** @internal */
8+
export const unusedInternal = () => {};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"name": "@fixtures/stale-internal-tag",
3+
"scripts": {
4+
"test": "node --test"
5+
}
6+
}

packages/knip/src/cli.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ const main = async () => {
7070
cwd: options.cwd,
7171
configFilePath: options.configFilePath,
7272
isDisableConfigHints: options.isDisableConfigHints,
73+
isDisableTagHints: options.isDisableTagHints,
7374
isProduction: options.isProduction,
7475
isShowProgress: options.isShowProgress,
7576
isTreatConfigHintsAsErrors: options.isTreatConfigHintsAsErrors,

packages/knip/src/graph-explorer/operations/build-exports-tree.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { CONTINUE } from '../constants.ts';
33
import type { Via } from '../walk-down.ts';
44
import { walkDown } from '../walk-down.ts';
55

6-
/** @internal */
76
export interface ExportsTreeNode {
87
filePath: string;
98
identifier: string;

packages/knip/src/graph/analyze.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import type { MainOptions } from '../util/create-options.ts';
1212
import { getPackageNameFromModuleSpecifier } from '../util/modules.ts';
1313
import { perfObserver } from '../util/Performance.ts';
1414
import { findMatch } from '../util/regex.ts';
15-
import { getShouldIgnoreHandler, getShouldIgnoreTagHandler } from '../util/tag.ts';
15+
import { getShouldIgnoreHandler, getShouldIgnoreTagHandler, isAlwaysIgnored } from '../util/tag.ts';
16+
import { INTERNAL_TAG } from '../constants.ts';
1617

1718
interface AnalyzeOptions {
1819
analyzedFiles: Set<string>;
@@ -97,10 +98,11 @@ export const analyze = async ({
9798
const importsForExport = file.importedBy;
9899

99100
for (const [identifier, exportedItem] of exportItems) {
100-
// Skip tagged exports
101-
if (shouldIgnore(exportedItem.jsDocTags)) continue;
101+
// Skip exports tagged @public/@beta/@alias entirely (no refs check)
102+
if (isAlwaysIgnored(exportedItem.jsDocTags)) continue;
102103

103-
const isIgnored = shouldIgnoreTags(exportedItem.jsDocTags);
104+
const isInternalProd = options.isProduction && exportedItem.jsDocTags.has(INTERNAL_TAG);
105+
const isIgnored = shouldIgnoreTags(exportedItem.jsDocTags) || isInternalProd;
104106

105107
if (importsForExport) {
106108
const [isReferenced, reExportingEntryFile] = explorer.isReferenced(filePath, identifier, {
@@ -112,7 +114,7 @@ export const analyze = async ({
112114
(isReferenced || isReferencedInUsedExport(exportedItem, filePath, isIncludeEntryExports))
113115
) {
114116
for (const tagName of exportedItem.jsDocTags) {
115-
if (options.tags[1].includes(tagName)) {
117+
if (options.tags[1].includes(tagName) || (isInternalProd && tagName === INTERNAL_TAG)) {
116118
collector.addTagHint({ type: 'tag', filePath, identifier, tagName });
117119
}
118120
}
@@ -233,7 +235,8 @@ export const analyze = async ({
233235
for (const extImport of file.imports.external) {
234236
const packageName = getPackageNameFromModuleSpecifier(extImport.specifier);
235237
const isHandled =
236-
packageName && deputy.maybeAddReferencedExternalDependency(ws, packageName, undefined, extImport.isTypeOnly);
238+
packageName &&
239+
deputy.maybeAddReferencedExternalDependency(ws, packageName, undefined, extImport.isTypeOnly);
237240
if (!isHandled)
238241
collector.addIssue({
239242
type: 'unlisted',

packages/knip/src/reporters/symbols.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import type { Entries } from '../types/entries.ts';
22
import type { ReporterOptions } from '../types/issues.ts';
3-
import { printConfigurationHints } from './util/configuration-hints.ts';
3+
import { printConfigurationHints, printTagHints } from './util/configuration-hints.ts';
44
import { dim, flattenIssues, getColoredTitle, getIssueTypeTitle, getTableForType } from './util/util.ts';
55

66
export default (options: ReporterOptions) => {
7-
const { report, issues, isDisableConfigHints, isShowProgress } = options;
7+
const { report, issues, isDisableConfigHints, isDisableTagHints, isShowProgress } = options;
88
const reportMultipleGroups = Object.values(report).filter(Boolean).length > 1;
99
let totalIssues = 0;
1010

@@ -31,6 +31,10 @@ export default (options: ReporterOptions) => {
3131
printConfigurationHints(options);
3232
}
3333

34+
if (!isDisableTagHints) {
35+
printTagHints(options);
36+
}
37+
3438
if (
3539
totalIssues === 0 &&
3640
isShowProgress &&

packages/knip/src/reporters/util/configuration-hints.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,9 @@ export const printConfigurationHints = ({
180180
console.log(getTitle('Configuration hints', configurationHints.length));
181181
console.warn(getTableForHints(rows).toString());
182182
}
183+
};
183184

185+
export const printTagHints = ({ cwd, tagHints }: ReporterOptions) => {
184186
if (tagHints.size > 0) {
185187
console.log(getDimmedTitle('Tag hints', tagHints.size));
186188
for (const hint of tagHints) {

packages/knip/src/types/issues.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ export type ReporterOptions = {
6363
configurationHints: ConfigurationHint[];
6464
enabledPlugins: Record<string, string[]>;
6565
isDisableConfigHints: boolean;
66+
isDisableTagHints: boolean;
6667
isTreatConfigHintsAsErrors: boolean;
6768
cwd: string;
6869
isProduction: boolean;

0 commit comments

Comments
 (0)