@jbrowse/jexl 5.0.0 → 5.0.2
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/README.md +4 -2
- package/dist/Expression.d.ts +0 -12
- package/dist/Expression.js +0 -16
- package/dist/Expression.js.map +1 -1
- package/dist/check.d.ts +0 -5
- package/dist/check.js +33 -211
- package/dist/check.js.map +1 -1
- package/dist/conditions.js +3 -3
- package/dist/evaluator/compile.js +18 -2
- package/dist/evaluator/compile.js.map +1 -1
- package/dist/grammar.d.ts +3 -0
- package/dist/grammar.js +18 -16
- package/dist/grammar.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/print.d.ts +9 -0
- package/dist/print.js +189 -0
- package/dist/print.js.map +1 -0
- package/esm/Expression.d.ts +0 -12
- package/esm/Expression.js +0 -16
- package/esm/Expression.js.map +1 -1
- package/esm/check.d.ts +0 -5
- package/esm/check.js +1 -178
- package/esm/check.js.map +1 -1
- package/esm/conditions.js +1 -1
- package/esm/evaluator/compile.js +18 -2
- package/esm/evaluator/compile.js.map +1 -1
- package/esm/grammar.d.ts +3 -0
- package/esm/grammar.js +14 -15
- package/esm/grammar.js.map +1 -1
- package/esm/index.d.ts +2 -1
- package/esm/index.js +2 -1
- package/esm/index.js.map +1 -1
- package/esm/print.d.ts +9 -0
- package/esm/print.js +183 -0
- package/esm/print.js.map +1 -0
- package/package.json +2 -1
- package/src/Expression.ts +0 -20
- package/src/check.ts +2 -198
- package/src/conditions.ts +1 -1
- package/src/evaluator/compile.ts +19 -2
- package/src/grammar.ts +16 -15
- package/src/index.ts +2 -1
- package/src/print.ts +205 -0
package/README.md
CHANGED
|
@@ -347,8 +347,10 @@ A name the expression assigns reads the assignment once it has run, and goes thr
|
|
|
347
347
|
its functions registered:
|
|
348
348
|
|
|
349
349
|
```javascript
|
|
350
|
-
|
|
351
|
-
|
|
350
|
+
import { analyze } from '@jbrowse/jexl'
|
|
351
|
+
|
|
352
|
+
const ast = jexl.parse("get(feature, 'score') > 10 ? feature.name : 'n/a'")
|
|
353
|
+
analyze(ast, { accessors: { get: [] }, row: 'feature' })
|
|
352
354
|
// {
|
|
353
355
|
// variables: ['feature'],
|
|
354
356
|
// fields: [{ path: ['score'] }, { path: ['name'] }],
|
package/dist/Expression.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import Lexer from './Lexer.ts';
|
|
2
|
-
import type { AnalyzeOptions } from './analyze.ts';
|
|
3
|
-
import type { CheckOptions } from './check.ts';
|
|
4
2
|
import type { CompiledNode } from './evaluator/compile.ts';
|
|
5
3
|
import type { Grammar } from './grammar.ts';
|
|
6
4
|
import type { AstNode } from './types.ts';
|
|
@@ -42,15 +40,5 @@ declare class Expression {
|
|
|
42
40
|
get source(): string;
|
|
43
41
|
/** The parsed tree, or null for an expression with no tokens. */
|
|
44
42
|
get ast(): AstNode | null;
|
|
45
|
-
/**
|
|
46
|
-
* Lists what the expression reads from its context, without evaluating it.
|
|
47
|
-
* See {@link analyze}.
|
|
48
|
-
*/
|
|
49
|
-
analyze(options?: AnalyzeOptions): import("./analyze.ts").Analysis;
|
|
50
|
-
/**
|
|
51
|
-
* Checks the expression against a host's fields and functions, without
|
|
52
|
-
* evaluating it. See {@link check}.
|
|
53
|
-
*/
|
|
54
|
-
check(options?: CheckOptions): import("./check.ts").CheckResult;
|
|
55
43
|
}
|
|
56
44
|
export default Expression;
|
package/dist/Expression.js
CHANGED
|
@@ -8,8 +8,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
8
8
|
};
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
const Lexer_ts_1 = __importDefault(require("./Lexer.js"));
|
|
11
|
-
const analyze_ts_1 = require("./analyze.js");
|
|
12
|
-
const check_ts_1 = require("./check.js");
|
|
13
11
|
const compile_ts_1 = require("./evaluator/compile.js");
|
|
14
12
|
const Parser_ts_1 = __importDefault(require("./parser/Parser.js"));
|
|
15
13
|
class Expression {
|
|
@@ -78,20 +76,6 @@ class Expression {
|
|
|
78
76
|
}
|
|
79
77
|
return this._ast;
|
|
80
78
|
}
|
|
81
|
-
/**
|
|
82
|
-
* Lists what the expression reads from its context, without evaluating it.
|
|
83
|
-
* See {@link analyze}.
|
|
84
|
-
*/
|
|
85
|
-
analyze(options) {
|
|
86
|
-
return (0, analyze_ts_1.analyze)(this.ast, options);
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Checks the expression against a host's fields and functions, without
|
|
90
|
-
* evaluating it. See {@link check}.
|
|
91
|
-
*/
|
|
92
|
-
check(options) {
|
|
93
|
-
return (0, check_ts_1.check)(this.ast, options);
|
|
94
|
-
}
|
|
95
79
|
}
|
|
96
80
|
exports.default = Expression;
|
|
97
81
|
//# sourceMappingURL=Expression.js.map
|
package/dist/Expression.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Expression.js","sourceRoot":"","sources":["../src/Expression.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;AAEH,0DAA8B;AAC9B,
|
|
1
|
+
{"version":3,"file":"Expression.js","sourceRoot":"","sources":["../src/Expression.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;AAEH,0DAA8B;AAC9B,uDAAmD;AACnD,mEAAuC;AAMvC,MAAM,UAAU;IACd,QAAQ,CAAS;IACjB,QAAQ,CAAQ;IAChB;;oDAEgD;IAChD,IAAI,CAAgB;IACpB,MAAM,CAAO;IACb,SAAS,GAAG,KAAK,CAAA;IACjB,2EAA2E;IAC3E,GAAG,GAAwB,IAAI,CAAA;IAE/B;;;;;;;OAOG;IACH,YAAY,OAAgB,EAAE,OAAe,EAAE,KAAa;QAC1D,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,MAAM,GAAG,KAAK,IAAI,IAAI,kBAAK,CAAC,OAAO,CAAC,CAAA;IAC3C,CAAC;IAED;;;;;OAKG;IACH,OAAO;QACL,IAAI,CAAC,IAAI,GAAG,IAAI,mBAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACvE,uEAAuE;QACvE,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAA,uBAAU,EAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QAClE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;QACrB,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;;OAMG;IACH,IAAI,CAAC,OAAO,GAAG,EAAE;QACf,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,IAAI,CAAC,OAAO,EAAE,CAAA;QAChB,CAAC;QACD,qEAAqE;QACrE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAC1B,CAAC;IAED,yDAAyD;IACzD,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAED,iEAAiE;IACjE,IAAI,GAAG;QACL,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,IAAI,CAAC,OAAO,EAAE,CAAA;QAChB,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAA;IAClB,CAAC;CACF;AAED,kBAAe,UAAU,CAAA"}
|
package/dist/check.d.ts
CHANGED
|
@@ -93,11 +93,6 @@ export interface CheckResult {
|
|
|
93
93
|
type: Type;
|
|
94
94
|
}
|
|
95
95
|
export declare const UNKNOWN: Type;
|
|
96
|
-
/**
|
|
97
|
-
* Renders a tree back to expression text, for messages and suggestions. The
|
|
98
|
-
* text parses back to the same tree.
|
|
99
|
-
*/
|
|
100
|
-
export declare function print(ast: AstNode): string;
|
|
101
96
|
/** The type of a row whose fields `schema` declares. */
|
|
102
97
|
export declare function recordOf(schema: readonly FieldSchema[]): Type;
|
|
103
98
|
export declare function union(a: Type, b: Type): Type;
|
package/dist/check.js
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.UNKNOWN = void 0;
|
|
8
|
-
exports.print = print;
|
|
9
8
|
exports.recordOf = recordOf;
|
|
10
9
|
exports.union = union;
|
|
11
10
|
exports.check = check;
|
|
11
|
+
const print_ts_1 = require("./print.js");
|
|
12
12
|
exports.UNKNOWN = { kind: 'unknown' };
|
|
13
13
|
const UNDEFINED = { kind: 'undefined' };
|
|
14
14
|
const BOOLEAN = { kind: 'boolean' };
|
|
@@ -18,184 +18,6 @@ const MAX_VALUES = 64;
|
|
|
18
18
|
const ARITHMETIC = new Set(['-', '*', '/', '//', '%', '^']);
|
|
19
19
|
const ORDER = new Set(['<', '<=', '>', '>=']);
|
|
20
20
|
const EQUALITY = new Set(['==', '!=']);
|
|
21
|
-
const PRECEDENCE = {
|
|
22
|
-
'=': 2,
|
|
23
|
-
'||': 10,
|
|
24
|
-
'??': 10,
|
|
25
|
-
'&&': 11,
|
|
26
|
-
'==': 20,
|
|
27
|
-
'!=': 20,
|
|
28
|
-
'~': 20,
|
|
29
|
-
'!~': 20,
|
|
30
|
-
'<': 20,
|
|
31
|
-
'<=': 20,
|
|
32
|
-
'>': 20,
|
|
33
|
-
'>=': 20,
|
|
34
|
-
in: 20,
|
|
35
|
-
'+': 30,
|
|
36
|
-
'-': 30,
|
|
37
|
-
'*': 40,
|
|
38
|
-
'/': 40,
|
|
39
|
-
'//': 40,
|
|
40
|
-
'%': 50,
|
|
41
|
-
'^': 50
|
|
42
|
-
};
|
|
43
|
-
const RIGHT_ASSOCIATIVE = new Set(['^']);
|
|
44
|
-
const LOGICAL = new Set(['||', '&&']);
|
|
45
|
-
// how tightly each form binds, mirroring the Parser's levels: `;`, then `=`
|
|
46
|
-
// and lambdas, then `?:`, then binary operators, then prefix operators
|
|
47
|
-
const SEQUENCE = 0;
|
|
48
|
-
const ASSIGNMENT = 1;
|
|
49
|
-
const CONDITIONAL = 2;
|
|
50
|
-
const CUSTOM_BINARY = 3;
|
|
51
|
-
const UNARY = 100;
|
|
52
|
-
const letter = String.raw `a-zA-Zа-яА-Я_À-ÖØ-öø-ÿ$`;
|
|
53
|
-
const IDENTIFIER = new RegExp(`^[${letter}][${letter}0-9]*$`);
|
|
54
|
-
const WORDS = new Set(['in', 'true', 'false', 'null']);
|
|
55
|
-
function isName(text) {
|
|
56
|
-
return IDENTIFIER.test(text) && !WORDS.has(text);
|
|
57
|
-
}
|
|
58
|
-
function key(name) {
|
|
59
|
-
return isName(name) ? `.${name}` : `[${quote(name)}]`;
|
|
60
|
-
}
|
|
61
|
-
function quote(text) {
|
|
62
|
-
return `'${text.replaceAll('\\', '\\\\').replaceAll("'", String.raw `\'`)}'`;
|
|
63
|
-
}
|
|
64
|
-
function precedenceOf(node) {
|
|
65
|
-
switch (node.type) {
|
|
66
|
-
case 'SequenceExpression': {
|
|
67
|
-
return SEQUENCE;
|
|
68
|
-
}
|
|
69
|
-
case 'AssignmentExpression':
|
|
70
|
-
case 'Lambda': {
|
|
71
|
-
return ASSIGNMENT;
|
|
72
|
-
}
|
|
73
|
-
case 'ConditionalExpression': {
|
|
74
|
-
// with no alternate, it ends only before `)`, `]`, `}`, `,`, `;` or the end
|
|
75
|
-
return node.alternate ? CONDITIONAL : SEQUENCE;
|
|
76
|
-
}
|
|
77
|
-
case 'BinaryExpression': {
|
|
78
|
-
return PRECEDENCE[node.operator] ?? CUSTOM_BINARY;
|
|
79
|
-
}
|
|
80
|
-
case 'UnaryExpression': {
|
|
81
|
-
return UNARY;
|
|
82
|
-
}
|
|
83
|
-
default: {
|
|
84
|
-
return Infinity;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
function within(ast, least) {
|
|
89
|
-
const text = print(ast);
|
|
90
|
-
return precedenceOf(ast) < least ? `(${text})` : text;
|
|
91
|
-
}
|
|
92
|
-
function binaryOperand(parent, ast, left) {
|
|
93
|
-
const own = PRECEDENCE[parent.operator];
|
|
94
|
-
if (own === undefined) {
|
|
95
|
-
return within(ast, UNARY);
|
|
96
|
-
}
|
|
97
|
-
const child = ast;
|
|
98
|
-
const theirs = precedenceOf(child);
|
|
99
|
-
const chained = child.type === 'BinaryExpression' &&
|
|
100
|
-
RIGHT_ASSOCIATIVE.has(parent.operator) &&
|
|
101
|
-
RIGHT_ASSOCIATIVE.has(child.operator);
|
|
102
|
-
const mixesNullish = child.type === 'BinaryExpression' &&
|
|
103
|
-
((parent.operator === '??' && LOGICAL.has(child.operator)) ||
|
|
104
|
-
(child.operator === '??' && LOGICAL.has(parent.operator)));
|
|
105
|
-
const text = print(ast);
|
|
106
|
-
return theirs < own || (theirs === own && left === chained) || mixesNullish
|
|
107
|
-
? `(${text})`
|
|
108
|
-
: text;
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Renders a tree back to expression text, for messages and suggestions. The
|
|
112
|
-
* text parses back to the same tree.
|
|
113
|
-
*/
|
|
114
|
-
function print(ast) {
|
|
115
|
-
const node = ast;
|
|
116
|
-
switch (node.type) {
|
|
117
|
-
case 'Literal': {
|
|
118
|
-
const { value } = node;
|
|
119
|
-
return typeof value === 'string'
|
|
120
|
-
? quote(value)
|
|
121
|
-
: Object.is(value, -0)
|
|
122
|
-
? '-0'
|
|
123
|
-
: String(value);
|
|
124
|
-
}
|
|
125
|
-
case 'Identifier': {
|
|
126
|
-
return node.from
|
|
127
|
-
? within(node.from, Infinity) + key(node.value)
|
|
128
|
-
: node.value;
|
|
129
|
-
}
|
|
130
|
-
case 'FilterExpression': {
|
|
131
|
-
return `${within(node.subject, Infinity)}[${within(node.expr, ASSIGNMENT)}]`;
|
|
132
|
-
}
|
|
133
|
-
case 'BinaryExpression': {
|
|
134
|
-
return `${binaryOperand(node, node.left, true)} ${node.operator} ${binaryOperand(node, node.right, false)}`;
|
|
135
|
-
}
|
|
136
|
-
case 'UnaryExpression': {
|
|
137
|
-
const { operator } = node;
|
|
138
|
-
const right = within(node.right, UNARY);
|
|
139
|
-
// the Lexer folds a minus before a digit into the number
|
|
140
|
-
if (operator === '-' && /^\d/.test(right)) {
|
|
141
|
-
return `-(${right})`;
|
|
142
|
-
}
|
|
143
|
-
return IDENTIFIER.test(operator)
|
|
144
|
-
? `${operator} ${right}`
|
|
145
|
-
: operator + right;
|
|
146
|
-
}
|
|
147
|
-
case 'ConditionalExpression': {
|
|
148
|
-
const test = within(node.test, CUSTOM_BINARY);
|
|
149
|
-
const consequent = node.consequent
|
|
150
|
-
? ` ${within(node.consequent, ASSIGNMENT)} `
|
|
151
|
-
: '';
|
|
152
|
-
const alternate = node.alternate
|
|
153
|
-
? ` ${within(node.alternate, ASSIGNMENT)}`
|
|
154
|
-
: '';
|
|
155
|
-
return `${test} ?${consequent}:${alternate}`;
|
|
156
|
-
}
|
|
157
|
-
case 'FunctionCall': {
|
|
158
|
-
const args = node.args.map((arg) => within(arg, ASSIGNMENT));
|
|
159
|
-
return `${node.name}(${args.join(', ')})`;
|
|
160
|
-
}
|
|
161
|
-
case 'ArrayLiteral': {
|
|
162
|
-
const items = node.value.map((item) => within(item, ASSIGNMENT));
|
|
163
|
-
return `[${items.join(', ')}]`;
|
|
164
|
-
}
|
|
165
|
-
case 'ObjectLiteral': {
|
|
166
|
-
const entries = Object.entries(node.value).map(([name, value]) => `${isName(name) ? name : quote(name)}: ${within(value, ASSIGNMENT)}`);
|
|
167
|
-
return `{${entries.join(', ')}}`;
|
|
168
|
-
}
|
|
169
|
-
case 'TemplateLiteral': {
|
|
170
|
-
const parts = node.parts.map((part) => part.type === 'static'
|
|
171
|
-
? part.value
|
|
172
|
-
.replaceAll('\\', '\\\\')
|
|
173
|
-
.replaceAll('`', '\\`')
|
|
174
|
-
.replaceAll('${', '\\${')
|
|
175
|
-
: `\${${print(part.value)}}`);
|
|
176
|
-
return `\`${parts.join('')}\``;
|
|
177
|
-
}
|
|
178
|
-
case 'SequenceExpression': {
|
|
179
|
-
const { expressions } = node;
|
|
180
|
-
const text = expressions
|
|
181
|
-
.map((expr) => within(expr, ASSIGNMENT))
|
|
182
|
-
.join('; ');
|
|
183
|
-
return expressions.length === 1 ? `${text};` : text;
|
|
184
|
-
}
|
|
185
|
-
case 'AssignmentExpression': {
|
|
186
|
-
return `${node.left.value} = ${within(node.right, ASSIGNMENT)}`;
|
|
187
|
-
}
|
|
188
|
-
case 'Lambda': {
|
|
189
|
-
const params = node.params.length === 1
|
|
190
|
-
? node.params[0]
|
|
191
|
-
: `(${node.params.join(', ')})`;
|
|
192
|
-
return `${params} => ${within(node.body, ASSIGNMENT)}`;
|
|
193
|
-
}
|
|
194
|
-
default: {
|
|
195
|
-
return '?';
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
21
|
function distance(a, b) {
|
|
200
22
|
let before = [];
|
|
201
23
|
let previous = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
@@ -574,8 +396,8 @@ function paramName(subject, context) {
|
|
|
574
396
|
const base = node.type === 'Identifier'
|
|
575
397
|
? node.value.toLowerCase().replaceAll(/\W/g, '')
|
|
576
398
|
: '';
|
|
577
|
-
const name = isName(base) ? base : 'x';
|
|
578
|
-
const text = print(context);
|
|
399
|
+
const name = (0, print_ts_1.isName)(base) ? base : 'x';
|
|
400
|
+
const text = (0, print_ts_1.print)(context);
|
|
579
401
|
let candidate = name;
|
|
580
402
|
for (let i = 2; new RegExp(String.raw `\b${candidate}\b`).test(text); i++) {
|
|
581
403
|
candidate = `${name}${i}`;
|
|
@@ -597,7 +419,7 @@ function describe(type) {
|
|
|
597
419
|
return type.values?.length === 1 ? String(type.values[0]) : 'a number';
|
|
598
420
|
}
|
|
599
421
|
case 'string': {
|
|
600
|
-
return type.values?.length === 1 ? quote(type.values[0]) : 'text';
|
|
422
|
+
return type.values?.length === 1 ? (0, print_ts_1.quote)(type.values[0]) : 'text';
|
|
601
423
|
}
|
|
602
424
|
case 'boolean': {
|
|
603
425
|
return type.field?.type === 'flag' ? 'a flag' : 'a boolean';
|
|
@@ -671,10 +493,10 @@ function check(ast, { schema, functions, accessors = {}, row, env } = {}) {
|
|
|
671
493
|
});
|
|
672
494
|
}
|
|
673
495
|
function text(node, name) {
|
|
674
|
-
return node ? print(node) + key(name) : name;
|
|
496
|
+
return node ? (0, print_ts_1.print)(node) + (0, print_ts_1.key)(name) : name;
|
|
675
497
|
}
|
|
676
498
|
function field(subject, name, node, subjectNode, spell = (candidate) => text(subjectNode, candidate)) {
|
|
677
|
-
const where = subjectNode ? print(subjectNode) : 'the row';
|
|
499
|
+
const where = subjectNode ? (0, print_ts_1.print)(subjectNode) : 'the row';
|
|
678
500
|
switch (subject.kind) {
|
|
679
501
|
case 'record': {
|
|
680
502
|
const found = subject.fields.get(name) ?? subject.each;
|
|
@@ -698,16 +520,16 @@ function check(ast, { schema, functions, accessors = {}, row, env } = {}) {
|
|
|
698
520
|
(item.open || !!item.each || item.fields.has(name)));
|
|
699
521
|
const suggestions = [];
|
|
700
522
|
if (entriesHave && subjectNode && node.type === 'Identifier') {
|
|
701
|
-
const list = print(subjectNode);
|
|
523
|
+
const list = (0, print_ts_1.print)(subjectNode);
|
|
702
524
|
const param = paramName(subjectNode, node);
|
|
703
|
-
suggestions.push(`${list}[0]${key(name)}`);
|
|
525
|
+
suggestions.push(`${list}[0]${(0, print_ts_1.key)(name)}`);
|
|
704
526
|
if (functions?.map) {
|
|
705
|
-
suggestions.push(`map(${list}, ${param} => ${param}${key(name)})`);
|
|
527
|
+
suggestions.push(`map(${list}, ${param} => ${param}${(0, print_ts_1.key)(name)})`);
|
|
706
528
|
}
|
|
707
529
|
}
|
|
708
|
-
report('dot-through-list', 'warning', node, `${where} is a list, so ${key(name)} is undefined` +
|
|
530
|
+
report('dot-through-list', 'warning', node, `${where} is a list, so ${(0, print_ts_1.key)(name)} is undefined` +
|
|
709
531
|
(entriesHave
|
|
710
|
-
? `; [0]${key(name)} reads the first entry's` +
|
|
532
|
+
? `; [0]${(0, print_ts_1.key)(name)} reads the first entry's` +
|
|
711
533
|
(functions?.any ? ', and any() tests each' : '')
|
|
712
534
|
: ''), suggestions);
|
|
713
535
|
return UNDEFINED;
|
|
@@ -730,7 +552,7 @@ function check(ast, { schema, functions, accessors = {}, row, env } = {}) {
|
|
|
730
552
|
return exports.UNKNOWN;
|
|
731
553
|
}
|
|
732
554
|
function index(subject, at, node, subjectNode) {
|
|
733
|
-
const where = print(subjectNode);
|
|
555
|
+
const where = (0, print_ts_1.print)(subjectNode);
|
|
734
556
|
switch (subject.kind) {
|
|
735
557
|
case 'list': {
|
|
736
558
|
const absent = firstAbsentIndex(subject.cardinality);
|
|
@@ -791,8 +613,8 @@ function check(ast, { schema, functions, accessors = {}, row, env } = {}) {
|
|
|
791
613
|
const stepReaches = step?.kind === 'record' &&
|
|
792
614
|
(step.fields.has(names[i + 1]) || !!step.each);
|
|
793
615
|
if (record.fields.has(whole) && !stepReaches) {
|
|
794
|
-
const fixed = print(subjectNode) + key(whole);
|
|
795
|
-
report('dotted-key', 'warning', node, `${whole} is one field of ${print(subjectNode)}; jexl reads ${names.slice(i, j).join(' then ')}`, [[fixed, ...names.slice(j).map((name) => key(name))].join('')]);
|
|
616
|
+
const fixed = (0, print_ts_1.print)(subjectNode) + (0, print_ts_1.key)(whole);
|
|
617
|
+
report('dotted-key', 'warning', node, `${whole} is one field of ${(0, print_ts_1.print)(subjectNode)}; jexl reads ${names.slice(i, j).join(' then ')}`, [[fixed, ...names.slice(j).map((name) => (0, print_ts_1.key)(name))].join('')]);
|
|
796
618
|
let resolved = record.fields.get(whole);
|
|
797
619
|
for (const name of names.slice(j)) {
|
|
798
620
|
resolved = field(resolved, name, node, undefined);
|
|
@@ -865,7 +687,7 @@ function check(ast, { schema, functions, accessors = {}, row, env } = {}) {
|
|
|
865
687
|
if (!found) {
|
|
866
688
|
return undefined;
|
|
867
689
|
}
|
|
868
|
-
report('unknown-field', 'warning', node, `${print(node)} subtracts; ${whole} is one field`, [text(left.from, whole)]);
|
|
690
|
+
report('unknown-field', 'warning', node, `${(0, print_ts_1.print)(node)} subtracts; ${whole} is one field`, [text(left.from, whole)]);
|
|
869
691
|
return found;
|
|
870
692
|
}
|
|
871
693
|
function memberFor(element, value, valueNode, listNode, node) {
|
|
@@ -878,10 +700,10 @@ function check(ast, { schema, functions, accessors = {}, row, env } = {}) {
|
|
|
878
700
|
const scalar = type.kind === 'list' ? type.of : type;
|
|
879
701
|
return scalar.kind === 'string' && scalar.values?.includes(literal);
|
|
880
702
|
});
|
|
881
|
-
report('never-equal', 'warning', node, `${print(listNode)} holds records, so no entry equals ${quote(literal)}` +
|
|
703
|
+
report('never-equal', 'warning', node, `${(0, print_ts_1.print)(listNode)} holds records, so no entry equals ${(0, print_ts_1.quote)(literal)}` +
|
|
882
704
|
(holder ? `; it is a value of their ${holder[0]} field` : ''), holder && functions?.any
|
|
883
705
|
? [
|
|
884
|
-
`any(${print(listNode)}, ${paramName(listNode, node)} => ${print(valueNode)} in ${paramName(listNode, node)}${key(holder[0])})`
|
|
706
|
+
`any(${(0, print_ts_1.print)(listNode)}, ${paramName(listNode, node)} => ${(0, print_ts_1.print)(valueNode)} in ${paramName(listNode, node)}${(0, print_ts_1.key)(holder[0])})`
|
|
885
707
|
]
|
|
886
708
|
: []);
|
|
887
709
|
return;
|
|
@@ -892,21 +714,21 @@ function check(ast, { schema, functions, accessors = {}, row, env } = {}) {
|
|
|
892
714
|
if (type.kind === 'number' &&
|
|
893
715
|
typeof literal === 'string' &&
|
|
894
716
|
Number.isNaN(Number(literal))) {
|
|
895
|
-
report('never-equal', 'warning', node, `${quote(literal)} is not a number, so it never equals ${describe(type)}`);
|
|
717
|
+
report('never-equal', 'warning', node, `${(0, print_ts_1.quote)(literal)} is not a number, so it never equals ${describe(type)}`);
|
|
896
718
|
}
|
|
897
719
|
else if (type.kind === 'boolean' && typeof literal === 'string') {
|
|
898
|
-
report('never-equal', 'warning', node, `${describe(type)} never equals the text ${quote(literal)}`, literal === 'true' || literal === 'false' ? [literal] : []);
|
|
720
|
+
report('never-equal', 'warning', node, `${describe(type)} never equals the text ${(0, print_ts_1.quote)(literal)}`, literal === 'true' || literal === 'false' ? [literal] : []);
|
|
899
721
|
}
|
|
900
722
|
else if (type.kind === 'string' &&
|
|
901
723
|
type.field?.categories &&
|
|
902
724
|
typeof literal === 'string' &&
|
|
903
725
|
!type.field.categories.includes(literal)) {
|
|
904
726
|
const near = nearest(literal, type.field.categories);
|
|
905
|
-
report('unknown-category', 'warning', node, `${quote(literal)} is not one of the values the header declares for ${type.field.path.join('.')}` +
|
|
906
|
-
(near.length ? `; did you mean ${near.map(quote).join(', ')}?` : ''), near.map(quote));
|
|
727
|
+
report('unknown-category', 'warning', node, `${(0, print_ts_1.quote)(literal)} is not one of the values the header declares for ${type.field.path.join('.')}` +
|
|
728
|
+
(near.length ? `; did you mean ${near.map(print_ts_1.quote).join(', ')}?` : ''), near.map(print_ts_1.quote));
|
|
907
729
|
}
|
|
908
730
|
else if (type.kind === 'record') {
|
|
909
|
-
report('never-equal', 'warning', node, `a record never equals ${quote(String(literal))}`);
|
|
731
|
+
report('never-equal', 'warning', node, `a record never equals ${(0, print_ts_1.quote)(String(literal))}`);
|
|
910
732
|
}
|
|
911
733
|
}
|
|
912
734
|
function binary(node) {
|
|
@@ -929,7 +751,7 @@ function check(ast, { schema, functions, accessors = {}, row, env } = {}) {
|
|
|
929
751
|
if (operator === '~' || operator === '!~') {
|
|
930
752
|
const pattern = literalOf(right);
|
|
931
753
|
if (typeof pattern === 'string' && !isPattern(pattern)) {
|
|
932
|
-
report('invalid-pattern', 'error', node, `${quote(pattern)} is not a valid regular expression`);
|
|
754
|
+
report('invalid-pattern', 'error', node, `${(0, print_ts_1.quote)(pattern)} is not a valid regular expression`);
|
|
933
755
|
}
|
|
934
756
|
return BOOLEAN;
|
|
935
757
|
}
|
|
@@ -945,7 +767,7 @@ function check(ast, { schema, functions, accessors = {}, row, env } = {}) {
|
|
|
945
767
|
second &&
|
|
946
768
|
(ARITHMETIC.has(operator) || operator === '+') &&
|
|
947
769
|
!pairs(first.cardinality, second.cardinality)) {
|
|
948
|
-
report('list-lengths', 'warning', node, `${print(node.left)} ${holding(first)} and ${print(rightNode)} ${holding(second)}, so ${operator} pairs them only where both hold one value`);
|
|
770
|
+
report('list-lengths', 'warning', node, `${(0, print_ts_1.print)(node.left)} ${holding(first)} and ${(0, print_ts_1.print)(rightNode)} ${holding(second)}, so ${operator} pairs them only where both hold one value`);
|
|
949
771
|
}
|
|
950
772
|
const eachOf = (item) => first ? { kind: 'list', of: item, cardinality: first.cardinality } : item;
|
|
951
773
|
if (operator === '+') {
|
|
@@ -960,9 +782,9 @@ function check(ast, { schema, functions, accessors = {}, row, env } = {}) {
|
|
|
960
782
|
]) {
|
|
961
783
|
const numericOther = ARITHMETIC.has(operator) || isNumberish(other);
|
|
962
784
|
if (type.kind === 'string' && type.field && numericOther) {
|
|
963
|
-
report('string-numeric', 'warning', node, `${print(typeNode)} is text, so ${operator} converts it to a number, ${ORDER.has(operator) ? 'answering false' : 'giving NaN'} wherever it is not one`, functions?.parseFloat
|
|
785
|
+
report('string-numeric', 'warning', node, `${(0, print_ts_1.print)(typeNode)} is text, so ${operator} converts it to a number, ${ORDER.has(operator) ? 'answering false' : 'giving NaN'} wherever it is not one`, functions?.parseFloat
|
|
964
786
|
? [
|
|
965
|
-
print(node).replace(print(typeNode), `parseFloat(${print(typeNode)})`)
|
|
787
|
+
(0, print_ts_1.print)(node).replace((0, print_ts_1.print)(typeNode), `parseFloat(${(0, print_ts_1.print)(typeNode)})`)
|
|
966
788
|
]
|
|
967
789
|
: []);
|
|
968
790
|
}
|
|
@@ -987,7 +809,7 @@ function check(ast, { schema, functions, accessors = {}, row, env } = {}) {
|
|
|
987
809
|
memberFor(right.of, leftItem, node.left, rightNode, node);
|
|
988
810
|
}
|
|
989
811
|
else if (right.kind === 'number' || right.kind === 'boolean') {
|
|
990
|
-
report('never-equal', 'warning', node, `in tests a list, text, a Set, a Map or an object's keys, and ${print(rightNode)} is ${describe(right)}`);
|
|
812
|
+
report('never-equal', 'warning', node, `in tests a list, text, a Set, a Map or an object's keys, and ${(0, print_ts_1.print)(rightNode)} is ${describe(right)}`);
|
|
991
813
|
}
|
|
992
814
|
return BOOLEAN;
|
|
993
815
|
}
|
|
@@ -1066,7 +888,7 @@ function check(ast, { schema, functions, accessors = {}, row, env } = {}) {
|
|
|
1066
888
|
keyArgs.forEach(infer);
|
|
1067
889
|
return exports.UNKNOWN;
|
|
1068
890
|
}
|
|
1069
|
-
step(String(name), arg, quote);
|
|
891
|
+
step(String(name), arg, print_ts_1.quote);
|
|
1070
892
|
}
|
|
1071
893
|
return type;
|
|
1072
894
|
}
|
|
@@ -1076,7 +898,7 @@ function check(ast, { schema, functions, accessors = {}, row, env } = {}) {
|
|
|
1076
898
|
if (functions) {
|
|
1077
899
|
const near = nearest(name, Object.keys(functions));
|
|
1078
900
|
report('unknown-function', 'error', node, `no function ${name}` +
|
|
1079
|
-
(near.length ? `; did you mean ${near.join(', ')}?` : ''), near.map((candidate) => print({ ...node, name: candidate })));
|
|
901
|
+
(near.length ? `; did you mean ${near.join(', ')}?` : ''), near.map((candidate) => (0, print_ts_1.print)({ ...node, name: candidate })));
|
|
1080
902
|
}
|
|
1081
903
|
return exports.UNKNOWN;
|
|
1082
904
|
}
|
|
@@ -1104,7 +926,7 @@ function check(ast, { schema, functions, accessors = {}, row, env } = {}) {
|
|
|
1104
926
|
const type = infer(arg);
|
|
1105
927
|
types.push(type);
|
|
1106
928
|
if (accepted.includes('lambda')) {
|
|
1107
|
-
report('argument-type', 'error', arg, `${name} expects a function such as x => …, not ${print(arg)}`);
|
|
929
|
+
report('argument-type', 'error', arg, `${name} expects a function such as x => …, not ${(0, print_ts_1.print)(arg)}`);
|
|
1108
930
|
continue;
|
|
1109
931
|
}
|
|
1110
932
|
if (accepted.includes('member') && lastCollection && lastCollectionNode) {
|
|
@@ -1119,7 +941,7 @@ function check(ast, { schema, functions, accessors = {}, row, env } = {}) {
|
|
|
1119
941
|
? 'list-operand'
|
|
1120
942
|
: type.kind === 'string'
|
|
1121
943
|
? 'string-numeric'
|
|
1122
|
-
: 'argument-type', 'warning', arg, `${name} expects ${accepted.join(' or ')} as argument ${i + 1}, but ${print(arg)} ${problems[0]}`);
|
|
944
|
+
: 'argument-type', 'warning', arg, `${name} expects ${accepted.join(' or ')} as argument ${i + 1}, but ${(0, print_ts_1.print)(arg)} ${problems[0]}`);
|
|
1123
945
|
}
|
|
1124
946
|
if (accepted.includes('list')) {
|
|
1125
947
|
lastCollection = type;
|
|
@@ -1166,14 +988,14 @@ function check(ast, { schema, functions, accessors = {}, row, env } = {}) {
|
|
|
1166
988
|
}
|
|
1167
989
|
if (typeof at === 'string') {
|
|
1168
990
|
if (subject.kind === 'list' && at !== 'length') {
|
|
1169
|
-
report('unknown-field', 'warning', node, `${print(node.subject)} is ${describe(subject)}, so [${quote(at)}] reads nothing`);
|
|
991
|
+
report('unknown-field', 'warning', node, `${(0, print_ts_1.print)(node.subject)} is ${describe(subject)}, so [${(0, print_ts_1.quote)(at)}] reads nothing`);
|
|
1170
992
|
return UNDEFINED;
|
|
1171
993
|
}
|
|
1172
994
|
return field(subject, at, node, node.subject);
|
|
1173
995
|
}
|
|
1174
996
|
const by = infer(node.expr);
|
|
1175
997
|
if (isMulti(by)) {
|
|
1176
|
-
report('list-operand', 'warning', node, `${print(node.expr)} ${holding(by)}, so indexing by it finds an entry only when there is exactly one`);
|
|
998
|
+
report('list-operand', 'warning', node, `${(0, print_ts_1.print)(node.expr)} ${holding(by)}, so indexing by it finds an entry only when there is exactly one`);
|
|
1177
999
|
}
|
|
1178
1000
|
if (subject.kind === 'record') {
|
|
1179
1001
|
return unionAll([
|