Beispiel #1
0
        /// <summary>
        /// Copies file from local file path to Temp folder on the remote session.
        /// </summary>
        /// <param name="filePath">Path to the file to be sent to remote session.</param>
        /// <param name="doCleanUp">true to add blob upon transfer for cleanup on dispose, false to ignore it after transfer.</param>
        /// <returns>Path to the file on the remote machine.</returns>
        public async Task <string> CopyFileToRemoteTempAsync(string filePath, bool doCleanUp, IProgress <long> progress, CancellationToken cancellationToken)
        {
            string fileName = Path.GetFileName(filePath);
            var    blobinfo = await SendFileAsync(filePath, doCleanUp, progress, cancellationToken);

            return(await _session.EvaluateAsync <string>(Invariant($"rtvs:::save_to_temp_folder({blobinfo.Id}, {fileName.ToRStringLiteral()})"), REvaluationKind.Normal, cancellationToken));
        }
Beispiel #2
0
        public async Task RawResult(byte[] data)
        {
            string expr = $"as.raw(c({string.Join(", ", data)}))";
            var    res  = await _session.EvaluateAsync(expr, REvaluationKind.RawResult);

            res.Result.Should().BeNull();
            res.RawResult.Should().Equal(data);

            var bytes = await _session.EvaluateAsync <byte[]>(expr, REvaluationKind.Normal);

            bytes.Should().Equal(data);
        }
        /// <summary>
        /// Gets contents of a remote file and copies it to given stream. This method adds the blob for clean up by default.
        /// </summary>
        /// <param name="remoteFile"></param>
        /// <param name="stream"></param>
        /// <param name="doCleanUp"></param>
        public async Task CopyToFileStreamAsync(string remoteFile, Stream stream, bool doCleanUp = true, IProgress <long> progress = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            string     filePath = remoteFile.ToRPath().ToRStringLiteral();
            IRBlobInfo blob     = new RBlobInfo(await _session.EvaluateAsync <ulong>($"rtvs:::create_blob(readBin({filePath}, 'raw', file.info({filePath})$size))", REvaluationKind.Normal, cancellationToken));

            using (RBlobStream blobStream = await RBlobStream.OpenAsync(blob, _blobService, cancellationToken)) {
                await blobStream.CopyToAsync(stream, progress, cancellationToken);
            }

            if (doCleanUp)
            {
                _cleanup.Add(blob);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Evaluates an R expresion in the specified environment, and returns an object describing the result.
        /// </summary>
        /// <param name="environmentExpression">
        /// R expression designating the environment in which <paramref name="expression"/> will be evaluated.
        /// </param>
        /// <param name="expression">Expression to evaluate.</param>
        /// <param name="name"><see cref="IREvaluationResultInfo.Name"/> of the returned evaluation result.</param>
        /// <param name="properties">Specifies which <see cref="IREvaluationResultInfo"/> properties should be present in the result.</param>
        /// <param name="repr">
        /// An R expression that must evaluate to a function that takes an R value as its sole argument, and returns the
        /// string representation of that argument as a single-element character vector. The representation is stored in
        /// <see cref="IRValueInfo.Representation"/> property of the produced result. If this argument is
        /// <see langword="null"/>, no representation is computed, and <see cref="IRValueInfo.Representation"/>
        /// will also be <see langword="null"/>.
        /// Use helper properties and methods in <see cref="RValueRepresentations"/> to obtain an appropriate expression
        /// for standard R functions such as <c>deparse()</c> or <c>str()</c>.
        /// </param>
        /// <remarks>
        /// <returns>
        /// If evaluation succeeded, an instance of <see cref="IRValueInfo"/> describing the resulting value.
        /// If evaluation failed with an error, an instance of <see cref="IRErrorInfo"/> describing the error.
        /// This method never returns <see cref="IRActiveBindingInfo"/> or <see cref="IRPromiseInfo"/>.
        /// </returns>
        public static async Task <IREvaluationResultInfo> TryEvaluateAndDescribeAsync(
            this IRSession session,
            string environmentExpression,
            string expression,
            string name,
            REvaluationResultProperties properties,
            string repr,
            CancellationToken cancellationToken = default(CancellationToken)
            )
        {
            if (environmentExpression == null)
            {
                throw new ArgumentNullException(nameof(environmentExpression));
            }
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            await TaskUtilities.SwitchToBackgroundThread();

            environmentExpression = environmentExpression ?? "NULL";
            var code   = Invariant($"rtvs:::eval_and_describe({expression.ToRStringLiteral()}, ({environmentExpression}),, {properties.ToRVector()},, {repr})");
            var result = await session.EvaluateAsync <JObject>(code, REvaluationKind.Normal, cancellationToken);

            return(REvaluationResultInfo.Parse(session, environmentExpression, name, result));
        }
Beispiel #5
0
        private async Task ExportToImageAsync(IRSession session, string format, string filePath, int widthInPixels, int heightInPixels, int resolution)
        {
            string script = String.Format("rtvs:::export_to_image({0}, {1}, {2}, {3})", format, widthInPixels, heightInPixels, resolution);
            var    data   = await session.EvaluateAsync <byte[]>(script, REvaluationKind.Normal);

            File.WriteAllBytes(filePath, data);
        }
Beispiel #6
0
        public async Task Serialize(string expr, string json)
        {
            if (json == SameAsInput)
            {
                json = expr;
            }

            var res = await _session.EvaluateAsync(expr, REvaluationKind.Normal);

            res.Error.Should().BeNullOrEmpty();
            res.Result.Should().NotBeNull();
            res.RawResult.Should().BeNull();
            var actualJson = JsonConvert.SerializeObject(res.Result).ToUnicodeQuotes();

            actualJson.Should().Be(json);
        }
Beispiel #7
0
        private async Task RMarkdownRenderAsync(IRSession session, IFileSystem fs, string inputFilePath, string outputFilePath, string format, int codePage, IApplicationShell appShell)
        {
            using (var fts = new DataTransferSession(session, fs)) {
                string       currentStatusText = string.Empty;
                uint         cookie            = 0;
                IVsStatusbar statusBar         = null;
                appShell.DispatchOnUIThread(() => {
                    statusBar = appShell.GetGlobalService <IVsStatusbar>(typeof(SVsStatusbar));
                    statusBar.GetText(out currentStatusText);
                    statusBar.Progress(ref cookie, 1, "", 0, 0);
                });

                try {
                    appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownSendingInputFile.FormatInvariant(Path.GetFileName(inputFilePath)), 0, 3); });
                    var rmd = await fts.SendFileAsync(inputFilePath);

                    appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownPublishingFile.FormatInvariant(Path.GetFileName(inputFilePath)), 1, 3); });
                    var publishResult = await session.EvaluateAsync <ulong>($"rtvs:::rmarkdown_publish(blob_id = {rmd.Id}, output_format = {format.ToRStringLiteral()}, encoding = 'cp{codePage}')", REvaluationKind.Normal);

                    appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownGetOutputFile.FormatInvariant(Path.GetFileName(outputFilePath)), 2, 3); });
                    await fts.FetchFileAsync(new RBlobInfo(publishResult), outputFilePath);

                    appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownPublishComplete.FormatInvariant(Path.GetFileName(outputFilePath)), 3, 3); });
                } finally {
                    appShell.DispatchOnUIThread(() => {
                        statusBar?.Progress(ref cookie, 0, "", 0, 0);
                        statusBar?.SetText(currentStatusText);
                    });
                }
            }
        }
