@@ -18,7 +18,7 @@ import { ExtractorMessageId } from '../api/ExtractorMessageId';
1818import { CollectorEntity } from './CollectorEntity' ;
1919import { AstSymbolTable } from '../analyzer/AstSymbolTable' ;
2020import type { AstEntity } from '../analyzer/AstEntity' ;
21- import type { AstModule , AstModuleExportInfo } from '../analyzer/AstModule' ;
21+ import type { AstModule , IAstModuleExportInfo } from '../analyzer/AstModule' ;
2222import { AstSymbol } from '../analyzer/AstSymbol' ;
2323import type { AstDeclaration } from '../analyzer/AstDeclaration' ;
2424import { TypeScriptHelpers } from '../analyzer/TypeScriptHelpers' ;
@@ -313,12 +313,12 @@ export class Collector {
313313 this . workingPackage . tsdocComment = this . workingPackage . tsdocParserContext ! . docComment ;
314314 }
315315
316- const astModuleExportInfo : AstModuleExportInfo =
316+ const { exportedLocalEntities , starExportedExternalModules , visitedAstModules } : IAstModuleExportInfo =
317317 this . astSymbolTable . fetchAstModuleExportInfo ( astEntryPoint ) ;
318318
319319 // Create a CollectorEntity for each top-level export.
320320 const processedAstEntities : AstEntity [ ] = [ ] ;
321- for ( const [ exportName , astEntity ] of astModuleExportInfo . exportedLocalEntities ) {
321+ for ( const [ exportName , astEntity ] of exportedLocalEntities ) {
322322 this . _createCollectorEntity ( astEntity , exportName ) ;
323323 processedAstEntities . push ( astEntity ) ;
324324 }
@@ -333,9 +333,33 @@ export class Collector {
333333 }
334334 }
335335
336+ // Ensure references are collected from any intermediate files that
337+ // only include exports
338+ const nonExternalSourceFiles : Set < ts . SourceFile > = new Set ( ) ;
339+ for ( const { sourceFile, isExternal } of visitedAstModules ) {
340+ if ( ! nonExternalSourceFiles . has ( sourceFile ) && ! isExternal ) {
341+ nonExternalSourceFiles . add ( sourceFile ) ;
342+ }
343+ }
344+
345+ // Here, we're collecting reference directives from all non-external source files
346+ // that were encountered while looking for exports, but only those references that
347+ // were explicitly written by the developer and marked with the `preserve="true"`
348+ // attribute. In TS >= 5.5, only references that are explicitly authored and marked
349+ // with `preserve="true"` are included in the output. See https://github.com/microsoft/TypeScript/pull/57681
350+ //
351+ // The `_collectReferenceDirectives` function pulls in all references in files that
352+ // contain definitions, but does not examine files that only reexport from other
353+ // files. Here, we're looking through files that were missed by `_collectReferenceDirectives`,
354+ // but only collecting references that were explicitly marked with `preserve="true"`.
355+ // It is intuitive for developers to include references that they explicitly want part of
356+ // their public API in a file like the entrypoint, which is likely to only contain reexports,
357+ // and this picks those up.
358+ this . _collectReferenceDirectivesFromSourceFiles ( nonExternalSourceFiles , true ) ;
359+
336360 this . _makeUniqueNames ( ) ;
337361
338- for ( const starExportedExternalModule of astModuleExportInfo . starExportedExternalModules ) {
362+ for ( const starExportedExternalModule of starExportedExternalModules ) {
339363 if ( starExportedExternalModule . externalModulePath !== undefined ) {
340364 this . _starExportedExternalModulePaths . push ( starExportedExternalModule . externalModulePath ) ;
341365 }
@@ -539,7 +563,7 @@ export class Collector {
539563 }
540564
541565 if ( astEntity instanceof AstNamespaceImport ) {
542- const astModuleExportInfo : AstModuleExportInfo = astEntity . fetchAstModuleExportInfo ( this ) ;
566+ const astModuleExportInfo : IAstModuleExportInfo = astEntity . fetchAstModuleExportInfo ( this ) ;
543567 const parentEntity : CollectorEntity | undefined = this . _entitiesByAstEntity . get ( astEntity ) ;
544568 if ( ! parentEntity ) {
545569 // This should never happen, as we've already created entities for all AstNamespaceImports.
@@ -992,44 +1016,82 @@ export class Collector {
9921016 }
9931017
9941018 private _collectReferenceDirectives ( astEntity : AstEntity ) : void {
1019+ // Here, we're collecting reference directives from source files that contain extracted
1020+ // definitions (i.e. - files that contain `export class ...`, `export interface ...`, ...).
1021+ // These references may or may not include the `preserve="true" attribute. In TS < 5.5,
1022+ // references that end up in .D.TS files may or may not be explicity written by the developer.
1023+ // In TS >= 5.5, only references that are explicitly authored and are marked with
1024+ // `preserve="true"` are included in the output. See https://github.com/microsoft/TypeScript/pull/57681
1025+ //
1026+ // The calls to `_collectReferenceDirectivesFromSourceFiles` in this function are
1027+ // preserving existing behavior, which is to include all reference directives
1028+ // regardless of whether they are explicitly authored or not, but only in files that
1029+ // contain definitions.
1030+
9951031 if ( astEntity instanceof AstSymbol ) {
9961032 const sourceFiles : ts . SourceFile [ ] = astEntity . astDeclarations . map ( ( astDeclaration ) =>
9971033 astDeclaration . declaration . getSourceFile ( )
9981034 ) ;
999- return this . _collectReferenceDirectivesFromSourceFiles ( sourceFiles ) ;
1035+ return this . _collectReferenceDirectivesFromSourceFiles ( sourceFiles , false ) ;
10001036 }
10011037
10021038 if ( astEntity instanceof AstNamespaceImport ) {
10031039 const sourceFiles : ts . SourceFile [ ] = [ astEntity . astModule . sourceFile ] ;
1004- return this . _collectReferenceDirectivesFromSourceFiles ( sourceFiles ) ;
1040+ return this . _collectReferenceDirectivesFromSourceFiles ( sourceFiles , false ) ;
10051041 }
10061042 }
10071043
1008- private _collectReferenceDirectivesFromSourceFiles ( sourceFiles : ts . SourceFile [ ] ) : void {
1044+ private _collectReferenceDirectivesFromSourceFiles (
1045+ sourceFiles : Iterable < ts . SourceFile > ,
1046+ onlyIncludeExplicitlyPreserved : boolean
1047+ ) : void {
10091048 const seenFilenames : Set < string > = new Set < string > ( ) ;
10101049
10111050 for ( const sourceFile of sourceFiles ) {
1012- if ( sourceFile && sourceFile . fileName ) {
1013- if ( ! seenFilenames . has ( sourceFile . fileName ) ) {
1014- seenFilenames . add ( sourceFile . fileName ) ;
1015-
1016- for ( const typeReferenceDirective of sourceFile . typeReferenceDirectives ) {
1017- const name : string = sourceFile . text . substring (
1018- typeReferenceDirective . pos ,
1019- typeReferenceDirective . end
1051+ if ( sourceFile ?. fileName ) {
1052+ const {
1053+ fileName,
1054+ typeReferenceDirectives,
1055+ libReferenceDirectives,
1056+ text : sourceFileText
1057+ } = sourceFile ;
1058+ if ( ! seenFilenames . has ( fileName ) ) {
1059+ seenFilenames . add ( fileName ) ;
1060+
1061+ for ( const typeReferenceDirective of typeReferenceDirectives ) {
1062+ const name : string | undefined = this . _getReferenceDirectiveFromSourceFile (
1063+ sourceFileText ,
1064+ typeReferenceDirective ,
1065+ onlyIncludeExplicitlyPreserved
10201066 ) ;
1021- this . _dtsTypeReferenceDirectives . add ( name ) ;
1067+ if ( name ) {
1068+ this . _dtsTypeReferenceDirectives . add ( name ) ;
1069+ }
10221070 }
10231071
1024- for ( const libReferenceDirective of sourceFile . libReferenceDirectives ) {
1025- const name : string = sourceFile . text . substring (
1026- libReferenceDirective . pos ,
1027- libReferenceDirective . end
1072+ for ( const libReferenceDirective of libReferenceDirectives ) {
1073+ const reference : string | undefined = this . _getReferenceDirectiveFromSourceFile (
1074+ sourceFileText ,
1075+ libReferenceDirective ,
1076+ onlyIncludeExplicitlyPreserved
10281077 ) ;
1029- this . _dtsLibReferenceDirectives . add ( name ) ;
1078+ if ( reference ) {
1079+ this . _dtsLibReferenceDirectives . add ( reference ) ;
1080+ }
10301081 }
10311082 }
10321083 }
10331084 }
10341085 }
1086+
1087+ private _getReferenceDirectiveFromSourceFile (
1088+ sourceFileText : string ,
1089+ { pos, end, preserve } : ts . FileReference ,
1090+ onlyIncludeExplicitlyPreserved : boolean
1091+ ) : string | undefined {
1092+ const reference : string = sourceFileText . substring ( pos , end ) ;
1093+ if ( preserve || ! onlyIncludeExplicitlyPreserved ) {
1094+ return reference ;
1095+ }
1096+ }
10351097}
0 commit comments