@eagleoutice/flowr 2.2.1 → 2.2.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.
Files changed (42) hide show
  1. package/cli/flowr.js +2 -1
  2. package/cli/repl/commands/repl-cfg.js +30 -7
  3. package/cli/repl/commands/repl-dataflow.js +22 -2
  4. package/cli/repl/commands/repl-normalize.js +22 -2
  5. package/cli/repl/commands/repl-parse.js +8 -2
  6. package/cli/repl/core.js +4 -0
  7. package/cli/repl/server/connection.js +1 -1
  8. package/cli/script-core/statistics-helper-core.js +1 -1
  9. package/config.js +8 -1
  10. package/dataflow/extractor.js +1 -1
  11. package/dataflow/graph/dataflowgraph-builder.d.ts +11 -10
  12. package/dataflow/graph/dataflowgraph-builder.js +11 -10
  13. package/dataflow/graph/edge.d.ts +1 -1
  14. package/dataflow/graph/edge.js +2 -2
  15. package/dataflow/graph/vertex.d.ts +6 -6
  16. package/dataflow/graph/vertex.js +5 -5
  17. package/dataflow/internal/process/functions/call/built-in/built-in-access.js +9 -5
  18. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +2 -2
  19. package/documentation/doc-util/doc-cfg.js +2 -2
  20. package/documentation/doc-util/doc-types.js +3 -3
  21. package/documentation/print-interface-wiki.js +0 -2
  22. package/documentation/print-query-wiki.js +30 -0
  23. package/package.json +8 -6
  24. package/queries/catalog/call-context-query/call-context-query-executor.js +1 -1
  25. package/queries/catalog/happens-before-query/happens-before-query-executor.d.ts +1 -1
  26. package/queries/catalog/happens-before-query/happens-before-query-executor.js +2 -2
  27. package/queries/catalog/resolve-value-query/resolve-value-query-executor.d.ts +4 -0
  28. package/queries/catalog/resolve-value-query/resolve-value-query-executor.js +34 -0
  29. package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +72 -0
  30. package/queries/catalog/resolve-value-query/resolve-value-query-format.js +49 -0
  31. package/queries/query.d.ts +60 -1
  32. package/queries/query.js +3 -1
  33. package/r-bridge/data/data.d.ts +2 -2
  34. package/r-bridge/data/data.js +2 -2
  35. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +46 -29
  36. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-types.d.ts +4 -1
  37. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-types.js +3 -0
  38. package/util/cfg/cfg.d.ts +10 -1
  39. package/util/cfg/cfg.js +56 -2
  40. package/util/range.d.ts +21 -0
  41. package/util/range.js +3 -0
  42. package/util/version.js +1 -1
@@ -17,6 +17,9 @@ function normalizeTreeSitterTreeToAst(tree) {
17
17
  }
18
18
  return root;
19
19
  }