Beispiel #8
0
        public async Task <IGridData <string> > GetGridDataAsync(string expression, GridRange?gridRange, ISortOrder sortOrder = null)
        {
            await TaskUtilities.SwitchToBackgroundThread();

            var rows        = gridRange?.Rows.ToRString();
            var columns     = gridRange?.Columns.ToRString();
            var rowSelector = (sortOrder != null && !sortOrder.IsEmpty) ? sortOrder.GetRowSelector() : "";

            if (_gridData != null && _expression == expression && _rows == rows && _columns == columns && _rowSelector == rowSelector)
            {
                return(_gridData);
            }

            var expr = Invariant($"rtvs:::grid_data({expression}, {rows}, {columns}, {rowSelector})");

            try {
                _gridData = await _session.EvaluateAsync <GridData>(expr, REvaluationKind.Normal);

                _expression  = expression;
                _rows        = rows;
                _columns     = columns;
                _rowSelector = rowSelector;
            } catch (RException ex) {
                var message = Invariant($"Grid data evaluation failed:{Environment.NewLine}{ex.Message}");
                VsAppShell.Current.Log().Write(LogVerbosity.Normal, MessageCategory.Error, message);
            }
            return(_gridData);
        }
Beispiel #9
0
 private async Task RMarkdownRenderAsync(IRSession session, IFileSystem fs, string inputFilePath, string outputFilePath, string format, int codePage, IApplicationShell appShell) {
     using (var fts = new DataTransferSession(session, fs)) {
         string currentStatusText = string.Empty;
         uint cookie = 0;
         IVsStatusbar statusBar = null;
         appShell.DispatchOnUIThread(() => {
             statusBar = appShell.GetGlobalService<IVsStatusbar>(typeof(SVsStatusbar));
             statusBar.GetText(out currentStatusText);
             statusBar.Progress(ref cookie, 1, "", 0, 0);
         });
         
         try {
             // TODO: progress and cancellation handling
             appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownSendingInputFile.FormatInvariant(Path.GetFileName(inputFilePath)), 0, 3); });
             var rmd = await fts.SendFileAsync(inputFilePath, true, null, CancellationToken.None);
             appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownPublishingFile.FormatInvariant(Path.GetFileName(inputFilePath)), 1, 3); });
             var publishResult = await session.EvaluateAsync<ulong>($"rtvs:::rmarkdown_publish(blob_id = {rmd.Id}, output_format = {format.ToRStringLiteral()}, encoding = 'cp{codePage}')", REvaluationKind.Normal);
             appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownGetOutputFile.FormatInvariant(Path.GetFileName(outputFilePath)), 2, 3); });
             await fts.FetchFileAsync(new RBlobInfo(publishResult), outputFilePath, true, null, CancellationToken.None);
             appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownPublishComplete.FormatInvariant(Path.GetFileName(outputFilePath)), 3, 3); });
         } finally {
             appShell.DispatchOnUIThread(() => {
                 statusBar?.Progress(ref cookie, 0, "", 0, 0);
                 statusBar?.SetText(currentStatusText);
             });
         }
     }
 }
