private computeExportPath()

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];
				}
			}
		}
	}