@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
JavaScript
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
};