Beispiel #10
0
        private async Task RMarkdownRenderAsync(IRSession session, string inputFilePath, string outputFilePath, string format, int codePage, IServiceContainer services)
        {
            using (var fts = new DataTransferSession(session, services.FileSystem())) {
                string       currentStatusText = string.Empty;
                uint         cookie            = 0;
                IVsStatusbar statusBar         = null;
                services.MainThread().Post(() => {
                    statusBar = services.GetService <IVsStatusbar>(typeof(SVsStatusbar));
                    statusBar.GetText(out currentStatusText);
                    statusBar.Progress(ref cookie, 1, "", 0, 0);
                });

                try {
                    // TODO: progress and cancellation handling
                    services.MainThread().Post(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownSendingInputFile.FormatInvariant(Path.GetFileName(inputFilePath)), 0, 3); });
                    var rmd = await fts.SendFileAsync(inputFilePath, true, null, CancellationToken.None);

                    services.MainThread().Post(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownPublishingFile.FormatInvariant(Path.GetFileName(inputFilePath)), 1, 3); });
                    var publishResult = await session.EvaluateAsync <ulong>($"rtvs:::rmarkdown_publish(blob_id = {rmd.Id}, output_format = {format.ToRStringLiteral()}, encoding = 'cp{codePage}')", REvaluationKind.Normal);

                    services.MainThread().Post(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownGetOutputFile.FormatInvariant(Path.GetFileName(outputFilePath)), 2, 3); });
                    await fts.FetchFileAsync(new RBlobInfo(publishResult), outputFilePath, true, null, CancellationToken.None);

                    services.MainThread().Post(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownPublishComplete.FormatInvariant(Path.GetFileName(outputFilePath)), 3, 3); });
                } finally {
                    services.MainThread().Post(() => {
                        statusBar?.Progress(ref cookie, 0, "", 0, 0);
                        statusBar?.SetText(currentStatusText);
                    });
                }
            }
        }
Beispiel #11
0
        private async Task RMarkdownRenderAsync(IRSession session, IFileSystem fs, string inputFilePath, string outputFilePath, string format, int codePage)
        {
            using (var fts = new FileTransferSession(session, fs)) {
                var rmd = await fts.SendFileAsync(inputFilePath);

                var publishResult = await session.EvaluateAsync <byte[]>($"rtvs:::rmarkdown_publish(blob_id = {rmd.Id}, output_format = {format.ToRStringLiteral()}, encoding = 'cp{codePage}')", REvaluationKind.Normal);

                File.WriteAllBytes(outputFilePath, publishResult);
            }
        }
