@eagleoutice/flowr 2.1.2 → 2.1.3

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.
@@ -1,8 +1,3 @@
1
- import { DEFAULT_DATAFLOW_PIPELINE } from '../../../core/steps/pipeline/default-pipelines';
2
1
  import type { ReplCommand } from './repl-main';
3
- import type { OutputFormatter } from '../../../util/ansi';
4
- import type { QueryResults, SupportedQueryTypes } from '../../../queries/query';
5
- import type { PipelineOutput } from '../../../core/steps/pipeline/pipeline';
6
- export declare function asciiSummaryOfQueryResult(formatter: OutputFormatter, totalInMs: number, results: QueryResults<SupportedQueryTypes>, processed: PipelineOutput<typeof DEFAULT_DATAFLOW_PIPELINE>): string;
7
2
  export declare const queryCommand: ReplCommand;
8
3
  export declare const queryStarCommand: ReplCommand;
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.queryStarCommand = exports.queryCommand = void 0;
4
- exports.asciiSummaryOfQueryResult = asciiSummaryOfQueryResult;
5
4
  const pipeline_executor_1 = require("../../../core/pipeline-executor");
6
5
  const default_pipelines_1 = require("../../../core/steps/pipeline/default-pipelines");
7
6
  const retriever_1 = require("../../../r-bridge/retriever");
@@ -11,11 +10,6 @@ const schema_1 = require("../../../util/schema");
11
10
  const query_1 = require("../../../queries/query");
12
11
  const json_1 = require("../../../util/json");
13
12
  const query_schema_1 = require("../../../queries/query-schema");
