@@ -18,7 +18,7 @@ import { ExtractorMessageId } from '../api/ExtractorMessageId';
18
18
import { CollectorEntity } from './CollectorEntity' ;
19
19
import { AstSymbolTable } from '../analyzer/AstSymbolTable' ;
20
20
import type { AstEntity } from '../analyzer/AstEntity' ;
21
- import type { AstModule , AstModuleExportInfo } from '../analyzer/AstModule' ;
21
+ import type { AstModule , IAstModuleExportInfo } from '../analyzer/AstModule' ;
22
22
import { AstSymbol } from '../analyzer/AstSymbol' ;
23
23
import type { AstDeclaration } from '../analyzer/AstDeclaration' ;
24
24
import { TypeScriptHelpers } from '../analyzer/TypeScriptHelpers' ;
@@ -313,12 +313,12 @@ export class Collector {
313
313
this . workingPackage . tsdocComment = this . workingPackage . tsdocParserContext ! . docComment ;
314
314
}
315
315
316
- const astModuleExportInfo : AstModuleExportInfo =
316
+ const { exportedLocalEntities , starExportedExternalModules , visitedAstModules } : IAstModuleExportInfo =
317
317
this . astSymbolTable . fetchAstModuleExportInfo ( astEntryPoint ) ;
318
318
319
319
// Create a CollectorEntity for each top-level export.
320
320
const processedAstEntities : AstEntity [ ] = [ ] ;
321
- for ( const [ exportName , astEntity ] of astModuleExportInfo . exportedLocalEntities ) {
321
+ for ( const [ exportName , astEntity ] of exportedLocalEntities ) {
322
322
this . _createCollectorEntity ( astEntity , exportName ) ;
323
323
processedAstEntities . push ( astEntity ) ;
324
324
}
@@ -333,9 +333,33 @@ export class Collector {
333
333
}
334
334
}
335
335
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
+
336
360
this . _makeUniqueNames ( ) ;
337
361
338
- for ( const starExportedExternalModule of astModuleExportInfo . starExportedExternalModules ) {
362
+ for ( const starExportedExternalModule of starExportedExternalModules ) {
339
363
if ( starExportedExternalModule . externalModulePath !== undefined ) {
340
364
this . _starExportedExternalModulePaths . push ( starExportedExternalModule . externalModulePath ) ;
341
365
}
@@ -539,7 +563,7 @@ export class Collector {
539
563
}
540
564
541
565
if ( astEntity instanceof AstNamespaceImport ) {
542
- const astModuleExportInfo : AstModuleExportInfo = astEntity . fetchAstModuleExportInfo ( this ) ;
566
+ const astModuleExportInfo : IAstModuleExportInfo = astEntity . fetchAstModuleExportInfo ( this ) ;
543
567
const parentEntity : CollectorEntity | undefined = this . _entitiesByAstEntity . get ( astEntity ) ;
544
568
if ( ! parentEntity ) {
545
569
// This should never happen, as we've already created entities for all AstNamespaceImports.
@@ -992,44 +1016,82 @@ export class Collector {
992
1016
}
993
1017
994
1018
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
+
995
1031
if ( astEntity instanceof AstSymbol ) {
996
1032
const sourceFiles : ts . SourceFile [ ] = astEntity . astDeclarations . map ( ( astDeclaration ) =>
997
1033
astDeclaration . declaration . getSourceFile ( )
998
1034
) ;
999
- return this . _collectReferenceDirectivesFromSourceFiles ( sourceFiles ) ;
1035
+ return this . _collectReferenceDirectivesFromSourceFiles ( sourceFiles , false ) ;
1000
1036
}
1001
1037
1002
1038
if ( astEntity instanceof AstNamespaceImport ) {
1003
1039
const sourceFiles : ts . SourceFile [ ] = [ astEntity . astModule . sourceFile ] ;
1004
- return this . _collectReferenceDirectivesFromSourceFiles ( sourceFiles ) ;
1040
+ return this . _collectReferenceDirectivesFromSourceFiles ( sourceFiles , false ) ;
1005
1041
}
1006
1042
}
1007
1043
1008
- private _collectReferenceDirectivesFromSourceFiles ( sourceFiles : ts . SourceFile [ ] ) : void {
1044
+ private _collectReferenceDirectivesFromSourceFiles (
1045
+ sourceFiles : Iterable < ts . SourceFile > ,
1046
+ onlyIncludeExplicitlyPreserved : boolean
1047
+ ) : void {
1009
1048
const seenFilenames : Set < string > = new Set < string > ( ) ;
1010
1049
1011
1050
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
1020
1066
) ;
1021
- this . _dtsTypeReferenceDirectives . add ( name ) ;
1067
+ if ( name ) {
1068
+ this . _dtsTypeReferenceDirectives . add ( name ) ;
1069
+ }
1022
1070
}
1023
1071
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
1028
1077
) ;
1029
- this . _dtsLibReferenceDirectives . add ( name ) ;
1078
+ if ( reference ) {
1079
+ this . _dtsLibReferenceDirectives . add ( reference ) ;
1080
+ }
1030
1081
}
1031
1082
}
1032
1083
}
1033
1084
}
1034
1085
}
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
+ }
1035
1097
}
0 commit comments