Beispiel #12
0
        private async Task ExportToImageAsync(IRSession session, string format, string filePath, int widthInPixels, int heightInPixels, int resolution)
        {
            string script = String.Format(@"
device_id <- rtvs:::graphics.ide.getactivedeviceid()
rtvs:::export_to_image(device_id, rtvs:::graphics.ide.getactiveplotid(device_id), {0}, {1}, {2}, {3})
", format, widthInPixels, heightInPixels, resolution);
            var    blobid = await session.EvaluateAsync <ulong>(script, REvaluationKind.Normal);

            using (DataTransferSession dts = new DataTransferSession(session, new FileSystem())) {
                await dts.FetchFileAsync(new RBlobInfo(blobid), filePath, true, null, CancellationToken.None);
            }
        }
Beispiel #13
0
        public async Task QuantmodGrid()
        {
            try {
                await _session.EvaluateAsync("quantmod::getSymbols", REvaluationKind.NoResult);
            } catch (REvaluationException) {
                Assert.True(false, "quantmod package is not installed");
            }

            await Test("quantmod::getSymbols('MSFT', auto.assign=FALSE)['2016-03-23::2016-03-28']", 1, 1, new[, ] {
                { null, "MSFT.Open", "MSFT.High", "MSFT.Low", "MSFT.Close", "MSFT.Volume", "MSFT.Adjusted" },
                { "2016-03-23", "54.11", "54.24", "53.74", "53.97", "20129000", "52.58695" },
                { "2016-03-24", "53.84", "54.33", "53.73", "54.21", "19950000", "52.82079" },
                { "2016-03-28", "54.21", "54.29", "53.33", "53.54", "17025100", "52.16797" },
            });
        }
Beispiel #14
0
        public static async Task<IGridData<string>> GetGridDataAsync(IRSession rSession, string expression, GridRange? gridRange, ISortOrder sortOrder = null) {
            await TaskUtilities.SwitchToBackgroundThread();

            string rows = gridRange?.Rows.ToRString();
            string columns = gridRange?.Columns.ToRString();
            string rowSelector = (sortOrder != null && !sortOrder.IsEmpty) ? sortOrder.GetRowSelector() : "";
            string expr = Invariant($"rtvs:::grid_data({expression}, {rows}, {columns}, {rowSelector})");

            try {
                return await rSession.EvaluateAsync<GridData>(expr, REvaluationKind.Normal);
            } catch (RException ex) {
                var message = Invariant($"Grid data evaluation failed:{Environment.NewLine}{ex.Message}");
                await VsAppShell.Current.Services.Log.WriteAsync(LogVerbosity.Normal, MessageCategory.Error, message);
                return null;
            }
        }
Beispiel #15
0
        public static async Task <IGridData <string> > GetGridDataAsync(IRSession rSession, string expression, GridRange?gridRange, ISortOrder sortOrder = null)
        {
            await TaskUtilities.SwitchToBackgroundThread();

            string rows        = gridRange?.Rows.ToRString();
            string columns     = gridRange?.Columns.ToRString();
            string rowSelector = (sortOrder != null && !sortOrder.IsEmpty) ? sortOrder.GetRowSelector() : "";
            string expr        = Invariant($"rtvs:::grid_data({expression}, {rows}, {columns}, {rowSelector})");

            try {
                return(await rSession.EvaluateAsync <GridData>(expr, REvaluationKind.Normal));
            } catch (RException ex) {
                var message = Invariant($"Grid data evaluation failed:{Environment.NewLine}{ex.Message}");
                VsAppShell.Current.Services.Log.Write(LogVerbosity.Normal, MessageCategory.Error, message);
                return(null);
            }
        }
Beispiel #16
0
        public async Task SetBreakpointOnNull()
        {
            const string code =
                @"f <- function() {
    NULL
  }";

            var tracer = await _session.TraceExecutionAsync();

            using (var sf = new SourceFile(code)) {
                var bp = await tracer.CreateBreakpointAsync(new RSourceLocation(sf.FilePath, 2));

                tracer.Breakpoints.Count.Should().Be(1);

                await sf.Source(_session);

                (await _session.EvaluateAsync <bool>("is.function(f)", REvaluationKind.Normal)).Should().BeTrue();
            }
        }
Beispiel #17
0
        public async Task RefreshEnvironmentsAsync()
        {
            await TaskUtilities.SwitchToBackgroundThread();

            var  envs    = new List <REnvironment>();
            bool success = false;

            try {
                var traceback = (await _rSession.TracebackAsync())
                                .Skip(1) // skip global - it's in the search path already
                                .Select(frame => new REnvironment(frame))
                                .Reverse();
                if (traceback.Any())
                {
                    envs.AddRange(traceback);
                    envs.Add(null);
                }

                var searchPath = (await _rSession.EvaluateAsync <string[]>("as.list(search())", REvaluationKind.BaseEnv))
                                 .Except(_hiddenEnvironments)
                                 .Select(name => new REnvironment(name));
                envs.AddRange(searchPath);

                success = true;
            } catch (RException) {
            } catch (MessageTransportException) {
            } catch (OperationCanceledException) {
            }

            VsAppShell.Current.DispatchOnUIThread(() => {
                var oldSelection = _selectedEnvironment;
                _environments.ReplaceWith(success ? envs : _errorEnvironments);

                IREnvironment newSelection = null;
                if (oldSelection != null)
                {
                    newSelection = _environments?.FirstOrDefault(env => env?.Name == oldSelection.Name);
                }
                SelectedEnvironment = newSelection ?? _environments.FirstOrDefault();
            });
        }
