in tsc/src/lsif.ts [1177:1267]
protected walkType(type: ts.Type, mode: FlowMode, markOnly: boolean, moduleSystem: ModuleSystemKind, path: string, level: number): void {
if (this.visitedTypes.has(type)) {
return;
}
this.visitedTypes.add(type);
let walkSymbol: boolean = this.walkSymbolFromTopLevelType || level > 0;
// We have a call signature
if (tss.Type.hasCallSignature(type) || tss.Type.hasConstructSignatures(type)) {
for (const signature of type.getCallSignatures().concat(type.getConstructSignatures())) {
// In a global module system signature can be merged hence type parameters need to be exported. Do that before
//we walt the parameter and return type since they can reference a type parameter
if (moduleSystem === ModuleSystemKind.global) {
const typeParameters = signature.getTypeParameters();
if (typeParameters !== undefined) {
for (const typeParameter of typeParameters) {
const symbol = typeParameter.getSymbol();
if (symbol !== undefined && !this.visitedSymbols.has(symbol)) {
this.visitedSymbols.add(symbol);
this.changeVisibility(symbol);
}
}
}
}
for (const parameter of signature.getParameters()) {
const parameterType = this.symbols.getTypeOfSymbol(parameter, () => { return this.getLocationNode(); });
const exportIdentifier = `${path}.__arg.${this.symbols.getExportSymbolName(parameter)}`;
const newMode = tss.Type.hasCallSignature(parameterType) ? FlowMode.reverse(mode) : mode;
this.walkType(parameterType, newMode, markOnly, moduleSystem, exportIdentifier, level + 1);
}
const returnType = signature.getReturnType();
this.walkType(returnType, mode, markOnly, moduleSystem, `${path}.__rt`, level + 1);
}
}
if (type.isUnionOrIntersection()) {
for (const part of type.types) {
this.walkType(part, mode, markOnly, moduleSystem, path, level + 1);
}
}
if (tss.Type.isInterface(type)) {
const bases = this.symbols.types.getBaseTypes(type);
if (bases !== undefined) {
for (const base of bases) {
this.walkType(base, mode, markOnly, moduleSystem, path, level + 1);
}
}
}
if (tss.Type.isClass(type)) {
const bases = this.symbols.types.getExtendsTypes(type);
if (bases !== undefined) {
for (const base of bases) {
this.walkType(base, mode, markOnly, moduleSystem, path, level + 1);
}
}
}
if (tss.Type.isObjectType(type)) {
if (tss.Type.isTypeReference(type)) {
const typeReferences = this.symbols.types.getTypeArguments(type);
for (const reference of typeReferences) {
this.walkType(reference, mode, markOnly, moduleSystem, path, level + 1);
}
} else if (tss.Type.isAnonymous(type)) {
walkSymbol = true;
}
}
if (type.aliasTypeArguments !== undefined) {
for (const aliasTypeArgument of type.aliasTypeArguments) {
this.walkType(aliasTypeArgument, mode, markOnly, moduleSystem, path, level + 1);
}
}
if (tss.Type.isConditionalType(type)) {
this.walkType(type.checkType, mode, markOnly, moduleSystem, path, level + 1);
this.walkType(type.extendsType, mode, markOnly, moduleSystem, path, level + 1);
type.resolvedTrueType !== undefined && this.walkType(type.resolvedTrueType, mode, markOnly, moduleSystem, path, level + 1);
type.resolvedFalseType !== undefined && this.walkType(type.resolvedFalseType, mode, markOnly, moduleSystem, path, level + 1);
}
const symbol = type.getSymbol();
if (symbol !== undefined && walkSymbol) {
// We don't need a stack or a counter since we guard
// against double visit with the visitedSymbols and visitedTypes
this.walkedSymbolsFromType.add(symbol);
this.walkSymbol(symbol, mode, !Symbols.isInternal(symbol), path, level + 1);
this.walkedSymbolsFromType.delete(symbol);
}
}