astronomical 1.0.0-beta.13 → 1.0.0-beta.14
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/lib/cjs/index.js +315 -323
- package/lib/cjs/nodeutils.js +5 -1
- package/lib/cjs/traverse.js +147 -142
- package/lib/cjs/types/index.d.ts +6 -2
- package/lib/cjs/types/index.d.ts.map +1 -1
- package/lib/cjs/types/nodeutils.d.ts +1 -0
- package/lib/cjs/types/nodeutils.d.ts.map +1 -1
- package/lib/cjs/types/traverse.d.ts +6 -4
- package/lib/cjs/types/traverse.d.ts.map +1 -1
- package/lib/cjs/types/utils.d.ts +3 -0
- package/lib/cjs/types/utils.d.ts.map +1 -0
- package/lib/cjs/utils.js +11 -0
- package/lib/esm/index.mjs +315 -323
- package/lib/esm/nodeutils.js +5 -1
- package/lib/esm/traverse.js +147 -142
- package/lib/esm/types/index.d.ts +6 -2
- package/lib/esm/types/index.d.ts.map +1 -1
- package/lib/esm/types/nodeutils.d.ts +1 -0
- package/lib/esm/types/nodeutils.d.ts.map +1 -1
- package/lib/esm/types/traverse.d.ts +6 -4
- package/lib/esm/types/traverse.d.ts.map +1 -1
- package/lib/esm/types/utils.d.ts +3 -0
- package/lib/esm/types/utils.d.ts.map +1 -0
- package/lib/esm/utils.js +11 -0
- package/package.json +1 -1
package/lib/cjs/index.js
CHANGED
|
@@ -1,32 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
24
4
|
};
|
|
25
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
6
|
exports.parseSource = exports.multiQuery = exports.query = exports.isAvailableFunction = exports.functions = void 0;
|
|
27
|
-
const traverse_1 =
|
|
7
|
+
const traverse_1 = __importDefault(require("./traverse"));
|
|
28
8
|
const parseQuery_1 = require("./parseQuery");
|
|
29
9
|
const meriyah_1 = require("meriyah");
|
|
10
|
+
const nodeutils_1 = require("./nodeutils");
|
|
30
11
|
const debugLogEnabled = false;
|
|
31
12
|
const log = {
|
|
32
13
|
debug: (...args) => {
|
|
@@ -83,10 +64,6 @@ function isAvailableFunction(name) {
|
|
|
83
64
|
return functionNames.includes(name);
|
|
84
65
|
}
|
|
85
66
|
exports.isAvailableFunction = isAvailableFunction;
|
|
86
|
-
function beginHandle(queries, path) {
|
|
87
|
-
const rootPath = (0, traverse_1.createNodePath)(path, undefined, undefined, undefined);
|
|
88
|
-
return travHandle(queries, rootPath);
|
|
89
|
-
}
|
|
90
67
|
function breadCrumb(path) {
|
|
91
68
|
return {
|
|
92
69
|
valueOf() {
|
|
@@ -96,354 +73,369 @@ function breadCrumb(path) {
|
|
|
96
73
|
}
|
|
97
74
|
};
|
|
98
75
|
}
|
|
99
|
-
function
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
76
|
+
function createQuerier() {
|
|
77
|
+
const traverser = (0, traverse_1.default)();
|
|
78
|
+
const { getChildren, getBinding, createNodePath, traverse } = traverser;
|
|
79
|
+
function createFilter(filter, filterResult) {
|
|
80
|
+
if (filter.type == "and" || filter.type == "or" || filter.type == "equals") {
|
|
81
|
+
return {
|
|
82
|
+
type: filter.type,
|
|
83
|
+
left: createFilter(filter.left, []),
|
|
84
|
+
right: createFilter(filter.right, [])
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
else if (filter.type == "literal") {
|
|
88
|
+
const r = [filter.value];
|
|
89
|
+
return {
|
|
90
|
+
node: filter,
|
|
91
|
+
result: r
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return createFNode(filter, filterResult);
|
|
106
95
|
}
|
|
107
|
-
|
|
108
|
-
const r = [filter.value];
|
|
96
|
+
function createFNode(token, result) {
|
|
109
97
|
return {
|
|
110
|
-
node:
|
|
111
|
-
result:
|
|
98
|
+
node: token,
|
|
99
|
+
result: result
|
|
112
100
|
};
|
|
113
101
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
node: token,
|
|
119
|
-
result: result
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
function addFilterChildrenToState(filter, state) {
|
|
123
|
-
if ("type" in filter && (filter.type == "and" || filter.type == "or" || filter.type == "equals")) {
|
|
124
|
-
addFilterChildrenToState(filter.left, state);
|
|
125
|
-
addFilterChildrenToState(filter.right, state);
|
|
126
|
-
}
|
|
127
|
-
else if ("node" in filter) {
|
|
128
|
-
if (filter.node.type == "child") {
|
|
129
|
-
log.debug("ADDING FILTER CHILD", filter.node);
|
|
130
|
-
state.child[state.depth + 1].push(filter);
|
|
102
|
+
function addFilterChildrenToState(filter, state) {
|
|
103
|
+
if ("type" in filter && (filter.type == "and" || filter.type == "or" || filter.type == "equals")) {
|
|
104
|
+
addFilterChildrenToState(filter.left, state);
|
|
105
|
+
addFilterChildrenToState(filter.right, state);
|
|
131
106
|
}
|
|
132
|
-
if (
|
|
133
|
-
|
|
134
|
-
|
|
107
|
+
else if ("node" in filter) {
|
|
108
|
+
if (filter.node.type == "child") {
|
|
109
|
+
log.debug("ADDING FILTER CHILD", filter.node);
|
|
110
|
+
state.child[state.depth + 1].push(filter);
|
|
111
|
+
}
|
|
112
|
+
if (filter.node.type == "descendant") {
|
|
113
|
+
log.debug("ADDING FILTER DESCENDANT", filter.node);
|
|
114
|
+
state.descendant[state.depth + 1].push(filter);
|
|
115
|
+
}
|
|
135
116
|
}
|
|
136
117
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
118
|
+
function createFNodeAndAddToState(token, result, state) {
|
|
119
|
+
log.debug("ADDING FNODE", token);
|
|
120
|
+
const fnode = createFNode(token, result);
|
|
121
|
+
if (token.type == "child") {
|
|
122
|
+
state.child[state.depth + 1].push(fnode);
|
|
123
|
+
}
|
|
124
|
+
else if (token.type == "descendant") {
|
|
125
|
+
state.descendant[state.depth + 1].push(fnode);
|
|
126
|
+
}
|
|
127
|
+
return fnode;
|
|
146
128
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
129
|
+
function isMatch(fnode, path) {
|
|
130
|
+
if (fnode.node.attribute) {
|
|
131
|
+
const m = fnode.node.value == path.parentKey || fnode.node.value == path.key;
|
|
132
|
+
if (m)
|
|
133
|
+
log.debug("ATTR MATCH", fnode.node.value, breadCrumb(path));
|
|
134
|
+
return m;
|
|
135
|
+
}
|
|
136
|
+
if (fnode.node.value == "*") {
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
const m = fnode.node.value == path.node.type;
|
|
152
140
|
if (m)
|
|
153
|
-
log.debug("
|
|
141
|
+
log.debug("NODE MATCH", fnode.node.value, breadCrumb(path));
|
|
154
142
|
return m;
|
|
155
143
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
144
|
+
function addIfTokenMatch(fnode, path, state) {
|
|
145
|
+
if (!isMatch(fnode, path))
|
|
146
|
+
return;
|
|
147
|
+
state.matches[state.depth].push([fnode, path]);
|
|
148
|
+
if (fnode.node.filter) {
|
|
149
|
+
const filter = createFilter(fnode.node.filter, []);
|
|
150
|
+
const filteredResult = [];
|
|
151
|
+
state.filters[state.depth].push({ filter: filter, qNode: fnode.node, node: path.node, result: filteredResult });
|
|
152
|
+
addFilterChildrenToState(filter, state);
|
|
153
|
+
const child = fnode.node.child;
|
|
154
|
+
if (child) {
|
|
155
|
+
if (child.type == "function") {
|
|
156
|
+
const fr = addFunction(fnode, child, path, state);
|
|
157
|
+
state.functionCalls[state.depth].push(fr);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
createFNodeAndAddToState(child, filteredResult, state);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
const child = fnode.node.child;
|
|
166
|
+
if (child?.type == "function") {
|
|
176
167
|
const fr = addFunction(fnode, child, path, state);
|
|
177
168
|
state.functionCalls[state.depth].push(fr);
|
|
178
169
|
}
|
|
179
|
-
else {
|
|
180
|
-
createFNodeAndAddToState(child,
|
|
170
|
+
else if (child && !fnode.node.binding && !fnode.node.resolve) {
|
|
171
|
+
createFNodeAndAddToState(child, fnode.result, state);
|
|
181
172
|
}
|
|
182
173
|
}
|
|
183
174
|
}
|
|
184
|
-
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
else if (child && !fnode.node.binding && !fnode.node.resolve) {
|
|
191
|
-
createFNodeAndAddToState(child, fnode.result, state);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
function addFunction(rootNode, functionCall, path, state) {
|
|
196
|
-
const functionNode = { node: rootNode.node, functionCall: functionCall, parameters: [], result: [] };
|
|
197
|
-
for (const param of functionCall.parameters) {
|
|
198
|
-
if (param.type == "literal") {
|
|
199
|
-
functionNode.parameters.push({ node: param, result: [param.value] });
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
if (param.type == "function") {
|
|
203
|
-
functionNode.parameters.push(addFunction(functionNode, param, path, state));
|
|
175
|
+
function addFunction(rootNode, functionCall, path, state) {
|
|
176
|
+
const functionNode = { node: rootNode.node, functionCall: functionCall, parameters: [], result: [] };
|
|
177
|
+
for (const param of functionCall.parameters) {
|
|
178
|
+
if (param.type == "literal") {
|
|
179
|
+
functionNode.parameters.push({ node: param, result: [param.value] });
|
|
204
180
|
}
|
|
205
181
|
else {
|
|
206
|
-
|
|
182
|
+
if (param.type == "function") {
|
|
183
|
+
functionNode.parameters.push(addFunction(functionNode, param, path, state));
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
functionNode.parameters.push(createFNodeAndAddToState(param, [], state));
|
|
187
|
+
}
|
|
207
188
|
}
|
|
208
189
|
}
|
|
190
|
+
return functionNode;
|
|
209
191
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
.
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
192
|
+
function addPrimitiveAttributeIfMatch(fnode, path) {
|
|
193
|
+
if (!fnode.node.attribute || !fnode.node.value)
|
|
194
|
+
return;
|
|
195
|
+
if (fnode.node.child || fnode.node.filter)
|
|
196
|
+
return;
|
|
197
|
+
if (!Object.hasOwn(path.node, fnode.node.value))
|
|
198
|
+
return;
|
|
199
|
+
const lookup = getChildren(fnode.node.value, path);
|
|
200
|
+
const nodes = toArray(lookup)
|
|
201
|
+
.filter(n => n.node != undefined)
|
|
202
|
+
.filter(n => (0, nodeutils_1.isPrimitive)(n.node));
|
|
203
|
+
if (nodes.length == 0)
|
|
204
|
+
return;
|
|
205
|
+
log.debug("PRIMITIVE", fnode.node.value, nodes.map(n => n.node));
|
|
206
|
+
fnode.result.push(...nodes.map(n => n.node));
|
|
207
|
+
}
|
|
208
|
+
function evaluateFilter(filter, path) {
|
|
209
|
+
log.debug("EVALUATING FILTER", filter, breadCrumb(path));
|
|
210
|
+
if ("type" in filter) {
|
|
211
|
+
if (filter.type == "and") {
|
|
212
|
+
const left = evaluateFilter(filter.left, path);
|
|
213
|
+
if (left.length == 0)
|
|
214
|
+
return [];
|
|
215
|
+
return evaluateFilter(filter.right, path);
|
|
216
|
+
}
|
|
217
|
+
if (filter.type == "or") {
|
|
218
|
+
const left = evaluateFilter(filter.left, path);
|
|
219
|
+
if (left.length > 0)
|
|
220
|
+
return left;
|
|
221
|
+
return evaluateFilter(filter.right, path);
|
|
222
|
+
}
|
|
223
|
+
if (filter.type == "equals") {
|
|
224
|
+
const left = evaluateFilter(filter.left, path);
|
|
225
|
+
const right = evaluateFilter(filter.right, path);
|
|
226
|
+
return left.filter(x => right.includes(x));
|
|
227
|
+
}
|
|
228
|
+
throw new Error("Unknown filter type: " + filter.type);
|
|
245
229
|
}
|
|
246
|
-
if (filter.type == "
|
|
247
|
-
|
|
248
|
-
const right = evaluateFilter(filter.right, path);
|
|
249
|
-
return left.filter(x => right.includes(x));
|
|
230
|
+
if (filter.node.type == "parent") {
|
|
231
|
+
return resolveFilterWithParent(filter.node, path);
|
|
250
232
|
}
|
|
251
|
-
|
|
233
|
+
return filter.result;
|
|
252
234
|
}
|
|
253
|
-
|
|
254
|
-
|
|
235
|
+
function resolveBinding(path) {
|
|
236
|
+
if (!(0, nodeutils_1.isIdentifier)(path.node))
|
|
237
|
+
return undefined;
|
|
238
|
+
log.debug("RESOLVING BINDING FOR ", path.node);
|
|
239
|
+
const name = path.node.name;
|
|
240
|
+
if (name == undefined || typeof name != "string")
|
|
241
|
+
return undefined;
|
|
242
|
+
//const binding = path.scope.getBinding(name);
|
|
243
|
+
const binding = getBinding(path.scopeId, name);
|
|
244
|
+
if (!binding)
|
|
245
|
+
return undefined;
|
|
246
|
+
log.debug("THIS IS THE BINDING", binding);
|
|
247
|
+
return binding.path;
|
|
255
248
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
const binding = (0, traverse_1.getBinding)(path.scopeId, name);
|
|
270
|
-
if (!binding)
|
|
271
|
-
return undefined;
|
|
272
|
-
log.debug("THIS IS THE BINDING", binding);
|
|
273
|
-
return binding.path;
|
|
274
|
-
}
|
|
275
|
-
function resolveFilterWithParent(node, path) {
|
|
276
|
-
let startNode = node;
|
|
277
|
-
let startPath = path;
|
|
278
|
-
while (startNode.type == "parent") {
|
|
279
|
-
if (!startNode.child)
|
|
280
|
-
throw new Error("Parent filter must have child");
|
|
281
|
-
if (!startPath.parentPath)
|
|
282
|
-
return [];
|
|
283
|
-
log.debug("STEP OUT", startNode, breadCrumb(startPath));
|
|
284
|
-
startNode = startNode.child;
|
|
285
|
-
startPath = startPath.parentPath;
|
|
249
|
+
function resolveFilterWithParent(node, path) {
|
|
250
|
+
let startNode = node;
|
|
251
|
+
let startPath = path;
|
|
252
|
+
while (startNode.type == "parent") {
|
|
253
|
+
if (!startNode.child)
|
|
254
|
+
throw new Error("Parent filter must have child");
|
|
255
|
+
if (!startPath.parentPath)
|
|
256
|
+
return [];
|
|
257
|
+
log.debug("STEP OUT", startNode, breadCrumb(startPath));
|
|
258
|
+
startNode = startNode.child;
|
|
259
|
+
startPath = startPath.parentPath;
|
|
260
|
+
}
|
|
261
|
+
return resolveDirectly(startNode, startPath);
|
|
286
262
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
let
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
263
|
+
const toArray = (value) => Array.isArray(value) ? value : [value];
|
|
264
|
+
function isDefined(value) {
|
|
265
|
+
return value != undefined && value != null;
|
|
266
|
+
}
|
|
267
|
+
let subQueryCounter = 0;
|
|
268
|
+
function resolveDirectly(node, path) {
|
|
269
|
+
let startNode = node;
|
|
270
|
+
const startPath = path;
|
|
271
|
+
let paths = [startPath];
|
|
272
|
+
while (startNode.attribute && startNode.type == "child") {
|
|
273
|
+
const lookup = startNode.value;
|
|
274
|
+
if (!lookup)
|
|
275
|
+
throw new Error("Selector must have a value");
|
|
276
|
+
log.debug("STEP IN ", lookup, paths.map(p => breadCrumb(p)));
|
|
277
|
+
const nodes = paths.map(n => getChildren(lookup, n)).map(toArray).flat().filter(n => n.node != undefined);
|
|
278
|
+
log.debug("LOOKUP", lookup, path.node.type, nodes.map(n => n.node), nodes.filter(n => n.node == undefined));
|
|
279
|
+
if (nodes.length == 0)
|
|
280
|
+
return [];
|
|
281
|
+
paths = nodes;
|
|
282
|
+
if (startNode.resolve) {
|
|
283
|
+
const resolved = paths.map(p => resolveBinding(p)).filter(isDefined).map(p => getChildren("init", p)).flatMap(toArray).filter(p => p.node != undefined).filter(isDefined);
|
|
284
|
+
if (resolved.length > 0)
|
|
285
|
+
paths = resolved;
|
|
286
|
+
}
|
|
287
|
+
else if (startNode.binding) {
|
|
288
|
+
paths = paths.map(p => resolveBinding(p)).filter(isDefined);
|
|
289
|
+
}
|
|
290
|
+
const filter = startNode.filter;
|
|
291
|
+
if (filter) {
|
|
292
|
+
paths = paths.filter(p => travHandle({ subquery: filter }, p).subquery.length > 0);
|
|
293
|
+
}
|
|
294
|
+
if (!startNode.child) {
|
|
295
|
+
return paths.map(p => p.node);
|
|
296
|
+
}
|
|
297
|
+
startNode = startNode.child;
|
|
312
298
|
}
|
|
313
|
-
|
|
314
|
-
|
|
299
|
+
log.debug("DIRECT TRAV RESOLVE", startNode, paths.map(p => breadCrumb(p)));
|
|
300
|
+
const result = paths.flatMap(path => {
|
|
301
|
+
const subQueryKey = "subquery-" + subQueryCounter++;
|
|
302
|
+
return travHandle({ [subQueryKey]: startNode }, path)[subQueryKey];
|
|
303
|
+
});
|
|
304
|
+
log.debug("DIRECT TRAV RESOLVE RESULT", result);
|
|
305
|
+
return result;
|
|
306
|
+
}
|
|
307
|
+
function addResultIfTokenMatch(fnode, path, state) {
|
|
308
|
+
const filters = state.filters[state.depth].filter(f => f.node == path.node && f.qNode == fnode.node);
|
|
309
|
+
const matchingFilters = filters.filter(f => evaluateFilter(f.filter, path).length > 0);
|
|
310
|
+
log.debug("RESULT MATCH", fnode.node.value, breadCrumb(path), filters.length, matchingFilters.length);
|
|
311
|
+
if (filters.length > 0 && matchingFilters.length == 0)
|
|
312
|
+
return;
|
|
313
|
+
if (fnode.node.resolve) {
|
|
314
|
+
const binding = resolveBinding(path);
|
|
315
|
+
const resolved = binding ? getChildren("init", binding)[0] : undefined;
|
|
316
|
+
if (fnode.node.child) {
|
|
317
|
+
const result = resolveDirectly(fnode.node.child, resolved ?? path);
|
|
318
|
+
fnode.result.push(...result);
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
fnode.result.push(path.node);
|
|
322
|
+
}
|
|
315
323
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
324
|
+
else if (fnode.node.binding) {
|
|
325
|
+
const binding = resolveBinding(path);
|
|
326
|
+
if (binding) {
|
|
327
|
+
if (fnode.node.child) {
|
|
328
|
+
const result = resolveDirectly(fnode.node.child, binding);
|
|
329
|
+
fnode.result.push(...result);
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
fnode.result.push(binding.node);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
319
335
|
}
|
|
320
|
-
if (!
|
|
321
|
-
|
|
336
|
+
else if (!fnode.node.child) {
|
|
337
|
+
fnode.result.push(path.node);
|
|
322
338
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
return travHandle({ [subQueryKey]: startNode }, path)[subQueryKey];
|
|
329
|
-
});
|
|
330
|
-
log.debug("DIRECT TRAV RESOLVE RESULT", result);
|
|
331
|
-
return result;
|
|
332
|
-
}
|
|
333
|
-
function addResultIfTokenMatch(fnode, path, state) {
|
|
334
|
-
const filters = state.filters[state.depth].filter(f => f.node == path.node && f.qNode == fnode.node);
|
|
335
|
-
const matchingFilters = filters.filter(f => evaluateFilter(f.filter, path).length > 0);
|
|
336
|
-
log.debug("RESULT MATCH", fnode.node.value, breadCrumb(path), filters.length, matchingFilters.length);
|
|
337
|
-
if (filters.length > 0 && matchingFilters.length == 0)
|
|
338
|
-
return;
|
|
339
|
-
if (fnode.node.resolve) {
|
|
340
|
-
const binding = resolveBinding(path);
|
|
341
|
-
const resolved = binding ? (0, traverse_1.getChildren)("init", binding)[0] : undefined;
|
|
342
|
-
if (fnode.node.child) {
|
|
343
|
-
const result = resolveDirectly(fnode.node.child, resolved ?? path);
|
|
344
|
-
fnode.result.push(...result);
|
|
339
|
+
else if (fnode.node.child.type == "function") {
|
|
340
|
+
const functionCallResult = state.functionCalls[state.depth].find(f => f.node == fnode.node);
|
|
341
|
+
if (!functionCallResult)
|
|
342
|
+
throw new Error("Did not find expected function call for " + fnode.node.child.function);
|
|
343
|
+
resolveFunctionCalls(fnode, functionCallResult, path, state);
|
|
345
344
|
}
|
|
346
|
-
else {
|
|
347
|
-
fnode.result.
|
|
345
|
+
else if (matchingFilters.length > 0) {
|
|
346
|
+
log.debug("HAS MATCHING FILTER", fnode.result.length, matchingFilters.length, breadCrumb(path));
|
|
347
|
+
fnode.result.push(...matchingFilters.flatMap(f => f.result));
|
|
348
348
|
}
|
|
349
349
|
}
|
|
350
|
-
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
if (
|
|
354
|
-
|
|
355
|
-
|
|
350
|
+
function resolveFunctionCalls(fnode, functionCallResult, path, state) {
|
|
351
|
+
const parameterResults = [];
|
|
352
|
+
for (const p of functionCallResult.parameters) {
|
|
353
|
+
if ("parameters" in p) {
|
|
354
|
+
resolveFunctionCalls(p, p, path, state);
|
|
355
|
+
parameterResults.push(p.result);
|
|
356
356
|
}
|
|
357
357
|
else {
|
|
358
|
-
|
|
358
|
+
parameterResults.push(p.result);
|
|
359
359
|
}
|
|
360
360
|
}
|
|
361
|
+
const functionResult = exports.functions[functionCallResult.functionCall.function].fn(parameterResults);
|
|
362
|
+
log.debug("PARAMETER RESULTS", functionCallResult.functionCall.function, parameterResults, functionResult);
|
|
363
|
+
fnode.result.push(...functionResult);
|
|
361
364
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
365
|
+
function travHandle(queries, root) {
|
|
366
|
+
const results = Object.fromEntries(Object.keys(queries).map(name => [name, []]));
|
|
367
|
+
const state = {
|
|
368
|
+
depth: 0,
|
|
369
|
+
child: [[], []],
|
|
370
|
+
descendant: [[], []],
|
|
371
|
+
filters: [[], []],
|
|
372
|
+
matches: [[]],
|
|
373
|
+
functionCalls: [[]]
|
|
374
|
+
};
|
|
375
|
+
Object.entries(queries).forEach(([name, node]) => {
|
|
376
|
+
createFNodeAndAddToState(node, results[name], state);
|
|
377
|
+
});
|
|
378
|
+
state.child[state.depth + 1].forEach(fnode => addPrimitiveAttributeIfMatch(fnode, root));
|
|
379
|
+
state.descendant.slice(0, state.depth + 1).forEach(fnodes => fnodes.forEach(fnode => addPrimitiveAttributeIfMatch(fnode, root)));
|
|
380
|
+
traverse(root.node, {
|
|
381
|
+
enter(path, state) {
|
|
382
|
+
log.debug("ENTER", breadCrumb(path));
|
|
383
|
+
state.depth++;
|
|
384
|
+
state.child.push([]);
|
|
385
|
+
state.descendant.push([]);
|
|
386
|
+
state.filters.push([]);
|
|
387
|
+
state.matches.push([]);
|
|
388
|
+
state.functionCalls.push([]);
|
|
389
|
+
state.child[state.depth].forEach(fnode => addIfTokenMatch(fnode, path, state));
|
|
390
|
+
state.descendant.slice(0, state.depth + 1).forEach(fnodes => fnodes.forEach(fnode => addIfTokenMatch(fnode, path, state)));
|
|
391
|
+
},
|
|
392
|
+
exit(path, state) {
|
|
393
|
+
log.debug("EXIT", breadCrumb(path));
|
|
394
|
+
// Check for attributes as not all attributes are visited
|
|
395
|
+
state.child[state.depth + 1].forEach(fnode => addPrimitiveAttributeIfMatch(fnode, path));
|
|
396
|
+
state.descendant.forEach(fnodes => fnodes.forEach(fnode => addPrimitiveAttributeIfMatch(fnode, path)));
|
|
397
|
+
state.matches[state.depth].forEach(([fNode, path]) => addResultIfTokenMatch(fNode, path, state));
|
|
398
|
+
state.depth--;
|
|
399
|
+
state.child.pop();
|
|
400
|
+
state.descendant.pop();
|
|
401
|
+
state.filters.pop();
|
|
402
|
+
state.matches.pop();
|
|
403
|
+
state.functionCalls.pop();
|
|
404
|
+
}
|
|
405
|
+
}, root.scopeId, state, root);
|
|
406
|
+
return results;
|
|
374
407
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
for (const p of functionCallResult.parameters) {
|
|
379
|
-
if ("parameters" in p) {
|
|
380
|
-
resolveFunctionCalls(p, p, path, state);
|
|
381
|
-
parameterResults.push(p.result);
|
|
382
|
-
}
|
|
383
|
-
else {
|
|
384
|
-
parameterResults.push(p.result);
|
|
385
|
-
}
|
|
408
|
+
function beginHandle(queries, path) {
|
|
409
|
+
const rootPath = createNodePath(path, undefined, undefined, undefined);
|
|
410
|
+
return travHandle(queries, rootPath);
|
|
386
411
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
fnode.result.push(...functionResult);
|
|
390
|
-
}
|
|
391
|
-
function travHandle(queries, root) {
|
|
392
|
-
const results = Object.fromEntries(Object.keys(queries).map(name => [name, []]));
|
|
393
|
-
const state = {
|
|
394
|
-
depth: 0,
|
|
395
|
-
child: [[], []],
|
|
396
|
-
descendant: [[], []],
|
|
397
|
-
filters: [[], []],
|
|
398
|
-
matches: [[]],
|
|
399
|
-
functionCalls: [[]]
|
|
412
|
+
return {
|
|
413
|
+
beginHandle
|
|
400
414
|
};
|
|
401
|
-
Object.entries(queries).forEach(([name, node]) => {
|
|
402
|
-
createFNodeAndAddToState(node, results[name], state);
|
|
403
|
-
});
|
|
404
|
-
state.child[state.depth + 1].forEach(fnode => addPrimitiveAttributeIfMatch(fnode, root));
|
|
405
|
-
state.descendant.slice(0, state.depth + 1).forEach(fnodes => fnodes.forEach(fnode => addPrimitiveAttributeIfMatch(fnode, root)));
|
|
406
|
-
(0, traverse_1.default)(root.node, {
|
|
407
|
-
enter(path, state) {
|
|
408
|
-
log.debug("ENTER", breadCrumb(path));
|
|
409
|
-
state.depth++;
|
|
410
|
-
state.child.push([]);
|
|
411
|
-
state.descendant.push([]);
|
|
412
|
-
state.filters.push([]);
|
|
413
|
-
state.matches.push([]);
|
|
414
|
-
state.functionCalls.push([]);
|
|
415
|
-
state.child[state.depth].forEach(fnode => addIfTokenMatch(fnode, path, state));
|
|
416
|
-
state.descendant.slice(0, state.depth + 1).forEach(fnodes => fnodes.forEach(fnode => addIfTokenMatch(fnode, path, state)));
|
|
417
|
-
},
|
|
418
|
-
exit(path, state) {
|
|
419
|
-
log.debug("EXIT", breadCrumb(path));
|
|
420
|
-
// Check for attributes as not all attributes are visited
|
|
421
|
-
state.child[state.depth + 1].forEach(fnode => addPrimitiveAttributeIfMatch(fnode, path));
|
|
422
|
-
state.descendant.forEach(fnodes => fnodes.forEach(fnode => addPrimitiveAttributeIfMatch(fnode, path)));
|
|
423
|
-
state.matches[state.depth].forEach(([fNode, path]) => addResultIfTokenMatch(fNode, path, state));
|
|
424
|
-
state.depth--;
|
|
425
|
-
state.child.pop();
|
|
426
|
-
state.descendant.pop();
|
|
427
|
-
state.filters.pop();
|
|
428
|
-
state.matches.pop();
|
|
429
|
-
state.functionCalls.pop();
|
|
430
|
-
}
|
|
431
|
-
}, root.scopeId, state, root);
|
|
432
|
-
return results;
|
|
433
415
|
}
|
|
434
416
|
const defaultKey = "__default__";
|
|
435
|
-
function query(code, query) {
|
|
436
|
-
|
|
417
|
+
function query(code, query, returnAST) {
|
|
418
|
+
const result = multiQuery(code, { [defaultKey]: query }, returnAST);
|
|
419
|
+
if (returnAST) {
|
|
420
|
+
const r = result[defaultKey];
|
|
421
|
+
r.__AST = result.__AST;
|
|
422
|
+
return r;
|
|
423
|
+
}
|
|
424
|
+
return result[defaultKey];
|
|
437
425
|
}
|
|
438
426
|
exports.query = query;
|
|
439
|
-
function multiQuery(code, namedQueries) {
|
|
427
|
+
function multiQuery(code, namedQueries, returnAST) {
|
|
440
428
|
const start = Date.now();
|
|
441
429
|
const ast = typeof code == "string" ? parseSource(code) : code;
|
|
442
430
|
if (ast == null)
|
|
443
431
|
throw new Error("Could not pase code");
|
|
444
432
|
const queries = Object.fromEntries(Object.entries(namedQueries).map(([name, query]) => [name, (0, parseQuery_1.parse)(query)]));
|
|
445
|
-
const
|
|
433
|
+
const querier = createQuerier();
|
|
434
|
+
const result = querier.beginHandle(queries, ast);
|
|
446
435
|
log.debug("Query time: ", Date.now() - start);
|
|
436
|
+
if (returnAST) {
|
|
437
|
+
return { ...result, __AST: ast };
|
|
438
|
+
}
|
|
447
439
|
return result;
|
|
448
440
|
}
|
|
449
441
|
exports.multiQuery = multiQuery;
|