@@ -15,6 +15,7 @@ import { TypeScriptHelpers } from '../analyzer/TypeScriptHelpers';
15
15
import { TypeScriptInternals } from '../analyzer/TypeScriptInternals' ;
16
16
import { Collector } from '../collector/Collector' ;
17
17
import { CollectorEntity } from '../collector/CollectorEntity' ;
18
+ import { AstNamespaceImport } from '../analyzer/AstNamespaceImport' ;
18
19
19
20
export class DeclarationReferenceGenerator {
20
21
public static readonly unknownReference : string = '?' ;
@@ -109,34 +110,27 @@ export class DeclarationReferenceGenerator {
109
110
return Navigation . Exports ;
110
111
}
111
112
112
- // Otherwise, this symbol is from the current package.
113
- if ( parent ) {
114
- // If we've found an exported CollectorEntity, then it's exported from the package entry point, so
115
- // use Exports.
116
- const namedDeclaration : ts . DeclarationName | undefined = (
117
- declaration as ts . NamedDeclaration | undefined
118
- ) ?. name ;
119
- if ( namedDeclaration && ts . isIdentifier ( namedDeclaration ) ) {
120
- const collectorEntity : CollectorEntity | undefined =
121
- this . _collector . tryGetEntityForNode ( namedDeclaration ) ;
122
- if ( collectorEntity && collectorEntity . exported ) {
123
- return Navigation . Exports ;
124
- }
125
- }
126
-
127
- // If its parent symbol is not a source file, then use either Exports or Members. If the parent symbol
128
- // is a source file, but it wasn't exported from the package entry point (in the check above), then the
129
- // symbol is a local, so fall through below.
130
- if ( ! DeclarationReferenceGenerator . _isExternalModuleSymbol ( parent ) ) {
131
- if (
132
- parent . members &&
133
- DeclarationReferenceGenerator . _isSameSymbol ( parent . members . get ( symbol . escapedName ) , symbol )
134
- ) {
135
- return Navigation . Members ;
136
- }
113
+ // Otherwise, this symbol is from the current package. If we've found an associated consumable
114
+ // `CollectorEntity`, then use Exports. We use `consumable` here instead of `exported` because
115
+ // if the symbol is exported from a non-consumable `AstNamespaceImport`, we don't want to use
116
+ // Exports. We should use Locals instead.
117
+ const entity : CollectorEntity | undefined = this . _collector . tryGetEntityForSymbol ( symbol ) ;
118
+ if ( entity ?. consumable ) {
119
+ return Navigation . Exports ;
120
+ }
137
121
138
- return Navigation . Exports ;
122
+ // If its parent symbol is not a source file, then use either Exports or Members. If the parent symbol
123
+ // is a source file, but it wasn't exported from the package entry point (in the check above), then the
124
+ // symbol is a local, so fall through below.
125
+ if ( parent && ! DeclarationReferenceGenerator . _isExternalModuleSymbol ( parent ) ) {
126
+ if (
127
+ parent . members &&
128
+ DeclarationReferenceGenerator . _isSameSymbol ( parent . members . get ( symbol . escapedName ) , symbol )
129
+ ) {
130
+ return Navigation . Members ;
139
131
}
132
+
133
+ return Navigation . Exports ;
140
134
}
141
135
142
136
// Otherwise, we have a local symbol, so use a Locals navigation. These are either:
@@ -209,6 +203,12 @@ export class DeclarationReferenceGenerator {
209
203
}
210
204
if ( followedSymbol . flags & ts . SymbolFlags . Alias ) {
211
205
followedSymbol = this . _collector . typeChecker . getAliasedSymbol ( followedSymbol ) ;
206
+
207
+ // Without this logic, we end up following the symbol `ns` in `import * as ns from './file'` to
208
+ // the actual file `file.ts`. We don't want to do this, so revert to the original symbol.
209
+ if ( followedSymbol . flags & ts . SymbolFlags . ValueModule ) {
210
+ followedSymbol = symbol ;
211
+ }
212
212
}
213
213
214
214
if ( DeclarationReferenceGenerator . _isExternalModuleSymbol ( followedSymbol ) ) {
@@ -229,6 +229,11 @@ export class DeclarationReferenceGenerator {
229
229
}
230
230
231
231
let localName : string = followedSymbol . name ;
232
+ const entity : CollectorEntity | undefined = this . _collector . tryGetEntityForSymbol ( followedSymbol ) ;
233
+ if ( entity ?. nameForEmit ) {
234
+ localName = entity . nameForEmit ;
235
+ }
236
+
232
237
if ( followedSymbol . escapedName === ts . InternalSymbolName . Constructor ) {
233
238
localName = 'constructor' ;
234
239
} else {
@@ -267,8 +272,38 @@ export class DeclarationReferenceGenerator {
267
272
268
273
private _getParentReference ( symbol : ts . Symbol ) : DeclarationReference | undefined {
269
274
const declaration : ts . Node | undefined = TypeScriptHelpers . tryGetADeclaration ( symbol ) ;
275
+ const sourceFile : ts . SourceFile | undefined = declaration ?. getSourceFile ( ) ;
276
+
277
+ // Note that it's possible for a symbol to be exported from an entry point as well as one or more
278
+ // namespaces. In that case, it's not clear what to choose as its parent. Today's logic is neither
279
+ // perfect nor particularly stable to API items being renamed and shuffled around.
280
+ const entity : CollectorEntity | undefined = this . _collector . tryGetEntityForSymbol ( symbol ) ;
281
+ if ( entity ) {
282
+ if ( entity . exportedFromEntryPoint ) {
283
+ return new DeclarationReference ( this . _sourceFileToModuleSource ( sourceFile ) ) ;
284
+ }
285
+
286
+ const firstExportingConsumableParent : CollectorEntity | undefined =
287
+ entity . getFirstExportingConsumableParent ( ) ;
288
+ if (
289
+ firstExportingConsumableParent &&
290
+ firstExportingConsumableParent . astEntity instanceof AstNamespaceImport
291
+ ) {
292
+ const parentSymbol : ts . Symbol | undefined = TypeScriptInternals . tryGetSymbolForDeclaration (
293
+ firstExportingConsumableParent . astEntity . declaration ,
294
+ this . _collector . typeChecker
295
+ ) ;
296
+ if ( parentSymbol ) {
297
+ return this . _symbolToDeclarationReference (
298
+ parentSymbol ,
299
+ parentSymbol . flags ,
300
+ /*includeModuleSymbols*/ true
301
+ ) ;
302
+ }
303
+ }
304
+ }
270
305
271
- // First , try to find a parent symbol via the symbol tree.
306
+ // Next , try to find a parent symbol via the symbol tree.
272
307
const parentSymbol : ts . Symbol | undefined = TypeScriptInternals . getSymbolParent ( symbol ) ;
273
308
if ( parentSymbol ) {
274
309
return this . _symbolToDeclarationReference (
@@ -306,7 +341,6 @@ export class DeclarationReferenceGenerator {
306
341
}
307
342
308
343
// At this point, we have a local symbol in a module.
309
- const sourceFile : ts . SourceFile | undefined = declaration ?. getSourceFile ( ) ;
310
344
if ( sourceFile && ts . isExternalModule ( sourceFile ) ) {
311
345
return new DeclarationReference ( this . _sourceFileToModuleSource ( sourceFile ) ) ;
312
346
} else {
0 commit comments