@eagleoutice/flowr 2.2.14 → 2.2.15
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/cli/repl/commands/repl-commands.js +1 -1
- package/cli/repl/commands/repl-execute.js +2 -1
- package/config.js +1 -1
- package/control-flow/basic-cfg-guided-visitor.d.ts +3 -3
- package/control-flow/cfg-dead-code.d.ts +4 -0
- package/control-flow/cfg-dead-code.js +81 -0
- package/control-flow/cfg-simplification.d.ts +17 -6
- package/control-flow/cfg-simplification.js +23 -19
- package/control-flow/control-flow-graph.d.ts +2 -1
- package/control-flow/control-flow-graph.js +1 -0
- package/control-flow/dfg-cfg-guided-visitor.d.ts +4 -4
- package/control-flow/dfg-cfg-guided-visitor.js +1 -1
- package/control-flow/extract-cfg.d.ts +1 -1
- package/control-flow/extract-cfg.js +60 -57
- package/control-flow/semantic-cfg-guided-visitor.d.ts +17 -8
- package/control-flow/semantic-cfg-guided-visitor.js +50 -17
- package/control-flow/simple-visitor.d.ts +4 -0
- package/control-flow/simple-visitor.js +14 -0
- package/control-flow/syntax-cfg-guided-visitor.d.ts +2 -2
- package/dataflow/environments/built-in-config.d.ts +1 -0
- package/dataflow/environments/built-in.d.ts +10 -1
- package/dataflow/environments/built-in.js +9 -3
- package/dataflow/environments/default-builtin-config.js +1 -1
- package/dataflow/environments/resolve-by-name.d.ts +0 -36
- package/dataflow/environments/resolve-by-name.js +0 -240
- package/dataflow/eval/resolve/alias-tracking.d.ts +87 -0
- package/dataflow/eval/resolve/alias-tracking.js +349 -0
- package/dataflow/eval/resolve/resolve.d.ts +34 -0
- package/dataflow/eval/resolve/resolve.js +93 -0
- package/dataflow/eval/values/general.d.ts +27 -0
- package/dataflow/eval/values/general.js +73 -0
- package/dataflow/eval/values/intervals/interval-constants.d.ts +4 -0
- package/dataflow/eval/values/intervals/interval-constants.js +27 -0
- package/dataflow/eval/values/logical/logical-constants.d.ts +7 -0
- package/dataflow/eval/values/logical/logical-constants.js +31 -0
- package/dataflow/eval/values/r-value.d.ts +58 -0
- package/dataflow/eval/values/r-value.js +90 -0
- package/dataflow/eval/values/scalar/scalar-consatnts.d.ts +15 -0
- package/dataflow/eval/values/scalar/scalar-consatnts.js +35 -0
- package/dataflow/eval/values/sets/set-constants.d.ts +7 -0
- package/dataflow/eval/values/sets/set-constants.js +34 -0
- package/dataflow/eval/values/string/string-constants.d.ts +8 -0
- package/dataflow/eval/values/string/string-constants.js +40 -0
- package/dataflow/eval/values/vectors/vector-constants.d.ts +14 -0
- package/dataflow/eval/values/vectors/vector-constants.js +35 -0
- package/dataflow/graph/unknown-replacement.d.ts +11 -0
- package/dataflow/graph/unknown-replacement.js +12 -0
- package/dataflow/graph/unknown-side-effect.d.ts +7 -0
- package/dataflow/graph/unknown-side-effect.js +13 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +8 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +4 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +12 -9
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +5 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +9 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +12 -15
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +23 -0
- package/dataflow/internal/process/functions/call/known-call-handling.js +2 -1
- package/documentation/doc-util/doc-query.d.ts +6 -3
- package/documentation/doc-util/doc-query.js +3 -1
- package/documentation/print-cfg-wiki.js +6 -6
- package/documentation/print-dataflow-graph-wiki.js +4 -3
- package/documentation/print-engines-wiki.js +1 -1
- package/documentation/print-query-wiki.js +80 -0
- package/linter/rules/1-deprecated-functions.js +1 -1
- package/linter/rules/2-file-path-validity.js +1 -1
- package/package.json +1 -1
- package/queries/catalog/control-flow-query/control-flow-query-executor.d.ts +3 -0
- package/queries/catalog/control-flow-query/control-flow-query-executor.js +20 -0
- package/queries/catalog/control-flow-query/control-flow-query-format.d.ts +81 -0
- package/queries/catalog/control-flow-query/control-flow-query-format.js +34 -0
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +33 -32
- package/queries/catalog/linter-query/linter-query-format.js +2 -1
- package/queries/catalog/resolve-value-query/resolve-value-query-executor.js +3 -3
- package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +2 -1
- package/queries/catalog/resolve-value-query/resolve-value-query-format.js +2 -22
- package/queries/query.d.ts +61 -1
- package/queries/query.js +2 -0
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +11 -4
- package/search/search-executor/search-enrichers.js +5 -2
- package/slicing/criterion/parse.d.ts +8 -0
- package/slicing/criterion/parse.js +20 -0
- package/util/version.js +1 -1
package/package.json
CHANGED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ControlFlowQuery, ControlFlowQueryResult } from './control-flow-query-format';
|
|
2
|
+
import type { BasicQueryData } from '../../base-query-format';
|
|
3
|
+
export declare function executeControlFlowQuery({ dataflow: { graph }, ast }: BasicQueryData, queries: readonly ControlFlowQuery[]): ControlFlowQueryResult;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.executeControlFlowQuery = executeControlFlowQuery;
|
|
4
|
+
const log_1 = require("../../../util/log");
|
|
5
|
+
const extract_cfg_1 = require("../../../control-flow/extract-cfg");
|
|
6
|
+
function executeControlFlowQuery({ dataflow: { graph }, ast }, queries) {
|
|
7
|
+
if (queries.length !== 1) {
|
|
8
|
+
log_1.log.warn('The control flow query expects only up to one query, but got', queries.length);
|
|
9
|
+
}
|
|
10
|
+
const query = queries[0];
|
|
11
|
+
const start = Date.now();
|
|
12
|
+
const controlFlow = (0, extract_cfg_1.extractCfg)(ast, graph, query.config?.simplificationPasses);
|
|
13
|
+
return {
|
|
14
|
+
'.meta': {
|
|
15
|
+
timing: Date.now() - start
|
|
16
|
+
},
|
|
17
|
+
controlFlow
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=control-flow-query-executor.js.map
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { BaseQueryFormat, BaseQueryResult } from '../../base-query-format';
|
|
2
|
+
import Joi from 'joi';
|
|
3
|
+
import { executeControlFlowQuery } from './control-flow-query-executor';
|
|
4
|
+
import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
5
|
+
import type { ControlFlowInformation } from '../../../control-flow/control-flow-graph';
|
|
6
|
+
import type { CfgSimplificationPassName } from '../../../control-flow/cfg-simplification';
|
|
7
|
+
/**
|
|
8
|
+
* Provides the control flow graph with an optional, fixed configuration
|
|
9
|
+
*/
|
|
10
|
+
export interface ControlFlowQuery extends BaseQueryFormat {
|
|
11
|
+
readonly type: 'control-flow';
|
|
12
|
+
readonly config?: {
|
|
13
|
+
/**
|
|
14
|
+
* If set, the control flow graph will be simplified using the given passes.
|
|
15
|
+
* Defaults to the default simplification order.
|
|
16
|
+
*/
|
|
17
|
+
simplificationPasses?: readonly CfgSimplificationPassName[];
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export interface ControlFlowQueryResult extends BaseQueryResult {
|
|
21
|
+
readonly controlFlow: ControlFlowInformation;
|
|
22
|
+
}
|
|
23
|
+
export declare const ControlFlowQueryDefinition: {
|
|
24
|
+
readonly executor: typeof executeControlFlowQuery;
|
|
25
|
+
readonly asciiSummarizer: (formatter: import("../../../util/text/ansi").OutputFormatter, processed: import("../../../core/steps/pipeline/pipeline").PipelineOutput<import("../../../core/steps/pipeline/pipeline").Pipeline<{
|
|
26
|
+
readonly name: "parse";
|
|
27
|
+
readonly humanReadableName: "parse with R shell";
|
|
28
|
+
readonly description: "Parse the given R code into an AST";
|
|
29
|
+
readonly processor: (_results: unknown, input: Partial<import("../../../r-bridge/parser").ParseRequiredInput<string>>) => Promise<import("../../../r-bridge/parser").ParseStepOutput<string>>;
|
|
30
|
+
readonly executed: import("../../../core/steps/pipeline-step").PipelineStepStage.OncePerFile;
|
|
31
|
+
readonly printer: {
|
|
32
|
+
readonly 0: typeof import("../../../core/print/print").internalPrinter;
|
|
33
|
+
readonly 2: {
|
|
34
|
+
(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
|
|
35
|
+
(value: any, replacer?: (number | string)[] | null, space?: string | number): string;
|
|
36
|
+
};
|
|
37
|
+
readonly 5: ({ parsed }: import("../../../r-bridge/parser").ParseStepOutput<string>, config: import("../../../util/quads").QuadSerializationConfiguration) => string;
|
|
38
|
+
};
|
|
39
|
+
readonly dependencies: readonly [];
|
|
40
|
+
readonly requiredInput: import("../../../r-bridge/parser").ParseRequiredInput<string>;
|
|
41
|
+
} | {
|
|
42
|
+
readonly name: "normalize";
|
|
43
|
+
readonly humanReadableName: "normalize";
|
|
44
|
+
readonly description: "Normalize the AST to flowR's AST";
|
|
45
|
+
readonly processor: (results: {
|
|
46
|
+
parse?: import("../../../r-bridge/parser").ParseStepOutput<string>;
|
|
47
|
+
}, input: Partial<import("../../../core/steps/all/core/10-normalize").NormalizeRequiredInput>) => import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst<import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../../r-bridge/lang-4.x/ast/model/model").RNode<import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>>;
|
|
48
|
+
readonly executed: import("../../../core/steps/pipeline-step").PipelineStepStage.OncePerFile;
|
|
49
|
+
readonly printer: {
|
|
50
|
+
readonly 0: typeof import("../../../core/print/print").internalPrinter;
|
|
51
|
+
readonly 2: typeof import("../../../core/print/normalize-printer").normalizedAstToJson;
|
|
52
|
+
readonly 5: typeof import("../../../core/print/normalize-printer").normalizedAstToQuads;
|
|
53
|
+
readonly 3: typeof import("../../../core/print/normalize-printer").printNormalizedAstToMermaid;
|
|
54
|
+
readonly 4: typeof import("../../../core/print/normalize-printer").printNormalizedAstToMermaidUrl;
|
|
55
|
+
};
|
|
56
|
+
readonly dependencies: readonly ["parse"];
|
|
57
|
+
readonly requiredInput: import("../../../core/steps/all/core/10-normalize").NormalizeRequiredInput;
|
|
58
|
+
} | {
|
|
59
|
+
readonly humanReadableName: "dataflow";
|
|
60
|
+
readonly processor: (results: {
|
|
61
|
+
normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
62
|
+
}, input: {
|
|
63
|
+
request?: import("../../../r-bridge/retriever").RParseRequests;
|
|
64
|
+
parser?: import("../../../r-bridge/parser").Parser<import("../../../r-bridge/parser").KnownParserType>;
|
|
65
|
+
}) => import("../../../dataflow/info").DataflowInformation;
|
|
66
|
+
readonly requiredInput: {};
|
|
67
|
+
readonly name: "dataflow";
|
|
68
|
+
readonly description: "Construct the dataflow graph";
|
|
69
|
+
readonly executed: import("../../../core/steps/pipeline-step").PipelineStepStage.OncePerFile;
|
|
70
|
+
readonly printer: {
|
|
71
|
+
readonly 0: typeof import("../../../core/print/print").internalPrinter;
|
|
72
|
+
readonly 2: typeof import("../../../core/print/dataflow-printer").dataflowGraphToJson;
|
|
73
|
+
readonly 5: typeof import("../../../core/print/dataflow-printer").dataflowGraphToQuads;
|
|
74
|
+
readonly 3: typeof import("../../../core/print/dataflow-printer").dataflowGraphToMermaid;
|
|
75
|
+
readonly 4: typeof import("../../../core/print/dataflow-printer").dataflowGraphToMermaidUrl;
|
|
76
|
+
};
|
|
77
|
+
readonly dependencies: readonly ["normalize"];
|
|
78
|
+
}>>, queryResults: BaseQueryResult, result: string[]) => true;
|
|
79
|
+
readonly schema: Joi.ObjectSchema<any>;
|
|
80
|
+
readonly flattenInvolvedNodes: (queryResults: BaseQueryResult) => NodeId[];
|
|
81
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
exports.ControlFlowQueryDefinition = void 0;
|
|
7
|
+
const ansi_1 = require("../../../util/text/ansi");
|
|
8
|
+
const joi_1 = __importDefault(require("joi"));
|
|
9
|
+
const control_flow_query_executor_1 = require("./control-flow-query-executor");
|
|
10
|
+
const control_flow_graph_1 = require("../../../control-flow/control-flow-graph");
|
|
11
|
+
const cfg_1 = require("../../../util/mermaid/cfg");
|
|
12
|
+
const cfg_simplification_1 = require("../../../control-flow/cfg-simplification");
|
|
13
|
+
exports.ControlFlowQueryDefinition = {
|
|
14
|
+
executor: control_flow_query_executor_1.executeControlFlowQuery,
|
|
15
|
+
asciiSummarizer: (formatter, processed, queryResults, result) => {
|
|
16
|
+
const out = queryResults;
|
|
17
|
+
result.push(`Query: ${(0, ansi_1.bold)('control-flow', formatter)} (${out['.meta'].timing.toFixed(0)}ms)`);
|
|
18
|
+
result.push(` ╰ CFG: ${(0, cfg_1.cfgToMermaidUrl)(out.controlFlow, processed.normalize)}`);
|
|
19
|
+
return true;
|
|
20
|
+
},
|
|
21
|
+
schema: joi_1.default.object({
|
|
22
|
+
type: joi_1.default.string().valid('control-flow').required().description('The type of the query.'),
|
|
23
|
+
config: joi_1.default.object({
|
|
24
|
+
simplificationPasses: joi_1.default.array().items(joi_1.default.string().valid(...Object.keys(cfg_simplification_1.CfgSimplificationPasses))).description('The simplification passes to apply to the control flow graph. If unset, the default simplification order will be used.')
|
|
25
|
+
}).optional().description('Optional configuration for the control flow query.')
|
|
26
|
+
}).description('The control flow query provides the control flow graph of the analysis, optionally simplified.'),
|
|
27
|
+
flattenInvolvedNodes: (queryResults) => {
|
|
28
|
+
const out = queryResults;
|
|
29
|
+
return [...out.controlFlow.graph.vertices(true)]
|
|
30
|
+
.filter(([, v]) => v.type !== control_flow_graph_1.CfgVertexType.Block)
|
|
31
|
+
.map(v => v[0]);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=control-flow-query-format.js.map
|
|
@@ -11,13 +11,16 @@ const r_function_call_1 = require("../../../r-bridge/lang-4.x/ast/model/nodes/r-
|
|
|
11
11
|
const visitor_1 = require("../../../r-bridge/lang-4.x/ast/model/processing/visitor");
|
|
12
12
|
const assert_1 = require("../../../util/assert");
|
|
13
13
|
const objects_1 = require("../../../util/objects");
|
|
14
|
-
const resolve_by_name_1 = require("../../../dataflow/environments/resolve-by-name");
|
|
15
14
|
const library_functions_1 = require("./function-info/library-functions");
|
|
16
15
|
const source_functions_1 = require("./function-info/source-functions");
|
|
17
16
|
const read_functions_1 = require("./function-info/read-functions");
|
|
18
17
|
const write_functions_1 = require("./function-info/write-functions");
|
|
19
18
|
const function_info_1 = require("./function-info/function-info");
|
|
20
19
|
const identify_link_to_last_call_relation_1 = require("../call-context-query/identify-link-to-last-call-relation");
|
|
20
|
+
const r_value_1 = require("../../../dataflow/eval/values/r-value");
|
|
21
|
+
const general_1 = require("../../../dataflow/eval/values/general");
|
|
22
|
+
const alias_tracking_1 = require("../../../dataflow/eval/resolve/alias-tracking");
|
|
23
|
+
const string_constants_1 = require("../../../dataflow/eval/values/string/string-constants");
|
|
21
24
|
function collectNamespaceAccesses(data, libraries) {
|
|
22
25
|
/* for libraries, we have to additionally track all uses of `::` and `:::`, for this we currently simply traverse all uses */
|
|
23
26
|
(0, visitor_1.visitAst)(data.ast.ast, n => {
|
|
@@ -203,31 +206,32 @@ function resolveBasedOnConfig(data, vertex, argument, environment, idMap, resolv
|
|
|
203
206
|
full = false;
|
|
204
207
|
}
|
|
205
208
|
}
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
209
|
+
full = true;
|
|
210
|
+
const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(argument, { environment, graph: data.dataflow.graph, full: full }));
|
|
211
|
+
if (resolved) {
|
|
212
|
+
const values = [];
|
|
213
|
+
for (const value of resolved.elements) {
|
|
214
|
+
if (!(0, r_value_1.isValue)(value)) {
|
|
215
|
+
return undefined;
|
|
216
|
+
}
|
|
217
|
+
if (value.type === 'string' && (0, r_value_1.isValue)(value.value)) {
|
|
218
|
+
values.push(value.value.str);
|
|
219
|
+
}
|
|
220
|
+
else if (value.type === 'logical' && (0, r_value_1.isValue)(value.value)) {
|
|
221
|
+
values.push(value.value.valueOf() ? 'TRUE' : 'FALSE');
|
|
222
|
+
}
|
|
223
|
+
else if (value.type === 'vector' && (0, r_value_1.isValue)(value.elements)) {
|
|
224
|
+
const elements = (0, string_constants_1.collectStrings)(value.elements);
|
|
225
|
+
if (elements === undefined) {
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
values.push(...elements);
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
return undefined;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return values;
|
|
231
235
|
}
|
|
232
236
|
}
|
|
233
237
|
/**
|
|
@@ -254,16 +258,14 @@ function getArgumentValue(data, vertex, argumentIndex, argumentName, resolveValu
|
|
|
254
258
|
valueNode = valueNode.value;
|
|
255
259
|
}
|
|
256
260
|
if (valueNode) {
|
|
257
|
-
// TDODO: extend vector support etc.
|
|
258
261
|
// this should be evaluated in the callee-context
|
|
259
|
-
const values = resolveBasedOnConfig(data, vertex, valueNode, vertex.environment, graph.idMap, resolveValue)
|
|
260
|
-
?.map(unwrapRValue) ?? [dependencies_query_format_1.Unknown];
|
|
262
|
+
const values = resolveBasedOnConfig(data, vertex, valueNode, vertex.environment, graph.idMap, resolveValue) ?? [dependencies_query_format_1.Unknown];
|
|
261
263
|
map.set(ref, new Set(values));
|
|
262
264
|
}
|
|
263
265
|
}
|
|
264
266
|
return map;
|
|
265
267
|
}
|
|
266
|
-
if (vertex.args.length
|
|
268
|
+
if (argumentIndex < vertex.args.length) {
|
|
267
269
|
const arg = (0, graph_1.getReferenceOfArgument)(vertex.args[argumentIndex]);
|
|
268
270
|
if (!arg) {
|
|
269
271
|
return undefined;
|
|
@@ -273,8 +275,7 @@ function getArgumentValue(data, vertex, argumentIndex, argumentName, resolveValu
|
|
|
273
275
|
valueNode = valueNode.value;
|
|
274
276
|
}
|
|
275
277
|
if (valueNode) {
|
|
276
|
-
const values = resolveBasedOnConfig(data, vertex, valueNode, vertex.environment, graph.idMap, resolveValue)
|
|
277
|
-
?.map(unwrapRValue) ?? [dependencies_query_format_1.Unknown];
|
|
278
|
+
const values = resolveBasedOnConfig(data, vertex, valueNode, vertex.environment, graph.idMap, resolveValue) ?? [dependencies_query_format_1.Unknown];
|
|
278
279
|
return new Map([[arg, new Set(values)]]);
|
|
279
280
|
}
|
|
280
281
|
}
|
|
@@ -10,6 +10,7 @@ const linter_rules_1 = require("../../../linter/linter-rules");
|
|
|
10
10
|
const linter_format_1 = require("../../../linter/linter-format");
|
|
11
11
|
const ansi_1 = require("../../../util/text/ansi");
|
|
12
12
|
const time_1 = require("../../../util/text/time");
|
|
13
|
+
const doc_code_1 = require("../../../documentation/doc-util/doc-code");
|
|
13
14
|
exports.LinterQueryDefinition = {
|
|
14
15
|
executor: linter_query_executor_1.executeLinterQuery,
|
|
15
16
|
asciiSummarizer: (formatter, _processed, queryResults, result) => {
|
|
@@ -27,7 +28,7 @@ exports.LinterQueryDefinition = {
|
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
|
-
result.push(` ╰
|
|
31
|
+
result.push(` ╰ _Metadata_: ${(0, doc_code_1.codeInline)(JSON.stringify(results['.meta']))}`);
|
|
31
32
|
}
|
|
32
33
|
return true;
|
|
33
34
|
},
|
|
@@ -4,7 +4,7 @@ exports.fingerPrintOfQuery = fingerPrintOfQuery;
|
|
|
4
4
|
exports.executeResolveValueQuery = executeResolveValueQuery;
|
|
5
5
|
const log_1 = require("../../../util/log");
|
|
6
6
|
const parse_1 = require("../../../slicing/criterion/parse");
|
|
7
|
-
const
|
|
7
|
+
const alias_tracking_1 = require("../../../dataflow/eval/resolve/alias-tracking");
|
|
8
8
|
function fingerPrintOfQuery(query) {
|
|
9
9
|
return JSON.stringify(query);
|
|
10
10
|
}
|
|
@@ -18,9 +18,9 @@ function executeResolveValueQuery({ dataflow: { graph }, ast }, queries) {
|
|
|
18
18
|
}
|
|
19
19
|
const values = query.criteria
|
|
20
20
|
.map(criteria => (0, parse_1.slicingCriterionToId)(criteria, ast.idMap))
|
|
21
|
-
.flatMap(ident => (0,
|
|
21
|
+
.flatMap(ident => (0, alias_tracking_1.resolveIdToValue)(ident, { graph, full: true, idMap: ast.idMap }));
|
|
22
22
|
results[key] = {
|
|
23
|
-
values: values
|
|
23
|
+
values: values
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
return {
|
|
@@ -2,6 +2,7 @@ import type { BaseQueryFormat, BaseQueryResult } from '../../base-query-format';
|
|
|
2
2
|
import type { SlicingCriteria } from '../../../slicing/criterion/parse';
|
|
3
3
|
import Joi from 'joi';
|
|
4
4
|
import { executeResolveValueQuery } from './resolve-value-query-executor';
|
|
5
|
+
import type { ResolveResult } from '../../../dataflow/eval/resolve/alias-tracking';
|
|
5
6
|
export interface ResolveValueQuery extends BaseQueryFormat {
|
|
6
7
|
readonly type: 'resolve-value';
|
|
7
8
|
/** The slicing criteria to use */
|
|
@@ -9,7 +10,7 @@ export interface ResolveValueQuery extends BaseQueryFormat {
|
|
|
9
10
|
}
|
|
10
11
|
export interface ResolveValueQueryResult extends BaseQueryResult {
|
|
11
12
|
results: Record<string, {
|
|
12
|
-
values:
|
|
13
|
+
values: ResolveResult[];
|
|
13
14
|
}>;
|
|
14
15
|
}
|
|
15
16
|
export declare const ResolveValueQueryDefinition: {
|
|
@@ -8,27 +8,7 @@ const ansi_1 = require("../../../util/text/ansi");
|
|
|
8
8
|
const time_1 = require("../../../util/text/time");
|
|
9
9
|
const joi_1 = __importDefault(require("joi"));
|
|
10
10
|
const resolve_value_query_executor_1 = require("./resolve-value-query-executor");
|
|
11
|
-
|
|
12
|
-
if (value === null || value === undefined) {
|
|
13
|
-
return 'undefined';
|
|
14
|
-
}
|
|
15
|
-
else if (typeof value === 'string') {
|
|
16
|
-
return value;
|
|
17
|
-
}
|
|
18
|
-
else if (typeof value === 'object') {
|
|
19
|
-
if ('num' in value) {
|
|
20
|
-
return value.num.toString();
|
|
21
|
-
}
|
|
22
|
-
else if ('str' in value) {
|
|
23
|
-
return `${value.quotes}${value.str}${value.quotes}`;
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
console.warn('omega lul');
|
|
27
|
-
return JSON.stringify(value);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return value;
|
|
31
|
-
}
|
|
11
|
+
const r_value_1 = require("../../../dataflow/eval/values/r-value");
|
|
32
12
|
exports.ResolveValueQueryDefinition = {
|
|
33
13
|
executor: resolve_value_query_executor_1.executeResolveValueQuery,
|
|
34
14
|
asciiSummarizer: (formatter, _processed, queryResults, result) => {
|
|
@@ -37,7 +17,7 @@ exports.ResolveValueQueryDefinition = {
|
|
|
37
17
|
for (const [fingerprint, obj] of Object.entries(out.results)) {
|
|
38
18
|
const { criteria } = JSON.parse(fingerprint);
|
|
39
19
|
result.push(` ╰ Values for {${criteria.join(', ')}}`);
|
|
40
|
-
result.push(` ╰ ${obj.values.map(v =>
|
|
20
|
+
result.push(` ╰ ${obj.values.map(v => (0, r_value_1.stringifyValue)(v)).join(', ')}`);
|
|
41
21
|
}
|
|
42
22
|
return true;
|
|
43
23
|
},
|
package/queries/query.d.ts
CHANGED
|
@@ -23,7 +23,8 @@ import type { ProjectQuery } from './catalog/project-query/project-query-format'
|
|
|
23
23
|
import type { OriginQuery } from './catalog/origin-query/origin-query-format';
|
|
24
24
|
import type { LinterQuery } from './catalog/linter-query/linter-query-format';
|
|
25
25
|
import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
26
|
-
|
|
26
|
+
import type { ControlFlowQuery } from './catalog/control-flow-query/control-flow-query-format';
|
|
27
|
+
export type Query = CallContextQuery | ConfigQuery | SearchQuery | DataflowQuery | ControlFlowQuery | DataflowLensQuery | NormalizedAstQuery | IdMapQuery | DataflowClusterQuery | StaticSliceQuery | LineageQuery | DependenciesQuery | LocationMapQuery | HappensBeforeQuery | ResolveValueQuery | ProjectQuery | OriginQuery | LinterQuery;
|
|
27
28
|
export type QueryArgumentsWithType<QueryType extends BaseQueryFormat['type']> = Query & {
|
|
28
29
|
type: QueryType;
|
|
29
30
|
};
|
|
@@ -54,6 +55,65 @@ export declare const SupportedQueries: {
|
|
|
54
55
|
readonly schema: Joi.ObjectSchema<any>;
|
|
55
56
|
readonly flattenInvolvedNodes: () => never[];
|
|
56
57
|
};
|
|
58
|
+
readonly 'control-flow': {
|
|
59
|
+
readonly executor: typeof import("./catalog/control-flow-query/control-flow-query-executor").executeControlFlowQuery;
|
|
60
|
+
readonly asciiSummarizer: (formatter: OutputFormatter, processed: PipelineOutput<import("../core/steps/pipeline/pipeline").Pipeline<{
|
|
61
|
+
readonly name: "parse";
|
|
62
|
+
readonly humanReadableName: "parse with R shell";
|
|
63
|
+
readonly description: "Parse the given R code into an AST";
|
|
64
|
+
readonly processor: (_results: unknown, input: Partial<import("../r-bridge/parser").ParseRequiredInput<string>>) => Promise<import("../r-bridge/parser").ParseStepOutput<string>>;
|
|
65
|
+
readonly executed: import("../core/steps/pipeline-step").PipelineStepStage.OncePerFile;
|
|
66
|
+
readonly printer: {
|
|
67
|
+
readonly 0: typeof import("../core/print/print").internalPrinter;
|
|
68
|
+
readonly 2: {
|
|
69
|
+
(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
|
|
70
|
+
(value: any, replacer?: (number | string)[] | null, space?: string | number): string;
|
|
71
|
+
};
|
|
72
|
+
readonly 5: ({ parsed }: import("../r-bridge/parser").ParseStepOutput<string>, config: import("../util/quads").QuadSerializationConfiguration) => string;
|
|
73
|
+
};
|
|
74
|
+
readonly dependencies: readonly [];
|
|
75
|
+
readonly requiredInput: import("../r-bridge/parser").ParseRequiredInput<string>;
|
|
76
|
+
} | {
|
|
77
|
+
readonly name: "normalize";
|
|
78
|
+
readonly humanReadableName: "normalize";
|
|
79
|
+
readonly description: "Normalize the AST to flowR's AST";
|
|
80
|
+
readonly processor: (results: {
|
|
81
|
+
parse?: import("../r-bridge/parser").ParseStepOutput<string>;
|
|
82
|
+
}, input: Partial<import("../core/steps/all/core/10-normalize").NormalizeRequiredInput>) => import("../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../r-bridge/lang-4.x/ast/model/model").RNode<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>>;
|
|
83
|
+
readonly executed: import("../core/steps/pipeline-step").PipelineStepStage.OncePerFile;
|
|
84
|
+
readonly printer: {
|
|
85
|
+
readonly 0: typeof import("../core/print/print").internalPrinter;
|
|
86
|
+
readonly 2: typeof import("../core/print/normalize-printer").normalizedAstToJson;
|
|
87
|
+
readonly 5: typeof import("../core/print/normalize-printer").normalizedAstToQuads;
|
|
88
|
+
readonly 3: typeof import("../core/print/normalize-printer").printNormalizedAstToMermaid;
|
|
89
|
+
readonly 4: typeof import("../core/print/normalize-printer").printNormalizedAstToMermaidUrl;
|
|
90
|
+
};
|
|
91
|
+
readonly dependencies: readonly ["parse"];
|
|
92
|
+
readonly requiredInput: import("../core/steps/all/core/10-normalize").NormalizeRequiredInput;
|
|
93
|
+
} | {
|
|
94
|
+
readonly humanReadableName: "dataflow";
|
|
95
|
+
readonly processor: (results: {
|
|
96
|
+
normalize?: import("../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
97
|
+
}, input: {
|
|
98
|
+
request?: import("../r-bridge/retriever").RParseRequests;
|
|
99
|
+
parser?: import("../r-bridge/parser").Parser<import("../r-bridge/parser").KnownParserType>;
|
|
100
|
+
}) => import("../dataflow/info").DataflowInformation;
|
|
101
|
+
readonly requiredInput: {};
|
|
102
|
+
readonly name: "dataflow";
|
|
103
|
+
readonly description: "Construct the dataflow graph";
|
|
104
|
+
readonly executed: import("../core/steps/pipeline-step").PipelineStepStage.OncePerFile;
|
|
105
|
+
readonly printer: {
|
|
106
|
+
readonly 0: typeof import("../core/print/print").internalPrinter;
|
|
107
|
+
readonly 2: typeof import("../core/print/dataflow-printer").dataflowGraphToJson;
|
|
108
|
+
readonly 5: typeof import("../core/print/dataflow-printer").dataflowGraphToQuads;
|
|
109
|
+
readonly 3: typeof import("../core/print/dataflow-printer").dataflowGraphToMermaid;
|
|
110
|
+
readonly 4: typeof import("../core/print/dataflow-printer").dataflowGraphToMermaidUrl;
|
|
111
|
+
};
|
|
112
|
+
readonly dependencies: readonly ["normalize"];
|
|
113
|
+
}>>, queryResults: BaseQueryResult, result: string[]) => true;
|
|
114
|
+
readonly schema: Joi.ObjectSchema<any>;
|
|
115
|
+
readonly flattenInvolvedNodes: (queryResults: BaseQueryResult) => NodeId[];
|
|
116
|
+
};
|
|
57
117
|
readonly dataflow: {
|
|
58
118
|
readonly executor: typeof import("./catalog/dataflow-query/dataflow-query-executor").executeDataflowQuery;
|
|
59
119
|
readonly asciiSummarizer: (formatter: OutputFormatter, _processed: PipelineOutput<import("../core/steps/pipeline/pipeline").Pipeline<{
|
package/queries/query.js
CHANGED
|
@@ -30,9 +30,11 @@ const dataflow_lens_query_format_1 = require("./catalog/dataflow-lens-query/data
|
|
|
30
30
|
const project_query_format_1 = require("./catalog/project-query/project-query-format");
|
|
31
31
|
const origin_query_format_1 = require("./catalog/origin-query/origin-query-format");
|
|
32
32
|
const linter_query_format_1 = require("./catalog/linter-query/linter-query-format");
|
|
33
|
+
const control_flow_query_format_1 = require("./catalog/control-flow-query/control-flow-query-format");
|
|
33
34
|
exports.SupportedQueries = {
|
|
34
35
|
'call-context': call_context_query_format_1.CallContextQueryDefinition,
|
|
35
36
|
'config': config_query_format_1.ConfigQueryDefinition,
|
|
37
|
+
'control-flow': control_flow_query_format_1.ControlFlowQueryDefinition,
|
|
36
38
|
'dataflow': dataflow_query_format_1.DataflowQueryDefinition,
|
|
37
39
|
'dataflow-lens': dataflow_lens_query_format_1.DataflowLensQueryDefinition,
|
|
38
40
|
'id-map': id_map_query_format_1.IdMapQueryDefinition,
|
|
@@ -293,13 +293,20 @@ function convertTreeNode(node) {
|
|
|
293
293
|
...defaultInfo
|
|
294
294
|
};
|
|
295
295
|
}
|
|
296
|
-
const
|
|
296
|
+
const rawArgs = nonErrorChildren(argsParentheses);
|
|
297
|
+
const [comments, noCommentrawArgs] = splitComments(rawArgs);
|
|
298
|
+
const args = (0, arrays_1.splitArrayOn)(noCommentrawArgs.slice(1, -1), x => x.type === 'comma');
|
|
297
299
|
const funcRange = makeSourceRange(func);
|
|
300
|
+
const mappedArgs = args.map(n => n.length == 0 ? r_function_call_1.EmptyArgument : convertTreeNode(n[0]));
|
|
298
301
|
const call = {
|
|
299
|
-
arguments:
|
|
302
|
+
arguments: mappedArgs,
|
|
300
303
|
location: funcRange,
|
|
301
304
|
lexeme: func.text,
|
|
302
|
-
...defaultInfo
|
|
305
|
+
...defaultInfo,
|
|
306
|
+
info: {
|
|
307
|
+
...defaultInfo.info,
|
|
308
|
+
additionalTokens: comments.map(c => c[1]),
|
|
309
|
+
}
|
|
303
310
|
};
|
|
304
311
|
if (func.type === tree_sitter_types_1.TreeSitterType.Identifier || func.type === tree_sitter_types_1.TreeSitterType.String || func.type === tree_sitter_types_1.TreeSitterType.NamespaceOperator || func.type === tree_sitter_types_1.TreeSitterType.Return) {
|
|
305
312
|
let funcNode = convertTreeNode(func);
|
|
@@ -491,7 +498,7 @@ function convertTreeNode(node) {
|
|
|
491
498
|
const nameRange = makeSourceRange(nameNode);
|
|
492
499
|
return {
|
|
493
500
|
type: type_1.RType.Argument,
|
|
494
|
-
name
|
|
501
|
+
name,
|
|
495
502
|
value: valueNode ? convertTreeNode(valueNode) : undefined,
|
|
496
503
|
location: nameRange,
|
|
497
504
|
lexeme: nameNode.text,
|
|
@@ -4,11 +4,11 @@ exports.Enrichments = exports.Enrichment = void 0;
|
|
|
4
4
|
exports.enrichmentContent = enrichmentContent;
|
|
5
5
|
exports.enrich = enrich;
|
|
6
6
|
const vertex_1 = require("../../dataflow/graph/vertex");
|
|
7
|
-
const log_1 = require("../../util/log");
|
|
8
7
|
const identify_link_to_last_call_relation_1 = require("../../queries/catalog/call-context-query/identify-link-to-last-call-relation");
|
|
9
8
|
const assert_1 = require("../../util/assert");
|
|
10
9
|
const extract_cfg_1 = require("../../control-flow/extract-cfg");
|
|
11
10
|
const dfg_get_origin_1 = require("../../dataflow/origin/dfg-get-origin");
|
|
11
|
+
const node_id_1 = require("../../r-bridge/lang-4.x/ast/model/processing/node-id");
|
|
12
12
|
/**
|
|
13
13
|
* An enumeration that stores the names of the available enrichments that can be applied to a set of search elements.
|
|
14
14
|
* See {@link FlowrSearchBuilder.with} for more information on how to apply enrichments.
|
|
@@ -31,7 +31,7 @@ exports.Enrichments = {
|
|
|
31
31
|
if (callVertex?.tag === vertex_1.VertexType.FunctionCall) {
|
|
32
32
|
const origins = (0, dfg_get_origin_1.getOriginInDfg)(data.dataflow.graph, callVertex.id);
|
|
33
33
|
if (!origins || origins.length === 0) {
|
|
34
|
-
|
|
34
|
+
content.targets = [(0, node_id_1.recoverName)(callVertex.id, data.normalize.idMap)];
|
|
35
35
|
return content;
|
|
36
36
|
}
|
|
37
37
|
// find call targets in user code (which have ids!)
|
|
@@ -47,6 +47,9 @@ exports.Enrichments = {
|
|
|
47
47
|
return undefined;
|
|
48
48
|
}
|
|
49
49
|
}).filter(assert_1.isNotUndefined));
|
|
50
|
+
if (content.targets.length === 0) {
|
|
51
|
+
content.targets = [(0, node_id_1.recoverName)(callVertex.id, data.normalize.idMap)];
|
|
52
|
+
}
|
|
50
53
|
}
|
|
51
54
|
return content;
|
|
52
55
|
},
|
|
@@ -11,8 +11,16 @@ export declare class CriteriaParseError extends Error {
|
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* Takes a criterion in the form of `line:column` or `line@variable-name` and returns the corresponding node id
|
|
14
|
+
*
|
|
15
|
+
* @see {@link tryResolveSliceCriterionToId} for a version that does not throw an error
|
|
14
16
|
*/
|
|
15
17
|
export declare function slicingCriterionToId(criterion: SingleSlicingCriterion, idMap: AstIdMap): NodeId;
|
|
18
|
+
/**
|
|
19
|
+
* Tries to resolve a slicing criterion to an id, but does not throw an error if it fails.
|
|
20
|
+
*
|
|
21
|
+
* @see {@link slicingCriterionToId} for the version that throws an error
|
|
22
|
+
*/
|
|
23
|
+
export declare function tryResolveSliceCriterionToId(criterion: string | NodeId, idMap: AstIdMap): NodeId | undefined;
|
|
16
24
|
export interface DecodedCriterion {
|
|
17
25
|
criterion: SingleSlicingCriterion;
|
|
18
26
|
id: NodeId;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CriteriaParseError = void 0;
|
|
4
4
|
exports.slicingCriterionToId = slicingCriterionToId;
|
|
5
|
+
exports.tryResolveSliceCriterionToId = tryResolveSliceCriterionToId;
|
|
5
6
|
exports.convertAllSlicingCriteriaToIds = convertAllSlicingCriteriaToIds;
|
|
6
7
|
const log_1 = require("../../util/log");
|
|
7
8
|
const node_id_1 = require("../../r-bridge/lang-4.x/ast/model/processing/node-id");
|
|
@@ -19,6 +20,8 @@ class CriteriaParseError extends Error {
|
|
|
19
20
|
exports.CriteriaParseError = CriteriaParseError;
|
|
20
21
|
/**
|
|
21
22
|
* Takes a criterion in the form of `line:column` or `line@variable-name` and returns the corresponding node id
|
|
23
|
+
*
|
|
24
|
+
* @see {@link tryResolveSliceCriterionToId} for a version that does not throw an error
|
|
22
25
|
*/
|
|
23
26
|
function slicingCriterionToId(criterion, idMap) {
|
|
24
27
|
let resolved;
|
|
@@ -38,6 +41,23 @@ function slicingCriterionToId(criterion, idMap) {
|
|
|
38
41
|
}
|
|
39
42
|
return resolved;
|
|
40
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Tries to resolve a slicing criterion to an id, but does not throw an error if it fails.
|
|
46
|
+
*
|
|
47
|
+
* @see {@link slicingCriterionToId} for the version that throws an error
|
|
48
|
+
*/
|
|
49
|
+
function tryResolveSliceCriterionToId(criterion, idMap) {
|
|
50
|
+
try {
|
|
51
|
+
return slicingCriterionToId(criterion, idMap);
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
if (e instanceof CriteriaParseError) {
|
|
55
|
+
(0, log_1.expensiveTrace)(static_slicer_1.slicerLogger, () => `could not resolve slicing criterion ${criterion}: ${e.message}`);
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
throw e; // rethrow other errors
|
|
59
|
+
}
|
|
60
|
+
}
|
|
41
61
|
function locationToId(location, dataflowIdMap) {
|
|
42
62
|
let candidate;
|
|
43
63
|
for (const [id, nodeInfo] of dataflowIdMap.entries()) {
|
package/util/version.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.flowrVersion = flowrVersion;
|
|
4
4
|
const semver_1 = require("semver");
|
|
5
5
|
// this is automatically replaced with the current version by release-it
|
|
6
|
-
const version = '2.2.
|
|
6
|
+
const version = '2.2.15';
|
|
7
7
|
function flowrVersion() {
|
|
8
8
|
return new semver_1.SemVer(version);
|
|
9
9
|
}
|