Beispiel #18
0
        private async Task RMarkdownRenderAsync(IRSession session, string inputFilePath, string outputFilePath, string format, int codePage, IServiceContainer services)
        {
            using (var fts = new DataTransferSession(session, services.FileSystem())) {
                var statusBar = services.GetService <IStatusBar>();
                using (var progress = await statusBar.ShowProgressAsync(3)) {
                    // TODO: cancellation handling
                    progress.Report(new StatusBarProgressData(Resources.Info_MarkdownSendingInputFile.FormatInvariant(Path.GetFileName(inputFilePath)), 0));

                    var rmd = await fts.SendFileAsync(inputFilePath, true, null, CancellationToken.None);

                    progress.Report(new StatusBarProgressData(Resources.Info_MarkdownPublishingFile.FormatInvariant(Path.GetFileName(inputFilePath)), 1));

                    var publishResult = await session.EvaluateAsync <ulong>($"rtvs:::rmarkdown_publish(blob_id = {rmd.Id}, output_format = {format.ToRStringLiteral()}, encoding = 'cp{codePage}')", REvaluationKind.Normal);

                    progress.Report(new StatusBarProgressData(Resources.Info_MarkdownGetOutputFile.FormatInvariant(Path.GetFileName(outputFilePath)), 2));
                    await fts.FetchFileAsync(new RBlobInfo(publishResult), outputFilePath, true, null, CancellationToken.None);

                    progress.Report(new StatusBarProgressData(Resources.Info_MarkdownPublishComplete.FormatInvariant(Path.GetFileName(outputFilePath)), 3));
                }
            }
        }
Beispiel #19
0
        public async Task RemoveBreakpointWhileRunning()
        {
            const string code =
                @"browser()
  f <- function() {
    NULL
    browser()
  }
  b <- FALSE;
  while (TRUE) if (b) f()";

            using (var debugSession = new DebugSession(_session))
                using (var sf = new SourceFile(code)) {
                    await debugSession.EnableBreakpointsAsync(true);

                    await sf.Source(_session);

                    await debugSession.NextPromptShouldBeBrowseAsync();

                    var bp = await debugSession.CreateBreakpointAsync(sf, 3);

                    int hitCount = 0;
                    bp.BreakpointHit += delegate { ++hitCount; };

                    await debugSession.ContinueAsync();

                    await Task.Delay(100);

                    await bp.DeleteAsync();

                    await _session.EvaluateAsync("b <- TRUE", REvaluationKind.Mutating);

                    await debugSession.NextPromptShouldBeBrowseAsync();

                    (await debugSession.GetStackFramesAsync()).Should().HaveTail(new MatchDebugStackFrames {
                        { sf, 4 }
                    });
                    hitCount.Should().Be(0);
                }
        }
Beispiel #20
0
        /// <summary>
        /// Retrieve the current call stack, in call order (i.e. the current active frame is last, the one that called it is second to last etc).
        /// </summary>
        /// <param name="skipSourceFrames">
        /// If <see langword="true"/>, excludes frames that belong to <c>source()</c> or <c>rtvs:::debug_source()</c> internal machinery at the bottom of the stack;
        /// the first reported frame will be the one with sourced code.
        /// </param>
        /// <remarks>
        /// This method has snapshot semantics for the frames and their properties - that is, the returned collection is not going to change as code runs.
        /// However, calling various methods on the returned <see cref="IRStackFrame"/> objects, such as <see cref="RStackFrameExtensions.DescribeChildrenAsync"/>,
        /// will fetch fresh data, possibly from altogether different frames if the call stack has changed. Thus, it is inadvisable to retain the returned
        /// stack and use it at a later point - it should always be obtained anew at the point where it is used.
        /// </remarks>
        public static async Task <IReadOnlyList <IRStackFrame> > TracebackAsync(
            this IRSession session,
            bool skipSourceFrames = true,
            CancellationToken cancellationToken = default
            )
        {
            await TaskUtilities.SwitchToBackgroundThread();

            var jFrames = await session.EvaluateAsync <JArray>("rtvs:::describe_traceback()", REvaluationKind.Normal, cancellationToken);

            Trace.Assert(jFrames.All(t => t is JObject), "rtvs:::describe_traceback(): array of objects expected.\n\n" + jFrames);

            var stackFrames = new List <RStackFrame>();

            RStackFrame lastFrame = null;
            int         i         = 0;

            foreach (JObject jFrame in jFrames)
            {
                lastFrame = new RStackFrame(session, i, lastFrame, jFrame);
                stackFrames.Add(lastFrame);
                ++i;
            }

            if (skipSourceFrames)
            {
                var firstFrame = stackFrames.FirstOrDefault();
                if (firstFrame != null && firstFrame.IsGlobal && firstFrame.Call != null)
                {
                    if (firstFrame.Call.StartsWith("source(") || firstFrame.Call.StartsWith("rtvs::debug_source("))
                    {
                        // Skip everything until the first frame that has a line number - that will be the sourced code.
                        stackFrames = stackFrames.SkipWhile(f => f.LineNumber == null).ToList();
                    }
                }
            }

            return(stackFrames);
        }
