@eagleoutice/flowr 2.7.5 → 2.7.6

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 CHANGED
@@ -24,7 +24,7 @@ It offers a wide variety of features, for example:
24
24
 
25
25
  ```shell
26
26
  $ docker run -it --rm eagleoutice/flowr # or npm run flowr
27
- flowR repl using flowR v2.7.4, R grammar v14 (tree-sitter engine)
27
+ flowR repl using flowR v2.7.5, R grammar v14 (tree-sitter engine)
28
28
  R> :query @linter "read.csv(\"/root/x.txt\")"
29
29
  ```
30
30
 
@@ -33,19 +33,19 @@ It offers a wide variety of features, for example:
33
33
 
34
34
 
35
35
  ```text
36
- Query: linter (2 ms)
36
+ Query: linter (1 ms)
37
37
  ╰ **Deprecated Functions** (deprecated-functions):
38
38
  ╰ _Metadata_: <code>{"totalCalls":0,"totalFunctionDefinitions":0,"searchTimeMs":0,"processTimeMs":0}</code>
39
39
  ╰ **File Path Validity** (file-path-validity):
40
40
  ╰ certain:
41
41
  ╰ Path `/root/x.txt` at 1.1-23
42
- ╰ _Metadata_: <code>{"totalReads":1,"totalUnknown":0,"totalWritesBeforeAlways":0,"totalValid":0,"searchTimeMs":1,"processTimeMs":0}</code>
42
+ ╰ _Metadata_: <code>{"totalReads":1,"totalUnknown":0,"totalWritesBeforeAlways":0,"totalValid":0,"searchTimeMs":0,"processTimeMs":0}</code>
43
43
  ╰ **Seeded Randomness** (seeded-randomness):
44
44
  ╰ _Metadata_: <code>{"consumerCalls":0,"callsWithFunctionProducers":0,"callsWithAssignmentProducers":0,"callsWithNonConstantProducers":0,"callsWithOtherBranchProducers":0,"searchTimeMs":0,"processTimeMs":0}</code>
45
45
  ╰ **Absolute Paths** (absolute-file-paths):
46
46
  ╰ certain:
47
47
  ╰ Path `/root/x.txt` at 1.1-23
48
- ╰ _Metadata_: <code>{"totalConsidered":1,"totalUnknown":0,"searchTimeMs":0,"processTimeMs":0}</code>
48
+ ╰ _Metadata_: <code>{"totalConsidered":1,"totalUnknown":0,"searchTimeMs":1,"processTimeMs":0}</code>
49
49
  ╰ **Unused Definitions** (unused-definitions):
50
50
  ╰ _Metadata_: <code>{"totalConsidered":0,"searchTimeMs":0,"processTimeMs":0}</code>
51
51
  ╰ **Naming Convention** (naming-convention):
@@ -53,12 +53,12 @@ It offers a wide variety of features, for example:
53
53
  ╰ **Network Functions** (network-functions):
54
54
  ╰ _Metadata_: <code>{"totalCalls":0,"totalFunctionDefinitions":0,"searchTimeMs":0,"processTimeMs":0}</code>
55
55
  ╰ **Dataframe Access Validation** (dataframe-access-validation):
56
- ╰ _Metadata_: <code>{"numOperations":0,"numAccesses":0,"totalAccessed":0,"searchTimeMs":0,"processTimeMs":1}</code>
56
+ ╰ _Metadata_: <code>{"numOperations":0,"numAccesses":0,"totalAccessed":0,"searchTimeMs":0,"processTimeMs":0}</code>
57
57
  ╰ **Dead Code** (dead-code):
58
58
  ╰ _Metadata_: <code>{"consideredNodes":5,"searchTimeMs":0,"processTimeMs":0}</code>
59
59
  ╰ **Useless Loops** (useless-loop):
60
60
  ╰ _Metadata_: <code>{"numOfUselessLoops":0,"searchTimeMs":0,"processTimeMs":0}</code>
61
- All queries together required ≈2 ms (1ms accuracy, total 2 ms)
61
+ All queries together required ≈1 ms (1ms accuracy, total 2 ms)
62
62
  ```
63
63
 
64
64
 
@@ -82,7 +82,7 @@ It offers a wide variety of features, for example:
82
82
 
83
83
  Query: **linter** (3 ms)\
84
84
  &nbsp;&nbsp;&nbsp;╰ **Deprecated Functions** (deprecated-functions):\
