@eagleoutice/flowr 2.8.2 → 2.8.4
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/cli/repl/core.js +22 -0
- package/config.d.ts +14 -0
- package/config.js +10 -2
- package/control-flow/extract-cfg.js +35 -14
- package/core/print/slice-diff-ansi.js +1 -1
- package/dataflow/environments/default-builtin-config.d.ts +2 -2
- package/dataflow/environments/default-builtin-config.js +8 -2
- package/dataflow/extractor.js +2 -2
- package/dataflow/graph/graph.js +0 -4
- package/dataflow/instrument/instrument-dataflow-count.d.ts +9 -0
- package/dataflow/instrument/instrument-dataflow-count.js +22 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +14 -7
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +4 -2
- package/documentation/wiki-interface.js +3 -1
- package/documentation/wiki-query.js +1 -1
- package/linter/rules/unused-definition.js +6 -5
- package/package.json +1 -1
- package/project/context/flowr-analyzer-files-context.d.ts +1 -0
- package/project/context/flowr-file.d.ts +2 -0
- package/project/context/flowr-file.js +2 -0
- package/project/plugins/file-plugins/files/flowr-namespace-file.d.ts +2 -0
- package/project/plugins/file-plugins/files/flowr-namespace-file.js +28 -0
- package/project/plugins/file-plugins/flowr-analyzer-license-file-plugin.d.ts +24 -0
- package/project/plugins/file-plugins/flowr-analyzer-license-file-plugin.js +37 -0
- package/project/plugins/flowr-analyzer-plugin-defaults.js +2 -0
- package/project/plugins/plugin-registry.d.ts +2 -1
- package/project/plugins/plugin-registry.js +3 -1
- package/queries/catalog/config-query/config-query-format.d.ts +2 -2
- package/queries/catalog/config-query/config-query-format.js +40 -2
- package/queries/catalog/dependencies-query/function-info/read-functions.js +8 -0
- package/queries/catalog/dependencies-query/function-info/write-functions.js +16 -3
- package/queries/query.d.ts +1 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +481 -447
- package/r-bridge/roxygen2/documentation-provider.d.ts +15 -0
- package/r-bridge/roxygen2/documentation-provider.js +115 -0
- package/r-bridge/roxygen2/roxygen-parse.d.ts +3 -1
- package/r-bridge/roxygen2/roxygen-parse.js +11 -5
- package/util/r-version.js +17 -1
- package/util/range.d.ts +1 -1
- package/util/range.js +1 -1
- package/util/version.js +1 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AstIdMap, ParentInformation } from '../lang-4.x/ast/model/processing/decorate';
|
|
2
|
+
import type { NodeId } from '../lang-4.x/ast/model/processing/node-id';
|
|
3
|
+
import type { RoxygenTag } from './roxygen-ast';
|
|
4
|
+
export interface DocumentationInfo {
|
|
5
|
+
doc?: Documentation;
|
|
6
|
+
}
|
|
7
|
+
export type Documentation = RoxygenTag | readonly RoxygenTag[];
|
|
8
|
+
/**
|
|
9
|
+
* Given a normalized AST and a node ID, returns the Roxygen documentation (if any) associated with that node.
|
|
10
|
+
* Please note that this does more than {@link parseRoxygenCommentsOfNode}, as it also traverses up the AST to find documentation.
|
|
11
|
+
* Additionally, this function instruments the normalized AST to cache the parsed documentation for future queries.
|
|
12
|
+
* @param idMap - The AST ID map to use for looking up nodes and traversing the AST.
|
|
13
|
+
* @param nodeId - The ID of the node to get documentation for.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getDocumentationOf(nodeId: NodeId, idMap: AstIdMap<ParentInformation & DocumentationInfo>): Documentation | undefined;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDocumentationOf = getDocumentationOf;
|
|
4
|
+
const roxygen_ast_1 = require("./roxygen-ast");
|
|
5
|
+
const type_1 = require("../lang-4.x/ast/model/type");
|
|
6
|
+
const roxygen_parse_1 = require("./roxygen-parse");
|
|
7
|
+
const CommentRetriever = {
|
|
8
|
+
[type_1.RType.Comment]: n => (0, roxygen_parse_1.parseRoxygenComment)([n.lexeme]),
|
|
9
|
+
[type_1.RType.Parameter]: (n, idMap) => {
|
|
10
|
+
// get the documentation of the parent function
|
|
11
|
+
const doc = n.info.parent ? getDocumentationOf(n.info.parent, idMap) : undefined;
|
|
12
|
+
const paramName = n.lexeme;
|
|
13
|
+
if (doc && paramName) {
|
|
14
|
+
if (Array.isArray(doc)) {
|
|
15
|
+
const res = doc.filter(t => t.type === roxygen_ast_1.KnownRoxygenTags.Param && t.value.name === paramName);
|
|
16
|
+
if (res.length === 1) {
|
|
17
|
+
return res[0];
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
return res;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
if (doc.type === roxygen_ast_1.KnownRoxygenTags.Param && doc.value.name === paramName) {
|
|
25
|
+
return doc;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Given a normalized AST and a node ID, returns the Roxygen documentation (if any) associated with that node.
|
|
34
|
+
* Please note that this does more than {@link parseRoxygenCommentsOfNode}, as it also traverses up the AST to find documentation.
|
|
35
|
+
* Additionally, this function instruments the normalized AST to cache the parsed documentation for future queries.
|
|
36
|
+
* @param idMap - The AST ID map to use for looking up nodes and traversing the AST.
|
|
37
|
+
* @param nodeId - The ID of the node to get documentation for.
|
|
38
|
+
*/
|
|
39
|
+
function getDocumentationOf(nodeId, idMap) {
|
|
40
|
+
const node = idMap.get(nodeId);
|
|
41
|
+
if (!node) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
else if ('doc' in node.info) {
|
|
45
|
+
return node.info.doc;
|
|
46
|
+
}
|
|
47
|
+
const retriever = CommentRetriever[node.type] ?? ((c, a) => (0, roxygen_parse_1.parseRoxygenCommentsOfNode)(c, a)?.tags);
|
|
48
|
+
const doc = retriever(node, idMap);
|
|
49
|
+
if (doc) {
|
|
50
|
+
// to avoid endless recursion, we block the caching here once:
|
|
51
|
+
node.info.doc = undefined;
|
|
52
|
+
// cache the documentation for future queries
|
|
53
|
+
const expanded = expandInheritsOfTags(doc, idMap);
|
|
54
|
+
node.info.doc = expanded;
|
|
55
|
+
return expanded;
|
|
56
|
+
}
|
|
57
|
+
return doc;
|
|
58
|
+
}
|
|
59
|
+
function expandInheritsOfTags(tags, idMap) {
|
|
60
|
+
const expandedTags = [];
|
|
61
|
+
const tagArray = Array.isArray(tags) ? tags : [tags];
|
|
62
|
+
for (const tag of tagArray) {
|
|
63
|
+
const expanded = expandInheritOfTag(tag, tagArray, idMap);
|
|
64
|
+
if (!expanded) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (Array.isArray(expanded)) {
|
|
68
|
+
expandedTags.push(...expanded);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
expandedTags.push(expanded);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (expandedTags.length === 1) {
|
|
75
|
+
return expandedTags[0];
|
|
76
|
+
}
|
|
77
|
+
return expandedTags;
|
|
78
|
+
}
|
|
79
|
+
function getDocumentationOfByName(name, idMap) {
|
|
80
|
+
for (const [, node] of idMap) {
|
|
81
|
+
const nodeName = node.lexeme ?? node.info.fullLexeme;
|
|
82
|
+
if (nodeName !== name) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
return getDocumentationOf(node.info.id, idMap);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function filterDocumentationForParams(doc, filter) {
|
|
89
|
+
if (!doc) {
|
|
90
|
+
return doc;
|
|
91
|
+
}
|
|
92
|
+
if (Array.isArray(doc)) {
|
|
93
|
+
return doc.filter(filter);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
return filter(doc) ? doc : undefined;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function expandInheritOfTag(tag, otherTags, idMap) {
|
|
100
|
+
if (tag.type === roxygen_ast_1.KnownRoxygenTags.Inherit) {
|
|
101
|
+
const inheritDoc = getDocumentationOfByName(tag.value.source, idMap);
|
|
102
|
+
return filterDocumentationForParams(inheritDoc, t => tag.value.components.includes(t.type));
|
|
103
|
+
}
|
|
104
|
+
else if (tag.type === roxygen_ast_1.KnownRoxygenTags.InheritDotParams) {
|
|
105
|
+
const inheritDoc = getDocumentationOfByName(tag.value.source, idMap);
|
|
106
|
+
return filterDocumentationForParams(inheritDoc, t => t.type === roxygen_ast_1.KnownRoxygenTags.Param && t.value.name === '...');
|
|
107
|
+
}
|
|
108
|
+
else if (tag.type === roxygen_ast_1.KnownRoxygenTags.InheritParams) {
|
|
109
|
+
const inheritDoc = getDocumentationOfByName(tag.value, idMap);
|
|
110
|
+
const alreadyExplainedParams = new Set(otherTags.filter(t => t.type === roxygen_ast_1.KnownRoxygenTags.Param).map(t => t.value.name));
|
|
111
|
+
return filterDocumentationForParams(inheritDoc, t => t.type === roxygen_ast_1.KnownRoxygenTags.Param && !alreadyExplainedParams.has(t.value.name));
|
|
112
|
+
}
|
|
113
|
+
return tag;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=documentation-provider.js.map
|
|
@@ -4,6 +4,8 @@ import type { AstIdMap, ParentInformation } from '../lang-4.x/ast/model/processi
|
|
|
4
4
|
/**
|
|
5
5
|
* Parses the roxygen comments attached to a node into a RoxygenBlock AST node.
|
|
6
6
|
* Will return `undefined` if there are no valid roxygen comments attached to the node.
|
|
7
|
+
* Please note that this does *not* do any clever mapping of parameters or requests.
|
|
8
|
+
* For a higher-level function that also traverses up the AST to find comments attached to parent nodes, see {@link getDocumentationOf}.
|
|
7
9
|
* @param node - The node to parse the roxygen comments for
|
|
8
10
|
* @param idMap - An optional id map to traverse up the AST to find comments attached to parent nodes
|
|
9
11
|
*/
|
|
@@ -20,5 +22,5 @@ type TagLine = [tag: string, remTagLine?: string];
|
|
|
20
22
|
* @see {@link parseRoxygenCommentsOfNode} - to parse comments attached to a node
|
|
21
23
|
*/
|
|
22
24
|
export declare function parseRoxygenComment(commentText: readonly string[]): RoxygenTag[];
|
|
23
|
-
export declare const firstAndRest: (firstName: string, secondName: string) => (s: RoxygenParseContext, t: TagLine) =>
|
|
25
|
+
export declare const firstAndRest: (firstName: string, secondName: string) => (s: RoxygenParseContext, t: TagLine) => TagLine | undefined;
|
|
24
26
|
export {};
|
|
@@ -26,6 +26,8 @@ function prepareCommentContext(commentText) {
|
|
|
26
26
|
/**
|
|
27
27
|
* Parses the roxygen comments attached to a node into a RoxygenBlock AST node.
|
|
28
28
|
* Will return `undefined` if there are no valid roxygen comments attached to the node.
|
|
29
|
+
* Please note that this does *not* do any clever mapping of parameters or requests.
|
|
30
|
+
* For a higher-level function that also traverses up the AST to find comments attached to parent nodes, see {@link getDocumentationOf}.
|
|
29
31
|
* @param node - The node to parse the roxygen comments for
|
|
30
32
|
* @param idMap - An optional id map to traverse up the AST to find comments attached to parent nodes
|
|
31
33
|
*/
|
|
@@ -47,7 +49,7 @@ function parseRoxygenCommentsOfNode(node, idMap) {
|
|
|
47
49
|
attachedTo: cur?.info.id,
|
|
48
50
|
requestNode: node.info.id,
|
|
49
51
|
range: [
|
|
50
|
-
...(0, range_1.mergeRanges)(
|
|
52
|
+
...(0, range_1.mergeRanges)(comments.map(c => c.location)),
|
|
51
53
|
comments.find(c => c.info.file)?.info.file
|
|
52
54
|
]
|
|
53
55
|
};
|
|
@@ -64,7 +66,10 @@ function parseRoxygenComment(commentText) {
|
|
|
64
66
|
tags: [],
|
|
65
67
|
idx: 0
|
|
66
68
|
};
|
|
67
|
-
val(state, [roxygen_ast_1.KnownRoxygenTags.Text]);
|
|
69
|
+
let tag = val(state, [roxygen_ast_1.KnownRoxygenTags.Text]);
|
|
70
|
+
while (tag) {
|
|
71
|
+
tag = parseRoxygenTag(state, tag);
|
|
72
|
+
}
|
|
68
73
|
return state.tags;
|
|
69
74
|
}
|
|
70
75
|
function atEnd(state) {
|
|
@@ -123,7 +128,7 @@ function val(state, tagName, lineToVal = l => l.join('\n').trim()) {
|
|
|
123
128
|
});
|
|
124
129
|
}
|
|
125
130
|
}
|
|
126
|
-
|
|
131
|
+
return nextTag;
|
|
127
132
|
}
|
|
128
133
|
const spaceVals = (s, t) => val(s, t, l => (0, args_1.splitAtEscapeSensitive)(l.join(' ')));
|
|
129
134
|
const flagVal = (s, t) => val(s, t, () => undefined);
|
|
@@ -204,11 +209,12 @@ const TagMap = {
|
|
|
204
209
|
content: l.join(' ')
|
|
205
210
|
}))
|
|
206
211
|
};
|
|
212
|
+
/** returns the next tag */
|
|
207
213
|
function parseRoxygenTag(state, tagName) {
|
|
208
214
|
if (tagName === undefined) {
|
|
209
|
-
return;
|
|
215
|
+
return undefined;
|
|
210
216
|
}
|
|
211
217
|
const parser = TagMap[tagName[0]] ?? val;
|
|
212
|
-
parser(state, tagName);
|
|
218
|
+
return parser(state, tagName);
|
|
213
219
|
}
|
|
214
220
|
//# sourceMappingURL=roxygen-parse.js.map
|
package/util/r-version.js
CHANGED
|
@@ -9,6 +9,18 @@ function makeVersion(version, original) {
|
|
|
9
9
|
semver.str = original;
|
|
10
10
|
return semver;
|
|
11
11
|
}
|
|
12
|
+
function tryNormalizeNumberPart(part) {
|
|
13
|
+
try {
|
|
14
|
+
const res = Number(part);
|
|
15
|
+
if (!Number.isNaN(res)) {
|
|
16
|
+
return String(res);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return part;
|
|
21
|
+
}
|
|
22
|
+
return part;
|
|
23
|
+
}
|
|
12
24
|
function normalizeVersion(version) {
|
|
13
25
|
version = version.trim();
|
|
14
26
|
let comparator = '';
|
|
@@ -29,7 +41,11 @@ function normalizeVersion(version) {
|
|
|
29
41
|
mainVersionParts.push('0');
|
|
30
42
|
}
|
|
31
43
|
}
|
|
32
|
-
|
|
44
|
+
let prerelease = '';
|
|
45
|
+
if (preReleaseParts.length > 0) {
|
|
46
|
+
prerelease = '-' + preReleaseParts.join('-').split('.').map(part => tryNormalizeNumberPart(part)).join('.');
|
|
47
|
+
}
|
|
48
|
+
return comparator + mainVersionParts.map(tryNormalizeNumberPart).join('.') + prerelease;
|
|
33
49
|
}
|
|
34
50
|
const AnyVerWithMaybeRangeRegex = /(\s*[<>=~^]*\s*\d+(\.\d*)*(-[0-9A-Za-z-.]+)?)/g;
|
|
35
51
|
function normalizeVersions(versions) {
|
package/util/range.d.ts
CHANGED
|
@@ -52,7 +52,7 @@ export declare function invalidRange(): SourceRange;
|
|
|
52
52
|
* If you are interested in combining overlapping ranges into a minimal set of ranges, see {@link combineRanges}.
|
|
53
53
|
* @throws if no ranges are provided
|
|
54
54
|
*/
|
|
55
|
-
export declare function mergeRanges(
|
|
55
|
+
export declare function mergeRanges(rs?: (SourceRange | undefined)[]): SourceRange;
|
|
56
56
|
/**
|
|
57
57
|
* @returns true iff `r1` starts and ends before `r2` starts (i.e., if `r1` and `r2` do not overlap and `r1` comes before `r2`
|
|
58
58
|
*/
|
package/util/range.js
CHANGED
|
@@ -45,7 +45,7 @@ function invalidRange() {
|
|
|
45
45
|
* If you are interested in combining overlapping ranges into a minimal set of ranges, see {@link combineRanges}.
|
|
46
46
|
* @throws if no ranges are provided
|
|
47
47
|
*/
|
|
48
|
-
function mergeRanges(
|
|
48
|
+
function mergeRanges(rs = []) {
|
|
49
49
|
const rsSafe = rs.filter(assert_1.isNotUndefined);
|
|
50
50
|
(0, assert_1.guard)(rsSafe.length > 0, 'Cannot merge no ranges');
|
|
51
51
|
return rsSafe.reduce(([sl, sc, el, ec], [nsl, nsc, nel, nec]) => [
|
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.8.
|
|
9
|
+
const version = '2.8.4';
|
|
10
10
|
/**
|
|
11
11
|
* Retrieves the current flowR version as a new {@link SemVer} object.
|
|
12
12
|
*/
|