@eagleoutice/flowr 1.4.1 → 1.4.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 +3 -3
- package/abstract-interpretation/processor.js +9 -3
- package/benchmark/slicer.d.ts +0 -3
- package/benchmark/slicer.js +4 -16
- package/benchmark/stats/print.js +0 -2
- package/benchmark/stats/stats.d.ts +2 -3
- package/benchmark/stats/stats.js +1 -1
- package/cli/benchmark-app.d.ts +1 -0
- package/cli/benchmark-app.js +21 -6
- package/cli/benchmark-helper-app.d.ts +2 -0
- package/cli/benchmark-helper-app.js +15 -6
- package/cli/common/options.js +4 -1
- package/cli/common/scripts-info.d.ts +1 -0
- package/cli/common/scripts-info.js +15 -1
- package/cli/export-quads-app.js +1 -5
- package/cli/repl/commands/cfg.js +2 -2
- package/cli/repl/commands/commands.d.ts +3 -1
- package/cli/repl/commands/commands.js +67 -28
- package/cli/repl/commands/dataflow.js +2 -2
- package/cli/repl/commands/normalize.js +2 -2
- package/cli/repl/commands/parse.js +12 -12
- package/cli/repl/commands/quit.js +4 -1
- package/cli/repl/core.d.ts +4 -2
- package/cli/repl/core.js +63 -7
- package/cli/repl/execute.d.ts +1 -1
- package/cli/repl/execute.js +3 -3
- package/cli/repl/server/connection.js +3 -8
- package/cli/repl/server/net.js +2 -2
- package/cli/statistics-helper-app.js +0 -1
- package/cli/summarizer-app.js +1 -2
- package/config.d.ts +16 -0
- package/config.js +75 -0
- package/core/input.d.ts +1 -1
- package/core/output.d.ts +1 -2
- package/core/print/parse-printer.d.ts +1 -2
- package/core/print/parse-printer.js +6 -4
- package/core/slicer.js +4 -8
- package/core/steps.d.ts +7 -24
- package/core/steps.js +5 -12
- package/dataflow/environments/environment.js +8 -0
- package/dataflow/environments/register.js +1 -0
- package/dataflow/extractor.d.ts +2 -2
- package/dataflow/extractor.js +10 -2
- package/dataflow/internal/process/functions/function-call.js +7 -1
- package/dataflow/internal/process/functions/source.d.ts +8 -0
- package/dataflow/internal/process/functions/source.js +81 -0
- package/dataflow/processor.d.ts +10 -1
- package/flowr.d.ts +2 -0
- package/flowr.js +14 -9
- package/package.json +41 -18
- package/r-bridge/lang-4.x/ast/index.d.ts +1 -0
- package/r-bridge/lang-4.x/ast/index.js +3 -0
- package/r-bridge/lang-4.x/ast/model/processing/decorate.d.ts +2 -0
- package/r-bridge/lang-4.x/ast/model/processing/decorate.js +6 -1
- package/r-bridge/lang-4.x/ast/parser/json/format.d.ts +14 -0
- package/r-bridge/lang-4.x/ast/parser/json/format.js +26 -0
- package/r-bridge/lang-4.x/ast/parser/json/parser.d.ts +7 -0
- package/r-bridge/lang-4.x/ast/parser/json/parser.js +57 -0
- package/r-bridge/lang-4.x/ast/parser/xml/data.d.ts +0 -3
- package/r-bridge/lang-4.x/ast/parser/xml/index.d.ts +0 -2
- package/r-bridge/lang-4.x/ast/parser/xml/index.js +0 -2
- package/r-bridge/lang-4.x/ast/parser/xml/input-format.d.ts +5 -1
- package/r-bridge/lang-4.x/ast/parser/xml/input-format.js +7 -10
- package/r-bridge/lang-4.x/ast/parser/xml/internal/access.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/control/if-then-else.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/xml/internal/control/if-then.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/expression/expression.js +4 -4
- package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/argument.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/call.js +4 -4
- package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/definition.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/parameter.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/index.d.ts +0 -1
- package/r-bridge/lang-4.x/ast/parser/xml/internal/index.js +0 -1
- package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/break.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/for.js +3 -6
- package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/next.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/repeat.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/while.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/meta.d.ts +6 -11
- package/r-bridge/lang-4.x/ast/parser/xml/internal/meta.js +15 -23
- package/r-bridge/lang-4.x/ast/parser/xml/internal/operators/binary.js +6 -6
- package/r-bridge/lang-4.x/ast/parser/xml/internal/operators/unary.js +3 -3
- package/r-bridge/lang-4.x/ast/parser/xml/internal/other/comment.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/other/line-directive.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/structure/elements.js +3 -3
- package/r-bridge/lang-4.x/ast/parser/xml/internal/structure/root.js +3 -4
- package/r-bridge/lang-4.x/ast/parser/xml/internal/structure/single-element.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/values/number.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/values/string.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/values/symbol.js +4 -4
- package/r-bridge/lang-4.x/values.d.ts +0 -1
- package/r-bridge/lang-4.x/values.js +14 -6
- package/r-bridge/retriever.d.ts +25 -21
- package/r-bridge/retriever.js +73 -23
- package/r-bridge/shell-executor.d.ts +3 -17
- package/r-bridge/shell-executor.js +9 -78
- package/r-bridge/shell.d.ts +5 -27
- package/r-bridge/shell.js +31 -92
- package/statistics/features/supported/assignments/post-process.js +6 -6
- package/statistics/features/supported/comments/post-process.js +2 -2
- package/statistics/features/supported/data-access/post-process.js +4 -4
- package/statistics/features/supported/defined-functions/post-process.js +4 -4
- package/statistics/features/supported/expression-list/post-process.js +3 -3
- package/statistics/features/supported/loops/post-process.js +3 -3
- package/statistics/features/supported/used-functions/post-process.js +5 -5
- package/statistics/features/supported/used-packages/post-process.js +5 -5
- package/statistics/features/supported/values/post-process.js +3 -3
- package/statistics/features/supported/variables/post-process.js +3 -3
- package/statistics/output/ansi.js +1 -1
- package/statistics/statistics.js +7 -8
- package/util/args.d.ts +8 -4
- package/util/args.js +11 -4
- package/util/cfg/visitor.js +1 -1
- package/util/files.d.ts +6 -0
- package/util/files.js +11 -1
- package/util/log.js +3 -0
- package/util/summarizer/benchmark/first-phase/input.d.ts +2 -1
- package/util/summarizer/benchmark/first-phase/input.js +20 -4
- package/util/summarizer/benchmark/first-phase/process.d.ts +2 -1
- package/util/summarizer/benchmark/first-phase/process.js +14 -5
- package/util/summarizer/benchmark/second-phase/graph.js +1 -1
- package/util/summarizer/benchmark/second-phase/process.d.ts +2 -0
- package/util/summarizer/benchmark/second-phase/process.js +48 -11
- package/util/summarizer/benchmark/summarizer.d.ts +0 -4
- package/util/summarizer/benchmark/summarizer.js +16 -7
- package/util/summarizer/statistics/first-phase/process.js +8 -8
- package/util/summarizer/statistics/post-process/post-process-output.js +4 -5
- package/r-bridge/lang-4.x/ast/parser/xml/config.d.ts +0 -25
- package/r-bridge/lang-4.x/ast/parser/xml/config.js +0 -16
- package/r-bridge/lang-4.x/ast/parser/xml/internal/xml-to-json.d.ts +0 -9
- package/r-bridge/lang-4.x/ast/parser/xml/internal/xml-to-json.js +0 -51
- package/r-bridge/lang-4.x/ast/parser/xml/parser.d.ts +0 -17
- package/r-bridge/lang-4.x/ast/parser/xml/parser.js +0 -30
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseNodesWithUnknownType = exports.normalizeBasedOnType = exports.splitComments = void 0;
|
|
4
4
|
const arrays_1 = require("../../../../../../../util/arrays");
|
|
5
|
-
const parser_1 = require("../../parser");
|
|
6
5
|
const meta_1 = require("../meta");
|
|
7
6
|
const single_element_1 = require("./single-element");
|
|
8
7
|
const values_1 = require("../values");
|
|
@@ -11,6 +10,7 @@ const loops_1 = require("../loops");
|
|
|
11
10
|
const control_1 = require("../control");
|
|
12
11
|
const log_1 = require("../../../../../../../util/log");
|
|
13
12
|
const other_1 = require("../other");
|
|
13
|
+
const parser_1 = require("../../../json/parser");
|
|
14
14
|
function normalizeMappedWithoutSemicolonBasedOnType(mappedWithName, data) {
|
|
15
15
|
if (mappedWithName.length === 1) {
|
|
16
16
|
return [(0, single_element_1.tryNormalizeSingleNode)(data, mappedWithName[0])];
|
|
@@ -103,14 +103,14 @@ function normalizeBasedOnType(data, obj) {
|
|
|
103
103
|
mappedWithName = obj;
|
|
104
104
|
}
|
|
105
105
|
else {
|
|
106
|
-
mappedWithName = (0, meta_1.getWithTokenType)(
|
|
106
|
+
mappedWithName = (0, meta_1.getWithTokenType)(obj);
|
|
107
107
|
}
|
|
108
108
|
log_1.log.trace(`[parseBasedOnType] names: [${mappedWithName.map(({ name }) => name).join(', ')}]`);
|
|
109
109
|
const semiColons = [];
|
|
110
110
|
const splitOnSemicolon = (0, arrays_1.splitArrayOn)(mappedWithName, node => {
|
|
111
111
|
const res = node.name === ";" /* RawRType.Semicolon */;
|
|
112
112
|
if (res) {
|
|
113
|
-
const { location, content } = (0, meta_1.retrieveMetaStructure)(
|
|
113
|
+
const { location, content } = (0, meta_1.retrieveMetaStructure)(node.content);
|
|
114
114
|
semiColons.push({
|
|
115
115
|
type: "RDelimiter" /* RType.Delimiter */,
|
|
116
116
|
subtype: ";" /* RawRType.Semicolon */,
|
|
@@ -7,12 +7,11 @@ const elements_1 = require("./elements");
|
|
|
7
7
|
const log_1 = require("../../../../../../../util/log");
|
|
8
8
|
const arrays_1 = require("../../../../../../../util/arrays");
|
|
9
9
|
function parseRootObjToAst(data, obj) {
|
|
10
|
-
const config = data.config;
|
|
11
10
|
const exprContent = (0, input_format_1.getKeysGuarded)(obj, "exprlist" /* RawRType.ExpressionList */);
|
|
12
|
-
(0, meta_1.assureTokenType)(
|
|
11
|
+
(0, meta_1.assureTokenType)(exprContent, "exprlist" /* RawRType.ExpressionList */);
|
|
13
12
|
let parsedChildren = [];
|
|
14
|
-
if (
|
|
15
|
-
const children = (0, input_format_1.getKeysGuarded)(exprContent,
|
|
13
|
+
if (input_format_1.childrenKey in exprContent) {
|
|
14
|
+
const children = (0, input_format_1.getKeysGuarded)(exprContent, input_format_1.childrenKey);
|
|
16
15
|
parsedChildren = (0, elements_1.normalizeBasedOnType)(data, children);
|
|
17
16
|
}
|
|
18
17
|
else {
|
|
@@ -10,7 +10,7 @@ const other_1 = require("../other");
|
|
|
10
10
|
const loops_1 = require("../loops");
|
|
11
11
|
const line_directive_1 = require("../other/line-directive");
|
|
12
12
|
function normalizeDelimiter(data, elem) {
|
|
13
|
-
const { location, content } = (0, meta_1.retrieveMetaStructure)(
|
|
13
|
+
const { location, content } = (0, meta_1.retrieveMetaStructure)(elem.content);
|
|
14
14
|
return {
|
|
15
15
|
type: "RDelimiter" /* RType.Delimiter */,
|
|
16
16
|
location,
|
|
@@ -52,7 +52,7 @@ function tryNormalizeSingleNode(data, elem) {
|
|
|
52
52
|
case "SYMBOL" /* RawRType.Symbol */:
|
|
53
53
|
case "SLOT" /* RawRType.Slot */:
|
|
54
54
|
case "NULL_CONST" /* RawRType.NullConst */: {
|
|
55
|
-
const symbol = (0, values_1.tryNormalizeSymbol)(data, (0, meta_1.getWithTokenType)(
|
|
55
|
+
const symbol = (0, values_1.tryNormalizeSymbol)(data, (0, meta_1.getWithTokenType)([elem.content]));
|
|
56
56
|
(0, assert_1.guard)(symbol !== undefined, () => `should have been parsed to a symbol but was ${JSON.stringify(symbol)}`);
|
|
57
57
|
return symbol;
|
|
58
58
|
}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.normalizeNumber = void 0;
|
|
4
4
|
const values_1 = require("../../../../../values");
|
|
5
|
-
const parser_1 = require("../../parser");
|
|
6
5
|
const meta_1 = require("../meta");
|
|
7
6
|
const hooks_1 = require("../../hooks");
|
|
7
|
+
const parser_1 = require("../../../json/parser");
|
|
8
8
|
/**
|
|
9
9
|
* Normalize the given object as a R number (see {@link number2ts}), supporting booleans (see {@link boolean2ts}),
|
|
10
10
|
* and special values.
|
|
@@ -16,7 +16,7 @@ const hooks_1 = require("../../hooks");
|
|
|
16
16
|
function normalizeNumber(data, obj) {
|
|
17
17
|
parser_1.parseLog.debug('[number]');
|
|
18
18
|
obj = (0, hooks_1.executeHook)(data.hooks.values.onNumber.before, data, obj);
|
|
19
|
-
const { location, content } = (0, meta_1.retrieveMetaStructure)(
|
|
19
|
+
const { location, content } = (0, meta_1.retrieveMetaStructure)(obj);
|
|
20
20
|
const common = {
|
|
21
21
|
location,
|
|
22
22
|
lexeme: content,
|
|
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.normalizeString = void 0;
|
|
4
4
|
const meta_1 = require("../meta");
|
|
5
5
|
const values_1 = require("../../../../../values");
|
|
6
|
-
const parser_1 = require("../../parser");
|
|
7
6
|
const hooks_1 = require("../../hooks");
|
|
8
7
|
const assert_1 = require("../../../../../../../util/assert");
|
|
8
|
+
const parser_1 = require("../../../json/parser");
|
|
9
9
|
/**
|
|
10
10
|
* Normalize the given object as a R string (see {@link string2ts}).
|
|
11
11
|
* This requires you to check the corresponding name beforehand.
|
|
@@ -16,7 +16,7 @@ const assert_1 = require("../../../../../../../util/assert");
|
|
|
16
16
|
function normalizeString(data, obj) {
|
|
17
17
|
parser_1.parseLog.debug('[string]');
|
|
18
18
|
obj = (0, hooks_1.executeHook)(data.hooks.values.onString.before, data, obj);
|
|
19
|
-
const { location, content } = (0, meta_1.retrieveMetaStructure)(
|
|
19
|
+
const { location, content } = (0, meta_1.retrieveMetaStructure)(obj);
|
|
20
20
|
// based on https://www.rdocumentation.org/packages/utils/versions/3.6.2/topics/getParseData we do not get strings with 1000 characters or more within the text field.
|
|
21
21
|
// therefore, we recover the full string from the surrounding expr lexeme field
|
|
22
22
|
let stringContent = content;
|
|
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.tryNormalizeSymbol = void 0;
|
|
4
4
|
const assert_1 = require("../../../../../../../util/assert");
|
|
5
5
|
const meta_1 = require("../meta");
|
|
6
|
-
const parser_1 = require("../../parser");
|
|
7
6
|
const model_1 = require("../../../../model");
|
|
8
7
|
const hooks_1 = require("../../hooks");
|
|
9
8
|
const strings_1 = require("../../../../../../../util/strings");
|
|
9
|
+
const parser_1 = require("../../../json/parser");
|
|
10
10
|
/**
|
|
11
11
|
* Normalize the given object as an R symbol (incorporating namespace information).
|
|
12
12
|
* <p>
|
|
@@ -23,16 +23,16 @@ function tryNormalizeSymbol(data, objs) {
|
|
|
23
23
|
objs = (0, hooks_1.executeHook)(data.hooks.values.onSymbol.before, data, objs);
|
|
24
24
|
let location, content, namespace;
|
|
25
25
|
if (objs.length === 1 && (0, model_1.isSymbol)(objs[0].name)) {
|
|
26
|
-
const meta = (0, meta_1.retrieveMetaStructure)(
|
|
26
|
+
const meta = (0, meta_1.retrieveMetaStructure)(objs[0].content);
|
|
27
27
|
location = meta.location;
|
|
28
28
|
content = meta.content;
|
|
29
29
|
namespace = undefined;
|
|
30
30
|
}
|
|
31
31
|
else if (objs.length === 3 && (0, model_1.isSymbol)(objs[2].name)) {
|
|
32
|
-
const meta = (0, meta_1.retrieveMetaStructure)(
|
|
32
|
+
const meta = (0, meta_1.retrieveMetaStructure)(objs[2].content);
|
|
33
33
|
location = meta.location;
|
|
34
34
|
content = meta.content;
|
|
35
|
-
namespace = (0, meta_1.retrieveMetaStructure)(
|
|
35
|
+
namespace = (0, meta_1.retrieveMetaStructure)(objs[0].content).content;
|
|
36
36
|
}
|
|
37
37
|
else {
|
|
38
38
|
return (0, hooks_1.executeUnknownHook)(data.hooks.values.onSymbol.unknown, data, objs);
|
|
@@ -36,4 +36,3 @@ export declare function string2ts(value: string): RStringValue;
|
|
|
36
36
|
export declare const RNa = "NA";
|
|
37
37
|
export declare const RNull = "NULL";
|
|
38
38
|
export declare function isNA(value: string): value is (typeof RNa);
|
|
39
|
-
export declare function parseCSV(lines: string[]): string[][];
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const sync_1 = require("csv-parse/sync");
|
|
3
|
+
exports.isNA = exports.RNull = exports.RNa = exports.string2ts = exports.number2ts = exports.RInf = exports.RIntegerMarker = exports.RImaginaryMarker = exports.RNumHexFloatRegex = exports.boolean2ts = exports.isBoolean = exports.RFalse = exports.RTrue = exports.ts2r = void 0;
|
|
5
4
|
class ValueConversionError extends Error {
|
|
6
5
|
constructor(message) {
|
|
7
6
|
super(message);
|
|
@@ -19,6 +18,12 @@ function ts2r(value) {
|
|
|
19
18
|
return JSON.stringify(value);
|
|
20
19
|
}
|
|
21
20
|
else if (typeof value === 'number') {
|
|
21
|
+
if (isNaN(value)) {
|
|
22
|
+
return exports.RNa;
|
|
23
|
+
}
|
|
24
|
+
else if (!isFinite(value)) {
|
|
25
|
+
return exports.RInf;
|
|
26
|
+
}
|
|
22
27
|
return value.toString();
|
|
23
28
|
}
|
|
24
29
|
else if (typeof value === 'boolean') {
|
|
@@ -81,6 +86,13 @@ function number2ts(value) {
|
|
|
81
86
|
markedAsInt
|
|
82
87
|
};
|
|
83
88
|
}
|
|
89
|
+
if (value === exports.RNa) {
|
|
90
|
+
return {
|
|
91
|
+
num: NaN,
|
|
92
|
+
complexNumber,
|
|
93
|
+
markedAsInt
|
|
94
|
+
};
|
|
95
|
+
}
|
|
84
96
|
const floatHex = lcValue.match(exports.RNumHexFloatRegex);
|
|
85
97
|
if (floatHex == null) {
|
|
86
98
|
return {
|
|
@@ -142,8 +154,4 @@ function isNA(value) {
|
|
|
142
154
|
return value === exports.RNa;
|
|
143
155
|
}
|
|
144
156
|
exports.isNA = isNA;
|
|
145
|
-
function parseCSV(lines) {
|
|
146
|
-
return (0, sync_1.parse)(lines.join('\n'), { skipEmptyLines: true });
|
|
147
|
-
}
|
|
148
|
-
exports.parseCSV = parseCSV;
|
|
149
157
|
//# sourceMappingURL=values.js.map
|
package/r-bridge/retriever.d.ts
CHANGED
|
@@ -1,28 +1,34 @@
|
|
|
1
1
|
import { type RShell } from './shell';
|
|
2
2
|
import type { XmlParserHooks, NormalizedAst } from './lang-4.x';
|
|
3
|
-
import type {
|
|
3
|
+
import type { AsyncOrSync, DeepPartial } from 'ts-essentials';
|
|
4
|
+
import { RShellExecutor } from './shell-executor';
|
|
5
|
+
export declare const fileProtocol: "file://";
|
|
4
6
|
export interface RParseRequestFromFile {
|
|
5
|
-
request: 'file';
|
|
7
|
+
readonly request: 'file';
|
|
6
8
|
/** The path to the file (absolute paths are probably best here */
|
|
7
|
-
content: string;
|
|
9
|
+
readonly content: string;
|
|
8
10
|
}
|
|
9
11
|
export interface RParseRequestFromText {
|
|
10
|
-
request: 'text';
|
|
11
|
-
content: string;
|
|
12
|
+
readonly request: 'text';
|
|
13
|
+
readonly content: string;
|
|
12
14
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
ensurePackageInstalled: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* A provider for an {@link RParseRequest} that can be used, for example, to override source file parsing behavior in tests
|
|
17
|
+
*/
|
|
18
|
+
export interface RParseRequestProvider {
|
|
19
|
+
createRequest(path: string): RParseRequest;
|
|
19
20
|
}
|
|
20
21
|
/**
|
|
21
|
-
* A request that can be passed along to {@link
|
|
22
|
+
* A request that can be passed along to {@link retrieveParseDataFromRCode}.
|
|
22
23
|
*/
|
|
23
|
-
export type RParseRequest = (RParseRequestFromFile | RParseRequestFromText)
|
|
24
|
-
export declare function requestFromInput(input:
|
|
25
|
-
export declare function requestFromInput(input: string): RParseRequestFromText
|
|
24
|
+
export type RParseRequest = (RParseRequestFromFile | RParseRequestFromText);
|
|
25
|
+
export declare function requestFromInput(input: `${typeof fileProtocol}${string}`): RParseRequestFromFile;
|
|
26
|
+
export declare function requestFromInput(input: string): RParseRequestFromText;
|
|
27
|
+
export declare function requestProviderFromFile(): RParseRequestProvider;
|
|
28
|
+
export declare function requestProviderFromText(text: {
|
|
29
|
+
[path: string]: string;
|
|
30
|
+
}): RParseRequestProvider;
|
|
31
|
+
export declare function requestFingerprint(request: RParseRequest): string;
|
|
26
32
|
/**
|
|
27
33
|
* Provides the capability to parse R files/R code using the R parser.
|
|
28
34
|
* Depends on {@link RShell} to provide a connection to R.
|
|
@@ -30,19 +36,17 @@ export declare function requestFromInput(input: string): RParseRequestFromText &
|
|
|
30
36
|
* Throws if the file could not be parsed.
|
|
31
37
|
* If successful, allows to further query the last result with {@link retrieveNumberOfRTokensOfLastParse}.
|
|
32
38
|
*/
|
|
33
|
-
export declare function
|
|
39
|
+
export declare function retrieveParseDataFromRCode(request: RParseRequest, shell: (RShell | RShellExecutor)): AsyncOrSync<string>;
|
|
34
40
|
/**
|
|
35
|
-
* Uses {@link
|
|
41
|
+
* Uses {@link retrieveParseDataFromRCode} and returns the nicely formatted object-AST.
|
|
36
42
|
* If successful, allows to further query the last result with {@link retrieveNumberOfRTokensOfLastParse}.
|
|
37
43
|
*/
|
|
38
44
|
export declare function retrieveNormalizedAstFromRCode(request: RParseRequest, shell: RShell, hooks?: DeepPartial<XmlParserHooks>): Promise<NormalizedAst>;
|
|
39
45
|
/**
|
|
40
46
|
* If the string has (R-)quotes around it, they will be removed, otherwise the string is returned unchanged.
|
|
41
47
|
*/
|
|
42
|
-
export declare function
|
|
43
|
-
export type TokenMap = DeepReadonly<Record<string, string>>;
|
|
48
|
+
export declare function removeRQuotes(str: string): string;
|
|
44
49
|
/**
|
|
45
|
-
* Needs to be called *after* {@link
|
|
50
|
+
* Needs to be called *after* {@link retrieveParseDataFromRCode} (or {@link retrieveNormalizedAstFromRCode})
|
|
46
51
|
*/
|
|
47
52
|
export declare function retrieveNumberOfRTokensOfLastParse(shell: RShell): Promise<number>;
|
|
48
|
-
export {};
|
package/r-bridge/retriever.js
CHANGED
|
@@ -1,21 +1,53 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.retrieveNumberOfRTokensOfLastParse = exports.
|
|
6
|
+
exports.retrieveNumberOfRTokensOfLastParse = exports.removeRQuotes = exports.retrieveNormalizedAstFromRCode = exports.retrieveParseDataFromRCode = exports.requestFingerprint = exports.requestProviderFromText = exports.requestProviderFromFile = exports.requestFromInput = exports.fileProtocol = void 0;
|
|
4
7
|
const lang_4_x_1 = require("./lang-4.x");
|
|
5
8
|
const strings_1 = require("../util/strings");
|
|
6
9
|
const assert_1 = require("../util/assert");
|
|
10
|
+
const shell_executor_1 = require("./shell-executor");
|
|
11
|
+
const object_hash_1 = __importDefault(require("object-hash"));
|
|
12
|
+
const parser_1 = require("./lang-4.x/ast/parser/json/parser");
|
|
13
|
+
exports.fileProtocol = 'file://';
|
|
7
14
|
/**
|
|
8
15
|
* Creates a {@link RParseRequest} from a given input.
|
|
9
16
|
*/
|
|
10
17
|
function requestFromInput(input) {
|
|
11
|
-
const file = input.startsWith(
|
|
18
|
+
const file = input.startsWith(exports.fileProtocol);
|
|
12
19
|
return {
|
|
13
20
|
request: file ? 'file' : 'text',
|
|
14
|
-
content: file ? input.slice(7) : input
|
|
15
|
-
ensurePackageInstalled: false // should be called within describeSession for that!
|
|
21
|
+
content: file ? input.slice(7) : input
|
|
16
22
|
};
|
|
17
23
|
}
|
|
18
24
|
exports.requestFromInput = requestFromInput;
|
|
25
|
+
function requestProviderFromFile() {
|
|
26
|
+
return {
|
|
27
|
+
createRequest(path) {
|
|
28
|
+
return {
|
|
29
|
+
request: 'file',
|
|
30
|
+
content: path,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
exports.requestProviderFromFile = requestProviderFromFile;
|
|
36
|
+
function requestProviderFromText(text) {
|
|
37
|
+
return {
|
|
38
|
+
createRequest(path) {
|
|
39
|
+
return {
|
|
40
|
+
request: 'text',
|
|
41
|
+
content: text[path]
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
exports.requestProviderFromText = requestProviderFromText;
|
|
47
|
+
function requestFingerprint(request) {
|
|
48
|
+
return (0, object_hash_1.default)(request);
|
|
49
|
+
}
|
|
50
|
+
exports.requestFingerprint = requestFingerprint;
|
|
19
51
|
const ErrorMarker = 'err';
|
|
20
52
|
/**
|
|
21
53
|
* Provides the capability to parse R files/R code using the R parser.
|
|
@@ -24,33 +56,47 @@ const ErrorMarker = 'err';
|
|
|
24
56
|
* Throws if the file could not be parsed.
|
|
25
57
|
* If successful, allows to further query the last result with {@link retrieveNumberOfRTokensOfLastParse}.
|
|
26
58
|
*/
|
|
27
|
-
|
|
28
|
-
if (request.ensurePackageInstalled) {
|
|
29
|
-
await shell.ensurePackageInstalled('xmlparsedata', true);
|
|
30
|
-
}
|
|
59
|
+
function retrieveParseDataFromRCode(request, shell) {
|
|
31
60
|
const suffix = request.request === 'file' ? ', encoding="utf-8"' : '';
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
61
|
+
const eol = (0, lang_4_x_1.ts2r)(shell.options.eol);
|
|
62
|
+
const command =
|
|
63
|
+
/* first check if flowr_get is already part of the environment */
|
|
64
|
+
'if(!exists("flowr_get")){'
|
|
65
|
+
/* if not, define it complete wrapped in a try so that we can handle failures gracefully on stdout */
|
|
66
|
+
+ 'flowr_get<-function(...){tryCatch({'
|
|
67
|
+
/* 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! */
|
|
68
|
+
+ 'flowr_output<<-utils::getParseData(parse(...,keep.source=TRUE),includeText=TRUE);'
|
|
69
|
+
/* json conversion of the output, dataframe="values" allows us to receive a list of lists (which is more compact)!
|
|
70
|
+
* so we do not depend on jsonlite and friends, we do so manually (:sparkles:)
|
|
71
|
+
*/
|
|
72
|
+
+ `cat("[",paste0(apply(flowr_output,1,function(o)sprintf("[%s,%s,%s,%s,%s,%s,%s,%s,%s]",o[[1]],o[[2]],o[[3]],o[[4]],o[[5]],o[[6]],deparse(o[[7]]),if(o[[8]])"true"else"false",deparse(o[[9]]))),collapse=","),"]",${eol},sep="")`
|
|
73
|
+
/* error handling (just produce the marker) */
|
|
74
|
+
+ `},error=function(e){cat("${ErrorMarker}",${eol})})};`
|
|
75
|
+
/* compile the function to improve perf. */
|
|
76
|
+
+ 'flowr_get<-compiler::cmpfun(flowr_get)};'
|
|
77
|
+
/* call the function with the request */
|
|
78
|
+
+ `flowr_get(${request.request}=${JSON.stringify(request.content)}${suffix})`;
|
|
79
|
+
if (shell instanceof shell_executor_1.RShellExecutor) {
|
|
80
|
+
return guardRetrievedOutput(shell.run(command), request);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
return shell.sendCommandWithOutput(command).then(result => guardRetrievedOutput(result.join(shell.options.eol), request));
|
|
84
|
+
}
|
|
39
85
|
}
|
|
40
|
-
exports.
|
|
86
|
+
exports.retrieveParseDataFromRCode = retrieveParseDataFromRCode;
|
|
41
87
|
/**
|
|
42
|
-
* Uses {@link
|
|
88
|
+
* Uses {@link retrieveParseDataFromRCode} and returns the nicely formatted object-AST.
|
|
43
89
|
* If successful, allows to further query the last result with {@link retrieveNumberOfRTokensOfLastParse}.
|
|
44
90
|
*/
|
|
45
91
|
async function retrieveNormalizedAstFromRCode(request, shell, hooks) {
|
|
46
|
-
const
|
|
47
|
-
return
|
|
92
|
+
const data = await retrieveParseDataFromRCode(request, shell);
|
|
93
|
+
return (0, parser_1.normalize)(data, hooks);
|
|
48
94
|
}
|
|
49
95
|
exports.retrieveNormalizedAstFromRCode = retrieveNormalizedAstFromRCode;
|
|
50
96
|
/**
|
|
51
97
|
* If the string has (R-)quotes around it, they will be removed, otherwise the string is returned unchanged.
|
|
52
98
|
*/
|
|
53
|
-
function
|
|
99
|
+
function removeRQuotes(str) {
|
|
54
100
|
if (str.length > 1 && ((0, strings_1.startAndEndsWith)(str, '\'') || (0, strings_1.startAndEndsWith)(str, '"'))) {
|
|
55
101
|
return str.slice(1, -1);
|
|
56
102
|
}
|
|
@@ -58,14 +104,18 @@ function removeTokenMapQuotationMarks(str) {
|
|
|
58
104
|
return str;
|
|
59
105
|
}
|
|
60
106
|
}
|
|
61
|
-
exports.
|
|
107
|
+
exports.removeRQuotes = removeRQuotes;
|
|
62
108
|
/**
|
|
63
|
-
* Needs to be called *after* {@link
|
|
109
|
+
* Needs to be called *after* {@link retrieveParseDataFromRCode} (or {@link retrieveNormalizedAstFromRCode})
|
|
64
110
|
*/
|
|
65
111
|
async function retrieveNumberOfRTokensOfLastParse(shell) {
|
|
66
|
-
const result = await shell.sendCommandWithOutput(`cat(nrow(
|
|
112
|
+
const result = await shell.sendCommandWithOutput(`cat(nrow(flowr_output),${(0, lang_4_x_1.ts2r)(shell.options.eol)})`);
|
|
67
113
|
(0, assert_1.guard)(result.length === 1, () => `expected exactly one line to obtain the number of R tokens, but got: ${JSON.stringify(result)}`);
|
|
68
114
|
return Number(result[0]);
|
|
69
115
|
}
|
|
70
116
|
exports.retrieveNumberOfRTokensOfLastParse = retrieveNumberOfRTokensOfLastParse;
|
|
117
|
+
function guardRetrievedOutput(output, request) {
|
|
118
|
+
(0, assert_1.guard)(output !== ErrorMarker, () => `unable to parse R code (see the log for more information) for request ${JSON.stringify(request)}}`);
|
|
119
|
+
return output;
|
|
120
|
+
}
|
|
71
121
|
//# sourceMappingURL=retriever.js.map
|
|
@@ -1,25 +1,11 @@
|
|
|
1
1
|
import type { RShellExecutionOptions } from './shell';
|
|
2
2
|
import type { SemVer } from 'semver';
|
|
3
|
-
import type { TokenMap } from './retriever';
|
|
4
3
|
export declare class RShellExecutor {
|
|
5
4
|
readonly options: Readonly<RShellExecutionOptions>;
|
|
6
|
-
private readonly log;
|
|
7
5
|
private readonly prerequisites;
|
|
8
6
|
constructor(options?: Partial<RShellExecutionOptions>);
|
|
9
|
-
continueOnError():
|
|
10
|
-
|
|
11
|
-
tryToInjectHomeLibPath(): RShellExecutor;
|
|
12
|
-
addPrerequisites(commands: string | string[]): RShellExecutor;
|
|
7
|
+
continueOnError(): this;
|
|
8
|
+
addPrerequisites(commands: string | string[]): this;
|
|
13
9
|
usedRVersion(): SemVer | null;
|
|
14
|
-
|
|
15
|
-
isPackageInstalled(packageName: string): boolean;
|
|
16
|
-
ensurePackageInstalled(packageName: string, autoload?: boolean, force?: boolean): {
|
|
17
|
-
packageName: string;
|
|
18
|
-
packageExistedAlready: boolean;
|
|
19
|
-
/** the temporary directory used for the installation, undefined if none was used */
|
|
20
|
-
libraryLocation?: string;
|
|
21
|
-
};
|
|
22
|
-
obtainTempDir(): string;
|
|
23
|
-
getTokenMap(): TokenMap;
|
|
24
|
-
run(commands: string | string[], returnErr?: boolean): string;
|
|
10
|
+
run(command: string, returnErr?: boolean): string;
|
|
25
11
|
}
|
|
@@ -10,107 +10,38 @@ const child_process_1 = require("child_process");
|
|
|
10
10
|
const lang_4_x_1 = require("./lang-4.x");
|
|
11
11
|
const preload_1 = __importDefault(require("semver/preload"));
|
|
12
12
|
const log_1 = require("../util/log");
|
|
13
|
-
const
|
|
14
|
-
const retriever_1 = require("./retriever");
|
|
13
|
+
const executorLog = log_1.log.getSubLogger({ name: 'RShellExecutor' });
|
|
15
14
|
class RShellExecutor {
|
|
16
15
|
options;
|
|
17
|
-
log;
|
|
18
16
|
prerequisites = [];
|
|
19
17
|
constructor(options) {
|
|
20
18
|
this.options = (0, objects_1.deepMergeObject)(shell_1.DEFAULT_R_SHELL_OPTIONS, options);
|
|
21
|
-
this.log = log_1.log.getSubLogger({ name: 'RShellExecutor' });
|
|
22
19
|
}
|
|
23
20
|
continueOnError() {
|
|
24
|
-
|
|
21
|
+
executorLog.info('continue in case of Errors');
|
|
25
22
|
this.addPrerequisites('options(error=function() {})');
|
|
26
23
|
return this;
|
|
27
24
|
}
|
|
28
|
-
injectLibPaths(...paths) {
|
|
29
|
-
this.log.debug(`injecting lib paths ${JSON.stringify(paths)}`);
|
|
30
|
-
this.addPrerequisites(`.libPaths(c(.libPaths(), ${paths.map(lang_4_x_1.ts2r).join(',')}))`);
|
|
31
|
-
return this;
|
|
32
|
-
}
|
|
33
|
-
tryToInjectHomeLibPath() {
|
|
34
|
-
if (this.options.homeLibPath === undefined) {
|
|
35
|
-
this.log.debug('ensuring home lib path exists (automatic inject)');
|
|
36
|
-
this.addPrerequisites([
|
|
37
|
-
'if(!dir.exists(Sys.getenv("R_LIBS_USER"))) { dir.create(path=Sys.getenv("R_LIBS_USER"),showWarnings=FALSE,recursive=TRUE) }',
|
|
38
|
-
'.libPaths(c(.libPaths(), Sys.getenv("R_LIBS_USER")))'
|
|
39
|
-
]);
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
this.injectLibPaths(this.options.homeLibPath);
|
|
43
|
-
}
|
|
44
|
-
return this;
|
|
45
|
-
}
|
|
46
25
|
addPrerequisites(commands) {
|
|
47
26
|
this.prerequisites.push(...(typeof commands == 'string' ? [commands] : commands));
|
|
48
27
|
return this;
|
|
49
28
|
}
|
|
50
29
|
usedRVersion() {
|
|
51
30
|
const version = this.run(`cat(paste0(R.version$major,".",R.version$minor), ${(0, lang_4_x_1.ts2r)(this.options.eol)})`);
|
|
52
|
-
|
|
31
|
+
executorLog.trace(`raw version: ${JSON.stringify(version)}`);
|
|
53
32
|
return preload_1.default.coerce(version);
|
|
54
33
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
isPackageInstalled(packageName) {
|
|
61
|
-
this.log.debug(`checking if package "${packageName}" is installed`);
|
|
62
|
-
return this.run(`cat(system.file(package="${packageName}")!="","${this.options.eol}")`) === 'TRUE';
|
|
63
|
-
}
|
|
64
|
-
ensurePackageInstalled(packageName, autoload = false, force = false) {
|
|
65
|
-
const packageExistedAlready = this.isPackageInstalled(packageName);
|
|
66
|
-
if (!force && packageExistedAlready) {
|
|
67
|
-
this.log.info(`package "${packageName}" is already installed`);
|
|
68
|
-
if (autoload)
|
|
69
|
-
this.addPrerequisites(`library(${(0, lang_4_x_1.ts2r)(packageName)})`);
|
|
70
|
-
return { packageName, packageExistedAlready };
|
|
34
|
+
run(command, returnErr = false) {
|
|
35
|
+
command += ';base::quit()';
|
|
36
|
+
if (executorLog.settings.minLevel >= 1 /* LogLevel.Trace */) {
|
|
37
|
+
executorLog.trace(`> ${JSON.stringify(command)}`);
|
|
71
38
|
}
|
|
72
|
-
const tempDir = this.obtainTempDir();
|
|
73
|
-
this.log.debug(`using temporary directory: "${tempDir}" to install package "${packageName}"`);
|
|
74
|
-
this.run(`install.packages(${(0, lang_4_x_1.ts2r)(packageName)},repos="https://cloud.r-project.org/",quiet=FALSE,lib=temp)`);
|
|
75
|
-
if (autoload)
|
|
76
|
-
this.addPrerequisites(`library(${(0, lang_4_x_1.ts2r)(packageName)},lib.loc=temp)`);
|
|
77
|
-
return { packageName, packageExistedAlready, libraryLocation: tempDir };
|
|
78
|
-
}
|
|
79
|
-
obtainTempDir() {
|
|
80
|
-
const tempDir = this.run([
|
|
81
|
-
'temp <- tempdir()',
|
|
82
|
-
`cat(temp, ${(0, lang_4_x_1.ts2r)(this.options.eol)})`
|
|
83
|
-
]);
|
|
84
|
-
log_1.log.info(`obtained temp dir ${tempDir}`);
|
|
85
|
-
const deleteOnExit = function () {
|
|
86
|
-
if (fs_1.default.existsSync(tempDir)) {
|
|
87
|
-
log_1.log.info(`deleting temp dir ${tempDir}`);
|
|
88
|
-
fs_1.default.rmSync(tempDir, { recursive: true, force: true });
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
process.on('SIGINT', deleteOnExit);
|
|
92
|
-
process.on('SIGTERM', deleteOnExit);
|
|
93
|
-
return tempDir;
|
|
94
|
-
}
|
|
95
|
-
getTokenMap() {
|
|
96
|
-
this.ensurePackageInstalled('xmlparsedata', true);
|
|
97
|
-
// we invert the token map to get a mapping back from the replacement
|
|
98
|
-
const parsed = (0, lang_4_x_1.parseCSV)(this.run('write.table(xmlparsedata::xml_parse_token_map,sep=",",col.names=FALSE)').split('\n'));
|
|
99
|
-
if (parsed.some(s => s.length !== 2))
|
|
100
|
-
throw new Error(`Expected two columns in token map, but got ${JSON.stringify(parsed)}`);
|
|
101
|
-
// we swap key and value to get the other direction, furthermore we remove quotes from keys if they are quoted
|
|
102
|
-
const ret = {};
|
|
103
|
-
for (const [key, value] of parsed)
|
|
104
|
-
ret[value] = (0, retriever_1.removeTokenMapQuotationMarks)(key);
|
|
105
|
-
return ret;
|
|
106
|
-
}
|
|
107
|
-
run(commands, returnErr = false) {
|
|
108
|
-
this.log.trace(`> ${JSON.stringify(commands)}`);
|
|
109
39
|
const returns = (0, child_process_1.spawnSync)(this.options.pathToRExecutable, this.options.commandLineOptions, {
|
|
110
40
|
env: this.options.env,
|
|
111
41
|
cwd: this.options.cwd,
|
|
42
|
+
windowsHide: true,
|
|
112
43
|
encoding: 'utf8',
|
|
113
|
-
input: [...this.prerequisites,
|
|
44
|
+
input: [...this.prerequisites, command].join(this.options.eol)
|
|
114
45
|
});
|
|
115
46
|
return (returnErr ? returns.stderr : returns.stdout).trim();
|
|
116
47
|
}
|
package/r-bridge/shell.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { type MergeableRecord } from '../util/objects';
|
|
3
3
|
import type { SemVer } from 'semver';
|
|
4
|
-
import type { TokenMap } from './retriever';
|
|
5
4
|
export type OutputStreamSelector = 'stdout' | 'stderr' | 'both';
|
|
6
5
|
export interface CollectorTimeout extends MergeableRecord {
|
|
7
6
|
/**
|
|
@@ -60,6 +59,7 @@ export interface RShellSessionOptions extends RShellExecutionOptions {
|
|
|
60
59
|
export interface RShellOptions extends RShellSessionOptions {
|
|
61
60
|
readonly sessionName: string;
|
|
62
61
|
}
|
|
62
|
+
export declare const DEFAULT_R_PATH: string;
|
|
63
63
|
export declare const DEFAULT_R_SHELL_EXEC_OPTIONS: RShellExecutionOptions;
|
|
64
64
|
export declare const DEFAULT_R_SHELL_OPTIONS: RShellOptions;
|
|
65
65
|
/**
|
|
@@ -75,7 +75,6 @@ export declare class RShell {
|
|
|
75
75
|
private session;
|
|
76
76
|
private readonly log;
|
|
77
77
|
private versionCache;
|
|
78
|
-
private tokenMapCache;
|
|
79
78
|
private tempDirs;
|
|
80
79
|
constructor(options?: Partial<RShellOptions>);
|
|
81
80
|
private revive;
|
|
@@ -85,13 +84,12 @@ export declare class RShell {
|
|
|
85
84
|
*/
|
|
86
85
|
sendCommand(command: string): void;
|
|
87
86
|
usedRVersion(): Promise<SemVer | null>;
|
|
87
|
+
injectLibPaths(...paths: string[]): void;
|
|
88
|
+
tryToInjectHomeLibPath(): void;
|
|
88
89
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* @note For multiple calls, this makes use of caching
|
|
90
|
+
* checks if a given package is already installed on the system!
|
|
92
91
|
*/
|
|
93
|
-
|
|
94
|
-
private retrieveTokenMap;
|
|
92
|
+
isPackageInstalled(packageName: string): Promise<boolean>;
|
|
95
93
|
/**
|
|
96
94
|
* Send a command and collect the output
|
|
97
95
|
*
|
|
@@ -115,26 +113,6 @@ export declare class RShell {
|
|
|
115
113
|
* continue working!
|
|
116
114
|
*/
|
|
117
115
|
continueOnError(): void;
|
|
118
|
-
injectLibPaths(...paths: string[]): void;
|
|
119
|
-
tryToInjectHomeLibPath(): void;
|
|
120
|
-
/**
|
|
121
|
-
* checks if a given package is already installed on the system!
|
|
122
|
-
*/
|
|
123
|
-
isPackageInstalled(packageName: string): Promise<boolean>;
|
|
124
|
-
allInstalledPackages(): Promise<string[]>;
|
|
125
|
-
/**
|
|
126
|
-
* Installs the package using a temporary location
|
|
127
|
-
*
|
|
128
|
-
* @param packageName - The package to install
|
|
129
|
-
* @param autoload - If true, the package will be loaded after installation
|
|
130
|
-
* @param force - If true, the package will be installed no if it is already on the system and ready to be loaded
|
|
131
|
-
*/
|
|
132
|
-
ensurePackageInstalled(packageName: string, autoload?: boolean, force?: boolean): Promise<{
|
|
133
|
-
packageName: string;
|
|
134
|
-
packageExistedAlready: boolean;
|
|
135
|
-
/** the temporary directory used for the installation, undefined if none was used */
|
|
136
|
-
libraryLocation?: string;
|
|
137
|
-
}>;
|
|
138
116
|
/**
|
|
139
117
|
* Obtain the temporary directory used by R.
|
|
140
118
|
* Additionally, this marks the directory for removal when the shell exits.
|