@eagleoutice/flowr 2.0.4 → 2.0.6

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 CHANGED
@@ -2,7 +2,7 @@
2
2
  [![QA (and potentially deploy)](https://github.com/Code-Inspect/flowr/actions/workflows/qa.yaml/badge.svg)](https://github.com/Code-Inspect/flowr/actions/workflows/qa.yaml) [![codecov](https://codecov.io/gh/Code-Inspect/flowr/graph/badge.svg)](https://codecov.io/gh/Code-Inspect/flowr) [![Docker Image Version (latest semver)](https://img.shields.io/docker/v/eagleoutice/flowr?logo=docker&logoColor=white&label=dockerhub)](https://hub.docker.com/r/eagleoutice/flowr) [![latest tag](https://badgen.net/github/tag/Code-Inspect/flowr?label=latest&color=purple)](https://github.com/Code-Inspect/flowr/releases/latest) [![Marketplace](https://badgen.net/vs-marketplace/v/code-inspect.vscode-flowr)](https://marketplace.visualstudio.com/items?itemName=code-inspect.vscode-flowr)
3
3
 
4
4
 
5
- *flowR* is a static [dataflow analyzer](https://en.wikipedia.org/wiki/Data-flow_analysis) and [program slicer](https://github.com/Code-Inspect/flowr/wiki/Terminology#program-slice) for the [*R*](https://www.r-project.org/) programming language (currently tested for versions `4.x`). It is available as a [Visual Studio Code extension](https://marketplace.visualstudio.com/items?itemName=code-inspect.vscode-flowr) and as a [docker image](https://hub.docker.com/r/eagleoutice/flowr).
5
+ *flowR* is a static [dataflow analyzer](https://en.wikipedia.org/wiki/Data-flow_analysis) and [program slicer](https://github.com/Code-Inspect/flowr/wiki/Terminology#program-slice) for the [*R*](https://www.r-project.org/) programming language (currently tested for versions `4.x` and `3.6.x`). It is available as a [Visual Studio Code extension](https://marketplace.visualstudio.com/items?itemName=code-inspect.vscode-flowr) and as a [docker image](https://hub.docker.com/r/eagleoutice/flowr).
6
6
 
7
7
  ## ⭐ Getting Started
8
8
 
@@ -55,7 +55,7 @@ function linkArgumentsOnCall(args, params, graph) {
55
55
  graph.addEdge(arg.nodeId, specialDotParameter.name.info.id, { type: 16 /* EdgeType.DefinesOnCall */ });
56
56
  }
57
57
  else {
58
- logger_1.dataflowLogger.error(`skipping argument ${i} as there is no corresponding parameter - R should block that`);
58
+ logger_1.dataflowLogger.warn(`skipping argument ${i} as there is no corresponding parameter - R should block that`);
59
59
  }
60
60
  continue;
61
61
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eagleoutice/flowr",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
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": {
package/r-bridge/init.js CHANGED
@@ -7,8 +7,9 @@ exports.ErrorMarker = 'err';
7
7
  function initCommand(eol) {
8
8
  /* define the get function complete wrapped in a try so that we can handle failures gracefully on stdout
9
9
  * furthermore, we compile for performance reasons
10
+ * Please note that we add a `flowr_output` assignment before to avoid issues with earlier R versions
10
11
  */
11
- return 'flowr_get_ast<-compiler::cmpfun(function(...){tryCatch({'
12
+ return 'flowr_output<-NULL;flowr_get_ast<-compiler::cmpfun(function(...){tryCatch({'
12
13
  /* the actual code to parse the R code, ... allows us to keep the old 'file=path' and 'text=content' semantics. we define flowr_output using the super assignment to persist it in the env! */
13
14
  + 'flowr_output<<-getParseData(parse(...,keep.source=TRUE),includeText=TRUE);'
14
15
  /* json conversion of the output, dataframe="values" allows us to receive a list of lists (which is more compact)!
@@ -138,6 +138,12 @@ export declare const enum RawRType {
138
138
  * https://github.com/REditorSupport/languageserver/pull/328
139
139
  */
140
140
  ExprOfAssignOrHelp = "expr_or_assign_or_help",
141
+ /**
142
+ * Pre-4.0 version of expr_or_assign_or_help, which was seemingly silently renamed here:
143
+ * https://github.com/wch/r-source/commit/84bbf385f909c0223924c310af6c7c77aa810234
144
+ * (Also see {@link ExprOfAssignOrHelp} documentation for more context.)
145
+ */
146
+ LegacyEqualAssign = "equal_assign",
141
147
  /** T65 */
142
148
  ExpressionList = "exprlist"
143
149
  }
@@ -8,7 +8,13 @@ exports.RootId = 0;
8
8
  * Parses the given data and sets child relationship, return the list of root entries (with a parent of {@link RootId}).
9
9
  */
10
10
  function prepareParsedData(data) {
11
- const json = JSON.parse(`[${data}]`);
11
+ let json;
12
+ try {
13
+ json = JSON.parse(`[${data}]`);
14
+ }
15
+ catch (e) {
16
+ throw new Error(`Failed to parse data ${data}: ${e?.message}`);
17
+ }
12
18
  (0, assert_1.guard)(Array.isArray(json), () => `Expected ${data} to be an array but was not`);
13
19
  const ret = new Map(json.map(([line1, col1, line2, col2, id, parent, token, terminal, text]) => {
14
20
  return [id, { line1, col1, line2, col2, id, parent, token: (0, retriever_1.removeRQuotes)(token), terminal, text }];
@@ -22,7 +22,7 @@ const normalize_symbol_1 = require("../values/normalize-symbol");
22
22
  */
23
23
  function tryNormalizeFunctionCall(data, mappedWithName) {
24
24
  const fnBase = mappedWithName[0];
25
- if (fnBase.name !== "expr" /* RawRType.Expression */ && fnBase.name !== "expr_or_assign_or_help" /* RawRType.ExprOfAssignOrHelp */) {
25
+ if (fnBase.name !== "expr" /* RawRType.Expression */ && fnBase.name !== "expr_or_assign_or_help" /* RawRType.ExprOfAssignOrHelp */ && fnBase.name !== "equal_assign" /* RawRType.LegacyEqualAssign */) {
26
26
  parser_1.parseLog.trace(`expected function call name to be wrapped an expression, yet received ${fnBase.name}`);
27
27
  return undefined;
28
28
  }
@@ -18,7 +18,7 @@ function tryNormalizeFor(data, [forToken, head, body]) {
18
18
  else if (head.name !== "forcond" /* RawRType.ForCondition */) {
19
19
  throw new input_format_1.XmlParseError(`expected condition for for-loop but found ${JSON.stringify(head)}`);
20
20
  }
21
- else if (body.name !== "expr" /* RawRType.Expression */ && body.name !== "expr_or_assign_or_help" /* RawRType.ExprOfAssignOrHelp */) {
21
+ else if (body.name !== "expr" /* RawRType.Expression */ && body.name !== "expr_or_assign_or_help" /* RawRType.ExprOfAssignOrHelp */ && body.name !== "equal_assign" /* RawRType.LegacyEqualAssign */) {
22
22
  throw new input_format_1.XmlParseError(`expected expr body for for-loop but found ${JSON.stringify(body)}`);
23
23
  }
24
24
  parser_1.parseLog.debug('trying to parse for-loop');
@@ -72,7 +72,7 @@ function tryNormalizeAccess(data, mappedWithName) {
72
72
  return undefined;
73
73
  }
74
74
  const accessed = mappedWithName[0];
75
- if (accessed.name !== "expr" /* RawRType.Expression */ && accessed.name !== "expr_or_assign_or_help" /* RawRType.ExprOfAssignOrHelp */) {
75
+ if (accessed.name !== "expr" /* RawRType.Expression */ && accessed.name !== "expr_or_assign_or_help" /* RawRType.ExprOfAssignOrHelp */ && accessed.name !== "equal_assign" /* RawRType.LegacyEqualAssign */) {
76
76
  parser_1.parseLog.trace(`expected accessed element to be wrapped an expression, yet received ${accessed.name}`);
77
77
  return undefined;
78
78
  }
@@ -33,7 +33,9 @@ function parseBinaryOp(data, lhs, operator, rhs) {
33
33
  const operationName = (0, normalize_meta_1.retrieveOpName)(operator);
34
34
  const { location, content } = (0, normalize_meta_1.retrieveMetaStructure)(operator.content);
35
35
  if ((0, strings_1.startAndEndsWith)(operationName, '%')) {
36
- (0, assert_1.guard)(parsedLhs.location !== undefined && parsedLhs.lexeme !== undefined && parsedRhs.location !== undefined && parsedRhs.lexeme !== undefined, () => `special op lhs and rhs must have a locations and lexemes, but ${JSON.stringify(parsedLhs)} and ${JSON.stringify(parsedRhs)})`);
36
+ const lhsLoc = parsedLhs.type === "RExpressionList" /* RType.ExpressionList */ ? parsedLhs.grouping?.[0].location : parsedLhs.location;
37
+ const rhsLoc = parsedRhs.type === "RExpressionList" /* RType.ExpressionList */ ? parsedRhs.grouping?.[0].location : parsedRhs.location;
38
+ (0, assert_1.guard)(lhsLoc !== undefined && rhsLoc !== undefined, () => `special op lhs and rhs must have a locations, but ${JSON.stringify(parsedLhs)} || ${JSON.stringify(lhsLoc)} and ${JSON.stringify(parsedRhs)} || || ${JSON.stringify(rhsLoc)})`);
37
39
  // parse as infix function call!
38
40
  return {
39
41
  type: "RFunctionCall" /* RType.FunctionCall */,
@@ -52,18 +54,18 @@ function parseBinaryOp(data, lhs, operator, rhs) {
52
54
  arguments: [
53
55
  {
54
56
  type: "RArgument" /* RType.Argument */,
55
- location: parsedLhs.location,
57
+ location: lhsLoc,
56
58
  value: parsedLhs,
57
59
  name: undefined,
58
- lexeme: parsedLhs.lexeme,
60
+ lexeme: parsedLhs.lexeme ?? '',
59
61
  info: {}
60
62
  },
61
63
  {
62
64
  type: "RArgument" /* RType.Argument */,
63
- location: parsedRhs.location,
65
+ location: rhsLoc,
64
66
  value: parsedRhs,
65
67
  name: undefined,
66
- lexeme: parsedRhs.lexeme,
68
+ lexeme: parsedRhs.lexeme ?? '',
67
69
  info: {}
68
70
  }
69
71
  ],
@@ -7,4 +7,4 @@ export declare function splitComments(tokens: readonly NamedXmlBasedJson[]): {
7
7
  others: NamedXmlBasedJson[];
8
8
  };
9
9
  export declare function normalizeExpressions(data: NormalizerData, tokens: readonly XmlBasedJson[] | readonly NamedXmlBasedJson[]): (RNode | RDelimiter)[];
10
- export declare function parseNodesWithUnknownType(data: NormalizerData, mappedWithName: readonly NamedXmlBasedJson[]): (RNode | RDelimiter)[];
10
+ export declare function parseNodesWithUnknownType(data: NormalizerData, mappedWithName: readonly NamedXmlBasedJson[] | undefined): (RNode | RDelimiter)[];
@@ -18,7 +18,7 @@ const normalize_if_then_else_1 = require("../control/normalize-if-then-else");
18
18
  const normalize_comment_1 = require("../other/normalize-comment");
19
19
  function normalizeMappedWithoutSemicolonBasedOnType(mappedWithName, data) {
20
20
  let result = undefined;
21
- switch (mappedWithName.length) {
21
+ switch (mappedWithName?.length) {
22
22
  case 1:
23
23
  result = (0, normalize_single_node_1.normalizeSingleNode)(data, mappedWithName[0]);
24
24
  break;
@@ -67,7 +67,7 @@ function splitExprs(tokens) {
67
67
  last = i + 1;
68
68
  }
69
69
  else {
70
- const thisExpr = token.name === "expr" /* RawRType.Expression */ || token.name === "expr_or_assign_or_help" /* RawRType.ExprOfAssignOrHelp */;
70
+ const thisExpr = token.name === "expr" /* RawRType.Expression */ || token.name === "expr_or_assign_or_help" /* RawRType.ExprOfAssignOrHelp */ || token.name === "equal_assign" /* RawRType.LegacyEqualAssign */;
71
71
  if (thisExpr && lastExpr) {
72
72
  if (i > last) {
73
73
  segments.push(tokens.slice(last, i));
@@ -93,7 +93,7 @@ function handleExpressionList(raw) {
93
93
  return { segments: [], comments: [], braces: undefined };
94
94
  }
95
95
  const { comments, others: tokens } = splitComments(raw);
96
- const first = tokens[0].name;
96
+ const first = tokens[0]?.name;
97
97
  if (first === "{" /* RawRType.BraceLeft */) {
98
98
  const endType = tokens[tokens.length - 1].name;
99
99
  (0, assert_1.guard)(endType === "}" /* RawRType.BraceRight */, () => `expected a brace at the end of the expression list as well, but ${endType} :: ${JSON.stringify(tokens[tokens.length - 1], json_1.jsonReplacer)}`);
@@ -172,7 +172,7 @@ exports.normalizeExpressions = normalizeExpressions;
172
172
  function parseNodesWithUnknownType(data, mappedWithName) {
173
173
  const parsedNodes = [];
174
174
  // used to indicate the new root node of this set of nodes
175
- for (const elem of mappedWithName) {
175
+ for (const elem of mappedWithName ?? []) {
176
176
  const retrieved = (0, normalize_single_node_1.normalizeSingleNode)(data, elem);
177
177
  parsedNodes.push(retrieved);
178
178
  }
@@ -35,6 +35,7 @@ function normalizeSingleNode(data, elem) {
35
35
  case "exprlist" /* RawRType.ExpressionList */:
36
36
  case "expr" /* RawRType.Expression */:
37
37
  case "expr_or_assign_or_help" /* RawRType.ExprOfAssignOrHelp */:
38
+ case "equal_assign" /* RawRType.LegacyEqualAssign */:
38
39
  return (0, normalize_expression_1.normalizeExpression)(data, elem.content);
39
40
  case "NUM_CONST" /* RawRType.NumericConst */:
40
41
  return (0, normalize_number_1.normalizeNumber)(data, elem.content);
@@ -32,7 +32,7 @@ export declare function assureTokenType(obj: XmlBasedJson, expectedName: RawRTyp
32
32
  * @param content - the json object to extract the token-type from
33
33
  */
34
34
  export declare function getTokenType(content: XmlBasedJson): RawRType;
35
- export declare function getWithTokenType(obj: XmlBasedJson[]): {
35
+ export declare function getWithTokenType(obj: readonly XmlBasedJson[]): {
36
36
  name: RawRType;
37
37
  content: XmlBasedJson;
38
38
  }[];
@@ -66,7 +66,7 @@ function getTokenType(content) {
66
66
  }
67
67
  exports.getTokenType = getTokenType;
68
68
  function getWithTokenType(obj) {
69
- return obj.map((content) => ({
69
+ return obj.map(content => ({
70
70
  name: getTokenType(content),
71
71
  content
72
72
  }));
package/r-bridge/shell.js CHANGED
@@ -51,7 +51,9 @@ exports.DEFAULT_OUTPUT_COLLECTOR_CONFIGURATION = {
51
51
  exports.DEFAULT_R_PATH = (0, os_1.getPlatform)() === 'windows' ? 'R.exe' : 'R';
52
52
  exports.DEFAULT_R_SHELL_EXEC_OPTIONS = {
53
53
  pathToRExecutable: (0, config_1.getConfig)().rPath ?? exports.DEFAULT_R_PATH,
54
- commandLineOptions: ['--vanilla', '--quiet', '--no-echo', '--no-save', '--slave'],
54
+ // -s is a short form of --no-echo (and the old version --slave), but this one works in R 3 and 4
55
+ // (see https://github.com/wch/r-source/commit/f1ff49e74593341c74c20de9517f31a22c8bcb04)
56
+ commandLineOptions: ['--vanilla', '--quiet', '--no-save', '-s'],
55
57
  cwd: process.cwd(),
56
58
  env: undefined,
57
59
  eol: '\n',
package/util/version.js CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.flowrVersion = void 0;
4
4
  const semver_1 = require("semver");
5
5
  // this is automatically replaced with the current version by release-it
6
- const version = '2.0.4';
6
+ const version = '2.0.6';
7
7
  function flowrVersion() {
8
8
  return new semver_1.SemVer(version);
9
9
  }