/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { Event, EventEmitter, extensions } from 'vscode'; /** * JSON language participant contribution. */ interface LanguageParticipantContribution { /** * The id of the language which participates with the JSON language server. */ languageId: string; /** * true if the language allows comments and false otherwise. * TODO: implement server side setting */ comments?: boolean; } export interface LanguageParticipants { readonly onDidChange: Event; readonly documentSelector: string[]; hasLanguage(languageId: string): boolean; useComments(languageId: string): boolean; dispose(): void; } export function getLanguageParticipants(): LanguageParticipants { const onDidChangeEmmiter = new EventEmitter(); let languages = new Set(); let comments = new Set(); function update() { const oldLanguages = languages, oldComments = comments; languages = new Set(); languages.add('json'); languages.add('jsonc'); languages.add('snippets'); comments = new Set(); comments.add('jsonc'); comments.add('snippets'); for (const extension of extensions.allAcrossExtensionHosts) { const jsonLanguageParticipants = extension.packageJSON?.contributes?.jsonLanguageParticipants as LanguageParticipantContribution[]; if (Array.isArray(jsonLanguageParticipants)) { for (const jsonLanguageParticipant of jsonLanguageParticipants) { const languageId = jsonLanguageParticipant.languageId; if (typeof languageId === 'string') { languages.add(languageId); if (jsonLanguageParticipant.comments === true) { comments.add(languageId); } } } } } return !isEqualSet(languages, oldLanguages) || !isEqualSet(comments, oldComments); } update(); const changeListener = extensions.onDidChange(_ => { if (update()) { onDidChangeEmmiter.fire(); } }); return { onDidChange: onDidChangeEmmiter.event, get documentSelector() { return Array.from(languages); }, hasLanguage(languageId: string) { return languages.has(languageId); }, useComments(languageId: string) { return comments.has(languageId); }, dispose: () => changeListener.dispose() }; } function isEqualSet(s1: Set, s2: Set) { if (s1.size !== s2.size) { return false; } for (const e of s1) { if (!s2.has(e)) { return false; } } return true; }