extensions/markdown-language-features/server/src/languageFeatures/diagnostics.ts/registerValidateSupport
export function registerValidateSupport(
	connection: Connection,
	workspace: md.IWorkspace,
	documents: TextDocuments<md.ITextDocument>,
	ls: md.IMdLanguageService,
	config: ConfigurationManager,
	logger: md.ILogger,
): Disposable {
	let diagnosticOptions: md.DiagnosticOptions = defaultDiagnosticOptions;
	function updateDiagnosticsSetting(): void {
		diagnosticOptions = getDiagnosticsOptions(config);
	}

	const subs: Disposable[] = [];
	const manager = ls.createPullDiagnosticsManager();
	subs.push(manager);

	subs.push(manager.onLinkedToFileChanged(() => {
		// TODO: We only need to refresh certain files
		connection.languages.diagnostics.refresh();
	}));

	const emptyDiagnosticsResponse = Object.freeze({ kind: 'full', items: [] });

	connection.languages.diagnostics.on(async (params, token): Promise<FullDocumentDiagnosticReport | UnchangedDocumentDiagnosticReport> => {
		logger.log(md.LogLevel.Trace, 'Server: connection.languages.diagnostics.on', params.textDocument.uri);

		if (!config.getSettings()?.markdown.validate.enabled) {
			return emptyDiagnosticsResponse;
		}

		const uri = URI.parse(params.textDocument.uri);
		if (!workspace.hasMarkdownDocument(uri)) {
			return emptyDiagnosticsResponse;
		}

		const document = await workspace.openMarkdownDocument(uri);
		if (!document) {
			return emptyDiagnosticsResponse;
		}

		const diagnostics = await manager.computeDiagnostics(document, diagnosticOptions, token);
		return {
			kind: 'full',
			items: diagnostics,
		};
	});

	updateDiagnosticsSetting();
	subs.push(config.onDidChangeConfiguration(() => {
		updateDiagnosticsSetting();
		connection.languages.diagnostics.refresh();
	}));

	subs.push(documents.onDidClose(e => {
		manager.disposeDocumentResources(URI.parse(e.document.uri));
	}));

	return {
		dispose: () => {
			disposeAll(subs);
		}
	};
}