extensions/html-language-features/client/src/htmlClient.ts/startClient
export async function startClient(context: ExtensionContext, newLanguageClient: LanguageClientConstructor, runtime: Runtime): Promise<AsyncDisposable> {

	const outputChannel = window.createOutputChannel(languageServerDescription);

	const languageParticipants = getLanguageParticipants();
	context.subscriptions.push(languageParticipants);

	let client: Disposable | undefined = await startClientWithParticipants(languageParticipants, newLanguageClient, outputChannel, runtime);

	const promptForLinkedEditingKey = 'html.promptForLinkedEditing';
	if (extensions.getExtension('formulahendry.auto-rename-tag') !== undefined && (context.globalState.get(promptForLinkedEditingKey) !== false)) {
		const config = workspace.getConfiguration('editor', { languageId: 'html' });
		if (!config.get('linkedEditing') && !config.get('renameOnType')) {
			const activeEditorListener = window.onDidChangeActiveTextEditor(async e => {
				if (e && languageParticipants.hasLanguage(e.document.languageId)) {
					context.globalState.update(promptForLinkedEditingKey, false);
					activeEditorListener.dispose();
					const configure = l10n.t('Configure');
					const res = await window.showInformationMessage(l10n.t('VS Code now has built-in support for auto-renaming tags. Do you want to enable it?'), configure);
					if (res === configure) {
						commands.executeCommand('workbench.action.openSettings', SettingIds.linkedEditing);
					}
				}
			});
			context.subscriptions.push(activeEditorListener);
		}
	}

	let restartTrigger: Disposable | undefined;
	languageParticipants.onDidChange(() => {
		if (restartTrigger) {
			restartTrigger.dispose();
		}
		restartTrigger = runtime.timer.setTimeout(async () => {
			if (client) {
				outputChannel.appendLine('Extensions have changed, restarting HTML server...');
				outputChannel.appendLine('');
				const oldClient = client;
				client = undefined;
				await oldClient.dispose();
				client = await startClientWithParticipants(languageParticipants, newLanguageClient, outputChannel, runtime);
			}
		}, 2000);
	});

	return {
		dispose: async () => {
			restartTrigger?.dispose();
			await client?.dispose();
			outputChannel.dispose();
		}
	};
}