@valtzu/codemirror-lang-el 0.6.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { LRParser } from '@lezer/lr';
1
+ import { LRParser, LocalTokenGroup } from '@lezer/lr';
2
2
  import { syntaxTree, LRLanguage, indentNodeProp, delimitedIndent, foldNodeProp, LanguageSupport } from '@codemirror/language';
3
3
  import { styleTags, tags } from '@lezer/highlight';
4
4
  import { linter } from '@codemirror/lint';
@@ -6,25 +6,42 @@ import { insertCompletionText } from '@codemirror/autocomplete';
6
6
  import { StateField } from '@codemirror/state';
7
7
  import { showTooltip, hoverTooltip, EditorView } from '@codemirror/view';
8
8
 
9
+ // @ts-ignore
10
+ const t = {
11
+ deserialize: (str) => str,
12
+ };
13
+
9
14
  // This file was generated by lezer-generator. You probably shouldn't edit it.
10
- const spec_word = {__proto__:null,true:80, false:82, null:84, starts:94, with:96, ends:98, contains:100, matches:102, not:104, in:106, and:108, or:110};
11
- const spec_Operator = {__proto__:null,"?":93, "!":113, "+":115, "-":117};
15
+ const spec_word = {__proto__:null,true:92, TRUE:94, false:96, FALSE:98, null:100, NULL:102, starts:112, with:114, ends:116, contains:118, matches:120, not:122, in:124, and:126, or:128, xor:130};
16
+ const spec_Operator = {__proto__:null,"?":111, "!":133, "+":135, "-":137};
12
17
  const parser = LRParser.deserialize({
13
18
  version: 14,
14
- states: "(pOVQPOOQ!QQPOOO!{QPO'#CdO$]QPO'#CmO$dQPO'#CnOVQPO'#CtOVQPO'#CvOOQO'#C|'#C|O$kQPO'#CcO$pQPO'#CcOOQO'#Ck'#CkOOQO'#Cl'#ClOOQO'#Cu'#CuO$uQPO,58xOVQPO,58|OVQPO,59^OVQPO,59[O$zQPO'#CsOOQO'#Cs'#CsO%PQPO'#CsO%}QPO,59XOOQO,59X,59XO&UQPO'#DSO&cQPO,59YO&hQPO,59`O'OQPO,59bO'VQPO'#CeOOQO,58},58}O'VQPO'#ChO'^QPO'#CaOOQO1G.d1G.dOOQO1G.l1G.lO(nQPO1G.hO(uQPO1G.xO)]QPO1G.vOOQO,59_,59_OVQPO1G.sOVQPO'#CwO)dQPO,59nOOQO1G.t1G.tOOQO1G.|1G.|O)oQPO,59PO)tQPO,59SOOQO7+$S7+$SOVQPO7+$bO)yQPO7+$_O*TQPO,59cOOQO-E6u-E6uOOQO1G.k1G.kOOQO1G.n1G.nO*bQPO<<G|OVQPO'#CxO*xQPO<<GyOOQO<<Gy<<GyO+QQPO,59dOOQO-E6v-E6vOOQOAN=eAN=eOVQPO1G/OO+XQPO7+$j",
15
- stateData: "+k~OoOS~O]VO^VOqQOsSOuUOxYOyYOzZO|RO!U[O!Y[O!Z[O![[O~OR]OS]Oe_Os^O!O`O!PaO!RaO!SbO!TbO!UcO!VbO!WbO!XbO~ORcXScXecXmcXscXuWX!OcX!PcX!RcX!ScX!TcX!UcX!VcX!WcX!XcX}cXrcXwcXtcX{cX~O{eO~PVOrvP~PVOujO~OulO~OqmO~O!QsO~O!VsO]gX^gXqgXsgXugXxgXygXzgX|gX!UgX!YgX!ZgX![gX~O}tO~P!QOwuOrvXtvX~P!QOrwO~Omha}harhawhatha{ha~P!QOtxO~P!QOtvP~PVORTXSTXeTXmTXsTXuZX!OTX!PTX!RTX!STX!TTX!UTX!VTX!WTX!XTX}TXrTXwTXtTX{TX~Or{O~P!QOmfi}firfiwfitfi{fi~P!QO}|O~P!QOwuOrvatva~Ot!QO~Ot!RO~Ow!TO{!VO~P!QOrkawkatka~P!QOmdy}dyrdywdytdy{dy~P!QOw!TO{!YO~O}!ZO~P!QOwlq{lq~P!QO^SeR]qR~",
16
- goto: "%]wPPxPP!Zxx!^!o!r#T#WPPxxxxxxPx#Zx#jx#{$RPPP$XPPPPP%SoVORSTU^_`jltu|!T!ZRn]oWORSTU^_`jltu|!T!ZRkWoXORSTU^_`jltu|!T!ZRo]RkXk_Pdfhipqr}!O!S!W![oTORSTU^_`jltu|!T!ZQvfR!PvQ!U}R!X!UQPOQdRUfSjlQhTQiUQp^Qq_Qr`Q}tQ!OuQ!S|Q!W!TR![!ZQgSQyjRzl",
17
- nodeNames: "⚠ Expression ObjectAccess MemberOf NullSafeMemberOf Property ArrayAccess Call Function Arguments ObjectAccess Method Arguments Number String Boolean Null Object Array Variable TernaryExpression Operator BinaryExpression OperatorKeyword UnaryExpression UnaryOperator Application",
18
- maxTerm: 58,
19
- skippedNodes: [0],
20
- repeatNodeCount: 2,
21
- tokenData: ",l~RqXY#YYZ#Y]^#Ypq#Yqr#krs$Quv#{vw%zwx&Sxy'wyz'|z{(R{|#{|}(Z}!O#{!O!P(`!P!Q#{!Q![(h![!]*}!^!_#s!_!`+S!`!a#s!a!b+Y!c!}+m!}#O,O#P#Q,T#Q#R#{#R#S+m#T#o+m#o#p,Y#p#q,_#q#r,g#r#s#{~#_So~XY#YYZ#Y]^#Ypq#Y~#pPe~!_!`#s~#xPe~!_!`#{~$QOe~~$TXOr$Qrs$ps#O$Q#O#P$u#P;'S$Q;'S;=`%t<%l~$Q~O$Q~~$p~$uO^~~$xRO;'S$Q;'S;=`%R;=`O$Q~%UYOr$Qrs$ps#O$Q#O#P$u#P;'S$Q;'S;=`%t;=`<%l$Q<%l~$Q~O$Q~~$p~%wP;=`<%l$Q~&PPe~vw#{~&VXOw&Swx$px#O&S#O#P&r#P;'S&S;'S;=`'q<%l~&S~O&S~~$p~&uRO;'S&S;'S;=`'O;=`O&S~'RYOw&Swx$px#O&S#O#P&r#P;'S&S;'S;=`'q;=`<%l&S<%l~&S~O&S~~$p~'tP;=`<%l&S~'|Ou~~(ROt~~(WPe~z{#{~(`Ow~~(ePR~!O!P#{~(mT]~!O!P(|!Q![(h!g!h)|#R#S*w#X#Y)|~)PSO!O)]!P;'S)];'S;=`*q<%lO)]~)bR]~!Q![)k!g!h)|#X#Y)|~)pS]~!Q![)k!g!h)|#R#S*k#X#Y)|~*PR{|*Y}!O*Y!Q![*`~*]P!Q![*`~*eQ]~!Q![*`#R#S*Y~*nP!Q![)k~*tP;=`<%l)]~*zP!Q![(h~+SO}~~+VP!_!`#s~+_Re~!O!P+h![!]#{!a!b#{~+mOS~~+rSq~!Q![+m!c!}+m#R#S+m#T#o+m~,TOs~~,YOr~~,_O|~~,dPe~#p#q#{~,lO{~",
22
- tokenizers: [0],
23
- topRules: {"Expression":[0,1]},
24
- specialized: [{term: 33, get: (value) => spec_word[value] || -1},{term: 21, get: (value) => spec_Operator[value] || -1}],
25
- tokenPrec: 479
19
+ states: ")rOYQPOOP!^OPOOQ!cQPOOO#aQPO'#CeO$tQPO'#CnO${QPO'#CoOYQPO'#CuOYQPO'#CwOOQO'#DS'#DSO%SQPO'#CdO%XQPO'#CdOOQO'#Cl'#ClOOQO'#Cm'#CmOOQO'#Cv'#CvP%^OQO'#C]POOO)C>r)C>rO%iQPO,58yOYQPO,58}OYQPO,59_OYQPO,59]O%nQPO'#CtOOQO'#Ct'#CtO%sQPO'#CtO&zQPO,59YOOQO,59Y,59YO'RQPO'#DYO'`QPO,59ZO'eQPO,59aO'{QPO,59cO(SQPO'#CfOOQO,59O,59OO(SQPO'#CiPOOO'#Cx'#CxP(ZOQO,58wPOOO,58w,58wO(fQPO'#CbOOQO1G.e1G.eOOQO1G.m1G.mO)yQPO1G.iO*QQPO1G.yO*hQPO1G.wOOQO,59`,59`OYQPO1G.tOYQPO'#CyO*oQPO,59tOOQO1G.u1G.uOOQO1G.}1G.}O*zQPO,59QO+PQPO,59TPOOO-E6v-E6vPOOO1G.c1G.cOOQO7+$T7+$TOYQPO7+$cO+UQPO7+$`O+`QPO,59eOOQO-E6w-E6wOOQO1G.l1G.lOOQO1G.o1G.oO+mQPO<<G}OYQPO'#CzO,TQPO<<GzOOQO<<Gz<<GzO,]QPO,59fOOQO-E6x-E6xOOQOAN=fAN=fOYQPO1G/QO,dQPO7+$l",
20
+ stateData: ",v~OqOSrPQ~O^WO_WOwROyTO{VO!OZO!PZO!QZO!RZO!S[O!T[O!VSO!_]O!d]O!e]O!f]O~Or^O~OS`OT`OfbOyaO!XcO!YdO![dO!]eO!^eO!_fO!`eO!aeO!beO!ceO~OSdXTdXfdXodXydX{XX!XdX!YdX![dX!]dX!^dX!_dX!`dX!adX!bdX!cdX!WdXxdX}dXzdX!UdX~O!UhO~PYOx|P~PYO{mO~O{oO~OspOtpOurO~OwsO~O!ZyO~O!`yO^hX_hXwhXyhX{hX!OhX!PhX!QhX!RhX!ShX!ThX!VhX!_hX!dhX!ehX!fhX~O!WzO~P!cO}{Ox|Xz|X~P!cOx}O~Ooia!Wiaxia}iazia!Uia~P!cOz!OO~P!cOz|P~PYOspOtpOu!SO~OSUXTUXfUXoUXyUX{[X!XUX!YUX![UX!]UX!^UX!_UX!`UX!aUX!bUX!cUX!WUXxUX}UXzUX!UUX~Ox!TO~P!cOogi!Wgixgi}gizgi!Ugi~P!cO!W!UO~P!cO}{Ox|az|a~Oz!YO~Oz!ZO~O}!]O!U!_O~P!cOxma}mazma~P!cOoey!Weyxey}eyzey!Uey~P!cO}!]O!U!bO~O!W!cO~P!cO}nq!Unq~P!cO_TfS^wS~",
21
+ goto: "%l}P!OP!RPP!d!R!R!g!x!{#^#aPP!R!R!R!R!R!RP!R#d!R#s!R$U$[$bPPPPPPP$hPPPPP%cR_PoWOSTUVabcmoz{!U!]!cRt`oXOSTUVabcmoz{!U!]!cRnXoYOSTUVabcmoz{!U!]!cRu`RnYkbQgiklvwx!V!W![!`!doUOSTUVabcmoz{!U!]!cQq^R!RqQ|iR!X|Q!^!VR!a!^QQOQgSUiTmoQkUQlVQvaQwbQxcQ!VzQ!W{Q![!UQ!`!]R!d!cQjTQ!PmR!Qo",
22
+ nodeNames: "⚠ BlockComment Expression ObjectAccess MemberOf NullSafeMemberOf Property ArrayAccess Call Function Arguments ObjectAccess Method Arguments Number String Boolean Null Object Array Variable TernaryExpression Operator BinaryExpression OperatorKeyword UnaryExpression UnaryOperator Application",
23
+ maxTerm: 68,
24
+ nodeProps: [
25
+ [t, 14,"number",15,"string",16,"bool",17,"null"]
26
+ ],
27
+ skippedNodes: [0,1,28],
28
+ repeatNodeCount: 3,
29
+ tokenData: "-a~RqXY#YYZ#Y]^#Ypq#Yqr#krs$Quv#{vw%zwx&Sxy'wyz'|z{(R{|#{|}(Z}!O#{!O!P(`!P!Q(h!Q![(u![!]+[!^!_+a!_!`+l!`!a+r!a!b+}!c!},b!}#O,s#P#Q,x#Q#R#{#R#S,b#T#o,b#o#p,}#p#q-S#q#r-[#r#s#{~#_Sq~XY#YYZ#Y]^#Ypq#Y~#pPf~!_!`#s~#xPf~!_!`#{~$QOf~~$TXOr$Qrs$ps#O$Q#O#P$u#P;'S$Q;'S;=`%t<%l~$Q~O$Q~~$p~$uO_~~$xRO;'S$Q;'S;=`%R;=`O$Q~%UYOr$Qrs$ps#O$Q#O#P$u#P;'S$Q;'S;=`%t;=`<%l$Q<%l~$Q~O$Q~~$p~%wP;=`<%l$Q~&PPf~vw#{~&VXOw&Swx$px#O&S#O#P&r#P;'S&S;'S;=`'q<%l~&S~O&S~~$p~&uRO;'S&S;'S;=`'O;=`O&S~'RYOw&Swx$px#O&S#O#P&r#P;'S&S;'S;=`'q;=`<%l&S<%l~&S~O&S~~$p~'tP;=`<%l&S~'|O{~~(ROz~~(WPf~z{#{~(`O}~~(ePS~!O!P#{~(mPf~z{(p~(uOr~~(zT^~!O!P)Z!Q![(u!g!h*Z#R#S+U#X#Y*Z~)^SO!O)j!P;'S)j;'S;=`+O<%lO)j~)oR^~!Q![)x!g!h*Z#X#Y*Z~)}S^~!Q![)x!g!h*Z#R#S*x#X#Y*Z~*^R{|*g}!O*g!Q![*m~*jP!Q![*m~*rQ^~!Q![*m#R#S*g~*{P!Q![)x~+RP;=`<%l)j~+XP!Q![(u~+aO!W~~+fQf~!^!_#{!_!`#{~+oP!_!`#s~+wQf~!_!`#{!`!a#{~,SRf~!O!P,]![!]#{!a!b#{~,bOT~~,gSw~!Q![,b!c!},b#R#S,b#T#o,b~,xOy~~,}Ox~~-SO!V~~-XPf~#p#q#{~-aO!U~",
30
+ tokenizers: [1, new LocalTokenGroup("j~RQYZXz{^~^Ot~~aP!P!Qd~iOu~~", 25, 35)],
31
+ topRules: {"Expression":[0,2]},
32
+ specialized: [{term: 39, get: (value) => spec_word[value] || -1},{term: 22, get: (value) => spec_Operator[value] || -1}],
33
+ tokenPrec: 536
26
34
  });
