extensions/typescript-language-features/src/utils/previewer.ts/convertLinkTags
function convertLinkTags(
	parts: readonly Proto.SymbolDisplayPart[] | string | undefined,
	filePathConverter: IFilePathToResourceConverter,
): string {
	if (!parts) {
		return '';
	}

	if (typeof parts === 'string') {
		return parts;
	}

	const out: string[] = [];

	let currentLink: { name?: string, target?: Proto.FileSpan, text?: string } | undefined;
	for (const part of parts) {
		switch (part.kind) {
			case 'link':
				if (currentLink) {
					const text = currentLink.text ?? currentLink.name;
					if (currentLink.target) {
						const link = filePathConverter.toResource(currentLink.target.file)
							.with({
								fragment: `L${currentLink.target.start.line},${currentLink.target.start.offset}`
							});

						out.push(`[${text}](${link.toString()})`);
					} else {
						if (text) {
							if (/^https?:/.test(text)) {
								const parts = text.split(' ');
								if (parts.length === 1) {
									out.push(parts[0]);
								} else if (parts.length > 1) {
									out.push(`[${parts.slice(1).join(' ')}](${parts[0]})`);
								}
							} else {
								out.push(text);
							}
						}
					}
					currentLink = undefined;
				} else {
					currentLink = {};
				}
				break;

			case 'linkName':
				if (currentLink) {
					currentLink.name = part.text;
					// TODO: remove cast once we pick up TS 4.3
					currentLink.target = (part as any as Proto.JSDocLinkDisplayPart).target;
				}
				break;

			case 'linkText':
				if (currentLink) {
					currentLink.text = part.text;
				}
				break;

			default:
				out.push(part.text);
				break;
		}
	}
	return processInlineTags(out.join(''));
}