protected walkType()

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