20
+ function nonErrorChildren(node) {
21
+ return node.children.filter(n => n.type !== tree_sitter_types_1.TreeSitterType.Error);
22
+ }
20
23
  function convertTreeNode(node) {
21
24
  // generally, the grammar source file dictates what children a node has in what order:
22
25
  // https://github.com/r-lib/tree-sitter-r/blob/main/grammar.js
@@ -30,7 +33,7 @@ function convertTreeNode(node) {
30
33
  };
31
34
  switch (node.type) {
32
35
  case tree_sitter_types_1.TreeSitterType.Program: {
33
- const [comments, children] = splitComments(node.children);
36
+ const [comments, children] = splitComments(nonErrorChildren(node));
34
37
  const body = children.map(n => [n, convertTreeNode(n)]);
35
38
  const remainingComments = linkCommentsToNextNodes(body, comments);
36
39
  return {
@@ -45,7 +48,7 @@ function convertTreeNode(node) {
45
48
  }
46
49
  case tree_sitter_types_1.TreeSitterType.BracedExpression:
47
50
  case tree_sitter_types_1.TreeSitterType.ParenthesizedExpression: {
48
- const [comments, children] = splitComments(node.children);
51
+ const [comments, children] = splitComments(nonErrorChildren(node));
49
52
  const opening = children[0];
50
53
  const body = children.slice(1, -1).map(n => [n, convertTreeNode(n)]);
51
54
  const remainingComments = linkCommentsToNextNodes(body, comments);
@@ -78,9 +81,10 @@ function convertTreeNode(node) {
78
81
  };
79
82
  }
80
83
  case tree_sitter_types_1.TreeSitterType.BinaryOperator: {
81
- const lhs = convertTreeNode(node.children[0]);
82
- const rhs = convertTreeNode(node.children[node.children.length - 1]);
83
- const [commentsBoth, [op]] = splitComments(node.children.slice(1, -1));
84
+ const children = nonErrorChildren(node);
85
+ const lhs = convertTreeNode(children[0]);
86
+ const rhs = convertTreeNode(children[children.length - 1]);
87
+ const [commentsBoth, [op]] = splitComments(children.slice(1, -1));
84
88
  const comments = commentsBoth.map(c => c[1]);
85
89
  const opSource = makeSourceRange(op);
86
90
  const lhsAsArg = {
@@ -150,7 +154,7 @@ function convertTreeNode(node) {
150
154
  }
151
155
  }
152
156
  case tree_sitter_types_1.TreeSitterType.UnaryOperator: {
153
- const [op, operand] = node.children;
157
+ const [op, operand] = nonErrorChildren(node);
154
158
  return {
155
159
  type: type_1.RType.UnaryOp,
156
160
  operand: convertTreeNode(operand),
@@ -161,7 +165,7 @@ function convertTreeNode(node) {
161
165
  };
162
166
  }
163
167
  case tree_sitter_types_1.TreeSitterType.NamespaceOperator: {
164
- const [lhs, /* :: or ::: */ , rhs] = node.children;
168
+ const [lhs, /* :: or ::: */ , rhs] = nonErrorChildren(node);
165
169
  return {
166
170
  type: type_1.RType.Symbol,
167
171
  location: makeSourceRange(rhs),
@@ -176,6 +180,7 @@ function convertTreeNode(node) {
176
180
  case tree_sitter_types_1.TreeSitterType.Na:
177
181
  case tree_sitter_types_1.TreeSitterType.Null:
178
182
  case tree_sitter_types_1.TreeSitterType.Dots:
183
+ case tree_sitter_types_1.TreeSitterType.DotDotI:
179
184
  case tree_sitter_types_1.TreeSitterType.Identifier:
180
185
  case tree_sitter_types_1.TreeSitterType.Return:
181
186
  return {
@@ -187,22 +192,24 @@ function convertTreeNode(node) {
187
192
  ...defaultInfo
188
193
  };
189
194
  case tree_sitter_types_1.TreeSitterType.IfStatement: {
190
- const [ifNode, /* ( */ , condition, /* ) */ , then, /* else */ , ...otherwise] = node.children;
195
+ const [ifNode, /* ( */ , condition, /* ) */ , then, /* else */ , ...otherwise] = nonErrorChildren(node);
196
+ const filteredOtherwise = otherwise.filter(n => n.type !== tree_sitter_types_1.TreeSitterType.ElseStatement);
191
197
  return {
192
198
  type: type_1.RType.IfThenElse,
193
199
  condition: convertTreeNode(condition),
194
200
  then: (0, normalize_meta_1.ensureExpressionList)(convertTreeNode(then)),
195
- otherwise: otherwise.length > 0 ? (0, normalize_meta_1.ensureExpressionList)(convertTreeNode(otherwise[0])) : undefined,
201
+ otherwise: filteredOtherwise.length > 0 ? (0, normalize_meta_1.ensureExpressionList)(convertTreeNode(filteredOtherwise[0])) : undefined,
196
202
  location: makeSourceRange(ifNode),
197
203
  lexeme: ifNode.text,
198
204
  ...defaultInfo
199
205
  };
200
206
  }
201
207
  case tree_sitter_types_1.TreeSitterType.ForStatement: {
202
- const forNode = node.children[0]; // we follow with a (
203
- const variable = getNodesUntil(node.children, 'in', 2); // we follow with the "in"
204
- const sequence = getNodesUntil(node.children, ')', 2 + variable.length + 1); // we follow with a (
205
- const body = node.children[2 + variable.length + 1 + sequence.length + 1];
208
+ const children = nonErrorChildren(node);
209
+ const forNode = children[0]; // we follow with a (
210
+ const variable = getNodesUntil(children, 'in', 2); // we follow with the "in"
211
+ const sequence = getNodesUntil(children, ')', 2 + variable.length + 1); // we follow with a (
212
+ const body = children[2 + variable.length + 1 + sequence.length + 1];
206
213
  const [variableComments, [variableNode]] = splitComments(variable);
207
214
  const [sequenceComments, [sequenceNode]] = splitComments(sequence);
208
215
  return {
@@ -231,7 +238,7 @@ function convertTreeNode(node) {
231
238
  };
232
239
  }
233
240
  case tree_sitter_types_1.TreeSitterType.WhileStatement: {
234
- const [whileNode, /* ( */ , condition, /* ) */ , body] = node.children;
241
+ const [whileNode, /* ( */ , condition, /* ) */ , body] = nonErrorChildren(node);
235
242
  return {
236
243
  type: type_1.RType.WhileLoop,
237
244
  condition: convertTreeNode(condition),
@@ -242,7 +249,7 @@ function convertTreeNode(node) {
242
249
  };
243
250
  }
244
251
  case tree_sitter_types_1.TreeSitterType.RepeatStatement: {
245
- const [repeatNode, body] = node.children;
252
+ const [repeatNode, body] = nonErrorChildren(node);
246
253
  return {
247
254
  type: type_1.RType.RepeatLoop,
248
255
  body: (0, normalize_meta_1.ensureExpressionList)(convertTreeNode(body)),
@@ -252,7 +259,7 @@ function convertTreeNode(node) {
252
259
  };
253
260
  }
254
261
  case tree_sitter_types_1.TreeSitterType.Call: {
255
- const [func, argsParentheses] = node.children;
262
+ const [func, argsParentheses] = nonErrorChildren(node);
256
263
  // tree-sitter wraps next and break in a function call, but we don't, so unwrap
257
264
  if (func.type === tree_sitter_types_1.TreeSitterType.Next || func.type == tree_sitter_types_1.TreeSitterType.Break) {
258
265
  return {
@@ -260,7 +267,7 @@ function convertTreeNode(node) {
260
267
  ...defaultInfo
261
268
  };
262
269
  }
263
- const args = (0, arrays_1.splitArrayOn)(argsParentheses.children.slice(1, -1), x => x.type === 'comma');
270
+ const args = (0, arrays_1.splitArrayOn)(nonErrorChildren(argsParentheses).slice(1, -1), x => x.type === 'comma');
264
271
  const funcRange = makeSourceRange(func);
265
272
  const call = {
266
273
  arguments: args.map(n => n.length == 0 ? r_function_call_1.EmptyArgument : convertTreeNode(n[0])),
@@ -302,7 +309,7 @@ function convertTreeNode(node) {
302
309
  }
303
310
  }
304
311
  case tree_sitter_types_1.TreeSitterType.FunctionDefinition: {
305
- const [name, paramsParens, body] = node.children;
312
+ const [name, paramsParens, body] = nonErrorChildren(node);
306
313
  const params = (0, arrays_1.splitArrayOn)(paramsParens.children.slice(1, -1), x => x.type === 'comma');
307
314
  return {
308
315
  type: type_1.RType.FunctionDefinition,
@@ -353,9 +360,9 @@ function convertTreeNode(node) {
353
360
  case tree_sitter_types_1.TreeSitterType.Subset:
354
361
  case tree_sitter_types_1.TreeSitterType.Subset2: {
355
362
  // subset has children like a and [x]
356
- const [func, content] = node.children;
363
+ const [func, content] = nonErrorChildren(node);
357
364
  // bracket is now [ or [[ and argsClosing is x] or x]]
358
- const [bracket, ...argsClosing] = content.children;
365
+ const [bracket, ...argsClosing] = nonErrorChildren(content);
359
366
  const args = (0, arrays_1.splitArrayOn)(argsClosing.slice(0, -1), x => x.type === 'comma');
360
367
  return {
361
368
  type: type_1.RType.Access,
@@ -368,7 +375,7 @@ function convertTreeNode(node) {
368
375
  };
369
376
  }
370
377
  case tree_sitter_types_1.TreeSitterType.ExtractOperator: {
371
- const [lhs, operator, rhs] = node.children;
378
+ const [lhs, operator, rhs] = nonErrorChildren(node);
372
379
  const rhsRange = makeSourceRange(rhs);
373
380
  return {
374
381
  type: type_1.RType.Access,
@@ -395,11 +402,12 @@ function convertTreeNode(node) {
395
402
  };
396
403
  }
397
404
  case tree_sitter_types_1.TreeSitterType.Parameter: {
398
- const name = node.children[0];
405
+ const children = nonErrorChildren(node);
406
+ const name = children[0];
399
407
  const nameRange = makeSourceRange(name);
400
408
  let defaultValue = undefined;
401
- if (node.children.length == 3) {
402
- defaultValue = convertTreeNode(node.children[2]);
409
+ if (children.length == 3) {
410
+ defaultValue = convertTreeNode(children[2]);
403
411
  }
404
412
  return {
405
413
  type: type_1.RType.Parameter,
@@ -427,8 +435,9 @@ function convertTreeNode(node) {
427
435
  };
428
436
  }
429
437
  case tree_sitter_types_1.TreeSitterType.Argument: {
430
- if (node.children.length == 1) {
431
- const [arg] = node.children;
438
+ const children = nonErrorChildren(node);
439
+ if (children.length == 1) {
440
+ const [arg] = children;
432
441
  return {
433
442
  type: type_1.RType.Argument,
434
443
  name: undefined,
@@ -439,7 +448,7 @@ function convertTreeNode(node) {
439
448
  };
440
449
  }
441
450
  else {
442
- const [nameNode, /* = */ , valueNode] = node.children;
451
+ const [nameNode, /* = */ , valueNode] = children;
443
452
  let name = convertTreeNode(nameNode);
444
453
  // unescape argument names
445
454
  if (name.type === type_1.RType.String) {
@@ -457,7 +466,7 @@ function convertTreeNode(node) {
457
466
  return {
458
467
  type: type_1.RType.Argument,
459
468
  name: name,
460
- value: convertTreeNode(valueNode),
469
+ value: valueNode ? convertTreeNode(valueNode) : undefined,
461
470
  location: nameRange,
462
471
  lexeme: nameNode.text,
463
472
  info: {
@@ -468,8 +477,16 @@ function convertTreeNode(node) {
468
477
  };
469
478
  }
470
479
  }
480
+ case tree_sitter_types_1.TreeSitterType.Comment:
481
+ return {
482
+ type: type_1.RType.Comment,
483
+ location: range,
484
+ content: node.text.slice(1),
485
+ lexeme: node.text,
486
+ ...defaultInfo
487
+ };
471
488
  default:
472
- throw new normalizer_data_1.ParseError(`unexpected node type ${node.type}`);
489
+ throw new normalizer_data_1.ParseError(`unexpected node type ${node.type} at ${JSON.stringify(range)}`);
473
490
  }
474
491
  }
475
492
  function makeSourceRange(node) {
@@ -7,6 +7,7 @@ export declare enum TreeSitterType {
7
7
  NamespaceOperator = "namespace_operator",
8
8
  Identifier = "identifier",
9
9
  IfStatement = "if_statement",
10
+ ElseStatement = "else",
10
11
  ForStatement = "for_statement",
11
12
  WhileStatement = "while_statement",
12
13
  RepeatStatement = "repeat_statement",
@@ -31,5 +32,7 @@ export declare enum TreeSitterType {
31
32
  Parameter = "parameter",
32
33
  Argument = "argument",
33
34
  Dots = "dots",
34
- Comment = "comment"
35
+ DotDotI = "dot_dot_i",
36
+ Comment = "comment",
37
+ Error = "ERROR"
35
38
  }
@@ -11,6 +11,7 @@ var TreeSitterType;
11
11
  TreeSitterType["NamespaceOperator"] = "namespace_operator";
12
12
  TreeSitterType["Identifier"] = "identifier";
13
13
  TreeSitterType["IfStatement"] = "if_statement";
14
+ TreeSitterType["ElseStatement"] = "else";
14
15
  TreeSitterType["ForStatement"] = "for_statement";
15
16
  TreeSitterType["WhileStatement"] = "while_statement";
16
17
  TreeSitterType["RepeatStatement"] = "repeat_statement";
@@ -35,6 +36,8 @@ var TreeSitterType;
35
36
  TreeSitterType["Parameter"] = "parameter";
36
37
  TreeSitterType["Argument"] = "argument";
37
38
  TreeSitterType["Dots"] = "dots";
39
+ TreeSitterType["DotDotI"] = "dot_dot_i";
38
40
  TreeSitterType["Comment"] = "comment";
41
+ TreeSitterType["Error"] = "ERROR";
39
42
  })(TreeSitterType || (exports.TreeSitterType = TreeSitterType = {}));
40
43
  //# sourceMappingURL=tree-sitter-types.js.map
package/util/cfg/cfg.d.ts CHANGED
@@ -3,6 +3,7 @@ import type { QuadSerializationConfiguration } from '../quads';
3
3
  import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
4
4
  import type { NormalizedAst, ParentInformation } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
5
5
  import { RFalse, RTrue } from '../../r-bridge/lang-4.x/convert-values';
6
+ import type { DataflowGraph } from '../../dataflow/graph/graph';
6
7
  export declare const enum CfgVertexType {
7
8
  /** Marks a break point in a construct (e.g., between the name and the value of an argument, or the formals and the body of a function) */
8
9
  MidMarker = "mid-marker",
@@ -57,7 +58,15 @@ export interface ControlFlowInformation extends MergeableRecord {
57
58
  graph: ControlFlowGraph;
58
59
  }
59
60
  export declare function emptyControlFlowInformation(): ControlFlowInformation;
60
- export declare function extractCFG<Info = ParentInformation>(ast: NormalizedAst<Info>): ControlFlowInformation;
61
+ /**
62
+ * Given a normalized AST this approximates the control flow graph of the program.
63
+ * This few is different from the computation of the dataflow graph and may differ,
64
+ * especially because it focuses on intra-procedural analysis.
65
+ *
66
+ * @param ast - the normalized AST
67
+ * @param graph - additional dataflow facts to consider by the control flow extraction
68
+ */
69
+ export declare function extractCFG<Info = ParentInformation>(ast: NormalizedAst<Info>, graph?: DataflowGraph): ControlFlowInformation;
61
70
  /**
62
71
  * Returns true if the given CFG equals the other CFG. False otherwise.
63
72
  */
package/util/cfg/cfg.js CHANGED
@@ -12,6 +12,8 @@ const json_1 = require("../json");
12
12
  const fold_1 = require("../../r-bridge/lang-4.x/ast/model/processing/fold");
13
13
  const convert_values_1 = require("../../r-bridge/lang-4.x/convert-values");
14
14
  const r_function_call_1 = require("../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
15
+ const linker_1 = require("../../dataflow/internal/linker");
16
+ const vertex_1 = require("../../dataflow/graph/vertex");
15
17
  /**
16
18
  * This class represents the control flow graph of an R program.
17
19
  * The control flow may be hierarchical when confronted with function definitions (see {@link CfgVertex} and {@link CFG#rootVertexIds|rootVertexIds()}).
@@ -101,8 +103,25 @@ const cfgFolds = {
101
103
  foldArgument: cfgArgumentOrParameter
102
104
  }
103
105
  };
104
- function extractCFG(ast) {
105
- return (0, fold_1.foldAst)(ast.ast, cfgFolds);
106
+ function dataflowCfgFolds(dataflowGraph) {
107
+ return {
108
+ ...cfgFolds,
109
+ functions: {
110
+ ...cfgFolds.functions,
111
+ foldFunctionCall: cfgFunctionCallWithDataflow(dataflowGraph)
112
+ }
113
+ };
114
+ }
115
+ /**
116
+ * Given a normalized AST this approximates the control flow graph of the program.
117
+ * This few is different from the computation of the dataflow graph and may differ,
118
+ * especially because it focuses on intra-procedural analysis.
119
+ *
120
+ * @param ast - the normalized AST
121
+ * @param graph - additional dataflow facts to consider by the control flow extraction
122
+ */
123
+ function extractCFG(ast, graph) {
124
+ return (0, fold_1.foldAst)(ast.ast, graph ? dataflowCfgFolds(graph) : cfgFolds);
106
125
  }
107
126
  function cfgLeaf(type) {
108
127
  return (leaf) => {
@@ -253,6 +272,9 @@ function cfgFunctionDefinition(fn, params, body) {
253
272
  graph.addEdge(fn.info.id + '-params', exit, { label: 'FD' });
254
273
  }
255
274
  }
275
+ if (params.length === 0) {
276
+ graph.addEdge(fn.info.id + '-params', fn.info.id, { label: 'FD' });
277
+ }
256
278
  for (const entry of body.entryPoints) {
257
279
  graph.addEdge(entry, fn.info.id + '-params', { label: 'FD' });
258
280
  }
@@ -296,6 +318,38 @@ function cfgFunctionCall(call, name, args) {
296
318
  // should not contain any breaks, nexts, or returns, (except for the body if something like 'break()')
297
319
  return info;
298
320
  }
321
+ function cfgFunctionCallWithDataflow(graph) {
322
+ return (call, name, args) => {
323
+ const baseCFG = cfgFunctionCall(call, name, args);
324
+ /* try to resolve the call and link the target definitions */
325
+ const targets = (0, linker_1.getAllFunctionCallTargets)(call.info.id, graph);
326
+ const exits = [];
327
+ for (const target of targets) {
328
+ // we have to filter out non func-call targets as the call targets contains names and call ids
329
+ if ((0, vertex_1.isFunctionDefinitionVertex)(graph.getVertex(target))) {
330
+ baseCFG.graph.addEdge(call.info.id, target, { label: 'FD' });
331
+ exits.push(target + '-exit');
332
+ }
333
+ }
334
+ if (exits.length > 0) {
335
+ baseCFG.graph.addVertex({
336
+ id: call.info.id + '-resolved-call-exit',
337
+ name: 'resolved-call-exit',
338
+ type: "end-marker" /* CfgVertexType.EndMarker */
339
+ });
340
+ for (const exit of [...baseCFG.exitPoints, ...exits]) {
341
+ baseCFG.graph.addEdge(call.info.id + '-resolved-call-exit', exit, { label: 'FD' });
342
+ }
343
+ return {
344
+ ...baseCFG,
345
+ exitPoints: [call.info.id + '-resolved-call-exit']
346
+ };
347
+ }
348
+ else {
349
+ return baseCFG;
350
+ }
351
+ };
352
+ }
299
353
  function cfgArgumentOrParameter(node, name, value) {
300
354
  const graph = new ControlFlowGraph();
301
355
  const info = { graph, breaks: [], nexts: [], returns: [], exitPoints: [node.info.id + '-exit'], entryPoints: [node.info.id] };
package/util/range.d.ts CHANGED
@@ -1,9 +1,27 @@
1
+ /**
2
+ * A source position in a file.
3
+ *
4
+ * Please note that some packages like `xmlparsedata` use their own start and end only to break ties
5
+ * (e.g., `xmlparsedata` calculates them on a max col width approximation)
6
+ */
1
7
  export type SourcePosition = [
2
8
  /** starts with 1 */
3
9
  line: number,
4
10
  /** starts with 1 */
5
11
  column: number
6
12
  ];
13
+ /**
14
+ * Describe the start and end {@link SourcePosition|source position} of an element.
15
+ *
16
+ * @see {@link rangeFrom} - to create a range
17
+ * @see {@link mergeRanges} - to merge multiple ranges
18
+ * @see {@link getRangeStart} - to get the start of a range
19
+ * @see {@link getRangeEnd} - to get the end of a range
20
+ * @see {@link rangeStartsCompletelyBefore} - to check if one range starts before another
21
+ * @see {@link rangesOverlap} - to check if two ranges overlap
22
+ * @see {@link addRanges} - to add two ranges
23
+ * @see {@link rangeCompare} - to compare two ranges
24
+ */
7
25
  export type SourceRange = [
8
26
  /** inclusive start position */
9
27
  startLine: number,
@@ -36,6 +54,9 @@ export declare function rangeStartsCompletelyBefore([, , r1el, r1ec]: SourceRang
36
54
  * Checks if the two ranges overlap.
37
55
  */
38
56
  export declare function rangesOverlap([r1sl, r1sc, r1el, r1ec]: SourceRange, [r2sl, r2sc, r2el, r2ec]: SourceRange): boolean;
57
+ /**
58
+ * Calculate the component-wise sum of two ranges
59
+ */
39
60
  export declare function addRanges([r1sl, r1sc, r1el, r1ec]: SourceRange, [r2sl, r2sc, r2el, r2ec]: SourceRange): SourceRange;
40
61
  /**
41
62
  * Provides a comparator for {@link SourceRange}s that sorts them in ascending order.
package/util/range.js CHANGED
@@ -45,6 +45,9 @@ function rangeStartsCompletelyBefore([, , r1el, r1ec], [r2sl, r2sc, ,]) {
45
45
  function rangesOverlap([r1sl, r1sc, r1el, r1ec], [r2sl, r2sc, r2el, r2ec]) {
46
46
  return r1sl <= r2el && r2sl <= r1el && r1sc <= r2ec && r2sc <= r1ec;
47
47
  }
48
+ /**
49
+ * Calculate the component-wise sum of two ranges
50
+ */
48
51
  function addRanges([r1sl, r1sc, r1el, r1ec], [r2sl, r2sc, r2el, r2ec]) {
49
52
  return [r1sl + r2sl, r1sc + r2sc, r1el + r2el, r1ec + r2ec];
50
53
  }
package/util/version.js CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.flowrVersion = flowrVersion;
4
4
  const semver_1 = require("semver");
5
5
  // this is automatically replaced with the current version by release-it
6
- const version = '2.2.1';
6
+ const version = '2.2.2';
7
7
  function flowrVersion() {
8
8
  return new semver_1.SemVer(version);
9
9
  }