85
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>{"totalCalls":0,"totalFunctionDefinitions":0,"searchTimeMs":1,"processTimeMs":0}</code>\
85
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>{"totalCalls":0,"totalFunctionDefinitions":0,"searchTimeMs":0,"processTimeMs":0}</code>\
86
86
  &nbsp;&nbsp;&nbsp;╰ **File Path Validity** (file-path-validity):\
87
87
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ certain:\
88
88
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ Path `/root/x.txt` at 1.1-23\
@@ -92,7 +92,7 @@ It offers a wide variety of features, for example:
92
92
  &nbsp;&nbsp;&nbsp;╰ **Absolute Paths** (absolute-file-paths):\
93
93
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ certain:\
94
94
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ Path `/root/x.txt` at 1.1-23\
95
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>{"totalConsidered":1,"totalUnknown":0,"searchTimeMs":0,"processTimeMs":0}</code>\
95
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>{"totalConsidered":1,"totalUnknown":0,"searchTimeMs":1,"processTimeMs":0}</code>\
96
96
  &nbsp;&nbsp;&nbsp;╰ **Unused Definitions** (unused-definitions):\
97
97
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>{"totalConsidered":0,"searchTimeMs":0,"processTimeMs":0}</code>\
98
98
  &nbsp;&nbsp;&nbsp;╰ **Naming Convention** (naming-convention):\
@@ -100,7 +100,7 @@ It offers a wide variety of features, for example:
100
100
  &nbsp;&nbsp;&nbsp;╰ **Network Functions** (network-functions):\
101
101
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>{"totalCalls":0,"totalFunctionDefinitions":0,"searchTimeMs":0,"processTimeMs":0}</code>\
102
102
  &nbsp;&nbsp;&nbsp;╰ **Dataframe Access Validation** (dataframe-access-validation):\
103
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>{"numOperations":0,"numAccesses":0,"totalAccessed":0,"searchTimeMs":0,"processTimeMs":1}</code>\
103
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>{"numOperations":0,"numAccesses":0,"totalAccessed":0,"searchTimeMs":0,"processTimeMs":0}</code>\
104
104
  &nbsp;&nbsp;&nbsp;╰ **Dead Code** (dead-code):\
105
105
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>{"consideredNodes":5,"searchTimeMs":0,"processTimeMs":0}</code>\
106
106
  &nbsp;&nbsp;&nbsp;╰ **Useless Loops** (useless-loop):\
@@ -109,7 +109,7 @@ It offers a wide variety of features, for example:
109
109
 
110
110
  <details> <summary style="color:gray">Show Detailed Results as Json</summary>
111
111
 
112
- The analysis required _3.0 ms_ (including parsing and normalization and the query) within the generation environment.
112
+ The analysis required _3.2 ms_ (including parsing and normalization and the query) within the generation environment.
113
113
 
114
114
  In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR.
115
115
  Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those.
@@ -126,7 +126,7 @@ It offers a wide variety of features, for example:
126
126
  ".meta": {
127
127
  "totalCalls": 0,
128
128
  "totalFunctionDefinitions": 0,
129
- "searchTimeMs": 1,
129
+ "searchTimeMs": 0,
130
130
  "processTimeMs": 0
131
131
  }
132
132
  },
@@ -180,7 +180,7 @@ It offers a wide variety of features, for example:
180
180
  ".meta": {
181
181
  "totalConsidered": 1,
182
182
  "totalUnknown": 0,
183
- "searchTimeMs": 0,
183
+ "searchTimeMs": 1,
184
184
  "processTimeMs": 0
185
185
  }
186
186
  },
@@ -217,7 +217,7 @@ It offers a wide variety of features, for example:
217
217
  "numAccesses": 0,
218
218
  "totalAccessed": 0,
219
219
  "searchTimeMs": 0,
220
- "processTimeMs": 1
220
+ "processTimeMs": 0
221
221
  }
222
222
  },