Beispiel #21
0
        public async Task BreakContinue()
        {
            const string code =
                @"browser()
  x <- 0
  while (x >= 0) {
    x <- x + 1
  }
  browser()";

            using (var debugSession = new DebugSession(_session))
                using (var sf = new SourceFile(code)) {
                    await sf.Source(_session);

                    await debugSession.NextPromptShouldBeBrowseAsync();

                    await debugSession.ContinueAsync();

                    await Task.Delay(100);

                    await debugSession.BreakAsync();

                    await debugSession.NextPromptShouldBeBrowseAsync();

                    (await debugSession.GetStackFramesAsync()).Should().HaveTail(new MatchDebugStackFrames {
                        { sf, new MatchRange <int>(1, 3) }
                    });

                    await _session.EvaluateAsync("x <- -42", REvaluationKind.Mutating);

                    await debugSession.ContinueAsync();

                    await debugSession.NextPromptShouldBeBrowseAsync();

                    (await debugSession.GetStackFramesAsync()).Should().HaveTail(new MatchDebugStackFrames {
                        { sf, 6 }
                    });
                }
        }
Beispiel #22
0
        /// <summary>
        /// Given function name returns package the function belongs to.
        /// The package is determined from the interactive R session since
        /// there may be functions with the same name but from different packages.
        /// Most recently loaded package typically wins.
        /// </summary>
        /// <param name="functionName">R function name</param>
        /// <returns>Function package or null if undefined</returns>
        public async Task <string> GetFunctionPackageNameAsync(string functionName)
        {
            IRSession session     = GetLoadedPackagesInspectionSession();
            string    packageName = null;

            if (session != null && session.IsHostRunning)
            {
                try {
                    packageName = await session.EvaluateAsync <string>(
                        Invariant(
                            $"as.list(find('{functionName}', mode='function')[1])[[1]]"
                            ), REvaluationKind.Normal);

                    if (packageName != null && packageName.StartsWithOrdinal("package:"))
                    {
                        packageName = packageName.Substring(8);
                    }
                } catch (Exception) { }
            }

            return(packageName);
        }
Beispiel #23
0
        /// <summary>
        /// Computes the children of the object represented by the given expression, and returns a collection of
        /// evaluation objects describing each child.
        /// See <see cref="RSessionExtensions.TryEvaluateAndDescribeAsync"/> for the meaning of other parameters.
        /// </summary>
        /// <param name="maxCount">If not <see langword="null"/>, return at most that many children.</param>
        /// <remarks>
        /// <para>
        /// The resulting collection has an item for every child. If the child could be retrieved, and represents
        /// a value, the corresponding item is an <see cref="IRValueInfo"/> instance. If the child represents
        /// a promise, the promise is not forced, and the item is an <see cref="IRPromiseInfo"/> instance. If the
        /// child represents an active binding, the binding is not evaluated to retrieve the value, and the item is
        /// an <see cref="IRActiveBindingInfo"/> instance. If the child could not be retrieved, the item is an
        /// <see cref="IRErrorInfo"/> instance describing the error that prevented its retrieval.
        /// </para>
        /// <para>
        /// Where order matters (e.g. for children of atomic vectors and lists), children are returned in that order.
        /// Otherwise, the order is undefined. If an object has both ordered and unordered children (e.g. it is a vector
        /// with slots), then it is guaranteed that each group is reported as a contiguous sequence within the returned
        /// collection, and order is honored within each group; but groups themselves are not ordered relative to each other.
        /// </para>
        /// </remarks>
        /// <exception cref="RException">
        /// Raised if the operation fails as a whole (note that if only specific children cannot be retrieved, those
        /// children are represented by <see cref="IRErrorInfo"/> instances in the returned collection instead).
        /// </exception>
        public static async Task <IReadOnlyList <IREvaluationResultInfo> > DescribeChildrenAsync(
            this IRSession session,
            string environmentExpression,
            string expression,
            REvaluationResultProperties properties,
            string repr,
            int?maxCount = null,
            CancellationToken cancellationToken = default(CancellationToken)
            )
        {
            await TaskUtilities.SwitchToBackgroundThread();

            var call      = Invariant($"rtvs:::describe_children({expression.ToRStringLiteral()}, {environmentExpression}, {properties.ToRVector()}, {maxCount}, {repr})");
            var jChildren = await session.EvaluateAsync <JArray>(call, REvaluationKind.Normal, cancellationToken);

            Trace.Assert(
                jChildren.Children().All(t => t is JObject),
                Invariant($"rtvs:::describe_children(): object of objects expected.\n\n{jChildren}"));

            var children = new List <REvaluationResultInfo>();

            foreach (var child in jChildren)
            {
                var childObject = (JObject)child;
                Trace.Assert(
                    childObject.Count == 1,
                    Invariant($"rtvs:::describe_children(): each object is expected contain one object\n\n"));
                foreach (var kv in childObject)
                {
                    var name        = kv.Key;
                    var jEvalResult = (JObject)kv.Value;
                    var evalResult  = REvaluationResultInfo.Parse(session, environmentExpression, name, jEvalResult);
                    children.Add(evalResult);
                }
            }

            return(children);
        }
