UNPKG

typedoc

Version:

Create api documentation for TypeScript projects.

66 lines (65 loc) 3.09 kB
import { ok } from "assert"; import { discoverAllReferenceTypes } from "../utils/reflections.js"; import { i18n } from "#utils"; function makeIntentionallyExportedHelper(project, intentional, logger) { const used = new Set(); const processed = intentional.map((v) => { const index = v.lastIndexOf(":"); if (index === -1) { return ["", v]; } return [v.substring(0, index), v.substring(index + 1)]; }); return { has(type, typeName) { ok(!type.reflection); // If it isn't declared anywhere, we can't produce a good error message about where // the non-exported symbol is, so even if it isn't ignored, pretend it is. In practice, // this will happen incredibly rarely, since symbols without declarations are very rare. // I know of only two instances: // 1. `undefined` in `globalThis` // 2. Properties on non-homomorphic mapped types, e.g. the symbol for "foo" on `Record<"foo", 1>` // There might be others, so still check this here rather than asserting, but print a debug log // so that we can possibly improve this in the future. if (!type.package) { logger.verbose(`The type ${type.qualifiedName} has no declarations, implicitly allowing missing export.`); return true; } // Don't produce warnings for third-party symbols. if (type.package !== project.packageName) { return true; } for (const [index, [file, name]] of processed.entries()) { if (typeName === name && `${type.symbolId.packageName}/${type.symbolId.packagePath}`.endsWith(file)) { used.add(index); return true; } } return false; }, getUnused() { return intentional.filter((_, i) => !used.has(i)); }, }; } export function validateExports(project, logger, intentionallyNotExported) { const intentional = makeIntentionallyExportedHelper(project, intentionallyNotExported, logger); const warned = new Set(); for (const { type, owner } of discoverAllReferenceTypes(project, true)) { const uniqueId = type.symbolId?.getStableKey(); if (!type.reflection && !type.externalUrl && !type.isIntentionallyBroken() && !intentional.has(type, type.qualifiedName) && !warned.has(uniqueId) && !project.symbolIdHasBeenRemoved(type.symbolId)) { warned.add(uniqueId); logger.warn(i18n.type_0_defined_in_1_is_referenced_by_2_but_not_included_in_docs(type.qualifiedName, `${type.symbolId.packageName}/${type.symbolId.packagePath}`, owner.getFriendlyFullName())); } } const unusedIntentional = intentional.getUnused(); if (unusedIntentional.length) { logger.warn(i18n.invalid_intentionally_not_exported_symbols_0(unusedIntentional.join("\n\t"))); } }