package/src/kustoMode.ts (125 lines of code) (raw):

import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; import { WorkerManager } from './workerManager'; import type { KustoWorker, LanguageServiceDefaults } from './monaco.contribution'; import * as languageFeatures from './languageFeatures'; import type { Schema } from './languageServiceManager/schema'; import type { IKustoWorkerImpl } from './kustoWorker'; import { kustoLanguageDefinition } from './syntaxHighlighting/kustoMonarchLanguageDefinition'; import { LANGUAGE_ID } from './globals'; import { semanticTokensProviderRegistrarCreator } from './syntaxHighlighting/semanticTokensProviderRegistrar'; import { languages } from 'monaco-editor/esm/vs/editor/editor.api'; import LanguageConfiguration = languages.LanguageConfiguration; export interface AugmentedWorker extends KustoWorker, Omit<IKustoWorkerImpl, 'setSchemaFromShowSchema' | 'getReferencedSymbols'> {} export interface AugmentedWorkerAccessor { (first: monaco.Uri, ...more: monaco.Uri[]): Promise<AugmentedWorker>; } let kustoWorker: AugmentedWorkerAccessor; let resolveWorker: (value: AugmentedWorkerAccessor | PromiseLike<AugmentedWorkerAccessor>) => void; let rejectWorker: (err: any) => void; let workerPromise: Promise<AugmentedWorkerAccessor> = new Promise((resolve, reject) => { resolveWorker = resolve; rejectWorker = reject; }); /** * Called when Kusto language is first needed (a model has the language set) * @param defaults */ export function setupMode(defaults: LanguageServiceDefaults, monacoInstance: typeof globalThis.monaco) { const onSchemaChange = new monaco.Emitter<Schema>(); const semanticTokensProviderRegistrar = semanticTokensProviderRegistrarCreator(); const client = new WorkerManager(monacoInstance, defaults); const workerAccessor: AugmentedWorkerAccessor = (first, ...more) => { const augmentedSetSchema = async (schema: Schema, worker: KustoWorker) => { const workerPromise = worker.setSchema(schema); await workerPromise.then(() => { onSchemaChange.fire(schema); }); semanticTokensProviderRegistrar(monacoInstance, workerAccessor); }; const worker = client.getLanguageServiceWorker(...[first].concat(more)); return worker.then( (worker): AugmentedWorker => ({ ...worker, setSchema: (schema) => augmentedSetSchema(schema, worker), async setSchemaFromShowSchema( schema, connection, database, globalScalarParameters, globalTabularParameters ) { await worker.normalizeSchema(schema, connection, database).then((schema) => { if (globalScalarParameters || globalTabularParameters) { schema = { ...schema, globalScalarParameters, globalTabularParameters }; } augmentedSetSchema(schema, worker); }); }, }) ); }; monacoInstance.languages.registerCompletionItemProvider( LANGUAGE_ID, new languageFeatures.CompletionAdapter(workerAccessor, defaults.languageSettings) ); monacoInstance.languages.setMonarchTokensProvider(LANGUAGE_ID, kustoLanguageDefinition); new languageFeatures.DiagnosticsAdapter( monacoInstance, LANGUAGE_ID, workerAccessor, defaults, onSchemaChange.event ); monacoInstance.languages.registerDocumentRangeFormattingEditProvider( LANGUAGE_ID, new languageFeatures.FormatAdapter(workerAccessor) ); monacoInstance.languages.registerFoldingRangeProvider( LANGUAGE_ID, new languageFeatures.FoldingAdapter(workerAccessor) ); monacoInstance.languages.registerDefinitionProvider( LANGUAGE_ID, new languageFeatures.DefinitionAdapter(workerAccessor) ); monacoInstance.languages.registerRenameProvider(LANGUAGE_ID, new languageFeatures.RenameAdapter(workerAccessor)); monacoInstance.languages.registerReferenceProvider( LANGUAGE_ID, new languageFeatures.ReferenceAdapter(workerAccessor) ); if (defaults.languageSettings.enableHover) { monacoInstance.languages.registerHoverProvider(LANGUAGE_ID, new languageFeatures.HoverAdapter(workerAccessor)); } monacoInstance.languages.registerDocumentFormattingEditProvider( LANGUAGE_ID, new languageFeatures.DocumentFormatAdapter(workerAccessor) ); kustoWorker = workerAccessor; resolveWorker(workerAccessor); monacoInstance.languages.setLanguageConfiguration(LANGUAGE_ID, languageConfiguration); } export function getKustoWorker(): Promise<AugmentedWorkerAccessor> { return workerPromise.then(() => kustoWorker); } const languageConfiguration: LanguageConfiguration = { folding: { offSide: false, markers: { start: /^\s*[\r\n]/gm, end: /^\s*[\r\n]/gm }, }, comments: { lineComment: '//', blockComment: null, }, autoClosingPairs: [ { open: '{', close: '}' }, { open: '[', close: ']' }, { open: '(', close: ')' }, { open: "'", close: "'", notIn: ['string', 'comment'] }, { open: '"', close: '"', notIn: ['string', 'comment'] }, ], brackets: [ ['[', ']'], ['{', '}'], ['(', ')'], ], colorizedBracketPairs: [], wordPattern: /[a-zA-Z0-9\-_]+/g, };