@eagleoutice/flowr 2.9.14 → 2.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -29
- package/abstract-interpretation/absint-visitor.d.ts +13 -8
- package/abstract-interpretation/absint-visitor.js +35 -26
- package/abstract-interpretation/data-frame/dataframe-domain.d.ts +1 -2
- package/abstract-interpretation/data-frame/dataframe-domain.js +14 -15
- package/abstract-interpretation/data-frame/mappers/access-mapper.js +2 -15
- package/abstract-interpretation/data-frame/mappers/arguments.d.ts +11 -17
- package/abstract-interpretation/data-frame/mappers/arguments.js +18 -18
- package/abstract-interpretation/data-frame/mappers/function-mapper.d.ts +41 -15
- package/abstract-interpretation/data-frame/mappers/function-mapper.js +74 -48
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.js +2 -1
- package/abstract-interpretation/data-frame/semantics.d.ts +1 -1
- package/abstract-interpretation/data-frame/semantics.js +31 -35
- package/abstract-interpretation/data-frame/shape-inference.js +1 -1
- package/abstract-interpretation/domains/interval-domain.d.ts +1 -0
- package/abstract-interpretation/domains/interval-domain.js +3 -0
- package/abstract-interpretation/domains/product-domain.d.ts +9 -0
- package/abstract-interpretation/domains/product-domain.js +26 -6
- package/abstract-interpretation/domains/state-abstract-domain.d.ts +36 -22
- package/abstract-interpretation/domains/state-abstract-domain.js +169 -62
- package/abstract-interpretation/unsupported-functions.d.ts +10 -0
- package/abstract-interpretation/unsupported-functions.js +45 -0
- package/benchmark/slicer.js +10 -13
- package/benchmark/stats/stats.d.ts +2 -2
- package/cli/flowr.js +1 -1
- package/cli/repl/parser/slice-query-parser.d.ts +2 -2
- package/config.d.ts +4 -0
- package/config.js +5 -3
- package/control-flow/control-flow-graph.js +13 -9
- package/control-flow/semantic-cfg-guided-visitor.d.ts +6 -0
- package/control-flow/semantic-cfg-guided-visitor.js +6 -0
- package/dataflow/environments/built-in-proc-name.d.ts +6 -0
- package/dataflow/environments/built-in-proc-name.js +6 -0
- package/dataflow/environments/built-in.d.ts +7 -5
- package/dataflow/environments/built-in.js +2 -0
- package/dataflow/environments/default-builtin-config.d.ts +442 -6
- package/dataflow/environments/default-builtin-config.js +158 -3
- package/dataflow/environments/identifier.d.ts +4 -0
- package/dataflow/environments/identifier.js +17 -0
- package/dataflow/environments/overwrite.js +2 -5
- package/dataflow/graph/call-graph.d.ts +4 -7
- package/dataflow/graph/call-graph.js +0 -22
- package/dataflow/graph/df-helper.d.ts +23 -12
- package/dataflow/graph/df-helper.js +44 -7
- package/dataflow/graph/graph-helper.d.ts +9 -4
- package/dataflow/graph/graph-helper.js +26 -3
- package/dataflow/graph/graph.d.ts +23 -2
- package/dataflow/graph/graph.js +38 -4
- package/dataflow/graph/vertex.d.ts +2 -0
- package/dataflow/instrument/instrument-dataflow-count.d.ts +10 -0
- package/dataflow/instrument/instrument-dataflow-count.js +10 -0
- package/dataflow/internal/process/functions/call/argument/unpack-argument.d.ts +4 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-access.d.ts +3 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +1 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +3 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +8 -19
- package/dataflow/internal/process/functions/call/built-in/built-in-get.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-library.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-list.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-local.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-pipe.d.ts +23 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +80 -12
- package/dataflow/internal/process/functions/call/built-in/built-in-purrr-formula.d.ts +41 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-purrr-formula.js +179 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-quote.d.ts +7 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-quote.js +62 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-recall.d.ts +7 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-recall.js +15 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-register-hook.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-s-seven-dispatch.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-s-seven-new-generic.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-s-three-dispatch.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-special-bin-op.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-stop-if-not.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-try-catch.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.d.ts +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.d.ts +2 -2
- package/dataflow/internal/process/functions/call/common.d.ts +2 -2
- package/dataflow/internal/process/functions/call/common.js +6 -4
- package/dataflow/internal/process/functions/call/known-call-handling.d.ts +2 -2
- package/dataflow/internal/process/functions/call/named-call-handling.d.ts +2 -2
- package/dataflow/internal/process/functions/process-parameter.js +1 -1
- package/documentation/doc-readme.js +2 -1
- package/documentation/wiki-absint.js +6 -5
- package/documentation/wiki-analyzer.js +0 -2
- package/documentation/wiki-linter.js +6 -0
- package/documentation/wiki-normalized-ast.js +7 -7
- package/linter/linter-rules.d.ts +49 -1
- package/linter/linter-rules.js +5 -1
- package/linter/rules/dataframe-access-validation.d.ts +1 -1
- package/linter/rules/dataframe-access-validation.js +3 -4
- package/linter/rules/problematic-eval.d.ts +44 -0
- package/linter/rules/problematic-eval.js +83 -0
- package/linter/rules/roxygen-arguments.d.ts +35 -0
- package/linter/rules/roxygen-arguments.js +100 -0
- package/package.json +8 -9
- package/project/context/flowr-analyzer-context.d.ts +1 -8
- package/project/context/flowr-analyzer-context.js +1 -7
- package/project/context/flowr-analyzer-environment-context.d.ts +5 -0
- package/project/context/flowr-analyzer-environment-context.js +6 -0
- package/project/context/flowr-analyzer-files-context.d.ts +6 -0
- package/project/context/flowr-analyzer-files-context.js +4 -2
- package/project/flowr-analyzer-builder.js +1 -4
- package/queries/catalog/call-context-query/call-context-query-executor.d.ts +1 -1
- package/queries/catalog/call-context-query/call-context-query-executor.js +10 -5
- package/queries/catalog/call-context-query/call-context-query-format.d.ts +1 -1
- package/queries/catalog/dependencies-query/function-info/library-functions.js +2 -0
- package/queries/catalog/df-shape-query/df-shape-query-executor.js +1 -1
- package/queries/catalog/df-shape-query/df-shape-query-format.d.ts +3 -3
- package/queries/catalog/df-shape-query/df-shape-query-format.js +7 -2
- package/queries/catalog/does-call-query/does-call-query-executor.js +1 -1
- package/queries/catalog/does-call-query/does-call-query-format.d.ts +2 -2
- package/queries/catalog/files-query/files-query-executor.js +0 -1
- package/queries/catalog/happens-before-query/happens-before-query-executor.js +2 -2
- package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +3 -3
- package/queries/catalog/input-sources-query/input-sources-query-executor.d.ts +6 -0
- package/queries/catalog/input-sources-query/input-sources-query-executor.js +66 -0
- package/queries/catalog/input-sources-query/input-sources-query-format.d.ts +36 -0
- package/queries/catalog/input-sources-query/input-sources-query-format.js +63 -0
- package/queries/catalog/input-sources-query/simple-input-classifier.d.ts +92 -0
- package/queries/catalog/input-sources-query/simple-input-classifier.js +310 -0
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-executor.d.ts +2 -2
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-executor.js +1 -1
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-format.d.ts +2 -2
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-executor.js +1 -1
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-format.d.ts +2 -2
- package/queries/catalog/inspect-recursion-query/inspect-recursion-query-format.d.ts +2 -2
- package/queries/catalog/location-map-query/location-map-query-executor.js +1 -1
- package/queries/catalog/location-map-query/location-map-query-format.d.ts +2 -2
- package/queries/catalog/origin-query/origin-query-executor.d.ts +2 -2
- package/queries/catalog/origin-query/origin-query-executor.js +1 -1
- package/queries/catalog/origin-query/origin-query-format.d.ts +3 -3
- package/queries/catalog/provenance-query/provenance-query-executor.d.ts +1 -4
- package/queries/catalog/provenance-query/provenance-query-executor.js +3 -6
- package/queries/catalog/provenance-query/provenance-query-format.d.ts +2 -2
- package/queries/catalog/resolve-value-query/resolve-value-query-executor.js +1 -1
- package/queries/query.d.ts +9 -1
- package/queries/query.js +2 -0
- package/r-bridge/data/data.d.ts +2 -2
- package/r-bridge/data/data.js +2 -2
- package/r-bridge/lang-4.x/ast/model/model.d.ts +3 -0
- package/r-bridge/lang-4.x/ast/model/model.js +3 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-access.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-access.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-argument.d.ts +29 -6
- package/r-bridge/lang-4.x/ast/model/nodes/r-argument.js +16 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-binary-op.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-binary-op.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-break.d.ts +15 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-break.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-comment.d.ts +15 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-comment.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-expression-list.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-expression-list.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-for-loop.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-for-loop.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-call.d.ts +19 -4
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-call.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.d.ts +21 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.js +16 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-if-then-else.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-if-then-else.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-line-directive.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-line-directive.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-logical.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-logical.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-next.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-next.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-number.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-parameter.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-parameter.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-pipe.d.ts +25 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-pipe.js +15 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-string.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-symbol.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-symbol.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-unary-op.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-unary-op.js +2 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-while-loop.d.ts +16 -1
- package/r-bridge/lang-4.x/ast/model/nodes/r-while-loop.js +2 -0
- package/r-bridge/lang-4.x/ast/model/versions.d.ts +2 -0
- package/r-bridge/lang-4.x/ast/model/versions.js +3 -1
- package/r-bridge/roxygen2/documentation-provider.js +15 -6
- package/r-bridge/roxygen2/roxygen-ast.d.ts +3 -1
- package/search/flowr-search-builder.js +3 -2
- package/search/search-executor/search-generators.js +1 -1
- package/slicing/criterion/parse.d.ts +11 -10
- package/slicing/criterion/parse.js +9 -8
- package/slicing/static/static-slicer.js +24 -1
- package/util/collections/arrays.d.ts +4 -0
- package/util/collections/arrays.js +7 -0
- package/util/mermaid/ast.js +2 -1
- package/util/mermaid/dfg.js +2 -1
- package/util/record.d.ts +23 -0
- package/util/record.js +33 -0
- package/util/version.js +1 -1
- package/abstract-interpretation/domains/mapped-abstract-domain.d.ts +0 -41
- package/abstract-interpretation/domains/mapped-abstract-domain.js +0 -213
|
@@ -2,7 +2,7 @@ import { type DataflowInformation } from '../../../../info';
|
|
|
2
2
|
import { type DataflowProcessorInformation } from '../../../../processor';
|
|
3
3
|
import type { RNode } from '../../../../../r-bridge/lang-4.x/ast/model/model';
|
|
4
4
|
import type { ParentInformation } from '../../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
5
|
-
import { EmptyArgument, type
|
|
5
|
+
import { EmptyArgument, type PotentiallyEmptyRArgument } from '../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
6
6
|
import type { DataflowGraph, FunctionArgument } from '../../../../graph/graph';
|
|
7
7
|
import type { NodeId } from '../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
8
8
|
import type { REnvironmentInformation } from '../../../../environments/environment';
|
|
@@ -15,7 +15,7 @@ export interface ForceArguments {
|
|
|
15
15
|
}
|
|
16
16
|
export interface ProcessAllArgumentInput<OtherInfo> extends ForceArguments {
|
|
17
17
|
readonly functionName: DataflowInformation;
|
|
18
|
-
readonly args: readonly (RNode<OtherInfo & ParentInformation> |
|
|
18
|
+
readonly args: readonly (RNode<OtherInfo & ParentInformation> | PotentiallyEmptyRArgument<OtherInfo & ParentInformation>)[];
|
|
19
19
|
readonly data: DataflowProcessorInformation<OtherInfo & ParentInformation>;
|
|
20
20
|
readonly finalGraph: DataflowGraph;
|
|
21
21
|
readonly functionRootId: NodeId;
|
|
@@ -69,6 +69,7 @@ function convertFnArgument(arg) {
|
|
|
69
69
|
else {
|
|
70
70
|
return {
|
|
71
71
|
nodeId: arg.info.id,
|
|
72
|
+
valueId: arg.value?.info.id,
|
|
72
73
|
name: arg.name.content,
|
|
73
74
|
cds: undefined,
|
|
74
75
|
type: identifier_1.ReferenceType.Argument
|
|
@@ -88,15 +89,16 @@ function processAllArguments({ functionName, args, data, finalGraph, functionRoo
|
|
|
88
89
|
let i = -1;
|
|
89
90
|
for (const arg of args) {
|
|
90
91
|
i++;
|
|
92
|
+
data = { ...data, environment: argEnv };
|
|
91
93
|
data = patchData?.(data, i) ?? data;
|
|
92
94
|
if (arg === r_function_call_1.EmptyArgument) {
|
|
93
95
|
callArgs.push(r_function_call_1.EmptyArgument);
|
|
94
96
|
processedArguments.push(undefined);
|
|
95
97
|
continue;
|
|
96
98
|
}
|
|
97
|
-
const processed = (0, processor_1.processDataflowFor)(arg,
|
|
99
|
+
const processed = (0, processor_1.processDataflowFor)(arg, data);
|
|
98
100
|
if (r_argument_1.RArgument.isWithValue(arg) && (forceArgs === 'all' || forceArgs[i]) && !model_1.RConstant.is(arg.value)) {
|
|
99
|
-
forceVertexArgumentValueReferences(functionRootId, processed, processed.graph,
|
|
101
|
+
forceVertexArgumentValueReferences(functionRootId, processed, processed.graph, data.environment);
|
|
100
102
|
}
|
|
101
103
|
processedArguments.push(processed);
|
|
102
104
|
finalEnv = (0, overwrite_1.overwriteEnvironment)(finalEnv, processed.environment);
|
|
@@ -107,7 +109,7 @@ function processAllArguments({ functionName, args, data, finalGraph, functionRoo
|
|
|
107
109
|
// check if it is called directly
|
|
108
110
|
const inId = ingoing.nodeId;
|
|
109
111
|
const refType = finalGraph.getVertex(inId)?.tag === vertex_1.VertexType.FunctionCall ? identifier_1.ReferenceType.Function : identifier_1.ReferenceType.Unknown;
|
|
110
|
-
const tryToResolve = ingoing.name ? (0, resolve_by_name_1.resolveByName)(ingoing.name,
|
|
112
|
+
const tryToResolve = ingoing.name ? (0, resolve_by_name_1.resolveByName)(ingoing.name, data.environment, refType) : undefined;
|
|
111
113
|
if (tryToResolve === undefined) {
|
|
112
114
|
remainingReadInArgs.push(ingoing);
|
|
113
115
|
}
|
|
@@ -134,7 +136,7 @@ function processAllArguments({ functionName, args, data, finalGraph, functionRoo
|
|
|
134
136
|
callArgs.push({ nodeId: processed.entryPoint, cds: undefined, type: identifier_1.ReferenceType.Argument });
|
|
135
137
|
}
|
|
136
138
|
else {
|
|
137
|
-
callArgs.push({ nodeId: processed.entryPoint, name: arg.name.content, cds: undefined, type: identifier_1.ReferenceType.Argument });
|
|
139
|
+
callArgs.push({ nodeId: processed.entryPoint, valueId: arg.value?.info.id, name: arg.name.content, cds: undefined, type: identifier_1.ReferenceType.Argument });
|
|
138
140
|
}
|
|
139
141
|
finalGraph.addEdge(functionRootId, processed.entryPoint, edge_1.EdgeType.Argument);
|
|
140
142
|
}
|
|
@@ -3,7 +3,7 @@ import type { DataflowInformation } from '../../../../info';
|
|
|
3
3
|
import { type ForceArguments } from './common';
|
|
4
4
|
import type { RSymbol } from '../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
|
|
5
5
|
import type { ParentInformation } from '../../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
6
|
-
import type {
|
|
6
|
+
import type { PotentiallyEmptyRArgument } from '../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
7
7
|
import type { NodeId } from '../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
8
8
|
import type { RNode } from '../../../../../r-bridge/lang-4.x/ast/model/model';
|
|
9
9
|
import { type IdentifierReference } from '../../../../environments/identifier';
|
|
@@ -14,7 +14,7 @@ export interface ProcessKnownFunctionCallInput<OtherInfo> extends ForceArguments
|
|
|
14
14
|
/** The name of the function being called. */
|
|
15
15
|
readonly name: RSymbol<OtherInfo & ParentInformation>;
|
|
16
16
|
/** The arguments to the function call. */
|
|
17
|
-
readonly args: readonly (RNode<OtherInfo & ParentInformation> |
|
|
17
|
+
readonly args: readonly (RNode<OtherInfo & ParentInformation> | PotentiallyEmptyRArgument<OtherInfo & ParentInformation>)[];
|
|
18
18
|
/** The node ID to use for the function call vertex. */
|
|
19
19
|
readonly rootId: NodeId;
|
|
20
20
|
/** The dataflow processor information at the point of the function call. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { DataflowProcessorInformation } from '../../../../processor';
|
|
2
2
|
import { DataflowInformation } from '../../../../info';
|
|
3
3
|
import type { ParentInformation } from '../../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
4
|
-
import type {
|
|
4
|
+
import type { PotentiallyEmptyRArgument } from '../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
5
5
|
import type { RSymbol } from '../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
|
|
6
6
|
import type { NodeId } from '../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
7
7
|
import type { DataflowGraph } from '../../../../graph/graph';
|
|
@@ -13,4 +13,4 @@ export declare function markAsOnlyBuiltIn(graph: DataflowGraph, rootId: NodeId):
|
|
|
13
13
|
* Processes a named function call within the dataflow analysis.
|
|
14
14
|
* For example, `myFunction(arg1, arg2)`, resolves against the environment.
|
|
15
15
|
*/
|
|
16
|
-
export declare function processNamedCall<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly
|
|
16
|
+
export declare function processNamedCall<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly PotentiallyEmptyRArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>): DataflowInformation;
|
|
@@ -23,7 +23,7 @@ function processFunctionParameter(parameter, data) {
|
|
|
23
23
|
for (const writtenNode of writtenNodes) {
|
|
24
24
|
const wid = writtenNode.nodeId;
|
|
25
25
|
(0, log_1.expensiveTrace)(log_1.log, () => `parameter ${writtenNode.name} (${wid}) is defined at id ${writtenNode.definedAt} with ${defaultValue === undefined ? 'no default value' : ' a default value'}`);
|
|
26
|
-
graph.setDefinitionOfVertex(writtenNode);
|
|
26
|
+
graph.setDefinitionOfVertex(writtenNode, defaultValue?.entryPoint ? [defaultValue?.entryPoint] : []);
|
|
27
27
|
environment = (0, define_1.define)(writtenNode, false, environment);
|
|
28
28
|
if (defaultValue !== undefined) {
|
|
29
29
|
if (r_function_definition_1.RFunctionDefinition.is(parameter.defaultValue)) {
|
|
@@ -282,7 +282,8 @@ We welcome every contribution! Please check out the ${ctx.linkPage('wiki/Onboard
|
|
|
282
282
|
|
|
283
283
|
*flowr* is actively developed by [Florian Sihler](https://eagleoutice.github.io/portfolio/) and (since October 1st 2025) [Oliver Gerstl](https://www.linkedin.com/in/oliver-gerstl) under the
|
|
284
284
|
[GPLv3 License](LICENSE).\\
|
|
285
|
-
It is partially supported by the German Research Foundation (DFG) under the grant [504226141](https://gepris.dfg.de/gepris/projekt/504226141) ("CodeInspector")
|
|
285
|
+
It is partially supported by the German Research Foundation (DFG) under the grant [504226141](https://gepris.dfg.de/gepris/projekt/504226141) ("CodeInspector")
|
|
286
|
+
and received an unrestricted gift from [Posit](https://posit.co/), the open-source data science company.
|
|
286
287
|
|
|
287
288
|
----
|
|
288
289
|
|
|
@@ -4,15 +4,16 @@ exports.WikiAbsint = void 0;
|
|
|
4
4
|
const absint_visitor_1 = require("../abstract-interpretation/absint-visitor");
|
|
5
5
|
const abstract_domain_1 = require("../abstract-interpretation/domains/abstract-domain");
|
|
6
6
|
const interval_domain_1 = require("../abstract-interpretation/domains/interval-domain");
|
|
7
|
+
const lattice_1 = require("../abstract-interpretation/domains/lattice");
|
|
7
8
|
const state_abstract_domain_1 = require("../abstract-interpretation/domains/state-abstract-domain");
|
|
8
9
|
const semantic_cfg_guided_visitor_1 = require("../control-flow/semantic-cfg-guided-visitor");
|
|
10
|
+
const identifier_1 = require("../dataflow/environments/identifier");
|
|
9
11
|
const cfg_kind_1 = require("../project/cfg-kind");
|
|
10
12
|
const flowr_analyzer_builder_1 = require("../project/flowr-analyzer-builder");
|
|
11
13
|
const r_function_call_1 = require("../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
12
14
|
const doc_code_1 = require("./doc-util/doc-code");
|
|
13
15
|
const doc_structure_1 = require("./doc-util/doc-structure");
|
|
14
16
|
const doc_maker_1 = require("./wiki-mk/doc-maker");
|
|
15
|
-
const identifier_1 = require("../dataflow/environments/identifier");
|
|
16
17
|
class IntervalInferenceVisitor extends absint_visitor_1.AbstractInterpretationVisitor {
|
|
17
18
|
onNumberConstant({ vertex, node }) {
|
|
18
19
|
super.onNumberConstant({ vertex, node });
|
|
@@ -51,12 +52,12 @@ async function inferIntervals() {
|
|
|
51
52
|
const dfg = (await analyzer.dataflow()).graph;
|
|
52
53
|
const cfg = await analyzer.controlflow(undefined, cfg_kind_1.CfgKind.NoFunctionDefs);
|
|
53
54
|
const ctx = analyzer.inspectContext();
|
|
54
|
-
const inference = new IntervalInferenceVisitor({ controlFlow: cfg, dfg: dfg, normalizedAst: ast, ctx: ctx });
|
|
55
|
+
const inference = new IntervalInferenceVisitor({ controlFlow: cfg, dfg: dfg, normalizedAst: ast, ctx: ctx }, interval_domain_1.IntervalDomain.top());
|
|
55
56
|
inference.start();
|
|
56
57
|
const result = inference.getEndState();
|
|
57
|
-
return result.value.entries().toArray()
|
|
58
|
+
return result.isValue() ? result.value.entries().toArray()
|
|
58
59
|
.map(([id, value]) => `${nodeIdToSlicingCriterion(id, ast.idMap)} -> ${value.toString()}`)
|
|
59
|
-
.join('\n');
|
|
60
|
+
.join('\n') : lattice_1.BottomSymbol;
|
|
60
61
|
}
|
|
61
62
|
function nodeIdToSlicingCriterion(id, idMap) {
|
|
62
63
|
const node = idMap.get(id);
|
|
@@ -135,7 +136,7 @@ If we now want to run the interval inference, we can write the following code:
|
|
|
135
136
|
|
|
136
137
|
${ctx.code(inferIntervals, { dropLinesStart: 1, dropLinesEnd: 5 })}
|
|
137
138
|
|
|
138
|
-
We first need a ${ctx.linkPage('wiki/Analyzer', 'flowR analyzer')} (in this case, using the ${ctx.linkPage('wiki/Engines', 'tree-sitter engine')}). In this example, we want to analyze a small example code that assigns \`42\` to the variable \`x\`, randomly assigns \`6\` or \`12\` to the variable \`y\`, and assignes the sum of \`x\` and \`y\` to the variable \`z\`. For the abstract interpretation visitor, we need to retrieve the ${ctx.linkPage('wiki/Normalized AST', 'normalized AST')}, ${ctx.linkPage('wiki/Dataflow Graph', 'dataflow graph')}, ${ctx.linkPage('wiki/Control Flow Graph', 'control flow graph')},
|
|
139
|
+
We first need a ${ctx.linkPage('wiki/Analyzer', 'flowR analyzer')} (in this case, using the ${ctx.linkPage('wiki/Engines', 'tree-sitter engine')}). In this example, we want to analyze a small example code that assigns \`42\` to the variable \`x\`, randomly assigns \`6\` or \`12\` to the variable \`y\`, and assignes the sum of \`x\` and \`y\` to the variable \`z\`. For the abstract interpretation visitor, we need to retrieve the ${ctx.linkPage('wiki/Normalized AST', 'normalized AST')}, ${ctx.linkPage('wiki/Dataflow Graph', 'dataflow graph')}, ${ctx.linkPage('wiki/Control Flow Graph', 'control flow graph')}, context of the flowR anaylzer, and provide a value domain for the state domain. For performance reasons, we construct the control flow graph without simplification passes, data flow information, and function definitions. We then create a new ${ctx.link(IntervalInferenceVisitor)} using the control flow graph, dataflow graph, normalized AST, and analyzer context, and start the visitor using ${ctx.linkM(absint_visitor_1.AbstractInterpretationVisitor, 'start', { hideClass: true })}. After the visitor is finished, we retrieve the inferred abstract state at the end of the program using ${ctx.linkM(absint_visitor_1.AbstractInterpretationVisitor, 'getEndState', { hideClass: true })}.
|
|
139
140
|
|
|
140
141
|
If we now print the inferred abstract state at the end of the program, we get the following output:
|
|
141
142
|
|
|
@@ -355,8 +355,6 @@ ${ctx.link(flowr_analyzer_context_1.contextFromSources)} to create a context fro
|
|
|
355
355
|
|
|
356
356
|
If for whatever reason you need to reset the context during an analysis, you can use
|
|
357
357
|
${ctx.linkM(flowr_analyzer_context_1.FlowrAnalyzerContext, 'reset')}.
|
|
358
|
-
To pre-compute all possible information in the context before starting the main analysis, you can use
|
|
359
|
-
${ctx.linkM(flowr_analyzer_context_1.FlowrAnalyzerContext, 'resolvePreAnalysis')}.
|
|
360
358
|
|
|
361
359
|
${(0, doc_structure_1.section)('Files Context', 3)}
|
|
362
360
|
|
|
@@ -123,6 +123,12 @@ df[6, "value"]
|
|
|
123
123
|
rule(knownParser, 'dead-code', 'DeadCodeConfig', 'DEAD_CODE', 'lint-dead-code', 'if(TRUE) 1 else 2', tagTypes);
|
|
124
124
|
rule(knownParser, 'useless-loop', 'UselessLoopConfig', 'USELESS_LOOP', 'lint-useless-loop', 'for(i in c(1)) { print(i) }', tagTypes);
|
|
125
125
|
rule(knownParser, 'stop-call', 'StopWithCallConfig', 'STOP_WITH_CALL_ARG', 'lint-stop-call', 'stop(42)', tagTypes);
|
|
126
|
+
rule(knownParser, 'roxygen-arguments', 'RoxygenArgsConfig', 'ROXYGEN_ARGS', 'lint-roxygen-arguments', '#\' A function with two parameters, but only only one documented\n#\' @param a A variable\nf = function(a, b){return a;}', tagTypes);
|
|
127
|
+
rule(knownParser, 'problematic-eval', 'ProblematicEvalConfig', 'PROBLEMATIC_EVAL', 'lint-problematic-eval', `
|
|
128
|
+
function(x) {
|
|
129
|
+
eval(x)
|
|
130
|
+
}
|
|
131
|
+
`, tagTypes);
|
|
126
132
|
function rule(parser, name, configType, ruleType, testfile, example, types) {
|
|
127
133
|
const rule = linter_rules_1.LintingRules[name];
|
|
128
134
|
const tags = rule.info.tags.toSorted((a, b) => {
|
|
@@ -6,7 +6,6 @@ const doc_normalized_ast_1 = require("./doc-util/doc-normalized-ast");
|
|
|
6
6
|
const doc_files_1 = require("./doc-util/doc-files");
|
|
7
7
|
const doc_cli_option_1 = require("./doc-util/doc-cli-option");
|
|
8
8
|
const doc_structure_1 = require("./doc-util/doc-structure");
|
|
9
|
-
const retriever_1 = require("../r-bridge/retriever");
|
|
10
9
|
const normalized_ast_fold_1 = require("../abstract-interpretation/normalized-ast-fold");
|
|
11
10
|
const flowr_analyzer_1 = require("../project/flowr-analyzer");
|
|
12
11
|
const flowr_analyzer_builder_1 = require("../project/flowr-analyzer-builder");
|
|
@@ -17,6 +16,12 @@ const r_binary_op_1 = require("../r-bridge/lang-4.x/ast/model/nodes/r-binary-op"
|
|
|
17
16
|
const model_1 = require("../r-bridge/lang-4.x/ast/model/model");
|
|
18
17
|
const r_project_1 = require("../r-bridge/lang-4.x/ast/model/nodes/r-project");
|
|
19
18
|
const r_expression_list_1 = require("../r-bridge/lang-4.x/ast/model/nodes/r-expression-list");
|
|
19
|
+
async function simpleNormalizedAst(code) {
|
|
20
|
+
const analyzer = await new flowr_analyzer_builder_1.FlowrAnalyzerBuilder().build();
|
|
21
|
+
analyzer.addRequest(code);
|
|
22
|
+
const result = await analyzer.normalize();
|
|
23
|
+
return result.ast;
|
|
24
|
+
}
|
|
20
25
|
async function quickNormalizedAstMultipleFiles() {
|
|
21
26
|
const analyzer = await new flowr_analyzer_builder_1.FlowrAnalyzerBuilder()
|
|
22
27
|
.setEngine('tree-sitter')
|
|
@@ -141,12 +146,7 @@ The following segments intend to give you an overview of how to work with the no
|
|
|
141
146
|
As explained alongside the [Interface](${doc_files_1.FlowrWikiBaseRef}/Interface#creating-flowr-analyses) wiki page, you can use an instance of
|
|
142
147
|
${ctx.link(flowr_analyzer_1.FlowrAnalyzer)} to get the ${ctx.link('NormalizedAst')}:
|
|
143
148
|
|
|
144
|
-
${(
|
|
145
|
-
async function getAst(code: string): Promise<RNode> {
|
|
146
|
-
const analyzer = await new FlowrAnalyzerBuilder(${retriever_1.requestFromInput.name}(code.trim())).build();
|
|
147
|
-
const result = analyzer.normalizedAst();
|
|
148
|
-
return result.ast;
|
|
149
|
-
}`)}
|
|
149
|
+
${ctx.code(simpleNormalizedAst, { dropLinesStart: 1, dropLinesEnd: 2, hideDefinedAt: true })}
|
|
150
150
|
|
|
151
151
|
From the REPL, you can use the ${(0, doc_cli_option_1.getReplCommand)('normalize')} command.
|
|
152
152
|
|
package/linter/linter-rules.d.ts
CHANGED
|
@@ -202,7 +202,7 @@ export declare const LintingRules: {
|
|
|
202
202
|
};
|
|
203
203
|
};
|
|
204
204
|
readonly 'dataframe-access-validation': {
|
|
205
|
-
readonly createSearch: () => import("../search/flowr-search-builder").FlowrSearchBuilder<"all", [
|
|
205
|
+
readonly createSearch: () => import("../search/flowr-search-builder").FlowrSearchBuilder<"all", [], import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../search/flowr-search").FlowrSearchElements<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../search/flowr-search").FlowrSearchElement<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>;
|
|
206
206
|
readonly processSearchResult: (elements: import("../search/flowr-search").FlowrSearchElements<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../search/flowr-search").FlowrSearchElement<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>, config: import("./rules/dataframe-access-validation").DataFrameAccessValidationConfig, data: {
|
|
207
207
|
normalize: import("../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
208
208
|
dataflow: import("../dataflow/info").DataflowInformation;
|
|
@@ -281,6 +281,31 @@ export declare const LintingRules: {
|
|
|
281
281
|
};
|
|
282
282
|
};
|
|
283
283
|
};
|
|
284
|
+
readonly 'problematic-eval': {
|
|
285
|
+
readonly createSearch: (config: import("./rules/problematic-eval").ProblematicEvalConfig) => import("../search/flowr-search-builder").FlowrSearchBuilder<"from-query", [], import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../search/flowr-search").FlowrSearchElements<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../search/flowr-search").FlowrSearchElement<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>;
|
|
286
|
+
readonly processSearchResult: (elements: import("../search/flowr-search").FlowrSearchElements<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../search/flowr-search").FlowrSearchElement<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>, _config: import("./rules/problematic-eval").ProblematicEvalConfig, data: {
|
|
287
|
+
normalize: import("../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
288
|
+
dataflow: import("../dataflow/info").DataflowInformation;
|
|
289
|
+
cfg: import("../control-flow/control-flow-graph").ControlFlowInformation;
|
|
290
|
+
analyzer: import("../project/flowr-analyzer").ReadonlyFlowrAnalysisProvider;
|
|
291
|
+
}) => Promise<{
|
|
292
|
+
results: import("./rules/problematic-eval").ProblematicEvalResult[];
|
|
293
|
+
".meta": import("./rules/problematic-eval").ProblematicEvalMetadata;
|
|
294
|
+
}>;
|
|
295
|
+
readonly prettyPrint: {
|
|
296
|
+
readonly query: (result: import("./rules/problematic-eval").ProblematicEvalResult) => string;
|
|
297
|
+
readonly full: (result: import("./rules/problematic-eval").ProblematicEvalResult) => string;
|
|
298
|
+
};
|
|
299
|
+
readonly info: {
|
|
300
|
+
readonly name: "Problematic eval";
|
|
301
|
+
readonly description: "Detects uses of eval-like functions whose inputs are not statically constant. Prints the computed input-sources for the eval and flags usages that depend on non-constant/trusted inputs.";
|
|
302
|
+
readonly tags: readonly [import("./linter-tags").LintingRuleTag.Security, import("./linter-tags").LintingRuleTag.Smell, import("./linter-tags").LintingRuleTag.Readability, import("./linter-tags").LintingRuleTag.Performance];
|
|
303
|
+
readonly certainty: import("./linter-format").LintingRuleCertainty.BestEffort;
|
|
304
|
+
readonly defaultConfig: {
|
|
305
|
+
readonly considerAsEval: "^eval$";
|
|
306
|
+
};
|
|
307
|
+
};
|
|
308
|
+
};
|
|
284
309
|
readonly 'stop-call': {
|
|
285
310
|
readonly createSearch: () => import("../search/flowr-search-builder").FlowrSearchBuilder<"get", ["filter"], import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, Promise<import("../search/flowr-search").FlowrSearchElements<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, [] | import("../search/flowr-search").FlowrSearchElement<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>>;
|
|
286
311
|
readonly processSearchResult: (elements: import("../search/flowr-search").FlowrSearchElements<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../search/flowr-search").FlowrSearchElement<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>, _config: import("../util/objects").MergeableRecord, { dataflow, analyzer }: {
|
|
@@ -304,6 +329,29 @@ export declare const LintingRules: {
|
|
|
304
329
|
readonly defaultConfig: {};
|
|
305
330
|
};
|
|
306
331
|
};
|
|
332
|
+
readonly 'roxygen-arguments': {
|
|
333
|
+
readonly createSearch: () => import("../search/flowr-search-builder").FlowrSearchBuilder<"all", ["filter"], import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, Promise<import("../search/flowr-search").FlowrSearchElements<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, [] | import("../search/flowr-search").FlowrSearchElement<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>>;
|
|
334
|
+
readonly processSearchResult: (elements: import("../search/flowr-search").FlowrSearchElements<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../search/flowr-search").FlowrSearchElement<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>, _config: import("../util/objects").MergeableRecord, { normalize }: {
|
|
335
|
+
normalize: import("../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
336
|
+
dataflow: import("../dataflow/info").DataflowInformation;
|
|
337
|
+
cfg: import("../control-flow/control-flow-graph").ControlFlowInformation;
|
|
338
|
+
analyzer: import("../project/flowr-analyzer").ReadonlyFlowrAnalysisProvider;
|
|
339
|
+
}) => {
|
|
340
|
+
results: import("ts-essentials").Writable<import("./rules/roxygen-arguments").RoxygenArgsResult>[];
|
|
341
|
+
'.meta': {};
|
|
342
|
+
};
|
|
343
|
+
readonly prettyPrint: {
|
|
344
|
+
readonly query: (result: import("./rules/roxygen-arguments").RoxygenArgsResult) => string;
|
|
345
|
+
readonly full: (result: import("./rules/roxygen-arguments").RoxygenArgsResult) => string;
|
|
346
|
+
};
|
|
347
|
+
readonly info: {
|
|
348
|
+
readonly name: "Roxygen Arguments";
|
|
349
|
+
readonly tags: readonly [import("./linter-tags").LintingRuleTag.Smell, import("./linter-tags").LintingRuleTag.Documentation, import("./linter-tags").LintingRuleTag.Style];
|
|
350
|
+
readonly certainty: import("./linter-format").LintingRuleCertainty.BestEffort;
|
|
351
|
+
readonly description: "Checks whether a function has undocumented or overdocumented parameters";
|
|
352
|
+
readonly defaultConfig: {};
|
|
353
|
+
};
|
|
354
|
+
};
|
|
307
355
|
};
|
|
308
356
|
export type LintingRuleNames = keyof typeof LintingRules;
|
|
309
357
|
export type LintingRuleMetadata<Name extends LintingRuleNames> = typeof LintingRules[Name] extends LintingRule<infer _Result, infer Metadata, infer _Config, infer _Info, infer _Elements> ? Metadata : never;
|
package/linter/linter-rules.js
CHANGED
|
@@ -12,6 +12,8 @@ const dataframe_access_validation_1 = require("./rules/dataframe-access-validati
|
|
|
12
12
|
const useless_loop_1 = require("./rules/useless-loop");
|
|
13
13
|
const network_functions_1 = require("./rules/network-functions");
|
|
14
14
|
const stop_with_call_arg_1 = require("./rules/stop-with-call-arg");
|
|
15
|
+
const roxygen_arguments_1 = require("./rules/roxygen-arguments");
|
|
16
|
+
const problematic_eval_1 = require("./rules/problematic-eval");
|
|
15
17
|
/**
|
|
16
18
|
* The registry of currently supported linting rules.
|
|
17
19
|
* A linting rule can be executed on a dataflow pipeline result using {@link executeLintingRule}.
|
|
@@ -27,6 +29,8 @@ exports.LintingRules = {
|
|
|
27
29
|
'dataframe-access-validation': dataframe_access_validation_1.DATA_FRAME_ACCESS_VALIDATION,
|
|
28
30
|
'dead-code': dead_code_1.DEAD_CODE,
|
|
29
31
|
'useless-loop': useless_loop_1.USELESS_LOOP,
|
|
30
|
-
'
|
|
32
|
+
'problematic-eval': problematic_eval_1.PROBLEMATIC_EVAL,
|
|
33
|
+
'stop-call': stop_with_call_arg_1.STOP_WITH_CALL_ARG,
|
|
34
|
+
'roxygen-arguments': roxygen_arguments_1.ROXYGEN_ARGS
|
|
31
35
|
};
|
|
32
36
|
//# sourceMappingURL=linter-rules.js.map
|
|
@@ -29,7 +29,7 @@ export interface DataFrameAccessValidationMetadata extends MergeableRecord {
|
|
|
29
29
|
totalAccessed: number;
|
|
30
30
|
}
|
|
31
31
|
export declare const DATA_FRAME_ACCESS_VALIDATION: {
|
|
32
|
-
readonly createSearch: () => import("../../search/flowr-search-builder").FlowrSearchBuilder<"all", [
|
|
32
|
+
readonly createSearch: () => import("../../search/flowr-search-builder").FlowrSearchBuilder<"all", [], ParentInformation, FlowrSearchElements<ParentInformation, import("../../search/flowr-search").FlowrSearchElement<ParentInformation>[]>>;
|
|
33
33
|
readonly processSearchResult: (elements: FlowrSearchElements<ParentInformation, import("../../search/flowr-search").FlowrSearchElement<ParentInformation>[]>, config: DataFrameAccessValidationConfig, data: {
|
|
34
34
|
normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
35
35
|
dataflow: import("../../dataflow/info").DataflowInformation;
|
|
@@ -3,18 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.DATA_FRAME_ACCESS_VALIDATION = void 0;
|
|
4
4
|
const shape_inference_1 = require("../../abstract-interpretation/data-frame/shape-inference");
|
|
5
5
|
const satisfiable_domain_1 = require("../../abstract-interpretation/domains/satisfiable-domain");
|
|
6
|
+
const config_1 = require("../../config");
|
|
7
|
+
const identifier_1 = require("../../dataflow/environments/identifier");
|
|
6
8
|
const cfg_kind_1 = require("../../project/cfg-kind");
|
|
7
9
|
const type_1 = require("../../r-bridge/lang-4.x/ast/model/type");
|
|
8
10
|
const flowr_search_builder_1 = require("../../search/flowr-search-builder");
|
|
9
|
-
const search_enrichers_1 = require("../../search/search-executor/search-enrichers");
|
|
10
11
|
const logic_1 = require("../../util/logic");
|
|
11
12
|
const range_1 = require("../../util/range");
|
|
12
13
|
const linter_format_1 = require("../linter-format");
|
|
13
14
|
const linter_tags_1 = require("../linter-tags");
|
|
14
|
-
const identifier_1 = require("../../dataflow/environments/identifier");
|
|
15
|
-
const config_1 = require("../../config");
|
|
16
15
|
exports.DATA_FRAME_ACCESS_VALIDATION = {
|
|
17
|
-
createSearch: () => flowr_search_builder_1.Q.all()
|
|
16
|
+
createSearch: () => flowr_search_builder_1.Q.all(),
|
|
18
17
|
processSearchResult: async (elements, config, data) => {
|
|
19
18
|
let ctx = data.analyzer.inspectContext();
|
|
20
19
|
ctx = {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type LintingResult, LintingRuleCertainty } from '../linter-format';
|
|
2
|
+
import type { MergeableRecord } from '../../util/objects';
|
|
3
|
+
import { SourceLocation } from '../../util/range';
|
|
4
|
+
import { LintingRuleTag } from '../linter-tags';
|
|
5
|
+
import type { InputSources } from '../../queries/catalog/input-sources-query/simple-input-classifier';
|
|
6
|
+
/**
|
|
7
|
+
* Describes a linting result for a problematic eval usage, including the location of the eval call and the computed input sources that lead to it.
|
|
8
|
+
*/
|
|
9
|
+
export interface ProblematicEvalResult extends LintingResult {
|
|
10
|
+
loc: SourceLocation;
|
|
11
|
+
sources: InputSources;
|
|
12
|
+
}
|
|
13
|
+
export interface ProblematicEvalConfig extends MergeableRecord {
|
|
14
|
+
/**
|
|
15
|
+
* All calls that should be considered to be valid eval entry points, this will be interpreted as a Regex!
|
|
16
|
+
*/
|
|
17
|
+
considerAsEval: string;
|
|
18
|
+
}
|
|
19
|
+
export type ProblematicEvalMetadata = MergeableRecord;
|
|
20
|
+
export declare const PROBLEMATIC_EVAL: {
|
|
21
|
+
readonly createSearch: (config: ProblematicEvalConfig) => import("../../search/flowr-search-builder").FlowrSearchBuilder<"from-query", [], import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElements<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>;
|
|
22
|
+
readonly processSearchResult: (elements: import("../../search/flowr-search").FlowrSearchElements<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>, _config: ProblematicEvalConfig, data: {
|
|
23
|
+
normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
24
|
+
dataflow: import("../../dataflow/info").DataflowInformation;
|
|
25
|
+
cfg: import("../../control-flow/control-flow-graph").ControlFlowInformation;
|
|
26
|
+
analyzer: import("../../project/flowr-analyzer").ReadonlyFlowrAnalysisProvider;
|
|
27
|
+
}) => Promise<{
|
|
28
|
+
results: ProblematicEvalResult[];
|
|
29
|
+
".meta": ProblematicEvalMetadata;
|
|
30
|
+
}>;
|
|
31
|
+
readonly prettyPrint: {
|
|
32
|
+
readonly query: (result: ProblematicEvalResult) => string;
|
|
33
|
+
readonly full: (result: ProblematicEvalResult) => string;
|
|
34
|
+
};
|
|
35
|
+
readonly info: {
|
|
36
|
+
readonly name: "Problematic eval";
|
|
37
|
+
readonly description: "Detects uses of eval-like functions whose inputs are not statically constant. Prints the computed input-sources for the eval and flags usages that depend on non-constant/trusted inputs.";
|
|
38
|
+
readonly tags: readonly [LintingRuleTag.Security, LintingRuleTag.Smell, LintingRuleTag.Readability, LintingRuleTag.Performance];
|
|
39
|
+
readonly certainty: LintingRuleCertainty.BestEffort;
|
|
40
|
+
readonly defaultConfig: {
|
|
41
|
+
readonly considerAsEval: "^eval$";
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PROBLEMATIC_EVAL = void 0;
|
|
4
|
+
const linter_format_1 = require("../linter-format");
|
|
5
|
+
const flowr_search_builder_1 = require("../../search/flowr-search-builder");
|
|
6
|
+
const range_1 = require("../../util/range");
|
|
7
|
+
const linter_tags_1 = require("../linter-tags");
|
|
8
|
+
const simple_input_classifier_1 = require("../../queries/catalog/input-sources-query/simple-input-classifier");
|
|
9
|
+
const query_1 = require("../../queries/query");
|
|
10
|
+
const parse_1 = require("../../slicing/criterion/parse");
|
|
11
|
+
/**
|
|
12
|
+
* Format a list of input sources either as a single-line string (inline) or a block.
|
|
13
|
+
* - inline: returns a semicolon-separated single-line summary
|
|
14
|
+
* - block: returns an array of lines (to be joined with newlines by the caller)
|
|
15
|
+
*/
|
|
16
|
+
function formatInputSources(inputs, inline = true) {
|
|
17
|
+
if (!inputs || inputs.length === 0) {
|
|
18
|
+
return inline ? '' : [];
|
|
19
|
+
}
|
|
20
|
+
if (inline) {
|
|
21
|
+
return inputs.map(s => `${s.id} (type: ${Array.isArray(s.type) ? '[' + s.type.join(',') + ']' : s.type}, trace: ${s.trace}${s.cds ? ', cds: [' + s.cds.join(',') + ']' : ''})`).join('; ');
|
|
22
|
+
}
|
|
23
|
+
return inputs.map(s => `- ${s.id}: type=${Array.isArray(s.type) ? '[' + s.type.join(',') + ']' : s.type}, trace=${s.trace}${s.cds ? ', cds=[' + s.cds.join(',') + ']' : ''}`);
|
|
24
|
+
}
|
|
25
|
+
exports.PROBLEMATIC_EVAL = {
|
|
26
|
+
/* create a search that finds calls that look like eval-like functions */
|
|
27
|
+
createSearch: config => flowr_search_builder_1.Q.fromQuery({
|
|
28
|
+
type: 'call-context',
|
|
29
|
+
callName: config.considerAsEval,
|
|
30
|
+
callNameExact: false
|
|
31
|
+
}),
|
|
32
|
+
processSearchResult: async (elements, _config, data) => {
|
|
33
|
+
const results = [];
|
|
34
|
+
for (const element of elements.getElements()) {
|
|
35
|
+
const nid = element.node.info.id;
|
|
36
|
+
// run an input-sources query for this eval-like call
|
|
37
|
+
const criterion = parse_1.SlicingCriterion.fromId(nid);
|
|
38
|
+
const q = { type: 'input-sources', criterion };
|
|
39
|
+
const all = await (0, query_1.executeQueries)({ analyzer: data.analyzer }, [q]);
|
|
40
|
+
const inputSourcesResult = all['input-sources'];
|
|
41
|
+
const sources = inputSourcesResult?.results?.[criterion] ?? [];
|
|
42
|
+
// if any input is not a constant or derived constant, flag it
|
|
43
|
+
const problematic = sources.some(s => Array.isArray(s.type)
|
|
44
|
+
? s.type.some(t => t !== simple_input_classifier_1.InputType.Constant && t !== simple_input_classifier_1.InputType.DerivedConstant)
|
|
45
|
+
: (s.type !== simple_input_classifier_1.InputType.Constant && s.type !== simple_input_classifier_1.InputType.DerivedConstant));
|
|
46
|
+
if (problematic) {
|
|
47
|
+
results.push({
|
|
48
|
+
involvedId: nid,
|
|
49
|
+
certainty: sources.some(s => Array.isArray(s.type) ? s.type.includes(simple_input_classifier_1.InputType.Unknown) : s.type === simple_input_classifier_1.InputType.Unknown) ? linter_format_1.LintingResultCertainty.Uncertain : linter_format_1.LintingResultCertainty.Certain,
|
|
50
|
+
loc: range_1.SourceLocation.fromNode(element.node) ?? range_1.SourceLocation.invalid(),
|
|
51
|
+
sources
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
results,
|
|
57
|
+
'.meta': {}
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
/* helper to format input sources for pretty printing */
|
|
61
|
+
prettyPrint: {
|
|
62
|
+
[linter_format_1.LintingPrettyPrintContext.Query]: result => {
|
|
63
|
+
const inputs = result.sources ?? [];
|
|
64
|
+
const srcStr = formatInputSources(inputs, true);
|
|
65
|
+
return `Use of eval-like function at ${range_1.SourceLocation.format(result.loc)}${srcStr ? `; inputs: ${srcStr}` : ''}`;
|
|
66
|
+
},
|
|
67
|
+
[linter_format_1.LintingPrettyPrintContext.Full]: result => {
|
|
68
|
+
const inputs = result.sources ?? [];
|
|
69
|
+
const srcLines = formatInputSources(inputs, false);
|
|
70
|
+
return `Use of eval-like function at ${range_1.SourceLocation.format(result.loc)} is potentially problematic${srcLines.length ? '\nInputs:\n' + srcLines.join('\n') : ''}`;
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
info: {
|
|
74
|
+
name: 'Problematic eval',
|
|
75
|
+
description: 'Detects uses of eval-like functions whose inputs are not statically constant. Prints the computed input-sources for the eval and flags usages that depend on non-constant/trusted inputs.',
|
|
76
|
+
tags: [linter_tags_1.LintingRuleTag.Security, linter_tags_1.LintingRuleTag.Smell, linter_tags_1.LintingRuleTag.Readability, linter_tags_1.LintingRuleTag.Performance],
|
|
77
|
+
certainty: linter_format_1.LintingRuleCertainty.BestEffort,
|
|
78
|
+
defaultConfig: {
|
|
79
|
+
considerAsEval: '^eval$'
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=problematic-eval.js.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type LintingResult, LintingRuleCertainty } from '../linter-format';
|
|
2
|
+
import { SourceLocation } from '../../util/range';
|
|
3
|
+
import type { MergeableRecord } from '../../util/objects';
|
|
4
|
+
import { LintingRuleTag } from '../linter-tags';
|
|
5
|
+
import type { Writable } from 'ts-essentials';
|
|
6
|
+
export interface RoxygenArgsResult extends LintingResult {
|
|
7
|
+
readonly loc: SourceLocation;
|
|
8
|
+
readonly overDocumented?: string[];
|
|
9
|
+
readonly underDocumented?: string[];
|
|
10
|
+
}
|
|
11
|
+
export type RoxygenArgsConfig = MergeableRecord;
|
|
12
|
+
export type RoxygenArgsMetadata = MergeableRecord;
|
|
13
|
+
export declare const ROXYGEN_ARGS: {
|
|
14
|
+
readonly createSearch: () => import("../../search/flowr-search-builder").FlowrSearchBuilder<"all", ["filter"], import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, Promise<import("../../search/flowr-search").FlowrSearchElements<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, [] | import("../../search/flowr-search").FlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>>;
|
|
15
|
+
readonly processSearchResult: (elements: import("../../search/flowr-search").FlowrSearchElements<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>, _config: MergeableRecord, { normalize }: {
|
|
16
|
+
normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
17
|
+
dataflow: import("../../dataflow/info").DataflowInformation;
|
|
18
|
+
cfg: import("../../control-flow/control-flow-graph").ControlFlowInformation;
|
|
19
|
+
analyzer: import("../../project/flowr-analyzer").ReadonlyFlowrAnalysisProvider;
|
|
20
|
+
}) => {
|
|
21
|
+
results: Writable<RoxygenArgsResult>[];
|
|
22
|
+
'.meta': {};
|
|
23
|
+
};
|
|
24
|
+
readonly prettyPrint: {
|
|
25
|
+
readonly query: (result: RoxygenArgsResult) => string;
|
|
26
|
+
readonly full: (result: RoxygenArgsResult) => string;
|
|
27
|
+
};
|
|
28
|
+
readonly info: {
|
|
29
|
+
readonly name: "Roxygen Arguments";
|
|
30
|
+
readonly tags: readonly [LintingRuleTag.Smell, LintingRuleTag.Documentation, LintingRuleTag.Style];
|
|
31
|
+
readonly certainty: LintingRuleCertainty.BestEffort;
|
|
32
|
+
readonly description: "Checks whether a function has undocumented or overdocumented parameters";
|
|
33
|
+
readonly defaultConfig: {};
|
|
34
|
+
};
|
|
35
|
+
};
|