@eagleoutice/flowr 2.1.3 → 2.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/benchmark/slicer.js +1 -1
- package/cli/repl/commands/repl-parse.js +1 -1
- package/cli/repl/commands/repl-query.js +4 -5
- package/cli/repl/server/connection.js +6 -1
- package/cli/repl/server/messages/message-query.js +2 -2
- package/cli/repl/server/net.js +1 -1
- package/cli/repl/server/send.js +3 -6
- package/cli/repl/server/server.d.ts +2 -2
- package/cli/repl/server/server.js +1 -1
- package/config.js +1 -1
- package/core/pipeline-executor.js +2 -1
- package/core/steps/all/core/00-parse.d.ts +11 -4
- package/core/steps/all/core/00-parse.js +5 -5
- package/core/steps/all/core/10-normalize.d.ts +2 -1
- package/core/steps/all/core/20-dataflow.d.ts +2 -2
- package/core/steps/all/core/20-dataflow.js +2 -2
- package/core/steps/pipeline/default-pipelines.d.ts +41 -23
- package/core/steps/pipeline/pipeline.d.ts +15 -3
- package/core/steps/pipeline/pipeline.js +2 -2
- package/dataflow/environments/built-in.d.ts +8 -6
- package/dataflow/environments/built-in.js +6 -1
- package/dataflow/environments/default-builtin-config.js +21 -5
- package/dataflow/environments/environment.d.ts +1 -0
- package/dataflow/environments/environment.js +5 -5
- package/dataflow/extractor.js +23 -0
- package/dataflow/graph/dataflowgraph-builder.d.ts +2 -0
- package/dataflow/graph/dataflowgraph-builder.js +9 -0
- package/dataflow/graph/diff.js +1 -1
- package/dataflow/graph/graph.d.ts +7 -2
- package/dataflow/graph/graph.js +10 -2
- package/dataflow/internal/process/functions/call/argument/unpack-argument.d.ts +1 -1
- package/dataflow/internal/process/functions/call/argument/unpack-argument.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +13 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +1 -1
- package/dataflow/internal/process/functions/call/named-call-handling.js +1 -1
- package/dataflow/processor.d.ts +3 -3
- package/documentation/data/server/doc-data-server-messages.js +8 -14
- package/documentation/doc-util/doc-cli-option.js +4 -4
- package/documentation/doc-util/doc-query.d.ts +4 -6
- package/documentation/doc-util/doc-query.js +16 -156
- package/documentation/doc-util/doc-repl.js +2 -2
- package/documentation/print-dataflow-graph-wiki.js +2 -1
- package/documentation/print-interface-wiki.js +8 -3
- package/documentation/print-query-wiki.js +107 -16
- package/package.json +1 -1
- package/queries/base-query-format.d.ts +6 -0
- package/queries/catalog/call-context-query/call-context-query-executor.d.ts +1 -1
- package/queries/catalog/call-context-query/call-context-query-executor.js +26 -80
- package/queries/catalog/call-context-query/call-context-query-format.d.ts +14 -13
- package/queries/catalog/call-context-query/call-context-query-format.js +32 -14
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +17 -0
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +99 -0
- package/queries/catalog/cluster-query/cluster-query-executor.d.ts +1 -1
- package/queries/catalog/cluster-query/cluster-query-format.d.ts +59 -0
- package/queries/catalog/cluster-query/cluster-query-format.js +29 -0
- package/queries/catalog/dataflow-query/dataflow-query-executor.d.ts +1 -1
- package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +59 -0
- package/queries/catalog/dataflow-query/dataflow-query-format.js +21 -0
- package/queries/catalog/dependencies-query/dependencies-query-executor.d.ts +3 -0
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +144 -0
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +102 -0
- package/queries/catalog/dependencies-query/dependencies-query-format.js +187 -0
- package/queries/catalog/id-map-query/id-map-query-executor.d.ts +1 -1
- package/queries/catalog/id-map-query/id-map-query-format.d.ts +59 -0
- package/queries/catalog/id-map-query/id-map-query-format.js +21 -0
- package/queries/catalog/lineage-query/lineage-query-executor.d.ts +1 -1
- package/queries/catalog/lineage-query/lineage-query-format.d.ts +59 -0
- package/queries/catalog/lineage-query/lineage-query-format.js +24 -0
- package/queries/catalog/location-map-query/location-map-query-executor.d.ts +3 -0
- package/queries/catalog/location-map-query/location-map-query-executor.js +21 -0
- package/queries/catalog/location-map-query/location-map-query-format.d.ts +17 -0
- package/queries/catalog/location-map-query/location-map-query-format.js +24 -0
- package/queries/catalog/normalized-ast-query/normalized-ast-query-executor.d.ts +1 -1
- package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +59 -0
- package/queries/catalog/normalized-ast-query/normalized-ast-query-format.js +21 -0
- package/queries/catalog/static-slice-query/static-slice-query-executor.d.ts +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-executor.js +8 -3
- package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +59 -0
- package/queries/catalog/static-slice-query/static-slice-query-format.js +40 -0
- package/queries/query-print.d.ts +8 -0
- package/queries/query-print.js +94 -0
- package/queries/query.d.ts +431 -26
- package/queries/query.js +36 -18
- package/r-bridge/lang-4.x/ast/parser/json/parser.d.ts +2 -1
- package/r-bridge/lang-4.x/ast/parser/json/parser.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-argument.js +2 -1
- package/r-bridge/retriever.js +1 -1
- package/r-bridge/shell-executor.js +1 -1
- package/r-bridge/shell.d.ts +1 -2
- package/r-bridge/shell.js +22 -18
- package/slicing/static/static-slicer.js +3 -1
- package/statistics/features/supported/used-functions/used-functions.js +1 -1
- package/{documentation/doc-util/doc-hover-over.js → util/html-hover-over.js} +1 -1
- package/util/json.d.ts +2 -1
- package/util/json.js +101 -3
- package/util/objects.d.ts +2 -1
- package/util/objects.js +3 -0
- package/util/version.js +1 -1
- package/queries/query-schema.d.ts +0 -13
- package/queries/query-schema.js +0 -54
- /package/{documentation/doc-util/doc-hover-over.d.ts → util/html-hover-over.d.ts} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RegisteredQueries = void 0;
|
|
4
|
-
exports.asciiSummaryOfQueryResult = asciiSummaryOfQueryResult;
|
|
5
4
|
exports.showQuery = showQuery;
|
|
6
5
|
exports.registerQueryDocumentation = registerQueryDocumentation;
|
|
6
|
+
exports.linkToQueryOfName = linkToQueryOfName;
|
|
7
7
|
exports.tocForQueryType = tocForQueryType;
|
|
8
8
|
exports.explainQueries = explainQueries;
|
|
9
9
|
const query_1 = require("../../queries/query");
|
|
@@ -16,154 +16,8 @@ const doc_files_1 = require("./doc-files");
|
|
|
16
16
|
const doc_dfg_1 = require("./doc-dfg");
|
|
17
17
|
const doc_code_1 = require("./doc-code");
|
|
18
18
|
const time_1 = require("../../util/time");
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
const ast_1 = require("../../util/mermaid/ast");
|
|
22
|
-
const doc_hover_over_1 = require("./doc-hover-over");
|
|
23
|
-
function nodeString(id, formatter, processed) {
|
|
24
|
-
if (id === built_in_1.BuiltIn) {
|
|
25
|
-
return (0, ansi_1.italic)('built-in', formatter);
|
|
26
|
-
}
|
|
27
|
-
const node = processed.normalize.idMap.get(id);
|
|
28
|
-
if (node === undefined) {
|
|
29
|
-
return `UNKNOWN: ${id}`;
|
|
30
|
-
}
|
|
31
|
-
return `${(0, ansi_1.italic)('`' + (node.lexeme ?? node.info.fullLexeme ?? 'UNKNOWN') + '`', formatter)} (L.${node.location?.[0]})`;
|
|
32
|
-
}
|
|
33
|
-
function asciiCallContextSubHit(formatter, results, processed) {
|
|
34
|
-
const result = [];
|
|
35
|
-
for (const { id, calls = [], linkedIds = [], aliasRoots = [] } of results) {
|
|
36
|
-
const node = processed.normalize.idMap.get(id);
|
|
37
|
-
if (node === undefined) {
|
|
38
|
-
result.push(` ${(0, ansi_1.bold)('UNKNOWN: ' + JSON.stringify({ calls, linkedIds }))}`);
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
let line = nodeString(id, formatter, processed);
|
|
42
|
-
if (calls.length > 0) {
|
|
43
|
-
line += ` with ${calls.length} call${calls.length > 1 ? 's' : ''} (${calls.map(c => nodeString(c, formatter, processed)).join(', ')})`;
|
|
44
|
-
}
|
|
45
|
-
if (linkedIds.length > 0) {
|
|
46
|
-
line += ` with ${linkedIds.length} link${linkedIds.length > 1 ? 's' : ''} (${linkedIds.map(c => nodeString(c, formatter, processed)).join(', ')})`;
|
|
47
|
-
}
|
|
48
|
-
if (aliasRoots.length > 0) {
|
|
49
|
-
line += ` with ${aliasRoots.length} alias root${aliasRoots.length > 1 ? 's' : ''} (${aliasRoots.map(c => nodeString(c, formatter, processed)).join(', ')})`;
|
|
50
|
-
}
|
|
51
|
-
result.push(line);
|
|
52
|
-
}
|
|
53
|
-
return result.join(', ');
|
|
54
|
-
}
|
|
55
|
-
function asciiCallContext(formatter, results, processed) {
|
|
56
|
-
/* traverse over 'kinds' and within them 'subkinds' */
|
|
57
|
-
const result = [];
|
|
58
|
-
for (const [kind, { subkinds }] of Object.entries(results['kinds'])) {
|
|
59
|
-
result.push(` ╰ ${(0, ansi_1.bold)(kind, formatter)}`);
|
|
60
|
-
for (const [subkind, values] of Object.entries(subkinds)) {
|
|
61
|
-
result.push(` ╰ ${(0, ansi_1.bold)(subkind, formatter)}: ${asciiCallContextSubHit(formatter, values, processed)}`);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return result.join('\n');
|
|
65
|
-
}
|
|
66
|
-
function summarizeIdsIfTooLong(ids) {
|
|
67
|
-
const naive = ids.join(', ');
|
|
68
|
-
if (naive.length <= 20) {
|
|
69
|
-
return naive;
|
|
70
|
-
}
|
|
71
|
-
let acc = '';
|
|
72
|
-
let i = 0;
|
|
73
|
-
while (acc.length <= 20) {
|
|
74
|
-
acc += ids[i++] + ', ';
|
|
75
|
-
}
|
|
76
|
-
if (i < ids.length) {
|
|
77
|
-
acc += '... (see JSON below)';
|
|
78
|
-
}
|
|
79
|
-
return (0, doc_hover_over_1.textWithTooltip)(acc, JSON.stringify(ids));
|
|
80
|
-
}
|
|
81
|
-
function asciiSummaryOfQueryResult(formatter, totalInMs, results, processed) {
|
|
82
|
-
const result = [];
|
|
83
|
-
for (const [query, queryResults] of Object.entries(results)) {
|
|
84
|
-
if (query === '.meta') {
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
if (query === 'call-context') {
|
|
88
|
-
const out = queryResults;
|
|
89
|
-
result.push(`Query: ${(0, ansi_1.bold)(query, formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
|
|
90
|
-
result.push(asciiCallContext(formatter, out, processed));
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
else if (query === 'dataflow') {
|
|
94
|
-
const out = queryResults;
|
|
95
|
-
result.push(`Query: ${(0, ansi_1.bold)(query, formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
|
|
96
|
-
result.push(` ╰ [Dataflow Graph](${(0, dfg_1.graphToMermaidUrl)(out.graph)})`);
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
else if (query === 'id-map') {
|
|
100
|
-
const out = queryResults;
|
|
101
|
-
result.push(`Query: ${(0, ansi_1.bold)(query, formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
|
|
102
|
-
result.push(` ╰ Id List: {${summarizeIdsIfTooLong([...out.idMap.keys()])}}`);
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
else if (query === 'normalized-ast') {
|
|
106
|
-
const out = queryResults;
|
|
107
|
-
result.push(`Query: ${(0, ansi_1.bold)(query, formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
|
|
108
|
-
result.push(` ╰ [Normalized AST](${(0, ast_1.normalizedAstToMermaidUrl)(out.normalized.ast)})`);
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
else if (query === 'static-slice') {
|
|
112
|
-
const out = queryResults;
|
|
113
|
-
result.push(`Query: ${(0, ansi_1.bold)(query, formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
|
|
114
|
-
for (const [fingerprint, obj] of Object.entries(out.results)) {
|
|
115
|
-
const { criteria, noMagicComments, noReconstruction } = JSON.parse(fingerprint);
|
|
116
|
-
const addons = [];
|
|
117
|
-
if (noReconstruction) {
|
|
118
|
-
addons.push('no reconstruction');
|
|
119
|
-
}
|
|
120
|
-
if (noMagicComments) {
|
|
121
|
-
addons.push('no magic comments');
|
|
122
|
-
}
|
|
123
|
-
result.push(` ╰ Slice for {${criteria.join(', ')}} ${addons.join(', ')}`);
|
|
124
|
-
if ('reconstruct' in obj) {
|
|
125
|
-
result.push(' ╰ Code (newline as <code>\n</code>): <code>' + obj.reconstruct.code.split('\n').join('\\n') + '</code>');
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
result.push(` ╰ Id List: {${summarizeIdsIfTooLong([...obj.slice.result])}}`);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
|
-
else if (query === 'dataflow-cluster') {
|
|
134
|
-
const out = queryResults;
|
|
135
|
-
result.push(`Query: ${(0, ansi_1.bold)(query, formatter)} (${out['.meta'].timing.toFixed(0)}ms)`);
|
|
136
|
-
result.push(` ╰ Found ${out.clusters.length} cluster${out.clusters.length === 1 ? '' : 's'}`);
|
|
137
|
-
for (const cluster of out.clusters) {
|
|
138
|
-
const unknownSideEffects = cluster.hasUnknownSideEffects ? '(has unknown side effect)' : '';
|
|
139
|
-
result.push(` ╰ ${unknownSideEffects} {${summarizeIdsIfTooLong(cluster.members)}} ([marked](${(0, dfg_1.graphToMermaidUrl)(processed.dataflow.graph, false, new Set(cluster.members))}))`);
|
|
140
|
-
}
|
|
141
|
-
continue;
|
|
142
|
-
}
|
|
143
|
-
else if (query === 'lineage') {
|
|
144
|
-
const out = queryResults;
|
|
145
|
-
result.push(`Query: ${(0, ansi_1.bold)(query, formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
|
|
146
|
-
for (const [criteria, lineage] of Object.entries(out.lineages)) {
|
|
147
|
-
result.push(` ╰ ${criteria}: {${summarizeIdsIfTooLong([...lineage])}}`);
|
|
148
|
-
}
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
result.push(`Query: ${(0, ansi_1.bold)(query, formatter)}`);
|
|
152
|
-
let timing = -1;
|
|
153
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
154
|
-
for (const [key, value] of Object.entries(queryResults)) {
|
|
155
|
-
if (key === '.meta') {
|
|
156
|
-
timing = value.timing;
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
result.push(` ╰ ${key}: ${JSON.stringify(value)}`);
|
|
160
|
-
}
|
|
161
|
-
result.push(` - Took ${(0, time_1.printAsMs)(timing, 0)}`);
|
|
162
|
-
}
|
|
163
|
-
result.push((0, ansi_1.italic)(`All queries together required ≈${(0, time_1.printAsMs)(results['.meta'].timing, 0)} (1ms accuracy, total ${(0, time_1.printAsMs)(totalInMs, 0)})`, formatter));
|
|
164
|
-
return formatter.format(result.join('\n'));
|
|
165
|
-
}
|
|
166
|
-
async function showQuery(shell, code, queries, { showCode, collapseResult } = {}) {
|
|
19
|
+
const query_print_1 = require("../../queries/query-print");
|
|
20
|
+
async function showQuery(shell, code, queries, { showCode, collapseResult, collapseQuery } = {}) {
|
|
167
21
|
const now = performance.now();
|
|
168
22
|
const analysis = await new pipeline_executor_1.PipelineExecutor(default_pipelines_1.DEFAULT_DATAFLOW_PIPELINE, {
|
|
169
23
|
shell,
|
|
@@ -174,17 +28,16 @@ async function showQuery(shell, code, queries, { showCode, collapseResult } = {}
|
|
|
174
28
|
const metaInfo = `
|
|
175
29
|
The analysis required _${(0, time_1.printAsMs)(duration)}_ (including parsing and normalization and the query) within the generation environment.
|
|
176
30
|
`.trim();
|
|
31
|
+
const str = JSON.stringify(queries, json_1.jsonReplacer, collapseQuery ? ' ' : 2);
|
|
177
32
|
return `
|
|
178
33
|
|
|
179
|
-
|
|
180
|
-
${JSON.stringify(queries, json_1.jsonReplacer, 2)}
|
|
181
|
-
\`\`\`
|
|
34
|
+
${(0, doc_code_1.codeBlock)('json', collapseQuery ? str.split('\n').join(' ').replace(/([{[])\s{2,}/g, '$1 ').replace(/\s{2,}([\]}])/g, ' $1') : str)}
|
|
182
35
|
|
|
183
36
|
${collapseResult ? ' <details> <summary style="color:gray">Show Results</summary>' : ''}
|
|
184
37
|
|
|
185
38
|
_Results (prettified and summarized):_
|
|
186
39
|
|
|
187
|
-
${asciiSummaryOfQueryResult(ansi_1.markdownFormatter, duration, results, analysis)}
|
|
40
|
+
${(0, query_print_1.asciiSummaryOfQueryResult)(ansi_1.markdownFormatter, duration, results, analysis)}
|
|
188
41
|
|
|
189
42
|
<details> <summary style="color:gray">Show Detailed Results as Json</summary>
|
|
190
43
|
|
|
@@ -223,6 +76,13 @@ function registerQueryDocumentation(query, doc) {
|
|
|
223
76
|
function linkify(name) {
|
|
224
77
|
return name.toLowerCase().replace(/ /g, '-');
|
|
225
78
|
}
|
|
79
|
+
function linkToQueryOfName(id) {
|
|
80
|
+
const query = exports.RegisteredQueries.active.get(id) ?? exports.RegisteredQueries.virtual.get(id);
|
|
81
|
+
if (!query) {
|
|
82
|
+
throw new Error(`Query ${id} not found`);
|
|
83
|
+
}
|
|
84
|
+
return `[${query.name}](#${linkify(query.name)})`;
|
|
85
|
+
}
|
|
226
86
|
function tocForQueryType(type) {
|
|
227
87
|
const queries = [...exports.RegisteredQueries[type].entries()].sort(([, { name: a }], [, { name: b }]) => a.localeCompare(b));
|
|
228
88
|
const result = [];
|
|
@@ -248,11 +108,11 @@ Responsible for the execution of the ${name} query is \`${functionName}\` in ${(
|
|
|
248
108
|
`;
|
|
249
109
|
}
|
|
250
110
|
async function explainQueries(shell, type) {
|
|
251
|
-
const queries = exports.RegisteredQueries[type];
|
|
111
|
+
const queries = [...exports.RegisteredQueries[type].entries()].sort(([, { name: a }], [, { name: b }]) => a.localeCompare(b));
|
|
252
112
|
const result = [];
|
|
253
|
-
for (const doc of queries
|
|
113
|
+
for (const [, doc] of queries) {
|
|
254
114
|
result.push(await explainQuery(shell, doc));
|
|
255
115
|
}
|
|
256
|
-
return result.join('\n\n
|
|
116
|
+
return result.join(`\n${'-'.repeat(5)}\n\n`);
|
|
257
117
|
}
|
|
258
118
|
//# sourceMappingURL=doc-query.js.map
|
|
@@ -4,7 +4,7 @@ exports.printReplHelpAsMarkdownTable = printReplHelpAsMarkdownTable;
|
|
|
4
4
|
exports.documentReplSession = documentReplSession;
|
|
5
5
|
const repl_commands_1 = require("../../cli/repl/commands/repl-commands");
|
|
6
6
|
const doc_cli_option_1 = require("./doc-cli-option");
|
|
7
|
-
const
|
|
7
|
+
const html_hover_over_1 = require("../../util/html-hover-over");
|
|
8
8
|
const core_1 = require("../../cli/repl/core");
|
|
9
9
|
const ansi_1 = require("../../util/ansi");
|
|
10
10
|
const doc_docker_1 = require("./doc-docker");
|
|
@@ -19,7 +19,7 @@ function printHelpForScript(script, starredVersion) {
|
|
|
19
19
|
return base;
|
|
20
20
|
}
|
|
21
21
|
const aliases = script[1].aliases;
|
|
22
|
-
return `${base} (alias${aliases.length > 1 ? 'es' : ''}: ${aliases.map(a => '**:' + (0,
|
|
22
|
+
return `${base} (alias${aliases.length > 1 ? 'es' : ''}: ${aliases.map(a => '**:' + (0, html_hover_over_1.textWithTooltip)(a, `Alias of ':${script[0]}'. ${script[1].description}`) + '**').join(', ')}) |`;
|
|
23
23
|
}
|
|
24
24
|
function printReplHelpAsMarkdownTable() {
|
|
25
25
|
const scriptHelp = [];
|
|
@@ -807,7 +807,8 @@ ${(0, doc_types_1.printHierarchy)({ program: vertexType.program, hierarchy: vert
|
|
|
807
807
|
Let's start by looking at the properties of the dataflow information object: ${Object.keys(result.dataflow).map(k => `\`${k}\``).join(', ')}.
|
|
808
808
|
|
|
809
809
|
${(() => {
|
|
810
|
-
|
|
810
|
+
/* this includes the meta field for timing */
|
|
811
|
+
(0, assert_1.guard)(Object.keys(result.dataflow).length === 8, () => 'Update Dataflow Documentation!');
|
|
811
812
|
return '';
|
|
812
813
|
})()}
|
|
813
814
|
|
|
@@ -18,6 +18,7 @@ const ansi_1 = require("../util/ansi");
|
|
|
18
18
|
const flowr_main_options_1 = require("../cli/flowr-main-options");
|
|
19
19
|
const doc_issue_1 = require("./doc-util/doc-issue");
|
|
20
20
|
const pipeline_executor_1 = require("../core/pipeline-executor");
|
|
21
|
+
const doc_structure_1 = require("./doc-util/doc-structure");
|
|
21
22
|
async function explainServer(shell) {
|
|
22
23
|
(0, doc_data_server_messages_1.documentAllServerMessages)();
|
|
23
24
|
return `
|
|
@@ -27,9 +28,13 @@ Additionally, the server is not well guarded against attacks (e.g., you can theo
|
|
|
27
28
|
|
|
28
29
|
Every message has to be given in a single line (i.e., without a newline in-between) and end with a newline character. Nevertheless, we will pretty-print example given in the following segments for the ease of reading.
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
${(0, doc_structure_1.block)({
|
|
32
|
+
type: 'NOTE',
|
|
33
|
+
content: `
|
|
34
|
+
The default ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'server', false)} uses a simple [TCP](https://de.wikipedia.org/wiki/Transmission_Control_Protocol)
|
|
35
|
+
connection. If you want _flowR_ to expose a [WebSocket](https://de.wikipedia.org/wiki/WebSocket) server instead, add the ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'ws', false)} flag (i.e., ${(0, doc_cli_option_1.multipleCliOptions)('flowr', 'server', 'ws')}) when starting _flowR_ from the command line.
|
|
36
|
+
`
|
|
37
|
+
})}
|
|
33
38
|
|
|
34
39
|
${await (0, doc_server_message_1.printServerMessages)(shell)}
|
|
35
40
|
|
|
@@ -6,9 +6,7 @@ const log_1 = require("../../test/functionality/_helper/log");
|
|
|
6
6
|
const query_1 = require("../queries/query");
|
|
7
7
|
const doc_files_1 = require("./doc-util/doc-files");
|
|
8
8
|
const doc_query_1 = require("./doc-util/doc-query");
|
|
9
|
-
const call_context_query_format_1 = require("../queries/catalog/call-context-query/call-context-query-format");
|
|
10
9
|
const schema_1 = require("../util/schema");
|
|
11
|
-
const query_schema_1 = require("../queries/query-schema");
|
|
12
10
|
const ansi_1 = require("../util/ansi");
|
|
13
11
|
const call_context_query_executor_1 = require("../queries/catalog/call-context-query/call-context-query-executor");
|
|
14
12
|
const compound_query_1 = require("../queries/virtual-query/compound-query");
|
|
@@ -22,6 +20,11 @@ const normalized_ast_query_executor_1 = require("../queries/catalog/normalized-a
|
|
|
22
20
|
const cluster_query_executor_1 = require("../queries/catalog/cluster-query/cluster-query-executor");
|
|
23
21
|
const static_slice_query_executor_1 = require("../queries/catalog/static-slice-query/static-slice-query-executor");
|
|
24
22
|
const lineage_query_executor_1 = require("../queries/catalog/lineage-query/lineage-query-executor");
|
|
23
|
+
const dependencies_query_executor_1 = require("../queries/catalog/dependencies-query/dependencies-query-executor");
|
|
24
|
+
const doc_cli_option_1 = require("./doc-util/doc-cli-option");
|
|
25
|
+
const doc_issue_1 = require("./doc-util/doc-issue");
|
|
26
|
+
const location_map_query_executor_1 = require("../queries/catalog/location-map-query/location-map-query-executor");
|
|
27
|
+
const identify_link_to_last_call_relation_1 = require("../queries/catalog/call-context-query/identify-link-to-last-call-relation");
|
|
25
28
|
(0, doc_query_1.registerQueryDocumentation)('call-context', {
|
|
26
29
|
name: 'Call-Context Query',
|
|
27
30
|
type: 'active',
|
|
@@ -54,7 +57,7 @@ ${await (0, doc_query_1.showQuery)(shell, example_query_code_1.exampleQueryCode,
|
|
|
54
57
|
callName: '^read_',
|
|
55
58
|
kind: 'input',
|
|
56
59
|
subkind: 'csv-file',
|
|
57
|
-
callTargets:
|
|
60
|
+
callTargets: identify_link_to_last_call_relation_1.CallTargets.OnlyGlobal
|
|
58
61
|
},
|
|
59
62
|
{
|
|
60
63
|
type: 'call-context',
|
|
@@ -67,7 +70,7 @@ ${await (0, doc_query_1.showQuery)(shell, example_query_code_1.exampleQueryCode,
|
|
|
67
70
|
|
|
68
71
|
As you can see, all kinds and subkinds with the same name are grouped together.
|
|
69
72
|
Yet, re-stating common arguments and kinds may be cumbersome (although you can already use clever regex patterns).
|
|
70
|
-
See the
|
|
73
|
+
See the ${(0, doc_query_1.linkToQueryOfName)('compound')} for a way to structure your queries more compactly if you think it gets too verbose.
|
|
71
74
|
|
|
72
75
|
${await (async () => {
|
|
73
76
|
const code = `
|
|
@@ -99,7 +102,7 @@ This query type does exactly that!
|
|
|
99
102
|
Using the example code \`${exampleCode}\`, the following query returns the dataflow graph of the code:
|
|
100
103
|
${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
101
104
|
type: 'dataflow'
|
|
102
|
-
}], { showCode: true })}
|
|
105
|
+
}], { showCode: true, collapseQuery: true })}
|
|
103
106
|
`;
|
|
104
107
|
}
|
|
105
108
|
});
|
|
@@ -118,7 +121,7 @@ This query type does exactly that!
|
|
|
118
121
|
Using the example code \`${exampleCode}\`, the following query returns the normalized AST of the code:
|
|
119
122
|
${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
120
123
|
type: 'normalized-ast'
|
|
121
|
-
}], { showCode: true })}
|
|
124
|
+
}], { showCode: true, collapseQuery: true })}
|
|
122
125
|
`;
|
|
123
126
|
}
|
|
124
127
|
});
|
|
@@ -176,7 +179,7 @@ ${(0, doc_structure_1.details)('Example <code>' + exampleB + '</code>', await (0
|
|
|
176
179
|
Using the example code from above, the following query returns all clusters:
|
|
177
180
|
${await (0, doc_query_1.showQuery)(shell, example_query_code_1.exampleQueryCode, [{
|
|
178
181
|
type: 'dataflow-cluster'
|
|
179
|
-
}], { showCode: false })}
|
|
182
|
+
}], { showCode: false, collapseQuery: true })}
|
|
180
183
|
`;
|
|
181
184
|
}
|
|
182
185
|
});
|
|
@@ -194,7 +197,7 @@ This query provides access to all nodes in the [normalized AST](${doc_files_1.Fl
|
|
|
194
197
|
Using the example code \`${exampleCode}\`, the following query returns all nodes from the code:
|
|
195
198
|
${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
196
199
|
type: 'id-map'
|
|
197
|
-
}], { showCode: true })}
|
|
200
|
+
}], { showCode: true, collapseQuery: true })}
|
|
198
201
|
`;
|
|
199
202
|
}
|
|
200
203
|
});
|
|
@@ -240,10 +243,10 @@ want to resolve to a local definition:
|
|
|
240
243
|
${await (0, doc_query_1.showQuery)(shell, example_query_code_1.exampleQueryCode, [{
|
|
241
244
|
type: 'compound',
|
|
242
245
|
query: 'call-context',
|
|
243
|
-
commonArguments: { kind: 'visualize', subkind: 'text', callTargets:
|
|
246
|
+
commonArguments: { kind: 'visualize', subkind: 'text', callTargets: identify_link_to_last_call_relation_1.CallTargets.OnlyGlobal },
|
|
244
247
|
arguments: [
|
|
245
248
|
{ callName: '^mean$' },
|
|
246
|
-
{ callName: '^print$', callTargets:
|
|
249
|
+
{ callName: '^print$', callTargets: identify_link_to_last_call_relation_1.CallTargets.OnlyLocal }
|
|
247
250
|
]
|
|
248
251
|
}], { showCode: false })}
|
|
249
252
|
|
|
@@ -289,6 +292,85 @@ This query replaces the old [\`request-slice\`](${doc_files_1.FlowrWikiBaseRef}/
|
|
|
289
292
|
`;
|
|
290
293
|
}
|
|
291
294
|
});
|
|
295
|
+
(0, doc_query_1.registerQueryDocumentation)('dependencies', {
|
|
296
|
+
name: 'Dependencies Query',
|
|
297
|
+
type: 'active',
|
|
298
|
+
shortDescription: 'Returns all direct dependencies (in- and outputs) of a given R script',
|
|
299
|
+
functionName: dependencies_query_executor_1.executeDependenciesQuery.name,
|
|
300
|
+
functionFile: '../queries/catalog/dependencies-query/dependencies-query-executor.ts',
|
|
301
|
+
buildExplanation: async (shell) => {
|
|
302
|
+
const exampleCode = 'library(x)';
|
|
303
|
+
const longerCode = `
|
|
304
|
+
source("sample.R")
|
|
305
|
+
foo <- loadNamespace("bar")
|
|
306
|
+
|
|
307
|
+
data <- read.csv("data.csv")
|
|
308
|
+
|
|
309
|
+
#' @importFrom ggplot2 ggplot geom_point aes
|
|
310
|
+
ggplot(data, aes(x=x, y=y)) + geom_point()
|
|
311
|
+
|
|
312
|
+
better::write.csv(data, "data2.csv")
|
|
313
|
+
print("hello world!")
|
|
314
|
+
`;
|
|
315
|
+
return `
|
|
316
|
+
This query extracts all dependencies from an R script, using a combination of a ${(0, doc_query_1.linkToQueryOfName)('call-context')}
|
|
317
|
+
and more advanced tracking in the [Dataflow Graph](${doc_files_1.FlowrWikiBaseRef}/Dataflow%20Graph).
|
|
318
|
+
|
|
319
|
+
In other words, if you have a script simply reading: \`${exampleCode}\`, the following query returns the loaded library:
|
|
320
|
+
${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
321
|
+
type: 'dependencies'
|
|
322
|
+
}], { showCode: false, collapseQuery: true })}
|
|
323
|
+
|
|
324
|
+
Of course, this works for more complicated scripts too. The query offers information on the loaded _libraries_, _sourced_ files, data which is _read_ and data which is _written_.
|
|
325
|
+
For example, consider the following script:
|
|
326
|
+
${(0, doc_code_1.codeBlock)('r', longerCode)}
|
|
327
|
+
The following query returns the dependencies of the script.
|
|
328
|
+
${await (0, doc_query_1.showQuery)(shell, longerCode, [{
|
|
329
|
+
type: 'dependencies'
|
|
330
|
+
}], { showCode: false, collapseQuery: true, collapseResult: true })}
|
|
331
|
+
|
|
332
|
+
Currently the dependency extraction may fail as it is essentially a set of heuristics guessing the dependencies.
|
|
333
|
+
We welcome any feedback on this (consider opening a [new issue](${doc_issue_1.NewIssueUrl})).
|
|
334
|
+
|
|
335
|
+
In the meantime we offer several properties to overwrite the default behavior (e.g., function names that should be collected)
|
|
336
|
+
|
|
337
|
+
${await (0, doc_query_1.showQuery)(shell, longerCode, [{
|
|
338
|
+
type: 'dependencies',
|
|
339
|
+
ignoreDefaultFunctions: true,
|
|
340
|
+
libraryFunctions: [{ name: 'print', argIdx: 0, argName: 'library' }],
|
|
341
|
+
sourceFunctions: [],
|
|
342
|
+
readFunctions: [],
|
|
343
|
+
writeFunctions: []
|
|
344
|
+
}], { showCode: false, collapseQuery: false, collapseResult: true })}
|
|
345
|
+
|
|
346
|
+
`;
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
(0, doc_query_1.registerQueryDocumentation)('location-map', {
|
|
350
|
+
name: 'Location Map Query',
|
|
351
|
+
type: 'active',
|
|
352
|
+
shortDescription: 'Returns a simple mapping of ids to their location in the source file',
|
|
353
|
+
functionName: location_map_query_executor_1.executeLocationMapQuery.name,
|
|
354
|
+
functionFile: '../queries/catalog/location-map-query/location-map-query-executor.ts',
|
|
355
|
+
buildExplanation: async (shell) => {
|
|
356
|
+
const exampleCode = 'x + 1\nx * 2';
|
|
357
|
+
return `
|
|
358
|
+
A query like the ${(0, doc_query_1.linkToQueryOfName)('id-map')} query can return a really big result, especially for larger scripts.
|
|
359
|
+
If you are not interested in all of the information contained within the full map, you can use the location map query to get a simple mapping of ids to their location in the source file.
|
|
360
|
+
|
|
361
|
+
Consider you have the following code:
|
|
362
|
+
|
|
363
|
+
${(0, doc_code_1.codeBlock)('r', exampleCode)}
|
|
364
|
+
|
|
365
|
+
The following query then gives you the aforementioned mapping:
|
|
366
|
+
|
|
367
|
+
${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
|
|
368
|
+
type: 'location-map'
|
|
369
|
+
}], { showCode: false, collapseQuery: true })}
|
|
370
|
+
|
|
371
|
+
`;
|
|
372
|
+
}
|
|
373
|
+
});
|
|
292
374
|
async function getText(shell) {
|
|
293
375
|
const rversion = (await shell.usedRVersion())?.format() ?? 'unknown';
|
|
294
376
|
return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'query API', rVersion: rversion })}
|
|
@@ -296,13 +378,22 @@ async function getText(shell) {
|
|
|
296
378
|
This page briefly summarizes flowR's query API, represented by the ${query_1.executeQueries.name} function in ${(0, doc_files_1.getFilePathMd)('../queries/query.ts')}.
|
|
297
379
|
Please see the [Interface](${doc_files_1.FlowrWikiBaseRef}/Interface) wiki page for more information on how to access this API.
|
|
298
380
|
|
|
381
|
+
${(0, doc_structure_1.block)({
|
|
382
|
+
type: 'NOTE',
|
|
383
|
+
content: `
|
|
384
|
+
There are many ways to query a dataflow graph created by flowR.
|
|
385
|
+
For example, you can use the [\`request-query\`](${doc_files_1.FlowrWikiBaseRef}/Interface#message-request-query) message
|
|
386
|
+
with a running flowR server, or the ${(0, doc_cli_option_1.getReplCommand)('query')} command in the flowR [REPL](${doc_files_1.FlowrWikiBaseRef}/Interface#repl).
|
|
387
|
+
`.trim()
|
|
388
|
+
})}
|
|
389
|
+
|
|
299
390
|
## The Query Format
|
|
300
391
|
|
|
301
392
|
Queries are JSON arrays of query objects, each of which uses a \`type\` property to specify the query type.
|
|
302
393
|
In general, we separate two types of queries:
|
|
303
394
|
|
|
304
|
-
1. **Active Queries**: Are exactly what you would expect from a query (e.g., the
|
|
305
|
-
2. **Virtual Queries**: Are used to structure your queries (e.g., the
|
|
395
|
+
1. **Active Queries**: Are exactly what you would expect from a query (e.g., the ${(0, doc_query_1.linkToQueryOfName)('call-context')}). They fetch information from the dataflow graph.
|
|
396
|
+
2. **Virtual Queries**: Are used to structure your queries (e.g., the ${(0, doc_query_1.linkToQueryOfName)('compound')}).
|
|
306
397
|
|
|
307
398
|
We separate these from a concept perspective.
|
|
308
399
|
For now, we support the following **active** queries (which we will refer to simply as a \`query\`):
|
|
@@ -320,7 +411,7 @@ ${(0, doc_query_1.tocForQueryType)('virtual')}
|
|
|
320
411
|
|
|
321
412
|
Although it is probably better to consult the detailed explanations below, if you want to have a look at the scehma, here is its description:
|
|
322
413
|
|
|
323
|
-
${(0, schema_1.describeSchema)(
|
|
414
|
+
${(0, schema_1.describeSchema)(query_1.QueriesSchema, ansi_1.markdownFormatter)}
|
|
324
415
|
|
|
325
416
|
</details>
|
|
326
417
|
|
|
@@ -349,11 +440,11 @@ However, this fails to incorporate
|
|
|
349
440
|
3. Context information (e.g., calls like \`points\` may link to the current plot)
|
|
350
441
|
|
|
351
442
|
To solve this, flowR provides a query API which allows you to specify queries on the dataflow graph.
|
|
352
|
-
For the specific use-case stated, you could use the
|
|
443
|
+
For the specific use-case stated, you could use the ${(0, doc_query_1.linkToQueryOfName)('call-context')} to find all calls to \`read_csv\` which refer functions that are not overwritten.
|
|
353
444
|
|
|
354
|
-
Just as an example, the following
|
|
445
|
+
Just as an example, the following ${(0, doc_query_1.linkToQueryOfName)('call-context')} finds all calls to \`read_csv\` that are not overwritten:
|
|
355
446
|
|
|
356
|
-
${await (0, doc_query_1.showQuery)(shell, example_query_code_1.exampleQueryCode, [{ type: 'call-context', callName: '^read_csv$', callTargets:
|
|
447
|
+
${await (0, doc_query_1.showQuery)(shell, example_query_code_1.exampleQueryCode, [{ type: 'call-context', callName: '^read_csv$', callTargets: identify_link_to_last_call_relation_1.CallTargets.OnlyGlobal, kind: 'input', subkind: 'csv-file' }], { showCode: false })}
|
|
357
448
|
|
|
358
449
|
${await (0, doc_query_1.explainQueries)(shell, 'active')}
|
|
359
450
|
|
package/package.json
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { NormalizedAst } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
2
|
+
import type { DataflowGraph } from '../dataflow/graph/graph';
|
|
1
3
|
export interface BaseQueryFormat {
|
|
2
4
|
/** used to select the query type :) */
|
|
3
5
|
readonly type: string;
|
|
@@ -9,3 +11,7 @@ export interface BaseQueryMeta {
|
|
|
9
11
|
export interface BaseQueryResult {
|
|
10
12
|
readonly '.meta': BaseQueryMeta;
|
|
11
13
|
}
|
|
14
|
+
export interface BasicQueryData {
|
|
15
|
+
readonly ast: NormalizedAst;
|
|
16
|
+
readonly graph: DataflowGraph;
|
|
17
|
+
}
|