@eagleoutice/flowr 2.2.10 → 2.2.12
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 +4 -4
- package/benchmark/slicer.d.ts +49 -22
- package/benchmark/slicer.js +88 -28
- package/benchmark/stats/print.js +16 -10
- package/benchmark/stats/size-of.js +18 -1
- package/benchmark/stats/stats.d.ts +3 -0
- package/benchmark/summarizer/second-phase/process.js +8 -2
- package/cli/benchmark-app.d.ts +5 -0
- package/cli/benchmark-app.js +49 -6
- package/cli/benchmark-helper-app.d.ts +4 -0
- package/cli/benchmark-helper-app.js +20 -4
- package/cli/common/options.js +13 -4
- package/cli/repl/commands/repl-commands.js +2 -0
- package/cli/repl/commands/repl-dataflow.d.ts +2 -0
- package/cli/repl/commands/repl-dataflow.js +35 -1
- package/cli/repl/server/compact.d.ts +2 -2
- package/cli/repl/server/compact.js +3 -3
- package/cli/repl/server/messages/message-analysis.d.ts +2 -2
- package/cli/repl/server/messages/message-analysis.js +2 -2
- package/config.d.ts +27 -2
- package/config.js +30 -4
- package/dataflow/environments/built-in-config.d.ts +5 -2
- package/dataflow/environments/built-in-config.js +8 -2
- package/dataflow/environments/built-in.d.ts +8 -1
- package/dataflow/environments/built-in.js +8 -1
- package/dataflow/environments/clone.d.ts +5 -0
- package/dataflow/environments/clone.js +5 -0
- package/dataflow/environments/default-builtin-config.js +96 -10
- package/dataflow/environments/define.d.ts +5 -1
- package/dataflow/environments/define.js +36 -10
- package/dataflow/environments/environment.js +4 -2
- package/dataflow/environments/overwrite.js +4 -0
- package/dataflow/environments/remove.d.ts +6 -0
- package/dataflow/environments/remove.js +24 -0
- package/dataflow/environments/resolve-by-name.js +1 -1
- package/dataflow/extractor.d.ts +1 -1
- package/dataflow/extractor.js +8 -6
- package/dataflow/graph/dataflowgraph-builder.d.ts +76 -6
- package/dataflow/graph/dataflowgraph-builder.js +102 -6
- package/dataflow/graph/edge.js +4 -1
- package/dataflow/graph/graph.d.ts +12 -1
- package/dataflow/graph/graph.js +37 -0
- package/dataflow/graph/vertex.d.ts +42 -2
- package/dataflow/graph/vertex.js +32 -0
- package/dataflow/internal/linker.js +3 -1
- package/dataflow/internal/process/functions/call/argument/unpack-argument.d.ts +3 -0
- package/dataflow/internal/process/functions/call/argument/unpack-argument.js +4 -10
- package/dataflow/internal/process/functions/call/built-in/built-in-access.d.ts +1 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +55 -45
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.d.ts +6 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +27 -8
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +37 -7
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +10 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +140 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-list.js +51 -17
- package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +21 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +3 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +83 -29
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.d.ts +7 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +41 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +20 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.d.ts +15 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +75 -0
- package/dataflow/internal/process/functions/call/common.d.ts +1 -1
- package/dataflow/internal/process/functions/call/common.js +4 -2
- package/dataflow/internal/process/functions/call/named-call-handling.d.ts +2 -0
- package/dataflow/internal/process/functions/call/named-call-handling.js +9 -5
- package/dataflow/internal/process/process-named-call.d.ts +3 -0
- package/dataflow/internal/process/process-named-call.js +3 -0
- package/dataflow/processor.d.ts +7 -7
- package/documentation/data/server/doc-data-server-messages.js +2 -2
- package/documentation/doc-util/doc-cfg.d.ts +11 -2
- package/documentation/doc-util/doc-cfg.js +35 -6
- package/documentation/doc-util/doc-code.js +10 -2
- package/documentation/print-capabilities-markdown.js +1 -1
- package/documentation/print-cfg-wiki.d.ts +1 -0
- package/documentation/print-cfg-wiki.js +84 -0
- package/documentation/print-core-wiki.js +2 -2
- package/documentation/print-interface-wiki.js +4 -0
- package/documentation/print-query-wiki.js +22 -3
- package/package.json +4 -3
- package/queries/catalog/call-context-query/call-context-query-executor.js +13 -0
- package/queries/catalog/call-context-query/call-context-query-format.d.ts +4 -0
- package/queries/catalog/call-context-query/call-context-query-format.js +1 -0
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +1 -1
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +13 -5
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -25
- package/queries/catalog/dependencies-query/dependencies-query-format.js +2 -145
- package/queries/catalog/dependencies-query/function-info/function-info.d.ts +24 -0
- package/queries/catalog/dependencies-query/function-info/function-info.js +10 -0
- package/queries/catalog/dependencies-query/function-info/library-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/library-functions.js +18 -0
- package/queries/catalog/dependencies-query/function-info/read-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/read-functions.js +101 -0
- package/queries/catalog/dependencies-query/function-info/source-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/source-functions.js +11 -0
- package/queries/catalog/dependencies-query/function-info/write-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/write-functions.js +87 -0
- package/queries/catalog/location-map-query/location-map-query-executor.d.ts +1 -1
- package/queries/catalog/location-map-query/location-map-query-executor.js +38 -3
- package/queries/catalog/location-map-query/location-map-query-format.d.ts +10 -1
- package/queries/catalog/location-map-query/location-map-query-format.js +5 -1
- package/queries/catalog/project-query/project-query-executor.d.ts +3 -0
- package/queries/catalog/project-query/project-query-executor.js +17 -0
- package/queries/catalog/project-query/project-query-format.d.ts +67 -0
- package/queries/catalog/project-query/project-query-format.js +26 -0
- package/queries/query.d.ts +60 -1
- package/queries/query.js +3 -1
- package/r-bridge/data/data.d.ts +2 -2
- package/r-bridge/data/data.js +2 -2
- package/slicing/static/fingerprint.js +8 -1
- package/slicing/static/slice-call.d.ts +1 -1
- package/slicing/static/slice-call.js +5 -16
- package/slicing/static/slicer-types.d.ts +2 -0
- package/slicing/static/static-slicer.d.ts +4 -2
- package/slicing/static/static-slicer.js +24 -18
- package/slicing/static/visiting-queue.d.ts +7 -1
- package/slicing/static/visiting-queue.js +20 -6
- package/util/arrays.d.ts +23 -0
- package/util/arrays.js +41 -0
- package/util/cfg/visitor.d.ts +1 -1
- package/util/cfg/visitor.js +2 -2
- package/util/{list-access.d.ts → containers.d.ts} +24 -4
- package/util/{list-access.js → containers.js} +42 -12
- package/util/mermaid/ast.js +12 -1
- package/util/mermaid/cfg.js +2 -2
- package/util/parallel.d.ts +2 -1
- package/util/parallel.js +11 -2
- package/util/prefix.d.ts +13 -0
- package/util/prefix.js +34 -0
- package/util/version.js +1 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processVector = processVector;
|
|
4
|
+
const r_function_call_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
5
|
+
const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
|
|
6
|
+
const known_call_handling_1 = require("../known-call-handling");
|
|
7
|
+
const config_1 = require("../../../../../../config");
|
|
8
|
+
const containers_1 = require("../../../../../../util/containers");
|
|
9
|
+
/**
|
|
10
|
+
* Process a vector call.
|
|
11
|
+
*
|
|
12
|
+
* Example:
|
|
13
|
+
* ```r
|
|
14
|
+
* c(1, 2, 3, 4)
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
function processVector(name, args, rootId, data) {
|
|
18
|
+
const fnCall = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data });
|
|
19
|
+
if (!(0, config_1.getConfig)().solver.pointerTracking) {
|
|
20
|
+
return fnCall.information;
|
|
21
|
+
}
|
|
22
|
+
const vectorArgs = [];
|
|
23
|
+
let argIndex = 1;
|
|
24
|
+
for (const arg of args) {
|
|
25
|
+
// Skip invalid argument types
|
|
26
|
+
if (arg === r_function_call_1.EmptyArgument || arg.type !== type_1.RType.Argument || arg.value === undefined) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (isPrimitive(arg.value.type)) {
|
|
30
|
+
vectorArgs.push({
|
|
31
|
+
identifier: { index: argIndex++ },
|
|
32
|
+
nodeId: arg.value.info.id,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// Check whether argument value can be resolved
|
|
37
|
+
let indicesCollection;
|
|
38
|
+
if (arg.value.type === type_1.RType.Symbol) {
|
|
39
|
+
indicesCollection = (0, containers_1.resolveIndicesByName)(arg.value.lexeme, data.environment);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
// Check whether argument is nested container
|
|
43
|
+
indicesCollection = fnCall.information.graph.getVertex(arg.value.info.id)?.indicesCollection;
|
|
44
|
+
}
|
|
45
|
+
const flattenedIndices = indicesCollection?.flatMap(indices => indices.indices)
|
|
46
|
+
.map(index => {
|
|
47
|
+
return {
|
|
48
|
+
identifier: { index: argIndex++ },
|
|
49
|
+
nodeId: index.nodeId,
|
|
50
|
+
};
|
|
51
|
+
}) ?? [];
|
|
52
|
+
vectorArgs.push(...flattenedIndices);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if ((0, config_1.isOverPointerAnalysisThreshold)(vectorArgs.length)) {
|
|
56
|
+
return fnCall.information;
|
|
57
|
+
}
|
|
58
|
+
const indices = {
|
|
59
|
+
indices: vectorArgs,
|
|
60
|
+
isContainer: true,
|
|
61
|
+
};
|
|
62
|
+
// Add resolved indices to vertex
|
|
63
|
+
const vertex = fnCall.information.graph.getVertex(rootId);
|
|
64
|
+
if (vertex) {
|
|
65
|
+
vertex.indicesCollection = [indices];
|
|
66
|
+
}
|
|
67
|
+
return fnCall.information;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Checks whether the passed type is primitive i.e. number, logical or string.
|
|
71
|
+
*/
|
|
72
|
+
function isPrimitive(type) {
|
|
73
|
+
return type === type_1.RType.Number || type === type_1.RType.Logical || type === type_1.RType.String;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=built-in-vector.js.map
|
|
@@ -34,6 +34,6 @@ export interface PatchFunctionCallInput<OtherInfo> {
|
|
|
34
34
|
readonly rootId: NodeId;
|
|
35
35
|
readonly name: RSymbol<OtherInfo & ParentInformation>;
|
|
36
36
|
readonly data: DataflowProcessorInformation<OtherInfo & ParentInformation>;
|
|
37
|
-
readonly argumentProcessResult: readonly (DataflowInformation | undefined)[];
|
|
37
|
+
readonly argumentProcessResult: readonly (Pick<DataflowInformation, 'entryPoint'> | undefined)[];
|
|
38
38
|
}
|
|
39
39
|
export declare function patchFunctionCall<OtherInfo>({ nextGraph, rootId, name, data, argumentProcessResult }: PatchFunctionCallInput<OtherInfo>): void;
|
|
@@ -64,9 +64,12 @@ function processAllArguments({ functionName, args, data, finalGraph, functionRoo
|
|
|
64
64
|
}
|
|
65
65
|
processedArguments.push(processed);
|
|
66
66
|
finalEnv = (0, overwrite_1.overwriteEnvironment)(finalEnv, processed.environment);
|
|
67
|
+
finalGraph.mergeWith(processed.graph);
|
|
67
68
|
// resolve reads within argument, we resolve before adding the `processed.environment` to avoid cyclic dependencies
|
|
68
69
|
for (const ingoing of [...processed.in, ...processed.unknownReferences]) {
|
|
69
|
-
|
|
70
|
+
// check if it is called directly
|
|
71
|
+
const vtx = finalGraph.getVertex(ingoing.nodeId);
|
|
72
|
+
const tryToResolve = ingoing.name ? (0, resolve_by_name_1.resolveByName)(ingoing.name, argEnv, vtx?.tag === vertex_1.VertexType.FunctionCall ? identifier_1.ReferenceType.Function : identifier_1.ReferenceType.Unknown) : undefined;
|
|
70
73
|
if (tryToResolve === undefined) {
|
|
71
74
|
remainingReadInArgs.push(ingoing);
|
|
72
75
|
}
|
|
@@ -90,7 +93,6 @@ function processAllArguments({ functionName, args, data, finalGraph, functionRoo
|
|
|
90
93
|
}
|
|
91
94
|
}
|
|
92
95
|
argEnv = (0, overwrite_1.overwriteEnvironment)(argEnv, processed.environment);
|
|
93
|
-
finalGraph.mergeWith(processed.graph);
|
|
94
96
|
if (arg.type !== type_1.RType.Argument || !arg.name) {
|
|
95
97
|
callArgs.push({ nodeId: processed.entryPoint, controlDependencies: undefined, type: identifier_1.ReferenceType.Argument });
|
|
96
98
|
}
|
|
@@ -4,4 +4,6 @@ import type { ParentInformation } from '../../../../../r-bridge/lang-4.x/ast/mod
|
|
|
4
4
|
import type { RFunctionArgument } from '../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
5
5
|
import type { RSymbol } from '../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
|
|
6
6
|
import type { NodeId } from '../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
7
|
+
import type { DataflowGraph } from '../../../../graph/graph';
|
|
8
|
+
export declare function markAsOnlyBuiltIn(graph: DataflowGraph, rootId: NodeId): void;
|
|
7
9
|
export declare function processNamedCall<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>): DataflowInformation;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.markAsOnlyBuiltIn = markAsOnlyBuiltIn;
|
|
3
4
|
exports.processNamedCall = processNamedCall;
|
|
4
5
|
const info_1 = require("../../../../info");
|
|
5
6
|
const known_call_handling_1 = require("./known-call-handling");
|
|
@@ -27,6 +28,13 @@ function processDefaultFunctionProcessor(information, name, args, rootId, data)
|
|
|
27
28
|
const call = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, forceArgs: (resolve?.length ?? 0) > 0 ? undefined : 'all' });
|
|
28
29
|
return mergeInformation(information, call.information);
|
|
29
30
|
}
|
|
31
|
+
function markAsOnlyBuiltIn(graph, rootId) {
|
|
32
|
+
const v = graph.getVertex(rootId);
|
|
33
|
+
if (v?.tag === vertex_1.VertexType.FunctionCall) {
|
|
34
|
+
v.onlyBuiltin = true;
|
|
35
|
+
v.environment = undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
30
38
|
function processNamedCall(name, args, rootId, data) {
|
|
31
39
|
const resolved = (0, resolve_by_name_1.resolveByName)(name.content, data.environment, identifier_1.ReferenceType.Function) ?? [];
|
|
32
40
|
let defaultProcessor = resolved.length === 0;
|
|
@@ -46,11 +54,7 @@ function processNamedCall(name, args, rootId, data) {
|
|
|
46
54
|
}
|
|
47
55
|
else if (information && builtIn) {
|
|
48
56
|
// mark the function call as built in only
|
|
49
|
-
|
|
50
|
-
if (v?.tag === vertex_1.VertexType.FunctionCall) {
|
|
51
|
-
v.onlyBuiltin = true;
|
|
52
|
-
v.environment = undefined;
|
|
53
|
-
}
|
|
57
|
+
markAsOnlyBuiltIn(information.graph, rootId);
|
|
54
58
|
}
|
|
55
59
|
return information ?? (0, info_1.initializeCleanDataflowInformation)(rootId, data);
|
|
56
60
|
}
|
|
@@ -3,4 +3,7 @@ import type { DataflowInformation } from '../../info';
|
|
|
3
3
|
import type { Base, RNode, Location } from '../../../r-bridge/lang-4.x/ast/model/model';
|
|
4
4
|
import type { ParentInformation } from '../../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
5
5
|
import type { EmptyArgument } from '../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
6
|
+
/**
|
|
7
|
+
* Helper function for {@link processNamedCall} using the given `functionName` as the name of the function.
|
|
8
|
+
*/
|
|
6
9
|
export declare function processAsNamedCall<OtherInfo>(functionName: RNode<OtherInfo & ParentInformation> & Base<OtherInfo> & Location, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, name: string, args: readonly (RNode<OtherInfo & ParentInformation> | typeof EmptyArgument | undefined)[]): DataflowInformation;
|
|
@@ -4,6 +4,9 @@ exports.processAsNamedCall = processAsNamedCall;
|
|
|
4
4
|
const named_call_handling_1 = require("./functions/call/named-call-handling");
|
|
5
5
|
const make_argument_1 = require("./functions/call/argument/make-argument");
|
|
6
6
|
const type_1 = require("../../../r-bridge/lang-4.x/ast/model/type");
|
|
7
|
+
/**
|
|
8
|
+
* Helper function for {@link processNamedCall} using the given `functionName` as the name of the function.
|
|
9
|
+
*/
|
|
7
10
|
function processAsNamedCall(functionName, data, name, args) {
|
|
8
11
|
return (0, named_call_handling_1.processNamedCall)({
|
|
9
12
|
type: type_1.RType.Symbol,
|
package/dataflow/processor.d.ts
CHANGED
|
@@ -10,17 +10,17 @@ import type { KnownParserType, Parser } from '../r-bridge/parser';
|
|
|
10
10
|
export interface DataflowProcessorInformation<OtherInfo> {
|
|
11
11
|
readonly parser: Parser<KnownParserType>;
|
|
12
12
|
/**
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
* Initial and frozen ast-information
|
|
14
|
+
*/
|
|
15
15
|
readonly completeAst: NormalizedAst<OtherInfo>;
|
|
16
16
|
/**
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
* Correctly contains pushed local scopes introduced by `function` scopes.
|
|
18
|
+
* Will by default *not* contain any symbol-bindings introduced along the way; they have to be decorated when moving up the tree.
|
|
19
|
+
*/
|
|
20
20
|
readonly environment: REnvironmentInformation;
|
|
21
21
|
/**
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
* Other processors to be called by the given functions
|
|
23
|
+
*/
|
|
24
24
|
readonly processors: DataflowProcessors<OtherInfo>;
|
|
25
25
|
/**
|
|
26
26
|
* The {@link RParseRequests} that is currently being parsed
|
|
@@ -201,10 +201,10 @@ While the context is derived from the \`filename\`, we currently offer no way to
|
|
|
201
201
|
})}
|
|
202
202
|
|
|
203
203
|
<a id="analysis-format-compact"></a>
|
|
204
|
-
**Retrieve the Output in a
|
|
204
|
+
**Retrieve the Output in a Compacted Form**
|
|
205
205
|
|
|
206
206
|
The default response is formatted as JSON. But this can get very big quickly.
|
|
207
|
-
By specifying \`format: "compact"\`, you can retrieve the results heavily compacted (using [
|
|
207
|
+
By specifying \`format: "compact"\`, you can retrieve the results heavily compacted (using [lz-string](https://www.npmjs.com/package/lz-string)).
|
|
208
208
|
This works with and without the control flow graph as described [above](#analysis-include-cfg).
|
|
209
209
|
|
|
210
210
|
${await (0, doc_server_message_1.documentServerMessageResponse)({
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import type { ControlFlowInformation } from '../../util/cfg/cfg';
|
|
2
|
-
import type { RShell } from '../../r-bridge/shell';
|
|
3
2
|
import type { NormalizedAst } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
4
|
-
|
|
3
|
+
import type { KnownParser } from '../../r-bridge/parser';
|
|
4
|
+
import type { DataflowInformation } from '../../dataflow/info';
|
|
5
|
+
export declare function getCfg(parser: KnownParser, code: string): Promise<{
|
|
5
6
|
info: ControlFlowInformation;
|
|
6
7
|
ast: NormalizedAst;
|
|
8
|
+
dataflow: DataflowInformation;
|
|
7
9
|
}>;
|
|
10
|
+
export declare function printCfg(cfg: ControlFlowInformation, ast: NormalizedAst, prefix?: string): string;
|
|
11
|
+
export interface PrintCfgOptions {
|
|
12
|
+
readonly showCode?: boolean;
|
|
13
|
+
readonly openCode?: boolean;
|
|
14
|
+
readonly prefix?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function printCFGCode(parser: KnownParser, code: string, { showCode, openCode, prefix }?: PrintCfgOptions): Promise<string>;
|
|
@@ -1,18 +1,47 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getCfg = getCfg;
|
|
4
|
+
exports.printCfg = printCfg;
|
|
5
|
+
exports.printCFGCode = printCFGCode;
|
|
4
6
|
const cfg_1 = require("../../util/cfg/cfg");
|
|
5
|
-
const pipeline_executor_1 = require("../../core/pipeline-executor");
|
|
6
7
|
const default_pipelines_1 = require("../../core/steps/pipeline/default-pipelines");
|
|
7
8
|
const retriever_1 = require("../../r-bridge/retriever");
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
const time_1 = require("../../util/time");
|
|
10
|
+
const doc_files_1 = require("./doc-files");
|
|
11
|
+
const cfg_2 = require("../../util/mermaid/cfg");
|
|
12
|
+
const doc_code_1 = require("./doc-code");
|
|
13
|
+
async function getCfg(parser, code) {
|
|
14
|
+
const result = await (0, default_pipelines_1.createDataflowPipeline)(parser, {
|
|
11
15
|
request: (0, retriever_1.requestFromInput)(code)
|
|
12
16
|
}).allRemainingSteps();
|
|
17
|
+
const cfg = (0, cfg_1.extractCFG)(result.normalize, result.dataflow.graph);
|
|
13
18
|
return {
|
|
14
|
-
info:
|
|
15
|
-
ast:
|
|
19
|
+
info: cfg,
|
|
20
|
+
ast: result.normalize,
|
|
21
|
+
dataflow: result.dataflow
|
|
16
22
|
};
|
|
17
23
|
}
|
|
24
|
+
function printCfg(cfg, ast, prefix = 'flowchart TD\n') {
|
|
25
|
+
return `
|
|
26
|
+
${(0, doc_code_1.codeBlock)('mermaid', (0, cfg_2.cfgToMermaid)(cfg, ast, prefix))}
|
|
27
|
+
`;
|
|
28
|
+
}
|
|
29
|
+
async function printCFGCode(parser, code, { showCode = true, openCode = false, prefix = 'flowchart BT\n' } = {}) {
|
|
30
|
+
const now = performance.now();
|
|
31
|
+
const res = await getCfg(parser, code);
|
|
32
|
+
const duration = performance.now() - now;
|
|
33
|
+
const metaInfo = `The analysis required _${(0, time_1.printAsMs)(duration)}_ (including the dataflow analysis, normalization, and parsing with the [${parser.name}](${doc_files_1.FlowrWikiBaseRef}/Engines) engine) within the generation environment.`;
|
|
34
|
+
return '\n\n' + printCfg(res.info, res.ast, prefix) + (showCode ? `
|
|
35
|
+
<details${openCode ? ' open' : ''}>
|
|
36
|
+
|
|
37
|
+
<summary style="color:gray">R Code of the CFG</summary>
|
|
38
|
+
|
|
39
|
+
${metaInfo}
|
|
40
|
+
|
|
41
|
+
${(0, doc_code_1.codeBlock)('r', code)}
|
|
42
|
+
|
|
43
|
+
</details>
|
|
44
|
+
|
|
45
|
+
` : '\n(' + metaInfo + ')\n\n');
|
|
46
|
+
}
|
|
18
47
|
//# sourceMappingURL=doc-cfg.js.map
|
|
@@ -4,17 +4,25 @@ exports.codeBlock = codeBlock;
|
|
|
4
4
|
exports.codeInline = codeInline;
|
|
5
5
|
exports.jsonWithLimit = jsonWithLimit;
|
|
6
6
|
const json_1 = require("../../util/json");
|
|
7
|
+
const environment_1 = require("../../dataflow/environments/environment");
|
|
7
8
|
function codeBlock(language, code) {
|
|
8
9
|
return `\n\`\`\`${language}\n${code?.trim() ?? ''}\n\`\`\`\n`;
|
|
9
10
|
}
|
|
10
11
|
function codeInline(code) {
|
|
11
12
|
return `<code>${code}</code>`;
|
|
12
13
|
}
|
|
13
|
-
function jsonWithLimit(object, maxLength = 5_000, tooLongText = '_As the code is pretty long, we inhibit pretty printing and syntax highlighting (JSON):_') {
|
|
14
|
+
function jsonWithLimit(object, maxLength = 5_000, tooLongText = '_As the code is pretty long, we inhibit pretty printing and syntax highlighting (JSON, hiding built-in):_') {
|
|
14
15
|
const prettyPrinted = JSON.stringify(object, json_1.jsonReplacer, 2);
|
|
15
16
|
return `
|
|
16
17
|
${prettyPrinted.length > maxLength ? tooLongText : ''}
|
|
17
|
-
${codeBlock(prettyPrinted.length > maxLength ? 'text' : 'json', prettyPrinted.length > 5_000 ? JSON.stringify(object,
|
|
18
|
+
${codeBlock(prettyPrinted.length > maxLength ? 'text' : 'json', prettyPrinted.length > 5_000 ? JSON.stringify(object, (k, v) => {
|
|
19
|
+
if (typeof v === 'object' && v !== null && 'id' in v && v['id'] === 0 && 'memory' in v && v['memory']) {
|
|
20
|
+
return '<BuiltInEnvironment>';
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
return (0, environment_1.builtInEnvJsonReplacer)(k, v);
|
|
24
|
+
}
|
|
25
|
+
}) : prettyPrinted)}
|
|
18
26
|
`;
|
|
19
27
|
}
|
|
20
28
|
//# sourceMappingURL=doc-code.js.map
|
|
@@ -86,7 +86,7 @@ async function printSingleCapability(info, depth, index, capability) {
|
|
|
86
86
|
if (capability.url) {
|
|
87
87
|
nextLine += '\\\nSee ' + (0, strings_1.joinWithLast)(capability.url.map(({ name, href }) => `[${name}](${href})`)) + ' for more info.';
|
|
88
88
|
}
|
|
89
|
-
nextLine += '
|
|
89
|
+
nextLine += ' (internal ID: `' + capability.id + '`)';
|
|
90
90
|
if (capability.example) {
|
|
91
91
|
nextLine += `\n${(0, doc_general_1.prefixLines)(typeof capability.example === 'string' ? capability.example : await capability.example(info.parser), nextLineIndent + '> ')}`;
|
|
92
92
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const shell_1 = require("../r-bridge/shell");
|
|
7
|
+
const log_1 = require("../../test/functionality/_helper/log");
|
|
8
|
+
const doc_auto_gen_1 = require("./doc-util/doc-auto-gen");
|
|
9
|
+
const doc_code_1 = require("./doc-util/doc-code");
|
|
10
|
+
const doc_types_1 = require("./doc-util/doc-types");
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
const doc_files_1 = require("./doc-util/doc-files");
|
|
13
|
+
const doc_cli_option_1 = require("./doc-util/doc-cli-option");
|
|
14
|
+
const doc_structure_1 = require("./doc-util/doc-structure");
|
|
15
|
+
const doc_issue_1 = require("./doc-util/doc-issue");
|
|
16
|
+
const doc_cfg_1 = require("./doc-util/doc-cfg");
|
|
17
|
+
const visitor_1 = require("../util/cfg/visitor");
|
|
18
|
+
async function getText(shell) {
|
|
19
|
+
const rversion = (await shell.usedRVersion())?.format() ?? 'unknown';
|
|
20
|
+
const types = (0, doc_types_1.getTypesFromFolderAsMermaid)({
|
|
21
|
+
rootFolder: path_1.default.resolve('./src'),
|
|
22
|
+
typeName: 'RNode',
|
|
23
|
+
inlineTypes: doc_types_1.mermaidHide
|
|
24
|
+
});
|
|
25
|
+
return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'control flow graph', rVersion: rversion })}
|
|
26
|
+
|
|
27
|
+
_flowR_ produces two main perspectives of the program: 1) a [normalized version of the AST](${doc_files_1.FlowrWikiBaseRef}/Normalized-AST)
|
|
28
|
+
and 2) a [dataflow graph](${doc_files_1.FlowrWikiBaseRef}/Dataflow%20Graph). However, for further analyses, we also provide an explicit control flow graph
|
|
29
|
+
that is calculated from the normalized AST **and** the dataflow graph to incorporate change in language semantics.
|
|
30
|
+
flowR also uses this CFG for some of its queries (e.g., to link to the last call in a [Call-Context Query](${doc_files_1.FlowrWikiBaseRef}/Query-API))
|
|
31
|
+
but does not incorporate it into its core analysis.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
${(0, doc_structure_1.block)({
|
|
35
|
+
type: 'TIP',
|
|
36
|
+
content: `If you want to investigate the Control Flow Graph,
|
|
37
|
+
you can use the ${(0, doc_cli_option_1.getReplCommand)('controlflow*')} command in the REPL (see the [Interface wiki page](${doc_files_1.FlowrWikiBaseRef}/Interface) for more information).`
|
|
38
|
+
})}
|
|
39
|
+
|
|
40
|
+
The CFG may be a little bit uncommon compared to the classical CFG with basic blocks. This is mostly due to historical reasons.
|
|
41
|
+
Please [open a new issue](${doc_issue_1.NewIssueUrl}) if you are interested in such a perspective.
|
|
42
|
+
|
|
43
|
+
But for now, let's look at a simple CFG for a program without any branching:
|
|
44
|
+
|
|
45
|
+
${(0, doc_code_1.codeBlock)('r', 'x <- 2 * 3 + 1')}
|
|
46
|
+
|
|
47
|
+
The corresponding CFG is a directed, labeled graph with two types of edges (control and flow dependencies):
|
|
48
|
+
|
|
49
|
+
${await (0, doc_cfg_1.printCFGCode)(shell, 'x <- 2 * 3 + 1', { showCode: false, prefix: 'flowchart RL\n' })}
|
|
50
|
+
|
|
51
|
+
Every normalized node of the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized-AST) that has any relevance to the
|
|
52
|
+
execution is added and automatically linked using its id (similarly to vertices of the [dataflow graph](${doc_files_1.FlowrWikiBaseRef}/Dataflow%20Graph)).
|
|
53
|
+
Higher expressions, such as \`2 * 3\` get an additional node with an artificial id that ends in \`-exit\` to mark whenever their calculation is over.
|
|
54
|
+
|
|
55
|
+
To gain a better understanding, let's have a look at a simple program with a single branching structure:
|
|
56
|
+
|
|
57
|
+
${await (0, doc_cfg_1.printCFGCode)(shell, 'if(u) 3 else 2', { showCode: true, openCode: true, prefix: 'flowchart RL\n' })}
|
|
58
|
+
|
|
59
|
+
Here, you can see the \`if\` node followed by the condition (in this case merely \`u\`) that then splits into two branches for the two possible outcomes.
|
|
60
|
+
The \`if\` structure is terminated by the corresponding \`-exit\` node.
|
|
61
|
+
|
|
62
|
+
For you to compare, the following shows the CFG of an \`if\` without an \`else\` branch:
|
|
63
|
+
|
|
64
|
+
${await (0, doc_cfg_1.printCFGCode)(shell, 'if(u || v) 3', { showCode: true, openCode: false, prefix: 'flowchart RL\n' })}
|
|
65
|
+
|
|
66
|
+
The control flow graph also harmonizes with function definitions, and calls:
|
|
67
|
+
|
|
68
|
+
${await (0, doc_cfg_1.printCFGCode)(shell, 'f <- function() { 3 }\nf()', { showCode: true, openCode: true, prefix: 'flowchart RL\n' })}
|
|
69
|
+
|
|
70
|
+
In general, it is probably best to use the ${(0, doc_cli_option_1.getReplCommand)('controlflow*')} command in the REPL to investigate the CFG interactively.
|
|
71
|
+
Have a look at the ${(0, doc_types_1.shortLink)(visitor_1.visitCfgInReverseOrder.name, types.info)} function for a generic CFG visitor.
|
|
72
|
+
|
|
73
|
+
`;
|
|
74
|
+
}
|
|
75
|
+
if (require.main === module) {
|
|
76
|
+
(0, log_1.setMinLevelOfAllLogs)(6 /* LogLevel.Fatal */);
|
|
77
|
+
const shell = new shell_1.RShell();
|
|
78
|
+
void getText(shell).then(str => {
|
|
79
|
+
console.log(str);
|
|
80
|
+
}).finally(() => {
|
|
81
|
+
shell.close();
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=print-cfg-wiki.js.map
|
|
@@ -390,10 +390,10 @@ ${await (0, doc_repl_1.documentReplSession)(shell, [{
|
|
|
390
390
|
### Getting flowR to Talk
|
|
391
391
|
|
|
392
392
|
When using flowR from the CLI, you can use the ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'verbose')} option to get more information about what flowR is doing.
|
|
393
|
-
While coding, however, you can use the ${log_1.setMinLevelOfAllLogs.name} function to set the minimum level of logs to be displayed (this works with the ${(0, doc_types_1.shortLink)(log_2.FlowrLogger.name, info)} abstraction).
|
|
393
|
+
While coding, however, you can use the ${(0, doc_types_1.shortLink)(log_1.setMinLevelOfAllLogs.name, info)} function to set the minimum level of logs to be displayed (this works with the ${(0, doc_types_1.shortLink)(log_2.FlowrLogger.name, info)} abstraction).
|
|
394
394
|
In general, you can configure the levels of individual logs, such as the general \`log\` (obtained with ${(0, doc_types_1.shortLink)('getActiveLog', info)}) or the ${(0, doc_types_1.shortLink)('parseLog', info)}.
|
|
395
395
|
Please note that flowR makes no guarantees that log outputs are persistent across versions, and it is up to the implementors to provide sensible logging.
|
|
396
|
-
If you are an implementor and want to add logging, please make sure
|
|
396
|
+
If you are an implementor and want to add logging, please make sure there are no larger runtime impliciations when logging is disabled.
|
|
397
397
|
Have a look at the ${(0, doc_types_1.shortLink)(log_2.expensiveTrace.name, info)} function for example, which uses a function to generate the log message only when the log level is reached.
|
|
398
398
|
|
|
399
399
|
`;
|
|
@@ -203,12 +203,16 @@ ${(0, doc_code_1.codeBlock)('json', JSON.stringify({
|
|
|
203
203
|
engines: [{ type: 'r-shell' }],
|
|
204
204
|
solver: {
|
|
205
205
|
variables: config_1.VariableResolve.Alias,
|
|
206
|
+
evalStrings: true,
|
|
206
207
|
pointerTracking: true,
|
|
207
208
|
resolveSource: {
|
|
208
209
|
dropPaths: config_1.DropPathsOption.No,
|
|
209
210
|
ignoreCapitalization: true,
|
|
210
211
|
inferWorkingDirectory: config_1.InferWorkingDirectory.ActiveScript,
|
|
211
212
|
searchPath: []
|
|
213
|
+
},
|
|
214
|
+
slicer: {
|
|
215
|
+
threshold: 50
|
|
212
216
|
}
|
|
213
217
|
}
|
|
214
218
|
}, null, 2))}
|
|
@@ -62,6 +62,7 @@ It's also possible to filter the results based on the following properties:
|
|
|
62
62
|
The \`fileFilter\` property is an object made up of two properties:
|
|
63
63
|
- **Filter** (\`filter\`): A regular expression that a node's file attribute must match to be considered.
|
|
64
64
|
- **Include Undefined Files** (\`includeUndefinedFiles\`): If \`fileFilter\` is set, but a node's file attribute is not present, should we include it in the results? Defaults to \`true\`.
|
|
65
|
+
2. **Ignore Parameter Values** (\`ignoreParameterValues\`): Should we ignore default values for parameters in the results?
|
|
65
66
|
|
|
66
67
|
Re-using the example code from above, the following query attaches all calls to \`mean\` to the kind \`visualize\` and the subkind \`text\`,
|
|
67
68
|
all calls that start with \`read_\` to the kind \`input\` but only if they are not locally overwritten, and the subkind \`csv-file\`, and links all calls to \`points\` to the last call to \`plot\`:
|
|
@@ -122,6 +123,24 @@ ${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
|
122
123
|
`;
|
|
123
124
|
}
|
|
124
125
|
});
|
|
126
|
+
(0, doc_query_1.registerQueryDocumentation)('project', {
|
|
127
|
+
name: 'Project Query',
|
|
128
|
+
type: 'active',
|
|
129
|
+
shortDescription: 'Returns information about the analyzed project',
|
|
130
|
+
functionName: dataflow_query_executor_1.executeDataflowQuery.name,
|
|
131
|
+
functionFile: '../queries/catalog/project-query/project-query-executor.ts',
|
|
132
|
+
buildExplanation: async (shell) => {
|
|
133
|
+
const exampleCode = 'x + 1';
|
|
134
|
+
return `
|
|
135
|
+
This query returns the information about the analyzed project.
|
|
136
|
+
Currently, this is only the list of file paths included.
|
|
137
|
+
|
|
138
|
+
${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
139
|
+
type: 'project'
|
|
140
|
+
}], { showCode: true, collapseQuery: true })}
|
|
141
|
+
`;
|
|
142
|
+
}
|
|
143
|
+
});
|
|
125
144
|
(0, doc_query_1.registerQueryDocumentation)('normalized-ast', {
|
|
126
145
|
name: 'Normalized AST Query',
|
|
127
146
|
type: 'active',
|
|
@@ -405,7 +424,7 @@ print("hello world!")
|
|
|
405
424
|
`;
|
|
406
425
|
return `
|
|
407
426
|
This query extracts all dependencies from an R script, using a combination of a ${(0, doc_query_1.linkToQueryOfName)('call-context')}
|
|
408
|
-
and more advanced tracking in the [Dataflow Graph](${doc_files_1.FlowrWikiBaseRef}/Dataflow%20Graph).
|
|
427
|
+
and more advanced tracking in the [Dataflow Graph](${doc_files_1.FlowrWikiBaseRef}/Dataflow%20Graph).
|
|
409
428
|
|
|
410
429
|
In other words, if you have a script simply reading: \`${exampleCode}\`, the following query returns the loaded library:
|
|
411
430
|
${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
@@ -428,7 +447,7 @@ In the meantime we offer several properties to overwrite the default behavior (e
|
|
|
428
447
|
${await (0, doc_query_1.showQuery)(shell, longerCode, [{
|
|
429
448
|
type: 'dependencies',
|
|
430
449
|
ignoreDefaultFunctions: true,
|
|
431
|
-
libraryFunctions: [{ name: 'print', argIdx: 0, argName: 'library', resolveValue: true }],
|
|
450
|
+
libraryFunctions: [{ package: 'base', name: 'print', argIdx: 0, argName: 'library', resolveValue: true }],
|
|
432
451
|
sourceFunctions: [],
|
|
433
452
|
readFunctions: [],
|
|
434
453
|
writeFunctions: []
|
|
@@ -464,7 +483,7 @@ ${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
|
464
483
|
type: 'location-map'
|
|
465
484
|
}], { showCode: false, collapseQuery: true })}
|
|
466
485
|
|
|
467
|
-
All locations are given as a ${(0, doc_types_1.shortLink)('SourceRange', types.info)} in the format \`[start-line, start-column, end-line, end-column]\`.
|
|
486
|
+
All locations are given as a ${(0, doc_types_1.shortLink)('SourceRange', types.info)} paired with the file id in the format \`[file-id, [start-line, start-column, end-line, end-column]]\`.
|
|
468
487
|
|
|
469
488
|
`;
|
|
470
489
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eagleoutice/flowr",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.12",
|
|
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": {
|
|
@@ -33,10 +33,11 @@
|
|
|
33
33
|
"wiki:search-api": "ts-node src/documentation/print-search-wiki.ts",
|
|
34
34
|
"wiki:linting-and-testing": "ts-node src/documentation/print-linting-and-testing-wiki.ts",
|
|
35
35
|
"wiki:interface": "ts-node src/documentation/print-interface-wiki.ts",
|
|
36
|
+
"wiki:cfg": "ts-node src/documentation/print-cfg-wiki.ts",
|
|
36
37
|
"gen:readme": "ts-node src/documentation/print-readme.ts",
|
|
37
38
|
"build": "tsc --project .",
|
|
38
39
|
"build-dev": "npm run build && npm run build:copy-wasm",
|
|
39
|
-
"build:bundle-flowr": "npm run build && esbuild --bundle dist/src/cli/flowr.js --platform=node --bundle --minify --external:clipboardy --target=node22 --outfile=dist/src/cli/flowr.min.js && npm run build:copy-wasm-min",
|
|
40
|
+
"build:bundle-flowr": "npm run build && esbuild --bundle dist/src/cli/flowr.js --platform=node --tree-shaking=true --bundle --minify --external:clipboardy --target=node22 --outfile=dist/src/cli/flowr.min.js && npm run build:copy-wasm-min",
|
|
40
41
|
"build:copy-wasm": "mkdir -p dist/src/r-bridge/lang-4.x/tree-sitter/ && cp src/r-bridge/lang-4.x/tree-sitter/tree-sitter-r.wasm src/r-bridge/lang-4.x/tree-sitter/tree-sitter.wasm dist/src/r-bridge/lang-4.x/tree-sitter/",
|
|
41
42
|
"build:copy-wasm-min": "mkdir -p dist/src/cli && cp src/r-bridge/lang-4.x/tree-sitter/tree-sitter-r.wasm src/r-bridge/lang-4.x/tree-sitter/tree-sitter.wasm dist/src/cli",
|
|
42
43
|
"lint-local": "npx eslint --version && npx eslint src/ test/ --rule \"no-warning-comments: off\"",
|
|
@@ -199,12 +200,12 @@
|
|
|
199
200
|
"vitest": "^3.0.6"
|
|
200
201
|
},
|
|
201
202
|
"dependencies": {
|
|
202
|
-
"@msgpack/msgpack": "^3.0.1",
|
|
203
203
|
"@xmldom/xmldom": "^0.9.7",
|
|
204
204
|
"clipboardy": "^4.0.0",
|
|
205
205
|
"command-line-args": "^6.0.1",
|
|
206
206
|
"command-line-usage": "^7.0.3",
|
|
207
207
|
"joi": "^17.13.3",
|
|
208
|
+
"lz-string": "^1.5.0",
|
|
208
209
|
"n-readlines": "^1.0.1",
|
|
209
210
|
"n3": "^1.23.1",
|
|
210
211
|
"object-hash": "^3.0.0",
|
|
@@ -152,6 +152,16 @@ function doesFilepathMatch(file, filter) {
|
|
|
152
152
|
}
|
|
153
153
|
return filter.filter.test(file);
|
|
154
154
|
}
|
|
155
|
+
function isParameterDefaultValue(nodeId, ast) {
|
|
156
|
+
let node = ast.idMap.get(nodeId);
|
|
157
|
+
while (node !== undefined) {
|
|
158
|
+
if (node.info.role === "param-value" /* RoleInParent.ParameterDefaultValue */) {
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
node = node.info.parent ? ast.idMap.get(node.info.parent) : undefined;
|
|
162
|
+
}
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
155
165
|
/**
|
|
156
166
|
* Multi-stage call context query resolve.
|
|
157
167
|
*
|
|
@@ -209,6 +219,9 @@ function executeCallContextQueries({ dataflow: { graph }, ast }, queries) {
|
|
|
209
219
|
/* if the call is quoted, we do not want to link to it */
|
|
210
220
|
continue;
|
|
211
221
|
}
|
|
222
|
+
else if (query.ignoreParameterValues && isParameterDefaultValue(nodeId, ast)) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
212
225
|
let linkedIds = undefined;
|
|
213
226
|
if (cfg && isSubCallQuery(query)) {
|
|
214
227
|
const linked = Array.isArray(query.linkTo) ? query.linkTo : [query.linkTo];
|
|
@@ -41,6 +41,10 @@ export interface DefaultCallContextQueryFormat<RegexType extends RegExp | string
|
|
|
41
41
|
* Consider a case like `f <- function_of_interest`, do you want uses of `f` to be included in the results?
|
|
42
42
|
*/
|
|
43
43
|
readonly includeAliases?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Should we ignore default values for parameters in the results?
|
|
46
|
+
*/
|
|
47
|
+
readonly ignoreParameterValues?: boolean;
|
|
44
48
|
/**
|
|
45
49
|
* Filter that, when set, a node's file attribute must match to be considered
|
|
46
50
|
*/
|
|
@@ -32,6 +32,7 @@ exports.CallContextQueryDefinition = {
|
|
|
32
32
|
kind: joi_1.default.string().optional().description('The kind of the call, this can be used to group calls together (e.g., linking `plot` to `visualize`). Defaults to `.`'),
|
|
33
33
|
subkind: joi_1.default.string().optional().description('The subkind of the call, this can be used to uniquely identify the respective call type when grouping the output (e.g., the normalized name, linking `ggplot` to `plot`). Defaults to `.`'),
|
|
34
34
|
callTargets: joi_1.default.string().valid(...Object.values(identify_link_to_last_call_relation_1.CallTargets)).optional().description('Call targets the function may have. This defaults to `any`. Request this specifically to gain all call targets we can resolve.'),
|
|
35
|
+
ignoreParameterValues: joi_1.default.boolean().optional().description('Should we ignore default values for parameters in the results?'),
|
|
35
36
|
includeAliases: joi_1.default.boolean().optional().description('Consider a case like `f <- function_of_interest`, do you want uses of `f` to be included in the results?'),
|
|
36
37
|
fileFilter: joi_1.default.object({
|
|
37
38
|
fileFilter: joi_1.default.string().required().description('Regex that a node\'s file attribute must match to be considered'),
|
|
@@ -109,7 +109,7 @@ function identifyLinkToLastCallRelation(from, cfg, graph, { callName, ignoreIf,
|
|
|
109
109
|
if (ignoreIf && ignoreIf(from, graph)) {
|
|
110
110
|
return found;
|
|
111
111
|
}
|
|
112
|
-
(0, visitor_1.
|
|
112
|
+
(0, visitor_1.visitCfgInReverseOrder)(cfg, from, node => {
|
|
113
113
|
/* we ignore the start id as it cannot be the last call */
|
|
114
114
|
if (node === from) {
|
|
115
115
|
return;
|