27
35
 
36
+ var ELScalar;
37
+ (function (ELScalar) {
38
+ ELScalar["Bool"] = "bool";
39
+ ELScalar["Number"] = "number";
40
+ ELScalar["String"] = "string";
41
+ ELScalar["Null"] = "null";
42
+ ELScalar["Any"] = "any";
43
+ })(ELScalar || (ELScalar = {}));
44
+
28
45
  const createInfoElement = (html) => {
29
46
  const dom = document.createElement("div");
30
47
  dom.innerHTML = html;
@@ -61,12 +78,16 @@ const resolveIdentifier = (nodeName, identifier, config) => {
61
78
  }
62
79
  };
63
80
  function resolveTypes(state, node, config, matchExact) {
64
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
81
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
65
82
  let types = new Set();
66
83
  if (!node) {
67
84
  return types;
68
85
  }
69
- if (node.name === 'Call' && node.firstChild && node.lastChild) {
86
+ let type;
87
+ if (typeof (type = node.type.prop(t)) !== "undefined") {
88
+ types.add(type);
89
+ }
90
+ else if (node.name === 'Call' && node.firstChild && node.lastChild) {
70
91
  resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
71
92
  }
72
93
  else if (node.name === 'Variable') {
@@ -102,17 +123,32 @@ function resolveTypes(state, node, config, matchExact) {
102
123
  resolveTypes(state, node.firstChild.nextSibling, config).forEach(x => types.add(x));
103
124
  resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
104
125
  }
105
- else if (node.name === 'BinaryExpression' && ((_k = (_j = node.firstChild) === null || _j === void 0 ? void 0 : _j.nextSibling) === null || _k === void 0 ? void 0 : _k.name) == 'Operator' && node.lastChild) {
126
+ else if (node.name === 'BinaryExpression' && ((_j = node.firstChild) === null || _j === void 0 ? void 0 : _j.nextSibling) && ((_l = (_k = node.firstChild) === null || _k === void 0 ? void 0 : _k.nextSibling) === null || _l === void 0 ? void 0 : _l.nextSibling)) {
106
127
  const operator = state.sliceDoc(node.firstChild.nextSibling.from, node.firstChild.nextSibling.to);
107
- if (operator == '?:' || operator == '??') {
108
- resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
109
- }
110
128
  if (operator == '?:' || operator == '??' || operator == '?') {
111
- resolveTypes(state, node.lastChild, config).forEach(x => types.add(x));
129
+ if (operator == '?:' || operator == '??') {
130
+ resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
131
+ }
132
+ resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
133
+ }
134
+ else if (['||', '&&', '==', '!=', '===', '!==', '>=', '<=', '>', '<'].includes(operator) || keywords.find(x => x.name == operator)) {
135
+ types.add(ELScalar.Bool);
136
+ }
137
+ else if (['**', '|', '^', '&', '<<', '>>', '+', '-', '*', '/', '%'].includes(operator)) {
138
+ types.add(ELScalar.Number);
139
+ }
140
+ }
141
+ else if (node.name === 'UnaryExpression' && node.firstChild) {
142
+ const operator = state.sliceDoc(node.firstChild.from, node.firstChild.to);
143
+ if (['not', '!'].includes(operator)) {
144
+ types.add(ELScalar.Bool);
145
+ }
146
+ else if (['+', '-'].includes(operator)) {
147
+ types.add(ELScalar.Number);
112
148
  }
113
149
  }
114
150
  if (types.size === 0) {
115
- types.add('any');
151
+ types.add(ELScalar.Any);
116
152
  }
117
153
  return types;
118
154
  }
@@ -129,6 +165,7 @@ const keywords = [
129
165
  { name: 'not' },
130
166
  { name: 'or' },
131
167
  { name: 'and' },
168
+ { name: 'xor' },
132
169
  ];
133
170
 
134
171
  /**
@@ -164,7 +201,7 @@ const expressionLanguageLinterSource = (state) => {
164
201
  let i = 0;
165
202
  let n = node.node.firstChild;
166
203
  while (n) {
167
- if (++i > args.length) {
204
+ if (n.name !== 'BlockComment' && ++i > args.length) {
168
205
  diagnostics.push({ from: n.from, to: n.to, severity: 'error', message: `Unexpected argument` });
169
206
  }
170
207
  n = n.nextSibling;
@@ -196,15 +233,15 @@ const expressionLanguageLinterSource = (state) => {
196
233
  const expressionLanguageLinter = linter(view => expressionLanguageLinterSource(view.state));
197
234
 
198
235
  const autocompleteFunction = (x) => {
199
- var _a, _b;
236
+ var _a, _b, _c;
200
237
  return ({
201
- label: `${x.name}(${((_a = x.args) === null || _a === void 0 ? void 0 : _a.join(',')) || ''})`,
238
+ label: `${x.name}(${((_b = (_a = x.args) === null || _a === void 0 ? void 0 : _a.map(x => x.name)) === null || _b === void 0 ? void 0 : _b.join(',')) || ''})`,
202
239
  apply: (view, completion, from, to) => {
203
240
  var _a;
204
241
  view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, `${x.name}()`, from, to)), { selection: { anchor: from + x.name.length + (((_a = x.args) === null || _a === void 0 ? void 0 : _a.length) > 0 ? 1 : 2) } }));
205
242
  },
206
- detail: (_b = x.returnType) === null || _b === void 0 ? void 0 : _b.join('|'),
207
- info: () => { var _a; return createInfoElement((_a = x.info) !== null && _a !== void 0 ? _a : ''); },
243
+ detail: (_c = x.returnType) === null || _c === void 0 ? void 0 : _c.join('|'),
244
+ info: x.info,
208
245
  type: "function",
209
246
  });
210
247
  };
@@ -213,7 +250,7 @@ const autocompleteIdentifier = (x) => {
213
250
  return ({
214
251
  label: x.name,
215
252
  apply: x.name,
216
- info: () => { var _a; return createInfoElement((_a = x.info) !== null && _a !== void 0 ? _a : ''); },
253
+ info: x.info,
217
254
  detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')),
218
255
  type: 'variable',
219
256
  });
@@ -223,7 +260,13 @@ function completeOperatorKeyword(state, config, tree, from, to, explicit) {
223
260
  return {
224
261
  from,
225
262
  to,
226
- options: (_a = keywords.map(({ name, info, detail }) => ({ label: name, apply: `${name} `, info, detail, type: "keyword" }))) !== null && _a !== void 0 ? _a : [],
263
+ options: (_a = keywords.map(({ name, info, detail }) => ({
264
+ label: name,
265
+ apply: `${name} `,
266
+ info: info,
267
+ detail,
268
+ type: "keyword"
269
+ }))) !== null && _a !== void 0 ? _a : [],
227
270
  validFor: (text) => { var _a; return (_a = keywords.some(({ name }) => explicit || name.includes(text))) !== null && _a !== void 0 ? _a : false; },
228
271
  };
229
272
  }
@@ -268,7 +311,7 @@ function expressionLanguageCompletion(context) {
268
311
  const config = getExpressionLanguageConfig(state);
269
312
  const isIdentifier = (node) => { var _a; return ['Variable', 'Function'].includes((_a = node === null || node === void 0 ? void 0 : node.name) !== null && _a !== void 0 ? _a : ''); };
270
313
  const isMember = (node) => { var _a; return ['Property', 'Method'].includes((_a = node === null || node === void 0 ? void 0 : node.name) !== null && _a !== void 0 ? _a : ''); };
271
- if (prevNode.name == 'String') {
314
+ if (prevNode.name == 'String' || prevNode.name == 'BlockComment') {
272
315
  return null;
273
316
  }
274
317
  if (((_a = prevNode.parent) === null || _a === void 0 ? void 0 : _a.name) == 'ObjectAccess' && ['ObjectAccess', 'ArrayAccess', 'Variable', 'Call', 'Application'].includes(((_b = prevNode.parent.firstChild) === null || _b === void 0 ? void 0 : _b.name) || '')) {
@@ -308,7 +351,7 @@ function getCursorTooltips(state) {
308
351
  return state.selection.ranges
309
352
  .filter(range => range.empty)
310
353
  .map(range => {
311
- var _a;
354
+ var _a, _b;
312
355
  const tree = syntaxTree(state);
313
356
  const node = tree.resolveInner(range.from, 0);
314
357
  const args = resolveArguments(node);
@@ -320,7 +363,7 @@ function getCursorTooltips(state) {
320
363
  return null;
321
364
  }
322
365
  const n = args.childAfter(range.from - 1);
323
- const argName = (_a = fn.args) === null || _a === void 0 ? void 0 : _a[n ? getNodeOrdinal(n) : 0];
366
+ const argName = (_b = (_a = fn.args) === null || _a === void 0 ? void 0 : _a[n ? getNodeOrdinal(n) : 0]) === null || _b === void 0 ? void 0 : _b.name;
324
367
  if (n && n.from !== range.from || !argName) {
325
368
  return null;
326
369
  }
@@ -395,17 +438,29 @@ const keywordTooltip = hoverTooltip((view, pos, side) => {
395
438
  create: () => ({ dom: createInfoElement(info) }),
396
439
  };
397
440
  });
398
- const cursorTooltipBaseTheme = EditorView.baseTheme({
441
+
442
+ const baseTheme = EditorView.baseTheme({
399
443
  ".cm-tooltip.cm-tooltip-cursor": {
400
444
  boxShadow: 'rgba(0, 0, 0, .15) 0 1px 2px',
401
445
  border: "1px solid rgba(127, 127, 127, .2)",
402
- padding: "2px 7px",
446
+ fontSize: ".85rem",
447
+ padding: ".4rem .5rem",
403
448
  borderRadius: "4px",
404
449
  "& .cm-tooltip-arrow:before": {},
405
450
  "& .cm-tooltip-arrow:after": {
406
451
  borderTopColor: "transparent"
407
- }
408
- }
452
+ },
453
+ },
454
+ ".cm-tooltip.cm-completionInfo, .cm-diagnostic": {
455
+ boxShadow: "rgba(0, 0, 0, .15) 0 2px 5px",
456
+ fontSize: ".85rem",
457
+ padding: ".8rem !important", // Couldn't figure out other means to override https://github.com/codemirror/autocomplete/blob/6.18.1/src/theme.ts#L65
458
+ },
459
+ ".cm-completionDetail": {
460
+ float: "right",
461
+ opacity: 0.5,
462
+ fontStyle: "inherit !important",
463
+ },
409
464
  });
410
465
 
411
466
  const ELLanguage = LRLanguage.define({
@@ -439,6 +494,7 @@ const ELLanguage = LRLanguage.define({
439
494
  OperatorKeyword: tags.operatorKeyword,
440
495
  UnaryOperator: tags.operator,
441
496
  Operator: tags.operator,
497
+ BlockComment: tags.comment,
442
498
  })
443
499
  ]
444
500
  }),
@@ -453,7 +509,7 @@ function expressionlanguage(config = {}, extensions = []) {
453
509
  expressionLanguageLinter,
454
510
  keywordTooltip,
455
511
  cursorTooltipField,
456
- cursorTooltipBaseTheme,
512
+ baseTheme,
457
513
  ...extensions,
458
514
  ]);
459
515
  }
package/dist/linter.cjs CHANGED
@@ -5,6 +5,20 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var lint = require('@codemirror/lint');
6
6
  var language = require('@codemirror/language');
7
7
 
8
+ var ELScalar;
9
+ (function (ELScalar) {
10
+ ELScalar["Bool"] = "bool";
11
+ ELScalar["Number"] = "number";
12
+ ELScalar["String"] = "string";
13
+ ELScalar["Null"] = "null";
14
+ ELScalar["Any"] = "any";
15
+ })(ELScalar || (ELScalar = {}));
16
+
17
+ // @ts-ignore
18
+ const t = {
19
+ deserialize: (str) => str,
20
+ };
21
+
8
22
  function resolveFunctionDefinition(node, state, config) {
9
23
  var _a;
10
24
  if (!node) {
@@ -35,12 +49,16 @@ const resolveIdentifier = (nodeName, identifier, config) => {
35
49
  }
36
50
  };
37
51
  function resolveTypes(state, node, config, matchExact) {
38
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
52
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
39
53
  let types = new Set();
40
54
  if (!node) {
41
55
  return types;
42
56
  }
43
- if (node.name === 'Call' && node.firstChild && node.lastChild) {
57
+ let type;
58
+ if (typeof (type = node.type.prop(t)) !== "undefined") {
59
+ types.add(type);
60
+ }
61
+ else if (node.name === 'Call' && node.firstChild && node.lastChild) {
44
62
  resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
45
63
  }
46
64
  else if (node.name === 'Variable') {
@@ -76,23 +94,50 @@ function resolveTypes(state, node, config, matchExact) {
76
94
  resolveTypes(state, node.firstChild.nextSibling, config).forEach(x => types.add(x));
77
95
  resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
78
96
  }
79
- else if (node.name === 'BinaryExpression' && ((_k = (_j = node.firstChild) === null || _j === void 0 ? void 0 : _j.nextSibling) === null || _k === void 0 ? void 0 : _k.name) == 'Operator' && node.lastChild) {
97
+ else if (node.name === 'BinaryExpression' && ((_j = node.firstChild) === null || _j === void 0 ? void 0 : _j.nextSibling) && ((_l = (_k = node.firstChild) === null || _k === void 0 ? void 0 : _k.nextSibling) === null || _l === void 0 ? void 0 : _l.nextSibling)) {
80
98
  const operator = state.sliceDoc(node.firstChild.nextSibling.from, node.firstChild.nextSibling.to);
81
- if (operator == '?:' || operator == '??') {
82
- resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
83
- }
84
99
  if (operator == '?:' || operator == '??' || operator == '?') {
85
- resolveTypes(state, node.lastChild, config).forEach(x => types.add(x));
100
+ if (operator == '?:' || operator == '??') {
101
+ resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
102
+ }
103
+ resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
104
+ }
105
+ else if (['||', '&&', '==', '!=', '===', '!==', '>=', '<=', '>', '<'].includes(operator) || keywords.find(x => x.name == operator)) {
106
+ types.add(ELScalar.Bool);
107
+ }
108
+ else if (['**', '|', '^', '&', '<<', '>>', '+', '-', '*', '/', '%'].includes(operator)) {
109
+ types.add(ELScalar.Number);
110
+ }
111
+ }
112
+ else if (node.name === 'UnaryExpression' && node.firstChild) {
113
+ const operator = state.sliceDoc(node.firstChild.from, node.firstChild.to);
114
+ if (['not', '!'].includes(operator)) {
115
+ types.add(ELScalar.Bool);
116
+ }
117
+ else if (['+', '-'].includes(operator)) {
118
+ types.add(ELScalar.Number);
86
119
  }
87
120
  }
88
121
  if (types.size === 0) {
89
- types.add('any');
122
+ types.add(ELScalar.Any);
90
123
  }
91
124
  return types;
92
125
  }
93
126
  function getExpressionLanguageConfig(state) {
94
127
  return state.languageDataAt('expressionLanguageConfig', 0)[0];
95
128
  }
129
+ const keywords = [
130
+ { name: 'starts with', info: 'Check if a string starts with a specific string' },
131
+ { name: 'ends with', info: 'Check if a string ends with a specific string' },
132
+ { name: 'contains', info: 'Check if a string is not included in another string' },
133
+ { name: 'matches', info: 'Check if a string matches a regex pattern' },
134
+ { name: 'not in', info: 'Check if a value is not included in an array' },
135
+ { name: 'in', info: 'Check if a value is included in an array' },
136
+ { name: 'not' },
137
+ { name: 'or' },
138
+ { name: 'and' },
139
+ { name: 'xor' },
140
+ ];
96
141
 
97
142
  /**
98
143
  * @internal
@@ -127,7 +172,7 @@ const expressionLanguageLinterSource = (state) => {
127
172
  let i = 0;
128
173
  let n = node.node.firstChild;
129
174
  while (n) {
130
- if (++i > args.length) {
175
+ if (n.name !== 'BlockComment' && ++i > args.length) {
131
176
  diagnostics.push({ from: n.from, to: n.to, severity: 'error', message: `Unexpected argument` });
132
177
  }
133
178
  n = n.nextSibling;
package/dist/linter.js CHANGED
@@ -1,6 +1,20 @@
1
1
  import { linter } from '@codemirror/lint';
2
2
  import { syntaxTree } from '@codemirror/language';
3
3
 
4
+ var ELScalar;
5
+ (function (ELScalar) {
6
+ ELScalar["Bool"] = "bool";
7
+ ELScalar["Number"] = "number";
8
+ ELScalar["String"] = "string";
9
+ ELScalar["Null"] = "null";
10
+ ELScalar["Any"] = "any";
11
+ })(ELScalar || (ELScalar = {}));
12
+
13
+ // @ts-ignore
14
+ const t = {
15
+ deserialize: (str) => str,
16
+ };
17
+
4
18
  function resolveFunctionDefinition(node, state, config) {
5
19
  var _a;
6
20
  if (!node) {
@@ -31,12 +45,16 @@ const resolveIdentifier = (nodeName, identifier, config) => {
31
45
  }
32
46
  };
33
47
  function resolveTypes(state, node, config, matchExact) {
34
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
48
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
35
49
  let types = new Set();
36
50
  if (!node) {
37
51
  return types;
38
52
  }
39
- if (node.name === 'Call' && node.firstChild && node.lastChild) {
53
+ let type;
54
+ if (typeof (type = node.type.prop(t)) !== "undefined") {
55
+ types.add(type);
56
+ }
57
+ else if (node.name === 'Call' && node.firstChild && node.lastChild) {
40
58
  resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
41
59
  }
42
60
  else if (node.name === 'Variable') {
@@ -72,23 +90,50 @@ function resolveTypes(state, node, config, matchExact) {
72
90
  resolveTypes(state, node.firstChild.nextSibling, config).forEach(x => types.add(x));
73
91
  resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
74
92
  }
75
- else if (node.name === 'BinaryExpression' && ((_k = (_j = node.firstChild) === null || _j === void 0 ? void 0 : _j.nextSibling) === null || _k === void 0 ? void 0 : _k.name) == 'Operator' && node.lastChild) {
93
+ else if (node.name === 'BinaryExpression' && ((_j = node.firstChild) === null || _j === void 0 ? void 0 : _j.nextSibling) && ((_l = (_k = node.firstChild) === null || _k === void 0 ? void 0 : _k.nextSibling) === null || _l === void 0 ? void 0 : _l.nextSibling)) {
76
94
  const operator = state.sliceDoc(node.firstChild.nextSibling.from, node.firstChild.nextSibling.to);
77
- if (operator == '?:' || operator == '??') {
78
- resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
79
- }
80
95
  if (operator == '?:' || operator == '??' || operator == '?') {
81
- resolveTypes(state, node.lastChild, config).forEach(x => types.add(x));
96
+ if (operator == '?:' || operator == '??') {
97
+ resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
98
+ }
99
+ resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
100
+ }
101
+ else if (['||', '&&', '==', '!=', '===', '!==', '>=', '<=', '>', '<'].includes(operator) || keywords.find(x => x.name == operator)) {
102
+ types.add(ELScalar.Bool);
103
+ }
104
+ else if (['**', '|', '^', '&', '<<', '>>', '+', '-', '*', '/', '%'].includes(operator)) {
105
+ types.add(ELScalar.Number);
106
+ }
107
+ }
108
+ else if (node.name === 'UnaryExpression' && node.firstChild) {
109
+ const operator = state.sliceDoc(node.firstChild.from, node.firstChild.to);
110
+ if (['not', '!'].includes(operator)) {
111
+ types.add(ELScalar.Bool);
112
+ }
113
+ else if (['+', '-'].includes(operator)) {
114
+ types.add(ELScalar.Number);
82
115
  }
83
116
  }
84
117
  if (types.size === 0) {
85
- types.add('any');
118
+ types.add(ELScalar.Any);
86
119
  }
87
120
  return types;
88
121
  }
89
122
  function getExpressionLanguageConfig(state) {
90
123
  return state.languageDataAt('expressionLanguageConfig', 0)[0];
91
124
  }
125
+ const keywords = [
126
+ { name: 'starts with', info: 'Check if a string starts with a specific string' },
127
+ { name: 'ends with', info: 'Check if a string ends with a specific string' },
128
+ { name: 'contains', info: 'Check if a string is not included in another string' },
129
+ { name: 'matches', info: 'Check if a string matches a regex pattern' },
130
+ { name: 'not in', info: 'Check if a value is not included in an array' },
131
+ { name: 'in', info: 'Check if a value is included in an array' },
132
+ { name: 'not' },
133
+ { name: 'or' },
134
+ { name: 'and' },
135
+ { name: 'xor' },
136
+ ];
92
137
 
93
138
  /**
94
139
  * @internal
@@ -123,7 +168,7 @@ const expressionLanguageLinterSource = (state) => {
123
168
  let i = 0;
124
169
  let n = node.node.firstChild;
125
170
  while (n) {
126
- if (++i > args.length) {
171
+ if (n.name !== 'BlockComment' && ++i > args.length) {
127
172
  diagnostics.push({ from: n.from, to: n.to, severity: 'error', message: `Unexpected argument` });
128
173
  }
129
174
  n = n.nextSibling;
package/dist/tooltip.cjs CHANGED
@@ -6,6 +6,20 @@ var state = require('@codemirror/state');
6
6
  var view = require('@codemirror/view');
7
7
  var language = require('@codemirror/language');
8
8
 
9
+ var ELScalar;
10
+ (function (ELScalar) {
11
+ ELScalar["Bool"] = "bool";
12
+ ELScalar["Number"] = "number";
13
+ ELScalar["String"] = "string";
14
+ ELScalar["Null"] = "null";
15
+ ELScalar["Any"] = "any";
16
+ })(ELScalar || (ELScalar = {}));
17
+
18
+ // @ts-ignore
19
+ const t = {
20
+ deserialize: (str) => str,
21
+ };
22
+
9
23
  const createInfoElement = (html) => {
10
24
  const dom = document.createElement("div");
11
25
  dom.innerHTML = html;
@@ -42,12 +56,16 @@ const resolveIdentifier = (nodeName, identifier, config) => {
42
56
  }
43
57
  };
44
58
  function resolveTypes(state, node, config, matchExact) {
45
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
59
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
46
60
  let types = new Set();
47
61
  if (!node) {
48
62
  return types;
49
63
  }
50
- if (node.name === 'Call' && node.firstChild && node.lastChild) {
64
+ let type;
65
+ if (typeof (type = node.type.prop(t)) !== "undefined") {
66
+ types.add(type);
67
+ }
68
+ else if (node.name === 'Call' && node.firstChild && node.lastChild) {
51
69
  resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
52
70
  }
53
71
  else if (node.name === 'Variable') {
@@ -83,17 +101,32 @@ function resolveTypes(state, node, config, matchExact) {
83
101
  resolveTypes(state, node.firstChild.nextSibling, config).forEach(x => types.add(x));
84
102
  resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
85
103
  }
86
- else if (node.name === 'BinaryExpression' && ((_k = (_j = node.firstChild) === null || _j === void 0 ? void 0 : _j.nextSibling) === null || _k === void 0 ? void 0 : _k.name) == 'Operator' && node.lastChild) {
104
+ else if (node.name === 'BinaryExpression' && ((_j = node.firstChild) === null || _j === void 0 ? void 0 : _j.nextSibling) && ((_l = (_k = node.firstChild) === null || _k === void 0 ? void 0 : _k.nextSibling) === null || _l === void 0 ? void 0 : _l.nextSibling)) {
87
105
  const operator = state.sliceDoc(node.firstChild.nextSibling.from, node.firstChild.nextSibling.to);
88
- if (operator == '?:' || operator == '??') {
89
- resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
90
- }
91
106
  if (operator == '?:' || operator == '??' || operator == '?') {
92
- resolveTypes(state, node.lastChild, config).forEach(x => types.add(x));
107
+ if (operator == '?:' || operator == '??') {
108
+ resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
109
+ }
110
+ resolveTypes(state, node.firstChild.nextSibling.nextSibling, config).forEach(x => types.add(x));
111
+ }
112
+ else if (['||', '&&', '==', '!=', '===', '!==', '>=', '<=', '>', '<'].includes(operator) || keywords.find(x => x.name == operator)) {
113
+ types.add(ELScalar.Bool);
114
+ }
115
+ else if (['**', '|', '^', '&', '<<', '>>', '+', '-', '*', '/', '%'].includes(operator)) {
116
+ types.add(ELScalar.Number);
117
+ }
118
+ }
119
+ else if (node.name === 'UnaryExpression' && node.firstChild) {
120
+ const operator = state.sliceDoc(node.firstChild.from, node.firstChild.to);
121
+ if (['not', '!'].includes(operator)) {
122
+ types.add(ELScalar.Bool);
123
+ }
124
+ else if (['+', '-'].includes(operator)) {
125
+ types.add(ELScalar.Number);
93
126
  }
94
127
  }
95
128
  if (types.size === 0) {
96
- types.add('any');
129
+ types.add(ELScalar.Any);
97
130
  }
98
131
  return types;
99
132
  }
@@ -110,6 +143,7 @@ const keywords = [
110
143
  { name: 'not' },
111
144
  { name: 'or' },
112
145
  { name: 'and' },
146
+ { name: 'xor' },
113
147
  ];
114
148
 
115
149
  function getNodeOrdinal(node) {
@@ -132,7 +166,7 @@ function getCursorTooltips(state) {
132
166
  return state.selection.ranges
133
167
  .filter(range => range.empty)
134
168
  .map(range => {
135
- var _a;
169
+ var _a, _b;
136
170
  const tree = language.syntaxTree(state);
137
171
  const node = tree.resolveInner(range.from, 0);
138
172
  const args = resolveArguments(node);
@@ -144,7 +178,7 @@ function getCursorTooltips(state) {
144
178
  return null;
145
179
  }
146
180
  const n = args.childAfter(range.from - 1);
147
- const argName = (_a = fn.args) === null || _a === void 0 ? void 0 : _a[n ? getNodeOrdinal(n) : 0];
181
+ const argName = (_b = (_a = fn.args) === null || _a === void 0 ? void 0 : _a[n ? getNodeOrdinal(n) : 0]) === null || _b === void 0 ? void 0 : _b.name;
148
182
  if (n && n.from !== range.from || !argName) {
149
183
  return null;
150
184
  }
@@ -219,19 +253,6 @@ const keywordTooltip = view.hoverTooltip((view, pos, side) => {
219
253
  create: () => ({ dom: createInfoElement(info) }),
220
254
  };
221
255
  });
222
- const cursorTooltipBaseTheme = view.EditorView.baseTheme({
223
- ".cm-tooltip.cm-tooltip-cursor": {
224
- boxShadow: 'rgba(0, 0, 0, .15) 0 1px 2px',
225
- border: "1px solid rgba(127, 127, 127, .2)",
226
- padding: "2px 7px",
227
- borderRadius: "4px",
228
- "& .cm-tooltip-arrow:before": {},
229
- "& .cm-tooltip-arrow:after": {
230
- borderTopColor: "transparent"
231
- }
232
- }
233
- });
234
256
 
235
- exports.cursorTooltipBaseTheme = cursorTooltipBaseTheme;
236
257
  exports.cursorTooltipField = cursorTooltipField;
237
258
  exports.keywordTooltip = keywordTooltip;
@@ -1,6 +1,7 @@
1
1
  import { StateField } from "@codemirror/state";
2
2
  import { Tooltip } from "@codemirror/view";
3
3
  declare const cursorTooltipField: StateField<readonly Tooltip[]>;
4
- declare const keywordTooltip: import("@codemirror/state").Extension;
5
- declare const cursorTooltipBaseTheme: import("@codemirror/state").Extension;
6
- export { cursorTooltipField, keywordTooltip, cursorTooltipBaseTheme };
4
+ declare const keywordTooltip: import("@codemirror/state").Extension & {
5
+ active: StateField<readonly Tooltip[]>;
6
+ };
7
+ export { cursorTooltipField, keywordTooltip };
package/dist/tooltip.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { StateField } from "@codemirror/state";
2
2
  import { Tooltip } from "@codemirror/view";
3
3
  declare const cursorTooltipField: StateField<readonly Tooltip[]>;
4
- declare const keywordTooltip: import("@codemirror/state").Extension;
5
- declare const cursorTooltipBaseTheme: import("@codemirror/state").Extension;
6
- export { cursorTooltipField, keywordTooltip, cursorTooltipBaseTheme };
4
+ declare const keywordTooltip: import("@codemirror/state").Extension & {
5
+ active: StateField<readonly Tooltip[]>;
6
+ };
7
+ export { cursorTooltipField, keywordTooltip };