in tsc/src/lsif.ts [1886:1941]
private computeExportPath(symbol: ts.Symbol, moduleSystem: ModuleSystemKind): [string | undefined | null, ModuleSystemKind] {
// For a declaration like export default function foo()
if (Symbols.isSourceFile(symbol) && (moduleSystem === ModuleSystemKind.module || moduleSystem === ModuleSystemKind.unknown)) {
return ['', moduleSystem];
}
const parent = tss.Symbol.getParent(symbol);
const isNotNamed = (Symbols.isInternal(symbol) && (symbol.escapedName !== ts.InternalSymbolName.Default && symbol.escapedName !== ts.InternalSymbolName.ExportEquals));
if (parent === undefined) {
// If we are in a module system `declare global` adds to the global namespace.
// Check if we are in this case
if (moduleSystem === ModuleSystemKind.module && symbol.escapedName === ts.InternalSymbolName.Global) {
return ['', ModuleSystemKind.global];
}
// In a global module system symbol inside other namespace don't have a parent
// if the symbol is not exported. So we need to check if the symbol is a top
// level symbol
else if (moduleSystem === ModuleSystemKind.global) {
if (this.isTopLevelSymbol(symbol)) {
return [isNotNamed ? null : this.getExportSymbolName(symbol), moduleSystem];
}
// In a global module system signature can be merged across file. So even parameters
// must be exported to allow merging across files.
const parameterDeclaration = Symbols.asParameterDeclaration(symbol);
if (parameterDeclaration !== undefined && parameterDeclaration.parent.name !== undefined) {
const parentSymbol = this.getSymbolAtLocation(parameterDeclaration.parent.name);
if (parentSymbol !== undefined) {
const parentExportPath = this.getExportPath(parentSymbol);
if (parentExportPath !== undefined) {
return [isNotNamed ? null : `${parentExportPath}.${this.getExportSymbolName(symbol)}`, moduleSystem];
}
}
}
}
return [undefined, moduleSystem];
} else {
// `export as namespace` create a global symbol also defined in a module file.
// This is comparable to declare global.
if (Symbols.isSourceFile(parent) && Symbols.isNamespaceExportDeclaration(symbol)) {
return [this.getExportSymbolName(symbol), ModuleSystemKind.global];
}
const parentValue = this.getExportPath(parent);
// The parent is not exported so any member isn't either
if (parentValue === undefined) {
return [undefined, moduleSystem];
} else {
const [parentExportPath, parentModuleSystem] = parentValue;
if (Symbols.isInterface(parent) || Symbols.isClass(parent) || Symbols.isTypeLiteral(parent)) {
return [isNotNamed || parentExportPath === null ? null : `${parentExportPath}.${this.getExportSymbolName(symbol)}`, parentModuleSystem];
} else if (this.parentExports(parent, symbol)) {
return [isNotNamed || parentExportPath === null ? null : parentExportPath.length > 0 ? `${parentExportPath}.${this.getExportSymbolName(symbol)}` : this.getExportSymbolName(symbol), parentModuleSystem];
} else {
return [undefined, moduleSystem];
}
}
}
}