diff --git a/apps/api-extractor/src/generators/ApiReportGenerator.ts b/apps/api-extractor/src/generators/ApiReportGenerator.ts index 67b9ab29c3d..cf91d725ed4 100644 --- a/apps/api-extractor/src/generators/ApiReportGenerator.ts +++ b/apps/api-extractor/src/generators/ApiReportGenerator.ts @@ -22,6 +22,7 @@ import type { IAstModuleExportInfo } from '../analyzer/AstModule'; import { SourceFileLocationFormatter } from '../analyzer/SourceFileLocationFormatter'; import { ExtractorMessageId } from '../api/ExtractorMessageId'; import type { ApiReportVariant } from '../api/IConfigFile'; +import type { SymbolMetadata } from '../collector/SymbolMetadata'; export class ApiReportGenerator { private static _trimSpacesRegExp: RegExp = / +$/gm; @@ -93,6 +94,13 @@ export class ApiReportGenerator { // Emit the regular declarations for (const entity of collector.entities) { const astEntity: AstEntity = entity.astEntity; + const symbolMetadata: SymbolMetadata | undefined = collector.tryFetchMetadataForAstEntity(astEntity); + const maxEffectiveReleaseTag: ReleaseTag = symbolMetadata?.maxEffectiveReleaseTag ?? ReleaseTag.None; + + if (!this._shouldIncludeReleaseTag(maxEffectiveReleaseTag, reportVariant)) { + continue; + } + if (entity.consumable || collector.extractorConfig.apiReportIncludeForgottenExports) { // First, collect the list of export names for this symbol. When reporting messages with // ExtractorMessage.properties.exportName, this will enable us to emit the warning comments alongside @@ -133,7 +141,7 @@ export class ApiReportGenerator { messagesToReport.push(message); } - if (this._shouldIncludeInReport(collector, astDeclaration, reportVariant)) { + if (this._shouldIncludeDeclaration(collector, astDeclaration, reportVariant)) { writer.ensureSkippedLine(); writer.write(ApiReportGenerator._getAedocSynopsis(collector, astDeclaration, messagesToReport)); @@ -276,7 +284,7 @@ export class ApiReportGenerator { ): void { // Should we process this declaration at all? // eslint-disable-next-line no-bitwise - if (!ApiReportGenerator._shouldIncludeInReport(collector, astDeclaration, reportVariant)) { + if (!ApiReportGenerator._shouldIncludeDeclaration(collector, astDeclaration, reportVariant)) { span.modification.skipAll(); return; } @@ -420,7 +428,7 @@ export class ApiReportGenerator { astDeclaration ); - if (ApiReportGenerator._shouldIncludeInReport(collector, childAstDeclaration, reportVariant)) { + if (ApiReportGenerator._shouldIncludeDeclaration(collector, childAstDeclaration, reportVariant)) { if (sortChildren) { span.modification.sortChildren = true; child.modification.sortKey = Collector.getSortKeyIgnoringUnderscore( @@ -456,7 +464,7 @@ export class ApiReportGenerator { } } - private static _shouldIncludeInReport( + private static _shouldIncludeDeclaration( collector: Collector, astDeclaration: AstDeclaration, reportVariant: ApiReportVariant @@ -469,22 +477,34 @@ export class ApiReportGenerator { const apiItemMetadata: ApiItemMetadata = collector.fetchApiItemMetadata(astDeclaration); - // No specified release tag is considered the same as `@public`. - const releaseTag: ReleaseTag = - apiItemMetadata.effectiveReleaseTag === ReleaseTag.None - ? ReleaseTag.Public - : apiItemMetadata.effectiveReleaseTag; + return this._shouldIncludeReleaseTag(apiItemMetadata.effectiveReleaseTag, reportVariant); + } - // If the declaration has a release tag that is not in scope, omit it from the report. + private static _shouldIncludeReleaseTag(releaseTag: ReleaseTag, reportVariant: ApiReportVariant): boolean { switch (reportVariant) { case 'complete': return true; case 'alpha': - return releaseTag >= ReleaseTag.Alpha; + return ( + releaseTag === ReleaseTag.Alpha || + releaseTag === ReleaseTag.Beta || + releaseTag === ReleaseTag.Public || + // NOTE: No specified release tag is implicitly treated as `@public`. + releaseTag === ReleaseTag.None + ); case 'beta': - return releaseTag >= ReleaseTag.Beta; + return ( + releaseTag === ReleaseTag.Beta || + releaseTag === ReleaseTag.Public || + // NOTE: No specified release tag is implicitly treated as `@public`. + releaseTag === ReleaseTag.None + ); case 'public': - return releaseTag === ReleaseTag.Public; + return ( + releaseTag === ReleaseTag.Public || + // NOTE: No specified release tag is implicitly treated as `@public`. + releaseTag === ReleaseTag.None + ); default: throw new Error(`Unrecognized release level: ${reportVariant}`); } diff --git a/build-tests/api-extractor-lib2-test/dist/api-extractor-lib2-test.d.ts b/build-tests/api-extractor-lib2-test/dist/api-extractor-lib2-test.d.ts index 3f860232b9f..2816f40985f 100644 --- a/build-tests/api-extractor-lib2-test/dist/api-extractor-lib2-test.d.ts +++ b/build-tests/api-extractor-lib2-test/dist/api-extractor-lib2-test.d.ts @@ -7,7 +7,7 @@ * @packageDocumentation */ -/** @public */ +/** @beta */ declare class DefaultClass { } export default DefaultClass; diff --git a/build-tests/api-extractor-lib2-test/etc/api-extractor-lib2-test.alpha.api.md b/build-tests/api-extractor-lib2-test/etc/api-extractor-lib2-test.alpha.api.md index b59a9c33877..145cfdd01b5 100644 --- a/build-tests/api-extractor-lib2-test/etc/api-extractor-lib2-test.alpha.api.md +++ b/build-tests/api-extractor-lib2-test/etc/api-extractor-lib2-test.alpha.api.md @@ -4,7 +4,7 @@ ```ts -// @public (undocumented) +// @beta (undocumented) class DefaultClass { } export default DefaultClass; diff --git a/build-tests/api-extractor-lib2-test/etc/api-extractor-lib2-test.api.md b/build-tests/api-extractor-lib2-test/etc/api-extractor-lib2-test.api.md index e89ae310395..e3df0b5f94d 100644 --- a/build-tests/api-extractor-lib2-test/etc/api-extractor-lib2-test.api.md +++ b/build-tests/api-extractor-lib2-test/etc/api-extractor-lib2-test.api.md @@ -4,7 +4,7 @@ ```ts -// @public (undocumented) +// @beta (undocumented) class DefaultClass { } export default DefaultClass; diff --git a/build-tests/api-extractor-lib2-test/etc/api-extractor-lib2-test.public.api.md b/build-tests/api-extractor-lib2-test/etc/api-extractor-lib2-test.public.api.md index 833c0d09f26..87ca7608c88 100644 --- a/build-tests/api-extractor-lib2-test/etc/api-extractor-lib2-test.public.api.md +++ b/build-tests/api-extractor-lib2-test/etc/api-extractor-lib2-test.public.api.md @@ -4,11 +4,6 @@ ```ts -// @public (undocumented) -class DefaultClass { -} -export default DefaultClass; - // @public (undocumented) export class Lib2Class { // (undocumented) diff --git a/build-tests/api-extractor-lib2-test/src/index.ts b/build-tests/api-extractor-lib2-test/src/index.ts index 6fd2ffc71cb..616e9f7f9f2 100644 --- a/build-tests/api-extractor-lib2-test/src/index.ts +++ b/build-tests/api-extractor-lib2-test/src/index.ts @@ -18,5 +18,5 @@ export class Lib2Class { /** @alpha */ export interface Lib2Interface {} -/** @public */ +/** @beta */ export default class DefaultClass {} diff --git a/common/changes/@microsoft/api-extractor/trim-export-default-from-reports_2025-04-29-00-30.json b/common/changes/@microsoft/api-extractor/trim-export-default-from-reports_2025-04-29-00-30.json new file mode 100644 index 00000000000..29cd724f150 --- /dev/null +++ b/common/changes/@microsoft/api-extractor/trim-export-default-from-reports_2025-04-29-00-30.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@microsoft/api-extractor", + "comment": "Fix an issue where default exports were sometimes trimmed incorrectly in .api.md files when using `reportVariants` (GitHub #4775)", + "type": "patch" + } + ], + "packageName": "@microsoft/api-extractor" +} \ No newline at end of file