@eagleoutice/flowr 2.9.0 → 2.9.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 +26 -26
- package/benchmark/slicer.js +1 -1
- package/benchmark/summarizer/first-phase/process.js +1 -1
- package/control-flow/semantic-cfg-guided-visitor.d.ts +25 -0
- package/control-flow/semantic-cfg-guided-visitor.js +25 -0
- package/dataflow/environments/built-in-config.d.ts +1 -1
- package/dataflow/environments/built-in.d.ts +10 -0
- package/dataflow/environments/built-in.js +10 -0
- package/dataflow/environments/default-builtin-config.d.ts +50 -7
- package/dataflow/environments/default-builtin-config.js +15 -3
- package/dataflow/environments/identifier.d.ts +4 -2
- package/dataflow/environments/identifier.js +3 -1
- package/dataflow/environments/resolve-by-name.js +5 -2
- package/dataflow/eval/resolve/alias-tracking.js +8 -1
- package/dataflow/eval/resolve/resolve-argument.js +2 -2
- package/dataflow/eval/values/general.js +1 -1
- package/dataflow/eval/values/r-value.d.ts +4 -1
- package/dataflow/eval/values/r-value.js +2 -0
- package/dataflow/graph/dataflowgraph-builder.d.ts +3 -2
- package/dataflow/graph/dataflowgraph-builder.js +4 -3
- package/dataflow/graph/diff-dataflow-graph.d.ts +1 -1
- package/dataflow/graph/diff-dataflow-graph.js +5 -1
- package/dataflow/graph/graph.d.ts +66 -10
- package/dataflow/graph/graph.js +85 -22
- package/dataflow/graph/vertex.d.ts +11 -1
- package/dataflow/internal/linker.d.ts +1 -1
- package/dataflow/internal/linker.js +22 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +2 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +14 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +30 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-register-hook.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +1 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +22 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-s-seven-dispatch.d.ts +12 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-s-seven-dispatch.js +27 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-s-seven-new-generic.d.ts +19 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-s-seven-new-generic.js +210 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-s-three-dispatch.d.ts +2 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-s-three-dispatch.js +24 -2
- package/dataflow/internal/process/functions/call/named-call-handling.d.ts +1 -0
- package/dataflow/internal/process/functions/call/named-call-handling.js +1 -0
- package/dataflow/internal/process/functions/call/unnamed-call-handling.d.ts +1 -0
- package/dataflow/internal/process/functions/call/unnamed-call-handling.js +1 -0
- package/documentation/data/interface/doc-writing-code.js +1 -2
- package/documentation/wiki-dataflow-graph.js +8 -4
- package/linter/rules/naming-convention.d.ts +9 -2
- package/linter/rules/naming-convention.js +38 -36
- package/linter/rules/seeded-randomness.js +2 -2
- package/package.json +2 -1
- package/project/plugins/file-plugins/files/flowr-namespace-file.d.ts +24 -1
- package/project/plugins/file-plugins/files/flowr-namespace-file.js +61 -0
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +3 -3
- package/r-bridge/data/data.d.ts +4 -4
- package/r-bridge/data/data.js +4 -4
- package/r-bridge/lang-4.x/ast/model/model.d.ts +1 -1
- package/r-bridge/lang-4.x/ast/model/type.d.ts +1 -1
- package/r-bridge/lang-4.x/ast/model/type.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/control/normalize-if-then.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/expression/normalize-expression.js +5 -5
- package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-argument.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-call.js +4 -4
- package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-definition.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-parameter.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/main/internal/loops/normalize-break.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/loops/normalize-for.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/loops/normalize-next.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/loops/normalize-repeat.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/loops/normalize-while.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/normalize-access.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/main/internal/operators/normalize-binary.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/main/internal/operators/normalize-unary.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/other/normalize-comment.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/other/normalize-line-directive.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/main/internal/structure/normalize-expressions.js +3 -3
- package/r-bridge/lang-4.x/ast/parser/main/internal/structure/normalize-root.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/values/normalize-number.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/values/normalize-string.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/values/normalize-symbol.js +1 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +22 -22
- package/r-bridge/roxygen2/roxygen-parse.js +1 -1
- package/reconstruct/auto-select/magic-comments.js +1 -1
- package/slicing/static/slice-call.d.ts +1 -1
- package/slicing/static/slice-call.js +4 -4
- package/util/mermaid/dfg.js +5 -5
- package/util/r-value.d.ts +3 -2
- package/util/r-value.js +3 -0
- package/util/version.js +1 -1
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.S7DispatchSeparator = void 0;
|
|
4
|
+
exports.processS7Dispatch = processS7Dispatch;
|
|
5
|
+
const known_call_handling_1 = require("../known-call-handling");
|
|
6
|
+
const built_in_1 = require("../../../../../environments/built-in");
|
|
7
|
+
const identifier_1 = require("../../../../../environments/identifier");
|
|
8
|
+
/** Used to separate S7 dispatch info in identifiers */
|
|
9
|
+
exports.S7DispatchSeparator = '﹕s3﹕';
|
|
10
|
+
/**
|
|
11
|
+
* Process an S7 generic dispatch call like `S7_dispatch`.
|
|
12
|
+
*/
|
|
13
|
+
function processS7Dispatch(name, args, rootId, data) {
|
|
14
|
+
if (!('currentS7name' in data) || !Array.isArray(data.currentS7name)) {
|
|
15
|
+
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: built_in_1.BuiltInProcName.S7Dispatch }).information;
|
|
16
|
+
}
|
|
17
|
+
const info = (0, known_call_handling_1.processKnownFunctionCall)({ name, forceArgs: 'all', args, rootId, data, origin: built_in_1.BuiltInProcName.S7Dispatch }).information;
|
|
18
|
+
for (const id of data.currentS7name) {
|
|
19
|
+
if (typeof id === 'string') {
|
|
20
|
+
const newIn = info.in.slice();
|
|
21
|
+
newIn.push({ nodeId: rootId, name: id, cds: data.cds, type: identifier_1.ReferenceType.S7MethodPrefix });
|
|
22
|
+
info.in = newIn;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return info;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=built-in-s-seven-dispatch.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DataflowProcessorInformation } from '../../../../../processor';
|
|
2
|
+
import type { DataflowInformation } from '../../../../../info';
|
|
3
|
+
import type { ParentInformation } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
4
|
+
import { type RFunctionArgument } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
5
|
+
import type { RSymbol } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
|
|
6
|
+
import type { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
7
|
+
/** e.g. new_generic(name, dispatch_args, fun=NULL) */
|
|
8
|
+
interface S7GenericDispatchConfig {
|
|
9
|
+
args: {
|
|
10
|
+
name: string;
|
|
11
|
+
dispatchArg: string | undefined;
|
|
12
|
+
fun: string;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Process an S7 new generic dispatch call like `new_generic` or `setGeneric`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function processS7NewGeneric<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, config: S7GenericDispatchConfig): DataflowInformation;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processS7NewGeneric = processS7NewGeneric;
|
|
4
|
+
const known_call_handling_1 = require("../known-call-handling");
|
|
5
|
+
const logger_1 = require("../../../../../logger");
|
|
6
|
+
const linker_1 = require("../../../../linker");
|
|
7
|
+
const common_1 = require("../common");
|
|
8
|
+
const unpack_argument_1 = require("../argument/unpack-argument");
|
|
9
|
+
const r_argument_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-argument");
|
|
10
|
+
const built_in_1 = require("../../../../../environments/built-in");
|
|
11
|
+
const edge_1 = require("../../../../../graph/edge");
|
|
12
|
+
const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
|
|
13
|
+
const range_1 = require("../../../../../../util/range");
|
|
14
|
+
const assert_1 = require("../../../../../../util/assert");
|
|
15
|
+
const identifier_1 = require("../../../../../environments/identifier");
|
|
16
|
+
const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
|
|
17
|
+
const r_value_1 = require("../../../../../eval/values/r-value");
|
|
18
|
+
const vertex_1 = require("../../../../../graph/vertex");
|
|
19
|
+
/**
|
|
20
|
+
* Process an S7 new generic dispatch call like `new_generic` or `setGeneric`.
|
|
21
|
+
*/
|
|
22
|
+
function processS7NewGeneric(name, args, rootId, data, config) {
|
|
23
|
+
if (args.length < 1) {
|
|
24
|
+
logger_1.dataflowLogger.warn('empty s7 new_generic, skipping');
|
|
25
|
+
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
|
|
26
|
+
}
|
|
27
|
+
const params = {
|
|
28
|
+
[config.args.name]: 'name',
|
|
29
|
+
};
|
|
30
|
+
if (config.args.dispatchArg) {
|
|
31
|
+
params[config.args.dispatchArg] = 'dispatchArg';
|
|
32
|
+
}
|
|
33
|
+
params[config.args.fun] = 'fun';
|
|
34
|
+
params['...'] = '...';
|
|
35
|
+
const argMaps = (0, linker_1.invertArgumentMap)((0, linker_1.pMatch)((0, common_1.convertFnArguments)(args), params));
|
|
36
|
+
const genName = (0, unpack_argument_1.unpackArg)((0, r_argument_1.getArgumentWithId)(args, argMaps.get('name')?.[0]));
|
|
37
|
+
if (!genName) {
|
|
38
|
+
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
|
|
39
|
+
}
|
|
40
|
+
const n = (0, alias_tracking_1.resolveIdToValue)(genName.info.id, { environment: data.environment, resolve: data.ctx.config.solver.variables, idMap: data.completeAst.idMap, full: true, ctx: data.ctx });
|
|
41
|
+
const accessedIdentifiers = [];
|
|
42
|
+
if (n.type === 'set') {
|
|
43
|
+
for (const elem of n.elements) {
|
|
44
|
+
if (elem.type === 'string' && (0, r_value_1.isValue)(elem.value)) {
|
|
45
|
+
accessedIdentifiers.push(elem.value.str);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (accessedIdentifiers.length === 0) {
|
|
50
|
+
logger_1.dataflowLogger.warn('s7 new_generic non-resolvable skipping');
|
|
51
|
+
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
|
|
52
|
+
}
|
|
53
|
+
data = { ...data, currentS7name: accessedIdentifiers };
|
|
54
|
+
let funArg = (0, unpack_argument_1.unpackArg)((0, r_argument_1.getArgumentWithId)(args, argMaps.get('fun')?.[0]))?.info.id;
|
|
55
|
+
const effectiveArgs = args.slice();
|
|
56
|
+
if (!funArg) {
|
|
57
|
+
const dispatchArg = (0, unpack_argument_1.unpackArg)((0, r_argument_1.getArgumentWithId)(args, argMaps.get('dispatchArg')?.[0]));
|
|
58
|
+
const newFun = makeS7DispatchFDef(name, [dispatchArg?.lexeme ?? undefined], rootId, args.length, data.completeAst.idMap);
|
|
59
|
+
// fake it 'function([dispatch_args],...) S7_dispatch()'
|
|
60
|
+
effectiveArgs.push(newFun[0]);
|
|
61
|
+
funArg = newFun[1];
|
|
62
|
+
}
|
|
63
|
+
const info = (0, known_call_handling_1.processKnownFunctionCall)({ name, forceArgs: 'all', args: effectiveArgs, rootId, data, origin: built_in_1.BuiltInProcName.S7NewGeneric }).information;
|
|
64
|
+
info.graph.addEdge(rootId, funArg, edge_1.EdgeType.Returns);
|
|
65
|
+
info.entryPoint = funArg;
|
|
66
|
+
const fArg = info.graph.getVertex(funArg);
|
|
67
|
+
if (fArg?.tag === vertex_1.VertexType.FunctionDefinition) {
|
|
68
|
+
fArg.mode ??= ['s4', 's7'];
|
|
69
|
+
}
|
|
70
|
+
return info;
|
|
71
|
+
}
|
|
72
|
+
// 'function([dispatch_args],...) S7_dispatch()'; returns the value id
|
|
73
|
+
function makeS7DispatchFDef(name, names, rootId, args, idMap) {
|
|
74
|
+
const argNameId = rootId + '-s7-new-generic-fun-arg-name';
|
|
75
|
+
const r = name.location ?? (0, range_1.invalidRange)();
|
|
76
|
+
const argName = {
|
|
77
|
+
type: type_1.RType.Symbol,
|
|
78
|
+
lexeme: 'fun',
|
|
79
|
+
content: 'fun',
|
|
80
|
+
info: {
|
|
81
|
+
id: argNameId,
|
|
82
|
+
nesting: name.info.nesting,
|
|
83
|
+
role: "arg-name" /* RoleInParent.ArgumentName */,
|
|
84
|
+
fullRange: r,
|
|
85
|
+
adToks: undefined,
|
|
86
|
+
file: name.info.file,
|
|
87
|
+
parent: rootId,
|
|
88
|
+
index: 0
|
|
89
|
+
},
|
|
90
|
+
location: r,
|
|
91
|
+
};
|
|
92
|
+
idMap.set(argNameId, argName);
|
|
93
|
+
const funcNameId = rootId + '-s7-new-generic-fun-name';
|
|
94
|
+
const funcName = {
|
|
95
|
+
type: type_1.RType.Symbol,
|
|
96
|
+
lexeme: 'S7_dispatch',
|
|
97
|
+
info: {
|
|
98
|
+
id: funcNameId,
|
|
99
|
+
nesting: name.info.nesting,
|
|
100
|
+
role: "call-name" /* RoleInParent.FunctionCallName */,
|
|
101
|
+
fullRange: r,
|
|
102
|
+
adToks: undefined,
|
|
103
|
+
file: name.info.file,
|
|
104
|
+
parent: rootId,
|
|
105
|
+
index: 0
|
|
106
|
+
},
|
|
107
|
+
location: r,
|
|
108
|
+
content: identifier_1.Identifier.make('S7_dispatch', 's7'),
|
|
109
|
+
};
|
|
110
|
+
const funcBody = {
|
|
111
|
+
type: type_1.RType.FunctionCall,
|
|
112
|
+
location: r,
|
|
113
|
+
lexeme: 'S7_dispatch',
|
|
114
|
+
named: true,
|
|
115
|
+
functionName: funcName,
|
|
116
|
+
arguments: [],
|
|
117
|
+
info: {
|
|
118
|
+
id: rootId + '-s7-new-generic-fun-body',
|
|
119
|
+
nesting: name.info.nesting,
|
|
120
|
+
role: "fun-body" /* RoleInParent.FunctionDefinitionBody */,
|
|
121
|
+
fullRange: r,
|
|
122
|
+
adToks: undefined,
|
|
123
|
+
file: name.info.file,
|
|
124
|
+
parent: rootId,
|
|
125
|
+
index: 0
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
const fdefId = rootId + '-s7-new-generic-fun-fdef';
|
|
129
|
+
const argValue = {
|
|
130
|
+
type: type_1.RType.FunctionDefinition,
|
|
131
|
+
info: {
|
|
132
|
+
file: name.info.file,
|
|
133
|
+
id: fdefId,
|
|
134
|
+
nesting: name.info.nesting,
|
|
135
|
+
role: "arg-value" /* RoleInParent.ArgumentValue */,
|
|
136
|
+
parent: rootId,
|
|
137
|
+
index: args + 1,
|
|
138
|
+
adToks: undefined,
|
|
139
|
+
fullRange: r,
|
|
140
|
+
},
|
|
141
|
+
lexeme: 'function',
|
|
142
|
+
location: r,
|
|
143
|
+
parameters: [...names.filter(assert_1.isNotUndefined), '...'].map((n, i) => {
|
|
144
|
+
const paramId = fdefId + `-param-${i}`;
|
|
145
|
+
const paramNameId = paramId + '-name';
|
|
146
|
+
const paramName = {
|
|
147
|
+
type: type_1.RType.Symbol,
|
|
148
|
+
lexeme: n,
|
|
149
|
+
content: n,
|
|
150
|
+
info: {
|
|
151
|
+
id: paramNameId,
|
|
152
|
+
nesting: name.info.nesting,
|
|
153
|
+
role: "param-name" /* RoleInParent.ParameterName */,
|
|
154
|
+
fullRange: r,
|
|
155
|
+
adToks: undefined,
|
|
156
|
+
file: name.info.file,
|
|
157
|
+
index: i,
|
|
158
|
+
parent: paramId
|
|
159
|
+
},
|
|
160
|
+
location: r,
|
|
161
|
+
};
|
|
162
|
+
const param = {
|
|
163
|
+
type: type_1.RType.Parameter,
|
|
164
|
+
location: r,
|
|
165
|
+
lexeme: n,
|
|
166
|
+
name: paramName,
|
|
167
|
+
defaultValue: undefined,
|
|
168
|
+
special: n === '...',
|
|
169
|
+
info: {
|
|
170
|
+
id: paramId,
|
|
171
|
+
nesting: name.info.nesting,
|
|
172
|
+
role: "param" /* RoleInParent.FunctionDefinitionParameter */,
|
|
173
|
+
parent: fdefId,
|
|
174
|
+
index: i,
|
|
175
|
+
adToks: undefined,
|
|
176
|
+
file: name.info.file,
|
|
177
|
+
fullRange: r,
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
idMap.set(paramNameId, paramName);
|
|
181
|
+
idMap.set(paramId, param);
|
|
182
|
+
return param;
|
|
183
|
+
}),
|
|
184
|
+
body: funcBody,
|
|
185
|
+
};
|
|
186
|
+
idMap.set(funcNameId, funcName);
|
|
187
|
+
idMap.set(funcBody.info.id, funcBody);
|
|
188
|
+
idMap.set(fdefId, argValue);
|
|
189
|
+
const argId = rootId + '-s7-new-generic-fun-arg';
|
|
190
|
+
const argument = {
|
|
191
|
+
type: type_1.RType.Argument,
|
|
192
|
+
lexeme: 'fun',
|
|
193
|
+
location: r,
|
|
194
|
+
info: {
|
|
195
|
+
id: argId,
|
|
196
|
+
nesting: name.info.nesting,
|
|
197
|
+
role: "call-arg" /* RoleInParent.FunctionCallArgument */,
|
|
198
|
+
fullRange: r,
|
|
199
|
+
adToks: undefined,
|
|
200
|
+
file: name.info.file,
|
|
201
|
+
parent: rootId,
|
|
202
|
+
index: args + 1
|
|
203
|
+
},
|
|
204
|
+
name: argName,
|
|
205
|
+
value: argValue
|
|
206
|
+
};
|
|
207
|
+
idMap.set(argument.info.id, argument);
|
|
208
|
+
return [argument, argValue.info.id];
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=built-in-s-seven-new-generic.js.map
|
|
@@ -19,7 +19,7 @@ const range_1 = require("../../../../../../util/range");
|
|
|
19
19
|
* Process an S3 dispatch call like `UseMethod`.
|
|
20
20
|
*/
|
|
21
21
|
function processS3Dispatch(name, args, rootId, data, config) {
|
|
22
|
-
if (args.length === 0) {
|
|
22
|
+
if (args.length === 0 && !config.inferFromClosure) {
|
|
23
23
|
logger_1.dataflowLogger.warn('empty s3, skipping');
|
|
24
24
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
|
|
25
25
|
}
|
|
@@ -30,7 +30,7 @@ function processS3Dispatch(name, args, rootId, data, config) {
|
|
|
30
30
|
};
|
|
31
31
|
const argMaps = (0, linker_1.invertArgumentMap)((0, linker_1.pMatch)((0, common_1.convertFnArguments)(args), params));
|
|
32
32
|
const generic = (0, unpack_argument_1.unpackArg)((0, r_argument_1.getArgumentWithId)(args, argMaps.get('generic')?.[0]));
|
|
33
|
-
if (!generic) {
|
|
33
|
+
if (!generic && !config.inferFromClosure) {
|
|
34
34
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
|
|
35
35
|
}
|
|
36
36
|
const obj = (0, unpack_argument_1.unpackArg)((0, r_argument_1.getArgumentWithId)(args, argMaps.get('object')?.[0]));
|
|
@@ -46,6 +46,28 @@ function processS3Dispatch(name, args, rootId, data, config) {
|
|
|
46
46
|
});
|
|
47
47
|
return dfObj;
|
|
48
48
|
}
|
|
49
|
+
if (!generic) {
|
|
50
|
+
(0, common_1.patchFunctionCall)({
|
|
51
|
+
nextGraph: dfObj.graph,
|
|
52
|
+
rootId,
|
|
53
|
+
name,
|
|
54
|
+
data,
|
|
55
|
+
argumentProcessResult: [dfObj],
|
|
56
|
+
origin: built_in_1.BuiltInProcName.S3DispatchNext
|
|
57
|
+
});
|
|
58
|
+
const ingoing = dfObj.in.concat(dfObj.unknownReferences);
|
|
59
|
+
ingoing.push({ nodeId: rootId, name: name.content, cds: data.cds, type: identifier_1.ReferenceType.Function });
|
|
60
|
+
return {
|
|
61
|
+
hooks: dfObj.hooks,
|
|
62
|
+
environment: dfObj.environment,
|
|
63
|
+
exitPoints: dfObj.exitPoints,
|
|
64
|
+
graph: dfObj.graph,
|
|
65
|
+
entryPoint: rootId,
|
|
66
|
+
in: ingoing,
|
|
67
|
+
out: dfObj.out,
|
|
68
|
+
unknownReferences: []
|
|
69
|
+
};
|
|
70
|
+
}
|
|
49
71
|
const n = (0, alias_tracking_1.resolveIdToValue)(generic.info.id, { environment: data.environment, resolve: data.ctx.config.solver.variables, idMap: data.completeAst.idMap, full: true, ctx: data.ctx });
|
|
50
72
|
const accessedIdentifiers = [];
|
|
51
73
|
if (n.type === 'set') {
|
|
@@ -11,5 +11,6 @@ import type { DataflowGraph } from '../../../../graph/graph';
|
|
|
11
11
|
export declare function markAsOnlyBuiltIn(graph: DataflowGraph, rootId: NodeId): void;
|
|
12
12
|
/**
|
|
13
13
|
* Processes a named function call within the dataflow analysis.
|
|
14
|
+
* For example, `myFunction(arg1, arg2)`, resolves against the environment.
|
|
14
15
|
*/
|
|
15
16
|
export declare function processNamedCall<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>): DataflowInformation;
|
|
@@ -41,6 +41,7 @@ function markAsOnlyBuiltIn(graph, rootId) {
|
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
43
|
* Processes a named function call within the dataflow analysis.
|
|
44
|
+
* For example, `myFunction(arg1, arg2)`, resolves against the environment.
|
|
44
45
|
*/
|
|
45
46
|
function processNamedCall(name, args, rootId, data) {
|
|
46
47
|
const resolved = (0, resolve_by_name_1.resolveByName)(name.content, data.environment, identifier_1.ReferenceType.Function) ?? [];
|
|
@@ -5,5 +5,6 @@ import type { ParentInformation } from '../../../../../r-bridge/lang-4.x/ast/mod
|
|
|
5
5
|
export declare const UnnamedFunctionCallPrefix = "unnamed-fc-";
|
|
6
6
|
/**
|
|
7
7
|
* Processes an unnamed function call.
|
|
8
|
+
* For example `(function(x) { x + 1 })(5)`
|
|
8
9
|
*/
|
|
9
10
|
export declare function processUnnamedFunctionCall<OtherInfo>(functionCall: RUnnamedFunctionCall<OtherInfo & ParentInformation>, data: DataflowProcessorInformation<OtherInfo & ParentInformation>): DataflowInformation;
|
|
@@ -15,6 +15,7 @@ const built_in_1 = require("../../../../environments/built-in");
|
|
|
15
15
|
exports.UnnamedFunctionCallPrefix = 'unnamed-fc-';
|
|
16
16
|
/**
|
|
17
17
|
* Processes an unnamed function call.
|
|
18
|
+
* For example `(function(x) { x + 1 })(5)`
|
|
18
19
|
*/
|
|
19
20
|
function processUnnamedFunctionCall(functionCall, data) {
|
|
20
21
|
const calledFunction = (0, processor_1.processDataflowFor)(functionCall.calledFunction, data);
|
|
@@ -4,7 +4,6 @@ exports.explainWritingCode = explainWritingCode;
|
|
|
4
4
|
const shell_1 = require("../../../r-bridge/shell");
|
|
5
5
|
const flowr_analyzer_1 = require("../../../project/flowr-analyzer");
|
|
6
6
|
const doc_code_1 = require("../../doc-util/doc-code");
|
|
7
|
-
const doc_files_1 = require("../../doc-util/doc-files");
|
|
8
7
|
const pipeline_executor_1 = require("../../../core/pipeline-executor");
|
|
9
8
|
const retriever_1 = require("../../../r-bridge/retriever");
|
|
10
9
|
const doc_structure_1 = require("../../doc-util/doc-structure");
|
|
@@ -77,7 +76,7 @@ See the in-code documentation for more information.
|
|
|
77
76
|
### Using the ${ctx.link(shell_1.RShell)} to Interact with R
|
|
78
77
|
|
|
79
78
|
The ${ctx.link(shell_1.RShell)} class allows interfacing with the \`R\` ecosystem installed on the host system.
|
|
80
|
-
Please have a look at
|
|
79
|
+
Please have a look at ${ctx.linkPage('wiki/Engines', 'flowR\'s Engines')} for more information on alternatives (for example, the ${ctx.link(tree_sitter_executor_1.TreeSitterExecutor)}).
|
|
81
80
|
|
|
82
81
|
${(0, doc_structure_1.block)({
|
|
83
82
|
type: 'IMPORTANT',
|
|
@@ -1004,13 +1004,17 @@ Depending on what you are interested in, there exists a plethora of functions an
|
|
|
1004
1004
|
* ${ctx.link(node_id_1.recoverName)} and ${ctx.link(node_id_1.recoverContent)} to get the name or content of a vertex in the dataflow graph
|
|
1005
1005
|
* ${ctx.link(alias_tracking_1.resolveIdToValue)} to resolve the value of a variable or id (if possible, see [below](#dfg-resolving-values))
|
|
1006
1006
|
* ${ctx.link(alias_tracking_1.getAliases)} to get all (potentially currently) aliases of a given definition
|
|
1007
|
-
* ${ctx.link('DfEdge', undefined, { type: 'variable' })} to get helpful functions wrt. edges (see [below](#dfg-resolving-values))
|
|
1008
|
-
* ${ctx.link('Identifier', undefined, { type: 'variable' })} to get helpful functions wrt. identifiers
|
|
1009
1007
|
* ${ctx.link(identify_link_to_last_call_relation_1.getValueOfArgument)} to get the (syntactical) value of an argument in a function call
|
|
1010
1008
|
* ${ctx.link(dfg_get_origin_1.getOriginInDfg)} to get information about where a read, call, ... comes from (see [below](#dfg-resolving-values))
|
|
1011
1009
|
|
|
1012
|
-
|
|
1013
|
-
|
|
1010
|
+
FlowR also provides various helper objects (with the same name as the corresponding type) to help you work with the dataflow graph:
|
|
1011
|
+
|
|
1012
|
+
* ${ctx.link('DfEdge', undefined, { type: 'variable' })} to get helpful functions wrt. edges (see [below](#dfg-resolving-values))
|
|
1013
|
+
* ${ctx.link('Identifier', undefined, { type: 'variable' })} to get helpful functions wrt. identifiers
|
|
1014
|
+
* ${ctx.link('FunctionArgument', undefined, { type: 'variable' })} to get helpful functions wrt. function arguments
|
|
1015
|
+
|
|
1016
|
+
Some of these functions have been explained in their respective wiki pages. However, some are part of the ${ctx.linkPage('wiki/Dataflow Graph', 'Dataflow Graph API')} and so we explain them here.
|
|
1017
|
+
If you are interested in which features we support and which features are still to be worked on, please refer to our ${ctx.linkPage('wiki/Capabilities', 'capabilities')} page.
|
|
1014
1018
|
|
|
1015
1019
|
${(0, doc_structure_1.section)('Resolving Values', 3, 'dfg-resolving-values')}
|
|
1016
1020
|
|
|
@@ -26,6 +26,8 @@ export interface NamingConventionConfig extends MergeableRecord {
|
|
|
26
26
|
caseing: CasingConvention | 'auto';
|
|
27
27
|
/** if true non alphabetic characters are ignored */
|
|
28
28
|
ignoreNonAlpha: boolean;
|
|
29
|
+
/** optional prefix to ignore on all identifiers, which is interpreted as a regular expression fragment (meaning special characters have to be escaped) */
|
|
30
|
+
ignorePrefix?: string;
|
|
29
31
|
}
|
|
30
32
|
export interface NamingConventionMetadata extends MergeableRecord {
|
|
31
33
|
/** number of symbols matching the casing convetion */
|
|
@@ -34,9 +36,14 @@ export interface NamingConventionMetadata extends MergeableRecord {
|
|
|
34
36
|
numBreak: number;
|
|
35
37
|
}
|
|
36
38
|
/**
|
|
37
|
-
* Attempts to detect the casing
|
|
39
|
+
* Attempts to detect the possible casing conventions used in the given identifier and returns an array ordered by likelihood of the casing convention being correct.
|
|
38
40
|
*/
|
|
39
|
-
export declare function
|
|
41
|
+
export declare function detectPotentialCasings(identifier: string, ignorePrefix?: string): CasingConvention[];
|
|
42
|
+
/**
|
|
43
|
+
* Attempts to detect the possible casing conventions used in the given identifier and returns the first result.
|
|
44
|
+
* The function {@link detectPotentialCasings} is generally preferred, as it returns all potential casings and not just the first one.
|
|
45
|
+
*/
|
|
46
|
+
export declare function detectCasing(identifier: string, ignorePrefix?: string): CasingConvention;
|
|
40
47
|
/**
|
|
41
48
|
* Determines the most used casing convention in the given list of symbols.
|
|
42
49
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.NAMING_CONVENTION = exports.CasingConvention = void 0;
|
|
4
|
+
exports.detectPotentialCasings = detectPotentialCasings;
|
|
4
5
|
exports.detectCasing = detectCasing;
|
|
5
6
|
exports.getMostUsedCasing = getMostUsedCasing;
|
|
6
7
|
exports.fixCasing = fixCasing;
|
|
@@ -26,50 +27,51 @@ function containsAlpha(s) {
|
|
|
26
27
|
return /[A-Za-z]/.test(s);
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
29
|
-
* Attempts to detect the casing
|
|
30
|
+
* Attempts to detect the possible casing conventions used in the given identifier and returns an array ordered by likelihood of the casing convention being correct.
|
|
30
31
|
*/
|
|
31
|
-
function
|
|
32
|
+
function detectPotentialCasings(identifier, ignorePrefix) {
|
|
32
33
|
if (identifier.trim() === '' || !containsAlpha(identifier)) {
|
|
33
|
-
return
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
if (ignorePrefix) {
|
|
37
|
+
identifier = identifier.replace(new RegExp(`^(${ignorePrefix})`), '');
|
|
34
38
|
}
|
|
35
39
|
const upper = identifier.toUpperCase();
|
|
36
40
|
const lower = identifier.toLowerCase();
|
|
37
41
|
const isAllUpper = identifier === upper;
|
|
38
42
|
const isAllLower = identifier === lower;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// Returns true if the letter after an _ is uppercase
|
|
47
|
-
function expectUpperAfterScore(identifier) {
|
|
48
|
-
for (let i = 0; i < identifier.length - 1; i++) {
|
|
49
|
-
if (identifier[i] === '_') {
|
|
50
|
-
if (identifier[i + 1] !== upper[i + 1]) {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return true;
|
|
56
|
-
}
|
|
57
|
-
if (identifier[0] === lower[0] && expectUpperAfterScore(identifier)) { // camel_Snake_Case
|
|
58
|
-
return CasingConvention.CamelSnakeCase;
|
|
59
|
-
}
|
|
60
|
-
else if (identifier[0] === upper[0] && expectUpperAfterScore(identifier)) { // Pascal_Snake_Case
|
|
61
|
-
return CasingConvention.PascalSnakeCase;
|
|
62
|
-
}
|
|
43
|
+
const hasUnderscores = identifier.includes('_');
|
|
44
|
+
const upperAfterAllScores = Array(identifier.length - 1).keys().every(i => identifier[i] !== '_' || identifier[i + 1] === upper[i + 1]);
|
|
45
|
+
const hasAnyUpperAfterLower = Array(identifier.length - 1).keys().some(i => containsAlpha(identifier[i]) && identifier[i] === lower[i] &&
|
|
46
|
+
containsAlpha(identifier[i + 1]) && identifier[i + 1] === upper[i + 1]);
|
|
47
|
+
const matches = [];
|
|
48
|
+
if (!hasUnderscores && identifier[0] === lower[0]) {
|
|
49
|
+
matches.push(CasingConvention.CamelCase); // camelCase
|
|
63
50
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
51
|
+
if (!hasUnderscores && identifier[0] === upper[0] && (identifier.length === 1 || !isAllUpper)) {
|
|
52
|
+
matches.push(CasingConvention.PascalCase); // PascalCase or Pascalcase
|
|
53
|
+
}
|
|
54
|
+
if (isAllUpper) {
|
|
55
|
+
matches.push(CasingConvention.ConstantCase); // CONSTANT_CASE or CONSTANTCASE
|
|
56
|
+
}
|
|
57
|
+
if (isAllLower) {
|
|
58
|
+
matches.push(CasingConvention.SnakeCase); // snake_case or snakecase or snakecase_
|
|
59
|
+
}
|
|
60
|
+
if (upperAfterAllScores && identifier[0] === lower[0] && !isAllUpper && hasUnderscores || (!hasUnderscores && isAllLower)) {
|
|
61
|
+
matches.push(CasingConvention.CamelSnakeCase); // camel_Snake_Case or camelsnakecase or camelsnakecase_
|
|
71
62
|
}
|
|
72
|
-
|
|
63
|
+
if (upperAfterAllScores && identifier[0] === upper[0] && (identifier.length === 1 || !isAllUpper) && !hasAnyUpperAfterLower) {
|
|
64
|
+
matches.push(CasingConvention.PascalSnakeCase); // Pascal_Snake_Case or Pascalsnakecase
|
|
65
|
+
}
|
|
66
|
+
return matches;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Attempts to detect the possible casing conventions used in the given identifier and returns the first result.
|
|
70
|
+
* The function {@link detectPotentialCasings} is generally preferred, as it returns all potential casings and not just the first one.
|
|
71
|
+
*/
|
|
72
|
+
function detectCasing(identifier, ignorePrefix) {
|
|
73
|
+
const casings = detectPotentialCasings(identifier, ignorePrefix);
|
|
74
|
+
return casings.length > 0 ? casings[0] : CasingConvention.Unknown;
|
|
73
75
|
}
|
|
74
76
|
/**
|
|
75
77
|
* Determines the most used casing convention in the given list of symbols.
|
|
@@ -156,7 +158,7 @@ exports.NAMING_CONVENTION = {
|
|
|
156
158
|
const symbols = elements.getElements()
|
|
157
159
|
.map(m => ({
|
|
158
160
|
certainty: linter_format_1.LintingResultCertainty.Certain,
|
|
159
|
-
detectedCasing: detectCasing(m.node.lexeme),
|
|
161
|
+
detectedCasing: detectCasing(m.node.lexeme, config.ignorePrefix),
|
|
160
162
|
name: m.node.lexeme,
|
|
161
163
|
range: m.node.info.fullRange,
|
|
162
164
|
id: m.node.info.id
|
|
@@ -86,7 +86,7 @@ exports.SEEDED_RANDOMNESS = {
|
|
|
86
86
|
// assignments have to be queried for their destination
|
|
87
87
|
for (const a of assignment ?? []) {
|
|
88
88
|
const argIdx = assignmentArgIndexes.get(identifier_1.Identifier.getName(a.name));
|
|
89
|
-
const dest =
|
|
89
|
+
const dest = graph_1.FunctionArgument.getReference(a.args[argIdx]);
|
|
90
90
|
if (dest !== undefined && assignmentProducers.has((0, node_id_1.recoverName)(dest, dataflow.graph.idMap))) {
|
|
91
91
|
// we either have arg index 0 or 1 for the assignmentProducers destination, so we select the assignment value as 1-argIdx here
|
|
92
92
|
if (isConstantArgument(dataflow.graph, a, 1 - argIdx, analyzer.inspectContext())) {
|
|
@@ -143,7 +143,7 @@ function getDefaultAssignments() {
|
|
|
143
143
|
return default_builtin_config_1.DefaultBuiltinConfig.filter(b => b.type === 'function' && (b.processor === built_in_1.BuiltInProcName.Assignment || b.processor === built_in_1.BuiltInProcName.AssignmentLike));
|
|
144
144
|
}
|
|
145
145
|
function isConstantArgument(graph, call, argIndex, ctx) {
|
|
146
|
-
const args = call.args.filter(arg => arg !== r_function_call_1.EmptyArgument && !arg.name).map(graph_1.
|
|
146
|
+
const args = call.args.filter(arg => arg !== r_function_call_1.EmptyArgument && !arg.name).map(graph_1.FunctionArgument.getReference);
|
|
147
147
|
const values = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(args[argIndex], { graph: graph, resolve: config_1.VariableResolve.Alias, ctx }));
|
|
148
148
|
return values?.elements.every(v => v.type === 'number' ||
|
|
149
149
|
v.type === 'logical' ||
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eagleoutice/flowr",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.2",
|
|
4
4
|
"description": "Static Dataflow Analyzer and Program Slicer for the R Programming Language",
|
|
5
5
|
"types": "dist/src/index.d.ts",
|
|
6
6
|
"repository": {
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"test:full": "npm run test-full",
|
|
44
44
|
"test-full": "npm run test:coverage -- --no-watch -- --make-summary --test-installation",
|
|
45
45
|
"performance-test": "func() { cd test/performance/ && bash run-all-suites.sh $1 $2 $3 $4; cd ../../; }; func",
|
|
46
|
+
"test:performance": "npm run performance-test --",
|
|
46
47
|
"detect-circular-deps": "npx madge --extensions ts,tsx --circular src/",
|
|
47
48
|
"checkup": "npm run flowr -- --execute \":version\" && npm run lint && npm run test-full -- --allowOnly=false && npm run test:system -- --no-watch && docker build -t test-flowr -f scripts/Dockerfile . && npm run doc && npm run gen:readme && npm-run-all wiki:*"
|
|
48
49
|
},
|
|
@@ -2,6 +2,7 @@ import type { FileRole, FlowrFileProvider } from '../../../context/flowr-file';
|
|
|
2
2
|
import { FlowrFile } from '../../../context/flowr-file';
|
|
3
3
|
import type { RNode } from '../../../../r-bridge/lang-4.x/ast/model/model';
|
|
4
4
|
import type { FlowrAnalyzerContext } from '../../../context/flowr-analyzer-context';
|
|
5
|
+
import type { ParentInformation } from '../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
5
6
|
export interface NamespaceInfo {
|
|
6
7
|
exportedSymbols: string[];
|
|
7
8
|
exportedFunctions: string[];
|
|
@@ -13,7 +14,7 @@ export interface NamespaceInfo {
|
|
|
13
14
|
* This will only be present in complex parsed NAMESPACE files and tell you
|
|
14
15
|
* about which parts are only active with given conditions!
|
|
15
16
|
*/
|
|
16
|
-
conditional?: Map<RNode
|
|
17
|
+
conditional?: Map<RNode<ParentInformation>, NamespaceInfo>;
|
|
17
18
|
}
|
|
18
19
|
export interface NamespaceFormat {
|
|
19
20
|
current: NamespaceInfo;
|
|
@@ -37,6 +38,13 @@ export declare class FlowrNamespaceFile extends FlowrFile<NamespaceFormat> {
|
|
|
37
38
|
* @see {@link parseNamespaceComplex} for a more complex parser.
|
|
38
39
|
*/
|
|
39
40
|
protected loadContent(): NamespaceFormat;
|
|
41
|
+
/**
|
|
42
|
+
* Either returns whether the given symbol/function is exported from the given package
|
|
43
|
+
* or the list of (`and`) conditions under which it is exported.
|
|
44
|
+
* @param name - The name of the symbol/function to check
|
|
45
|
+
* @param pkg - The package to check in
|
|
46
|
+
*/
|
|
47
|
+
isExported(name: string, pkg?: string): boolean | RNode<ParentInformation>[];
|
|
40
48
|
/**
|
|
41
49
|
* Namespace file lifter, this does not re-create if already a namespace file
|
|
42
50
|
* and handles role assignments.
|
|
@@ -46,3 +54,18 @@ export declare class FlowrNamespaceFile extends FlowrFile<NamespaceFormat> {
|
|
|
46
54
|
*/
|
|
47
55
|
static from(file: FlowrFileProvider | FlowrNamespaceFile, ctx?: FlowrAnalyzerContext, role?: FileRole): FlowrNamespaceFile;
|
|
48
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Either returns whether the given symbol/function is exported from the given package
|
|
59
|
+
* or the list of (`and`) conditions under which it is exported.
|
|
60
|
+
* @param fmt - The namespace format to check in
|
|
61
|
+
* @param name - The name of the symbol/function to check
|
|
62
|
+
* @param pkg - The package to check in
|
|
63
|
+
*/
|
|
64
|
+
export declare function isExportedInNamespaceFormat(this: void, fmt: NamespaceFormat, name: string, pkg?: string): boolean | RNode<ParentInformation>[];
|
|
65
|
+
/**
|
|
66
|
+
* Either returns whether the given symbol/function is exported from the given namespace info,
|
|
67
|
+
* or the list of (`and`) conditions under which it is exported.
|
|
68
|
+
* @param name - The name of the symbol/function to check
|
|
69
|
+
* @param nsInfo - The namespace info to check in
|
|
70
|
+
*/
|
|
71
|
+
export declare function isExportedInInfo(this: void, name: string, nsInfo: NamespaceInfo): boolean | RNode<ParentInformation>[];
|