diff --git a/package-lock.json b/package-lock.json index a17c0e2..fcff8f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "monaco-json", - "version": "2.5.1", + "version": "2.6.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/src/jsonMode.ts b/src/jsonMode.ts index cbdd06e..656136f 100644 --- a/src/jsonMode.ts +++ b/src/jsonMode.ts @@ -13,9 +13,10 @@ import { createTokenizationSupport } from './tokenization'; import Uri = monaco.Uri; import IDisposable = monaco.IDisposable; -export function setupMode(defaults: LanguageServiceDefaultsImpl): void { +export function setupMode(defaults: LanguageServiceDefaultsImpl): IDisposable { - let disposables: IDisposable[] = []; + const disposables: IDisposable[] = []; + const providers: IDisposable[] = []; const client = new WorkerManager(defaults); disposables.push(client); @@ -24,20 +25,67 @@ export function setupMode(defaults: LanguageServiceDefaultsImpl): void { return client.getLanguageServiceWorker(...uris); }; - let languageId = defaults.languageId; - - disposables.push(monaco.languages.registerCompletionItemProvider(languageId, new languageFeatures.CompletionAdapter(worker))); - disposables.push(monaco.languages.registerHoverProvider(languageId, new languageFeatures.HoverAdapter(worker))); - disposables.push(monaco.languages.registerDocumentSymbolProvider(languageId, new languageFeatures.DocumentSymbolAdapter(worker))); - disposables.push(monaco.languages.registerDocumentFormattingEditProvider(languageId, new languageFeatures.DocumentFormattingEditProvider(worker))); - disposables.push(monaco.languages.registerDocumentRangeFormattingEditProvider(languageId, new languageFeatures.DocumentRangeFormattingEditProvider(worker))); - disposables.push(new languageFeatures.DiagnosticsAdapter(languageId, worker, defaults)); - disposables.push(monaco.languages.setTokensProvider(languageId, createTokenizationSupport(true))); - disposables.push(monaco.languages.setLanguageConfiguration(languageId, richEditConfiguration)); - disposables.push(monaco.languages.registerColorProvider(languageId, new languageFeatures.DocumentColorAdapter(worker))); - disposables.push(monaco.languages.registerFoldingRangeProvider(languageId, new languageFeatures.FoldingRangeAdapter(worker))); + + function registerProviders(): void { + const { languageId, modeConfiguration } = defaults; + + disposeAll(providers); + + if (modeConfiguration.documentFormattingEdits) { + providers.push(monaco.languages.registerDocumentFormattingEditProvider(languageId, new languageFeatures.DocumentFormattingEditProvider(worker))); + } + if (modeConfiguration.documentRangeFormattingEdits) { + providers.push(monaco.languages.registerDocumentRangeFormattingEditProvider(languageId, new languageFeatures.DocumentRangeFormattingEditProvider(worker))); + } + if (modeConfiguration.completionItems) { + providers.push(monaco.languages.registerCompletionItemProvider(languageId, new languageFeatures.CompletionAdapter(worker))); + } + if (modeConfiguration.hovers) { + providers.push(monaco.languages.registerHoverProvider(languageId, new languageFeatures.HoverAdapter(worker))); + } + if (modeConfiguration.documentSymbols) { + providers.push(monaco.languages.registerDocumentSymbolProvider(languageId, new languageFeatures.DocumentSymbolAdapter(worker))); + } + if (modeConfiguration.tokens) { + providers.push(monaco.languages.setTokensProvider(languageId, createTokenizationSupport(true))); + } + if (modeConfiguration.colors) { + providers.push(monaco.languages.registerColorProvider(languageId, new languageFeatures.DocumentColorAdapter(worker))); + } + if (modeConfiguration.foldingRanges) { + providers.push(monaco.languages.registerFoldingRangeProvider(languageId, new languageFeatures.FoldingRangeAdapter(worker))); + } + if (modeConfiguration.diagnostics) { + providers.push(new languageFeatures.DiagnosticsAdapter(languageId, worker, defaults)); + } + } + + registerProviders(); + + disposables.push(monaco.languages.setLanguageConfiguration(defaults.languageId, richEditConfiguration)); + + let modeConfiguration = defaults.modeConfiguration; + defaults.onDidChange((newDefaults) => { + if (newDefaults.modeConfiguration !== modeConfiguration) { + modeConfiguration = newDefaults.modeConfiguration; + registerProviders(); + } + }); + + disposables.push(asDisposable(providers)); + + return asDisposable(disposables); } +function asDisposable(disposables: IDisposable[]): IDisposable { + return { dispose: () => disposeAll(disposables) }; +} + +function disposeAll(disposables: IDisposable[]) { + while (disposables.length) { + disposables.pop().dispose(); + } +} const richEditConfiguration: monaco.languages.LanguageConfiguration = { wordPattern: /(-?\d*\.\d\w*)|([^\[\{\]\}\:\"\,\s]+)/g, diff --git a/src/monaco.contribution.ts b/src/monaco.contribution.ts index c776a3a..49c5108 100644 --- a/src/monaco.contribution.ts +++ b/src/monaco.contribution.ts @@ -8,7 +8,6 @@ import * as mode from './jsonMode'; import Emitter = monaco.Emitter; import IEvent = monaco.IEvent; -import IDisposable = monaco.IDisposable; // --- JSON configuration and defaults --------- @@ -16,11 +15,13 @@ export class LanguageServiceDefaultsImpl implements monaco.languages.json.Langua private _onDidChange = new Emitter(); private _diagnosticsOptions: monaco.languages.json.DiagnosticsOptions; + private _modeConfiguration: monaco.languages.json.ModeConfiguration; private _languageId: string; - constructor(languageId: string, diagnosticsOptions: monaco.languages.json.DiagnosticsOptions) { + constructor(languageId: string, diagnosticsOptions: monaco.languages.json.DiagnosticsOptions, modeConfiguration: monaco.languages.json.ModeConfiguration) { this._languageId = languageId; this.setDiagnosticsOptions(diagnosticsOptions); + this.setModeConfiguration(modeConfiguration) } get onDidChange(): IEvent { @@ -31,6 +32,10 @@ export class LanguageServiceDefaultsImpl implements monaco.languages.json.Langua return this._languageId; } + get modeConfiguration(): monaco.languages.json.ModeConfiguration { + return this._modeConfiguration; + } + get diagnosticsOptions(): monaco.languages.json.DiagnosticsOptions { return this._diagnosticsOptions; } @@ -39,22 +44,37 @@ export class LanguageServiceDefaultsImpl implements monaco.languages.json.Langua this._diagnosticsOptions = options || Object.create(null); this._onDidChange.fire(this); } + setModeConfiguration(modeConfiguration: monaco.languages.json.ModeConfiguration): void { + this._modeConfiguration = modeConfiguration || Object.create(null); + this._onDidChange.fire(this); + }; } const diagnosticDefault: monaco.languages.json.DiagnosticsOptions = { validate: true, allowComments: true, schemas: [], - enableSchemaRequest: false + enableSchemaRequest: false }; -const jsonDefaults = new LanguageServiceDefaultsImpl('json', diagnosticDefault); +const modeConfigurationDefault: monaco.languages.json.ModeConfiguration = { + documentFormattingEdits: true, + documentRangeFormattingEdits: true, + completionItems: true, + hovers: true, + documentSymbols: true, + tokens: true, + colors: true, + foldingRanges: true, + diagnostics: true +} +const jsonDefaults = new LanguageServiceDefaultsImpl('json', diagnosticDefault, modeConfigurationDefault); // Export API function createAPI(): typeof monaco.languages.json { return { - jsonDefaults: jsonDefaults, + jsonDefaults: jsonDefaults } } monaco.languages.json = createAPI(); @@ -71,6 +91,7 @@ monaco.languages.register({ aliases: ['JSON', 'json'], mimetypes: ['application/json'], }); + monaco.languages.onLanguage('json', () => { getMode().then(mode => mode.setupMode(jsonDefaults)); }); diff --git a/src/monaco.d.ts b/src/monaco.d.ts index c1b21ed..091b218 100644 --- a/src/monaco.d.ts +++ b/src/monaco.d.ts @@ -33,13 +33,63 @@ declare module monaco.languages.json { /** * If set, the schema service would load schema content on-demand with 'fetch' if available */ - readonly enableSchemaRequest? : boolean + readonly enableSchemaRequest?: boolean; + } + + export interface ModeConfiguration { + /** + * Defines whether the built-in documentFormattingEdit provider is enabled. + */ + readonly documentFormattingEdits?: boolean; + + /** + * Defines whether the built-in documentRangeFormattingEdit provider is enabled. + */ + readonly documentRangeFormattingEdits?: boolean; + + /** + * Defines whether the built-in completionItemProvider is enabled. + */ + readonly completionItems?: boolean; + + /** + * Defines whether the built-in hoverProvider is enabled. + */ + readonly hovers?: boolean; + + /** + * Defines whether the built-in documentSymbolProvider is enabled. + */ + readonly documentSymbols?: boolean; + + /** + * Defines whether the built-in tokens provider is enabled. + */ + readonly tokens?: boolean; + + /** + * Defines whether the built-in color provider is enabled. + */ + readonly colors?: boolean; + + /** + * Defines whether the built-in foldingRange provider is enabled. + */ + readonly foldingRanges?: boolean; + + /** + * Defines whether the built-in diagnostic provider is enabled. + */ + readonly diagnostics?: boolean; + } export interface LanguageServiceDefaults { readonly onDidChange: IEvent; readonly diagnosticsOptions: DiagnosticsOptions; + readonly modeConfiguration: ModeConfiguration; setDiagnosticsOptions(options: DiagnosticsOptions): void; + setModeConfiguration(modeConfiguration: ModeConfiguration): void; } export var jsonDefaults: LanguageServiceDefaults;