14
- const built_in_1 = require("../../../dataflow/environments/built-in");
15
- const dfg_1 = require("../../../util/mermaid/dfg");
16
- const ast_1 = require("../../../util/mermaid/ast");
17
- const time_1 = require("../../../util/time");
18
- const doc_hover_over_1 = require("../../../documentation/doc-util/doc-hover-over");
19
13
  async function getDataflow(shell, remainingLine) {
20
14
  return await new pipeline_executor_1.PipelineExecutor(default_pipelines_1.DEFAULT_DATAFLOW_PIPELINE, {
21
15
  shell,
@@ -60,141 +54,6 @@ async function processQueryArgs(line, shell, output) {
60
54
  processed
61
55
  };
62
56
  }
63
- function nodeString(id, formatter, processed) {
64
- if (id === built_in_1.BuiltIn) {
65
- return (0, ansi_1.italic)('built-in', formatter);
66
- }
67
- const node = processed.normalize.idMap.get(id);
68
- if (node === undefined) {
69
- return `UNKNOWN: ${id}`;
70
- }
71
- return `${(0, ansi_1.italic)('`' + (node.lexeme ?? node.info.fullLexeme ?? 'UNKNOWN') + '`', formatter)} (L.${node.location?.[0]})`;
72
- }
73
- function asciiCallContextSubHit(formatter, results, processed) {
74
- const result = [];
75
- for (const { id, calls = [], linkedIds = [], aliasRoots = [] } of results) {
76
- const node = processed.normalize.idMap.get(id);
77
- if (node === undefined) {
78
- result.push(` ${(0, ansi_1.bold)('UNKNOWN: ' + JSON.stringify({ calls, linkedIds }))}`);
79
- continue;
80
- }
81
- let line = nodeString(id, formatter, processed);
82
- if (calls.length > 0) {
83
- line += ` with ${calls.length} call${calls.length > 1 ? 's' : ''} (${calls.map(c => nodeString(c, formatter, processed)).join(', ')})`;
84
- }
85
- if (linkedIds.length > 0) {
86
- line += ` with ${linkedIds.length} link${linkedIds.length > 1 ? 's' : ''} (${linkedIds.map(c => nodeString(c, formatter, processed)).join(', ')})`;
87
- }
88
- if (aliasRoots.length > 0) {
89
- line += ` with ${aliasRoots.length} alias root${aliasRoots.length > 1 ? 's' : ''} (${aliasRoots.map(c => nodeString(c, formatter, processed)).join(', ')})`;
90
- }
91
- result.push(line);
92
- }
93
- return result.join(', ');
94
- }
95
- function asciiCallContext(formatter, results, processed) {
96
- /* traverse over 'kinds' and within them 'subkinds' */
97
- const result = [];
98
- for (const [kind, { subkinds }] of Object.entries(results['kinds'])) {
99
- result.push(` ╰ ${(0, ansi_1.bold)(kind, formatter)}`);
100
- for (const [subkind, values] of Object.entries(subkinds)) {
101
- result.push(` ╰ ${(0, ansi_1.bold)(subkind, formatter)}: ${asciiCallContextSubHit(formatter, values, processed)}`);
102
- }
103
- }
104
- return result.join('\n');
105
- }
106
- function summarizeIdsIfTooLong(ids) {
107
- const naive = ids.join(', ');
108
- if (naive.length <= 20) {
109
- return naive;
110
- }
111
- let acc = '';
112
- let i = 0;
113
- while (acc.length <= 20) {
114
- acc += ids[i++] + ', ';
115
- }
116
- if (i < ids.length) {
117
- acc += '... (see JSON below)';
118
- }
119
- return (0, doc_hover_over_1.textWithTooltip)(acc, JSON.stringify(ids));
120
- }
121
- function asciiSummaryOfQueryResult(formatter, totalInMs, results, processed) {
122
- const result = [];
123
- for (const [query, queryResults] of Object.entries(results)) {
124
- if (query === '.meta') {
125
- continue;
126
- }
127
- if (query === 'call-context') {
128
- const out = queryResults;
129
- result.push(`Query: ${(0, ansi_1.bold)(query, formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
130
- result.push(asciiCallContext(formatter, out, processed));
131
- continue;
132
- }
133
- else if (query === 'dataflow') {
134
- const out = queryResults;
135
- result.push(`Query: ${(0, ansi_1.bold)(query, formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
136
- result.push(` ╰ [Dataflow Graph](${(0, dfg_1.graphToMermaidUrl)(out.graph)})`);
137
- continue;
138
- }
139
- else if (query === 'id-map') {
140
- const out = queryResults;
141
- result.push(`Query: ${(0, ansi_1.bold)(query, formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
142
- result.push(` ╰ Id List: {${summarizeIdsIfTooLong([...out.idMap.keys()])}}`);
143
- continue;
144
- }
145
- else if (query === 'normalized-ast') {
146
- const out = queryResults;
147
- result.push(`Query: ${(0, ansi_1.bold)(query, formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
148
- result.push(` ╰ [Normalized AST](${(0, ast_1.normalizedAstToMermaidUrl)(out.normalized.ast)})`);
149
- continue;
150
- }
151
- else if (query === 'static-slice') {
152
- const out = queryResults;
153
- result.push(`Query: ${(0, ansi_1.bold)(query, formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
154
- for (const [fingerprint, obj] of Object.entries(out.results)) {
155
- const { criteria, noMagicComments, noReconstruction } = JSON.parse(fingerprint);
156
- const addons = [];
157
- if (noReconstruction) {
158
- addons.push('no reconstruction');
159
- }
160
- if (noMagicComments) {
161
- addons.push('no magic comments');
162
- }
163
- result.push(` ╰ Slice for {${criteria.join(', ')}} ${addons.join(', ')}`);
164
- if ('reconstruct' in obj) {
165
- result.push(' ╰ Code (newline as <code>&#92;n</code>): <code>' + obj.reconstruct.code.split('\n').join('\\n') + '</code>');
166
- }
167
- else {
168
- result.push(` ╰ Id List: {${summarizeIdsIfTooLong([...obj.slice.result])}}`);
169
- }
170
- }
171
- continue;
172
- }
173
- else if (query === 'dataflow-cluster') {
174
- const out = queryResults;
175
- result.push(`Query: ${(0, ansi_1.bold)(query, formatter)} (${out['.meta'].timing.toFixed(0)}ms)`);
176
- result.push(` ╰ Found ${out.clusters.length} cluster${out.clusters.length === 1 ? '' : 's'}`);
177
- for (const cluster of out.clusters) {
178
- const unknownSideEffects = cluster.hasUnknownSideEffects ? '(has unknown side effect)' : '';
179
- result.push(` ╰ ${unknownSideEffects} {${summarizeIdsIfTooLong(cluster.members)}} ([marked](${(0, dfg_1.graphToMermaidUrl)(processed.dataflow.graph, false, new Set(cluster.members))}))`);
180
- }
181
- continue;
182
- }
183
- result.push(`Query: ${(0, ansi_1.bold)(query, formatter)}`);
184
- let timing = -1;
185
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
186
- for (const [key, value] of Object.entries(queryResults)) {
187
- if (key === '.meta') {
188
- timing = value.timing;
189
- continue;
190
- }
191
- result.push(` ╰ ${key}: ${JSON.stringify(value)}`);
192
- }
193
- result.push(` - Took ${(0, time_1.printAsMs)(timing, 0)}`);
194
- }
195
- 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));
196
- return formatter.format(result.join('\n'));
197
- }
198
57
  exports.queryCommand = {
199
58
  description: `Query the given R code, start with '${retriever_1.fileProtocol}' to indicate a file. The query is to be a valid query in json format (use 'help' to get more information).`,
200
59
  usageExample: ':query "<query>" <code>',
@@ -205,7 +64,8 @@ exports.queryCommand = {
205
64
  const results = await processQueryArgs(remainingLine, shell, output);
206
65
  const totalEnd = Date.now();
207
66
  if (results) {
208
- output.stdout(asciiSummaryOfQueryResult(output.formatter, totalEnd - totalStart, results.query, results.processed));
67
+ output.stdout(JSON.stringify(results));
68
+ output.stdout('Total time: ' + (totalEnd - totalStart) + 'ms');
209
69
  }
210
70
  }
211
71
  };
@@ -467,10 +467,15 @@ See [above](#message-request-file-analysis) for the general structure of the res
467
467
  end
468
468
  deactivate Server
469
469
  `,
470
- shortDescription: 'Obtain the lineage of a given slicing criterion.',
470
+ shortDescription: '([DEPRECATED](${FlowrWikiBaseRef}/Query%20API)) Obtain the lineage of a given slicing criterion.',
471
471
  text: async (shell) => {
472
472
  return `
473
473
 
474
+ ${(0, doc_structure_1.block)({
475
+ type: 'WARNING',
476
+ content: `We deprecated the lineage request in favor of the \`lineage\` [Query](${doc_files_1.FlowrWikiBaseRef}/Query%20API).`
477
+ })}
478
+
474
479
  In order to retrieve the lineage of an object, you have to send a file analysis request first. The \`filetoken\` you assign is of use here as you can re-use it to repeatedly retrieve the lineage of the same file.
475
480
  Besides that, you will need to add a [criterion](${doc_files_1.FlowrWikiBaseRef}/Terminology#slicing-criterion) that specifies the object whose lineage you're interested in.
476
481
 
@@ -1,11 +1,15 @@
1
1
  import type { RShell } from '../../r-bridge/shell';
2
- import type { Queries, SupportedQueryTypes } from '../../queries/query';
2
+ import type { Queries, QueryResults, SupportedQueryTypes } from '../../queries/query';
3
+ import { DEFAULT_DATAFLOW_PIPELINE } from '../../core/steps/pipeline/default-pipelines';
4
+ import { type OutputFormatter } from '../../util/ansi';
3
5
  import type { SupportedVirtualQueryTypes } from '../../queries/virtual-query/virtual-queries';
4
6
  import type { VirtualCompoundConstraint } from '../../queries/virtual-query/compound-query';
7
+ import type { PipelineOutput } from '../../core/steps/pipeline/pipeline';
5
8
  export interface ShowQueryOptions {
6
9
  readonly showCode?: boolean;
7
10
  readonly collapseResult?: boolean;
8
11
  }
12
+ export declare function asciiSummaryOfQueryResult(formatter: OutputFormatter, totalInMs: number, results: QueryResults<SupportedQueryTypes>, processed: PipelineOutput<typeof DEFAULT_DATAFLOW_PIPELINE>): string;
9
13
  export declare function showQuery<Base extends SupportedQueryTypes, VirtualArguments extends VirtualCompoundConstraint<Base> = VirtualCompoundConstraint<Base>>(shell: RShell, code: string, queries: Queries<Base, VirtualArguments>, { showCode, collapseResult }?: ShowQueryOptions): Promise<string>;
10
14
  export interface QueryDocumentation {
11
15
  readonly name: string;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RegisteredQueries = void 0;
4
+ exports.asciiSummaryOfQueryResult = asciiSummaryOfQueryResult;
4
5
  exports.showQuery = showQuery;
5
6
  exports.registerQueryDocumentation = registerQueryDocumentation;
6
7
  exports.tocForQueryType = tocForQueryType;
@@ -11,11 +12,157 @@ const default_pipelines_1 = require("../../core/steps/pipeline/default-pipelines
11
12
  const retriever_1 = require("../../r-bridge/retriever");
12
13
  const json_1 = require("../../util/json");
13
14
  const ansi_1 = require("../../util/ansi");
14
- const repl_query_1 = require("../../cli/repl/commands/repl-query");
15
15
  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 built_in_1 = require("../../dataflow/environments/built-in");
20
+ const dfg_1 = require("../../util/mermaid/dfg");
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>&#92;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
+ }
19
166
  async function showQuery(shell, code, queries, { showCode, collapseResult } = {}) {
20
167
  const now = performance.now();
21
168
  const analysis = await new pipeline_executor_1.PipelineExecutor(default_pipelines_1.DEFAULT_DATAFLOW_PIPELINE, {
@@ -37,7 +184,7 @@ ${collapseResult ? ' <details> <summary style="color:gray">Show Results</summary
37
184
 
38
185
  _Results (prettified and summarized):_
39
186
 
40
- ${(0, repl_query_1.asciiSummaryOfQueryResult)(ansi_1.markdownFormatter, duration, results, analysis)}
187
+ ${asciiSummaryOfQueryResult(ansi_1.markdownFormatter, duration, results, analysis)}
41
188
 
42
189
  <details> <summary style="color:gray">Show Detailed Results as Json</summary>
43
190
 
@@ -21,6 +21,7 @@ const id_map_query_executor_1 = require("../queries/catalog/id-map-query/id-map-
21
21
  const normalized_ast_query_executor_1 = require("../queries/catalog/normalized-ast-query/normalized-ast-query-executor");
22
22
  const cluster_query_executor_1 = require("../queries/catalog/cluster-query/cluster-query-executor");
23
23
  const static_slice_query_executor_1 = require("../queries/catalog/static-slice-query/static-slice-query-executor");
24
+ const lineage_query_executor_1 = require("../queries/catalog/lineage-query/lineage-query-executor");
24
25
  (0, doc_query_1.registerQueryDocumentation)('call-context', {
25
26
  name: 'Call-Context Query',
26
27
  type: 'active',
@@ -121,6 +122,37 @@ ${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
121
122
  `;
122
123
  }
123
124
  });
125
+ (0, doc_query_1.registerQueryDocumentation)('lineage', {
126
+ name: 'Lineage Query',
127
+ type: 'active',
128
+ shortDescription: 'Returns lineage of a criteria.',
129
+ functionName: lineage_query_executor_1.executeLineageQuery.name,
130
+ functionFile: '../queries/catalog/lineage-query/lineage-query-executor.ts',
131
+ buildExplanation: async (shell) => {
132
+ const exampleCode = 'x <- 1\nx';
133
+ return `
134
+ This query calculates the _lineage_ of a given slicing criterion. The lineage traces back all parts that the
135
+ respective variables stems from given the reads, definitions, and returns in the dataflow graph.
136
+
137
+ To understand this, let's start with a simple example query, to get the lineage of the second use of \`x\` in the following code:
138
+ ${(0, doc_code_1.codeBlock)('r', exampleCode)}
139
+
140
+ For this, we use the criterion \`2@x\` (which is the first use of \`x\` in the second line).
141
+
142
+ ${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
143
+ type: 'lineage',
144
+ criterion: '2@x'
145
+ }], { showCode: false })}
146
+
147
+ In this simple scenario, the _lineage_ is equivalent to the slice (and in-fact the complete code).
148
+ In general the lineage is smaller and makes no executability guarantees.
149
+ It is just a quick and neither complete nor sound way to get information on where the variable originates from.
150
+
151
+ This query replaces the old [\`request-lineage\`](${doc_files_1.FlowrWikiBaseRef}/Interface#message-request-lineage) message.
152
+
153
+ `;
154
+ }
155
+ });
124
156
  (0, doc_query_1.registerQueryDocumentation)('dataflow-cluster', {
125
157
  name: 'Dataflow Cluster Query',
126
158
  type: 'active',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eagleoutice/flowr",
3
- "version": "2.1.2",
3
+ "version": "2.1.3",
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": {
@@ -38,7 +38,8 @@
38
38
  "test": "nyc --no-clean mocha",
39
39
  "performance-test": "func() { cd test/performance/ && bash run-all-suites.sh $1 $2 $3; cd ../../; }; func",
40
40
  "test-full": "npm run test -- --test-installation",
41
- "detect-circular-deps": "npx madge --extensions ts,tsx --circular src/"
41
+ "detect-circular-deps": "npx madge --extensions ts,tsx --circular src/",
42
+ "checkup": "npm run flowr -- --execute \":version\" && npm run lint && npm run test-full -- --forbid-only && docker build -t test-flowr -f scripts/Dockerfile . && npm run doc && npm-run-all wiki:*"
42
43
  },
43
44
  "keywords": [
44
45
  "static code analysis",
@@ -93,7 +93,7 @@ function isSubCallQuery(query) {
93
93
  return 'linkTo' in query;
94
94
  }
95
95
  function exactCallNameRegex(name) {
96
- return new RegExp(`^${name}$`);
96
+ return new RegExp(`^(${name})$`);
97
97
  }
98
98
  function promoteQueryCallNames(queries) {
99
99
  let requiresCfg = false;
@@ -0,0 +1,3 @@
1
+ import type { BasicQueryData } from '../../query';
2
+ import type { LineageQuery, LineageQueryResult } from './lineage-query-format';
3
+ export declare function executeLineageQuery({ graph, ast }: BasicQueryData, queries: readonly LineageQuery[]): LineageQueryResult;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.executeLineageQuery = executeLineageQuery;
4
+ const log_1 = require("../../../util/log");
5
+ const repl_lineage_1 = require("../../../cli/repl/commands/repl-lineage");
6
+ function executeLineageQuery({ graph, ast }, queries) {
7
+ const start = Date.now();
8
+ const result = {};
9
+ for (const { criterion } of queries) {
10
+ if (result[criterion]) {
11
+ log_1.log.warn('Duplicate criterion in lineage query:', criterion);
12
+ }
13
+ result[criterion] = (0, repl_lineage_1.getLineage)(criterion, graph, ast.idMap);
14
+ }
15
+ return {
16
+ '.meta': {
17
+ timing: Date.now() - start
18
+ },
19
+ lineages: result
20
+ };
21
+ }
22
+ //# sourceMappingURL=lineage-query-executor.js.map
@@ -0,0 +1,14 @@
1
+ import type { BaseQueryFormat, BaseQueryResult } from '../../base-query-format';
2
+ import type { SingleSlicingCriterion } from '../../../slicing/criterion/parse';
3
+ import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
4
+ /**
5
+ * Calculates the lineage of the given criterion.
6
+ */
7
+ export interface LineageQuery extends BaseQueryFormat {
8
+ readonly type: 'lineage';
9
+ readonly criterion: SingleSlicingCriterion;
10
+ }
11
+ export interface LineageQueryResult extends BaseQueryResult {
12
+ /** Maps each criterion to the found lineage, duplicates are ignored. */
13
+ readonly lineages: Record<SingleSlicingCriterion, Set<NodeId>>;
14
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=lineage-query-format.js.map
@@ -5,6 +5,7 @@ export declare const IdMapQuerySchema: Joi.ObjectSchema<any>;
5
5
  export declare const NormalizedAstQuerySchema: Joi.ObjectSchema<any>;
6
6
  export declare const DataflowClusterQuerySchema: Joi.ObjectSchema<any>;
7
7
  export declare const StaticSliceQuerySchema: Joi.ObjectSchema<any>;
8
+ export declare const LineageQuerySchema: Joi.ObjectSchema<any>;
8
9
  export declare const SupportedQueriesSchema: Joi.AlternativesSchema<any>;
9
10
  export declare const CompoundQuerySchema: Joi.ObjectSchema<any>;
10
11
  export declare const VirtualQuerySchema: Joi.AlternativesSchema<any>;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.QueriesSchema = exports.AnyQuerySchema = exports.VirtualQuerySchema = exports.CompoundQuerySchema = exports.SupportedQueriesSchema = exports.StaticSliceQuerySchema = exports.DataflowClusterQuerySchema = exports.NormalizedAstQuerySchema = exports.IdMapQuerySchema = exports.DataflowQuerySchema = exports.CallContextQuerySchema = void 0;
6
+ exports.QueriesSchema = exports.AnyQuerySchema = exports.VirtualQuerySchema = exports.CompoundQuerySchema = exports.SupportedQueriesSchema = exports.LineageQuerySchema = exports.StaticSliceQuerySchema = exports.DataflowClusterQuerySchema = exports.NormalizedAstQuerySchema = exports.IdMapQuerySchema = exports.DataflowQuerySchema = exports.CallContextQuerySchema = void 0;
7
7
  const joi_1 = __importDefault(require("joi"));
8
8
  const call_context_query_format_1 = require("./catalog/call-context-query/call-context-query-format");
9
9
  exports.CallContextQuerySchema = joi_1.default.object({
@@ -37,7 +37,11 @@ exports.StaticSliceQuerySchema = joi_1.default.object({
37
37
  noReconstruction: joi_1.default.boolean().optional().description('Do not reconstruct the slice into readable code.'),
38
38
  noMagicComments: joi_1.default.boolean().optional().description('Should the magic comments (force-including lines within the slice) be ignored?')
39
39
  }).description('Slice query used to slice the dataflow graph');
40
- exports.SupportedQueriesSchema = joi_1.default.alternatives(exports.CallContextQuerySchema, exports.DataflowQuerySchema, exports.IdMapQuerySchema, exports.NormalizedAstQuerySchema, exports.DataflowClusterQuerySchema, exports.StaticSliceQuerySchema).description('Supported queries');
40
+ exports.LineageQuerySchema = joi_1.default.object({
41
+ type: joi_1.default.string().valid('lineage').required().description('The type of the query.'),
42
+ id: joi_1.default.string().required().description('The ID of the node to get the lineage of.')
43
+ }).description('Lineage query used to find the lineage of a node in the dataflow graph');
44
+ exports.SupportedQueriesSchema = joi_1.default.alternatives(exports.CallContextQuerySchema, exports.DataflowQuerySchema, exports.IdMapQuerySchema, exports.NormalizedAstQuerySchema, exports.DataflowClusterQuerySchema, exports.StaticSliceQuerySchema, exports.LineageQuerySchema).description('Supported queries');
41
45
  exports.CompoundQuerySchema = joi_1.default.object({
42
46
  type: joi_1.default.string().valid('compound').required().description('The type of the query.'),
43
47
  query: joi_1.default.string().required().description('The query to run on the file analysis information.'),
@@ -15,7 +15,9 @@ import type { DataflowClusterQuery } from './catalog/cluster-query/cluster-query
15
15
  import { executeDataflowClusterQuery } from './catalog/cluster-query/cluster-query-executor';
16
16
  import type { StaticSliceQuery } from './catalog/static-slice-query/static-slice-query-format';
17
17
  import { executeStaticSliceClusterQuery } from './catalog/static-slice-query/static-slice-query-executor';
18
- export type Query = CallContextQuery | DataflowQuery | NormalizedAstQuery | IdMapQuery | DataflowClusterQuery | StaticSliceQuery;
18
+ import type { LineageQuery } from './catalog/lineage-query/lineage-query-format';
19
+ import { executeLineageQuery } from './catalog/lineage-query/lineage-query-executor';
20
+ export type Query = CallContextQuery | DataflowQuery | NormalizedAstQuery | IdMapQuery | DataflowClusterQuery | StaticSliceQuery | LineageQuery;
19
21
  export type QueryArgumentsWithType<QueryType extends BaseQueryFormat['type']> = Query & {
20
22
  type: QueryType;
21
23
  };
@@ -34,6 +36,7 @@ export declare const SupportedQueries: {
34
36
  readonly 'normalized-ast': typeof executeNormalizedAstQuery;
35
37
  readonly 'dataflow-cluster': typeof executeDataflowClusterQuery;
36
38
  readonly 'static-slice': typeof executeStaticSliceClusterQuery;
39
+ readonly lineage: typeof executeLineageQuery;
37
40
  };
38
41
  export type SupportedQueryTypes = keyof typeof SupportedQueries;
39
42
  export type QueryResult<Type extends Query['type']> = ReturnType<typeof SupportedQueries[Type]>;
package/queries/query.js CHANGED
@@ -11,13 +11,15 @@ const id_map_query_executor_1 = require("./catalog/id-map-query/id-map-query-exe
11
11
  const normalized_ast_query_executor_1 = require("./catalog/normalized-ast-query/normalized-ast-query-executor");
12
12
  const cluster_query_executor_1 = require("./catalog/cluster-query/cluster-query-executor");
13
13
  const static_slice_query_executor_1 = require("./catalog/static-slice-query/static-slice-query-executor");
14
+ const lineage_query_executor_1 = require("./catalog/lineage-query/lineage-query-executor");
14
15
  exports.SupportedQueries = {
15
16
  'call-context': call_context_query_executor_1.executeCallContextQueries,
16
17
  'dataflow': dataflow_query_executor_1.executeDataflowQuery,
17
18
  'id-map': id_map_query_executor_1.executeIdMapQuery,
18
19
  'normalized-ast': normalized_ast_query_executor_1.executeNormalizedAstQuery,
19
20
  'dataflow-cluster': cluster_query_executor_1.executeDataflowClusterQuery,
20
- 'static-slice': static_slice_query_executor_1.executeStaticSliceClusterQuery
21
+ 'static-slice': static_slice_query_executor_1.executeStaticSliceClusterQuery,
22
+ 'lineage': lineage_query_executor_1.executeLineageQuery
21
23
  };
22
24
  function executeQueriesOfSameType(data, ...queries) {
23
25
  (0, assert_1.guard)(queries.length > 0, 'At least one query must be provided');
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.1.2';
6
+ const version = '2.1.3';
7
7
  function flowrVersion() {
8
8
  return new semver_1.SemVer(version);
9
9
  }