223
223
  "dead-code": {
@@ -307,7 +307,7 @@ It offers a wide variety of features, for example:
307
307
 
308
308
  ```shell
309
309
  $ docker run -it --rm eagleoutice/flowr # or npm run flowr
310
- flowR repl using flowR v2.7.4, R grammar v14 (tree-sitter engine)
310
+ flowR repl using flowR v2.7.5, R grammar v14 (tree-sitter engine)
311
311
  R> :query @static-slice (11@sum) file://test/testfiles/example.R
312
312
  ```
313
313
 
@@ -321,7 +321,7 @@ It offers a wide variety of features, for example:
321
321
  N <- 10
322
322
  for(i in 1:(N-1)) sum <- sum + i + w
323
323
  sum
324
- All queries together required ≈2 ms (1ms accuracy, total 3 ms)
324
+ All queries together required ≈2 ms (1ms accuracy, total 2 ms)
325
325
  ```
326
326
 
327
327
 
@@ -355,7 +355,7 @@ It offers a wide variety of features, for example:
355
355
 
356
356
 
357
357
  * 🚀 **fast data- and control-flow graphs**\
358
- Within just <i><span title="This measurement is automatically fetched from the latest benchmark!">117.6 ms</span></i> (as of Dec 22, 2025),
358
+ Within just <i><span title="This measurement is automatically fetched from the latest benchmark!">122.3 ms</span></i> (as of Dec 23, 2025),
359
359
  _flowR_ can analyze the data- and control-flow of the average real-world R script. See the [benchmarks](https://flowr-analysis.github.io/flowr/wiki/stats/benchmark) for more information,
360
360
  and consult the [wiki pages](https://github.com/flowr-analysis/flowr/wiki/Dataflow-Graph) for more details on the dataflow graph.
361
361
 
@@ -391,7 +391,7 @@ It offers a wide variety of features, for example:
391
391
 
392
392
  ```shell
393
393
  $ docker run -it --rm eagleoutice/flowr # or npm run flowr
394
- flowR repl using flowR v2.7.4, R grammar v14 (tree-sitter engine)
394
+ flowR repl using flowR v2.7.5, R grammar v14 (tree-sitter engine)
395
395
  R> :dataflow* test/testfiles/example.R
396
396
  ```
397
397
 
@@ -696,7 +696,7 @@ It offers a wide variety of features, for example:
696
696
  ```
697
697
 
698
698
 
699
- (The analysis required _2.7 ms_ (including parse and normalize, using the [tree-sitter](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment.)
699
+ (The analysis required _2.1 ms_ (including parse and normalize, using the [tree-sitter](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment.)
700
700
 
701
701
 
702
702
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eagleoutice/flowr",
3
- "version": "2.7.5",
3
+ "version": "2.7.6",
4
4
  "description": "Static Dataflow Analyzer and Program Slicer for the R Programming Language",
5
5
  "types": "dist/src/index.d.ts",
6
6
  "repository": {
@@ -178,7 +178,6 @@
178
178
  "@types/object-hash": "^3.0.6",
179
179
  "@types/seedrandom": "^3.0.8",
180
180
  "@types/semver": "^7.7.0",
181
- "@types/spdx-expression-parse": "^3.0.5",
182
181
  "@types/tmp": "^0.2.6",
183
182
  "@types/ws": "^8.18.1",
184
183
  "@typescript-eslint/eslint-plugin": "^8.40.0",
@@ -216,7 +215,6 @@
216
215
  "rotating-file-stream": "^3.2.6",
217
216
  "seedrandom": "^3.0.5",
218
217
  "semver": "^7.7.1",
219
- "spdx-expression-parse": "^4.0.0",
220
218
  "tar": "^7.4.3",
221
219
  "tmp": "^0.2.3",
222
220
  "ts-essentials": "^10.1.1",
@@ -1,7 +1,7 @@
1
1
  import { type FlowrFileProvider, type FileRole, FlowrFile } from '../../../context/flowr-file';
2
- import type { Info } from 'spdx-expression-parse';
3
2
  import type { RAuthorInfo } from '../../../../util/r-author';
4
3
  import type { DeepReadonly } from 'ts-essentials';
4
+ import type { RLicenseElementInfo } from '../../../../util/r-license';
5
5
  export type DCF = Map<string, string[]>;
6
6
  /**
7
7
  * This decorates a text file and provides access to its content as a DCF (Debian Control File)-like structure.
@@ -25,7 +25,7 @@ export declare class FlowrDescriptionFile extends FlowrFile<DeepReadonly<DCF>> {
25
25
  /**
26
26
  * Returns the parsed license information from the 'License' field in the DESCRIPTION file.
27
27
  */
28
- license(): Info[] | undefined;
28
+ license(): RLicenseElementInfo[] | undefined;
29
29
  /**
30
30
  * Returns the parsed authors from the `Authors@R` field in the DESCRIPTION file.
31
31
  */
@@ -36,4 +36,4 @@ export declare class FlowrDescriptionFile extends FlowrFile<DeepReadonly<DCF>> {
36
36
  * @param licenseField - The 'License' field from the DESCRIPTION file as an array of strings.
37
37
  * @returns An array of SPDX license information objects if parsing was successful.
38
38
  */
39
- export declare function parseRLicenseField(...licenseField: string[]): Info[];
39
+ export declare function parseRLicenseField(...licenseField: string[]): RLicenseElementInfo[];
@@ -1,15 +1,11 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.FlowrDescriptionFile = void 0;
7
4
  exports.parseRLicenseField = parseRLicenseField;
8
5
  const flowr_file_1 = require("../../../context/flowr-file");
9
- const spdx_expression_parse_1 = __importDefault(require("spdx-expression-parse"));
10
- const log_1 = require("../../../../util/log");
11
6
  const r_author_1 = require("../../../../util/r-author");
12
7
  const args_1 = require("../../../../util/text/args");
8
+ const r_license_1 = require("../../../../util/r-license");
13
9
  /**
14
10
  * This decorates a text file and provides access to its content as a DCF (Debian Control File)-like structure.
15
11
  */
@@ -58,32 +54,13 @@ class FlowrDescriptionFile extends flowr_file_1.FlowrFile {
58
54
  }
59
55
  }
60
56
  exports.FlowrDescriptionFile = FlowrDescriptionFile;
61
- function cleanUpDescLicense(licenseStr) {
62
- // we have to replace '\s[|+&]\s' with ' OR ' or ' AND ' respectively
63
- return licenseStr
64
- .replaceAll(/\s*\|\s*/g, ' OR ')
65
- .replaceAll(/\s*[&+,]\s*/g, ' AND ')
66
- // we have to replace any variant of 'file LICENSE' with just LicenseRef-FILE
67
- .replaceAll(/file(\s+|-)LICENSE/gi, 'LicenseRef-FILE');
68
- }
69
57
  /**
70
58
  * Parses the 'License' field from an R DESCRIPTION file into SPDX license expressions.
71
59
  * @param licenseField - The 'License' field from the DESCRIPTION file as an array of strings.
72
60
  * @returns An array of SPDX license information objects if parsing was successful.
73
61
  */
74
62
  function parseRLicenseField(...licenseField) {
75
- const licenses = [];
76
- for (const licenseEntry of licenseField) {
77
- const cleanedLicense = cleanUpDescLicense(licenseEntry);
78
- try {
79
- const parsed = (0, spdx_expression_parse_1.default)(cleanedLicense);
80
- licenses.push(parsed);
81
- }
82
- catch (e) {
83
- log_1.log.warn(`Failed to parse license expression '${cleanedLicense}': ${e.message}`);
84
- }
85
- }
86
- return licenses;
63
+ return licenseField.map(r_license_1.parseRLicense);
87
64
  }
88
65
  function emplaceDCF(key, val, result) {
89
66
  if (!key) {
@@ -2,7 +2,7 @@ import type { BaseQueryFormat, BaseQueryResult } from '../../base-query-format';
2
2
  import { executeProjectQuery } from './project-query-executor';
3
3
  import Joi from 'joi';
4
4
  import type { RAuthorInfo } from '../../../util/r-author';
5
- import type { Info } from 'spdx-expression-parse';
5
+ import type { RLicenseElementInfo } from '../../../util/r-license';
6
6
  export interface ProjectQuery extends BaseQueryFormat {
7
7
  readonly type: 'project';
8
8
  /** Whether to include Dataflow information in the result. */
@@ -14,7 +14,7 @@ export interface ProjectQueryResult extends BaseQueryResult {
14
14
  /** The files considered part of the project. */
15
15
  readonly files: (string | '<inline>')[];
16
16
  /** The licenses of the project. */
17
- readonly licenses?: Info[];
17
+ readonly licenses?: RLicenseElementInfo[];
18
18
  /** The encoding of the project files. */
19
19
  readonly encoding?: string;
20
20
  /** The version of the project, if available. */
@@ -0,0 +1,23 @@
1
+ import { Range } from 'semver';
2
+ export interface RLicenseInfo {
3
+ type: 'license';
4
+ license: string;
5
+ versionConstraint?: Range;
6
+ }
7
+ export interface RLicenseExceptionInfo {
8
+ type: 'exception';
9
+ exception: string;
10
+ }
11
+ export interface RLicenseCombinationInfo {
12
+ type: 'combination';
13
+ combination: 'and' | 'or' | 'with';
14
+ elements: [left: RLicenseElementInfo, right: RLicenseElementInfo];
15
+ }
16
+ export interface NoLicenseInfo {
17
+ type: 'no-license';
18
+ }
19
+ export type RLicenseElementInfo = RLicenseInfo | RLicenseExceptionInfo | RLicenseCombinationInfo | NoLicenseInfo;
20
+ /**
21
+ * Parses an R license string into its structured representation.
22
+ */
23
+ export declare function parseRLicense(licenseString: string): RLicenseElementInfo;
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseRLicense = parseRLicense;
4
+ const semver_1 = require("semver");
5
+ const assert_1 = require("./assert");
6
+ const objects_1 = require("./objects");
7
+ /**
8
+ * Parses an R license string into its structured representation.
9
+ */
10
+ function parseRLicense(licenseString) {
11
+ const start = skipWhitespace({ position: 0, remInput: licenseString });
12
+ const parsed = parseLicenseInfo(start);
13
+ return parsed.element;
14
+ }
15
+ function parseLicenseInfo(info) {
16
+ info = skipWhitespace(info);
17
+ if (info.remInput.length === 0) {
18
+ return { ...info, element: { type: 'no-license' } };
19
+ }
20
+ else if (info.remInput.startsWith('(')) {
21
+ return parseParenthesizedExpression(info);
22
+ }
23
+ else {
24
+ return parseBinaryOperator(info);
25
+ }
26
+ }
27
+ function parseParenthesizedExpression(info) {
28
+ const openParen = consumeString(info, '(');
29
+ (0, assert_1.guard)(openParen.element, `Expected (, but found ${info.remInput[0]} at position ${info.position}`);
30
+ const innerInfo = parseLicenseInfo(openParen);
31
+ const closeParen = consumeString(innerInfo, ')');
32
+ (0, assert_1.guard)(closeParen.element, `Expected ), but found ${innerInfo.remInput[0]} at position ${innerInfo.position}`);
33
+ return { ...closeParen, element: innerInfo.element };
34
+ }
35
+ function skipWhitespace({ remInput, position }) {
36
+ let idx = remInput.search(/\S/);
37
+ if (idx === -1) {
38
+ idx = remInput.length;
39
+ }
40
+ position += idx;
41
+ remInput = remInput.slice(idx);
42
+ return { position, remInput };
43
+ }
44
+ function consumeLicenseName(info) {
45
+ info = skipWhitespace(info);
46
+ let licenseName = '';
47
+ let isAtWhitespace = false;
48
+ for (let i = 0; i < info.remInput.length; i++) {
49
+ const char = info.remInput[i];
50
+ if (/[()<>~!=,&|+]/.test(char)) {
51
+ break;
52
+ }
53
+ else {
54
+ isAtWhitespace = /\s/.test(char);
55
+ }
56
+ if (isAtWhitespace) {
57
+ if (/^\s*(with|and|or)\s+/i.test(info.remInput.slice(i))) {
58
+ break;
59
+ }
60
+ }
61
+ licenseName += char;
62
+ }
63
+ const newInfo = {
64
+ position: info.position + licenseName.length,
65
+ remInput: info.remInput.slice(licenseName.length)
66
+ };
67
+ // file licenses are a special case!
68
+ if (licenseName && /^file[\s-]+license$/i.test(licenseName.trim())) {
69
+ return { ...newInfo, element: 'file LICENSE' };
70
+ }
71
+ return { ...newInfo, element: licenseName?.trim() ?? '' };
72
+ }
73
+ function makeRange(rangeStr) {
74
+ try {
75
+ rangeStr = rangeStr.trim().replaceAll('==', '=');
76
+ return new semver_1.Range(rangeStr);
77
+ }
78
+ catch {
79
+ return undefined;
80
+ }
81
+ }
82
+ function parseLicenseElement(info) {
83
+ const licenseName = consumeLicenseName(info);
84
+ info = skipWhitespace(licenseName);
85
+ // may be followed by version constraint in parentheses or directly
86
+ let versionConstraint;
87
+ if (/^\(\s*?[\d<>=!~]/.test(info.remInput)) {
88
+ // version constraint
89
+ if (info.remInput.startsWith('(')) {
90
+ const openParen = consumeString(info, '(');
91
+ (0, assert_1.guard)(openParen.element, `Expected (, but found ${info.remInput[0]} at position ${info.position}`);
92
+ info = skipWhitespace(openParen);
93
+ // consume until closing parenthesis
94
+ const versionStr = consumeUntilString(info, ')');
95
+ versionConstraint = makeRange(versionStr.element);
96
+ const closeParen = consumeString(versionStr, ')');
97
+ (0, assert_1.guard)(closeParen.element, `Expected ), but found ${versionStr.remInput[0]} at position ${versionStr.position}`);
98
+ info = skipWhitespace(closeParen);
99
+ }
100
+ else {
101
+ // consume until whitespace or special character
102
+ const versionStr = consumeRegexp(info, /^[\d<>=!~.\s]+/);
103
+ versionConstraint = versionStr.element ? makeRange(versionStr.element) : undefined;
104
+ info = skipWhitespace(versionStr);
105
+ }
106
+ }
107
+ const licenseInfo = (0, objects_1.compactRecord)({
108
+ type: 'license',
109
+ license: licenseName.element,
110
+ versionConstraint
111
+ });
112
+ return { ...info, element: licenseInfo };
113
+ }
114
+ const operators = {
115
+ 'and': ['and', '+', '&'],
116
+ 'or': ['or', '|'],
117
+ 'with': ['with']
118
+ };
119
+ function parseBinaryOperator(info) {
120
+ const license = parseLicenseElement(info);
121
+ info = skipWhitespace(license);
122
+ const operator = tryConsumeOperator(info);
123
+ if (operator.element) {
124
+ info = skipWhitespace(operator);
125
+ let rightLicense = parseLicenseInfo(info);
126
+ if (operator.element === 'with' && rightLicense.element.type === 'license') {
127
+ rightLicense = {
128
+ ...rightLicense,
129
+ element: {
130
+ type: 'exception',
131
+ exception: rightLicense.element.license
132
+ }
133
+ };
134
+ }
135
+ const combination = {
136
+ type: 'combination',
137
+ combination: operator.element,
138
+ elements: [license.element, rightLicense.element]
139
+ };
140
+ return { ...rightLicense, element: combination };
141
+ }
142
+ return { ...info, element: license.element };
143
+ }
144
+ function tryConsumeOperator(info) {
145
+ for (const [opName, opSymbols] of Object.entries(operators)) {
146
+ for (const symbol of opSymbols) {
147
+ if (info.remInput.toLowerCase().startsWith(symbol)) {
148
+ const newInfo = {
149
+ position: info.position + symbol.length,
150
+ remInput: info.remInput.slice(symbol.length)
151
+ };
152
+ return { ...newInfo, element: opName };
153
+ }
154
+ }
155
+ }
156
+ return { ...info, element: undefined };
157
+ }
158
+ function consumeString(info, str) {
159
+ info = skipWhitespace(info);
160
+ if (info.remInput.startsWith(str)) {
161
+ const newInfo = {
162
+ position: info.position + str.length,
163
+ remInput: info.remInput.slice(str.length)
164
+ };
165
+ return { ...newInfo, element: true };
166
+ }
167
+ else {
168
+ return { ...info, element: false };
169
+ }
170
+ }
171
+ function consumeUntilString(info, str) {
172
+ let idx = info.remInput.indexOf(str);
173
+ if (idx === -1) {
174
+ idx = info.remInput.length;
175
+ }
176
+ const consumed = info.remInput.slice(0, idx);
177
+ const newInfo = {
178
+ position: info.position + idx,
179
+ remInput: info.remInput.slice(idx)
180
+ };
181
+ return { ...newInfo, element: consumed };
182
+ }
183
+ function consumeRegexp(info, regex) {
184
+ info = skipWhitespace(info);
185
+ const match = info.remInput.match(regex);
186
+ if (match && match.index === 0) {
187
+ const matchedStr = match[0];
188
+ const newInfo = {
189
+ position: info.position + matchedStr.length,
190
+ remInput: info.remInput.slice(matchedStr.length)
191
+ };
192
+ return { ...newInfo, element: matchedStr };
193
+ }
194
+ return { ...info, element: null };
195
+ }
196
+ //# sourceMappingURL=r-license.js.map
package/util/version.js CHANGED
@@ -6,7 +6,7 @@ exports.printVersionInformation = printVersionInformation;
6
6
  const semver_1 = require("semver");
7
7
  const assert_1 = require("./assert");
8
8
  // this is automatically replaced with the current version by release-it
9
- const version = '2.7.5';
9
+ const version = '2.7.6';
10
10
  /**
11
11
  * Retrieves the current flowR version as a new {@link SemVer} object.
12
12
  */