Beispiel #24
0
        public async Task InteractDuringBrowse()
        {
            var tracer = await _session.TraceExecutionAsync();

            using (var sf = new SourceFile("x <- 'old'; browser()")) {
                var browse = new TaskCompletionSource <bool>();
                tracer.Browse += (s, e) => {
                    browse.TrySetResult(true);
                };

                await sf.Source(_session);

                await browse.Task;

                using (var inter = await _session.BeginInteractionAsync()) {
                    await inter.RespondAsync("x <- 'new'\n");
                }

                var x = await _session.EvaluateAsync <string>("x", REvaluationKind.Normal);

                x.Should().Be("new");
            }
        }
Beispiel #25
0
        private static async Task CreateCsvAndStartProcess(
            IREvaluationResultInfo result,
            IRSession session,
            ICoreShell coreShell,
            string fileName,
            IFileSystem fileSystem,
            IProgress <ProgressDialogData> progress,
            CancellationToken cancellationToken)
        {
            await TaskUtilities.SwitchToBackgroundThread();

            var sep = CultureInfo.CurrentCulture.TextInfo.ListSeparator;
            var dec = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;

            try {
                var csvDataBlobId = await session.EvaluateAsync <ulong>($"rtvs:::export_to_csv({result.Expression}, sep={sep.ToRStringLiteral()}, dec={dec.ToRStringLiteral()})", REvaluationKind.Normal, cancellationToken);

                using (DataTransferSession dts = new DataTransferSession(session, fileSystem)) {
                    await dts.FetchAndDecompressFileAsync(csvDataBlobId, fileName, progress, Resources.Status_WritingCSV, cancellationToken);
                }
            } catch (RException) {
                await coreShell.ShowErrorMessageAsync(Resources.Error_CannotExportToCsv, cancellationToken);
            }
        }
Beispiel #26
0
 private static Task <int> GetRSessionProcessId(IRSession session)
 => session.EvaluateAsync <int>("Sys.getpid()", REvaluationKind.Normal);
Beispiel #27
0
 public static Task <string> GetFunctionCodeAsync(this IRSession session, string functionName)
 {
     return(session.EvaluateAsync <string>(Invariant($"paste0(deparse({functionName}), collapse='\n')"), REvaluationKind.Normal));
 }
Beispiel #28
0
 public static Task <string> GetFunctionCodeAsync(this IRSession session, string functionName, CancellationToken cancellationToken = default(CancellationToken))
 => session.EvaluateAsync <string>(Invariant($"paste0(deparse({functionName}), collapse='\n')"), REvaluationKind.Normal, cancellationToken);
