@eagleoutice/flowr 2.1.8 → 2.1.9
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/benchmark/summarizer/first-phase/process.js +6 -5
- package/cli/repl/commands/repl-dataflow.js +5 -2
- package/cli/repl/commands/repl-normalize.js +5 -2
- package/cli/repl/commands/repl-query.js +2 -2
- package/cli/repl/server/messages/message-query.js +1 -1
- package/dataflow/environments/default-builtin-config.js +45 -6
- package/dataflow/environments/environment.d.ts +46 -8
- package/dataflow/environments/environment.js +24 -1
- package/dataflow/environments/identifier.d.ts +49 -7
- package/dataflow/environments/identifier.js +11 -2
- package/dataflow/extractor.js +5 -4
- package/dataflow/graph/dataflowgraph-builder.d.ts +6 -0
- package/dataflow/graph/dataflowgraph-builder.js +8 -0
- package/dataflow/graph/edge.d.ts +10 -4
- package/dataflow/graph/edge.js +12 -5
- package/dataflow/graph/graph.d.ts +41 -3
- package/dataflow/graph/graph.js +39 -34
- package/dataflow/graph/vertex.d.ts +66 -7
- package/dataflow/graph/vertex.js +15 -0
- package/dataflow/info.d.ts +79 -11
- package/dataflow/info.js +20 -0
- package/dataflow/internal/linker.d.ts +4 -2
- package/dataflow/internal/linker.js +12 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +2 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +5 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.d.ts +16 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +83 -6
- package/dataflow/internal/process/functions/call/common.js +1 -1
- package/documentation/doc-util/doc-dfg.d.ts +0 -1
- package/documentation/doc-util/doc-dfg.js +1 -14
- package/documentation/print-capabilities-markdown.js +1 -1
- package/documentation/print-dataflow-graph-wiki.js +26 -7
- package/documentation/print-linting-and-testing-wiki.js +60 -26
- package/documentation/print-query-wiki.js +1 -1
- package/package.json +17 -3
- package/queries/catalog/call-context-query/call-context-query-executor.js +1 -1
- package/queries/catalog/call-context-query/call-context-query-format.d.ts +13 -0
- package/queries/catalog/call-context-query/call-context-query-format.js +3 -1
- package/queries/catalog/call-context-query/cascade-action.d.ts +8 -0
- package/queries/catalog/call-context-query/cascade-action.js +13 -0
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +11 -1
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +41 -4
- package/queries/catalog/dependencies-query/dependencies-query-format.js +4 -0
- package/queries/query.d.ts +4 -4
- package/queries/query.js +17 -5
- package/r-bridge/lang-4.x/ast/model/model.d.ts +3 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +5 -1
- package/r-bridge/lang-4.x/ast/model/processing/node-id.d.ts +6 -1
- package/r-bridge/lang-4.x/ast/model/processing/node-id.js +6 -1
- package/slicing/static/slice-call.d.ts +7 -2
- package/slicing/static/slice-call.js +33 -44
- package/slicing/static/static-slicer.d.ts +5 -1
- package/slicing/static/static-slicer.js +22 -8
- package/slicing/static/visiting-queue.d.ts +4 -4
- package/slicing/static/visiting-queue.js +5 -3
- package/statistics/output/print-stats.js +2 -1
- package/statistics/summarizer/post-process/histogram.js +2 -1
- package/statistics/summarizer/post-process/post-process-output.js +2 -1
- package/statistics/summarizer/second-phase/process.js +3 -3
- package/util/arrays.d.ts +1 -1
- package/util/arrays.js +3 -3
- package/util/cfg/cfg.js +4 -2
- package/util/mermaid/cfg.js +1 -1
- package/util/summarizer.js +2 -2
- package/util/version.js +1 -1
|
@@ -84,11 +84,13 @@ function linkArgumentsOnCall(args, params, graph) {
|
|
|
84
84
|
if (param !== undefined) {
|
|
85
85
|
logger_1.dataflowLogger.trace(`mapping named argument "${name}" to parameter "${param.name.content}"`);
|
|
86
86
|
graph.addEdge(arg.nodeId, param.name.info.id, edge_1.EdgeType.DefinesOnCall);
|
|
87
|
+
graph.addEdge(param.name.info.id, arg.nodeId, edge_1.EdgeType.DefinedByOnCall);
|
|
87
88
|
matchedParameters.add(name);
|
|
88
89
|
}
|
|
89
90
|
else if (specialDotParameter !== undefined) {
|
|
90
91
|
logger_1.dataflowLogger.trace(`mapping named argument "${name}" to dot-dot-dot parameter`);
|
|
91
92
|
graph.addEdge(arg.nodeId, specialDotParameter.name.info.id, edge_1.EdgeType.DefinesOnCall);
|
|
93
|
+
graph.addEdge(specialDotParameter.name.info.id, arg.nodeId, edge_1.EdgeType.DefinedByOnCall);
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
96
|
const remainingParameter = params.filter(p => !matchedParameters.has(p.name.content));
|
|
@@ -103,6 +105,7 @@ function linkArgumentsOnCall(args, params, graph) {
|
|
|
103
105
|
if (specialDotParameter !== undefined) {
|
|
104
106
|
logger_1.dataflowLogger.trace(`mapping unnamed argument ${i} (id: ${arg.nodeId}) to dot-dot-dot parameter`);
|
|
105
107
|
graph.addEdge(arg.nodeId, specialDotParameter.name.info.id, edge_1.EdgeType.DefinesOnCall);
|
|
108
|
+
graph.addEdge(specialDotParameter.name.info.id, arg.nodeId, edge_1.EdgeType.DefinedByOnCall);
|
|
106
109
|
}
|
|
107
110
|
else {
|
|
108
111
|
logger_1.dataflowLogger.warn(`skipping argument ${i} as there is no corresponding parameter - R should block that`);
|
|
@@ -112,6 +115,7 @@ function linkArgumentsOnCall(args, params, graph) {
|
|
|
112
115
|
const param = remainingParameter[i];
|
|
113
116
|
logger_1.dataflowLogger.trace(`mapping unnamed argument ${i} (id: ${arg.nodeId}) to parameter "${param.name.content}"`);
|
|
114
117
|
graph.addEdge(arg.nodeId, param.name.info.id, edge_1.EdgeType.DefinesOnCall);
|
|
118
|
+
graph.addEdge(param.name.info.id, arg.nodeId, edge_1.EdgeType.DefinedByOnCall);
|
|
115
119
|
}
|
|
116
120
|
}
|
|
117
121
|
function linkFunctionCallArguments(targetId, idMap, functionCallName, functionRootId, callArgs, finalGraph) {
|
|
@@ -138,7 +142,8 @@ function linkFunctionCallWithSingleTarget(graph, def, info, idMap) {
|
|
|
138
142
|
continue;
|
|
139
143
|
}
|
|
140
144
|
for (const def of defs) {
|
|
141
|
-
graph.addEdge(
|
|
145
|
+
graph.addEdge(ingoing, def, edge_1.EdgeType.DefinedByOnCall);
|
|
146
|
+
graph.addEdge(id, def, edge_1.EdgeType.DefinesOnCall);
|
|
142
147
|
}
|
|
143
148
|
}
|
|
144
149
|
}
|
|
@@ -187,8 +192,10 @@ function linkFunctionCalls(graph, idMap, thisGraph) {
|
|
|
187
192
|
}
|
|
188
193
|
return calledFunctionDefinitions;
|
|
189
194
|
}
|
|
190
|
-
/**
|
|
191
|
-
function
|
|
195
|
+
/**
|
|
196
|
+
* convenience function returning all known call targets, as well as the name source which defines them
|
|
197
|
+
*/
|
|
198
|
+
function getAllFunctionCallTargets(call, graph, environment) {
|
|
192
199
|
const found = [];
|
|
193
200
|
const callVertex = graph.get(call, true);
|
|
194
201
|
if (callVertex === undefined) {
|
|
@@ -198,8 +205,8 @@ function getAllFunctionCallTargets(call, graph) {
|
|
|
198
205
|
if (info.tag !== vertex_1.VertexType.FunctionCall) {
|
|
199
206
|
return [];
|
|
200
207
|
}
|
|
201
|
-
if (info.name !== undefined && info.environment !== undefined) {
|
|
202
|
-
const functionCallDefs = (0, resolve_by_name_1.resolveByName)(info.name, info.environment, identifier_1.ReferenceType.Function)?.map(d => d.nodeId) ?? [];
|
|
208
|
+
if (info.name !== undefined && (environment !== undefined || info.environment !== undefined)) {
|
|
209
|
+
const functionCallDefs = (0, resolve_by_name_1.resolveByName)(info.name, environment ?? info.environment, identifier_1.ReferenceType.Function)?.map(d => d.nodeId) ?? [];
|
|
203
210
|
for (const [target, outgoingEdge] of outgoingEdges.entries()) {
|
|
204
211
|
if ((0, edge_1.edgeIncludesType)(outgoingEdge.types, edge_1.EdgeType.Calls)) {
|
|
205
212
|
functionCallDefs.push(target);
|
|
@@ -15,6 +15,8 @@ export interface AssignmentConfiguration extends ForceArguments {
|
|
|
15
15
|
readonly makeMaybe?: boolean;
|
|
16
16
|
readonly quoteSource?: boolean;
|
|
17
17
|
readonly canBeReplacement?: boolean;
|
|
18
|
+
/** is the target a variable pointing at the actual name? */
|
|
19
|
+
readonly targetVariable?: boolean;
|
|
18
20
|
}
|
|
19
21
|
/**
|
|
20
22
|
* Processes an assignment, i.e., `<target> <- <source>`.
|
|
@@ -57,7 +57,7 @@ args, rootId, data, config) {
|
|
|
57
57
|
const effectiveArgs = getEffectiveOrder(config, args);
|
|
58
58
|
const { target, source } = extractSourceAndTarget(effectiveArgs, name);
|
|
59
59
|
const { type, named } = target;
|
|
60
|
-
if (type === type_1.RType.Symbol) {
|
|
60
|
+
if (!config.targetVariable && type === type_1.RType.Symbol) {
|
|
61
61
|
const res = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, reverseOrder: !config.swapSourceAndTarget, forceArgs: config.forceArgs });
|
|
62
62
|
return processAssignmentToSymbol({
|
|
63
63
|
...config,
|
|
@@ -107,8 +107,10 @@ args, rootId, data, config) {
|
|
|
107
107
|
else if (type === type_1.RType.String) {
|
|
108
108
|
return processAssignmentToString(target, args, name, rootId, data, config, source);
|
|
109
109
|
}
|
|
110
|
-
logger_1.dataflowLogger.warn(`Assignment ${name.content} has an unknown target type ${target.type}
|
|
111
|
-
|
|
110
|
+
logger_1.dataflowLogger.warn(`Assignment ${name.content} has an unknown target type ${target.type} => unknown impact`);
|
|
111
|
+
const info = (0, known_call_handling_1.processKnownFunctionCall)({ name, args: effectiveArgs, rootId, data, forceArgs: config.forceArgs }).information;
|
|
112
|
+
info.graph.markIdForUnknownSideEffects(rootId);
|
|
113
|
+
return info;
|
|
112
114
|
}
|
|
113
115
|
function extractSourceAndTarget(args, name) {
|
|
114
116
|
const source = (0, unpack_argument_1.unpackArgument)(args[1], false);
|
|
@@ -4,4 +4,20 @@ import type { ParentInformation } from '../../../../../../r-bridge/lang-4.x/ast/
|
|
|
4
4
|
import type { RSymbol } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
|
|
5
5
|
import type { RFunctionArgument } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
6
6
|
import type { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
7
|
+
import { DataflowGraph } from '../../../../../graph/graph';
|
|
8
|
+
import type { REnvironmentInformation } from '../../../../../environments/environment';
|
|
7
9
|
export declare function processFunctionDefinition<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>): DataflowInformation;
|
|
10
|
+
export declare function retrieveActiveEnvironment(callerEnvironment: REnvironmentInformation | undefined, baseEnvironment: REnvironmentInformation): REnvironmentInformation;
|
|
11
|
+
/**
|
|
12
|
+
* Update the closure links of all nested function definitions
|
|
13
|
+
* @param graph - dataflow graph to collect the function definitions from and to update the closure links for
|
|
14
|
+
* @param outEnvironment - active environment on resolving closures (i.e., exit of the function definition)
|
|
15
|
+
* @param fnId - id of the function definition to update the closure links for
|
|
16
|
+
*/
|
|
17
|
+
export declare function updateNestedFunctionClosures(graph: DataflowGraph, outEnvironment: REnvironmentInformation, fnId: NodeId): void;
|
|
18
|
+
/**
|
|
19
|
+
* Update the closure links of all nested function calls, this is probably to be done once at the end of the script
|
|
20
|
+
* @param graph - dataflow graph to collect the function calls from and to update the closure links for
|
|
21
|
+
* @param outEnvironment - active environment on resolving closures (i.e., exit of the function definition)
|
|
22
|
+
*/
|
|
23
|
+
export declare function updateNestedFunctionCalls(graph: DataflowGraph, outEnvironment: REnvironmentInformation): void;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.processFunctionDefinition = processFunctionDefinition;
|
|
4
|
+
exports.retrieveActiveEnvironment = retrieveActiveEnvironment;
|
|
5
|
+
exports.updateNestedFunctionClosures = updateNestedFunctionClosures;
|
|
6
|
+
exports.updateNestedFunctionCalls = updateNestedFunctionCalls;
|
|
4
7
|
const processor_1 = require("../../../../../processor");
|
|
5
8
|
const linker_1 = require("../../../../linker");
|
|
6
9
|
const known_call_handling_1 = require("../known-call-handling");
|
|
@@ -77,7 +80,7 @@ function processFunctionDefinition(name, args, rootId, data) {
|
|
|
77
80
|
graph: new Set(subgraph.rootIds()),
|
|
78
81
|
environment: outEnvironment
|
|
79
82
|
};
|
|
80
|
-
updateNestedFunctionClosures(subgraph, outEnvironment, name);
|
|
83
|
+
updateNestedFunctionClosures(subgraph, outEnvironment, name.info.id);
|
|
81
84
|
const exitPoints = body.exitPoints;
|
|
82
85
|
const graph = new graph_1.DataflowGraph(data.completeAst.idMap).mergeWith(subgraph, false);
|
|
83
86
|
graph.addVertex({
|
|
@@ -99,10 +102,32 @@ function processFunctionDefinition(name, args, rootId, data) {
|
|
|
99
102
|
environment: originalEnvironment
|
|
100
103
|
};
|
|
101
104
|
}
|
|
102
|
-
|
|
105
|
+
// this is no longer necessary when we update environments to be back to front (e.g., with a list of environments)
|
|
106
|
+
// this favors the bigger environment
|
|
107
|
+
function retrieveActiveEnvironment(callerEnvironment, baseEnvironment) {
|
|
108
|
+
callerEnvironment ??= (0, environment_1.initializeCleanEnvironments)(true);
|
|
109
|
+
let level = callerEnvironment.level ?? 0;
|
|
110
|
+
if (baseEnvironment.level !== level) {
|
|
111
|
+
while (baseEnvironment.level < level) {
|
|
112
|
+
baseEnvironment = (0, scoping_1.pushLocalEnvironment)(baseEnvironment);
|
|
113
|
+
}
|
|
114
|
+
while (baseEnvironment.level > level) {
|
|
115
|
+
callerEnvironment = (0, scoping_1.pushLocalEnvironment)(callerEnvironment);
|
|
116
|
+
level = callerEnvironment.level;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return (0, overwrite_1.overwriteEnvironment)(baseEnvironment, callerEnvironment);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Update the closure links of all nested function definitions
|
|
123
|
+
* @param graph - dataflow graph to collect the function definitions from and to update the closure links for
|
|
124
|
+
* @param outEnvironment - active environment on resolving closures (i.e., exit of the function definition)
|
|
125
|
+
* @param fnId - id of the function definition to update the closure links for
|
|
126
|
+
*/
|
|
127
|
+
function updateNestedFunctionClosures(graph, outEnvironment, fnId) {
|
|
103
128
|
// track *all* function definitions - including those nested within the current graph,
|
|
104
129
|
// try to resolve their 'in' by only using the lowest scope which will be popped after this definition
|
|
105
|
-
for (const [id, { subflow, tag }] of
|
|
130
|
+
for (const [id, { subflow, tag }] of graph.vertices(true)) {
|
|
106
131
|
if (tag !== vertex_1.VertexType.FunctionDefinition) {
|
|
107
132
|
continue;
|
|
108
133
|
}
|
|
@@ -114,15 +139,67 @@ function updateNestedFunctionClosures(subgraph, outEnvironment, name) {
|
|
|
114
139
|
remainingIn.push(ingoing);
|
|
115
140
|
continue;
|
|
116
141
|
}
|
|
117
|
-
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Found ${resolved.length} references to open ref ${id} in closure of function definition ${
|
|
142
|
+
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Found ${resolved.length} references to open ref ${id} in closure of function definition ${fnId}`);
|
|
118
143
|
for (const ref of resolved) {
|
|
119
|
-
|
|
144
|
+
graph.addEdge(ingoing, ref, edge_1.EdgeType.Reads);
|
|
120
145
|
}
|
|
121
146
|
}
|
|
122
|
-
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Keeping ${remainingIn.length} references to open ref ${id} in closure of function definition ${
|
|
147
|
+
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Keeping ${remainingIn.length} references to open ref ${id} in closure of function definition ${fnId}`);
|
|
123
148
|
subflow.in = remainingIn;
|
|
124
149
|
}
|
|
125
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Update the closure links of all nested function calls, this is probably to be done once at the end of the script
|
|
153
|
+
* @param graph - dataflow graph to collect the function calls from and to update the closure links for
|
|
154
|
+
* @param outEnvironment - active environment on resolving closures (i.e., exit of the function definition)
|
|
155
|
+
*/
|
|
156
|
+
function updateNestedFunctionCalls(graph, outEnvironment) {
|
|
157
|
+
// track *all* function definitions - including those nested within the current graph,
|
|
158
|
+
// try to resolve their 'in' by only using the lowest scope which will be popped after this definition
|
|
159
|
+
for (const [id, { onlyBuiltin, tag, environment, name }] of graph.vertices(true)) {
|
|
160
|
+
if (tag !== vertex_1.VertexType.FunctionCall || !name || onlyBuiltin) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
// only the call environment counts!
|
|
164
|
+
if (environment) {
|
|
165
|
+
while (outEnvironment.level > environment.level) {
|
|
166
|
+
outEnvironment = (0, scoping_1.popLocalEnvironment)(outEnvironment);
|
|
167
|
+
}
|
|
168
|
+
while (outEnvironment.level < environment.level) {
|
|
169
|
+
outEnvironment = (0, scoping_1.pushLocalEnvironment)(outEnvironment);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const effectiveEnvironment = environment ? (0, overwrite_1.overwriteEnvironment)(outEnvironment, environment) : outEnvironment;
|
|
173
|
+
const targets = (0, linker_1.getAllFunctionCallTargets)(id, graph, effectiveEnvironment);
|
|
174
|
+
for (const target of targets) {
|
|
175
|
+
const targetVertex = graph.getVertex(target);
|
|
176
|
+
if (targetVertex?.tag !== vertex_1.VertexType.FunctionDefinition) {
|
|
177
|
+
// support reads on symbols
|
|
178
|
+
if (targetVertex?.tag === vertex_1.VertexType.Use) {
|
|
179
|
+
graph.addEdge(id, target, edge_1.EdgeType.Reads);
|
|
180
|
+
}
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
graph.addEdge(id, target, edge_1.EdgeType.Calls);
|
|
184
|
+
const ingoingRefs = targetVertex.subflow.in;
|
|
185
|
+
const remainingIn = [];
|
|
186
|
+
for (const ingoing of ingoingRefs) {
|
|
187
|
+
const resolved = ingoing.name ? (0, resolve_by_name_1.resolveByName)(ingoing.name, effectiveEnvironment, ingoing.type) : undefined;
|
|
188
|
+
if (resolved === undefined) {
|
|
189
|
+
remainingIn.push(ingoing);
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Found ${resolved.length} references to open ref ${id} in closure of function definition ${id}`);
|
|
193
|
+
for (const def of resolved) {
|
|
194
|
+
graph.addEdge(ingoing, def, edge_1.EdgeType.DefinedByOnCall);
|
|
195
|
+
graph.addEdge(id, def, edge_1.EdgeType.DefinesOnCall);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Keeping ${remainingIn.length} references to open ref ${id} in closure of function definition ${id}`);
|
|
199
|
+
targetVertex.subflow.in = remainingIn;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
126
203
|
function prepareFunctionEnvironment(data) {
|
|
127
204
|
let env = (0, environment_1.initializeCleanEnvironments)();
|
|
128
205
|
for (let i = 0; i < data.environment.level + 1 /* add another env */; i++) {
|
|
@@ -35,7 +35,7 @@ function forceVertexArgumentValueReferences(rootId, value, graph, env) {
|
|
|
35
35
|
// try to resolve them against the current environment
|
|
36
36
|
for (const ref of [...value.in, ...containedSubflowIn.flatMap(n => n.subflow.in)]) {
|
|
37
37
|
if (ref.name) {
|
|
38
|
-
const resolved = (0, resolve_by_name_1.resolveByName)(ref.name, env, ref.type) ?? [];
|
|
38
|
+
const resolved = ref.name ? (0, resolve_by_name_1.resolveByName)(ref.name, env, ref.type) ?? [] : [];
|
|
39
39
|
for (const resolve of resolved) {
|
|
40
40
|
graph.addEdge(ref.nodeId, resolve.nodeId, edge_1.EdgeType.Reads);
|
|
41
41
|
}
|
|
@@ -10,7 +10,6 @@ export interface PrintDataflowGraphOptions {
|
|
|
10
10
|
readonly codeOpen?: boolean;
|
|
11
11
|
readonly exposeResult?: boolean;
|
|
12
12
|
readonly switchCodeAndGraph?: boolean;
|
|
13
|
-
readonly hideEnvInMermaid?: boolean;
|
|
14
13
|
}
|
|
15
14
|
export declare function formatSideEffect(ef: UnknownSidEffect): string;
|
|
16
15
|
export declare function printDfGraphForCode(shell: RShell, code: string, options: PrintDataflowGraphOptions & {
|
|
@@ -32,7 +32,7 @@ function formatSideEffect(ef) {
|
|
|
32
32
|
return `${ef}`;
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
-
async function printDfGraphForCode(shell, code, { mark, showCode = true, codeOpen = false, exposeResult, switchCodeAndGraph = false
|
|
35
|
+
async function printDfGraphForCode(shell, code, { mark, showCode = true, codeOpen = false, exposeResult, switchCodeAndGraph = false } = {}) {
|
|
36
36
|
const now = performance.now();
|
|
37
37
|
const result = await new pipeline_executor_1.PipelineExecutor(default_pipelines_1.DEFAULT_DATAFLOW_PIPELINE, {
|
|
38
38
|
shell,
|
|
@@ -60,19 +60,6 @@ We encountered ${result.dataflow.graph.unknownSideEffects.size > 0 ? 'unknown si
|
|
|
60
60
|
|
|
61
61
|
${switchCodeAndGraph ? dfGraph : codeText}
|
|
62
62
|
|
|
63
|
-
<details>
|
|
64
|
-
|
|
65
|
-
<summary style="color:gray">Mermaid Code ${(mark?.size ?? 0) > 0 ? '(without markings)' : ''}</summary>
|
|
66
|
-
|
|
67
|
-
\`\`\`
|
|
68
|
-
${(0, dfg_1.graphToMermaid)({
|
|
69
|
-
graph: result.dataflow.graph,
|
|
70
|
-
prefix: 'flowchart LR',
|
|
71
|
-
includeEnvironments: !hideEnvInMermaid
|
|
72
|
-
}).string}
|
|
73
|
-
\`\`\`
|
|
74
|
-
|
|
75
|
-
</details>
|
|
76
63
|
|
|
77
64
|
</details>
|
|
78
65
|
|
|
@@ -39,7 +39,7 @@ function printAsMarkdown(capabilities, depth = 0, lines = []) {
|
|
|
39
39
|
function getPreamble() {
|
|
40
40
|
const currentDateAndTime = new Date().toISOString().replace('T', ', ').replace(/\.\d+Z$/, ' UTC');
|
|
41
41
|
const shortenFilename = module.filename.replace(/^.*src\//, 'src/');
|
|
42
|
-
return `_This document was generated from '${shortenFilename}' on ${currentDateAndTime}
|
|
42
|
+
return `_This document was generated from '${shortenFilename}' on ${currentDateAndTime} summarizing flowR's current capabilities (v${(0, version_1.flowrVersion)().format()})._
|
|
43
43
|
|
|
44
44
|
The code-font behind each capability name is a link to the capability's id. This id can be used to reference the capability in a labeled test within flowR.
|
|
45
45
|
Besides, we use colored bullets like this:
|
|
@@ -561,26 +561,45 @@ However, nested definitions can carry it (in the nested case, \`x\` is defined b
|
|
|
561
561
|
code: 'foo <- function() x\nfoo()',
|
|
562
562
|
expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().returns('2@foo', '1@x')
|
|
563
563
|
}, []]);
|
|
564
|
+
const lateBindingExample = `
|
|
565
|
+
f <- function() x
|
|
566
|
+
x <- 3
|
|
567
|
+
f()
|
|
568
|
+
`.trim();
|
|
569
|
+
const dfInfo = await (0, doc_dfg_1.printDfGraphForCode)(shell, lateBindingExample, { switchCodeAndGraph: true, codeOpen: true, mark: new Set([1, '1->5', '9->5']) });
|
|
564
570
|
edgeExplanations.set(edge_1.EdgeType.DefinesOnCall, [{
|
|
565
571
|
shell: shell,
|
|
566
572
|
name: 'DefinesOnCall Edge',
|
|
567
573
|
type: edge_1.EdgeType.DefinesOnCall,
|
|
568
|
-
description:
|
|
574
|
+
description: `*This edge is usually joined with ${linkEdgeName(edge_1.EdgeType.DefinedByOnCall)}!*
|
|
569
575
|
|
|
570
|
-
|
|
576
|
+
Links an Argument to whichever parameter they cause to be defined if the related function call is invoked.
|
|
577
|
+
|
|
578
|
+
In the context of functions which access their closure environment these edges play another tricky role as there are many cases
|
|
579
|
+
made more difficult by R's way of allowing closure environments to later receive variables.
|
|
580
|
+
Consider the following scenario in which we first define a function which returns the value of a variable named \`x\` and then define \`x\`
|
|
581
|
+
only after we defined the function:
|
|
582
|
+
|
|
583
|
+
${dfInfo}
|
|
584
|
+
|
|
585
|
+
The final call evaluates to \`3\` (similar to if we would have defined \`x\` before the function definition).
|
|
586
|
+
Within a dataflow graph you can see this with two edges. The \`x\` within the function body will have a ${linkEdgeName(edge_1.EdgeType.DefinedByOnCall)}
|
|
587
|
+
to every definition it _may_ refer to. In turn, each call vertex calling the function which encloses the use of \`x\` will have a
|
|
588
|
+
${linkEdgeName(edge_1.EdgeType.DefinesOnCall)} edge to the definition(s) it causes to be active within the function body.
|
|
589
|
+
`,
|
|
571
590
|
code: 'f <- function(x) {}\nf(x=1)',
|
|
572
591
|
// here we use the ids as the argument wrappers are not easily selected with slicing criteria
|
|
573
|
-
expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().definesOnCall('$11', '$1')
|
|
592
|
+
expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().definesOnCall('$11', '$1').definedByOnCall('$1', '$11')
|
|
574
593
|
}, []]);
|
|
575
594
|
edgeExplanations.set(edge_1.EdgeType.DefinedByOnCall, [{
|
|
576
595
|
shell: shell,
|
|
577
596
|
name: 'DefinedByOnCall Edge',
|
|
578
597
|
type: edge_1.EdgeType.DefinedByOnCall,
|
|
579
|
-
description:
|
|
598
|
+
description: `*This edge is usually joined with ${linkEdgeName(edge_1.EdgeType.DefinesOnCall)}!*
|
|
580
599
|
|
|
581
|
-
This represents the other
|
|
600
|
+
This represents the other part of the ${linkEdgeName(edge_1.EdgeType.DefinesOnCall)} edge (e.g., links the parameter to the argument). Please look there for further documentation.`,
|
|
582
601
|
code: 'f <- function(x) {}\nf(x=1)',
|
|
583
|
-
expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().definesOnCall('$11', '$1')
|
|
602
|
+
expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().definesOnCall('$11', '$1').definedByOnCall('$1', '$11')
|
|
584
603
|
}, []]);
|
|
585
604
|
edgeExplanations.set(edge_1.EdgeType.Argument, [{
|
|
586
605
|
shell: shell,
|
|
@@ -611,7 +630,7 @@ Marks cases in which R's non-standard evaluation mechanisms cause the default se
|
|
|
611
630
|
${(0, doc_structure_1.block)({
|
|
612
631
|
type: 'NOTE',
|
|
613
632
|
content: `
|
|
614
|
-
What to do if you encounter this
|
|
633
|
+
What to do if you encounter a vertex marked with this edge?
|
|
615
634
|
|
|
616
635
|
This depends on your analysis. To handle many real-world sources correctly you are probably fine with just ignoring it.
|
|
617
636
|
Yet, you may choose to follow these references for other queries. For now, _flowR's_ support for non-standard evaluation is limited.
|
|
@@ -3,9 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const log_1 = require("../../test/functionality/_helper/log");
|
|
4
4
|
const doc_code_1 = require("./doc-util/doc-code");
|
|
5
5
|
const doc_files_1 = require("./doc-util/doc-files");
|
|
6
|
+
const doc_structure_1 = require("./doc-util/doc-structure");
|
|
6
7
|
function getText() {
|
|
7
8
|
return `
|
|
8
|
-
For the latest code
|
|
9
|
+
For the latest code coverage information, see [codecov.io](${doc_files_1.FlowrCodecovRef}),
|
|
9
10
|
for the latest benchmark results, see the [benchmark results](${doc_files_1.FlowrSiteBaseRef}/wiki/stats/benchmark) wiki page.
|
|
10
11
|
|
|
11
12
|
- [Testing Suites](#testing-suites)
|
|
@@ -13,32 +14,37 @@ for the latest benchmark results, see the [benchmark results](${doc_files_1.Flow
|
|
|
13
14
|
- [Test Structure](#test-structure)
|
|
14
15
|
- [Writing a Test](#writing-a-test)
|
|
15
16
|
- [Running Only Some Tests](#running-only-some-tests)
|
|
17
|
+
- [System Tests](#system-tests)
|
|
16
18
|
- [Performance Tests](#performance-tests)
|
|
17
19
|
- [Oh no, the tests are slow](#oh-no-the-tests-are-slow)
|
|
18
20
|
- [Testing Within Your IDE](#testing-within-your-ide)
|
|
19
|
-
- [
|
|
20
|
-
- [
|
|
21
|
+
- [VS Code](#vs-code)
|
|
22
|
+
- [Webstorm](#webstorm)
|
|
21
23
|
- [CI Pipeline](#ci-pipeline)
|
|
22
24
|
- [Linting](#linting)
|
|
23
25
|
- [Oh no, the linter fails](#oh-no-the-linter-fails)
|
|
24
26
|
- [License Checker](#license-checker)
|
|
27
|
+
- [Debugging](#debugging)
|
|
28
|
+
- [VS Code](#vs-code-1)
|
|
25
29
|
|
|
26
30
|
## Testing Suites
|
|
27
31
|
|
|
28
|
-
Currently, flowR contains
|
|
29
|
-
|
|
32
|
+
Currently, flowR contains three testing suites: one for [functionality](#functionality-tests),
|
|
33
|
+
one for [system tests](#system-tests), and one for [performance](#performance-tests). We explain each of them in the following.
|
|
34
|
+
In addition to running those tests, you can use the more generalized \`npm run checkup\`.
|
|
35
|
+
This command includes the construction of the docker image, the generation of the wiki pages, and the linter.
|
|
30
36
|
|
|
31
37
|
### Functionality Tests
|
|
32
38
|
|
|
33
39
|
The functionality tests represent conventional unit (and depending on your terminology component/api) tests.
|
|
34
40
|
We use [vitest](https://vitest.dev/) as our testing framework.
|
|
35
|
-
You can run the tests by issuing:
|
|
41
|
+
You can run the tests by issuing (some quick benchmarks may be available with \`vitest bench\`):
|
|
36
42
|
|
|
37
43
|
${(0, doc_code_1.codeBlock)('shell', 'npm run test')}
|
|
38
44
|
|
|
39
45
|
Within the commandline,
|
|
40
|
-
this should automatically drop you into a watch mode which will automatically re-run
|
|
41
|
-
If, at any time there are too many errors, you can use \`--bail=<value>\` to stop the tests after a certain number of errors.
|
|
46
|
+
this should automatically drop you into a watch mode which will automatically re-run (potentially) affected tests if you change the code.
|
|
47
|
+
If, at any time there are too many errors for you to comprehend, you can use \`--bail=<value>\` to stop the tests after a certain number of errors.
|
|
42
48
|
For example:
|
|
43
49
|
|
|
44
50
|
${(0, doc_code_1.codeBlock)('shell', 'npm run test -- --bail=1')}
|
|
@@ -51,10 +57,10 @@ To run all tests, including a coverage report and label summary, run:
|
|
|
51
57
|
|
|
52
58
|
${(0, doc_code_1.codeBlock)('shell', 'npm run test-full')}
|
|
53
59
|
|
|
54
|
-
However, depending on your local R
|
|
55
|
-
(or
|
|
60
|
+
However, depending on your local version of R, your network connection, and other factors (each test may have a set of criteria),
|
|
61
|
+
some tests may be skipped automatically as they do not apply to your current system setup (or cannot be tested with the current prerequisites).
|
|
56
62
|
Each test can specify such requirements as part of the \`TestConfiguration\`, which is then used in the \`test.skipIf\` function of _vitest_.
|
|
57
|
-
It is up to the [ci](#ci-pipeline) to run the tests on different systems to ensure that those tests
|
|
63
|
+
It is up to the [ci](#ci-pipeline) to run the tests on different systems to ensure that those tests run.
|
|
58
64
|
|
|
59
65
|
#### Test Structure
|
|
60
66
|
|
|
@@ -62,12 +68,18 @@ All functionality tests are to be located under [test/functionality](${doc_files
|
|
|
62
68
|
|
|
63
69
|
This folder contains three special and important elements:
|
|
64
70
|
|
|
65
|
-
- \`test-setup\` which is the entry point if *all* tests are run. It should automatically disable logging statements and configure global variables (e.g., if installation tests should run).
|
|
66
|
-
- \`_helper
|
|
67
|
-
- \`test-summary\` which may produce a summary of the covered capabilities.
|
|
71
|
+
- \`test-setup.ts\` which is the entry point if *all* tests are run. It should automatically disable logging statements and configure global variables (e.g., if installation tests should run).
|
|
72
|
+
- \`_helper/\` folder which contains helper functions to be used by other tests.
|
|
73
|
+
- \`test-summary.ts\` which may produce a summary of the covered capabilities.
|
|
68
74
|
|
|
69
|
-
|
|
70
|
-
|
|
75
|
+
${(0, doc_structure_1.block)({
|
|
76
|
+
type: 'WARNING',
|
|
77
|
+
content: `
|
|
78
|
+
We name all test files using the \`.test.ts\` suffix and try to run them in parallel.
|
|
79
|
+
Whenever this is not possible (e.g., when using \`withShell\`), please use \`describe.sequential\`
|
|
80
|
+
to disable parallel execution for the respective test (otherwise, such tests are flaky).
|
|
81
|
+
`
|
|
82
|
+
})}
|
|
71
83
|
|
|
72
84
|
#### Writing a Test
|
|
73
85
|
|
|
@@ -86,10 +98,11 @@ assertDataflow(label('simple variable', ['name-normal']), shell,
|
|
|
86
98
|
`)}
|
|
87
99
|
|
|
88
100
|
When writing dataflow tests, additional settings can be used to reduce the amount of graph data that needs to be pre-written. Notably:
|
|
101
|
+
|
|
89
102
|
- \`expectIsSubgraph\` indicates that the expected graph is a subgraph, rather than the full graph that the test should generate. The test will then only check if the supplied graph is contained in the result graph, rather than an exact match.
|
|
90
103
|
- \`resolveIdsAsCriterion\` indicates that the ids given in the expected (sub)graph should be resolved as [slicing criteria](${doc_files_1.FlowrWikiBaseRef}/Terminology#slicing-criterion) rather than actual ids. For example, passing \`12@a\` as an id in the expected (sub)graph will cause it to be resolved as the corresponding id.
|
|
91
104
|
|
|
92
|
-
The following example shows both in use
|
|
105
|
+
The following example shows both in use:
|
|
93
106
|
${(0, doc_code_1.codeBlock)('typescript', `
|
|
94
107
|
assertDataflow(label('without distractors', [...OperatorDatabase['<-'].capabilities, 'numbers', 'name-normal', 'newlines', 'name-escaped']),
|
|
95
108
|
shell, '\`a\` <- 2\\na',
|
|
@@ -108,10 +121,25 @@ assertDataflow(label('without distractors', [...OperatorDatabase['<-'].capabilit
|
|
|
108
121
|
To run only some tests, vitest allows you to [filter](https://vitest.dev/guide/filtering.html) tests.
|
|
109
122
|
Besides, you can use the watch mode (with \`npm run test\`) to only run tests that are affected by your changes.
|
|
110
123
|
|
|
124
|
+
### System Tests
|
|
125
|
+
|
|
126
|
+
In contrast to the [functionality tests](#functionality-tests), the system tests use runners like the \`npm\` scripts
|
|
127
|
+
to test the behavior of the whole system, for example, by running the CLI or the server.
|
|
128
|
+
They are slower and hence not part of \`npm run test\` but can be run using:
|
|
129
|
+
${(0, doc_code_1.codeBlock)('shell', 'npm run test:system')}
|
|
130
|
+
To work, they require you to set up your system correctly (e.g., have \`npm\` available on your path).
|
|
131
|
+
The CI environment will make sure of that. At the moment, these tests are not labeled and only intended
|
|
132
|
+
to check basic availability of *flowR*'s core features (as we test the functionality of these features dedicately
|
|
133
|
+
with the [functionality tests](#functionality-tests)).
|
|
134
|
+
|
|
135
|
+
Have a look at the [test/system-tests](${doc_files_1.RemoteFlowrFilePathBaseRef}test/system-tests) folder for more information.
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
111
139
|
### Performance Tests
|
|
112
140
|
|
|
113
141
|
The performance test suite of *flowR* uses several suites to check for variations in the required times for certain steps.
|
|
114
|
-
Although we measure wall time in the CI (which is subject to rather large variations), it should give a rough idea
|
|
142
|
+
Although we measure wall time in the CI (which is subject to rather large variations), it should give a rough idea *flowR*'s performance.
|
|
115
143
|
Furthermore, the respective scripts can be used locally as well.
|
|
116
144
|
To run them, issue:
|
|
117
145
|
|
|
@@ -143,18 +171,18 @@ Please follow the official guide [here](https://www.jetbrains.com/help/webstorm/
|
|
|
143
171
|
|
|
144
172
|
## CI Pipeline
|
|
145
173
|
|
|
146
|
-
We have several workflows defined in [.github/workflows](
|
|
174
|
+
We have several workflows defined in [.github/workflows](${doc_files_1.RemoteFlowrFilePathBaseRef}/.github/workflows/).
|
|
147
175
|
We explain the most important workflows in the following:
|
|
148
176
|
|
|
149
|
-
- [qa.yaml](
|
|
177
|
+
- [qa.yaml](${doc_files_1.RemoteFlowrFilePathBaseRef}/.github/workflows/qa.yaml) is the main workflow that will run different steps depending on several factors. It is responsible for:
|
|
150
178
|
- running the [functionality](#functionality-tests) and [performance tests](#performance-tests)
|
|
151
179
|
- uploading the results to the [benchmark page](${doc_files_1.FlowrSiteBaseRef}/wiki/stats/benchmark) for releases
|
|
152
180
|
- running the [functionality tests](#functionality-tests) on different operating systems (Windows, macOS, Linux) and with different versions of R
|
|
153
181
|
- reporting code coverage
|
|
154
182
|
- running the [linter](#linting) and reporting its results
|
|
155
183
|
- deploying the documentation to [GitHub Pages](${doc_files_1.FlowrSiteBaseRef}/doc/)
|
|
156
|
-
- [release.yaml](
|
|
157
|
-
- [broken-links-and-wiki.yaml](
|
|
184
|
+
- [release.yaml](${doc_files_1.RemoteFlowrFilePathBaseRef}/.github/workflows/release.yaml) is responsible for creating a new release, only to be run by repository owners. Furthermore, it adds the new docker image to [docker hub](${doc_files_1.FlowrDockerRef}).
|
|
185
|
+
- [broken-links-and-wiki.yaml](${doc_files_1.RemoteFlowrFilePathBaseRef}/.github/workflows/broken-links-and-wiki.yaml) repeatedly tests that all links are not dead!
|
|
158
186
|
|
|
159
187
|
## Linting
|
|
160
188
|
|
|
@@ -163,11 +191,11 @@ The main one:
|
|
|
163
191
|
|
|
164
192
|
${(0, doc_code_1.codeBlock)('shell', 'npm run lint')}
|
|
165
193
|
|
|
166
|
-
And a weaker version of the first (allowing for *todo* comments) which is run automatically in the [pre-push githook](
|
|
194
|
+
And a weaker version of the first (allowing for *todo* comments) which is run automatically in the [pre-push githook](${doc_files_1.RemoteFlowrFilePathBaseRef}/.githooks/pre-push) as explained in the [CONTRIBUTING.md](${doc_files_1.RemoteFlowrFilePathBaseRef}/.github/CONTRIBUTING.md):
|
|
167
195
|
|
|
168
196
|
${(0, doc_code_1.codeBlock)('shell', 'npm run lint-local')}
|
|
169
197
|
|
|
170
|
-
Besides checking coding style (as defined in the [package.json](
|
|
198
|
+
Besides checking coding style (as defined in the [package.json](${doc_files_1.RemoteFlowrFilePathBaseRef}/package.json)), the *full* linter runs the [license checker](#license-checker).
|
|
171
199
|
|
|
172
200
|
In case you are unaware,
|
|
173
201
|
eslint can automatically fix several linting problems[](https://eslint.org/docs/latest/use/command-line-interface#fix-problems).
|
|
@@ -178,14 +206,20 @@ ${(0, doc_code_1.codeBlock)('shell', 'npm run lint-local -- --fix')}
|
|
|
178
206
|
### Oh no, the linter fails
|
|
179
207
|
|
|
180
208
|
By now, the rules should be rather stable and so, if the linter fails,
|
|
181
|
-
it is usually best if you (
|
|
209
|
+
it is usually best if you (when necessary) read the respective description and fix the respective problem.
|
|
182
210
|
Rules in this project cover general JavaScript issues [using regular ESLint](https://eslint.org/docs/latest/rules), TypeScript-specific issues [using typescript-eslint](https://typescript-eslint.io/rules/), and code formatting [with ESLint Stylistic](https://eslint.style/packages/default#rules).
|
|
183
211
|
|
|
184
212
|
However, in case you think that the linter is wrong, please do not hesitate to open a [new issue](${doc_files_1.FlowrGithubBaseRef}/flowr/issues/new/choose).
|
|
185
213
|
|
|
186
214
|
### License Checker
|
|
187
215
|
|
|
188
|
-
*flowR* is licensed under the [GPLv3 License](${doc_files_1.FlowrGithubBaseRef}/flowr/blob/main/LICENSE) requiring us to only rely on [compatible licenses](https://www.gnu.org/licenses/license-list.en.html). For now, this list is hardcoded as part of the npm [\`license-compat\`](
|
|
216
|
+
*flowR* is licensed under the [GPLv3 License](${doc_files_1.FlowrGithubBaseRef}/flowr/blob/main/LICENSE) requiring us to only rely on [compatible licenses](https://www.gnu.org/licenses/license-list.en.html). For now, this list is hardcoded as part of the npm [\`license-compat\`](${doc_files_1.RemoteFlowrFilePathBaseRef}/package.json) script so it can very well be that a new dependency you add causes the checker to fail — *even though it is compatible*. In that case, please either open a [new issue](${doc_files_1.FlowrGithubBaseRef}/flowr/issues/new/choose) or directly add the license to the list (including a reference to why it is compatible).
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
## Debugging
|
|
220
|
+
### VS Code
|
|
221
|
+
When working with VS Code, you can attach a debugger to the REPL. This works automatically by running the \`Start Debugging\` command (\`F5\` by default).
|
|
222
|
+
You can also set the \`Auto Attach Filter\` setting to automatically attach the debugger, when running \`npm run flowr\`.
|
|
189
223
|
`;
|
|
190
224
|
}
|
|
191
225
|
if (require.main === module) {
|
|
@@ -418,7 +418,7 @@ ${(0, doc_query_1.tocForQueryType)('virtual')}
|
|
|
418
418
|
|
|
419
419
|
Although it is probably better to consult the detailed explanations below, if you want to have a look at the scehma, here is its description:
|
|
420
420
|
|
|
421
|
-
${(0, schema_1.describeSchema)(query_1.QueriesSchema, ansi_1.markdownFormatter)}
|
|
421
|
+
${(0, schema_1.describeSchema)((0, query_1.QueriesSchema)(), ansi_1.markdownFormatter)}
|
|
422
422
|
|
|
423
423
|
</details>
|
|
424
424
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eagleoutice/flowr",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.9",
|
|
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": {
|
|
@@ -36,12 +36,13 @@
|
|
|
36
36
|
"lint": "npm run license-compat -- --summary && npx eslint --version && npx eslint src/ test/",
|
|
37
37
|
"license-compat": "license-checker --onlyAllow 'MIT;MIT OR X11;GPLv2;LGPL;GNUGPL;ISC;Apache-2.0;FreeBSD;BSD-2-Clause;clearbsd;ModifiedBSD;BSD-3-Clause;Python-2.0;Unlicense;WTFPL;BlueOak-1.0.0;CC-BY-4.0;CC-BY-3.0;CC0-1.0;0BSD'",
|
|
38
38
|
"doc": "typedoc",
|
|
39
|
-
"test": "vitest --config test/vitest.config.mts",
|
|
39
|
+
"test": "vitest --exclude \"test/system-tests/**\" --config test/vitest.config.mts",
|
|
40
|
+
"test:system": "vitest --dir test/system-tests --config test/system-tests/vitest.config.mts",
|
|
40
41
|
"test:coverage": "npm run test -- --coverage",
|
|
41
42
|
"performance-test": "func() { cd test/performance/ && bash run-all-suites.sh $1 $2 $3; cd ../../; }; func",
|
|
42
43
|
"test-full": "npm run test:coverage -- --no-watch -- --make-summary --test-installation",
|
|
43
44
|
"detect-circular-deps": "npx madge --extensions ts,tsx --circular src/",
|
|
44
|
-
"checkup": "npm run flowr -- --execute \":version\" && npm run lint && npm run test-full -- --allowOnly=false && docker build -t test-flowr -f scripts/Dockerfile . && npm run doc && npm-run-all wiki:*"
|
|
45
|
+
"checkup": "npm run flowr -- --execute \":version\" && npm run lint && npm run test-full -- --allowOnly=false && npm run test:system -- --no-watch && docker build -t test-flowr -f scripts/Dockerfile . && npm run doc && npm-run-all wiki:*"
|
|
45
46
|
},
|
|
46
47
|
"keywords": [
|
|
47
48
|
"static code analysis",
|
|
@@ -84,6 +85,19 @@
|
|
|
84
85
|
"**/node_modules/**/*",
|
|
85
86
|
"**/index.ts"
|
|
86
87
|
],
|
|
88
|
+
"highlightLanguages": [
|
|
89
|
+
"bash",
|
|
90
|
+
"console",
|
|
91
|
+
"css",
|
|
92
|
+
"html",
|
|
93
|
+
"javascript",
|
|
94
|
+
"json",
|
|
95
|
+
"jsonc",
|
|
96
|
+
"json5",
|
|
97
|
+
"tsx",
|
|
98
|
+
"typescript",
|
|
99
|
+
"r"
|
|
100
|
+
],
|
|
87
101
|
"theme": "hierarchy",
|
|
88
102
|
"out": "doc",
|
|
89
103
|
"readme": "README.md",
|
|
@@ -209,7 +209,7 @@ function executeCallContextQueries({ graph, ast }, queries) {
|
|
|
209
209
|
let linkedIds = undefined;
|
|
210
210
|
if (cfg && isSubCallQuery(query)) {
|
|
211
211
|
/* if we have a linkTo query, we have to find the last call */
|
|
212
|
-
const lastCall = (0, identify_link_to_last_call_relation_1.identifyLinkToLastCallRelation)(nodeId, cfg.graph, graph, query.linkTo
|
|
212
|
+
const lastCall = (0, identify_link_to_last_call_relation_1.identifyLinkToLastCallRelation)(nodeId, cfg.graph, graph, query.linkTo);
|
|
213
213
|
if (lastCall) {
|
|
214
214
|
linkedIds = lastCall;
|
|
215
215
|
}
|