@eagleoutice/flowr 2.7.5 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -65
- package/cli/wiki.js +1 -1
- package/control-flow/extract-cfg.js +3 -3
- package/control-flow/useless-loop.d.ts +1 -1
- package/control-flow/useless-loop.js +2 -2
- package/dataflow/cluster.js +3 -3
- package/dataflow/environments/built-in-config.d.ts +8 -4
- package/dataflow/environments/built-in.d.ts +27 -14
- package/dataflow/environments/built-in.js +27 -12
- package/dataflow/environments/default-builtin-config.d.ts +614 -3
- package/dataflow/environments/default-builtin-config.js +50 -15
- package/dataflow/environments/environment.js +3 -2
- package/dataflow/environments/identifier.d.ts +5 -1
- package/dataflow/environments/reference-to-maybe.d.ts +2 -2
- package/dataflow/environments/reference-to-maybe.js +23 -14
- package/dataflow/environments/resolve-by-name.d.ts +6 -2
- package/dataflow/environments/resolve-by-name.js +5 -1
- package/dataflow/environments/scoping.js +1 -3
- package/dataflow/eval/resolve/alias-tracking.js +5 -1
- package/dataflow/extractor.js +3 -3
- package/dataflow/fn/exceptions-of-function.d.ts +13 -0
- package/dataflow/fn/exceptions-of-function.js +47 -0
- package/dataflow/fn/higher-order-function.d.ts +1 -1
- package/dataflow/fn/higher-order-function.js +3 -3
- package/dataflow/fn/recursive-function.d.ts +6 -0
- package/dataflow/fn/recursive-function.js +32 -0
- package/dataflow/graph/call-graph.d.ts +10 -0
- package/dataflow/graph/call-graph.js +209 -0
- package/dataflow/graph/dataflowgraph-builder.d.ts +7 -2
- package/dataflow/graph/dataflowgraph-builder.js +14 -9
- package/dataflow/graph/diff-dataflow-graph.js +96 -2
- package/dataflow/graph/graph.d.ts +10 -7
- package/dataflow/graph/graph.js +7 -8
- package/dataflow/graph/vertex.d.ts +6 -3
- package/dataflow/hooks.d.ts +30 -0
- package/dataflow/hooks.js +38 -0
- package/dataflow/info.d.ts +28 -5
- package/dataflow/info.js +66 -31
- package/dataflow/internal/linker.d.ts +13 -3
- package/dataflow/internal/linker.js +155 -53
- package/dataflow/internal/process/functions/call/argument/unpack-argument.d.ts +4 -0
- package/dataflow/internal/process/functions/call/argument/unpack-argument.js +7 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +19 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +14 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +30 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +24 -17
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.d.ts +5 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +59 -21
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-register-hook.d.ts +34 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-register-hook.js +92 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +1 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-stop-if-not.d.ts +21 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-stop-if-not.js +129 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-try-catch.d.ts +16 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-try-catch.js +127 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +5 -3
- package/dataflow/internal/process/functions/call/common.d.ts +13 -1
- package/dataflow/internal/process/functions/call/common.js +33 -2
- package/dataflow/internal/process/functions/call/known-call-handling.d.ts +13 -1
- package/dataflow/internal/process/functions/call/known-call-handling.js +29 -3
- package/dataflow/internal/process/functions/call/named-call-handling.js +2 -1
- package/dataflow/internal/process/functions/call/unnamed-call-handling.js +6 -4
- package/dataflow/internal/process/functions/process-argument.js +7 -6
- package/dataflow/internal/process/functions/process-parameter.js +2 -1
- package/dataflow/internal/process/process-named-call.d.ts +2 -2
- package/dataflow/internal/process/process-symbol.js +3 -2
- package/dataflow/internal/process/process-value.d.ts +3 -2
- package/dataflow/internal/process/process-value.js +8 -6
- package/dataflow/origin/dfg-get-origin.js +2 -1
- package/dataflow/origin/dfg-get-symbol-refs.js +1 -1
- package/documentation/doc-readme.d.ts +1 -1
- package/documentation/doc-readme.js +6 -6
- package/documentation/doc-util/doc-code.js +1 -1
- package/documentation/doc-util/doc-dfg.d.ts +1 -0
- package/documentation/doc-util/doc-dfg.js +7 -4
- package/documentation/doc-util/doc-query.d.ts +1 -0
- package/documentation/doc-util/doc-query.js +1 -1
- package/documentation/doc-util/doc-repl.d.ts +2 -1
- package/documentation/doc-util/doc-repl.js +11 -3
- package/documentation/wiki-analyzer.js +2 -0
- package/documentation/wiki-dataflow-graph.js +59 -16
- package/documentation/wiki-interface.js +33 -5
- package/documentation/wiki-mk/doc-context.d.ts +2 -1
- package/documentation/wiki-mk/doc-context.js +2 -2
- package/documentation/wiki-mk/doc-maker.js +4 -3
- package/documentation/wiki-normalized-ast.js +6 -0
- package/documentation/wiki-query.js +109 -1
- package/linter/linter-rules.d.ts +1 -1
- package/linter/rules/seeded-randomness.js +17 -12
- package/linter/rules/useless-loop.d.ts +1 -1
- package/package.json +9 -11
- package/project/cache/flowr-analyzer-cache.d.ts +11 -0
- package/project/cache/flowr-analyzer-cache.js +19 -0
- package/project/context/flowr-analyzer-dependencies-context.d.ts +6 -1
- package/project/context/flowr-analyzer-dependencies-context.js +6 -0
- package/project/context/flowr-analyzer-files-context.d.ts +5 -2
- package/project/context/flowr-analyzer-files-context.js +24 -17
- package/project/context/flowr-file.d.ts +9 -4
- package/project/context/flowr-file.js +20 -6
- package/project/flowr-analyzer.d.ts +11 -0
- package/project/flowr-analyzer.js +6 -0
- package/project/plugins/file-plugins/files/flowr-description-file.d.ts +11 -3
- package/project/plugins/file-plugins/files/flowr-description-file.js +38 -28
- package/project/plugins/file-plugins/files/flowr-jupyter-file.js +1 -1
- package/project/plugins/file-plugins/files/flowr-namespace-file.js +1 -1
- package/project/plugins/file-plugins/files/flowr-news-file.js +1 -1
- package/project/plugins/file-plugins/files/flowr-rmarkdown-file.js +1 -1
- package/project/plugins/file-plugins/flowr-analyzer-description-file-plugin.js +1 -1
- package/project/plugins/file-plugins/flowr-analyzer-file-plugin.d.ts +4 -1
- package/project/plugins/file-plugins/flowr-analyzer-file-plugin.js +3 -0
- package/project/plugins/file-plugins/{flowr-analyzer-namespace-file-plugin.d.ts → flowr-analyzer-namespace-files-plugin.d.ts} +1 -1
- package/project/plugins/file-plugins/{flowr-analyzer-namespace-file-plugin.js → flowr-analyzer-namespace-files-plugin.js} +4 -4
- package/project/plugins/file-plugins/flowr-analyzer-test-file-plugin.d.ts +26 -0
- package/project/plugins/file-plugins/flowr-analyzer-test-file-plugin.js +39 -0
- package/project/plugins/file-plugins/flowr-analyzer-vignette-file-plugin.d.ts +26 -0
- package/project/plugins/file-plugins/flowr-analyzer-vignette-file-plugin.js +39 -0
- package/project/plugins/flowr-analyzer-plugin-defaults.js +6 -2
- package/project/plugins/package-version-plugins/flowr-analyzer-package-versions-description-file-plugin.js +3 -13
- package/project/plugins/package-version-plugins/package.d.ts +1 -1
- package/project/plugins/package-version-plugins/package.js +3 -3
- package/project/plugins/plugin-registry.d.ts +4 -2
- package/project/plugins/plugin-registry.js +6 -2
- package/project/plugins/project-discovery/flowr-analyzer-project-discovery-plugin.d.ts +11 -0
- package/project/plugins/project-discovery/flowr-analyzer-project-discovery-plugin.js +5 -2
- package/queries/catalog/call-context-query/call-context-query-format.d.ts +4 -12
- package/queries/catalog/call-graph-query/call-graph-query-executor.d.ts +6 -0
- package/queries/catalog/call-graph-query/call-graph-query-executor.js +21 -0
- package/queries/catalog/call-graph-query/call-graph-query-format.d.ts +21 -0
- package/queries/catalog/call-graph-query/call-graph-query-format.js +32 -0
- package/queries/catalog/dataflow-query/dataflow-query-executor.js +4 -3
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +29 -3
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -0
- package/queries/catalog/dependencies-query/function-info/function-info.d.ts +8 -1
- package/queries/catalog/dependencies-query/function-info/write-functions.js +13 -0
- package/queries/catalog/does-call-query/does-call-query-executor.d.ts +6 -0
- package/queries/catalog/does-call-query/does-call-query-executor.js +100 -0
- package/queries/catalog/does-call-query/does-call-query-format.d.ts +51 -0
- package/queries/catalog/does-call-query/does-call-query-format.js +102 -0
- package/queries/catalog/files-query/files-query-executor.js +4 -4
- package/queries/catalog/files-query/files-query-format.d.ts +2 -1
- package/queries/catalog/files-query/files-query-format.js +18 -2
- package/queries/catalog/id-map-query/id-map-query-executor.js +4 -3
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-executor.d.ts +18 -0
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-executor.js +56 -0
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-format.d.ts +34 -0
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-format.js +54 -0
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-executor.js +3 -28
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-format.d.ts +6 -0
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-format.js +12 -0
- package/queries/catalog/inspect-recursion-query/inspect-recursion-query-executor.d.ts +6 -0
- package/queries/catalog/inspect-recursion-query/inspect-recursion-query-executor.js +23 -0
- package/queries/catalog/inspect-recursion-query/inspect-recursion-query-format.d.ts +28 -0
- package/queries/catalog/inspect-recursion-query/inspect-recursion-query-format.js +44 -0
- package/queries/catalog/linter-query/linter-query-format.js +4 -1
- package/queries/catalog/location-map-query/location-map-query-executor.js +1 -1
- package/queries/catalog/normalized-ast-query/normalized-ast-query-executor.js +4 -3
- package/queries/catalog/project-query/project-query-executor.js +9 -3
- package/queries/catalog/project-query/project-query-format.d.ts +8 -3
- package/queries/catalog/project-query/project-query-format.js +35 -9
- package/queries/query.d.ts +34 -2
- package/queries/query.js +9 -0
- package/r-bridge/data/data.d.ts +10 -5
- package/r-bridge/data/data.js +11 -5
- package/r-bridge/lang-4.x/ast/model/model.d.ts +7 -7
- package/r-bridge/lang-4.x/ast/model/nodes/r-access.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-argument.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-binary-op.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-comment.d.ts +5 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-comment.js +8 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-expression-list.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-for-loop.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-call.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-if-then-else.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-parameter.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-pipe.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-unary-op.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-while-loop.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/parser/main/internal/other/normalize-comment.js +0 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +0 -2
- package/r-bridge/roxygen2/roxygen-ast.d.ts +218 -0
- package/r-bridge/roxygen2/roxygen-ast.js +82 -0
- package/r-bridge/roxygen2/roxygen-parse.d.ts +24 -0
- package/r-bridge/roxygen2/roxygen-parse.js +214 -0
- package/reconstruct/auto-select/magic-comments.js +4 -4
- package/slicing/static/slice-call.js +3 -4
- package/slicing/static/static-slicer.js +2 -2
- package/statistics/features/supported/defined-functions/defined-functions.js +1 -1
- package/util/collections/defaultmap.d.ts +3 -3
- package/util/mermaid/dfg.js +5 -5
- package/util/objects.js +1 -1
- package/util/r-author.d.ts +5 -0
- package/util/r-author.js +110 -0
- package/util/r-license.d.ts +32 -0
- package/util/r-license.js +217 -0
- package/util/r-version.d.ts +19 -0
- package/util/r-version.js +106 -0
- package/util/range.d.ts +6 -0
- package/util/range.js +7 -0
- package/util/simple-df/dfg-ascii.js +2 -2
- package/util/text/args.d.ts +9 -0
- package/util/text/args.js +65 -0
- package/util/version.js +1 -1
package/util/mermaid/dfg.js
CHANGED
|
@@ -33,7 +33,7 @@ function formatRange(range) {
|
|
|
33
33
|
}
|
|
34
34
|
return `${range[0]}.${range[1]}-${range[2]}.${range[3]}`;
|
|
35
35
|
}
|
|
36
|
-
function subflowToMermaid(nodeId,
|
|
36
|
+
function subflowToMermaid(nodeId, subflow, mermaid, idPrefix = '') {
|
|
37
37
|
if (subflow === undefined) {
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
@@ -166,7 +166,7 @@ function vertexToMermaid(info, mermaid, id, idPrefix, mark, includeOnlyIds) {
|
|
|
166
166
|
}
|
|
167
167
|
else {
|
|
168
168
|
const escapedName = (0, mermaid_1.escapeMarkdown)(node ? `[${node.type}] ${lexeme}` : '??');
|
|
169
|
-
const deps = info.
|
|
169
|
+
const deps = info.controlDependencies ? ', :may:' + info.controlDependencies.map(c => c.id + (c.when ? '+' : '-')).join(',') : '';
|
|
170
170
|
const lnks = info.link?.origin ? ', :links:' + info.link.origin.join(',') : '';
|
|
171
171
|
const n = node?.info.fullRange ?? node?.location ?? (node?.type === type_1.RType.ExpressionList ? node?.grouping?.[0].location : undefined);
|
|
172
172
|
mermaid.nodeLines.push(` ${idPrefix}${id}${open}"\`${escapedName}${escapedName.length > 10 ? '\n ' : ' '}(${id}${deps}${lnks})\n *${formatRange(n)}*${fCall ? displayFunctionArgMapping(info.args) : ''}\`"${close}`);
|
|
@@ -182,7 +182,7 @@ function vertexToMermaid(info, mermaid, id, idPrefix, mark, includeOnlyIds) {
|
|
|
182
182
|
mermaid.nodeLines.push(' %% No edges found for ' + id);
|
|
183
183
|
return;
|
|
184
184
|
}
|
|
185
|
-
const artificialCdEdges = (info.
|
|
185
|
+
const artificialCdEdges = (info.controlDependencies ?? []).map(x => [x.id, { types: new Set([x.when ? 'CD-True' : 'CD-False']) }]);
|
|
186
186
|
// eslint-disable-next-line prefer-const
|
|
187
187
|
for (let [target, edge] of [...edges[1], ...artificialCdEdges]) {
|
|
188
188
|
if (includeOnlyIds && !includeOnlyIds.has(target)) {
|
|
@@ -207,14 +207,14 @@ function vertexToMermaid(info, mermaid, id, idPrefix, mark, includeOnlyIds) {
|
|
|
207
207
|
mermaid.edgeLines.push(` linkStyle ${mermaid.presentEdges.size - 1} stroke:gray;`);
|
|
208
208
|
if (!mermaid.presentVertices.has(target)) {
|
|
209
209
|
mermaid.nodeLines.push(` ${idPrefix}${target}["\`Built-In:\n${(0, mermaid_1.escapeMarkdown)(String(originalTarget).replace('built-in:', ''))}\`"]`);
|
|
210
|
-
mermaid.nodeLines.push(` style ${idPrefix}${target} stroke:gray,fill:
|
|
210
|
+
mermaid.nodeLines.push(` style ${idPrefix}${target} stroke:gray,fill:gray,stroke-width:2px,opacity:.8;`);
|
|
211
211
|
mermaid.presentVertices.add(target);
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
if (info.tag === vertex_1.VertexType.FunctionDefinition) {
|
|
217
|
-
subflowToMermaid(id, info.
|
|
217
|
+
subflowToMermaid(id, info.subflow, mermaid, idPrefix);
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
220
|
// make the passing of root ids more performant again
|
package/util/objects.js
CHANGED
|
@@ -30,7 +30,7 @@ function deepMergeObject(base, addon) {
|
|
|
30
30
|
deepMergeObjectWithResult(addon, base, result);
|
|
31
31
|
}
|
|
32
32
|
else if (baseIsArray && addonIsArray) {
|
|
33
|
-
return
|
|
33
|
+
return base.concat(addon);
|
|
34
34
|
}
|
|
35
35
|
else {
|
|
36
36
|
throw new Error('cannot merge object with array!');
|
package/util/r-author.d.ts
CHANGED
|
@@ -37,3 +37,8 @@ export declare function rAuthorInfoToReadable(author: RAuthorInfo): string;
|
|
|
37
37
|
* For now, this works *without* the full dataflow engine, so complex cases may not be parsed correctly.
|
|
38
38
|
*/
|
|
39
39
|
export declare function parseRAuthorString(authorString: string): RAuthorInfo[];
|
|
40
|
+
/**
|
|
41
|
+
* In contrast to `parseRAuthorString`, this function parses simple textual author strings,
|
|
42
|
+
* like `First Middle Last <email> [roles] (comment)...`. It does not support the full R `person()` syntax.
|
|
43
|
+
*/
|
|
44
|
+
export declare function parseTextualAuthorString(authorString: string, addRoles?: AuthorRole[]): RAuthorInfo[];
|
package/util/r-author.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.AuthorRole = void 0;
|
|
4
4
|
exports.rAuthorInfoToReadable = rAuthorInfoToReadable;
|
|
5
5
|
exports.parseRAuthorString = parseRAuthorString;
|
|
6
|
+
exports.parseTextualAuthorString = parseTextualAuthorString;
|
|
6
7
|
const args_1 = require("./text/args");
|
|
7
8
|
const assert_1 = require("./assert");
|
|
8
9
|
const objects_1 = require("./objects");
|
|
@@ -191,4 +192,113 @@ function parseRPersonCall(personCall) {
|
|
|
191
192
|
orcid: comments?.orcid
|
|
192
193
|
});
|
|
193
194
|
}
|
|
195
|
+
function collectUntil(source, anyOf) {
|
|
196
|
+
let collected = '';
|
|
197
|
+
let i = 0;
|
|
198
|
+
while (i < source.length && !anyOf.test(source[i])) {
|
|
199
|
+
collected += source[i];
|
|
200
|
+
i++;
|
|
201
|
+
}
|
|
202
|
+
return { collected, rest: source.slice(i) };
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* In contrast to `parseRAuthorString`, this function parses simple textual author strings,
|
|
206
|
+
* like `First Middle Last <email> [roles] (comment)...`. It does not support the full R `person()` syntax.
|
|
207
|
+
*/
|
|
208
|
+
function parseTextualAuthorString(authorString, addRoles = []) {
|
|
209
|
+
const parts = (0, args_1.splitOnNestingSensitive)(authorString, 'and', {
|
|
210
|
+
'<': '>',
|
|
211
|
+
'[': ']',
|
|
212
|
+
'(': ')',
|
|
213
|
+
'"': '"',
|
|
214
|
+
"'": "'"
|
|
215
|
+
});
|
|
216
|
+
const authors = [];
|
|
217
|
+
for (const part of parts) {
|
|
218
|
+
const name = collectUntil(part.trim(), /[<[(]/);
|
|
219
|
+
const others = parseOnRest(name.rest);
|
|
220
|
+
const c = processComment(others.comment);
|
|
221
|
+
authors.push((0, objects_1.compactRecord)({
|
|
222
|
+
name: name.collected.trim().split(/\s+/),
|
|
223
|
+
email: others.email,
|
|
224
|
+
roles: others.roles.concat(addRoles),
|
|
225
|
+
comment: c.comment,
|
|
226
|
+
orcid: c.orcid
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
229
|
+
return authors;
|
|
230
|
+
}
|
|
231
|
+
function processComment(comment) {
|
|
232
|
+
if (!comment) {
|
|
233
|
+
return {};
|
|
234
|
+
}
|
|
235
|
+
const parts = comment.split(/\s*[,;]\s*/);
|
|
236
|
+
const comments = [];
|
|
237
|
+
let orcid = undefined;
|
|
238
|
+
for (const part of parts) {
|
|
239
|
+
const orcidExtract = /ORCID\s*[:= ]\s*(?<orcid>.+)/i;
|
|
240
|
+
const match = part.match(orcidExtract);
|
|
241
|
+
if (match && match.groups && match.groups['orcid']) {
|
|
242
|
+
orcid = match.groups['orcid'].trim();
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
comments.push(part.trim());
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
if (orcid) {
|
|
249
|
+
return { comment: comments.length > 0 ? comments : undefined, orcid };
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
return { comment: [comment] };
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function parseOnRest(rest) {
|
|
256
|
+
let email = undefined;
|
|
257
|
+
let roles = [];
|
|
258
|
+
let comment = undefined;
|
|
259
|
+
while (rest.length > 0) {
|
|
260
|
+
rest = rest.trim();
|
|
261
|
+
switch (rest[0]) {
|
|
262
|
+
case '<': {
|
|
263
|
+
const emailEnd = rest.indexOf('>');
|
|
264
|
+
if (emailEnd !== -1) {
|
|
265
|
+
email = rest.slice(1, emailEnd).trim();
|
|
266
|
+
rest = rest.slice(emailEnd + 1);
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
rest = '';
|
|
270
|
+
}
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
case '[': {
|
|
274
|
+
const rolesEnd = rest.indexOf(']');
|
|
275
|
+
if (rolesEnd !== -1) {
|
|
276
|
+
const rolesStr = rest.slice(1, rolesEnd).trim();
|
|
277
|
+
roles = rolesStr.split(/\s*,\s*/).map(r => r);
|
|
278
|
+
rest = rest.slice(rolesEnd + 1);
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
rest = '';
|
|
282
|
+
}
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
case '(': {
|
|
286
|
+
const commentEnd = rest.indexOf(')');
|
|
287
|
+
if (commentEnd !== -1) {
|
|
288
|
+
comment = rest.slice(1, commentEnd).trim();
|
|
289
|
+
rest = rest.slice(commentEnd + 1);
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
rest = '';
|
|
293
|
+
}
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
default: {
|
|
297
|
+
rest = '';
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return { email, roles, comment };
|
|
303
|
+
}
|
|
194
304
|
//# sourceMappingURL=r-author.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { 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
|
+
/**
|
|
20
|
+
* The structured representation of an R license element.
|
|
21
|
+
* This can be a license, an exception, a combination of licenses, or no license.
|
|
22
|
+
* @see {@link parseRLicense} and {@link stringifyRLicense} to parse and stringify R license strings.
|
|
23
|
+
*/
|
|
24
|
+
export type RLicenseElementInfo = RLicenseInfo | RLicenseExceptionInfo | RLicenseCombinationInfo | NoLicenseInfo;
|
|
25
|
+
/**
|
|
26
|
+
* Parses an R license string into its structured representation.
|
|
27
|
+
*/
|
|
28
|
+
export declare function parseRLicense(licenseString: string): RLicenseElementInfo;
|
|
29
|
+
/**
|
|
30
|
+
* Stringifies an R license element back into its string representation.
|
|
31
|
+
*/
|
|
32
|
+
export declare function stringifyRLicense(license: RLicenseElementInfo): string;
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseRLicense = parseRLicense;
|
|
4
|
+
exports.stringifyRLicense = stringifyRLicense;
|
|
5
|
+
const assert_1 = require("./assert");
|
|
6
|
+
const objects_1 = require("./objects");
|
|
7
|
+
const r_version_1 = require("./r-version");
|
|
8
|
+
/**
|
|
9
|
+
* Parses an R license string into its structured representation.
|
|
10
|
+
*/
|
|
11
|
+
function parseRLicense(licenseString) {
|
|
12
|
+
return parseLicenseInfo(skipWhitespace({ position: 0, remInput: licenseString })).element;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Stringifies an R license element back into its string representation.
|
|
16
|
+
*/
|
|
17
|
+
function stringifyRLicense(license) {
|
|
18
|
+
const t = license.type;
|
|
19
|
+
switch (t) {
|
|
20
|
+
case 'no-license':
|
|
21
|
+
return 'NO LICENSE';
|
|
22
|
+
case 'license':
|
|
23
|
+
return license.versionConstraint ? `${license.license} (${license.versionConstraint.raw})` : license.license;
|
|
24
|
+
case 'exception':
|
|
25
|
+
return `with ${license.exception}`;
|
|
26
|
+
case 'combination': {
|
|
27
|
+
const left = stringifyRLicense(license.elements[0]);
|
|
28
|
+
const right = stringifyRLicense(license.elements[1]);
|
|
29
|
+
const leftStr = license.elements[0].type === 'combination' ? `(${left})` : left;
|
|
30
|
+
const rightStr = license.elements[1].type === 'combination' ? `(${right})` : right;
|
|
31
|
+
return `${leftStr} ${license.combination} ${rightStr}`;
|
|
32
|
+
}
|
|
33
|
+
default:
|
|
34
|
+
(0, assert_1.assertUnreachable)(t);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function parseLicenseInfo(info) {
|
|
38
|
+
info = skipWhitespace(info);
|
|
39
|
+
if (info.remInput.length === 0) {
|
|
40
|
+
return { ...info, element: { type: 'no-license' } };
|
|
41
|
+
}
|
|
42
|
+
else if (info.remInput.startsWith('(')) {
|
|
43
|
+
return parseParenthesizedExpression(info);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
return parseBinaryOperator(info);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function parseParenthesizedExpression(info) {
|
|
50
|
+
const openParen = consumeString(info, '(');
|
|
51
|
+
(0, assert_1.guard)(openParen.element, `Expected (, but found ${info.remInput[0]} at position ${info.position}`);
|
|
52
|
+
const innerInfo = parseLicenseInfo(openParen);
|
|
53
|
+
const closeParen = consumeString(innerInfo, ')');
|
|
54
|
+
(0, assert_1.guard)(closeParen.element, `Expected ), but found ${innerInfo.remInput[0]} at position ${innerInfo.position}`);
|
|
55
|
+
return { ...closeParen, element: innerInfo.element };
|
|
56
|
+
}
|
|
57
|
+
function skipWhitespace({ remInput, position }) {
|
|
58
|
+
let idx = remInput.search(/\S/);
|
|
59
|
+
if (idx === -1) {
|
|
60
|
+
idx = remInput.length;
|
|
61
|
+
}
|
|
62
|
+
position += idx;
|
|
63
|
+
remInput = remInput.slice(idx);
|
|
64
|
+
return { position, remInput };
|
|
65
|
+
}
|
|
66
|
+
function consumeLicenseName(info) {
|
|
67
|
+
info = skipWhitespace(info);
|
|
68
|
+
let licenseName = '';
|
|
69
|
+
let isAtWhitespace = false;
|
|
70
|
+
for (let i = 0; i < info.remInput.length; i++) {
|
|
71
|
+
const char = info.remInput[i];
|
|
72
|
+
if (/[()<>~!=,&|+]/.test(char)) {
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
isAtWhitespace = /\s/.test(char);
|
|
77
|
+
}
|
|
78
|
+
if (isAtWhitespace) {
|
|
79
|
+
if (/^\s*(with|and|or)\s+/i.test(info.remInput.slice(i))) {
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
licenseName += char;
|
|
84
|
+
}
|
|
85
|
+
const newInfo = {
|
|
86
|
+
position: info.position + licenseName.length,
|
|
87
|
+
remInput: info.remInput.slice(licenseName.length)
|
|
88
|
+
};
|
|
89
|
+
// file licenses are a special case!
|
|
90
|
+
if (licenseName && /^file[\s-]+license$/i.test(licenseName.trim())) {
|
|
91
|
+
return { ...newInfo, element: 'file LICENSE' };
|
|
92
|
+
}
|
|
93
|
+
return { ...newInfo, element: licenseName?.trim() ?? '' };
|
|
94
|
+
}
|
|
95
|
+
function makeRange(rangeStr) {
|
|
96
|
+
try {
|
|
97
|
+
return (0, r_version_1.parseRRange)(rangeStr);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function parseLicenseElement(info) {
|
|
104
|
+
const licenseName = consumeLicenseName(info);
|
|
105
|
+
info = skipWhitespace(licenseName);
|
|
106
|
+
// may be followed by version constraint in parentheses or directly
|
|
107
|
+
let versionConstraint;
|
|
108
|
+
if (/^\(\s*?[\d<>=!~]/.test(info.remInput)) {
|
|
109
|
+
// version constraint
|
|
110
|
+
if (info.remInput.startsWith('(')) {
|
|
111
|
+
const openParen = consumeString(info, '(');
|
|
112
|
+
(0, assert_1.guard)(openParen.element, `Expected (, but found ${info.remInput[0]} at position ${info.position}`);
|
|
113
|
+
info = skipWhitespace(openParen);
|
|
114
|
+
// consume until closing parenthesis
|
|
115
|
+
const versionStr = consumeUntilString(info, ')');
|
|
116
|
+
versionConstraint = makeRange(versionStr.element);
|
|
117
|
+
const closeParen = consumeString(versionStr, ')');
|
|
118
|
+
(0, assert_1.guard)(closeParen.element, `Expected ), but found ${versionStr.remInput[0]} at position ${versionStr.position}`);
|
|
119
|
+
info = skipWhitespace(closeParen);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// consume until whitespace or special character
|
|
123
|
+
const versionStr = consumeRegexp(info, /^[\d<>=!~.\s]+/);
|
|
124
|
+
versionConstraint = versionStr.element ? makeRange(versionStr.element) : undefined;
|
|
125
|
+
info = skipWhitespace(versionStr);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const licenseInfo = (0, objects_1.compactRecord)({
|
|
129
|
+
type: 'license',
|
|
130
|
+
license: licenseName.element,
|
|
131
|
+
versionConstraint
|
|
132
|
+
});
|
|
133
|
+
return { ...info, element: licenseInfo };
|
|
134
|
+
}
|
|
135
|
+
const operators = {
|
|
136
|
+
'and': ['and', '+', '&'],
|
|
137
|
+
'or': ['or', '|'],
|
|
138
|
+
'with': ['with']
|
|
139
|
+
};
|
|
140
|
+
function parseBinaryOperator(info) {
|
|
141
|
+
const license = parseLicenseElement(info);
|
|
142
|
+
info = skipWhitespace(license);
|
|
143
|
+
const operator = tryConsumeOperator(info);
|
|
144
|
+
if (operator.element) {
|
|
145
|
+
info = skipWhitespace(operator);
|
|
146
|
+
let rightLicense = parseLicenseInfo(info);
|
|
147
|
+
if (operator.element === 'with' && rightLicense.element.type === 'license') {
|
|
148
|
+
rightLicense = {
|
|
149
|
+
...rightLicense,
|
|
150
|
+
element: {
|
|
151
|
+
type: 'exception',
|
|
152
|
+
exception: rightLicense.element.license
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
const combination = {
|
|
157
|
+
type: 'combination',
|
|
158
|
+
combination: operator.element,
|
|
159
|
+
elements: [license.element, rightLicense.element]
|
|
160
|
+
};
|
|
161
|
+
return { ...rightLicense, element: combination };
|
|
162
|
+
}
|
|
163
|
+
return { ...info, element: license.element };
|
|
164
|
+
}
|
|
165
|
+
function tryConsumeOperator(info) {
|
|
166
|
+
for (const [opName, opSymbols] of Object.entries(operators)) {
|
|
167
|
+
for (const symbol of opSymbols) {
|
|
168
|
+
if (info.remInput.toLowerCase().startsWith(symbol)) {
|
|
169
|
+
const newInfo = {
|
|
170
|
+
position: info.position + symbol.length,
|
|
171
|
+
remInput: info.remInput.slice(symbol.length)
|
|
172
|
+
};
|
|
173
|
+
return { ...newInfo, element: opName };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return { ...info, element: undefined };
|
|
178
|
+
}
|
|
179
|
+
function consumeString(info, str) {
|
|
180
|
+
info = skipWhitespace(info);
|
|
181
|
+
if (info.remInput.startsWith(str)) {
|
|
182
|
+
const newInfo = {
|
|
183
|
+
position: info.position + str.length,
|
|
184
|
+
remInput: info.remInput.slice(str.length)
|
|
185
|
+
};
|
|
186
|
+
return { ...newInfo, element: true };
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
return { ...info, element: false };
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function consumeUntilString(info, str) {
|
|
193
|
+
let idx = info.remInput.indexOf(str);
|
|
194
|
+
if (idx === -1) {
|
|
195
|
+
idx = info.remInput.length;
|
|
196
|
+
}
|
|
197
|
+
const consumed = info.remInput.slice(0, idx);
|
|
198
|
+
const newInfo = {
|
|
199
|
+
position: info.position + idx,
|
|
200
|
+
remInput: info.remInput.slice(idx)
|
|
201
|
+
};
|
|
202
|
+
return { ...newInfo, element: consumed };
|
|
203
|
+
}
|
|
204
|
+
function consumeRegexp(info, regex) {
|
|
205
|
+
info = skipWhitespace(info);
|
|
206
|
+
const match = info.remInput.match(regex);
|
|
207
|
+
if (match && match.index === 0) {
|
|
208
|
+
const matchedStr = match[0];
|
|
209
|
+
const newInfo = {
|
|
210
|
+
position: info.position + matchedStr.length,
|
|
211
|
+
remInput: info.remInput.slice(matchedStr.length)
|
|
212
|
+
};
|
|
213
|
+
return { ...newInfo, element: matchedStr };
|
|
214
|
+
}
|
|
215
|
+
return { ...info, element: null };
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=r-license.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Range, SemVer } from 'semver';
|
|
2
|
+
/**
|
|
3
|
+
* This parses an R version string and returns a SemVer object.
|
|
4
|
+
* In contrast to just using `new SemVer(version)`, this function also tries to
|
|
5
|
+
* normalize R's much free-er versioning scheme into valid SemVer versions.
|
|
6
|
+
* You can always access the original version string via the `str` property on the returned object.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseRVersion(version: string): SemVer & {
|
|
9
|
+
str: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* This parses an R version range string and returns a SemVer Range object.
|
|
13
|
+
* In contrast to just using `new Range(range)`, this function also tries to
|
|
14
|
+
* normalize R's much free-er versioning scheme into valid SemVer ranges.
|
|
15
|
+
* You can always access the original range string via the `str` property on the returned object.
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseRRange(range: string): Range & {
|
|
18
|
+
str: string;
|
|
19
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseRVersion = parseRVersion;
|
|
4
|
+
exports.parseRRange = parseRRange;
|
|
5
|
+
const semver_1 = require("semver");
|
|
6
|
+
const assert_1 = require("./assert");
|
|
7
|
+
function makeVersion(version, original) {
|
|
8
|
+
const semver = new semver_1.SemVer(version);
|
|
9
|
+
semver.str = original;
|
|
10
|
+
return semver;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Additionally, this transforms `a-b.c` into `a.0.0-b.c` and `a.b-c.d` into `a.b.0-c.d` to
|
|
14
|
+
* ensure valid SemVer format.
|
|
15
|
+
*/
|
|
16
|
+
function normalizeTooShortVersions(versions) {
|
|
17
|
+
const TooShortVersionRegex = /(^|(?<=[^\d.-]))(?<major>\d+)(\.(?<minor>\d+))?\.?-(?<prerelease>[0-9A-Za-z-.]+)(\s|$)/g;
|
|
18
|
+
let newVersions = '';
|
|
19
|
+
let match;
|
|
20
|
+
while ((match = TooShortVersionRegex.exec(versions)) !== null) {
|
|
21
|
+
const { major, minor, prerelease } = match.groups;
|
|
22
|
+
const prefix = versions.slice(0, match.index);
|
|
23
|
+
let newVersion = '';
|
|
24
|
+
if (minor === undefined) {
|
|
25
|
+
// only major version present
|
|
26
|
+
newVersion = `${major}.0.0-${prerelease}`;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
// major and minor version present, but dot before prerelease
|
|
30
|
+
newVersion = `${major}.${minor}.0-${prerelease}`;
|
|
31
|
+
}
|
|
32
|
+
newVersions += `${prefix}${newVersion}`;
|
|
33
|
+
versions = versions.slice(match.index + match[0].length);
|
|
34
|
+
}
|
|
35
|
+
newVersions += versions; // append any remaining part
|
|
36
|
+
return newVersions;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* For every version `a.b.c.d.e...` converts it to `a.b.c-d.e...`
|
|
40
|
+
* If the version already contains a prerelease part, it is appended:
|
|
41
|
+
* `a.b.c.d.e-prerelease...` becomes `a.b.c-d.e-prerelease...`
|
|
42
|
+
*/
|
|
43
|
+
function normalizeAdditionalVersionsToPrerelease(version) {
|
|
44
|
+
version = normalizeTooShortVersions(version);
|
|
45
|
+
const AdditionalVersionRegex = /(\d+\.\d+\.\d+)(?<additional>(\.\d+)+)(-(?<prerelease>[0-9A-Za-z-.]+))?/g;
|
|
46
|
+
let match;
|
|
47
|
+
let newVersion = '';
|
|
48
|
+
// repeat until no more matches
|
|
49
|
+
while ((match = AdditionalVersionRegex.exec(version)) !== null) {
|
|
50
|
+
// append to new version, first take over anything before the match
|
|
51
|
+
const prefix = version.slice(0, match.index);
|
|
52
|
+
const { additional, prerelease } = match.groups;
|
|
53
|
+
const additionalParts = additional.slice(1).split('.'); // remove leading dot and split
|
|
54
|
+
if (additionalParts.length === 0) {
|
|
55
|
+
continue; // nothing to do
|
|
56
|
+
}
|
|
57
|
+
let newPrerelease = additionalParts.join('.');
|
|
58
|
+
if (prerelease) {
|
|
59
|
+
newPrerelease = `${newPrerelease}-${prerelease}`;
|
|
60
|
+
}
|
|
61
|
+
newVersion = `${prefix}${match[1]}-${newPrerelease}`;
|
|
62
|
+
version = version.slice(match.index + match[0].length);
|
|
63
|
+
}
|
|
64
|
+
newVersion += version; // append any remaining part
|
|
65
|
+
return newVersion;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* This parses an R version string and returns a SemVer object.
|
|
69
|
+
* In contrast to just using `new SemVer(version)`, this function also tries to
|
|
70
|
+
* normalize R's much free-er versioning scheme into valid SemVer versions.
|
|
71
|
+
* You can always access the original version string via the `str` property on the returned object.
|
|
72
|
+
*/
|
|
73
|
+
function parseRVersion(version) {
|
|
74
|
+
try {
|
|
75
|
+
return makeVersion(version, version);
|
|
76
|
+
}
|
|
77
|
+
catch { /* do nothing */ }
|
|
78
|
+
try {
|
|
79
|
+
const normalized = normalizeAdditionalVersionsToPrerelease(version);
|
|
80
|
+
return makeVersion(normalized, version);
|
|
81
|
+
}
|
|
82
|
+
catch { /* do nothing */ }
|
|
83
|
+
const coerced = (0, semver_1.coerce)(version, { loose: true, includePrerelease: true });
|
|
84
|
+
(0, assert_1.guard)(coerced !== null, `Could not coerce R version "${version}" to SemVer`);
|
|
85
|
+
return makeVersion(coerced.version, version);
|
|
86
|
+
}
|
|
87
|
+
function makeRange(range, original) {
|
|
88
|
+
const semverRange = new semver_1.Range(range);
|
|
89
|
+
semverRange.str = original;
|
|
90
|
+
return semverRange;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* This parses an R version range string and returns a SemVer Range object.
|
|
94
|
+
* In contrast to just using `new Range(range)`, this function also tries to
|
|
95
|
+
* normalize R's much free-er versioning scheme into valid SemVer ranges.
|
|
96
|
+
* You can always access the original range string via the `str` property on the returned object.
|
|
97
|
+
*/
|
|
98
|
+
function parseRRange(range) {
|
|
99
|
+
try {
|
|
100
|
+
return makeRange(range, range);
|
|
101
|
+
}
|
|
102
|
+
catch { /* try to normalize R range to SemVer */ }
|
|
103
|
+
const normalized = normalizeAdditionalVersionsToPrerelease(range);
|
|
104
|
+
return makeRange(normalized.replace(/==/g, '='), range);
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=r-version.js.map
|
package/util/range.d.ts
CHANGED
|
@@ -43,6 +43,10 @@ export declare function getRangeEnd(p: SourceRange | undefined): SourcePosition
|
|
|
43
43
|
* @param ec - end column
|
|
44
44
|
*/
|
|
45
45
|
export declare function rangeFrom(sl: number | string, sc: number | string, el: number | string, ec: number | string): SourceRange;
|
|
46
|
+
/**
|
|
47
|
+
* @returns an invalid source range
|
|
48
|
+
*/
|
|
49
|
+
export declare function invalidRange(): SourceRange;
|
|
46
50
|
/**
|
|
47
51
|
* Merges multiple source ranges into a single source range that spans from the earliest start to the latest end.
|
|
48
52
|
* If you are interested in combining overlapping ranges into a minimal set of ranges, see {@link combineRanges}.
|
|
@@ -75,3 +79,5 @@ export declare function rangeIsSubsetOf([r1sl, r1sc, r1el, r1ec]: SourceRange, [
|
|
|
75
79
|
* If you are interested in merging overlapping ranges, see {@link mergeRanges}.
|
|
76
80
|
*/
|
|
77
81
|
export declare function combineRanges(...ranges: SourceRange[]): SourceRange[];
|
|
82
|
+
/** A source location consisting of a source range and an optional file name. */
|
|
83
|
+
export type SourceLocation = [...r: SourceRange, f?: string];
|
package/util/range.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getRangeStart = getRangeStart;
|
|
4
4
|
exports.getRangeEnd = getRangeEnd;
|
|
5
5
|
exports.rangeFrom = rangeFrom;
|
|
6
|
+
exports.invalidRange = invalidRange;
|
|
6
7
|
exports.mergeRanges = mergeRanges;
|
|
7
8
|
exports.rangeStartsCompletelyBefore = rangeStartsCompletelyBefore;
|
|
8
9
|
exports.rangesOverlap = rangesOverlap;
|
|
@@ -33,6 +34,12 @@ function getRangeEnd(p) {
|
|
|
33
34
|
function rangeFrom(sl, sc, el, ec) {
|
|
34
35
|
return [Number(sl), Number(sc), Number(el), Number(ec)];
|
|
35
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* @returns an invalid source range
|
|
39
|
+
*/
|
|
40
|
+
function invalidRange() {
|
|
41
|
+
return [-1, -1, -1, -1];
|
|
42
|
+
}
|
|
36
43
|
/**
|
|
37
44
|
* Merges multiple source ranges into a single source range that spans from the earliest start to the latest end.
|
|
38
45
|
* If you are interested in combining overlapping ranges into a minimal set of ranges, see {@link combineRanges}.
|
package/util/text/args.d.ts
CHANGED
|
@@ -14,3 +14,12 @@
|
|
|
14
14
|
* @param split - The character or character sequence to split on (can not be backslash or quote!)
|
|
15
15
|
*/
|
|
16
16
|
export declare function splitAtEscapeSensitive(inputString: string, escapeQuote?: boolean, split?: RegExp | string): string[];
|
|
17
|
+
/**
|
|
18
|
+
* Splits the given string on 'and', but only if not nested inside `<>`, `[]`, `()`, or quotes.
|
|
19
|
+
* This also handles escaped quotes.
|
|
20
|
+
* @param str - The string to split
|
|
21
|
+
* @param splitOn - The string to split on (default: 'and')
|
|
22
|
+
* @param closes - The matching of closing characters for nesting, structures with different open and close characters only can be nested
|
|
23
|
+
* of each other, while those with the same open and close character (like quotes) can not be nested inside themselves.
|
|
24
|
+
*/
|
|
25
|
+
export declare function splitOnNestingSensitive(str: string, splitOn?: string, closes?: Record<string, string>): string[];
|