@eagleoutice/flowr 2.2.16 → 2.4.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 -20
- package/abstract-interpretation/data-frame/absint-info.d.ts +109 -0
- package/abstract-interpretation/data-frame/absint-info.js +31 -0
- package/abstract-interpretation/data-frame/absint-visitor.d.ts +58 -0
- package/abstract-interpretation/data-frame/absint-visitor.js +171 -0
- package/abstract-interpretation/data-frame/domain.d.ts +107 -0
- package/abstract-interpretation/data-frame/domain.js +315 -0
- package/abstract-interpretation/data-frame/mappers/access-mapper.d.ts +17 -0
- package/abstract-interpretation/data-frame/mappers/access-mapper.js +166 -0
- package/abstract-interpretation/data-frame/mappers/arguments.d.ts +117 -0
- package/abstract-interpretation/data-frame/mappers/arguments.js +188 -0
- package/abstract-interpretation/data-frame/mappers/assignment-mapper.d.ts +20 -0
- package/abstract-interpretation/data-frame/mappers/assignment-mapper.js +34 -0
- package/abstract-interpretation/data-frame/mappers/function-mapper.d.ts +261 -0
- package/abstract-interpretation/data-frame/mappers/function-mapper.js +1219 -0
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.d.ts +12 -0
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.js +206 -0
- package/abstract-interpretation/data-frame/resolve-args.d.ts +42 -0
- package/abstract-interpretation/data-frame/resolve-args.js +118 -0
- package/abstract-interpretation/data-frame/semantics.d.ts +213 -0
- package/abstract-interpretation/data-frame/semantics.js +363 -0
- package/abstract-interpretation/data-frame/shape-inference.d.ts +38 -0
- package/abstract-interpretation/data-frame/shape-inference.js +111 -0
- package/benchmark/slicer.d.ts +15 -1
- package/benchmark/slicer.js +137 -0
- package/benchmark/stats/print.js +123 -45
- package/benchmark/stats/size-of.d.ts +7 -0
- package/benchmark/stats/size-of.js +1 -0
- package/benchmark/stats/stats.d.ts +30 -1
- package/benchmark/stats/stats.js +4 -2
- package/benchmark/summarizer/data.d.ts +33 -2
- package/benchmark/summarizer/first-phase/input.js +5 -1
- package/benchmark/summarizer/first-phase/process.js +47 -1
- package/benchmark/summarizer/second-phase/graph.js +1 -1
- package/benchmark/summarizer/second-phase/process.js +102 -4
- package/cli/benchmark-app.d.ts +2 -0
- package/cli/benchmark-app.js +2 -0
- package/cli/benchmark-helper-app.d.ts +2 -0
- package/cli/benchmark-helper-app.js +10 -3
- package/cli/common/options.js +4 -0
- package/cli/repl/commands/repl-query.js +1 -1
- package/cli/repl/server/connection.js +14 -5
- package/config.d.ts +31 -0
- package/config.js +21 -1
- package/control-flow/basic-cfg-guided-visitor.d.ts +1 -2
- package/control-flow/basic-cfg-guided-visitor.js +0 -6
- package/control-flow/cfg-simplification.d.ts +6 -0
- package/control-flow/cfg-simplification.js +18 -9
- package/control-flow/control-flow-graph.d.ts +3 -8
- package/control-flow/control-flow-graph.js +5 -6
- package/control-flow/dfg-cfg-guided-visitor.js +1 -1
- package/control-flow/extract-cfg.d.ts +2 -2
- package/control-flow/extract-cfg.js +52 -63
- package/control-flow/semantic-cfg-guided-visitor.d.ts +1 -1
- package/control-flow/semantic-cfg-guided-visitor.js +1 -1
- package/core/steps/all/static-slicing/00-slice.d.ts +7 -1
- package/core/steps/all/static-slicing/00-slice.js +9 -3
- package/core/steps/pipeline/default-pipelines.d.ts +74 -74
- package/dataflow/environments/built-in.d.ts +7 -5
- package/dataflow/environments/built-in.js +16 -13
- package/dataflow/eval/resolve/alias-tracking.js +2 -2
- package/dataflow/eval/resolve/resolve.d.ts +53 -9
- package/dataflow/eval/resolve/resolve.js +132 -38
- package/dataflow/graph/dataflowgraph-builder.js +2 -2
- package/dataflow/graph/graph.js +1 -1
- package/dataflow/graph/invert-dfg.d.ts +2 -0
- package/dataflow/graph/invert-dfg.js +17 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +1 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +4 -0
- package/documentation/doc-util/doc-query.js +11 -1
- package/documentation/doc-util/doc-search.js +2 -2
- package/documentation/print-cfg-wiki.js +3 -4
- package/documentation/print-core-wiki.js +2 -2
- package/documentation/print-dataflow-graph-wiki.js +7 -0
- package/documentation/print-faq-wiki.js +4 -0
- package/documentation/print-interface-wiki.js +11 -0
- package/documentation/print-linter-wiki.js +36 -4
- package/documentation/print-linting-and-testing-wiki.js +13 -1
- package/documentation/print-onboarding-wiki.js +4 -0
- package/documentation/print-query-wiki.js +29 -3
- package/linter/linter-executor.js +1 -2
- package/linter/linter-format.d.ts +26 -4
- package/linter/linter-format.js +25 -6
- package/linter/linter-rules.d.ts +63 -12
- package/linter/linter-rules.js +5 -1
- package/linter/rules/absolute-path.d.ts +4 -7
- package/linter/rules/absolute-path.js +9 -6
- package/linter/rules/dataframe-access-validation.d.ts +55 -0
- package/linter/rules/dataframe-access-validation.js +118 -0
- package/linter/rules/dead-code.d.ts +43 -0
- package/linter/rules/dead-code.js +50 -0
- package/linter/rules/deprecated-functions.d.ts +3 -2
- package/linter/rules/deprecated-functions.js +3 -1
- package/linter/rules/file-path-validity.d.ts +4 -4
- package/linter/rules/file-path-validity.js +8 -6
- package/linter/rules/naming-convention.d.ts +5 -4
- package/linter/rules/naming-convention.js +8 -2
- package/linter/rules/seeded-randomness.d.ts +4 -3
- package/linter/rules/seeded-randomness.js +3 -1
- package/linter/rules/unused-definition.d.ts +2 -0
- package/linter/rules/unused-definition.js +3 -1
- package/package.json +2 -2
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +6 -1
- package/queries/catalog/dependencies-query/function-info/read-functions.js +1 -0
- package/queries/catalog/dependencies-query/function-info/write-functions.js +1 -0
- package/queries/catalog/df-shape-query/df-shape-query-executor.d.ts +3 -0
- package/queries/catalog/df-shape-query/df-shape-query-executor.js +46 -0
- package/queries/catalog/df-shape-query/df-shape-query-format.d.ts +72 -0
- package/queries/catalog/df-shape-query/df-shape-query-format.js +31 -0
- package/queries/catalog/linter-query/linter-query-format.js +1 -1
- package/queries/catalog/location-map-query/location-map-query-executor.js +7 -5
- package/queries/catalog/location-map-query/location-map-query-format.d.ts +3 -0
- package/queries/catalog/location-map-query/location-map-query-format.js +1 -0
- package/queries/catalog/search-query/search-query-executor.js +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-executor.js +2 -1
- package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +3 -0
- package/queries/catalog/static-slice-query/static-slice-query-format.js +3 -1
- package/queries/query-print.d.ts +1 -1
- package/queries/query-print.js +0 -1
- package/queries/query.d.ts +77 -6
- package/queries/query.js +26 -11
- package/search/flowr-search-builder.d.ts +6 -6
- package/search/flowr-search-executor.d.ts +2 -2
- package/search/flowr-search-executor.js +1 -1
- package/search/flowr-search.d.ts +13 -8
- package/search/flowr-search.js +21 -0
- package/search/search-executor/search-enrichers.d.ts +87 -20
- package/search/search-executor/search-enrichers.js +44 -5
- package/search/search-executor/search-generators.d.ts +4 -4
- package/search/search-executor/search-generators.js +12 -7
- package/search/search-executor/search-mappers.js +3 -2
- package/search/search-executor/search-transformer.d.ts +3 -3
- package/search/search-executor/search-transformer.js +2 -2
- package/slicing/static/static-slicer.d.ts +4 -2
- package/slicing/static/static-slicer.js +10 -4
- package/util/collections/arrays.d.ts +2 -0
- package/util/collections/arrays.js +9 -0
- package/util/files.d.ts +8 -2
- package/util/files.js +22 -4
- package/util/mermaid/dfg.js +4 -2
- package/util/r-value.d.ts +23 -0
- package/util/r-value.js +113 -0
- package/util/range.d.ts +1 -0
- package/util/range.js +5 -1
- package/util/version.js +1 -1
- package/util/cfg/cfg.d.ts +0 -0
- package/util/cfg/cfg.js +0 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { FlowrSearch, FlowrSearchLike, SearchOutput } from './flowr-search-builder';
|
|
2
|
-
import type {
|
|
2
|
+
import type { FlowrSearchInput } from './flowr-search';
|
|
3
3
|
import type { Pipeline } from '../core/steps/pipeline/pipeline';
|
|
4
|
-
type GetSearchElements<S> = S extends FlowrSearch<infer _, infer _, infer _, infer Elements> ? Elements
|
|
4
|
+
type GetSearchElements<S> = S extends FlowrSearch<infer _, infer _, infer _, infer Elements> ? Elements : never;
|
|
5
5
|
/**
|
|
6
6
|
* Run a search with the given search query and data.
|
|
7
7
|
*/
|
|
@@ -11,6 +11,6 @@ function runSearch(search, data) {
|
|
|
11
11
|
const s = (0, flowr_search_builder_1.getFlowrSearch)(search);
|
|
12
12
|
return s.search.reduce((acc, transformer) => (0, search_transformer_1.getTransformer)(transformer.name)(data, acc, transformer.args),
|
|
13
13
|
/* support multiple arguments may be abstracted away in search frontend */
|
|
14
|
-
(0, search_generators_1.getGenerator)(s.generator.name)(data, s.generator.args))
|
|
14
|
+
(0, search_generators_1.getGenerator)(s.generator.name)(data, s.generator.args));
|
|
15
15
|
}
|
|
16
16
|
//# sourceMappingURL=flowr-search-executor.js.map
|
package/search/flowr-search.d.ts
CHANGED
|
@@ -3,22 +3,18 @@ import type { Pipeline, PipelineOutput, PipelineStepOutputWithName } from '../co
|
|
|
3
3
|
import type { NormalizedAst } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
4
4
|
import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
5
5
|
import type { DataflowInformation } from '../dataflow/info';
|
|
6
|
-
import type { BaseQueryResult } from '../queries/base-query-format';
|
|
7
|
-
import type { Query } from '../queries/query';
|
|
8
6
|
import type { FlowrConfigOptions } from '../config';
|
|
9
|
-
import type {
|
|
7
|
+
import type { Enrichment, EnrichmentSearchArguments, EnrichmentElementContent, EnrichmentSearchContent } from './search-executor/search-enrichers';
|
|
10
8
|
/**
|
|
11
9
|
* Yes, for now we do technically not need a wrapper around the RNode, but this allows us to attach caches etc.
|
|
12
10
|
* just for the respective search.
|
|
13
11
|
*/
|
|
14
12
|
export interface FlowrSearchElement<Info> {
|
|
15
13
|
readonly node: RNode<Info>;
|
|
14
|
+
readonly enrichments?: {
|
|
15
|
+
[E in Enrichment]?: EnrichmentElementContent<E>;
|
|
16
|
+
};
|
|
16
17
|
}
|
|
17
|
-
export interface FlowrSearchElementFromQuery<Info> extends FlowrSearchElement<Info> {
|
|
18
|
-
readonly query: Query['type'];
|
|
19
|
-
readonly queryResult: BaseQueryResult;
|
|
20
|
-
}
|
|
21
|
-
export type FlowrSearchElementMaybeFromQuery<Info> = MarkOptional<FlowrSearchElementFromQuery<Info>, 'query' | 'queryResult'>;
|
|
22
18
|
export interface FlowrSearchNodeBase<Type extends string, Name extends string, Args extends Record<string, unknown> | undefined> {
|
|
23
19
|
readonly type: Type;
|
|
24
20
|
readonly name: Name;
|
|
@@ -59,10 +55,19 @@ export type FlowrSearchInput<P extends Pipeline> = MinimumInputForFlowrSearch<P>
|
|
|
59
55
|
/** Intentionally, we abstract away from an array to avoid the use of conventional typescript operations */
|
|
60
56
|
export declare class FlowrSearchElements<Info = NoInfo, Elements extends FlowrSearchElement<Info>[] = FlowrSearchElement<Info>[]> {
|
|
61
57
|
private elements;
|
|
58
|
+
private enrichments;
|
|
62
59
|
constructor(elements?: Elements);
|
|
63
60
|
add(element: FlowrSearchElement<Info>): this;
|
|
64
61
|
addAll(elements: FlowrSearchElement<Info>[]): this;
|
|
65
62
|
getElements(): Readonly<Elements>;
|
|
66
63
|
mutate<OutElements extends Elements>(mutator: (elements: Elements) => OutElements): this;
|
|
64
|
+
/**
|
|
65
|
+
* Enriches this flowr search element collection with the given enrichment.
|
|
66
|
+
* To retrieve enrichment content for a given enrichment type, use {@link enrichmentContent}.
|
|
67
|
+
*
|
|
68
|
+
* Please note that this function does not also enrich individual elements, which is done through {@link enrichElement}. Both functions are called in a consise manner in {@link FlowrSearchBuilder.with}, which is the preferred way to add enrichments to a search.
|
|
69
|
+
*/
|
|
70
|
+
enrich<E extends Enrichment>(data: FlowrSearchInput<Pipeline>, enrichment: E, args?: EnrichmentSearchArguments<E>): this;
|
|
71
|
+
enrichmentContent<E extends Enrichment>(enrichment: E): EnrichmentSearchContent<E>;
|
|
67
72
|
}
|
|
68
73
|
export {};
|
package/search/flowr-search.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FlowrSearchElements = void 0;
|
|
4
|
+
const search_enrichers_1 = require("./search-executor/search-enrichers");
|
|
4
5
|
/** Intentionally, we abstract away from an array to avoid the use of conventional typescript operations */
|
|
5
6
|
class FlowrSearchElements {
|
|
6
7
|
elements = [];
|
|
8
|
+
enrichments = {};
|
|
7
9
|
constructor(elements) {
|
|
8
10
|
if (elements) {
|
|
9
11
|
this.elements = elements;
|
|
@@ -24,6 +26,25 @@ class FlowrSearchElements {
|
|
|
24
26
|
this.elements = mutator(this.elements);
|
|
25
27
|
return this;
|
|
26
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Enriches this flowr search element collection with the given enrichment.
|
|
31
|
+
* To retrieve enrichment content for a given enrichment type, use {@link enrichmentContent}.
|
|
32
|
+
*
|
|
33
|
+
* Please note that this function does not also enrich individual elements, which is done through {@link enrichElement}. Both functions are called in a consise manner in {@link FlowrSearchBuilder.with}, which is the preferred way to add enrichments to a search.
|
|
34
|
+
*/
|
|
35
|
+
enrich(data, enrichment, args) {
|
|
36
|
+
const enrichmentData = search_enrichers_1.Enrichments[enrichment];
|
|
37
|
+
if (enrichmentData.enrichSearch !== undefined) {
|
|
38
|
+
this.enrichments = {
|
|
39
|
+
...this.enrichments ?? {},
|
|
40
|
+
[enrichment]: enrichmentData.enrichSearch(this, data, args, this.enrichments?.[enrichment])
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return this;
|
|
44
|
+
}
|
|
45
|
+
enrichmentContent(enrichment) {
|
|
46
|
+
return this.enrichments?.[enrichment];
|
|
47
|
+
}
|
|
27
48
|
}
|
|
28
49
|
exports.FlowrSearchElements = FlowrSearchElements;
|
|
29
50
|
//# sourceMappingURL=flowr-search.js.map
|
|
@@ -1,37 +1,38 @@
|
|
|
1
|
-
import type { FlowrSearchElement, FlowrSearchInput } from '../flowr-search';
|
|
1
|
+
import type { FlowrSearchElement, FlowrSearchElements, FlowrSearchInput } from '../flowr-search';
|
|
2
2
|
import type { ParentInformation } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
3
3
|
import type { Pipeline } from '../../core/steps/pipeline/pipeline';
|
|
4
4
|
import type { MergeableRecord } from '../../util/objects';
|
|
5
5
|
import type { Identifier } from '../../dataflow/environments/identifier';
|
|
6
6
|
import type { LinkToLastCall } from '../../queries/catalog/call-context-query/call-context-query-format';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
[E in Enrichment]?: EnrichmentContent<E>;
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
export interface EnrichmentData<EnrichmentContent extends MergeableRecord, EnrichmentArguments = undefined> {
|
|
7
|
+
import { type NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
8
|
+
import type { ControlFlowInformation } from '../../control-flow/control-flow-graph';
|
|
9
|
+
import type { QueryResult, SynchronousQuery } from '../../queries/query';
|
|
10
|
+
import type { CfgSimplificationPassName } from '../../control-flow/cfg-simplification';
|
|
11
|
+
import type { AsyncOrSyncType } from 'ts-essentials';
|
|
12
|
+
export interface EnrichmentData<ElementContent extends MergeableRecord, ElementArguments = undefined, SearchContent extends MergeableRecord = never, SearchArguments = ElementArguments> {
|
|
17
13
|
/**
|
|
18
14
|
* A function that is applied to each element of the search to enrich it with additional data.
|
|
19
15
|
*/
|
|
20
|
-
readonly
|
|
16
|
+
readonly enrichElement?: (element: FlowrSearchElement<ParentInformation>, search: FlowrSearchElements<ParentInformation>, data: FlowrSearchInput<Pipeline>, args: ElementArguments | undefined, previousValue: ElementContent | undefined) => ElementContent;
|
|
17
|
+
readonly enrichSearch?: (search: FlowrSearchElements<ParentInformation>, data: FlowrSearchInput<Pipeline>, args: SearchArguments | undefined, previousValue: SearchContent | undefined) => SearchContent;
|
|
21
18
|
/**
|
|
22
19
|
* The mapping function used by the {@link Mapper.Enrichment} mapper.
|
|
23
20
|
*/
|
|
24
|
-
readonly mapper
|
|
21
|
+
readonly mapper?: (content: ElementContent) => FlowrSearchElement<ParentInformation>[];
|
|
25
22
|
}
|
|
26
|
-
export type
|
|
27
|
-
export type
|
|
23
|
+
export type EnrichmentElementContent<E extends Enrichment> = typeof Enrichments[E] extends EnrichmentData<infer EC, infer _EA, infer _SC, infer _SA> ? EC : never;
|
|
24
|
+
export type EnrichmentElementArguments<E extends Enrichment> = typeof Enrichments[E] extends EnrichmentData<infer _EC, infer EA, infer _SC, infer _SA> ? EA : never;
|
|
25
|
+
export type EnrichmentSearchContent<E extends Enrichment> = typeof Enrichments[E] extends EnrichmentData<infer _EC, infer _EA, infer SC, infer _SA> ? SC : never;
|
|
26
|
+
export type EnrichmentSearchArguments<E extends Enrichment> = typeof Enrichments[E] extends EnrichmentData<infer _EC, infer _EA, infer _SC, infer SA> ? SA : never;
|
|
28
27
|
/**
|
|
29
28
|
* An enumeration that stores the names of the available enrichments that can be applied to a set of search elements.
|
|
30
29
|
* See {@link FlowrSearchBuilder.with} for more information on how to apply enrichments.
|
|
31
30
|
*/
|
|
32
31
|
export declare enum Enrichment {
|
|
33
32
|
CallTargets = "call-targets",
|
|
34
|
-
LastCall = "last-call"
|
|
33
|
+
LastCall = "last-call",
|
|
34
|
+
CfgInformation = "cfg-information",
|
|
35
|
+
QueryData = "query-data"
|
|
35
36
|
}
|
|
36
37
|
export interface CallTargetsContent extends MergeableRecord {
|
|
37
38
|
/**
|
|
@@ -43,13 +44,52 @@ export interface CallTargetsContent extends MergeableRecord {
|
|
|
43
44
|
export interface LastCallContent extends MergeableRecord {
|
|
44
45
|
linkedIds: FlowrSearchElement<ParentInformation>[];
|
|
45
46
|
}
|
|
47
|
+
export interface CfgInformationElementContent extends MergeableRecord {
|
|
48
|
+
/**
|
|
49
|
+
* Whether the current node is a root node in the CFG, which is a node that is not contained inside of a function definition.
|
|
50
|
+
*/
|
|
51
|
+
isRoot: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Whether the current node is reachable from the root of the CFG.
|
|
54
|
+
* Only has a value if {@link CfgInformationArguments.checkReachable} was true.
|
|
55
|
+
*/
|
|
56
|
+
isReachable?: boolean;
|
|
57
|
+
}
|
|
58
|
+
export interface CfgInformationSearchContent extends MergeableRecord {
|
|
59
|
+
/**
|
|
60
|
+
* The CFG attached to the search, extracted using {@link extractCfg}.
|
|
61
|
+
*/
|
|
62
|
+
cfg: ControlFlowInformation;
|
|
63
|
+
/**
|
|
64
|
+
* The set of all nodes that are reachable from the root of the CFG, extracted using {@link visitCfgInOrder}.
|
|
65
|
+
* Only has a value if {@link CfgInformationArguments.checkReachable} was true.
|
|
66
|
+
*/
|
|
67
|
+
reachableNodes?: Set<NodeId>;
|
|
68
|
+
}
|
|
69
|
+
export interface CfgInformationArguments extends MergeableRecord {
|
|
70
|
+
/** Whether to recalculate the CFG information if it already exists on the current search. Defaults to `false`. */
|
|
71
|
+
forceRefresh?: boolean;
|
|
72
|
+
/** The simplification passes that should be run on the extracted CFG. Defaults to the entries of {@link DefaultCfgSimplificationOrder}. */
|
|
73
|
+
simplificationPasses?: CfgSimplificationPassName[];
|
|
74
|
+
/** Whether to check nodes for reachability, and subsequently set {@link CfgInformationSearchContent.reachableNodes} and {@link CfgInformationElementContent.isReachable}. Defaults to `false`. */
|
|
75
|
+
checkReachable?: boolean;
|
|
76
|
+
}
|
|
77
|
+
export interface QueryDataElementContent extends MergeableRecord {
|
|
78
|
+
/** The name of the query that this element originated from. To get each query's data, see {@link QueryDataSearchContent}. */
|
|
79
|
+
query: SynchronousQuery['type'];
|
|
80
|
+
}
|
|
81
|
+
export interface QueryDataSearchContent extends MergeableRecord {
|
|
82
|
+
queries: {
|
|
83
|
+
[QueryType in SynchronousQuery['type']]: AsyncOrSyncType<QueryResult<QueryType>>;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
46
86
|
/**
|
|
47
87
|
* The registry of enrichments that are currently supported by the search.
|
|
48
88
|
* See {@link FlowrSearchBuilder.with} for more information on how to apply enrichments.
|
|
49
89
|
*/
|
|
50
90
|
export declare const Enrichments: {
|
|
51
91
|
readonly "call-targets": {
|
|
52
|
-
|
|
92
|
+
enrichElement: (e: FlowrSearchElement<ParentInformation>, _s: FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>, data: import("../../core/steps/pipeline/pipeline").PipelineOutput<Pipeline<import("../../core/steps/pipeline-step").IPipelineStep<import("../../core/steps/pipeline-step").PipelineStepName, (...args: any[]) => any>>> & {
|
|
53
93
|
normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
54
94
|
dataflow: import("../../dataflow/info").DataflowInformation;
|
|
55
95
|
config: import("../../config").FlowrConfigOptions;
|
|
@@ -59,13 +99,40 @@ export declare const Enrichments: {
|
|
|
59
99
|
mapper: ({ targets }: CallTargetsContent) => FlowrSearchElement<ParentInformation>[];
|
|
60
100
|
};
|
|
61
101
|
readonly "last-call": {
|
|
62
|
-
|
|
102
|
+
enrichElement: (e: FlowrSearchElement<ParentInformation>, _s: FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>, data: import("../../core/steps/pipeline/pipeline").PipelineOutput<Pipeline<import("../../core/steps/pipeline-step").IPipelineStep<import("../../core/steps/pipeline-step").PipelineStepName, (...args: any[]) => any>>> & {
|
|
63
103
|
normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
64
104
|
dataflow: import("../../dataflow/info").DataflowInformation;
|
|
65
105
|
config: import("../../config").FlowrConfigOptions;
|
|
66
106
|
}, args: Omit<LinkToLastCall<string | RegExp>, "type">[] | undefined, prev: LastCallContent | undefined) => LastCallContent;
|
|
67
107
|
mapper: ({ linkedIds }: LastCallContent) => FlowrSearchElement<ParentInformation>[];
|
|
68
108
|
};
|
|
109
|
+
readonly "cfg-information": {
|
|
110
|
+
enrichElement: (e: FlowrSearchElement<ParentInformation>, search: FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>, _data: import("../../core/steps/pipeline/pipeline").PipelineOutput<Pipeline<import("../../core/steps/pipeline-step").IPipelineStep<import("../../core/steps/pipeline-step").PipelineStepName, (...args: any[]) => any>>> & {
|
|
111
|
+
normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
112
|
+
dataflow: import("../../dataflow/info").DataflowInformation;
|
|
113
|
+
config: import("../../config").FlowrConfigOptions;
|
|
114
|
+
}, _args: CfgInformationArguments | undefined, prev: CfgInformationElementContent | undefined) => {
|
|
115
|
+
isRoot: boolean;
|
|
116
|
+
isReachable: boolean | undefined;
|
|
117
|
+
};
|
|
118
|
+
enrichSearch: (_search: FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>, data: import("../../core/steps/pipeline/pipeline").PipelineOutput<Pipeline<import("../../core/steps/pipeline-step").IPipelineStep<import("../../core/steps/pipeline-step").PipelineStepName, (...args: any[]) => any>>> & {
|
|
119
|
+
normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
120
|
+
dataflow: import("../../dataflow/info").DataflowInformation;
|
|
121
|
+
config: import("../../config").FlowrConfigOptions;
|
|
122
|
+
}, args: CfgInformationArguments | undefined, prev: CfgInformationSearchContent | undefined) => CfgInformationSearchContent;
|
|
123
|
+
};
|
|
124
|
+
readonly "query-data": {
|
|
125
|
+
enrichElement: (_e: FlowrSearchElement<ParentInformation>, _search: FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>, _data: import("../../core/steps/pipeline/pipeline").PipelineOutput<Pipeline<import("../../core/steps/pipeline-step").IPipelineStep<import("../../core/steps/pipeline-step").PipelineStepName, (...args: any[]) => any>>> & {
|
|
126
|
+
normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
127
|
+
dataflow: import("../../dataflow/info").DataflowInformation;
|
|
128
|
+
config: import("../../config").FlowrConfigOptions;
|
|
129
|
+
}, args: QueryDataElementContent | undefined, prev: QueryDataElementContent | undefined) => QueryDataElementContent;
|
|
130
|
+
enrichSearch: (_search: FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>, _data: import("../../core/steps/pipeline/pipeline").PipelineOutput<Pipeline<import("../../core/steps/pipeline-step").IPipelineStep<import("../../core/steps/pipeline-step").PipelineStepName, (...args: any[]) => any>>> & {
|
|
131
|
+
normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
132
|
+
dataflow: import("../../dataflow/info").DataflowInformation;
|
|
133
|
+
config: import("../../config").FlowrConfigOptions;
|
|
134
|
+
}, args: QueryDataSearchContent | undefined, prev: QueryDataSearchContent | undefined) => Required<QueryDataSearchContent>;
|
|
135
|
+
};
|
|
69
136
|
};
|
|
70
137
|
/**
|
|
71
138
|
* Returns the content of the given enrichment type from a {@link FlowrSearchElement}.
|
|
@@ -73,5 +140,5 @@ export declare const Enrichments: {
|
|
|
73
140
|
* @param e - The search element whose enrichment content should be retrieved.
|
|
74
141
|
* @param enrichment - The enrichment content, if present, else `undefined`.
|
|
75
142
|
*/
|
|
76
|
-
export declare function enrichmentContent<E extends Enrichment>(e: FlowrSearchElement<ParentInformation>, enrichment: E):
|
|
77
|
-
export declare function
|
|
143
|
+
export declare function enrichmentContent<E extends Enrichment>(e: FlowrSearchElement<ParentInformation>, enrichment: E): EnrichmentElementContent<E>;
|
|
144
|
+
export declare function enrichElement<Element extends FlowrSearchElement<ParentInformation>, E extends Enrichment>(e: Element, s: FlowrSearchElements<ParentInformation>, data: FlowrSearchInput<Pipeline>, enrichment: E, args?: EnrichmentElementArguments<E>): Element;
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Enrichments = exports.Enrichment = void 0;
|
|
4
4
|
exports.enrichmentContent = enrichmentContent;
|
|
5
|
-
exports.
|
|
5
|
+
exports.enrichElement = enrichElement;
|
|
6
|
+
const objects_1 = require("../../util/objects");
|
|
6
7
|
const vertex_1 = require("../../dataflow/graph/vertex");
|
|
7
8
|
const identify_link_to_last_call_relation_1 = require("../../queries/catalog/call-context-query/identify-link-to-last-call-relation");
|
|
8
9
|
const assert_1 = require("../../util/assert");
|
|
9
10
|
const extract_cfg_1 = require("../../control-flow/extract-cfg");
|
|
10
11
|
const dfg_get_origin_1 = require("../../dataflow/origin/dfg-get-origin");
|
|
11
12
|
const node_id_1 = require("../../r-bridge/lang-4.x/ast/model/processing/node-id");
|
|
13
|
+
const cfg_simplification_1 = require("../../control-flow/cfg-simplification");
|
|
12
14
|
/**
|
|
13
15
|
* An enumeration that stores the names of the available enrichments that can be applied to a set of search elements.
|
|
14
16
|
* See {@link FlowrSearchBuilder.with} for more information on how to apply enrichments.
|
|
@@ -17,6 +19,8 @@ var Enrichment;
|
|
|
17
19
|
(function (Enrichment) {
|
|
18
20
|
Enrichment["CallTargets"] = "call-targets";
|
|
19
21
|
Enrichment["LastCall"] = "last-call";
|
|
22
|
+
Enrichment["CfgInformation"] = "cfg-information";
|
|
23
|
+
Enrichment["QueryData"] = "query-data";
|
|
20
24
|
})(Enrichment || (exports.Enrichment = Enrichment = {}));
|
|
21
25
|
/**
|
|
22
26
|
* The registry of enrichments that are currently supported by the search.
|
|
@@ -24,7 +28,7 @@ var Enrichment;
|
|
|
24
28
|
*/
|
|
25
29
|
exports.Enrichments = {
|
|
26
30
|
[Enrichment.CallTargets]: {
|
|
27
|
-
|
|
31
|
+
enrichElement: (e, _s, data, args, prev) => {
|
|
28
32
|
// we don't resolve aliases here yet!
|
|
29
33
|
const content = { targets: [] };
|
|
30
34
|
const callVertex = data.dataflow.graph.getVertex(e.node.info.id);
|
|
@@ -65,7 +69,7 @@ exports.Enrichments = {
|
|
|
65
69
|
mapper: ({ targets }) => targets.map(t => t).filter(t => t.node !== undefined)
|
|
66
70
|
},
|
|
67
71
|
[Enrichment.LastCall]: {
|
|
68
|
-
|
|
72
|
+
enrichElement: (e, _s, data, args, prev) => {
|
|
69
73
|
(0, assert_1.guard)(args && args.length, `${Enrichment.LastCall} enrichment requires at least one argument`);
|
|
70
74
|
const content = prev ?? { linkedIds: [] };
|
|
71
75
|
const vertex = data.dataflow.graph.get(e.node.info.id);
|
|
@@ -86,6 +90,41 @@ exports.Enrichments = {
|
|
|
86
90
|
},
|
|
87
91
|
mapper: ({ linkedIds }) => linkedIds
|
|
88
92
|
},
|
|
93
|
+
[Enrichment.CfgInformation]: {
|
|
94
|
+
enrichElement: (e, search, _data, _args, prev) => {
|
|
95
|
+
const searchContent = search.enrichmentContent(Enrichment.CfgInformation);
|
|
96
|
+
return {
|
|
97
|
+
...prev,
|
|
98
|
+
isRoot: searchContent.cfg.graph.rootIds().has(e.node.info.id),
|
|
99
|
+
isReachable: searchContent.reachableNodes?.has(e.node.info.id)
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
enrichSearch: (_search, data, args, prev) => {
|
|
103
|
+
args = {
|
|
104
|
+
forceRefresh: false,
|
|
105
|
+
checkReachable: false,
|
|
106
|
+
simplificationPasses: cfg_simplification_1.DefaultCfgSimplificationOrder,
|
|
107
|
+
...args
|
|
108
|
+
};
|
|
109
|
+
// short-circuit if we already have a cfg stored
|
|
110
|
+
if (!args.forceRefresh && prev?.simpleCfg) {
|
|
111
|
+
return prev;
|
|
112
|
+
}
|
|
113
|
+
const content = {
|
|
114
|
+
...prev,
|
|
115
|
+
cfg: (0, extract_cfg_1.extractCfg)(data.normalize, data.config, data.dataflow.graph, args.simplificationPasses),
|
|
116
|
+
};
|
|
117
|
+
if (args.checkReachable) {
|
|
118
|
+
content.reachableNodes = (0, cfg_simplification_1.cfgFindAllReachable)(content.cfg);
|
|
119
|
+
}
|
|
120
|
+
return content;
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
[Enrichment.QueryData]: {
|
|
124
|
+
// the query data enrichment is just a "pass-through" that passes the query data to the underlying search
|
|
125
|
+
enrichElement: (_e, _search, _data, args, prev) => (args ?? prev),
|
|
126
|
+
enrichSearch: (_search, _data, args, prev) => (0, objects_1.deepMergeObject)(prev, args)
|
|
127
|
+
}
|
|
89
128
|
};
|
|
90
129
|
/**
|
|
91
130
|
* Returns the content of the given enrichment type from a {@link FlowrSearchElement}.
|
|
@@ -96,14 +135,14 @@ exports.Enrichments = {
|
|
|
96
135
|
function enrichmentContent(e, enrichment) {
|
|
97
136
|
return e?.enrichments?.[enrichment];
|
|
98
137
|
}
|
|
99
|
-
function
|
|
138
|
+
function enrichElement(e, s, data, enrichment, args) {
|
|
100
139
|
const enrichmentData = exports.Enrichments[enrichment];
|
|
101
140
|
const prev = e?.enrichments;
|
|
102
141
|
return {
|
|
103
142
|
...e,
|
|
104
143
|
enrichments: {
|
|
105
144
|
...prev ?? {},
|
|
106
|
-
[enrichment]: enrichmentData.
|
|
145
|
+
[enrichment]: enrichmentData.enrichElement?.(e, s, data, args, prev?.[enrichment])
|
|
107
146
|
}
|
|
108
147
|
};
|
|
109
148
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { FlowrSearchElement,
|
|
1
|
+
import type { FlowrSearchElement, FlowrSearchGeneratorNodeBase, FlowrSearchGetFilter, FlowrSearchInput } from '../flowr-search';
|
|
2
2
|
import { FlowrSearchElements } from '../flowr-search';
|
|
3
3
|
import type { Pipeline } from '../../core/steps/pipeline/pipeline';
|
|
4
4
|
import type { TailTypesOrUndefined } from '../../util/collections/arrays';
|
|
5
5
|
import type { ParentInformation } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
6
6
|
import type { SlicingCriteria } from '../../slicing/criterion/parse';
|
|
7
|
-
import type {
|
|
7
|
+
import type { SynchronousQuery } from '../../queries/query';
|
|
8
8
|
/**
|
|
9
9
|
* This is a union of all possible generator node types
|
|
10
10
|
*/
|
|
@@ -33,8 +33,8 @@ declare function generateFrom(data: FlowrSearchInput<Pipeline>, args: {
|
|
|
33
33
|
from: FlowrSearchElement<ParentInformation> | FlowrSearchElement<ParentInformation>[];
|
|
34
34
|
}): FlowrSearchElements<ParentInformation>;
|
|
35
35
|
declare function generateFromQuery(data: FlowrSearchInput<Pipeline>, args: {
|
|
36
|
-
from: readonly
|
|
37
|
-
}): FlowrSearchElements<ParentInformation,
|
|
36
|
+
from: readonly SynchronousQuery[];
|
|
37
|
+
}): FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>;
|
|
38
38
|
declare function generateCriterion(data: FlowrSearchInput<Pipeline>, args: {
|
|
39
39
|
criterion: SlicingCriteria;
|
|
40
40
|
}): FlowrSearchElements<ParentInformation>;
|
|
@@ -6,6 +6,7 @@ const flowr_search_1 = require("../flowr-search");
|
|
|
6
6
|
const parse_1 = require("../../slicing/criterion/parse");
|
|
7
7
|
const assert_1 = require("../../util/assert");
|
|
8
8
|
const query_1 = require("../../queries/query");
|
|
9
|
+
const search_enrichers_1 = require("./search-enrichers");
|
|
9
10
|
/**
|
|
10
11
|
* All supported generators!
|
|
11
12
|
*/
|
|
@@ -55,22 +56,26 @@ function generateFrom(data, args) {
|
|
|
55
56
|
return new flowr_search_1.FlowrSearchElements(Array.isArray(args.from) ? args.from : [args.from]);
|
|
56
57
|
}
|
|
57
58
|
function generateFromQuery(data, args) {
|
|
58
|
-
const nodes = new Set();
|
|
59
59
|
const result = (0, query_1.executeQueries)({ ast: data.normalize, dataflow: data.dataflow, config: data.config }, args.from);
|
|
60
|
+
// collect involved nodes
|
|
61
|
+
const nodesByQuery = new Map();
|
|
60
62
|
for (const [query, content] of Object.entries(result)) {
|
|
61
63
|
if (query === '.meta') {
|
|
62
64
|
continue;
|
|
63
65
|
}
|
|
66
|
+
const nodes = new Set();
|
|
64
67
|
const queryDef = query_1.SupportedQueries[query];
|
|
65
68
|
for (const node of queryDef.flattenInvolvedNodes(content)) {
|
|
66
|
-
nodes.add({
|
|
67
|
-
node: data.normalize.idMap.get(node),
|
|
68
|
-
query: query,
|
|
69
|
-
queryResult: content
|
|
70
|
-
});
|
|
69
|
+
nodes.add({ node: data.normalize.idMap.get(node) });
|
|
71
70
|
}
|
|
71
|
+
nodesByQuery.set(query, nodes);
|
|
72
72
|
}
|
|
73
|
-
|
|
73
|
+
// enrich elements with query data
|
|
74
|
+
const elements = new flowr_search_1.FlowrSearchElements([...nodesByQuery].flatMap(([_, nodes]) => [...nodes])).enrich(data, search_enrichers_1.Enrichment.QueryData, { queries: result });
|
|
75
|
+
return elements.mutate(s => s.map(e => {
|
|
76
|
+
const [query, _] = [...nodesByQuery].find(([_, nodes]) => nodes.has(e));
|
|
77
|
+
return (0, search_enrichers_1.enrichElement)(e, elements, data, search_enrichers_1.Enrichment.QueryData, { query });
|
|
78
|
+
}));
|
|
74
79
|
}
|
|
75
80
|
function generateCriterion(data, args) {
|
|
76
81
|
return new flowr_search_1.FlowrSearchElements(args.criterion.map(c => ({ node: data.normalize.idMap.get((0, parse_1.slicingCriterionToId)(c, data.normalize.idMap)) })));
|
|
@@ -10,8 +10,9 @@ var Mapper;
|
|
|
10
10
|
const Mappers = {
|
|
11
11
|
[Mapper.Enrichment]: {
|
|
12
12
|
mapper: (e, _data, enrichment) => {
|
|
13
|
-
const
|
|
14
|
-
|
|
13
|
+
const enrichmentData = search_enrichers_1.Enrichments[enrichment];
|
|
14
|
+
const content = (0, search_enrichers_1.enrichmentContent)(e, enrichment);
|
|
15
|
+
return content !== undefined ? enrichmentData.mapper?.(content) ?? [] : [];
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
};
|
|
@@ -4,7 +4,7 @@ import type { LastOfArray, Tail2TypesOrUndefined, TailOfArray } from '../../util
|
|
|
4
4
|
import type { FlowrFilterExpression } from '../flowr-search-filters';
|
|
5
5
|
import type { FlowrSearchGeneratorNode } from './search-generators';
|
|
6
6
|
import type { ParentInformation } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
7
|
-
import type {
|
|
7
|
+
import type { Enrichment, EnrichmentElementArguments } from './search-enrichers';
|
|
8
8
|
import type { Mapper, MapperArguments } from './search-mappers';
|
|
9
9
|
/**
|
|
10
10
|
* This is a union of all possible transformer node types
|
|
@@ -57,8 +57,8 @@ declare function getFilter<Elements extends FlowrSearchElement<ParentInformation
|
|
|
57
57
|
}): CascadeEmpty<Elements, Elements | []>;
|
|
58
58
|
declare function getWith<Elements extends FlowrSearchElement<ParentInformation>[], FSE extends FlowrSearchElements<ParentInformation, Elements>>(data: FlowrSearchInput<Pipeline>, elements: FSE, { info, args }: {
|
|
59
59
|
info: Enrichment;
|
|
60
|
-
args?:
|
|
61
|
-
}): FlowrSearchElements<ParentInformation,
|
|
60
|
+
args?: EnrichmentElementArguments<Enrichment>;
|
|
61
|
+
}): FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>;
|
|
62
62
|
declare function getMap<Elements extends FlowrSearchElement<ParentInformation>[], FSE extends FlowrSearchElements<ParentInformation, Elements>>(data: FlowrSearchInput<Pipeline>, elements: FSE, { mapper, args }: {
|
|
63
63
|
mapper: Mapper;
|
|
64
64
|
args: MapperArguments<Mapper>;
|
|
@@ -96,7 +96,7 @@ function getFilter(data, elements, { filter }) {
|
|
|
96
96
|
return elements.mutate(e => e.filter(e => (0, flowr_search_filters_1.evalFilter)(filter, { element: e, normalize: data.normalize, dataflow: data.dataflow })));
|
|
97
97
|
}
|
|
98
98
|
function getWith(data, elements, { info, args }) {
|
|
99
|
-
return elements.mutate(
|
|
99
|
+
return elements.enrich(data, info, args).mutate(s => s.map(e => (0, search_enrichers_1.enrichElement)(e, elements, data, info, args)));
|
|
100
100
|
}
|
|
101
101
|
function getMap(data, elements, { mapper, args }) {
|
|
102
102
|
return elements.mutate(elements => elements.flatMap(e => (0, search_mappers_1.map)(e, data, mapper, args)));
|
|
@@ -105,7 +105,7 @@ function getMerge(
|
|
|
105
105
|
/* search has to be unknown because it is a recursive type */
|
|
106
106
|
data, elements, other) {
|
|
107
107
|
const resultOther = (0, flowr_search_executor_1.runSearch)(other, data);
|
|
108
|
-
return elements.addAll(resultOther);
|
|
108
|
+
return elements.addAll([...resultOther.getElements()]);
|
|
109
109
|
}
|
|
110
110
|
function getUnique(data, elements) {
|
|
111
111
|
return elements.mutate(e => e.reduce((acc, cur) => {
|
|
@@ -6,17 +6,19 @@ import type { NormalizedAst } from '../../r-bridge/lang-4.x/ast/model/processing
|
|
|
6
6
|
import type { SlicingCriteria } from '../criterion/parse';
|
|
7
7
|
import type { REnvironmentInformation } from '../../dataflow/environments/environment';
|
|
8
8
|
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
9
|
+
import { SliceDirection } from '../../core/steps/all/static-slicing/00-slice';
|
|
9
10
|
export declare const slicerLogger: import("tslog").Logger<import("tslog").ILogObj>;
|
|
10
11
|
/**
|
|
11
|
-
* This returns the ids to include in the static
|
|
12
|
+
* This returns the ids to include in the static slice of the given type, when slicing with the given seed id's (must be at least one).
|
|
12
13
|
* <p>
|
|
13
14
|
* The returned ids can be used to {@link reconstructToCode|reconstruct the slice to R code}.
|
|
14
15
|
*
|
|
15
16
|
* @param graph - The dataflow graph to conduct the slicing on.
|
|
16
17
|
* @param ast - The normalized AST of the code (used to get static nesting information of the lexemes in case of control flow dependencies that may have no effect on the slicing scope).
|
|
17
18
|
* @param criteria - The criteria to slice on.
|
|
19
|
+
* @param direction - The direction to slice in.
|
|
18
20
|
* @param threshold - The maximum number of nodes to visit in the graph. If the threshold is reached, the slice will side with inclusion and drop its minimal guarantee. The limit ensures that the algorithm halts.
|
|
19
21
|
* @param cache - A cache to store the results of the slice. If provided, the slice may use this cache to speed up the slicing process.
|
|
20
22
|
*/
|
|
21
|
-
export declare function
|
|
23
|
+
export declare function staticSlice(graph: DataflowGraph, { idMap }: NormalizedAst, criteria: SlicingCriteria, direction: SliceDirection, threshold?: number, cache?: Map<Fingerprint, Set<NodeId>>): Readonly<SliceResult>;
|
|
22
24
|
export declare function updatePotentialAddition(queue: VisitingQueue, id: NodeId, target: NodeId, baseEnvironment: REnvironmentInformation, envFingerprint: string): void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.slicerLogger = void 0;
|
|
4
|
-
exports.
|
|
4
|
+
exports.staticSlice = staticSlice;
|
|
5
5
|
exports.updatePotentialAddition = updatePotentialAddition;
|
|
6
6
|
const assert_1 = require("../../util/assert");
|
|
7
7
|
const log_1 = require("../../util/log");
|
|
@@ -12,22 +12,28 @@ const parse_1 = require("../criterion/parse");
|
|
|
12
12
|
const environment_1 = require("../../dataflow/environments/environment");
|
|
13
13
|
const vertex_1 = require("../../dataflow/graph/vertex");
|
|
14
14
|
const edge_1 = require("../../dataflow/graph/edge");
|
|
15
|
+
const _00_slice_1 = require("../../core/steps/all/static-slicing/00-slice");
|
|
16
|
+
const invert_dfg_1 = require("../../dataflow/graph/invert-dfg");
|
|
15
17
|
exports.slicerLogger = log_1.log.getSubLogger({ name: 'slicer' });
|
|
16
18
|
/**
|
|
17
|
-
* This returns the ids to include in the static
|
|
19
|
+
* This returns the ids to include in the static slice of the given type, when slicing with the given seed id's (must be at least one).
|
|
18
20
|
* <p>
|
|
19
21
|
* The returned ids can be used to {@link reconstructToCode|reconstruct the slice to R code}.
|
|
20
22
|
*
|
|
21
23
|
* @param graph - The dataflow graph to conduct the slicing on.
|
|
22
24
|
* @param ast - The normalized AST of the code (used to get static nesting information of the lexemes in case of control flow dependencies that may have no effect on the slicing scope).
|
|
23
25
|
* @param criteria - The criteria to slice on.
|
|
26
|
+
* @param direction - The direction to slice in.
|
|
24
27
|
* @param threshold - The maximum number of nodes to visit in the graph. If the threshold is reached, the slice will side with inclusion and drop its minimal guarantee. The limit ensures that the algorithm halts.
|
|
25
28
|
* @param cache - A cache to store the results of the slice. If provided, the slice may use this cache to speed up the slicing process.
|
|
26
29
|
*/
|
|
27
|
-
function
|
|
30
|
+
function staticSlice(graph, { idMap }, criteria, direction, threshold = 75, cache) {
|
|
28
31
|
(0, assert_1.guard)(criteria.length > 0, 'must have at least one seed id to calculate slice');
|
|
29
32
|
const decodedCriteria = (0, parse_1.convertAllSlicingCriteriaToIds)(criteria, idMap);
|
|
30
|
-
(0, log_1.expensiveTrace)(exports.slicerLogger, () => `calculating slice for ${decodedCriteria.length} seed criteria: ${decodedCriteria.map(s => JSON.stringify(s)).join(', ')}`);
|
|
33
|
+
(0, log_1.expensiveTrace)(exports.slicerLogger, () => `calculating ${direction} slice for ${decodedCriteria.length} seed criteria: ${decodedCriteria.map(s => JSON.stringify(s)).join(', ')}`);
|
|
34
|
+
if (direction === _00_slice_1.SliceDirection.Forward) {
|
|
35
|
+
graph = (0, invert_dfg_1.invertDfg)(graph);
|
|
36
|
+
}
|
|
31
37
|
const queue = new visiting_queue_1.VisitingQueue(threshold, cache);
|
|
32
38
|
let minNesting = Number.MAX_SAFE_INTEGER;
|
|
33
39
|
const sliceSeedIds = new Set();
|
|
@@ -88,3 +88,5 @@ export declare function equidistantSampling<T>(list: readonly T[], sampleCount:
|
|
|
88
88
|
*
|
|
89
89
|
*/
|
|
90
90
|
export declare function cartesianProduct<T>(...arrays: T[][]): T[][];
|
|
91
|
+
/** merge two arrays, removing duplicates */
|
|
92
|
+
export declare function uniqueArrayMerge<T>(left: readonly T[], right: readonly T[]): T[];
|
|
@@ -10,6 +10,7 @@ exports.array2bag = array2bag;
|
|
|
10
10
|
exports.arrayEqual = arrayEqual;
|
|
11
11
|
exports.equidistantSampling = equidistantSampling;
|
|
12
12
|
exports.cartesianProduct = cartesianProduct;
|
|
13
|
+
exports.uniqueArrayMerge = uniqueArrayMerge;
|
|
13
14
|
const assert_1 = require("../assert");
|
|
14
15
|
/**
|
|
15
16
|
* Splits the array every time the given predicate fires.
|
|
@@ -215,4 +216,12 @@ function equidistantSampling(list, sampleCount, rounding = 'ceil') {
|
|
|
215
216
|
function cartesianProduct(...arrays) {
|
|
216
217
|
return arrays.reduce((a, b) => a.flatMap(x => b.map(y => x.concat(y))), [[]]);
|
|
217
218
|
}
|
|
219
|
+
/** merge two arrays, removing duplicates */
|
|
220
|
+
function uniqueArrayMerge(left, right) {
|
|
221
|
+
const result = new Set(left);
|
|
222
|
+
for (const elem of right) {
|
|
223
|
+
result.add(elem);
|
|
224
|
+
}
|
|
225
|
+
return Array.from(result);
|
|
226
|
+
}
|
|
218
227
|
//# sourceMappingURL=arrays.js.map
|
package/util/files.d.ts
CHANGED
|
@@ -40,17 +40,23 @@ export declare function writeTableAsCsv(table: Table, file: string, sep?: string
|
|
|
40
40
|
/**
|
|
41
41
|
* Reads a file line by line and calls the given function for each line.
|
|
42
42
|
* The `lineNumber` starts at `0`.
|
|
43
|
+
* The `maxLines` option limits the maximum number of read lines and is `Infinity` by default.
|
|
44
|
+
*
|
|
45
|
+
* @returns Whether all lines have been successfully read (`false` if `maxLines` was reached)
|
|
43
46
|
*
|
|
44
47
|
* See {@link readLineByLineSync} for a synchronous version.
|
|
45
48
|
*/
|
|
46
|
-
export declare function readLineByLine(filePath: string, onLine: (line: Buffer, lineNumber: number) => Promise<void
|
|
49
|
+
export declare function readLineByLine(filePath: string, onLine: (line: Buffer, lineNumber: number) => Promise<void>, maxLines?: number): Promise<boolean>;
|
|
47
50
|
/**
|
|
48
51
|
* Reads a file line by line and calls the given function for each line.
|
|
49
52
|
* The `lineNumber` starts at `0`.
|
|
53
|
+
* The `maxLines` option limits the maximum number of read lines and is `Infinity` by default.
|
|
54
|
+
*
|
|
55
|
+
* @returns Whether the file exists and all lines have been successfully read (`false` if `maxLines` was reached)
|
|
50
56
|
*
|
|
51
57
|
* See {@link readLineByLine} for an asynchronous version.
|
|
52
58
|
*/
|
|
53
|
-
export declare function readLineByLineSync(filePath: string, onLine: (line: Buffer, lineNumber: number) => void):
|
|
59
|
+
export declare function readLineByLineSync(filePath: string, onLine: (line: Buffer, lineNumber: number) => void, maxLines?: number): boolean;
|
|
54
60
|
/**
|
|
55
61
|
* Chops off the last part of the given directory path after a path separator, essentially returning the path's parent directory.
|
|
56
62
|
* If an absolute path is passed, the returned path is also absolute.
|