UNPKG

@arcgis/coding-components

Version:

Contains components for editing code in different languages. The currently supported languages are html, css, json, TypeScript, JavaScript, and Arcade.

365 lines (364 loc) • 9.82 kB
import { languages as u, Emitter as T } from "monaco-editor"; import "monaco-editor/esm/vs/editor/standalone/browser/standaloneServices.js"; import "monaco-editor/esm/vs/editor/standalone/common/standaloneTheme.js"; import "monaco-editor/esm/vs/editor/common/languages/supports/tokenization.js"; import { i as p } from "./monaco-importer.js"; import { Deferred as _, debounce as N } from "@arcgis/components-utils"; import { a as d } from "./sql-expr-defaults.js"; /*! All material copyright Esri, All Rights Reserved, unless otherwise specified. See https://js.arcgis.com/4.32/esri/copyright.txt for details. v4.32.13 */ let h = new _(); class k { constructor(e) { this._defaults = e, this._worker = null, this._client = null, this._configChangeListener = this._defaults.onDidChange(() => this.stopWorker()); } dispose() { this._configChangeListener.dispose(), this.stopWorker(); } stopWorker() { this._worker && (this._worker.dispose(), this._worker = null, h = new _()), this._client = null; } /** * Wait for the worker to be ready. * @returns A promise that resolves when the worker is ready. */ static async waitForWorker() { return await h.promise; } async _getClientProxy() { const e = await p(); if (!this._client) { const { languageId: t } = this._defaults; this._worker = e.createWebWorker({ moduleId: "SqlExprWorker", label: t, createData: { languageId: t }, host: this._defaults.workerHost }), h.resolve(this._worker), this._client = this._worker.getProxy(); } return await this._client; } async getLanguageServiceWorker(...e) { const t = await this._getClientProxy(); return await this._worker?.withSyncedResources(e), t; } } const f = [ "AND", "AS", "BOTH", "CASE", "CAST", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATE", "DAY", "ELSE", "END", "ESCAPE", "FALSE", "FLOAT", "FOR", "FROM", "HOUR", "IN", "INT", "INTEGER", "INTERVAL", "LEADING", "LIKE", "MINUTE", "MONTH", "POSITION", "REAL", "SECOND", "SMALLINT", "THEN", "TIME", "TIMESTAMP", "TIMEZONE_HOUR", "TIMEZONE_MINUTE", "TO", "TRAILING", "TRIM", "TRUE", "VARCHAR", "WHEN", "WITH", "YEAR", "ZONE" ], S = [ // Logical "AND", "BETWEEN", "LIKE", "NOT", "OR", // Predicates "IS", "NULL" ], A = [ // Conversion "CAST", // Datetime "EXTRACT", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_USER", // Mathematical "ABS", "ACOS", "ASIN", "ATAN", "CEILING", "COS", "FLOOR", "LOG", "LOG10", "MOD", "NULLIF", "POWER", "ROUND", "SIGN", "SIN", "TAN", "TRUNCATE", // String "CHAR_LENGTH", "COALESCE", "CONCAT", "LOWER", "POSITION", "SUBSTRING", "TRIM", "UPPER" ], L = { comments: { lineComment: "--", blockComment: ["/*", "*/"] }, brackets: [ ["{", "}"], ["[", "]"], ["(", ")"] ], autoClosingPairs: [ { open: "{", close: "}" }, { open: "[", close: "]" }, { open: "(", close: ")" }, { open: '"', close: '"' }, { open: "'", close: "'" } ], surroundingPairs: [ { open: "{", close: "}" }, { open: "[", close: "]" }, { open: "(", close: ")" }, { open: '"', close: '"' }, { open: "'", close: "'" } ] }, R = { defaultToken: "", tokenPostfix: ".arcgis", ignoreCase: !0, brackets: [ { open: "[", close: "]", token: "delimiter.square" }, { open: "(", close: ")", token: "delimiter.parenthesis" } ], keywords: f, operators: S, builtinFunctions: A, builtinVariables: [], tokenizer: { root: [ { include: "@comments" }, { include: "@whitespace" }, { include: "@numbers" }, { include: "@strings" }, { include: "@complexIdentifiers" }, { include: "@scopes" }, [/[;,.]/, "delimiter"], [/[()]/, "@brackets"], [ /[\w@#$]+/, { cases: { "@operators": "operator", "@builtinVariables": "predefined", "@builtinFunctions": "predefined", "@keywords": "keyword", "@default": "identifier" } } ], [/[<>=!%&+\-*/|~^]/, "operator"] ], whitespace: [[/\s+/, "white"]], comments: [ [/--+.*/, "comment"], [/\/\*/, { token: "comment.quote", next: "@comment" }] ], comment: [ [/[^*/]+/, "comment"], // Not supporting nested comments, as nested comments seem to not be standard? // i.e. http://stackoverflow.com/questions/728172/are-there-multiline-comment-delimiters-in-sql-that-are-vendor-agnostic // [/\/\*/, { token: 'comment.quote', next: '@push' }], // nested comment not allowed :-( [/\*\//, { token: "comment.quote", next: "@pop" }], [/./, "comment"] ], numbers: [ [/0[xX][0-9a-fA-F]*/, "number"], [/[$][+-]*\d*(\.\d*)?/, "number"], [/((\d+(\.\d*)?)|(\.\d+))([eE][\-+]?\d+)?/, "number"] ], strings: [ [/N'/, { token: "string", next: "@string" }], [/'/, { token: "string", next: "@string" }] ], string: [ [/[^']+/, "string"], [/''/, "string"], [/'/, { token: "string", next: "@pop" }] ], complexIdentifiers: [[/"/, { token: "identifier.quote", next: "@quotedIdentifier" }]], quotedIdentifier: [ [/[^"]+/, "identifier"], [/""/, "identifier"], [/"/, { token: "identifier.quote", next: "@pop" }] ], scopes: [ [/(BEGIN|CASE)\b/i, { token: "keyword.block" }], [/END\b/i, { token: "keyword.block" }], [/WHEN\b/i, { token: "keyword.choice" }], [/THEN\b/i, { token: "keyword.choice" }] ] } }; class M { constructor(e, t) { this._worker = e, this._defaults = t; } async provideCompletionItems(e, t) { try { const i = await this._worker(e.uri), r = e.getWordUntilPosition(t), n = { startLineNumber: t.lineNumber, endLineNumber: t.lineNumber, startColumn: r.startColumn, endColumn: r.endColumn }, c = this._defaults.getApiContextForModel(e.uri); return await i.doComplete(e.uri.toString(), n, t, c); } catch (i) { return console.error(i), { suggestions: [] }; } } } class x { constructor(e, t, { defaults: i, diagnosticService: r }) { this._languageId = e, this._worker = t, this._disposables = [], this._modelListeners = /* @__PURE__ */ new Map(), this._diagnosticsService = r, this._defaults = i, p().then((n) => { const c = (o) => { const s = o.getLanguageId(); if (s !== this._languageId) return; const l = N(() => { this._doValidate(o, s).catch((m) => { throw m; }); }), w = o.onDidChangeContent(l), I = o.onDidChangeAttached(l); this._modelListeners.set(o.uri.toString(), [w, I]), this._doValidate(o, s).catch(console.error); }, g = (o) => { const s = o.uri.toString(); n.setModelMarkers(o, this._languageId, []); const l = this._modelListeners.get(s); if (l) { for (; l.length; ) l.pop()?.dispose(); this._modelListeners.delete(s); } }; this._disposables.push(n.onDidCreateModel(c)), this._disposables.push(n.onWillDisposeModel((o) => g(o))), this._disposables.push( n.onDidChangeModelLanguage((o) => { g(o.model), c(o.model); }) ), this._disposables.push( i.onDidChange(() => { n.getModels().forEach((o) => { o.getLanguageId() === this._languageId && (g(o), c(o)); }); }) ), this._disposables.push( i.onModelContextDidChange((o) => { n.getModels().forEach((s) => { s.getLanguageId() === this._languageId && s.uri.toString() === o && this._doValidate(s, this._languageId).catch(console.error); }); }) ), this._disposables.push({ dispose: () => { this._modelListeners.forEach((o) => o.forEach((s) => s.dispose())), this._modelListeners.clear(); } }), n.getModels().forEach(c); }); } async _doValidate(e, t) { const i = await p(); if (e.isAttachedToEditor()) try { const r = await this._worker(e.uri), n = this._defaults.getApiContextForModel(e.uri), c = await r.doValidation(e.uri.toString(), n); this._diagnosticsService.fireDiagnosticsChange(e.uri, c), i.setModelMarkers(e, t, c); } catch (r) { console.error(r); } } } let E; async function v(...a) { return await k.waitForWorker(), await new Promise((e, t) => { if (!E) { t(new Error("sql expression worker not registered!")); return; } e(E(...a)); }); } class b { constructor() { this._onDiagnosticsChange = new T(); } /** * An event to signal changes to the diagnostics. * The event value is the uri string and the diagnostics. */ get onDiagnosticsChange() { return this._onDiagnosticsChange.event; } /** * Fires the diagnostics change event. * @param uri The uri of the model for which the diagnostics changed. * @param diagnostics The diagnostics for the model. */ fireDiagnosticsChange(e, t) { this._onDiagnosticsChange.fire({ uri: e, diagnostics: t }); } } const C = new b(); function F() { return C; } function H(a) { const e = new k(a), t = async (...r) => await e.getLanguageServiceWorker(...r); E = t, u.setMonarchTokensProvider(d.languageId, R), u.setLanguageConfiguration(d.languageId, L); const i = new M(t, d); u.registerCompletionItemProvider(d.languageId, i), new x(a.languageId, t, { defaults: a, diagnosticService: C }); } export { F as getSqlExprDiagnosticService, v as getSqlExprWorker, H as setupMode };