Beispiel #29
0
        private static async Task CreateCsvAndStartProcess(
            IREvaluationResultInfo result, 
            IRSession session, 
            string fileName, 
            IFileSystem fileSystem, 
            IProgress<ProgressDialogData> progress,
            CancellationToken cancellationToken) {
            await TaskUtilities.SwitchToBackgroundThread();

            var sep = CultureInfo.CurrentCulture.TextInfo.ListSeparator;
            var dec = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;

            var csvDataBlobId = await session.EvaluateAsync<ulong>($"rtvs:::export_to_csv({result.Expression}, sep={sep.ToRStringLiteral()}, dec={dec.ToRStringLiteral()})", REvaluationKind.Normal, cancellationToken);
            using (DataTransferSession dts = new DataTransferSession(session, fileSystem)) {
                var total = await session.GetBlobSizeAsync(csvDataBlobId, cancellationToken);
                progress.Report(new ProgressDialogData(0, statusBarText: Resources.Status_WritingCSV, waitMessage: Resources.Status_WritingCSV));
                await dts.FetchAndDecompressFileAsync(new RBlobInfo(csvDataBlobId), fileName, true, new Progress<long>(b => {
                    var step = (int)(b * 100 / total);
                    progress.Report(new ProgressDialogData(step, statusBarText: Resources.Status_WritingCSV, waitMessage: Resources.Status_WritingCSV));
                }), cancellationToken);
                progress.Report(new ProgressDialogData(100, statusBarText: Resources.Status_WritingCSV, waitMessage: Resources.Status_WritingCSV));
            }
        }
Beispiel #30
0
        private async Task Environments(string script, params IREnvironment[] expectedEnvs)
        {
            // Detach all packages that can be detached before doing anything else. The only two that
            // cannot be detached are .GlobalEnv, which is the first in the list, and package:base,
            // which is the last. So, just keep detaching the 2nd item until the list only has 2 left.
            await _session.ExecuteAsync("while (length(search()) > 2) detach(2)");

            // Wait for prompt to appear.
            using (var eval = await _session.BeginInteractionAsync()) { }

            var envProvider = new REnvironmentProvider(_session);
            var envTcs      = new TaskCompletionSource <IREnvironment[]>();

            envProvider.Environments.CollectionChanged += (sender, args) => {
                envTcs.TrySetResult(envProvider.Environments.ToArray());
            };

            using (var inter = await _session.BeginInteractionAsync()) {
                inter.RespondAsync(script + "\n").DoNotWait();
            }

            // Wait until we hit the Browse> prompt.
            using (var inter = await _session.BeginInteractionAsync()) {
                inter.Contexts.IsBrowser().Should().BeTrue();
            }

            var actualEnvs = await envTcs.Task;

            actualEnvs.ShouldAllBeEquivalentTo(expectedEnvs, options => options
                                               .Including(env => env.Name)
                                               .Including(env => env.Kind)
                                               .WithStrictOrdering());

            // Validating EnvironmentExpression:
            // For environments that are on the search list, we can validate it by retrieving environment by name,
            // and verifying that it is indeed the same. format() generates comparable string values - it returns strings
            // that are unique for any given environment (using its name if it has one, and its memory address otherwise).
            // For all other environments, we validate by looking at a variable named 'tag' in that environment, and
            // comparing its value to the name of the function extracted from the call (i.e. environment name).
            var expectedObjects = new List <string>();
            var actualObjects   = new List <string>();

            foreach (var env in actualEnvs)
            {
                if (env == null)
                {
                    expectedObjects.Add(null);
                    actualObjects.Add(null);
                }
                else if (env.Kind == REnvironmentKind.Function)
                {
                    int tagEnd = env.Name.IndexOf("(");
                    tagEnd.Should().BePositive();
                    string tag = env.Name.Substring(0, tagEnd);

                    expectedObjects.Add(tag);
                    actualObjects.Add(await _session.EvaluateAsync <string>(
                                          $"({env.EnvironmentExpression})$tag",
                                          REvaluationKind.Normal));
                }
                else
                {
                    expectedObjects.Add(await _session.EvaluateAsync <string>(
                                            $"format(as.environment({env.Name.ToRStringLiteral()}))",
                                            REvaluationKind.Normal));
                    actualObjects.Add(await _session.EvaluateAsync <string>(
                                          $"format({env.EnvironmentExpression})",
                                          REvaluationKind.Normal));
                }
            }

            actualObjects.Should().Equal(expectedObjects);
        }
Beispiel #31
0
 private static Task<int> GetRSessionProcessId(IRSession session) 
     => session.EvaluateAsync<int>("Sys.getpid()", REvaluationKind.Normal);
Beispiel #32
0
        private async Task ExportToImageAsync(IRSession session, string format, string filePath, int widthInPixels,int heightInPixels, int resolution) {
            string script = String.Format(@"
device_id <- rtvs:::graphics.ide.getactivedeviceid()
rtvs:::export_to_image(device_id, rtvs:::graphics.ide.getactiveplotid(device_id), {0}, {1}, {2}, {3})
", format, widthInPixels, heightInPixels, resolution);
            var blobid = await session.EvaluateAsync<ulong>(script, REvaluationKind.Normal);

            using(DataTransferSession dts = new DataTransferSession(session, new FileSystem())) {
                await dts.FetchFileAsync(new RBlobInfo(blobid), filePath, true, null, CancellationToken.None);
            }
        }