@eagleoutice/flowr 2.4.7 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -38
- package/abstract-interpretation/data-frame/absint-visitor.js +3 -2
- package/benchmark/slicer.js +2 -2
- package/benchmark/summarizer/first-phase/process.js +1 -1
- package/benchmark/summarizer/second-phase/graph.js +2 -2
- package/cli/repl/commands/repl-query.js +11 -2
- package/cli/repl/core.d.ts +2 -2
- package/cli/repl/core.js +26 -7
- package/cli/repl/server/connection.js +3 -1
- package/cli/repl/server/messages/message-slice.d.ts +3 -0
- package/cli/repl/server/messages/message-slice.js +2 -0
- package/cli/slicer-app.js +7 -2
- package/control-flow/extract-cfg.d.ts +3 -3
- package/control-flow/extract-cfg.js +4 -4
- package/control-flow/useless-loop.js +30 -21
- package/dataflow/environments/built-in.d.ts +1 -1
- package/dataflow/environments/default-builtin-config.d.ts +9 -0
- package/dataflow/environments/default-builtin-config.js +21 -21
- package/dataflow/environments/environment.js +18 -9
- package/dataflow/environments/overwrite.js +2 -2
- package/dataflow/extractor.js +1 -1
- package/dataflow/graph/diff-dataflow-graph.js +4 -4
- package/dataflow/graph/graph.d.ts +3 -3
- package/dataflow/graph/graph.js +4 -1
- package/dataflow/graph/quads.js +4 -4
- package/dataflow/info.js +1 -1
- package/dataflow/internal/linker.d.ts +2 -0
- package/dataflow/internal/linker.js +18 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +3 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +68 -21
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +1 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +4 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +5 -18
- package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +1 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +4 -5
- package/dataflow/internal/process/functions/call/common.js +4 -3
- package/documentation/doc-util/doc-query.js +6 -2
- package/documentation/doc-util/doc-types.d.ts +7 -2
- package/documentation/doc-util/doc-types.js +20 -4
- package/documentation/print-core-wiki.js +5 -1
- package/documentation/print-dataflow-graph-wiki.js +21 -12
- package/documentation/print-faq-wiki.js +5 -0
- package/documentation/print-interface-wiki.js +2 -0
- package/documentation/print-linter-wiki.js +2 -3
- package/documentation/print-linting-and-testing-wiki.js +4 -0
- package/documentation/print-query-wiki.js +22 -7
- package/documentation/print-readme.js +6 -0
- package/linter/linter-executor.js +25 -17
- package/linter/linter-format.d.ts +10 -1
- package/linter/linter-format.js +8 -0
- package/linter/linter-rules.d.ts +1 -0
- package/linter/rules/absolute-path.js +8 -8
- package/linter/rules/dataframe-access-validation.js +1 -1
- package/linter/rules/file-path-validity.js +8 -11
- package/linter/rules/naming-convention.d.ts +5 -1
- package/linter/rules/naming-convention.js +24 -8
- package/linter/rules/seeded-randomness.js +2 -2
- package/linter/rules/unused-definition.js +1 -1
- package/package.json +20 -15
- package/queries/catalog/call-context-query/call-context-query-executor.d.ts +5 -1
- package/queries/catalog/call-context-query/call-context-query-executor.js +14 -12
- package/queries/catalog/call-context-query/call-context-query-format.d.ts +6 -5
- package/queries/catalog/call-context-query/call-context-query-format.js +1 -1
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +2 -1
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +1 -1
- package/queries/catalog/config-query/config-query-executor.js +7 -1
- package/queries/catalog/config-query/config-query-format.d.ts +7 -0
- package/queries/catalog/config-query/config-query-format.js +72 -1
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +50 -75
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +50 -26
- package/queries/catalog/dependencies-query/dependencies-query-format.js +75 -20
- package/queries/catalog/dependencies-query/function-info/function-info.d.ts +2 -2
- package/queries/catalog/dependencies-query/function-info/visualize-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/visualize-functions.js +13 -0
- package/queries/catalog/happens-before-query/happens-before-query-executor.js +1 -1
- package/queries/catalog/linter-query/linter-query-format.js +4 -0
- package/queries/query-print.d.ts +2 -2
- package/queries/query-print.js +3 -2
- package/queries/query.d.ts +28 -21
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.js +1 -1
- package/r-bridge/retriever.d.ts +14 -2
- package/r-bridge/retriever.js +10 -4
- package/search/flowr-search-builder.d.ts +1 -1
- package/search/flowr-search-builder.js +1 -1
- package/search/flowr-search-filters.d.ts +20 -10
- package/search/flowr-search-filters.js +19 -3
- package/search/search-executor/search-enrichers.d.ts +1 -1
- package/search/search-executor/search-enrichers.js +3 -2
- package/search/search-executor/search-generators.js +1 -1
- package/search/search-executor/search-transformer.js +1 -1
- package/util/formats/adapter-format.d.ts +6 -0
- package/util/formats/adapter-format.js +3 -0
- package/util/formats/adapter.d.ts +16 -0
- package/util/formats/adapter.js +42 -0
- package/util/formats/adapters/r-adapter.d.ts +4 -0
- package/util/formats/adapters/r-adapter.js +7 -0
- package/util/formats/adapters/rmd-adapter.d.ts +26 -0
- package/util/formats/adapters/rmd-adapter.js +91 -0
- package/util/objects.d.ts +11 -0
- package/util/objects.js +26 -0
- package/util/version.js +1 -1
|
@@ -20,7 +20,7 @@ export interface FileFilter<FilterType> {
|
|
|
20
20
|
*/
|
|
21
21
|
readonly includeUndefinedFiles?: boolean;
|
|
22
22
|
}
|
|
23
|
-
export interface DefaultCallContextQueryFormat<RegexType extends
|
|
23
|
+
export interface DefaultCallContextQueryFormat<RegexType extends CallNameTypes> extends BaseQueryFormat {
|
|
24
24
|
readonly type: 'call-context';
|
|
25
25
|
/** Regex regarding the function name, please note that strings will be interpreted as regular expressions too! */
|
|
26
26
|
readonly callName: RegexType;
|
|
@@ -50,13 +50,14 @@ export interface DefaultCallContextQueryFormat<RegexType extends RegExp | string
|
|
|
50
50
|
*/
|
|
51
51
|
readonly fileFilter?: FileFilter<RegexType>;
|
|
52
52
|
}
|
|
53
|
+
export type CallNameTypes = RegExp | string | string[];
|
|
53
54
|
/**
|
|
54
55
|
* Links the current call to the last call of the given kind.
|
|
55
56
|
* This way, you can link a call like `points` to the latest graphics plot etc.
|
|
56
57
|
* For now, this uses the static Control-Flow-Graph produced by flowR as the FD over-approximation is still not stable (see #1005).
|
|
57
58
|
* In short, this means that we are unable to detect origins over function call boundaries but plan on being more precise in the future.
|
|
58
59
|
*/
|
|
59
|
-
export interface LinkToLastCall<CallName extends
|
|
60
|
+
export interface LinkToLastCall<CallName extends CallNameTypes = CallNameTypes> extends BaseQueryFormat {
|
|
60
61
|
readonly type: 'link-to-last-call';
|
|
61
62
|
/** Regex regarding the function name of the last call. Similar to {@link DefaultCallContextQueryFormat#callName}, strings are interpreted as a `RegExp`. */
|
|
62
63
|
readonly callName: CallName;
|
|
@@ -71,10 +72,10 @@ export interface LinkToLastCall<CallName extends RegExp | string = RegExp | stri
|
|
|
71
72
|
*/
|
|
72
73
|
readonly cascadeIf?: (target: DataflowGraphVertexInfo, from: NodeId, graph: DataflowGraph) => CascadeAction;
|
|
73
74
|
}
|
|
74
|
-
export type LinkTo<CallName extends
|
|
75
|
+
export type LinkTo<CallName extends CallNameTypes = CallNameTypes, AttachLinkInfo = NoInfo> = (LinkToLastCall<CallName>) & {
|
|
75
76
|
attachLinkInfo?: AttachLinkInfo;
|
|
76
77
|
};
|
|
77
|
-
export interface SubCallContextQueryFormat<CallName extends
|
|
78
|
+
export interface SubCallContextQueryFormat<CallName extends CallNameTypes = CallNameTypes, AttachLinkInfo = NoInfo> extends DefaultCallContextQueryFormat<CallName> {
|
|
78
79
|
readonly linkTo: LinkTo<CallName, AttachLinkInfo> | LinkTo<CallName, AttachLinkInfo>[];
|
|
79
80
|
}
|
|
80
81
|
export interface CallContextQuerySubKindResult {
|
|
@@ -105,7 +106,7 @@ export type CallContextQueryKindResult = Record<string, {
|
|
|
105
106
|
export interface CallContextQueryResult extends BaseQueryResult {
|
|
106
107
|
readonly kinds: CallContextQueryKindResult;
|
|
107
108
|
}
|
|
108
|
-
export type CallContextQuery<CallName extends
|
|
109
|
+
export type CallContextQuery<CallName extends CallNameTypes = CallNameTypes, AttachLinkInfo = NoInfo> = DefaultCallContextQueryFormat<CallName> | SubCallContextQueryFormat<CallName, AttachLinkInfo>;
|
|
109
110
|
export declare const CallContextQueryDefinition: {
|
|
110
111
|
readonly executor: typeof executeCallContextQueries;
|
|
111
112
|
readonly asciiSummarizer: (formatter: OutputFormatter, processed: PipelineOutput<typeof DEFAULT_DATAFLOW_PIPELINE>, queryResults: BaseQueryResult, result: string[]) => boolean;
|
|
@@ -12,7 +12,7 @@ const query_print_1 = require("../../query-print");
|
|
|
12
12
|
const identify_link_to_last_call_relation_1 = require("./identify-link-to-last-call-relation");
|
|
13
13
|
const CallContextQueryLinkTo = joi_1.default.object({
|
|
14
14
|
type: joi_1.default.string().valid('link-to-last-call').required().description('The type of the linkTo sub-query.'),
|
|
15
|
-
callName: joi_1.default.string().required().description('
|
|
15
|
+
callName: joi_1.default.alternatives(joi_1.default.string(), joi_1.default.array().items(joi_1.default.string())).required().description('Test regarding the function name of the last call. Similar to `callName`, strings are interpreted as a regular expression, and string arrays are checked for containment.'),
|
|
16
16
|
ignoreIf: joi_1.default.function().optional().description('Should we ignore this (source) call? Currently, there is no well working serialization for this.'),
|
|
17
17
|
cascadeIf: joi_1.default.function().optional().description('Should we continue searching after the link was created? Currently, there is no well working serialization for this.'),
|
|
18
18
|
attachLinkInfo: joi_1.default.object().optional().description('Additional information to attach to the link.')
|
|
@@ -5,6 +5,7 @@ import { RType } from '../../../r-bridge/lang-4.x/ast/model/type';
|
|
|
5
5
|
import type { RNodeWithParent } from '../../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
6
6
|
import type { LinkTo } from './call-context-query-format';
|
|
7
7
|
import type { ControlFlowGraph } from '../../../control-flow/control-flow-graph';
|
|
8
|
+
import type { PromotedLinkTo } from './call-context-query-executor';
|
|
8
9
|
export declare enum CallTargets {
|
|
9
10
|
/** call targets a function that is not defined locally in the script (e.g., the call targets a library function) */
|
|
10
11
|
OnlyGlobal = "global",
|
|
@@ -24,4 +25,4 @@ export declare function getValueOfArgument<Types extends readonly RType[] = read
|
|
|
24
25
|
}, additionalAllowedTypes?: Types): (RNodeWithParent & {
|
|
25
26
|
type: Types[number];
|
|
26
27
|
}) | undefined;
|
|
27
|
-
export declare function identifyLinkToLastCallRelation(from: NodeId, cfg: ControlFlowGraph, graph: DataflowGraph, { callName, ignoreIf, cascadeIf }: LinkTo<RegExp>): NodeId[];
|
|
28
|
+
export declare function identifyLinkToLastCallRelation(from: NodeId, cfg: ControlFlowGraph, graph: DataflowGraph, { callName, ignoreIf, cascadeIf }: LinkTo<RegExp> | PromotedLinkTo): NodeId[];
|
|
@@ -121,7 +121,7 @@ function identifyLinkToLastCallRelation(from, cfg, graph, { callName, ignoreIf,
|
|
|
121
121
|
if (vertex === undefined || vertex.tag !== vertex_1.VertexType.FunctionCall) {
|
|
122
122
|
return;
|
|
123
123
|
}
|
|
124
|
-
if (callName.test(vertex.name)) {
|
|
124
|
+
if (callName instanceof RegExp ? callName.test(vertex.name) : callName.has(vertex.name)) {
|
|
125
125
|
const act = cascadeIf ? cascadeIf(vertex, from, graph) : cascade_action_1.CascadeAction.Stop;
|
|
126
126
|
if (act === cascade_action_1.CascadeAction.Skip) {
|
|
127
127
|
return;
|
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.executeConfigQuery = executeConfigQuery;
|
|
4
4
|
const log_1 = require("../../../util/log");
|
|
5
|
+
const assert_1 = require("../../../util/assert");
|
|
6
|
+
const objects_1 = require("../../../util/objects");
|
|
5
7
|
function executeConfigQuery({ config }, queries) {
|
|
6
8
|
if (queries.length !== 1) {
|
|
7
|
-
log_1.log.warn('Config query expects only up to one query, but got', queries.length);
|
|
9
|
+
log_1.log.warn('Config query usually expects only up to one query, but got', queries.length);
|
|
10
|
+
}
|
|
11
|
+
const updates = queries.map(q => q.update).filter(assert_1.isNotUndefined);
|
|
12
|
+
for (const update of updates) {
|
|
13
|
+
(0, objects_1.deepMergeObjectInPlace)(config, update);
|
|
8
14
|
}
|
|
9
15
|
return {
|
|
10
16
|
'.meta': {
|
|
@@ -3,15 +3,22 @@ import { executeConfigQuery } from './config-query-executor';
|
|
|
3
3
|
import { type OutputFormatter } from '../../../util/text/ansi';
|
|
4
4
|
import Joi from 'joi';
|
|
5
5
|
import type { FlowrConfigOptions } from '../../../config';
|
|
6
|
+
import type { DeepPartial } from 'ts-essentials';
|
|
6
7
|
export interface ConfigQuery extends BaseQueryFormat {
|
|
7
8
|
readonly type: 'config';
|
|
9
|
+
readonly update?: DeepPartial<FlowrConfigOptions>;
|
|
8
10
|
}
|
|
9
11
|
export interface ConfigQueryResult extends BaseQueryResult {
|
|
10
12
|
readonly config: FlowrConfigOptions;
|
|
11
13
|
}
|
|
14
|
+
declare function configReplCompleter(partialLine: readonly string[], config: FlowrConfigOptions): string[];
|
|
15
|
+
declare function configQueryLineParser(line: readonly string[], _config: FlowrConfigOptions): [ConfigQuery];
|
|
12
16
|
export declare const ConfigQueryDefinition: {
|
|
13
17
|
readonly executor: typeof executeConfigQuery;
|
|
14
18
|
readonly asciiSummarizer: (formatter: OutputFormatter, _processed: unknown, queryResults: BaseQueryResult, result: string[]) => boolean;
|
|
19
|
+
readonly completer: typeof configReplCompleter;
|
|
20
|
+
readonly fromLine: typeof configQueryLineParser;
|
|
15
21
|
readonly schema: Joi.ObjectSchema<any>;
|
|
16
22
|
readonly flattenInvolvedNodes: () => never[];
|
|
17
23
|
};
|
|
24
|
+
export {};
|
|
@@ -9,6 +9,74 @@ const ansi_1 = require("../../../util/text/ansi");
|
|
|
9
9
|
const time_1 = require("../../../util/text/time");
|
|
10
10
|
const joi_1 = __importDefault(require("joi"));
|
|
11
11
|
const json_1 = require("../../../util/json");
|
|
12
|
+
function configReplCompleter(partialLine, config) {
|
|
13
|
+
if (partialLine.length === 0) {
|
|
14
|
+
// update specific fields
|
|
15
|
+
return ['+'];
|
|
16
|
+
}
|
|
17
|
+
else if (partialLine.length === 1 && partialLine[0].startsWith('+')) {
|
|
18
|
+
const path = partialLine[0].slice(1).split('.').filter(p => p.length > 0);
|
|
19
|
+
const fullPath = path.slice();
|
|
20
|
+
const lastPath = partialLine[0].endsWith('.') ? '' : path.pop() ?? '';
|
|
21
|
+
if (lastPath.endsWith('=')) {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
const subConfig = path.reduce((obj, key) => (obj && obj[key] !== undefined && typeof obj[key] === 'object') ? obj[key] : obj, config);
|
|
25
|
+
if (subConfig && !(subConfig[lastPath] !== undefined && typeof subConfig[lastPath] !== 'object')) {
|
|
26
|
+
const have = Object.keys(subConfig)
|
|
27
|
+
.filter(k => k.startsWith(lastPath) && k !== lastPath)
|
|
28
|
+
.map(k => `${partialLine[0].slice(0, 1)}${[...path, k].join('.')}`);
|
|
29
|
+
if (have.length > 0) {
|
|
30
|
+
return have;
|
|
31
|
+
}
|
|
32
|
+
else if (lastPath.length > 0) {
|
|
33
|
+
return [`${partialLine[0].slice(0, 1)}${fullPath.join('.')}.`];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return [`${partialLine[0].slice(0, 1)}${fullPath.join('.')}=`];
|
|
37
|
+
}
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
function configQueryLineParser(line, _config) {
|
|
41
|
+
if (line.length > 0 && line[0].startsWith('+')) {
|
|
42
|
+
const [pathPart, ...valueParts] = line[0].slice(1).split('=');
|
|
43
|
+
// build the update object
|
|
44
|
+
const path = pathPart.split('.').filter(p => p.length > 0);
|
|
45
|
+
if (path.length === 0 || valueParts.length !== 1) {
|
|
46
|
+
console.error('Invalid config update syntax, must be of the form +path.to.field=value');
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const update = {};
|
|
50
|
+
const value = valueParts[0];
|
|
51
|
+
let current = update;
|
|
52
|
+
for (let i = 0; i < path.length; i++) {
|
|
53
|
+
const key = path[i];
|
|
54
|
+
if (i === path.length - 1) {
|
|
55
|
+
// last part, set the value
|
|
56
|
+
// try to parse as JSON first
|
|
57
|
+
try {
|
|
58
|
+
current[key] = JSON.parse(value);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// fallback to string
|
|
62
|
+
current[key] = value;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
current[key] = {};
|
|
67
|
+
current = current[key];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return [{
|
|
71
|
+
type: 'config',
|
|
72
|
+
update
|
|
73
|
+
}];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return [{
|
|
77
|
+
type: 'config'
|
|
78
|
+
}];
|
|
79
|
+
}
|
|
12
80
|
exports.ConfigQueryDefinition = {
|
|
13
81
|
executor: config_query_executor_1.executeConfigQuery,
|
|
14
82
|
asciiSummarizer: (formatter, _processed, queryResults, result) => {
|
|
@@ -17,9 +85,12 @@ exports.ConfigQueryDefinition = {
|
|
|
17
85
|
result.push(` ╰ Config:\n${JSON.stringify(out.config, json_1.jsonReplacer, 4)}`);
|
|
18
86
|
return true;
|
|
19
87
|
},
|
|
88
|
+
completer: configReplCompleter,
|
|
89
|
+
fromLine: configQueryLineParser,
|
|
20
90
|
schema: joi_1.default.object({
|
|
21
91
|
type: joi_1.default.string().valid('config').required().description('The type of the query.'),
|
|
22
|
-
|
|
92
|
+
update: joi_1.default.object().optional().description('An optional partial configuration to update the current configuration with before returning it. Only the provided fields will be updated, all other fields will remain unchanged.')
|
|
93
|
+
}).description('The config query retrieves the current configuration of the flowR instance and optionally also updates it.'),
|
|
23
94
|
flattenInvolvedNodes: () => []
|
|
24
95
|
};
|
|
25
96
|
//# sourceMappingURL=config-query-format.js.map
|
|
@@ -6,29 +6,11 @@ const dependencies_query_format_1 = require("./dependencies-query-format");
|
|
|
6
6
|
const vertex_1 = require("../../../dataflow/graph/vertex");
|
|
7
7
|
const log_1 = require("../../../util/log");
|
|
8
8
|
const type_1 = require("../../../r-bridge/lang-4.x/ast/model/type");
|
|
9
|
-
const visitor_1 = require("../../../r-bridge/lang-4.x/ast/model/processing/visitor");
|
|
10
9
|
const objects_1 = require("../../../util/objects");
|
|
11
|
-
const library_functions_1 = require("./function-info/library-functions");
|
|
12
|
-
const source_functions_1 = require("./function-info/source-functions");
|
|
13
|
-
const read_functions_1 = require("./function-info/read-functions");
|
|
14
|
-
const write_functions_1 = require("./function-info/write-functions");
|
|
15
10
|
const function_info_1 = require("./function-info/function-info");
|
|
16
11
|
const identify_link_to_last_call_relation_1 = require("../call-context-query/identify-link-to-last-call-relation");
|
|
17
12
|
const resolve_argument_1 = require("../../../dataflow/eval/resolve/resolve-argument");
|
|
18
13
|
const assert_1 = require("../../../util/assert");
|
|
19
|
-
function collectNamespaceAccesses(data, libraries) {
|
|
20
|
-
/* for libraries, we have to additionally track all uses of `::` and `:::`, for this we currently simply traverse all uses */
|
|
21
|
-
(0, visitor_1.visitAst)(data.ast.ast, n => {
|
|
22
|
-
if (n.type === type_1.RType.Symbol && n.namespace) {
|
|
23
|
-
/* we should improve the identification of ':::' */
|
|
24
|
-
libraries.push({
|
|
25
|
-
nodeId: n.info.id,
|
|
26
|
-
functionName: (n.info.fullLexeme ?? n.lexeme).includes(':::') ? ':::' : '::',
|
|
27
|
-
libraryName: n.namespace,
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
14
|
function executeDependenciesQuery(data, queries) {
|
|
33
15
|
if (queries.length !== 1) {
|
|
34
16
|
log_1.log.warn('Dependencies query expects only up to one query, but got ', queries.length, 'only using the first query');
|
|
@@ -36,64 +18,28 @@ function executeDependenciesQuery(data, queries) {
|
|
|
36
18
|
const now = Date.now();
|
|
37
19
|
const [query] = queries;
|
|
38
20
|
const ignoreDefault = query.ignoreDefaultFunctions ?? false;
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
const readFunctions = getFunctionsToCheck(query.readFunctions, ignoreDefault, read_functions_1.ReadFunctions);
|
|
42
|
-
const writeFunctions = getFunctionsToCheck(query.writeFunctions, ignoreDefault, write_functions_1.WriteFunctions);
|
|
43
|
-
const numberOfFunctions = libraryFunctions.length + sourceFunctions.length + readFunctions.length + writeFunctions.length;
|
|
44
|
-
const results = numberOfFunctions === 0 ? { kinds: {}, '.meta': { timing: 0 } } : (0, query_1.executeQueriesOfSameType)(data, [
|
|
45
|
-
makeCallContextQuery(libraryFunctions, 'library'),
|
|
46
|
-
makeCallContextQuery(sourceFunctions, 'source'),
|
|
47
|
-
makeCallContextQuery(readFunctions, 'read'),
|
|
48
|
-
makeCallContextQuery(writeFunctions, 'write')
|
|
49
|
-
].flat());
|
|
50
|
-
function getLexeme(argument, id) {
|
|
51
|
-
if ((argument && argument !== dependencies_query_format_1.Unknown) || !id) {
|
|
52
|
-
return undefined;
|
|
53
|
-
}
|
|
54
|
-
let get = data.ast.idMap.get(id);
|
|
55
|
-
if (get?.type === type_1.RType.Argument) {
|
|
56
|
-
get = get.value;
|
|
57
|
-
}
|
|
58
|
-
return get?.info.fullLexeme ?? get?.lexeme;
|
|
59
|
-
}
|
|
60
|
-
const libraries = getResults(data, results, 'library', libraryFunctions, (id, vertex, argId, value, linkedIds) => ({
|
|
61
|
-
nodeId: id,
|
|
62
|
-
functionName: vertex.name,
|
|
63
|
-
lexemeOfArgument: getLexeme(value, argId),
|
|
64
|
-
libraryName: value ?? dependencies_query_format_1.Unknown,
|
|
65
|
-
linkedIds: linkedIds?.length ? linkedIds : undefined
|
|
21
|
+
const functions = new Map(Object.entries(dependencies_query_format_1.DefaultDependencyCategories).map(([c, v]) => {
|
|
22
|
+
return [c, getFunctionsToCheck(query[`${c}Functions`], c, query.enabledCategories, ignoreDefault, v.functions)];
|
|
66
23
|
}));
|
|
67
|
-
if (
|
|
68
|
-
|
|
24
|
+
if (query.additionalCategories !== undefined) {
|
|
25
|
+
for (const [category, value] of Object.entries(query.additionalCategories)) {
|
|
26
|
+
// custom categories only use the "functions" collection and do not allow specifying additional functions in the object itself, so we "undefined" a lot here
|
|
27
|
+
functions.set(category, getFunctionsToCheck(undefined, category, undefined, false, value.functions));
|
|
28
|
+
}
|
|
69
29
|
}
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const readData = getResults(data, results, 'read', readFunctions, (id, vertex, argId, value, linkedIds) => ({
|
|
78
|
-
nodeId: id,
|
|
79
|
-
functionName: vertex.name,
|
|
80
|
-
source: value ?? dependencies_query_format_1.Unknown,
|
|
81
|
-
lexemeOfArgument: getLexeme(value, argId),
|
|
82
|
-
linkedIds: linkedIds?.length ? linkedIds : undefined
|
|
83
|
-
}));
|
|
84
|
-
const writtenData = getResults(data, results, 'write', writeFunctions, (id, vertex, argId, value, linkedIds) => ({
|
|
85
|
-
nodeId: id,
|
|
86
|
-
functionName: vertex.name,
|
|
87
|
-
// write functions that don't have argIndex are assumed to write to stdout
|
|
88
|
-
destination: value ?? 'stdout',
|
|
89
|
-
lexemeOfArgument: getLexeme(value, argId),
|
|
90
|
-
linkedIds: linkedIds?.length ? linkedIds : undefined
|
|
30
|
+
const queryResults = functions.values().toArray().flat().length === 0 ? { kinds: {}, '.meta': { timing: 0 } } :
|
|
31
|
+
(0, query_1.executeQueriesOfSameType)(data, functions.entries().map(([c, f]) => makeCallContextQuery(f, c)).toArray().flat());
|
|
32
|
+
const results = Object.fromEntries(functions.entries().map(([c, f]) => {
|
|
33
|
+
const results = getResults(queries, data, queryResults, c, f);
|
|
34
|
+
// only default categories allow additional analyses, so we null coalese here!
|
|
35
|
+
dependencies_query_format_1.DefaultDependencyCategories[c]?.additionalAnalysis?.(data, ignoreDefault, f, queryResults, results);
|
|
36
|
+
return [c, results];
|
|
91
37
|
}));
|
|
92
38
|
return {
|
|
93
39
|
'.meta': {
|
|
94
40
|
timing: Date.now() - now
|
|
95
41
|
},
|
|
96
|
-
|
|
42
|
+
...results
|
|
97
43
|
};
|
|
98
44
|
}
|
|
99
45
|
function makeCallContextQuery(functions, kind) {
|
|
@@ -116,19 +62,28 @@ function dropInfoOnLinkedIds(linkedIds) {
|
|
|
116
62
|
}
|
|
117
63
|
const readOnlyModes = new Set(['r', 'rt', 'rb']);
|
|
118
64
|
const writeOnlyModes = new Set(['w', 'wt', 'wb', 'a', 'at', 'ab']);
|
|
119
|
-
function getResults(data, results, kind, functions
|
|
65
|
+
function getResults(queries, data, results, kind, functions) {
|
|
66
|
+
const defaultValue = (0, dependencies_query_format_1.getAllCategories)(queries)[kind].defaultValue;
|
|
67
|
+
const functionMap = new Map(functions.map(f => [f.name, f]));
|
|
120
68
|
const kindEntries = Object.entries(results?.kinds[kind]?.subkinds ?? {});
|
|
121
69
|
return kindEntries.flatMap(([name, results]) => results.flatMap(({ id, linkedIds }) => {
|
|
122
70
|
const vertex = data.dataflow.graph.getVertex(id);
|
|
123
|
-
const info =
|
|
71
|
+
const info = functionMap.get(name);
|
|
124
72
|
const args = (0, resolve_argument_1.getArgumentStringValue)(data.config.solver.variables, data.dataflow.graph, vertex, info.argIdx, info.argName, info.resolveValue);
|
|
125
73
|
const linkedArgs = collectValuesFromLinks(args, data, linkedIds);
|
|
74
|
+
const linked = dropInfoOnLinkedIds(linkedIds);
|
|
126
75
|
const foundValues = linkedArgs ?? args;
|
|
127
76
|
if (!foundValues) {
|
|
128
77
|
if (info.ignoreIf === 'arg-missing') {
|
|
129
78
|
return [];
|
|
130
79
|
}
|
|
131
|
-
const record = (0, objects_1.compactRecord)(
|
|
80
|
+
const record = (0, objects_1.compactRecord)({
|
|
81
|
+
nodeId: id,
|
|
82
|
+
functionName: vertex.name,
|
|
83
|
+
lexemeOfArgument: undefined,
|
|
84
|
+
linkedIds: linked?.length ? linked : undefined,
|
|
85
|
+
value: defaultValue
|
|
86
|
+
});
|
|
132
87
|
return record ? [record] : [];
|
|
133
88
|
}
|
|
134
89
|
else if (info.ignoreIf === 'mode-only-read' || info.ignoreIf === 'mode-only-write') {
|
|
@@ -136,7 +91,7 @@ function getResults(data, results, kind, functions, makeInfo) {
|
|
|
136
91
|
const margs = info.additionalArgs?.mode;
|
|
137
92
|
(0, assert_1.guard)(margs, 'Need additional argument mode when checking for mode');
|
|
138
93
|
const modeArgs = (0, resolve_argument_1.getArgumentStringValue)(data.config.solver.variables, data.dataflow.graph, vertex, margs.argIdx, margs.argName, margs.resolveValue);
|
|
139
|
-
const modeValues =
|
|
94
|
+
const modeValues = modeArgs?.values().flatMap(v => [...v]) ?? [];
|
|
140
95
|
if (info.ignoreIf === 'mode-only-read' && modeValues.every(m => m && readOnlyModes.has(m))) {
|
|
141
96
|
// all modes are read-only, so we can ignore this
|
|
142
97
|
return [];
|
|
@@ -149,7 +104,13 @@ function getResults(data, results, kind, functions, makeInfo) {
|
|
|
149
104
|
const results = [];
|
|
150
105
|
for (const [arg, values] of foundValues.entries()) {
|
|
151
106
|
for (const value of values) {
|
|
152
|
-
const result = (0, objects_1.compactRecord)(
|
|
107
|
+
const result = (0, objects_1.compactRecord)({
|
|
108
|
+
nodeId: id,
|
|
109
|
+
functionName: vertex.name,
|
|
110
|
+
lexemeOfArgument: getLexeme(value, arg),
|
|
111
|
+
linkedIds: linked?.length ? linked : undefined,
|
|
112
|
+
value: value ?? defaultValue
|
|
113
|
+
});
|
|
153
114
|
if (result) {
|
|
154
115
|
results.push(result);
|
|
155
116
|
}
|
|
@@ -157,6 +118,16 @@ function getResults(data, results, kind, functions, makeInfo) {
|
|
|
157
118
|
}
|
|
158
119
|
return results;
|
|
159
120
|
})) ?? [];
|
|
121
|
+
function getLexeme(argument, id) {
|
|
122
|
+
if ((argument && argument !== dependencies_query_format_1.Unknown) || !id) {
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
let get = data.ast.idMap.get(id);
|
|
126
|
+
if (get?.type === type_1.RType.Argument) {
|
|
127
|
+
get = get.value;
|
|
128
|
+
}
|
|
129
|
+
return get?.info.fullLexeme ?? get?.lexeme;
|
|
130
|
+
}
|
|
160
131
|
}
|
|
161
132
|
function collectValuesFromLinks(args, data, linkedIds) {
|
|
162
133
|
if (!linkedIds || linkedIds.length === 0) {
|
|
@@ -192,7 +163,11 @@ function collectValuesFromLinks(args, data, linkedIds) {
|
|
|
192
163
|
}
|
|
193
164
|
return map.size ? map : undefined;
|
|
194
165
|
}
|
|
195
|
-
function getFunctionsToCheck(customFunctions, ignoreDefaultFunctions, defaultFunctions) {
|
|
166
|
+
function getFunctionsToCheck(customFunctions, functionFlag, enabled, ignoreDefaultFunctions, defaultFunctions) {
|
|
167
|
+
// "If unset or empty, all function types are searched for."
|
|
168
|
+
if (enabled?.length && enabled.indexOf(functionFlag) < 0) {
|
|
169
|
+
return [];
|
|
170
|
+
}
|
|
196
171
|
let functions = ignoreDefaultFunctions ? [] : [...defaultFunctions];
|
|
197
172
|
if (customFunctions) {
|
|
198
173
|
functions = functions.concat(customFunctions);
|
|
@@ -1,42 +1,66 @@
|
|
|
1
|
-
import type { BaseQueryFormat, BaseQueryResult } from '../../base-query-format';
|
|
1
|
+
import type { BaseQueryFormat, BaseQueryResult, BasicQueryData } from '../../base-query-format';
|
|
2
2
|
import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
3
3
|
import Joi from 'joi';
|
|
4
4
|
import { executeDependenciesQuery } from './dependencies-query-executor';
|
|
5
5
|
import type { FunctionInfo } from './function-info/function-info';
|
|
6
|
+
import type { CallContextQueryResult } from '../call-context-query/call-context-query-format';
|
|
6
7
|
export declare const Unknown = "unknown";
|
|
7
|
-
export interface
|
|
8
|
+
export interface DependencyCategorySettings {
|
|
9
|
+
queryDisplayName?: string;
|
|
10
|
+
functions: FunctionInfo[];
|
|
11
|
+
defaultValue?: string;
|
|
12
|
+
additionalAnalysis?: (data: BasicQueryData, ignoreDefault: boolean, functions: FunctionInfo[], queryResults: CallContextQueryResult, result: DependencyInfo[]) => void;
|
|
13
|
+
}
|
|
14
|
+
export declare const DefaultDependencyCategories: {
|
|
15
|
+
readonly library: {
|
|
16
|
+
readonly queryDisplayName: "Libraries";
|
|
17
|
+
readonly functions: FunctionInfo[];
|
|
18
|
+
readonly defaultValue: "unknown";
|
|
19
|
+
readonly additionalAnalysis: (data: BasicQueryData, ignoreDefault: boolean, _functions: FunctionInfo[], _queryResults: CallContextQueryResult, result: DependencyInfo[]) => void;
|
|
20
|
+
};
|
|
21
|
+
readonly source: {
|
|
22
|
+
readonly queryDisplayName: "Sourced Files";
|
|
23
|
+
readonly functions: FunctionInfo[];
|
|
24
|
+
readonly defaultValue: "unknown";
|
|
25
|
+
};
|
|
26
|
+
readonly read: {
|
|
27
|
+
readonly queryDisplayName: "Read Data";
|
|
28
|
+
readonly functions: FunctionInfo[];
|
|
29
|
+
readonly defaultValue: "unknown";
|
|
30
|
+
};
|
|
31
|
+
readonly write: {
|
|
32
|
+
readonly queryDisplayName: "Written Data";
|
|
33
|
+
readonly functions: FunctionInfo[];
|
|
34
|
+
readonly defaultValue: "stdout";
|
|
35
|
+
};
|
|
36
|
+
readonly visualize: {
|
|
37
|
+
readonly queryDisplayName: "Visualizations";
|
|
38
|
+
readonly functions: FunctionInfo[];
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
export type DefaultDependencyCategoryName = keyof typeof DefaultDependencyCategories;
|
|
42
|
+
export type DependencyCategoryName = DefaultDependencyCategoryName | string;
|
|
43
|
+
export interface DependenciesQuery extends BaseQueryFormat, Partial<Record<`${DefaultDependencyCategoryName}Functions`, FunctionInfo[]>> {
|
|
8
44
|
readonly type: 'dependencies';
|
|
45
|
+
readonly enabledCategories?: DependencyCategoryName[];
|
|
9
46
|
readonly ignoreDefaultFunctions?: boolean;
|
|
10
|
-
readonly
|
|
11
|
-
readonly sourceFunctions?: FunctionInfo[];
|
|
12
|
-
readonly readFunctions?: FunctionInfo[];
|
|
13
|
-
readonly writeFunctions?: FunctionInfo[];
|
|
14
|
-
}
|
|
15
|
-
export interface DependenciesQueryResult extends BaseQueryResult {
|
|
16
|
-
libraries: LibraryInfo[];
|
|
17
|
-
sourcedFiles: SourceInfo[];
|
|
18
|
-
readData: ReadInfo[];
|
|
19
|
-
writtenData: WriteInfo[];
|
|
47
|
+
readonly additionalCategories?: Record<string, Omit<DependencyCategorySettings, 'additionalAnalysis'>>;
|
|
20
48
|
}
|
|
49
|
+
export type DependenciesQueryResult = BaseQueryResult & {
|
|
50
|
+
[C in DefaultDependencyCategoryName]: DependencyInfo[];
|
|
51
|
+
} & {
|
|
52
|
+
[S in string]?: DependencyInfo[];
|
|
53
|
+
};
|
|
21
54
|
export interface DependencyInfo extends Record<string, unknown> {
|
|
22
55
|
nodeId: NodeId;
|
|
23
56
|
functionName: string;
|
|
24
57
|
linkedIds?: readonly NodeId[];
|
|
25
58
|
/** the lexeme is presented whenever the specific info is of {@link Unknown} */
|
|
26
59
|
lexemeOfArgument?: string;
|
|
60
|
+
/** The library name, file, source, destination etc. being sourced, read from, or written to. */
|
|
61
|
+
value?: string;
|
|
27
62
|
}
|
|
28
|
-
export
|
|
29
|
-
libraryName: 'unknown' | string;
|
|
30
|
-
});
|
|
31
|
-
export type SourceInfo = (DependencyInfo & {
|
|
32
|
-
file: string;
|
|
33
|
-
});
|
|
34
|
-
export type ReadInfo = (DependencyInfo & {
|
|
35
|
-
source: string;
|
|
36
|
-
});
|
|
37
|
-
export type WriteInfo = (DependencyInfo & {
|
|
38
|
-
destination: 'stdout' | string;
|
|
39
|
-
});
|
|
63
|
+
export declare function getAllCategories(queries: readonly DependenciesQuery[]): Record<DependencyCategoryName, DependencyCategorySettings>;
|
|
40
64
|
export declare const DependenciesQueryDefinition: {
|
|
41
65
|
readonly executor: typeof executeDependenciesQuery;
|
|
42
66
|
readonly asciiSummarizer: (formatter: import("../../../util/text/ansi").OutputFormatter, _processed: import("../../../core/steps/pipeline/pipeline").PipelineOutput<import("../../../core/steps/pipeline/pipeline").Pipeline<{
|
|
@@ -92,7 +116,7 @@ export declare const DependenciesQueryDefinition: {
|
|
|
92
116
|
readonly 4: typeof import("../../../core/print/dataflow-printer").dataflowGraphToMermaidUrl;
|
|
93
117
|
};
|
|
94
118
|
readonly dependencies: readonly ["normalize"];
|
|
95
|
-
}>>, queryResults: BaseQueryResult, result: string[]) => true;
|
|
119
|
+
}>>, queryResults: BaseQueryResult, result: string[], queries: readonly import("../../query").Query[]) => true;
|
|
96
120
|
readonly schema: Joi.ObjectSchema<any>;
|
|
97
|
-
readonly flattenInvolvedNodes: (queryResults: BaseQueryResult) => NodeId[];
|
|
121
|
+
readonly flattenInvolvedNodes: (queryResults: BaseQueryResult, query: readonly import("../../query").Query[]) => NodeId[];
|
|
98
122
|
};
|
|
@@ -3,13 +3,62 @@ 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.DependenciesQueryDefinition = exports.Unknown = void 0;
|
|
6
|
+
exports.DependenciesQueryDefinition = exports.DefaultDependencyCategories = exports.Unknown = void 0;
|
|
7
|
+
exports.getAllCategories = getAllCategories;
|
|
7
8
|
const ansi_1 = require("../../../util/text/ansi");
|
|
8
9
|
const time_1 = require("../../../util/text/time");
|
|
9
10
|
const joi_1 = __importDefault(require("joi"));
|
|
10
11
|
const dependencies_query_executor_1 = require("./dependencies-query-executor");
|
|
12
|
+
const library_functions_1 = require("./function-info/library-functions");
|
|
13
|
+
const source_functions_1 = require("./function-info/source-functions");
|
|
14
|
+
const read_functions_1 = require("./function-info/read-functions");
|
|
15
|
+
const write_functions_1 = require("./function-info/write-functions");
|
|
16
|
+
const visualize_functions_1 = require("./function-info/visualize-functions");
|
|
17
|
+
const visitor_1 = require("../../../r-bridge/lang-4.x/ast/model/processing/visitor");
|
|
18
|
+
const type_1 = require("../../../r-bridge/lang-4.x/ast/model/type");
|
|
11
19
|
exports.Unknown = 'unknown';
|
|
12
|
-
|
|
20
|
+
exports.DefaultDependencyCategories = {
|
|
21
|
+
'library': {
|
|
22
|
+
queryDisplayName: 'Libraries',
|
|
23
|
+
functions: library_functions_1.LibraryFunctions,
|
|
24
|
+
defaultValue: exports.Unknown,
|
|
25
|
+
/* for libraries, we have to additionally track all uses of `::` and `:::`, for this we currently simply traverse all uses */
|
|
26
|
+
additionalAnalysis: (data, ignoreDefault, _functions, _queryResults, result) => {
|
|
27
|
+
if (!ignoreDefault) {
|
|
28
|
+
(0, visitor_1.visitAst)(data.ast.ast, n => {
|
|
29
|
+
if (n.type === type_1.RType.Symbol && n.namespace) {
|
|
30
|
+
/* we should improve the identification of ':::' */
|
|
31
|
+
result.push({
|
|
32
|
+
nodeId: n.info.id,
|
|
33
|
+
functionName: (n.info.fullLexeme ?? n.lexeme).includes(':::') ? ':::' : '::',
|
|
34
|
+
value: n.namespace,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
'source': {
|
|
42
|
+
queryDisplayName: 'Sourced Files',
|
|
43
|
+
functions: source_functions_1.SourceFunctions,
|
|
44
|
+
defaultValue: exports.Unknown
|
|
45
|
+
},
|
|
46
|
+
'read': {
|
|
47
|
+
queryDisplayName: 'Read Data',
|
|
48
|
+
functions: read_functions_1.ReadFunctions,
|
|
49
|
+
defaultValue: exports.Unknown
|
|
50
|
+
},
|
|
51
|
+
'write': {
|
|
52
|
+
queryDisplayName: 'Written Data',
|
|
53
|
+
functions: write_functions_1.WriteFunctions,
|
|
54
|
+
defaultValue: 'stdout'
|
|
55
|
+
},
|
|
56
|
+
'visualize': {
|
|
57
|
+
queryDisplayName: 'Visualizations',
|
|
58
|
+
functions: visualize_functions_1.VisualizeFunctions
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
function printResultSection(title, infos, result) {
|
|
13
62
|
if (infos.length <= 0) {
|
|
14
63
|
return;
|
|
15
64
|
}
|
|
@@ -26,9 +75,18 @@ function printResultSection(title, infos, result, sectionSpecifics) {
|
|
|
26
75
|
}, new Map());
|
|
27
76
|
for (const [functionName, infos] of grouped) {
|
|
28
77
|
result.push(` ╰ \`${functionName}\``);
|
|
29
|
-
result.push(infos.map(i => ` ╰ Node Id: ${i.nodeId}
|
|
78
|
+
result.push(infos.map(i => ` ╰ Node Id: ${i.nodeId}${i.value !== undefined ? `, \`${i.value}\`` : ''}`).join('\n'));
|
|
30
79
|
}
|
|
31
80
|
}
|
|
81
|
+
function getAllCategories(queries) {
|
|
82
|
+
let categories = exports.DefaultDependencyCategories;
|
|
83
|
+
for (const query of queries) {
|
|
84
|
+
if (query.additionalCategories) {
|
|
85
|
+
categories = { ...categories, ...query.additionalCategories };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return categories;
|
|
89
|
+
}
|
|
32
90
|
const functionInfoSchema = joi_1.default.array().items(joi_1.default.object({
|
|
33
91
|
name: joi_1.default.string().required().description('The name of the library function.'),
|
|
34
92
|
package: joi_1.default.string().optional().description('The package name of the library function'),
|
|
@@ -37,31 +95,28 @@ const functionInfoSchema = joi_1.default.array().items(joi_1.default.object({
|
|
|
37
95
|
})).optional();
|
|
38
96
|
exports.DependenciesQueryDefinition = {
|
|
39
97
|
executor: dependencies_query_executor_1.executeDependenciesQuery,
|
|
40
|
-
asciiSummarizer: (formatter, _processed, queryResults, result) => {
|
|
98
|
+
asciiSummarizer: (formatter, _processed, queryResults, result, queries) => {
|
|
41
99
|
const out = queryResults;
|
|
42
100
|
result.push(`Query: ${(0, ansi_1.bold)('dependencies', formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
printResultSection('Written Data', out.writtenData, result, w => `\`${w.destination}\``);
|
|
101
|
+
for (const [category, value] of Object.entries(getAllCategories(queries))) {
|
|
102
|
+
printResultSection(value.queryDisplayName ?? category, out[category] ?? [], result);
|
|
103
|
+
}
|
|
47
104
|
return true;
|
|
48
105
|
},
|
|
49
106
|
schema: joi_1.default.object({
|
|
50
107
|
type: joi_1.default.string().valid('dependencies').required().description('The type of the query.'),
|
|
51
|
-
ignoreDefaultFunctions: joi_1.default.boolean().optional().description('Should the set of functions that are detected by default be ignored/skipped?'),
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
108
|
+
ignoreDefaultFunctions: joi_1.default.boolean().optional().description('Should the set of functions that are detected by default be ignored/skipped? Defaults to false.'),
|
|
109
|
+
...Object.fromEntries(Object.keys(exports.DefaultDependencyCategories).map(c => [`${c}Functions`, functionInfoSchema.description(`The set of ${c} functions to search for.`)])),
|
|
110
|
+
enabledCategories: joi_1.default.array().optional().items(joi_1.default.string().valid(...Object.keys(exports.DefaultDependencyCategories))).description('A set of flags that determines what types of dependencies are searched for. If unset or empty, all dependency types are searched for.'),
|
|
111
|
+
additionalCategories: joi_1.default.object().allow(joi_1.default.object({
|
|
112
|
+
queryDisplayName: joi_1.default.string().description('The display name in the query result.'),
|
|
113
|
+
functions: functionInfoSchema.description('The functions that this additional category should search for.'),
|
|
114
|
+
defaultValue: joi_1.default.string().description('The default value to return when there is no value to gather from the function information.').optional()
|
|
115
|
+
})).description('A set of additional, user-supplied dependency categories, whose results will be included in the query return value.').optional()
|
|
56
116
|
}).description('The dependencies query retrieves and returns the set of all dependencies in the dataflow graph, which includes libraries, sourced files, read data, and written data.'),
|
|
57
|
-
flattenInvolvedNodes: (queryResults) => {
|
|
117
|
+
flattenInvolvedNodes: (queryResults, query) => {
|
|
58
118
|
const out = queryResults;
|
|
59
|
-
return [
|
|
60
|
-
...out.libraries.map(library => library.nodeId),
|
|
61
|
-
...out.sourcedFiles.map(sourced => sourced.nodeId),
|
|
62
|
-
...out.readData.map(read => read.nodeId),
|
|
63
|
-
...out.writtenData.map(write => write.nodeId)
|
|
64
|
-
];
|
|
119
|
+
return Object.keys(getAllCategories(query)).flatMap(c => out[c] ?? []).map(o => o.nodeId);
|
|
65
120
|
}
|
|
66
121
|
};
|
|
67
122
|
//# sourceMappingURL=dependencies-query-format.js.map
|