@@ -10,38 +10,26 @@ import {
10
10
Navigation ,
11
11
Meaning
12
12
} from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference' ;
13
- import { PackageJsonLookup , INodePackageJson , InternalError } from '@rushstack/node-core-library' ;
13
+ import { INodePackageJson , InternalError } from '@rushstack/node-core-library' ;
14
14
import { TypeScriptHelpers } from '../analyzer/TypeScriptHelpers' ;
15
15
import { TypeScriptInternals } from '../analyzer/TypeScriptInternals' ;
16
+ import { Collector } from '../collector/Collector' ;
17
+ import { CollectorEntity } from '../collector/CollectorEntity' ;
16
18
17
19
export class DeclarationReferenceGenerator {
18
20
public static readonly unknownReference : string = '?' ;
19
21
20
- private _packageJsonLookup : PackageJsonLookup ;
21
- private _workingPackageName : string ;
22
- private _program : ts . Program ;
23
- private _typeChecker : ts . TypeChecker ;
24
- private _bundledPackageNames : ReadonlySet < string > ;
25
-
26
- public constructor (
27
- packageJsonLookup : PackageJsonLookup ,
28
- workingPackageName : string ,
29
- program : ts . Program ,
30
- typeChecker : ts . TypeChecker ,
31
- bundledPackageNames : ReadonlySet < string >
32
- ) {
33
- this . _packageJsonLookup = packageJsonLookup ;
34
- this . _workingPackageName = workingPackageName ;
35
- this . _program = program ;
36
- this . _typeChecker = typeChecker ;
37
- this . _bundledPackageNames = bundledPackageNames ;
22
+ private _collector : Collector ;
23
+
24
+ public constructor ( collector : Collector ) {
25
+ this . _collector = collector ;
38
26
}
39
27
40
28
/**
41
29
* Gets the UID for a TypeScript Identifier that references a type.
42
30
*/
43
31
public getDeclarationReferenceForIdentifier ( node : ts . Identifier ) : DeclarationReference | undefined {
44
- const symbol : ts . Symbol | undefined = this . _typeChecker . getSymbolAtLocation ( node ) ;
32
+ const symbol : ts . Symbol | undefined = this . _collector . typeChecker . getSymbolAtLocation ( node ) ;
45
33
if ( symbol !== undefined ) {
46
34
const isExpression : boolean = DeclarationReferenceGenerator . _isInExpressionContext ( node ) ;
47
35
return (
@@ -99,68 +87,48 @@ export class DeclarationReferenceGenerator {
99
87
) ;
100
88
}
101
89
102
- private static _getNavigationToSymbol ( symbol : ts . Symbol ) : Navigation | 'global' {
90
+ private _getNavigationToSymbol ( symbol : ts . Symbol ) : Navigation {
91
+ const declaration : ts . Declaration | undefined = TypeScriptHelpers . tryGetADeclaration ( symbol ) ;
92
+ const sourceFile : ts . SourceFile | undefined = declaration ?. getSourceFile ( ) ;
103
93
const parent : ts . Symbol | undefined = TypeScriptInternals . getSymbolParent ( symbol ) ;
104
- // First, try to determine navigation to symbol via its parent.
105
- if ( parent ) {
106
- if (
107
- parent . exports &&
108
- DeclarationReferenceGenerator . _isSameSymbol ( parent . exports . get ( symbol . escapedName ) , symbol )
109
- ) {
110
- return Navigation . Exports ;
111
- }
112
- if (
113
- parent . members &&
114
- DeclarationReferenceGenerator . _isSameSymbol ( parent . members . get ( symbol . escapedName ) , symbol )
115
- ) {
116
- return Navigation . Members ;
117
- }
118
- if (
119
- parent . globalExports &&
120
- DeclarationReferenceGenerator . _isSameSymbol ( parent . globalExports . get ( symbol . escapedName ) , symbol )
121
- ) {
122
- return 'global' ;
123
- }
94
+
95
+ // If it's a global, then use an Exports navigation.
96
+ if ( sourceFile && ! ts . isExternalModule ( sourceFile ) ) {
97
+ return Navigation . Exports ;
124
98
}
125
99
126
- // Next, try determining navigation to symbol by its node
127
- if ( symbol . valueDeclaration ) {
128
- const declaration : ts . Declaration = ts . isBindingElement ( symbol . valueDeclaration )
129
- ? ts . walkUpBindingElementsAndPatterns ( symbol . valueDeclaration )
130
- : symbol . valueDeclaration ;
131
- if ( ts . isClassElement ( declaration ) && ts . isClassLike ( declaration . parent ) ) {
132
- // class members are an "export" if they have the static modifier.
133
- return ts . getCombinedModifierFlags ( declaration ) & ts . ModifierFlags . Static
134
- ? Navigation . Exports
135
- : Navigation . Members ;
136
- }
137
- if ( ts . isTypeElement ( declaration ) || ts . isObjectLiteralElement ( declaration ) ) {
138
- // type and object literal element members are just members
139
- return Navigation . Members ;
140
- }
141
- if ( ts . isEnumMember ( declaration ) ) {
142
- // enum members are exports
143
- return Navigation . Exports ;
144
- }
145
- if (
146
- ts . isExportSpecifier ( declaration ) ||
147
- ts . isExportAssignment ( declaration ) ||
148
- ts . isExportSpecifier ( declaration ) ||
149
- ts . isExportDeclaration ( declaration ) ||
150
- ts . isNamedExports ( declaration )
151
- ) {
152
- return Navigation . Exports ;
100
+ // If it's from an external library, then use an Exports navigation.
101
+ if ( sourceFile && this . _collector . program . isSourceFileFromExternalLibrary ( sourceFile ) ) {
102
+ return Navigation . Exports ;
103
+ }
104
+
105
+ // Otherwise, this symbol is from the current package.
106
+ if ( parent ) {
107
+ // If we've found an exported CollectorEntity, then it's exported from the package entry point, so
108
+ // use an Exports navigation.
109
+ const namedDeclaration : ts . DeclarationName | undefined = (
110
+ declaration as ts . NamedDeclaration | undefined
111
+ ) ?. name ;
112
+ if ( namedDeclaration && ts . isIdentifier ( namedDeclaration ) ) {
113
+ const collectorEntity : CollectorEntity | undefined =
114
+ this . _collector . tryGetEntityForNode ( namedDeclaration ) ;
115
+ if ( collectorEntity && collectorEntity . exported ) {
116
+ return Navigation . Exports ;
117
+ }
153
118
}
154
- // declarations are exports if they have an `export` modifier.
155
- if ( ts . getCombinedModifierFlags ( declaration ) & ts . ModifierFlags . Export ) {
119
+
120
+ // If its parent symbol is not a source file, then use an Exports navigation. If the parent symbol is
121
+ // a source file, but it wasn't exported from the package entry point (in the check above), then the symbol
122
+ // is a local, so fall through below.
123
+ if ( ! DeclarationReferenceGenerator . _isExternalModuleSymbol ( parent ) ) {
156
124
return Navigation . Exports ;
157
125
}
158
- if ( ts . isSourceFile ( declaration . parent ) && ! ts . isExternalModule ( declaration . parent ) ) {
159
- // declarations in a source file are global if the source file is not a module.
160
- return 'global' ;
161
- }
162
126
}
163
- // all other declarations are locals
127
+
128
+ // Otherwise, we have a local symbol, so use a Locals navigation. These are either:
129
+ //
130
+ // 1. Symbols that are exported from a file module but not the package entry point.
131
+ // 2. Symbols that are not exported from their parent module.
164
132
return Navigation . Locals ;
165
133
}
166
134
@@ -218,20 +186,21 @@ export class DeclarationReferenceGenerator {
218
186
meaning : ts . SymbolFlags ,
219
187
includeModuleSymbols : boolean
220
188
) : DeclarationReference | undefined {
189
+ const declaration : ts . Node | undefined = TypeScriptHelpers . tryGetADeclaration ( symbol ) ;
190
+ const sourceFile : ts . SourceFile | undefined = declaration ?. getSourceFile ( ) ;
191
+
221
192
let followedSymbol : ts . Symbol = symbol ;
222
193
if ( followedSymbol . flags & ts . SymbolFlags . ExportValue ) {
223
- followedSymbol = this . _typeChecker . getExportSymbolOfSymbol ( followedSymbol ) ;
194
+ followedSymbol = this . _collector . typeChecker . getExportSymbolOfSymbol ( followedSymbol ) ;
224
195
}
225
196
if ( followedSymbol . flags & ts . SymbolFlags . Alias ) {
226
- followedSymbol = this . _typeChecker . getAliasedSymbol ( followedSymbol ) ;
197
+ followedSymbol = this . _collector . typeChecker . getAliasedSymbol ( followedSymbol ) ;
227
198
}
228
199
229
200
if ( DeclarationReferenceGenerator . _isExternalModuleSymbol ( followedSymbol ) ) {
230
201
if ( ! includeModuleSymbols ) {
231
202
return undefined ;
232
203
}
233
- const declaration : ts . Node | undefined = TypeScriptHelpers . tryGetADeclaration ( symbol ) ;
234
- const sourceFile : ts . SourceFile | undefined = declaration ?. getSourceFile ( ) ;
235
204
return new DeclarationReference ( this . _sourceFileToModuleSource ( sourceFile ) ) ;
236
205
}
237
206
@@ -270,13 +239,11 @@ export class DeclarationReferenceGenerator {
270
239
}
271
240
}
272
241
273
- let navigation : Navigation | 'global' =
274
- DeclarationReferenceGenerator . _getNavigationToSymbol ( followedSymbol ) ;
275
- if ( navigation === 'global' ) {
276
- if ( parentRef . source !== GlobalSource . instance ) {
277
- parentRef = new DeclarationReference ( GlobalSource . instance ) ;
278
- }
279
- navigation = Navigation . Exports ;
242
+ const navigation : Navigation = this . _getNavigationToSymbol ( followedSymbol ) ;
243
+
244
+ // If the symbol is a global, ensure the source is global.
245
+ if ( sourceFile && ! ts . isExternalModule ( sourceFile ) && parentRef . source !== GlobalSource . instance ) {
246
+ parentRef = new DeclarationReference ( GlobalSource . instance ) ;
280
247
}
281
248
282
249
return parentRef
@@ -313,7 +280,7 @@ export class DeclarationReferenceGenerator {
313
280
if ( grandParent && ts . isModuleDeclaration ( grandParent ) ) {
314
281
const grandParentSymbol : ts . Symbol | undefined = TypeScriptInternals . tryGetSymbolForDeclaration (
315
282
grandParent ,
316
- this . _typeChecker
283
+ this . _collector . typeChecker
317
284
) ;
318
285
if ( grandParentSymbol ) {
319
286
return this . _symbolToDeclarationReference (
@@ -334,28 +301,27 @@ export class DeclarationReferenceGenerator {
334
301
}
335
302
336
303
private _getPackageName ( sourceFile : ts . SourceFile ) : string {
337
- if ( this . _program . isSourceFileFromExternalLibrary ( sourceFile ) ) {
338
- const packageJson : INodePackageJson | undefined = this . _packageJsonLookup . tryLoadNodePackageJsonFor (
339
- sourceFile . fileName
340
- ) ;
304
+ if ( this . _collector . program . isSourceFileFromExternalLibrary ( sourceFile ) ) {
305
+ const packageJson : INodePackageJson | undefined =
306
+ this . _collector . packageJsonLookup . tryLoadNodePackageJsonFor ( sourceFile . fileName ) ;
341
307
342
308
if ( packageJson && packageJson . name ) {
343
309
return packageJson . name ;
344
310
}
345
311
return DeclarationReferenceGenerator . unknownReference ;
346
312
}
347
- return this . _workingPackageName ;
313
+ return this . _collector . workingPackage . name ;
348
314
}
349
315
350
316
private _sourceFileToModuleSource ( sourceFile : ts . SourceFile | undefined ) : GlobalSource | ModuleSource {
351
317
if ( sourceFile && ts . isExternalModule ( sourceFile ) ) {
352
318
const packageName : string = this . _getPackageName ( sourceFile ) ;
353
319
354
- if ( this . _bundledPackageNames . has ( packageName ) ) {
320
+ if ( this . _collector . bundledPackageNames . has ( packageName ) ) {
355
321
// The api-extractor.json config file has a "bundledPackages" setting, which causes imports from
356
322
// certain NPM packages to be treated as part of the working project. In this case, we need to
357
323
// substitute the working package name.
358
- return new ModuleSource ( this . _workingPackageName ) ;
324
+ return new ModuleSource ( this . _collector . workingPackage . name ) ;
359
325
} else {
360
326
return new ModuleSource ( packageName ) ;
361
327
}
0 commit comments