@eagleoutice/flowr 2.3.0 → 2.4.1
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 +42 -30
- package/abstract-interpretation/data-frame/absint-visitor.d.ts +2 -3
- package/abstract-interpretation/data-frame/absint-visitor.js +14 -16
- package/abstract-interpretation/data-frame/mappers/function-mapper.js +3 -3
- package/abstract-interpretation/data-frame/semantics.d.ts +1 -1
- package/abstract-interpretation/data-frame/semantics.js +7 -10
- package/abstract-interpretation/data-frame/shape-inference.js +2 -8
- package/benchmark/slicer.js +7 -5
- package/benchmark/stats/size-of.js +3 -3
- package/benchmark/summarizer/second-phase/graph.js +1 -1
- package/benchmark/summarizer/second-phase/process.js +1 -1
- package/cli/benchmark-app.d.ts +1 -0
- package/cli/benchmark-app.js +1 -0
- package/cli/benchmark-helper-app.d.ts +1 -0
- package/cli/benchmark-helper-app.js +4 -3
- package/cli/common/options.js +2 -0
- package/cli/repl/commands/repl-query.js +1 -1
- package/cli/repl/server/connection.js +14 -5
- package/control-flow/basic-cfg-guided-visitor.d.ts +1 -2
- package/control-flow/basic-cfg-guided-visitor.js +0 -6
- package/control-flow/cfg-simplification.d.ts +6 -0
- package/control-flow/cfg-simplification.js +18 -9
- package/control-flow/control-flow-graph.d.ts +2 -8
- package/control-flow/control-flow-graph.js +1 -6
- package/control-flow/extract-cfg.d.ts +2 -2
- package/control-flow/extract-cfg.js +52 -63
- package/core/pipeline-executor.js +0 -8
- package/core/steps/all/static-slicing/00-slice.d.ts +7 -1
- package/core/steps/all/static-slicing/00-slice.js +9 -3
- package/core/steps/pipeline/default-pipelines.d.ts +74 -74
- package/dataflow/environments/append.js +1 -1
- package/dataflow/environments/built-in-config.d.ts +12 -4
- package/dataflow/environments/built-in-config.js +23 -82
- package/dataflow/environments/built-in.d.ts +40 -6
- package/dataflow/environments/built-in.js +119 -23
- package/dataflow/environments/clone.d.ts +3 -2
- package/dataflow/environments/clone.js +6 -5
- package/dataflow/environments/define.js +1 -2
- package/dataflow/environments/diff.js +1 -3
- package/dataflow/environments/environment.d.ts +18 -24
- package/dataflow/environments/environment.js +25 -37
- package/dataflow/environments/overwrite.d.ts +1 -1
- package/dataflow/environments/overwrite.js +1 -1
- package/dataflow/environments/remove.d.ts +2 -2
- package/dataflow/environments/remove.js +3 -4
- package/dataflow/environments/resolve-by-name.d.ts +3 -3
- package/dataflow/environments/resolve-by-name.js +4 -5
- package/dataflow/eval/resolve/alias-tracking.d.ts +12 -12
- package/dataflow/eval/resolve/alias-tracking.js +12 -12
- package/dataflow/eval/resolve/resolve.js +1 -1
- package/dataflow/extractor.js +6 -1
- package/dataflow/graph/dataflowgraph-builder.d.ts +3 -1
- package/dataflow/graph/dataflowgraph-builder.js +2 -2
- package/dataflow/graph/graph.d.ts +2 -1
- package/dataflow/graph/graph.js +6 -2
- package/dataflow/graph/invert-dfg.d.ts +2 -0
- package/dataflow/graph/invert-dfg.js +17 -0
- package/dataflow/info.d.ts +1 -1
- package/dataflow/internal/linker.js +9 -9
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +3 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +5 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +9 -7
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +1 -1
- package/dataflow/processor.d.ts +5 -1
- package/documentation/doc-util/doc-env.js +1 -2
- package/documentation/doc-util/doc-query.js +1 -1
- package/documentation/doc-util/doc-search.js +2 -2
- package/documentation/print-cfg-wiki.js +3 -4
- package/documentation/print-core-wiki.js +2 -2
- package/documentation/print-dataflow-graph-wiki.js +7 -0
- package/documentation/print-faq-wiki.js +4 -0
- package/documentation/print-linter-wiki.js +32 -4
- package/documentation/print-linting-and-testing-wiki.js +13 -1
- package/documentation/print-onboarding-wiki.js +4 -0
- package/documentation/print-query-wiki.js +12 -3
- package/linter/linter-executor.js +1 -2
- package/linter/linter-format.d.ts +26 -4
- package/linter/linter-format.js +25 -6
- package/linter/linter-rules.d.ts +40 -12
- package/linter/linter-rules.js +3 -1
- package/linter/rules/absolute-path.d.ts +4 -7
- package/linter/rules/absolute-path.js +9 -6
- package/linter/rules/dataframe-access-validation.d.ts +3 -1
- package/linter/rules/dataframe-access-validation.js +3 -1
- package/linter/rules/dead-code.d.ts +43 -0
- package/linter/rules/dead-code.js +50 -0
- package/linter/rules/deprecated-functions.d.ts +3 -2
- package/linter/rules/deprecated-functions.js +3 -1
- package/linter/rules/file-path-validity.d.ts +4 -4
- package/linter/rules/file-path-validity.js +8 -6
- package/linter/rules/naming-convention.d.ts +4 -3
- package/linter/rules/naming-convention.js +3 -1
- package/linter/rules/seeded-randomness.d.ts +4 -3
- package/linter/rules/seeded-randomness.js +3 -1
- package/linter/rules/unused-definition.d.ts +2 -0
- package/linter/rules/unused-definition.js +3 -1
- package/package.json +1 -1
- package/queries/base-query-format.d.ts +2 -0
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +7 -7
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +24 -1
- package/queries/catalog/dependencies-query/function-info/function-info.d.ts +9 -5
- package/queries/catalog/dependencies-query/function-info/read-functions.js +5 -2
- package/queries/catalog/dependencies-query/function-info/write-functions.js +6 -0
- package/queries/catalog/linter-query/linter-query-format.js +1 -1
- package/queries/catalog/location-map-query/location-map-query-executor.js +7 -5
- package/queries/catalog/location-map-query/location-map-query-format.d.ts +3 -0
- package/queries/catalog/location-map-query/location-map-query-format.js +1 -0
- package/queries/catalog/search-query/search-query-executor.js +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-executor.d.ts +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-executor.js +3 -2
- package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +3 -0
- package/queries/catalog/static-slice-query/static-slice-query-format.js +3 -1
- package/queries/query-print.d.ts +1 -1
- package/queries/query-print.js +0 -1
- package/queries/query.d.ts +16 -5
- package/queries/query.js +24 -11
- package/search/flowr-search-builder.d.ts +6 -6
- package/search/flowr-search-executor.d.ts +2 -2
- package/search/flowr-search-executor.js +1 -1
- package/search/flowr-search.d.ts +13 -8
- package/search/flowr-search.js +21 -0
- package/search/search-executor/search-enrichers.d.ts +87 -20
- package/search/search-executor/search-enrichers.js +44 -5
- package/search/search-executor/search-generators.d.ts +4 -4
- package/search/search-executor/search-generators.js +12 -7
- package/search/search-executor/search-mappers.js +3 -2
- package/search/search-executor/search-transformer.d.ts +3 -3
- package/search/search-executor/search-transformer.js +2 -2
- package/slicing/static/fingerprint.js +1 -2
- package/slicing/static/slice-call.d.ts +2 -1
- package/slicing/static/slice-call.js +3 -3
- package/slicing/static/static-slicer.d.ts +6 -5
- package/slicing/static/static-slicer.js +13 -7
- package/util/collections/arrays.d.ts +2 -0
- package/util/collections/arrays.js +9 -0
- package/util/containers.d.ts +1 -0
- package/util/containers.js +1 -0
- package/util/json.js +1 -4
- package/util/mermaid/dfg.js +5 -4
- package/util/prefix.d.ts +1 -1
- package/util/range.d.ts +1 -0
- package/util/range.js +5 -1
- package/util/version.js +1 -1
|
@@ -78,9 +78,9 @@ function getUseAlias(sourceId, dataflow, environment) {
|
|
|
78
78
|
* us later, in the {@link trackAliasInEnvironments} function, to get all the
|
|
79
79
|
* aliases of an identifier.
|
|
80
80
|
*
|
|
81
|
-
* @param sourceIds
|
|
82
|
-
* @param dataflow
|
|
83
|
-
* @param environment
|
|
81
|
+
* @param sourceIds - node ids to get the definitions for
|
|
82
|
+
* @param dataflow - dataflow graph
|
|
83
|
+
* @param environment - environment
|
|
84
84
|
* @returns node id of alias
|
|
85
85
|
*/
|
|
86
86
|
function getAliases(sourceIds, dataflow, environment) {
|
|
@@ -110,12 +110,12 @@ function getAliases(sourceIds, dataflow, environment) {
|
|
|
110
110
|
* to resolve values. For e.g. in the Dependency Query it is used to resolve calls
|
|
111
111
|
* like `lapply(c("a", "b", "c"), library, character.only = TRUE)`
|
|
112
112
|
*
|
|
113
|
-
* @param id
|
|
114
|
-
* @param environment
|
|
115
|
-
* @param graph
|
|
116
|
-
* @param idMap
|
|
117
|
-
* @param full
|
|
118
|
-
* @param resolve
|
|
113
|
+
* @param id - The node id or node to resolve
|
|
114
|
+
* @param environment - The current environment used for name resolution
|
|
115
|
+
* @param graph - The graph to resolve in
|
|
116
|
+
* @param idMap - The id map to resolve the node if given as an id
|
|
117
|
+
* @param full - Whether to track aliases on resolve
|
|
118
|
+
* @param resolve - Variable resolve mode
|
|
119
119
|
*/
|
|
120
120
|
function resolveIdToValue(id, { environment, graph, idMap, full = true, resolve }) {
|
|
121
121
|
if (id === undefined) {
|
|
@@ -160,7 +160,7 @@ function resolveIdToValue(id, { environment, graph, idMap, full = true, resolve
|
|
|
160
160
|
* @param resolve - Variable resolve mode
|
|
161
161
|
* @param identifier - Identifier to resolve
|
|
162
162
|
* @param use - Environment to use
|
|
163
|
-
* @param graph -
|
|
163
|
+
* @param graph - dataflow graph
|
|
164
164
|
* @param idMap - id map of Dataflow graph
|
|
165
165
|
* @returns Value of Identifier or Top
|
|
166
166
|
*/
|
|
@@ -333,8 +333,8 @@ function trackAliasesInGraph(id, graph, idMap) {
|
|
|
333
333
|
*
|
|
334
334
|
* Resolve an Identifier to a constant, if the identifier is a constant
|
|
335
335
|
*
|
|
336
|
-
* @param name
|
|
337
|
-
* @param environment
|
|
336
|
+
* @param name - Identifier to resolve
|
|
337
|
+
* @param environment - Environment to use
|
|
338
338
|
* @returns Value of Constant or Top
|
|
339
339
|
*/
|
|
340
340
|
function resolveToConstants(name, environment) {
|
|
@@ -59,7 +59,7 @@ function resolveNode(resolve, a, env, graph, map) {
|
|
|
59
59
|
else {
|
|
60
60
|
return r_value_2.Top;
|
|
61
61
|
}
|
|
62
|
-
if (Object.
|
|
62
|
+
if (Object.hasOwn(built_in_1.BuiltInEvalHandlerMapper, builtInName)) {
|
|
63
63
|
const handler = built_in_1.BuiltInEvalHandlerMapper[builtInName];
|
|
64
64
|
return handler(resolve, a, env, graph, map);
|
|
65
65
|
}
|
package/dataflow/extractor.js
CHANGED
|
@@ -20,6 +20,7 @@ const extract_cfg_1 = require("../control-flow/extract-cfg");
|
|
|
20
20
|
const edge_1 = require("./graph/edge");
|
|
21
21
|
const identify_link_to_last_call_relation_1 = require("../queries/catalog/call-context-query/identify-link-to-last-call-relation");
|
|
22
22
|
const built_in_function_definition_1 = require("./internal/process/functions/call/built-in/built-in-function-definition");
|
|
23
|
+
const built_in_config_1 = require("./environments/built-in-config");
|
|
23
24
|
/**
|
|
24
25
|
* The best friend of {@link produceDataFlowGraph} and {@link processDataflowFor}.
|
|
25
26
|
* Maps every {@link RType} in the normalized AST to a processor.
|
|
@@ -89,10 +90,14 @@ function produceDataFlowGraph(parser, request, completeAst, config) {
|
|
|
89
90
|
else {
|
|
90
91
|
firstRequest = request;
|
|
91
92
|
}
|
|
93
|
+
const builtInsConfig = config.semantics.environment.overwriteBuiltIns;
|
|
94
|
+
const builtIns = (0, built_in_config_1.getBuiltInDefinitions)(builtInsConfig.definitions, builtInsConfig.loadDefaults);
|
|
95
|
+
const env = (0, environment_1.initializeCleanEnvironments)(builtIns.builtInMemory);
|
|
92
96
|
const dfData = {
|
|
93
97
|
parser,
|
|
94
98
|
completeAst,
|
|
95
|
-
environment:
|
|
99
|
+
environment: env,
|
|
100
|
+
builtInEnvironment: env.current.parent,
|
|
96
101
|
processors: exports.processors,
|
|
97
102
|
currentRequest: firstRequest,
|
|
98
103
|
controlDependencies: undefined,
|
|
@@ -2,7 +2,7 @@ import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-i
|
|
|
2
2
|
import type { AstIdMap } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
3
3
|
import type { DataflowFunctionFlowInformation, FunctionArgument } from './graph';
|
|
4
4
|
import { DataflowGraph } from './graph';
|
|
5
|
-
import type { REnvironmentInformation } from '../environments/environment';
|
|
5
|
+
import type { IEnvironment, REnvironmentInformation } from '../environments/environment';
|
|
6
6
|
import type { DataflowGraphVertexAstLink, DataflowGraphVertexUse, FunctionOriginInformation } from './vertex';
|
|
7
7
|
import type { ControlDependency } from '../info';
|
|
8
8
|
import type { LinkTo } from '../../queries/catalog/call-context-query/call-context-query-format';
|
|
@@ -29,6 +29,7 @@ export declare class DataflowGraphBuilder extends DataflowGraph {
|
|
|
29
29
|
*/
|
|
30
30
|
defineFunction(id: NodeId, exitPoints: readonly NodeId[], subflow: DataflowFunctionFlowInformation, info?: {
|
|
31
31
|
environment?: REnvironmentInformation;
|
|
32
|
+
builtInEnvironment?: IEnvironment;
|
|
32
33
|
controlDependencies?: ControlDependency[];
|
|
33
34
|
}, asRoot?: boolean): this;
|
|
34
35
|
/**
|
|
@@ -46,6 +47,7 @@ export declare class DataflowGraphBuilder extends DataflowGraph {
|
|
|
46
47
|
reads?: readonly NodeId[];
|
|
47
48
|
onlyBuiltIn?: boolean;
|
|
48
49
|
environment?: REnvironmentInformation;
|
|
50
|
+
builtInEnvironment?: IEnvironment;
|
|
49
51
|
controlDependencies?: ControlDependency[];
|
|
50
52
|
origin?: FunctionOriginInformation[];
|
|
51
53
|
link?: DataflowGraphVertexAstLink;
|
|
@@ -180,7 +180,7 @@ class DataflowGraphBuilder extends graph_1.DataflowGraph {
|
|
|
180
180
|
fromId = from.nodeId;
|
|
181
181
|
}
|
|
182
182
|
else {
|
|
183
|
-
const result = (0, flowr_search_executor_1.runSearch)(from.query, data);
|
|
183
|
+
const result = (0, flowr_search_executor_1.runSearch)(from.query, data).getElements();
|
|
184
184
|
(0, assert_1.guard)(result.length === 1, `from query result should yield exactly one node, but yielded ${result.length}`);
|
|
185
185
|
fromId = result[0].node.info.id;
|
|
186
186
|
}
|
|
@@ -189,7 +189,7 @@ class DataflowGraphBuilder extends graph_1.DataflowGraph {
|
|
|
189
189
|
toIds = to.target;
|
|
190
190
|
}
|
|
191
191
|
else {
|
|
192
|
-
const result = (0, flowr_search_executor_1.runSearch)(to.query, data);
|
|
192
|
+
const result = (0, flowr_search_executor_1.runSearch)(to.query, data).getElements();
|
|
193
193
|
toIds = result.map(r => r.node.info.id);
|
|
194
194
|
}
|
|
195
195
|
return this.edgeHelper(fromId, toIds, type);
|
|
@@ -160,7 +160,7 @@ export declare class DataflowGraph<Vertex extends DataflowGraphVertexInfo = Data
|
|
|
160
160
|
*
|
|
161
161
|
* @see #edges
|
|
162
162
|
*/
|
|
163
|
-
vertices(includeDefinedFunctions: boolean):
|
|
163
|
+
vertices(includeDefinedFunctions: boolean): MapIterator<[NodeId, Vertex]>;
|
|
164
164
|
/**
|
|
165
165
|
* @returns the ids of all edges in the graph together with their edge information
|
|
166
166
|
*
|
|
@@ -231,5 +231,6 @@ export interface IEnvironmentJson {
|
|
|
231
231
|
readonly id: number;
|
|
232
232
|
parent: IEnvironmentJson;
|
|
233
233
|
memory: Record<Identifier, IdentifierDefinition[]>;
|
|
234
|
+
builtInEnv: true | undefined;
|
|
234
235
|
}
|
|
235
236
|
export {};
|
package/dataflow/graph/graph.js
CHANGED
|
@@ -376,7 +376,7 @@ function mergeNodeInfos(current, next) {
|
|
|
376
376
|
}
|
|
377
377
|
else if (current.tag === vertex_1.VertexType.FunctionDefinition) {
|
|
378
378
|
(0, assert_1.guard)(current.scope === next.scope, 'nodes to be joined for the same id must have the same scope');
|
|
379
|
-
|
|
379
|
+
current.exitPoints = (0, arrays_1.uniqueArrayMerge)(current.exitPoints, next.exitPoints);
|
|
380
380
|
}
|
|
381
381
|
return current;
|
|
382
382
|
}
|
|
@@ -394,11 +394,15 @@ function envFromJson(json) {
|
|
|
394
394
|
for (const [key, value] of Object.entries(json.memory)) {
|
|
395
395
|
memory.set(key, value);
|
|
396
396
|
}
|
|
397
|
-
|
|
397
|
+
const obj = {
|
|
398
398
|
id: json.id,
|
|
399
399
|
parent: parent,
|
|
400
400
|
memory
|
|
401
401
|
};
|
|
402
|
+
if (json.builtInEnv) {
|
|
403
|
+
obj.builtInEnv = true;
|
|
404
|
+
}
|
|
405
|
+
return obj;
|
|
402
406
|
}
|
|
403
407
|
function renvFromJson(json) {
|
|
404
408
|
const current = envFromJson(json.current);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.invertDfg = invertDfg;
|
|
4
|
+
const graph_1 = require("./graph");
|
|
5
|
+
function invertDfg(graph) {
|
|
6
|
+
const invertedGraph = new graph_1.DataflowGraph(graph.idMap);
|
|
7
|
+
for (const [, v] of graph.vertices(true)) {
|
|
8
|
+
invertedGraph.addVertex(v);
|
|
9
|
+
}
|
|
10
|
+
for (const [from, targets] of graph.edges()) {
|
|
11
|
+
for (const [to, { types }] of targets) {
|
|
12
|
+
invertedGraph.addEdge(to, from, types);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return invertedGraph;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=invert-dfg.js.map
|
package/dataflow/info.d.ts
CHANGED
|
@@ -109,7 +109,7 @@ export interface DataflowInformation extends DataflowCfgInformation {
|
|
|
109
109
|
*
|
|
110
110
|
* @see {@link DataflowInformation}
|
|
111
111
|
*/
|
|
112
|
-
export declare function initializeCleanDataflowInformation<T>(entryPoint: NodeId, data: Pick<DataflowProcessorInformation<T>, 'environment' | 'completeAst'>): DataflowInformation;
|
|
112
|
+
export declare function initializeCleanDataflowInformation<T>(entryPoint: NodeId, data: Pick<DataflowProcessorInformation<T>, 'environment' | 'builtInEnvironment' | 'completeAst'>): DataflowInformation;
|
|
113
113
|
/**
|
|
114
114
|
* Checks whether the given control dependencies are exhaustive (i.e. if for every control dependency on a boolean,
|
|
115
115
|
* the list contains a dependency on the `true` and on the `false` case).
|
|
@@ -25,7 +25,7 @@ const built_in_1 = require("../environments/built-in");
|
|
|
25
25
|
const prefix_1 = require("../../util/prefix");
|
|
26
26
|
function findNonLocalReads(graph, ignore) {
|
|
27
27
|
const ignores = new Set(ignore.map(i => i.nodeId));
|
|
28
|
-
const ids = new Set(
|
|
28
|
+
const ids = new Set(graph.vertices(true)
|
|
29
29
|
.filter(([_, info]) => info.tag === vertex_1.VertexType.Use || info.tag === vertex_1.VertexType.FunctionCall)
|
|
30
30
|
.map(([id, _]) => id));
|
|
31
31
|
/* find all variable use ids which do not link to a given id */
|
|
@@ -74,27 +74,27 @@ function produceNameSharedIdMap(references) {
|
|
|
74
74
|
}
|
|
75
75
|
function linkArgumentsOnCall(args, params, graph) {
|
|
76
76
|
const nameArgMap = new Map(args.filter(graph_1.isNamedArgument).map(a => [a.name, a]));
|
|
77
|
-
const nameParamMap = new Map(params.filter(p => p
|
|
77
|
+
const nameParamMap = new Map(params.filter(p => p?.name?.content !== undefined).map(p => [p.name.content, p]));
|
|
78
78
|
const specialDotParameter = params.find(p => p.special);
|
|
79
79
|
// all parameters matched by name
|
|
80
80
|
const matchedParameters = new Set();
|
|
81
81
|
// first map names
|
|
82
82
|
for (const [name, arg] of nameArgMap) {
|
|
83
|
-
const pmatchName = (0, prefix_1.findByPrefixIfUnique)(name,
|
|
83
|
+
const pmatchName = (0, prefix_1.findByPrefixIfUnique)(name, nameParamMap.keys()) ?? name;
|
|
84
84
|
const param = nameParamMap.get(pmatchName);
|
|
85
|
-
if (param
|
|
85
|
+
if (param?.name) {
|
|
86
86
|
logger_1.dataflowLogger.trace(`mapping named argument "${name}" to parameter "${param.name.content}"`);
|
|
87
87
|
graph.addEdge(arg.nodeId, param.name.info.id, edge_1.EdgeType.DefinesOnCall);
|
|
88
88
|
graph.addEdge(param.name.info.id, arg.nodeId, edge_1.EdgeType.DefinedByOnCall);
|
|
89
89
|
matchedParameters.add(name);
|
|
90
90
|
}
|
|
91
|
-
else if (specialDotParameter
|
|
91
|
+
else if (specialDotParameter?.name) {
|
|
92
92
|
logger_1.dataflowLogger.trace(`mapping named argument "${name}" to dot-dot-dot parameter`);
|
|
93
93
|
graph.addEdge(arg.nodeId, specialDotParameter.name.info.id, edge_1.EdgeType.DefinesOnCall);
|
|
94
94
|
graph.addEdge(specialDotParameter.name.info.id, arg.nodeId, edge_1.EdgeType.DefinedByOnCall);
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
-
const remainingParameter = params.filter(p => !p
|
|
97
|
+
const remainingParameter = params.filter(p => !p?.name || !matchedParameters.has(p.name.content));
|
|
98
98
|
const remainingArguments = args.filter(a => !(0, graph_1.isNamedArgument)(a));
|
|
99
99
|
for (let i = 0; i < remainingArguments.length; i++) {
|
|
100
100
|
const arg = remainingArguments[i];
|
|
@@ -169,14 +169,14 @@ function linkFunctionCall(graph, id, info, idMap, thisGraph, calledFunctionDefin
|
|
|
169
169
|
return;
|
|
170
170
|
}
|
|
171
171
|
const readBits = edge_1.EdgeType.Reads | edge_1.EdgeType.Calls;
|
|
172
|
-
const functionDefinitionReadIds =
|
|
172
|
+
const functionDefinitionReadIds = edges.entries().filter(([_, e]) => (0, edge_1.edgeDoesNotIncludeType)(e.types, edge_1.EdgeType.Argument)
|
|
173
173
|
&& (0, edge_1.edgeIncludesType)(e.types, readBits)).map(([target, _]) => target);
|
|
174
174
|
const functionDefs = getAllLinkedFunctionDefinitions(new Set(functionDefinitionReadIds), graph)[0];
|
|
175
175
|
for (const def of functionDefs.values()) {
|
|
176
176
|
(0, assert_1.guard)(def.tag === vertex_1.VertexType.FunctionDefinition, () => `expected function definition, but got ${def.tag}`);
|
|
177
177
|
linkFunctionCallWithSingleTarget(graph, def, info, idMap);
|
|
178
178
|
}
|
|
179
|
-
if (thisGraph.isRoot(id)) {
|
|
179
|
+
if (thisGraph.isRoot(id) && functionDefs.size > 0) {
|
|
180
180
|
calledFunctionDefinitions.push({ functionCall: id, called: [...functionDefs.values()] });
|
|
181
181
|
}
|
|
182
182
|
}
|
|
@@ -189,7 +189,7 @@ function linkFunctionCall(graph, id, info, idMap, thisGraph, calledFunctionDefin
|
|
|
189
189
|
* @param thisGraph - The graph to search for function calls in
|
|
190
190
|
*/
|
|
191
191
|
function linkFunctionCalls(graph, idMap, thisGraph) {
|
|
192
|
-
const functionCalls =
|
|
192
|
+
const functionCalls = thisGraph.vertices(true)
|
|
193
193
|
.filter(([_, info]) => info.tag === vertex_1.VertexType.FunctionCall);
|
|
194
194
|
const calledFunctionDefinitions = [];
|
|
195
195
|
for (const [id, info] of functionCalls) {
|
|
@@ -112,7 +112,7 @@ function processNumberBasedAccess(data, name, args, rootId, config, head) {
|
|
|
112
112
|
data.environment.current.memory.set(':=', existing);
|
|
113
113
|
}
|
|
114
114
|
if (head.value && outInfo.definitionRootNodes.length > 0) {
|
|
115
|
-
(0, built_in_assignment_1.markAsAssignment)(fnCall.information, { type: identifier_1.ReferenceType.Variable, name: head.value.lexeme ?? '', nodeId: head.value.info.id, definedAt: rootId, controlDependencies: [] }, outInfo.definitionRootNodes, rootId, data
|
|
115
|
+
(0, built_in_assignment_1.markAsAssignment)(fnCall.information, { type: identifier_1.ReferenceType.Variable, name: head.value.lexeme ?? '', nodeId: head.value.info.id, definedAt: rootId, controlDependencies: [] }, outInfo.definitionRootNodes, rootId, data);
|
|
116
116
|
}
|
|
117
117
|
if (data.flowrConfig.solver.pointerTracking) {
|
|
118
118
|
referenceAccessedIndices(args, data, fnCall, rootId, true);
|
|
@@ -10,7 +10,6 @@ import type { ContainerIndicesCollection } from '../../../../../graph/vertex';
|
|
|
10
10
|
import type { ForceArguments } from '../common';
|
|
11
11
|
import type { REnvironmentInformation } from '../../../../../environments/environment';
|
|
12
12
|
import type { DataflowGraph } from '../../../../../graph/graph';
|
|
13
|
-
import type { FlowrConfigOptions } from '../../../../../../config';
|
|
14
13
|
export interface AssignmentConfiguration extends ForceArguments {
|
|
15
14
|
readonly superAssignment?: boolean;
|
|
16
15
|
readonly swapSourceAndTarget?: boolean;
|
|
@@ -44,10 +43,10 @@ export interface AssignmentToSymbolParameters<OtherInfo> extends AssignmentConfi
|
|
|
44
43
|
* @param nodeToDefine - `x`
|
|
45
44
|
* @param sourceIds - `v`
|
|
46
45
|
* @param rootIdOfAssignment - `<-`
|
|
47
|
-
* @param
|
|
46
|
+
* @param data - The dataflow analysis fold backpack
|
|
48
47
|
* @param assignmentConfig - configuration for the assignment processing
|
|
49
48
|
*/
|
|
50
|
-
export declare function markAsAssignment(information: {
|
|
49
|
+
export declare function markAsAssignment<OtherInfo>(information: {
|
|
51
50
|
environment: REnvironmentInformation;
|
|
52
51
|
graph: DataflowGraph;
|
|
53
|
-
}, nodeToDefine: InGraphIdentifierDefinition, sourceIds: readonly NodeId[], rootIdOfAssignment: NodeId,
|
|
52
|
+
}, nodeToDefine: InGraphIdentifierDefinition, sourceIds: readonly NodeId[], rootIdOfAssignment: NodeId, data: DataflowProcessorInformation<OtherInfo>, assignmentConfig?: AssignmentConfiguration): void;
|
|
@@ -215,11 +215,11 @@ function checkTargetReferenceType(source, sourceInfo) {
|
|
|
215
215
|
* @param nodeToDefine - `x`
|
|
216
216
|
* @param sourceIds - `v`
|
|
217
217
|
* @param rootIdOfAssignment - `<-`
|
|
218
|
-
* @param
|
|
218
|
+
* @param data - The dataflow analysis fold backpack
|
|
219
219
|
* @param assignmentConfig - configuration for the assignment processing
|
|
220
220
|
*/
|
|
221
|
-
function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignment,
|
|
222
|
-
if (
|
|
221
|
+
function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignment, data, assignmentConfig) {
|
|
222
|
+
if (data.flowrConfig.solver.pointerTracking) {
|
|
223
223
|
let indicesCollection = undefined;
|
|
224
224
|
if (sourceIds.length === 1) {
|
|
225
225
|
// support for tracking indices.
|
|
@@ -248,7 +248,7 @@ function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignme
|
|
|
248
248
|
}
|
|
249
249
|
nodeToDefine.indicesCollection ??= indicesCollection;
|
|
250
250
|
}
|
|
251
|
-
information.environment = (0, define_1.define)(nodeToDefine, assignmentConfig?.superAssignment, information.environment,
|
|
251
|
+
information.environment = (0, define_1.define)(nodeToDefine, assignmentConfig?.superAssignment, information.environment, data.flowrConfig);
|
|
252
252
|
information.graph.setDefinitionOfVertex(nodeToDefine);
|
|
253
253
|
if (!assignmentConfig?.quoteSource) {
|
|
254
254
|
for (const sourceId of sourceIds) {
|
|
@@ -285,7 +285,7 @@ function processAssignmentToSymbol(config) {
|
|
|
285
285
|
information.environment = (0, overwrite_1.overwriteEnvironment)(sourceArg.environment, targetArg.environment);
|
|
286
286
|
// install assigned variables in environment
|
|
287
287
|
for (const write of writeNodes) {
|
|
288
|
-
markAsAssignment(information, write, [source.info.id], rootId, data
|
|
288
|
+
markAsAssignment(information, write, [source.info.id], rootId, data, config);
|
|
289
289
|
}
|
|
290
290
|
information.graph.addEdge(rootId, targetArg.entryPoint, edge_1.EdgeType.Returns);
|
|
291
291
|
if (quoteSource) {
|
|
@@ -50,24 +50,24 @@ function linkReadNameToWriteIfPossible(read, environments, listEnvironments, rem
|
|
|
50
50
|
}
|
|
51
51
|
function processNextExpression(currentElement, environment, listEnvironments, remainingRead, nextGraph) {
|
|
52
52
|
// all inputs that have not been written until now are read!
|
|
53
|
-
for (const read of
|
|
53
|
+
for (const read of currentElement.in.concat(currentElement.unknownReferences)) {
|
|
54
54
|
linkReadNameToWriteIfPossible(read, environment, listEnvironments, remainingRead, nextGraph);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
function updateSideEffectsForCalledFunctions(calledEnvs, inputEnvironment, nextGraph, localDefs) {
|
|
58
58
|
for (const { functionCall, called } of calledEnvs) {
|
|
59
|
-
|
|
59
|
+
let callDependencies = null;
|
|
60
60
|
for (const calledFn of called) {
|
|
61
61
|
(0, assert_1.guard)(calledFn.tag === vertex_1.VertexType.FunctionDefinition, 'called function must be a function definition');
|
|
62
62
|
// only merge the environments they have in common
|
|
63
|
-
let environment = calledFn.environment;
|
|
63
|
+
let environment = calledFn.subflow.environment;
|
|
64
64
|
while (environment.level > inputEnvironment.level) {
|
|
65
65
|
environment = (0, scoping_1.popLocalEnvironment)(environment);
|
|
66
66
|
}
|
|
67
67
|
// update alle definitions to be defined at this function call
|
|
68
68
|
let current = environment.current;
|
|
69
69
|
let hasUpdate = false;
|
|
70
|
-
while (current
|
|
70
|
+
while (!current?.builtInEnv) {
|
|
71
71
|
for (const definitions of current.memory.values()) {
|
|
72
72
|
for (const def of definitions) {
|
|
73
73
|
if (!(0, built_in_1.isBuiltIn)(def.definedAt)) {
|
|
@@ -84,6 +84,9 @@ function updateSideEffectsForCalledFunctions(calledEnvs, inputEnvironment, nextG
|
|
|
84
84
|
if (localDefs.length > 0) {
|
|
85
85
|
environment = (0, remove_1.removeAll)(localDefs, environment);
|
|
86
86
|
}
|
|
87
|
+
if (callDependencies === null) {
|
|
88
|
+
callDependencies = nextGraph.getVertex(functionCall, true)?.cds;
|
|
89
|
+
}
|
|
87
90
|
inputEnvironment = (0, overwrite_1.overwriteEnvironment)(inputEnvironment, environment, callDependencies);
|
|
88
91
|
}
|
|
89
92
|
}
|
|
@@ -110,7 +113,7 @@ function processExpressionList(name, args, rootId, data) {
|
|
|
110
113
|
continue;
|
|
111
114
|
}
|
|
112
115
|
// use the current environments for processing
|
|
113
|
-
data =
|
|
116
|
+
data.environment = environment;
|
|
114
117
|
const processed = (0, processor_1.processDataflowFor)(expression, data);
|
|
115
118
|
processedExpressions.push(processed);
|
|
116
119
|
nextGraph.mergeWith(processed.graph);
|
|
@@ -140,7 +143,6 @@ function processExpressionList(name, args, rootId, data) {
|
|
|
140
143
|
break;
|
|
141
144
|
}
|
|
142
145
|
}
|
|
143
|
-
logger_1.dataflowLogger.trace(`expression list exits with ${remainingRead.size} remaining read names`);
|
|
144
146
|
if (defaultReturnExpr) {
|
|
145
147
|
exitPoints.push({
|
|
146
148
|
type: 0 /* ExitPointType.Default */,
|
|
@@ -148,7 +150,7 @@ function processExpressionList(name, args, rootId, data) {
|
|
|
148
150
|
controlDependencies: data.controlDependencies
|
|
149
151
|
});
|
|
150
152
|
}
|
|
151
|
-
const ingoing = [...remainingRead.values()
|
|
153
|
+
const ingoing = [...remainingRead.values().flatMap(v => v)];
|
|
152
154
|
const rootNode = data.completeAst.idMap.get(rootId);
|
|
153
155
|
const withGroup = rootNode?.grouping;
|
|
154
156
|
if (withGroup) {
|
|
@@ -107,7 +107,7 @@ function processFunctionDefinition(name, args, rootId, data) {
|
|
|
107
107
|
// this is no longer necessary when we update environments to be back to front (e.g., with a list of environments)
|
|
108
108
|
// this favors the bigger environment
|
|
109
109
|
function retrieveActiveEnvironment(callerEnvironment, baseEnvironment) {
|
|
110
|
-
callerEnvironment ??= (0, environment_1.initializeCleanEnvironments)(true);
|
|
110
|
+
callerEnvironment ??= (0, environment_1.initializeCleanEnvironments)(undefined, true);
|
|
111
111
|
let level = callerEnvironment.level ?? 0;
|
|
112
112
|
if (baseEnvironment.level !== level) {
|
|
113
113
|
while (baseEnvironment.level < level) {
|
|
@@ -212,7 +212,7 @@ function updateNestedFunctionCalls(graph, outEnvironment) {
|
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
214
|
function prepareFunctionEnvironment(data) {
|
|
215
|
-
let env = (0, environment_1.initializeCleanEnvironments)();
|
|
215
|
+
let env = (0, environment_1.initializeCleanEnvironments)(data.builtInEnvironment.memory);
|
|
216
216
|
for (let i = 0; i < data.environment.level + 1 /* add another env */; i++) {
|
|
217
217
|
env = (0, scoping_1.pushLocalEnvironment)(env);
|
|
218
218
|
}
|
package/dataflow/processor.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { ControlDependency, DataflowInformation } from './info';
|
|
5
5
|
import type { NormalizedAst, ParentInformation, RNodeWithParent } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
6
|
-
import type { REnvironmentInformation } from './environments/environment';
|
|
6
|
+
import type { IEnvironment, REnvironmentInformation } from './environments/environment';
|
|
7
7
|
import type { RParseRequest } from '../r-bridge/retriever';
|
|
8
8
|
import type { RNode } from '../r-bridge/lang-4.x/ast/model/model';
|
|
9
9
|
import type { KnownParserType, Parser } from '../r-bridge/parser';
|
|
@@ -36,6 +36,10 @@ export interface DataflowProcessorInformation<OtherInfo> {
|
|
|
36
36
|
* The chain of control-flow {@link NodeId}s that lead to the current node (e.g., of known ifs).
|
|
37
37
|
*/
|
|
38
38
|
readonly controlDependencies: ControlDependency[] | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* The built-in environment
|
|
41
|
+
*/
|
|
42
|
+
readonly builtInEnvironment: IEnvironment;
|
|
39
43
|
/**
|
|
40
44
|
* The flowr configuration used for environment seeding, and precision control
|
|
41
45
|
*/
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.printEnvironmentToMarkdown = printEnvironmentToMarkdown;
|
|
4
|
-
const environment_1 = require("../../dataflow/environments/environment");
|
|
5
4
|
const dfg_1 = require("../../util/mermaid/dfg");
|
|
6
5
|
function printEnvironmentToMarkdown(env) {
|
|
7
6
|
if (env === undefined) {
|
|
8
7
|
return '?? (error)';
|
|
9
8
|
}
|
|
10
|
-
else if (env.
|
|
9
|
+
else if (env.builtInEnv) {
|
|
11
10
|
return `_Built-in Environment (${env.memory.size} entries)_`;
|
|
12
11
|
}
|
|
13
12
|
const lines = ['| Name | Definitions |', '|------|-------------|'];
|
|
@@ -25,7 +25,7 @@ async function showQuery(shell, code, queries, { showCode, collapseResult, colla
|
|
|
25
25
|
parser: shell,
|
|
26
26
|
request: (0, retriever_1.requestFromInput)(code)
|
|
27
27
|
}, config_1.defaultConfigOptions).allRemainingSteps();
|
|
28
|
-
const results = (0, query_1.executeQueries)({ dataflow: analysis.dataflow, ast: analysis.normalize, config: config_1.defaultConfigOptions }, queries);
|
|
28
|
+
const results = await Promise.resolve((0, query_1.executeQueries)({ dataflow: analysis.dataflow, ast: analysis.normalize, config: config_1.defaultConfigOptions }, queries));
|
|
29
29
|
const duration = performance.now() - now;
|
|
30
30
|
const metaInfo = `
|
|
31
31
|
The analysis required _${(0, time_1.printAsMs)(duration)}_ (including parsing and normalization and the query) within the generation environment.
|
|
@@ -53,13 +53,13 @@ ${(0, doc_code_1.codeBlock)('json', JSON.stringify(search, null, 2))}
|
|
|
53
53
|
${collapseResult ? ' <details> <summary style="color:gray">Show Results</summary>' : ''}
|
|
54
54
|
|
|
55
55
|
The query returns the following vetices (all references to \`x\` in the code):
|
|
56
|
-
${result.map(({ node }) => `<b>${node.info.id} ('${(0, node_id_1.recoverContent)(node.info.id, analysis.dataflow.graph)}')</b> at L${(0, dfg_1.formatRange)(node.location)}`).join(', ')}
|
|
56
|
+
${result.getElements().map(({ node }) => `<b>${node.info.id} ('${(0, node_id_1.recoverContent)(node.info.id, analysis.dataflow.graph)}')</b> at L${(0, dfg_1.formatRange)(node.location)}`).join(', ')}
|
|
57
57
|
|
|
58
58
|
${metaInfo}
|
|
59
59
|
|
|
60
60
|
The returned results are highlighted thick and blue within the dataflow graph:
|
|
61
61
|
|
|
62
|
-
${await (0, doc_dfg_1.printDfGraphForCode)(shell, code, { showCode: false, switchCodeAndGraph: false, mark: new Set(result.map(({ node }) => node.info.id)) })}
|
|
62
|
+
${await (0, doc_dfg_1.printDfGraphForCode)(shell, code, { showCode: false, switchCodeAndGraph: false, mark: new Set(result.getElements().map(({ node }) => node.info.id)) })}
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
${collapseResult ? '</details>' : ''}
|
|
@@ -224,8 +224,7 @@ ${Object.entries(control_flow_graph_1.CfgVertexType).map(([key, value]) => `- \`
|
|
|
224
224
|
We use the ${(0, doc_types_1.shortLink)('CfgBasicBlockVertex', types.info)} to represent [basic blocks](#cfg-basic-blocks) and separate
|
|
225
225
|
expressions (${(0, doc_types_1.shortLink)('CfgExpressionVertex', types.info)}) and statements (${(0, doc_types_1.shortLink)('CfgStatementVertex', types.info)})
|
|
226
226
|
as control flow units with and without side effects (if you want to, you can see view statements as effectful expressions).
|
|
227
|
-
The markers (${(0, doc_types_1.shortLink)('
|
|
228
|
-
indicate specific segments of larger expressions/statements (e.g., an \`if\` which has a condition and its branches).
|
|
227
|
+
The markers (${(0, doc_types_1.shortLink)('CfgEndMarkerVertex', types.info)}) indicate the end of larger expressions/statements.
|
|
229
228
|
|
|
230
229
|
To signal these links, the expressions and statements contain information about the attached markers:
|
|
231
230
|
|
|
@@ -235,7 +234,7 @@ Similarly, the markers contain a link to their root:
|
|
|
235
234
|
|
|
236
235
|
${(0, doc_types_1.printHierarchy)({ info: types.info, root: 'CfgWithRoot', program: types.program, openTop: true })}
|
|
237
236
|
|
|
238
|
-
In mermaid visualizations, we use rectangles for statements, rounded rectangles for expressions
|
|
237
|
+
In mermaid visualizations, we use rectangles for statements, rounded rectangles for expressions and circles for exit markers.
|
|
239
238
|
Blocks are visualized as boxes around the contained vertices.
|
|
240
239
|
|
|
241
240
|
${(0, doc_structure_1.block)({
|
|
@@ -554,7 +553,7 @@ Hence, you may rely on the corresponding exit point(s) to identify all exits of
|
|
|
554
553
|
|
|
555
554
|
${(0, doc_structure_1.block)({
|
|
556
555
|
type: 'WARNING',
|
|
557
|
-
content: 'Using basic blocks, this works just the same. However please keep in mind that the corresponding exit markers do not (and for control statements usually will not) be part of the same basic block.'
|
|
556
|
+
content: 'Using basic blocks, this works just the same. However, please keep in mind that the corresponding exit markers do not (and for control statements usually will not) be part of the same basic block.'
|
|
558
557
|
})}
|
|
559
558
|
|
|
560
559
|
`;
|
|
@@ -28,7 +28,6 @@ const built_in_access_1 = require("../dataflow/internal/process/functions/call/b
|
|
|
28
28
|
const built_in_for_loop_1 = require("../dataflow/internal/process/functions/call/built-in/built-in-for-loop");
|
|
29
29
|
const built_in_repeat_loop_1 = require("../dataflow/internal/process/functions/call/built-in/built-in-repeat-loop");
|
|
30
30
|
const linker_1 = require("../dataflow/internal/linker");
|
|
31
|
-
const static_slicer_1 = require("../slicing/static/static-slicer");
|
|
32
31
|
const info_1 = require("../dataflow/info");
|
|
33
32
|
const processor_1 = require("../dataflow/processor");
|
|
34
33
|
const default_pipelines_1 = require("../core/steps/pipeline/default-pipelines");
|
|
@@ -42,6 +41,7 @@ const normalize_for_1 = require("../r-bridge/lang-4.x/ast/parser/main/internal/l
|
|
|
42
41
|
const doc_issue_1 = require("./doc-util/doc-issue");
|
|
43
42
|
const pipeline_executor_1 = require("../core/pipeline-executor");
|
|
44
43
|
const pipeline_1 = require("../core/steps/pipeline/pipeline");
|
|
44
|
+
const static_slicer_1 = require("../slicing/static/static-slicer");
|
|
45
45
|
const config_1 = require("../config");
|
|
46
46
|
async function getText(shell) {
|
|
47
47
|
const rversion = (await shell.usedRVersion())?.format() ?? 'unknown';
|
|
@@ -373,7 +373,7 @@ Of course, all of these endeavors work not just with the ${(0, doc_types_1.short
|
|
|
373
373
|
The slicing is available as an extra step as you can see by inspecting he ${(0, doc_types_1.shortLink)('DEFAULT_SLICING_PIPELINE', info)}.
|
|
374
374
|
Besides ${(0, doc_types_1.shortLink)('STATIC_SLICE', info)} it contains a ${(0, doc_types_1.shortLink)('NAIVE_RECONSTRUCT', info)} to print the slice as (executable) R code.
|
|
375
375
|
|
|
376
|
-
Your main point of interesting here is the ${(0, doc_types_1.shortLink)(static_slicer_1.
|
|
376
|
+
Your main point of interesting here is the ${(0, doc_types_1.shortLink)(static_slicer_1.staticSlice.name, info)} function which relies on a modified
|
|
377
377
|
breadth-first search to collect all nodes which are part of the slice.
|
|
378
378
|
For more information on how the slicing works, please refer to the [tool demonstration (Section 3.2)](https://doi.org/10.1145/3691620.3695359),
|
|
379
379
|
or the [original master's thesis (Chapter 4)](https://doi.org/10.18725/OPARU-50107).
|
|
@@ -835,6 +835,13 @@ The following sections present details on the different types of vertices and ed
|
|
|
835
835
|
${(0, doc_general_1.prefixLines)((0, doc_code_1.codeBlock)('ts', 'const node = graph.idMap.get(id);'), '> ')}
|
|
836
836
|
> In case you just need the name (\`lexeme\`) of the respective vertex, ${(0, doc_types_1.shortLink)(node_id_1.recoverName.name, vertexType.info)} can help you out:
|
|
837
837
|
${(0, doc_general_1.prefixLines)((0, doc_code_1.codeBlock)('ts', `const name = ${node_id_1.recoverName.name}(id, graph.idMap);`), '> ')}
|
|
838
|
+
>
|
|
839
|
+
> Please note that not every node in the normalized AST is represented in the dataflow graph.
|
|
840
|
+
> For example, if the node is unreachable in a way that can be detected during the analysis and flowR
|
|
841
|
+
> is configured to ignore dead code. Likewise, empty argument wrappers do not have a corresponding
|
|
842
|
+
> dataflow graph vertex (as they are not relevant for the dataflow graph). It depends on the scenario what to do in such a case.
|
|
843
|
+
> For argument wrappers you can access the dataflow information for their value. For dead code, however, flowR currently contains
|
|
844
|
+
> some core heuristics that remove it which cannot be reversed easily. So please open [an issue](${doc_issue_1.NewIssueUrl}) if you encounter such a case and require the node to be present in the dataflow graph.
|
|
838
845
|
|
|
839
846
|
${(0, doc_structure_1.section)('Vertices', 2, 'vertices')}
|
|
840
847
|
|
|
@@ -39,6 +39,10 @@ With \`npm\` you have to pass arguments in a specific way. The \`--\` operator i
|
|
|
39
39
|
${(0, doc_code_1.codeBlock)('shell', 'npm run flowR -- --help')}
|
|
40
40
|
`)}
|
|
41
41
|
|
|
42
|
+
${qAndA('How to do logging in flowR?', `
|
|
43
|
+
Check out the [Logging Section in the Linting and Testing wiki page](${doc_files_1.FlowrWikiBaseRef}/Linting-and-Testing#logging) for more information on how to do logging in *flowR*.
|
|
44
|
+
`)}
|
|
45
|
+
|
|
42
46
|
## 🇷 R FAQ
|
|
43
47
|
|
|
44
48
|
### 📦 R Packages
|