@eagleoutice/flowr 2.2.0 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/flowr.js +2 -1
- package/cli/repl/commands/repl-cfg.js +30 -7
- package/cli/repl/commands/repl-dataflow.js +22 -2
- package/cli/repl/commands/repl-normalize.js +22 -2
- package/cli/repl/commands/repl-parse.js +8 -2
- package/cli/repl/core.js +4 -0
- package/cli/repl/server/connection.js +1 -1
- package/cli/script-core/statistics-helper-core.js +1 -1
- package/config.js +8 -1
- package/dataflow/environments/resolve-by-name.js +5 -4
- package/dataflow/extractor.js +1 -1
- package/dataflow/graph/dataflowgraph-builder.d.ts +11 -10
- package/dataflow/graph/dataflowgraph-builder.js +11 -10
- package/dataflow/graph/edge.d.ts +1 -1
- package/dataflow/graph/edge.js +2 -2
- package/dataflow/graph/vertex.d.ts +6 -6
- package/dataflow/graph/vertex.js +5 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +9 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +2 -2
- package/documentation/doc-util/doc-cfg.js +2 -2
- package/documentation/doc-util/doc-types.js +3 -3
- package/documentation/print-interface-wiki.js +0 -2
- package/documentation/print-query-wiki.js +54 -0
- package/package.json +8 -6
- package/queries/catalog/call-context-query/call-context-query-executor.js +1 -1
- package/queries/catalog/happens-before-query/happens-before-query-executor.d.ts +3 -0
- package/queries/catalog/happens-before-query/happens-before-query-executor.js +36 -0
- package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +71 -0
- package/queries/catalog/happens-before-query/happens-before-query-format.js +27 -0
- package/queries/catalog/resolve-value-query/resolve-value-query-executor.d.ts +4 -0
- package/queries/catalog/resolve-value-query/resolve-value-query-executor.js +34 -0
- package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +72 -0
- package/queries/catalog/resolve-value-query/resolve-value-query-format.js +49 -0
- package/queries/catalog/search-query/search-query-executor.js +0 -4
- package/queries/query.d.ts +119 -1
- package/queries/query.js +5 -1
- package/r-bridge/data/data.d.ts +2 -2
- package/r-bridge/data/data.js +2 -2
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +46 -29
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-types.d.ts +4 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-types.js +3 -0
- package/util/cfg/cfg.d.ts +12 -1
- package/util/cfg/cfg.js +64 -10
- package/util/cfg/happens-before.d.ts +7 -0
- package/util/cfg/happens-before.js +32 -0
- package/util/logic.d.ts +4 -4
- package/util/logic.js +8 -0
- package/util/range.d.ts +21 -0
- package/util/range.js +3 -0
- package/util/version.js +1 -1
|
@@ -312,9 +312,9 @@ function implSnippet(node, program, showName = true, nesting = 0) {
|
|
|
312
312
|
const sep = node.comments ? ' \n' : '\n';
|
|
313
313
|
let text = node.comments?.join('\n') ?? '';
|
|
314
314
|
const code = node.node.getFullText(program.getSourceFile(node.node.getSourceFile().fileName));
|
|
315
|
-
text += `\n<details><summary style="color:gray">Defined at <a href="${getTypePathLink(node)}">${getTypePathLink(node, '.')}</a></summary>\n\n${(0, doc_code_1.codeBlock)('ts', code)}\n\n</details>\n`;
|
|
316
|
-
const init = showName ?
|
|
317
|
-
return ` ${indent}
|
|
315
|
+
text += `\n${indent}<details><summary style="color:gray">Defined at <a href="${getTypePathLink(node)}">${getTypePathLink(node, '.')}</a></summary>\n\n${(0, doc_code_1.codeBlock)('ts', code)}\n\n</details>\n`;
|
|
316
|
+
const init = showName ? `* ${bold}[${node.name}](${getTypePathLink(node)})${bold} ${sep}${indent}` : '';
|
|
317
|
+
return ` ${indent}${showName ? init : ''} ${text.replaceAll('\t', ' ').split(/\n/g).join(`\n${indent} `)}`;
|
|
318
318
|
}
|
|
319
319
|
exports.mermaidHide = ['Leaf', 'Location', 'Namespace', 'Base', 'WithChildren', 'Partial', 'RAccessBase'];
|
|
320
320
|
function printHierarchy({ program, hierarchy, root, collapseFromNesting = 1, initialNesting = 0, maxDepth = 20 }) {
|
|
@@ -175,7 +175,6 @@ ${(0, doc_code_1.codeBlock)('shell', ':query @config')}
|
|
|
175
175
|
The following summarizes the configuration options:
|
|
176
176
|
|
|
177
177
|
- \`ignoreSourceCalls\`: If set to \`true\`, _flowR_ will ignore source calls when analyzing the code, i.e., ignoring the inclusion of other files.
|
|
178
|
-
- \`rPath\`: The path to the R executable. If not set, _flowR_ will try to find the R executable in the system's PATH.
|
|
179
178
|
- \`semantics\`: allows to configure the way _flowR_ handles R, although we currently only support \`semantics/environment/overwriteBuiltIns\`.
|
|
180
179
|
You may use this to overwrite _flowR_'s handling of built-in function and even completely clear the preset definitions shipped with flowR.
|
|
181
180
|
See [Configure BuiltIn Semantics](#configure-builtin-semantics) for more information.
|
|
@@ -191,7 +190,6 @@ So you can configure _flowR_ by adding a file like the following:
|
|
|
191
190
|
|
|
192
191
|
${(0, doc_code_1.codeBlock)('json', JSON.stringify({
|
|
193
192
|
ignoreSourceCalls: true,
|
|
194
|
-
rPath: '/usr/bin/R',
|
|
195
193
|
semantics: {
|
|
196
194
|
environment: {
|
|
197
195
|
overwriteBuiltIns: {
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
const shell_1 = require("../r-bridge/shell");
|
|
4
7
|
const doc_dfg_1 = require("./doc-util/doc-dfg");
|
|
@@ -29,6 +32,8 @@ const config_query_executor_1 = require("../queries/catalog/config-query/config-
|
|
|
29
32
|
const search_query_executor_1 = require("../queries/catalog/search-query/search-query-executor");
|
|
30
33
|
const flowr_search_builder_1 = require("../search/flowr-search-builder");
|
|
31
34
|
const vertex_1 = require("../dataflow/graph/vertex");
|
|
35
|
+
const doc_types_1 = require("./doc-util/doc-types");
|
|
36
|
+
const path_1 = __importDefault(require("path"));
|
|
32
37
|
(0, doc_query_1.registerQueryDocumentation)('call-context', {
|
|
33
38
|
name: 'Call-Context Query',
|
|
34
39
|
type: 'active',
|
|
@@ -194,6 +199,25 @@ ${await (0, doc_query_1.showQuery)(shell, example_query_code_1.exampleQueryCode,
|
|
|
194
199
|
`;
|
|
195
200
|
}
|
|
196
201
|
});
|
|
202
|
+
(0, doc_query_1.registerQueryDocumentation)('resolve-value', {
|
|
203
|
+
name: 'Resolve Value Query',
|
|
204
|
+
type: 'active',
|
|
205
|
+
shortDescription: 'Provides access to flowR\'s value tracking (which is configurable)',
|
|
206
|
+
functionName: search_query_executor_1.executeSearch.name,
|
|
207
|
+
functionFile: '../queries/catalog/resolve-value-query/resolve-value-query-executor.ts',
|
|
208
|
+
buildExplanation: async (shell) => {
|
|
209
|
+
const exampleCode = 'x <- 1\nprint(x)';
|
|
210
|
+
return `
|
|
211
|
+
With this query you can use flowR's value-tracking capabilities to resolve identifiers to all potential values they may have at runtime (if possible). The extend to which flowR traces values (e.g. built-ins vs. constants) can be configured in flowR's Configuration file (see the [Interface](${doc_files_1.FlowrWikiBaseRef}/Interface) wiki page for more information).
|
|
212
|
+
|
|
213
|
+
Using the example code \`${exampleCode}\`, the following query returns all values of 'x' in the code:
|
|
214
|
+
${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
215
|
+
type: 'resolve-value',
|
|
216
|
+
criteria: ['2@x']
|
|
217
|
+
}], { showCode: true })}
|
|
218
|
+
`;
|
|
219
|
+
}
|
|
220
|
+
});
|
|
197
221
|
(0, doc_query_1.registerQueryDocumentation)('search', {
|
|
198
222
|
name: 'Search Query',
|
|
199
223
|
type: 'active',
|
|
@@ -213,6 +237,30 @@ ${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
|
213
237
|
`;
|
|
214
238
|
}
|
|
215
239
|
});
|
|
240
|
+
(0, doc_query_1.registerQueryDocumentation)('happens-before', {
|
|
241
|
+
name: 'Happens-Before Query',
|
|
242
|
+
type: 'active',
|
|
243
|
+
shortDescription: 'Check whether one normalized AST node happens before another in the CFG.',
|
|
244
|
+
functionName: search_query_executor_1.executeSearch.name,
|
|
245
|
+
functionFile: '../queries/catalog/happens-before-query/happens-before-query-executor.ts',
|
|
246
|
+
buildExplanation: async (shell) => {
|
|
247
|
+
const exampleCode = 'x <- 1\ny <- 2';
|
|
248
|
+
return `
|
|
249
|
+
With this query you can analyze the control flow graph:
|
|
250
|
+
|
|
251
|
+
Using the example code:
|
|
252
|
+
|
|
253
|
+
${(0, doc_code_1.codeBlock)('r', exampleCode)}
|
|
254
|
+
|
|
255
|
+
the following query returns that the first assignment happens always before the other:
|
|
256
|
+
${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
257
|
+
type: 'happens-before',
|
|
258
|
+
a: '1@x',
|
|
259
|
+
b: '2@y'
|
|
260
|
+
}], { showCode: true, collapseQuery: false })}
|
|
261
|
+
`;
|
|
262
|
+
}
|
|
263
|
+
});
|
|
216
264
|
(0, doc_query_1.registerQueryDocumentation)('id-map', {
|
|
217
265
|
name: 'Id-Map Query',
|
|
218
266
|
type: 'active',
|
|
@@ -395,6 +443,10 @@ ${await (0, doc_query_1.showQuery)(shell, longerCode, [{
|
|
|
395
443
|
functionName: location_map_query_executor_1.executeLocationMapQuery.name,
|
|
396
444
|
functionFile: '../queries/catalog/location-map-query/location-map-query-executor.ts',
|
|
397
445
|
buildExplanation: async (shell) => {
|
|
446
|
+
const types = (0, doc_types_1.getTypesFromFolderAsMermaid)({
|
|
447
|
+
files: [path_1.default.resolve('./src/util/range.ts')],
|
|
448
|
+
typeName: 'SourceRange'
|
|
449
|
+
});
|
|
398
450
|
const exampleCode = 'x + 1\nx * 2';
|
|
399
451
|
return `
|
|
400
452
|
A query like the ${(0, doc_query_1.linkToQueryOfName)('id-map')} query can return a really big result, especially for larger scripts.
|
|
@@ -410,6 +462,8 @@ ${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
|
410
462
|
type: 'location-map'
|
|
411
463
|
}], { showCode: false, collapseQuery: true })}
|
|
412
464
|
|
|
465
|
+
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]\`.
|
|
466
|
+
|
|
413
467
|
`;
|
|
414
468
|
}
|
|
415
469
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eagleoutice/flowr",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
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": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"stats-helper": "ts-node src/cli/statistics-helper-app.ts",
|
|
22
22
|
"slicer": "ts-node src/cli/slicer-app.ts",
|
|
23
23
|
"benchmark-helper": "ts-node src/cli/benchmark-helper-app.ts",
|
|
24
|
-
"benchmark": "npm run build
|
|
24
|
+
"benchmark": "npm run build-dev && node dist/src/cli/benchmark-app.js",
|
|
25
25
|
"summarizer": "ts-node src/cli/summarizer-app.ts",
|
|
26
26
|
"export-quads": "ts-node src/cli/export-quads-app.ts",
|
|
27
27
|
"capabilities-markdown": "ts-node src/documentation/print-capabilities-markdown.ts",
|
|
@@ -33,9 +33,10 @@
|
|
|
33
33
|
"wiki:linting-and-testing": "ts-node src/documentation/print-linting-and-testing-wiki.ts",
|
|
34
34
|
"wiki:interface": "ts-node src/documentation/print-interface-wiki.ts",
|
|
35
35
|
"build": "tsc --project .",
|
|
36
|
-
"build
|
|
37
|
-
"build:
|
|
38
|
-
"build:copy-wasm
|
|
36
|
+
"build-dev": "npm run build && npm run build:copy-wasm",
|
|
37
|
+
"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",
|
|
38
|
+
"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/",
|
|
39
|
+
"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",
|
|
39
40
|
"lint-local": "npx eslint --version && npx eslint src/ test/ --rule \"no-warning-comments: off\"",
|
|
40
41
|
"lint": "npm run license-compat -- --summary && npx eslint --version && npx eslint src/ test/",
|
|
41
42
|
"license-compat": "license-checker --onlyAllow 'MIT;MIT OR X11;GPLv2;LGPL;GNUGPL;ISC;Apache-2.0;FreeBSD;BSD-2-Clause;clearbsd;ModifiedBSD;BSD-3-Clause;Python-2.0;Unlicense;WTFPL;BlueOak-1.0.0;CC-BY-4.0;CC-BY-3.0;CC0-1.0;0BSD'",
|
|
@@ -166,7 +167,7 @@
|
|
|
166
167
|
"npm run lint",
|
|
167
168
|
"npm run test-full"
|
|
168
169
|
],
|
|
169
|
-
"after:bump": "npm run build
|
|
170
|
+
"after:bump": "npm run build-dev",
|
|
170
171
|
"after:git:release": "echo After git push, before github release",
|
|
171
172
|
"after:release": "echo Successfully released ${name} v${version} to ${repo.repository}."
|
|
172
173
|
},
|
|
@@ -210,6 +211,7 @@
|
|
|
210
211
|
},
|
|
211
212
|
"dependencies": {
|
|
212
213
|
"@xmldom/xmldom": "^0.9.2",
|
|
214
|
+
"clipboardy": "^4.0.0",
|
|
213
215
|
"command-line-args": "^6.0.0",
|
|
214
216
|
"command-line-usage": "^7.0.3",
|
|
215
217
|
"joi": "^17.13.3",
|
|
@@ -167,7 +167,7 @@ function executeCallContextQueries({ dataflow: { graph }, ast }, queries) {
|
|
|
167
167
|
const { promotedQueries, requiresCfg } = promoteQueryCallNames(queries);
|
|
168
168
|
let cfg = undefined;
|
|
169
169
|
if (requiresCfg) {
|
|
170
|
-
cfg = (0, cfg_1.extractCFG)(ast);
|
|
170
|
+
cfg = (0, cfg_1.extractCFG)(ast, graph);
|
|
171
171
|
}
|
|
172
172
|
const queriesWhichWantAliases = promotedQueries.filter(q => q.includeAliases);
|
|
173
173
|
for (const [nodeId, info] of graph.vertices(true)) {
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { BasicQueryData } from '../../base-query-format';
|
|
2
|
+
import type { HappensBeforeQuery, HappensBeforeQueryResult } from './happens-before-query-format';
|
|
3
|
+
export declare function executeHappensBefore({ ast, dataflow }: BasicQueryData, queries: readonly HappensBeforeQuery[]): HappensBeforeQueryResult;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.executeHappensBefore = executeHappensBefore;
|
|
4
|
+
const logic_1 = require("../../../util/logic");
|
|
5
|
+
const log_1 = require("../../../util/log");
|
|
6
|
+
const cfg_1 = require("../../../util/cfg/cfg");
|
|
7
|
+
const happens_before_1 = require("../../../util/cfg/happens-before");
|
|
8
|
+
const parse_1 = require("../../../slicing/criterion/parse");
|
|
9
|
+
function executeHappensBefore({ ast, dataflow }, queries) {
|
|
10
|
+
const start = Date.now();
|
|
11
|
+
const results = {};
|
|
12
|
+
const cfg = (0, cfg_1.extractCFG)(ast, dataflow.graph);
|
|
13
|
+
for (const query of queries) {
|
|
14
|
+
const { a, b } = query;
|
|
15
|
+
const fingerprint = `${a}<${b}`;
|
|
16
|
+
if (fingerprint in results) {
|
|
17
|
+
log_1.log.warn('Duplicate happens-before query', query, 'ignoring');
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
const resolvedA = (0, parse_1.slicingCriterionToId)(a, ast.idMap);
|
|
21
|
+
const resolvedB = (0, parse_1.slicingCriterionToId)(b, ast.idMap);
|
|
22
|
+
results[fingerprint] = (0, happens_before_1.happensBefore)(cfg.graph, resolvedA, resolvedB);
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
log_1.log.error('Error while executing happens-before query', query, e);
|
|
26
|
+
results[fingerprint] = logic_1.Ternary.Maybe;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
'.meta': {
|
|
31
|
+
timing: Date.now() - start
|
|
32
|
+
},
|
|
33
|
+
results
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=happens-before-query-executor.js.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { BaseQueryFormat, BaseQueryResult } from '../../base-query-format';
|
|
2
|
+
import Joi from 'joi';
|
|
3
|
+
import { executeHappensBefore } from './happens-before-query-executor';
|
|
4
|
+
import type { SingleSlicingCriterion } from '../../../slicing/criterion/parse';
|
|
5
|
+
import type { Ternary } from '../../../util/logic';
|
|
6
|
+
export interface HappensBeforeQuery extends BaseQueryFormat {
|
|
7
|
+
readonly type: 'happens-before';
|
|
8
|
+
readonly a: SingleSlicingCriterion;
|
|
9
|
+
readonly b: SingleSlicingCriterion;
|
|
10
|
+
}
|
|
11
|
+
export interface HappensBeforeQueryResult extends BaseQueryResult {
|
|
12
|
+
readonly results: Record<string, Ternary>;
|
|
13
|
+
}
|
|
14
|
+
export declare const HappensBeforeQueryDefinition: {
|
|
15
|
+
readonly executor: typeof executeHappensBefore;
|
|
16
|
+
readonly asciiSummarizer: (formatter: import("../../../util/ansi").OutputFormatter, _processed: import("../../../core/steps/pipeline/pipeline").PipelineOutput<import("../../../core/steps/pipeline/pipeline").Pipeline<{
|
|
17
|
+
readonly name: "parse";
|
|
18
|
+
readonly humanReadableName: "parse with R shell";
|
|
19
|
+
readonly description: "Parse the given R code into an AST";
|
|
20
|
+
readonly processor: (_results: unknown, input: Partial<import("../../../r-bridge/parser").ParseRequiredInput<string>>) => Promise<import("../../../r-bridge/parser").ParseStepOutput<string>>;
|
|
21
|
+
readonly executed: import("../../../core/steps/pipeline-step").PipelineStepStage.OncePerFile;
|
|
22
|
+
readonly printer: {
|
|
23
|
+
readonly 0: typeof import("../../../core/print/print").internalPrinter;
|
|
24
|
+
readonly 2: {
|
|
25
|
+
(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
|
|
26
|
+
(value: any, replacer?: (number | string)[] | null, space?: string | number): string;
|
|
27
|
+
};
|
|
28
|
+
readonly 5: ({ parsed }: import("../../../r-bridge/parser").ParseStepOutput<string>, config: import("../../../util/quads").QuadSerializationConfiguration) => string;
|
|
29
|
+
};
|
|
30
|
+
readonly dependencies: readonly [];
|
|
31
|
+
readonly requiredInput: import("../../../r-bridge/parser").ParseRequiredInput<string>;
|
|
32
|
+
} | {
|
|
33
|
+
readonly name: "normalize";
|
|
34
|
+
readonly humanReadableName: "normalize";
|
|
35
|
+
readonly description: "Normalize the AST to flowR's AST";
|
|
36
|
+
readonly processor: (results: {
|
|
37
|
+
parse?: import("../../../r-bridge/parser").ParseStepOutput<string>;
|
|
38
|
+
}, 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>>;
|
|
39
|
+
readonly executed: import("../../../core/steps/pipeline-step").PipelineStepStage.OncePerFile;
|
|
40
|
+
readonly printer: {
|
|
41
|
+
readonly 0: typeof import("../../../core/print/print").internalPrinter;
|
|
42
|
+
readonly 2: typeof import("../../../core/print/normalize-printer").normalizedAstToJson;
|
|
43
|
+
readonly 5: typeof import("../../../core/print/normalize-printer").normalizedAstToQuads;
|
|
44
|
+
readonly 3: typeof import("../../../core/print/normalize-printer").printNormalizedAstToMermaid;
|
|
45
|
+
readonly 4: typeof import("../../../core/print/normalize-printer").printNormalizedAstToMermaidUrl;
|
|
46
|
+
};
|
|
47
|
+
readonly dependencies: readonly ["parse"];
|
|
48
|
+
readonly requiredInput: import("../../../core/steps/all/core/10-normalize").NormalizeRequiredInput;
|
|
49
|
+
} | {
|
|
50
|
+
readonly humanReadableName: "dataflow";
|
|
51
|
+
readonly processor: (results: {
|
|
52
|
+
normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
53
|
+
}, input: {
|
|
54
|
+
request?: import("../../../r-bridge/retriever").RParseRequests;
|
|
55
|
+
parser?: import("../../../r-bridge/parser").Parser<import("../../../r-bridge/parser").KnownParserType>;
|
|
56
|
+
}) => import("../../../dataflow/info").DataflowInformation;
|
|
57
|
+
readonly requiredInput: {};
|
|
58
|
+
readonly name: "dataflow";
|
|
59
|
+
readonly description: "Construct the dataflow graph";
|
|
60
|
+
readonly executed: import("../../../core/steps/pipeline-step").PipelineStepStage.OncePerFile;
|
|
61
|
+
readonly printer: {
|
|
62
|
+
readonly 0: typeof import("../../../core/print/print").internalPrinter;
|
|
63
|
+
readonly 2: typeof import("../../../core/print/dataflow-printer").dataflowGraphToJson;
|
|
64
|
+
readonly 5: typeof import("../../../core/print/dataflow-printer").dataflowGraphToQuads;
|
|
65
|
+
readonly 3: typeof import("../../../core/print/dataflow-printer").dataflowGraphToMermaid;
|
|
66
|
+
readonly 4: typeof import("../../../core/print/dataflow-printer").dataflowGraphToMermaidUrl;
|
|
67
|
+
};
|
|
68
|
+
readonly dependencies: readonly ["normalize"];
|
|
69
|
+
}>>, queryResults: BaseQueryResult, result: string[]) => true;
|
|
70
|
+
readonly schema: Joi.ObjectSchema<any>;
|
|
71
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
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.HappensBeforeQueryDefinition = void 0;
|
|
7
|
+
const ansi_1 = require("../../../util/ansi");
|
|
8
|
+
const time_1 = require("../../../util/time");
|
|
9
|
+
const joi_1 = __importDefault(require("joi"));
|
|
10
|
+
const happens_before_query_executor_1 = require("./happens-before-query-executor");
|
|
11
|
+
exports.HappensBeforeQueryDefinition = {
|
|
12
|
+
executor: happens_before_query_executor_1.executeHappensBefore,
|
|
13
|
+
asciiSummarizer: (formatter, _processed, queryResults, result) => {
|
|
14
|
+
const out = queryResults;
|
|
15
|
+
result.push(`Query: ${(0, ansi_1.bold)('happens-before', formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
|
|
16
|
+
for (const [key, value] of Object.entries(out.results)) {
|
|
17
|
+
result.push(` ╰ ${key}: ${value}`);
|
|
18
|
+
}
|
|
19
|
+
return true;
|
|
20
|
+
},
|
|
21
|
+
schema: joi_1.default.object({
|
|
22
|
+
type: joi_1.default.string().valid('happens-before').required().description('The type of the query.'),
|
|
23
|
+
a: joi_1.default.string().required().description('The first slicing criterion.'),
|
|
24
|
+
b: joi_1.default.string().required().description('The second slicing criterion.')
|
|
25
|
+
}).description('The id map query retrieves the id map from the normalized AST.')
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=happens-before-query-format.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ResolveValueQuery, ResolveValueQueryResult } from './resolve-value-query-format';
|
|
2
|
+
import type { BasicQueryData } from '../../base-query-format';
|
|
3
|
+
export declare function fingerPrintOfQuery(query: ResolveValueQuery): string;
|
|
4
|
+
export declare function executeResolveValueQuery({ dataflow: { graph, environment }, ast }: BasicQueryData, queries: readonly ResolveValueQuery[]): ResolveValueQueryResult;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fingerPrintOfQuery = fingerPrintOfQuery;
|
|
4
|
+
exports.executeResolveValueQuery = executeResolveValueQuery;
|
|
5
|
+
const log_1 = require("../../../util/log");
|
|
6
|
+
const parse_1 = require("../../../slicing/criterion/parse");
|
|
7
|
+
const resolve_by_name_1 = require("../../../dataflow/environments/resolve-by-name");
|
|
8
|
+
const node_id_1 = require("../../../r-bridge/lang-4.x/ast/model/processing/node-id");
|
|
9
|
+
function fingerPrintOfQuery(query) {
|
|
10
|
+
return JSON.stringify(query);
|
|
11
|
+
}
|
|
12
|
+
function executeResolveValueQuery({ dataflow: { graph, environment }, ast }, queries) {
|
|
13
|
+
const start = Date.now();
|
|
14
|
+
const results = {};
|
|
15
|
+
for (const query of queries) {
|
|
16
|
+
const key = fingerPrintOfQuery(query);
|
|
17
|
+
if (results[key]) {
|
|
18
|
+
log_1.log.warn(`Duplicate Key for resolve-value-query: ${key}, skipping...`);
|
|
19
|
+
}
|
|
20
|
+
const values = query.criteria
|
|
21
|
+
.map(criteria => (0, node_id_1.recoverName)((0, parse_1.slicingCriterionToId)(criteria, ast.idMap), ast.idMap))
|
|
22
|
+
.flatMap(ident => (0, resolve_by_name_1.resolveToValues)(ident, environment, graph));
|
|
23
|
+
results[key] = {
|
|
24
|
+
values: [...new Set(values)]
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
'.meta': {
|
|
29
|
+
timing: Date.now() - start
|
|
30
|
+
},
|
|
31
|
+
results
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=resolve-value-query-executor.js.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { BaseQueryFormat, BaseQueryResult } from '../../base-query-format';
|
|
2
|
+
import type { SlicingCriteria } from '../../../slicing/criterion/parse';
|
|
3
|
+
import Joi from 'joi';
|
|
4
|
+
import { executeResolveValueQuery } from './resolve-value-query-executor';
|
|
5
|
+
export interface ResolveValueQuery extends BaseQueryFormat {
|
|
6
|
+
readonly type: 'resolve-value';
|
|
7
|
+
/** The slicing criteria to use */
|
|
8
|
+
readonly criteria: SlicingCriteria;
|
|
9
|
+
}
|
|
10
|
+
export interface ResolveValueQueryResult extends BaseQueryResult {
|
|
11
|
+
results: Record<string, {
|
|
12
|
+
values: unknown[];
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
15
|
+
export declare const ResolveValueQueryDefinition: {
|
|
16
|
+
readonly executor: typeof executeResolveValueQuery;
|
|
17
|
+
readonly asciiSummarizer: (formatter: import("../../../util/ansi").OutputFormatter, _processed: import("../../../core/steps/pipeline/pipeline").PipelineOutput<import("../../../core/steps/pipeline/pipeline").Pipeline<{
|
|
18
|
+
readonly name: "parse";
|
|
19
|
+
readonly humanReadableName: "parse with R shell";
|
|
20
|
+
readonly description: "Parse the given R code into an AST";
|
|
21
|
+
readonly processor: (_results: unknown, input: Partial<import("../../../r-bridge/parser").ParseRequiredInput<string>>) => Promise<import("../../../r-bridge/parser").ParseStepOutput<string>>;
|
|
22
|
+
readonly executed: import("../../../core/steps/pipeline-step").PipelineStepStage.OncePerFile;
|
|
23
|
+
readonly printer: {
|
|
24
|
+
readonly 0: typeof import("../../../core/print/print").internalPrinter;
|
|
25
|
+
readonly 2: {
|
|
26
|
+
(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
|
|
27
|
+
(value: any, replacer?: (number | string)[] | null, space?: string | number): string;
|
|
28
|
+
};
|
|
29
|
+
readonly 5: ({ parsed }: import("../../../r-bridge/parser").ParseStepOutput<string>, config: import("../../../util/quads").QuadSerializationConfiguration) => string;
|
|
30
|
+
};
|
|
31
|
+
readonly dependencies: readonly [];
|
|
32
|
+
readonly requiredInput: import("../../../r-bridge/parser").ParseRequiredInput<string>;
|
|
33
|
+
} | {
|
|
34
|
+
readonly name: "normalize";
|
|
35
|
+
readonly humanReadableName: "normalize";
|
|
36
|
+
readonly description: "Normalize the AST to flowR's AST";
|
|
37
|
+
readonly processor: (results: {
|
|
38
|
+
parse?: import("../../../r-bridge/parser").ParseStepOutput<string>;
|
|
39
|
+
}, 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>>;
|
|
40
|
+
readonly executed: import("../../../core/steps/pipeline-step").PipelineStepStage.OncePerFile;
|
|
41
|
+
readonly printer: {
|
|
42
|
+
readonly 0: typeof import("../../../core/print/print").internalPrinter;
|
|
43
|
+
readonly 2: typeof import("../../../core/print/normalize-printer").normalizedAstToJson;
|
|
44
|
+
readonly 5: typeof import("../../../core/print/normalize-printer").normalizedAstToQuads;
|
|
45
|
+
readonly 3: typeof import("../../../core/print/normalize-printer").printNormalizedAstToMermaid;
|
|
46
|
+
readonly 4: typeof import("../../../core/print/normalize-printer").printNormalizedAstToMermaidUrl;
|
|
47
|
+
};
|
|
48
|
+
readonly dependencies: readonly ["parse"];
|
|
49
|
+
readonly requiredInput: import("../../../core/steps/all/core/10-normalize").NormalizeRequiredInput;
|
|
50
|
+
} | {
|
|
51
|
+
readonly humanReadableName: "dataflow";
|
|
52
|
+
readonly processor: (results: {
|
|
53
|
+
normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
54
|
+
}, input: {
|
|
55
|
+
request?: import("../../../r-bridge/retriever").RParseRequests;
|
|
56
|
+
parser?: import("../../../r-bridge/parser").Parser<import("../../../r-bridge/parser").KnownParserType>;
|
|
57
|
+
}) => import("../../../dataflow/info").DataflowInformation;
|
|
58
|
+
readonly requiredInput: {};
|
|
59
|
+
readonly name: "dataflow";
|
|
60
|
+
readonly description: "Construct the dataflow graph";
|
|
61
|
+
readonly executed: import("../../../core/steps/pipeline-step").PipelineStepStage.OncePerFile;
|
|
62
|
+
readonly printer: {
|
|
63
|
+
readonly 0: typeof import("../../../core/print/print").internalPrinter;
|
|
64
|
+
readonly 2: typeof import("../../../core/print/dataflow-printer").dataflowGraphToJson;
|
|
65
|
+
readonly 5: typeof import("../../../core/print/dataflow-printer").dataflowGraphToQuads;
|
|
66
|
+
readonly 3: typeof import("../../../core/print/dataflow-printer").dataflowGraphToMermaid;
|
|
67
|
+
readonly 4: typeof import("../../../core/print/dataflow-printer").dataflowGraphToMermaidUrl;
|
|
68
|
+
};
|
|
69
|
+
readonly dependencies: readonly ["normalize"];
|
|
70
|
+
}>>, queryResults: BaseQueryResult, result: string[]) => true;
|
|
71
|
+
readonly schema: Joi.ObjectSchema<any>;
|
|
72
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
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.ResolveValueQueryDefinition = void 0;
|
|
7
|
+
const ansi_1 = require("../../../util/ansi");
|
|
8
|
+
const time_1 = require("../../../util/time");
|
|
9
|
+
const joi_1 = __importDefault(require("joi"));
|
|
10
|
+
const resolve_value_query_executor_1 = require("./resolve-value-query-executor");
|
|
11
|
+
function rValueToAscii(value) {
|
|
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
|
+
}
|
|
32
|
+
exports.ResolveValueQueryDefinition = {
|
|
33
|
+
executor: resolve_value_query_executor_1.executeResolveValueQuery,
|
|
34
|
+
asciiSummarizer: (formatter, _processed, queryResults, result) => {
|
|
35
|
+
const out = queryResults;
|
|
36
|
+
result.push(`Query: ${(0, ansi_1.bold)('resolve-value', formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
|
|
37
|
+
for (const [fingerprint, obj] of Object.entries(out.results)) {
|
|
38
|
+
const { criteria } = JSON.parse(fingerprint);
|
|
39
|
+
result.push(` ╰ Values for {${criteria.join(', ')}}`);
|
|
40
|
+
result.push(` ╰ ${obj.values.map(v => rValueToAscii(v)).join(', ')}`);
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
},
|
|
44
|
+
schema: joi_1.default.object({
|
|
45
|
+
type: joi_1.default.string().valid('resolve-value').required().description('The type of the query.'),
|
|
46
|
+
criteria: joi_1.default.array().items(joi_1.default.string()).min(1).required().description('The slicing criteria to use.'),
|
|
47
|
+
}).description('Resolve Value query used to get definitions of an identifier')
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=resolve-value-query-format.js.map
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.executeSearch = executeSearch;
|
|
4
|
-
const log_1 = require("../../../util/log");
|
|
5
4
|
const flowr_search_executor_1 = require("../../../search/flowr-search-executor");
|
|
6
5
|
function executeSearch({ ast, dataflow }, queries) {
|
|
7
6
|
const start = Date.now();
|
|
8
|
-
if (queries.length !== 1) {
|
|
9
|
-
log_1.log.warn('Id-Map query expects only up to one query, but got', queries.length);
|
|
10
|
-
}
|
|
11
7
|
const results = [];
|
|
12
8
|
for (const query of queries) {
|
|
13
9
|
const { search } = query;
|