Beispiel #1
0
        private void DoTaskInternal()
        {
            Debug.Assert(_taskDoneEvent != null);
            Action finalAction;

            if (!IsDisposed)
            {
                object result = null;

                try {
                    result = _taskAction();
                } catch (Exception ex) {
                    Debug.Fail(String.Format(CultureInfo.CurrentCulture,
                                             "Background task exception: {0}.\nInner exception: {1}\nInner exception callstack: {2}",
                                             ex.Message,
                                             ex.InnerException != null ? ex.InnerException.Message : "(none)",
                                             ex.InnerException != null ? ex.InnerException.StackTrace : "(none)"));

                    result = ex;
                } finally {
                    finalAction = () => UIThreadCompletedCallback(result);
                }
            }
            else
            {
                finalAction = () => UIThreadCanceledCallback(null);
            }

            _taskDoneEvent.Set();

            EditorShell.DispatchOnUIThread(finalAction);
        }
Beispiel #2
0
        private async Task InsertFunctionBraces(SnapshotPoint position, string name)
        {
            bool function = await IsFunction(name);

            if (function)
            {
                EditorShell.DispatchOnUIThread(() => {
                    if (TextView.TextBuffer.CurrentSnapshot.Version.VersionNumber == position.Snapshot.Version.VersionNumber)
                    {
                        TextView.TextBuffer.Insert(position.Position, "()");
                        TextView.Caret.MoveTo(new SnapshotPoint(TextView.TextBuffer.CurrentSnapshot, position.Position + 1));
                        EditorShell.DispatchOnUIThread(() => TriggerSignatureHelp());
                    }
                });
            }
        }
Beispiel #3
0
        protected void SubmitToInteractive(string command, CancellationToken cancellationToken)
        {
            var sessionProvider = EditorShell.Current.ExportProvider.GetExportedValue <IRSessionProvider>();
            var session         = sessionProvider.GetOrCreate(GuidList.InteractiveWindowRSessionGuid);

            if (session != null && session.IsHostRunning)
            {
                _runningAction = Task.Run(async() => {
                    try {
                        using (var eval = await session.BeginInteractionAsync(isVisible: true, cancellationToken: cancellationToken)) {
                            await eval.RespondAsync(command);
                        }
                    } finally {
                        EditorShell.DispatchOnUIThread(() => _runningAction = null);
                    }
                });

                _runningAction.SilenceException <OperationCanceledException>()
                .SilenceException <MessageTransportException>();
            }
        }
Beispiel #4
0
        /// <summary>
        /// Fetches help on the function from R asynchronously.
        /// When function data is obtained, parsed and the function
        /// index is updated, method invokes <see cref="infoReadyCallback"/>
        /// callback passing the specified parameter. Callback method can now
        /// fetch function information from the index.
        /// </summary>
        private static void GetFunctionInfoFromEngineAsync(string functionName, string packageName,
                                                           Action <object> infoReadyCallback = null, object parameter = null)
        {
            _functionRdDataProvider.GetFunctionRdData(
                functionName,
                packageName,
                (string rdData) => {
                IReadOnlyList <IFunctionInfo> functionInfos = GetFunctionInfosFromRd(rdData);
                foreach (IFunctionInfo info in functionInfos)
                {
                    _functionToInfoMap[info.Name] = info;
                }
                if (!_functionToInfoMap.ContainsKey(functionName))
                {
                    if (functionInfos.Count > 0)
                    {
                        // RD doesn't contain the requested function.
                        // e.g. as.Date.character has RD for as.Date but not itself
                        // without its own named info, this will request indefinitely many times
                        // as workaround, add the first info with functionName
                        _functionToInfoMap[functionName] = functionInfos[0];
                    }
                    else
                    {
                        // TODO: add some stub function info here to prevent subsequent calls for the same function as we already know the call will fail.
                    }
                }

                if (infoReadyCallback != null)
                {
                    EditorShell.DispatchOnUIThread(() => {
                        infoReadyCallback(parameter);
                    });
                }
            });
        }
Beispiel #5
0
        /// <summary>
        /// Main asyncronous task body
        /// </summary>
        void ProcessTextChanges(TextChange changeToProcess, bool async, Func <bool> isCancelledCallback)
        {
            lock (_disposeLock) {
                if (_editorTree == null || _disposed || isCancelledCallback())
                {
                    return;
                }

                EditorTreeChangeCollection treeChanges = null;
                // Cache id since it can change if task is canceled
                long taskId = TaskId;

                try {
                    AstRoot rootNode;

                    // We only need read lock since changes will be applied
                    // from the main thread
                    if (async)
                    {
                        rootNode = _editorTree.AcquireReadLock(_treeUserId);
                    }
                    else
                    {
                        rootNode = _editorTree.GetAstRootUnsafe();
                    }

                    treeChanges = new EditorTreeChangeCollection(changeToProcess.Version, changeToProcess.FullParseRequired);
                    TextChangeProcessor changeProcessor = new TextChangeProcessor(_editorTree, rootNode, isCancelledCallback);

                    bool fullParseRequired = changeToProcess.FullParseRequired;
                    if (fullParseRequired)
                    {
                        changeProcessor.FullParse(treeChanges, changeToProcess.NewTextProvider);
                    }
                    else
                    {
                        changeProcessor.ProcessChange(changeToProcess, treeChanges);
                    }
                } finally {
                    if (async && _editorTree != null)
                    {
                        _editorTree.ReleaseReadLock(_treeUserId);
                    }
                }

                // Lock should be released at this point since actual application
                // of tree changes is going to be happen from the main thread.

                if (!isCancelledCallback() && treeChanges != null)
                {
                    // Queue results for the main thread application. This must be done before
                    // signaling that the task is complete since if EnsureProcessingComplete
                    // is waiting it will want to apply changes itself rather than wait for
                    // the DispatchOnUIThread to go though and hence it will need all changes
                    // stored and ready for application.

                    _backgroundParsingResults.Enqueue(treeChanges);
                }

                // Signal task complete now so if main thread is waiting
                // it can proceed and appy the changes immediately.
                SignalTaskComplete(taskId);

                if (_backgroundParsingResults.Count > 0)
                {
                    _uiThreadTransitionRequestTime = DateTime.UtcNow;

                    // It is OK to post results while main thread might be working
                    // on them since if if it does, by the time posted request comes
                    // queue will already be empty.
                    if (async)
                    {
                        // Post request to apply tree changes to the main thread.
                        // This must NOT block or else task will never enter 'RanToCompletion' state.
                        EditorShell.DispatchOnUIThread(() => ApplyBackgroundProcessingResults());
                    }
                    else
                    {
                        // When processing is synchronous, apply changes and fire events right away.
                        ApplyBackgroundProcessingResults();
                    }
                }
            }
        }
Beispiel #6
0
        private static bool LoadIndex()
        {
            ConcurrentDictionary <string, string>        functionToPackageMap = new ConcurrentDictionary <string, string>();
            ConcurrentDictionary <string, IFunctionInfo> functionToInfoMap    = new ConcurrentDictionary <string, IFunctionInfo>();
            ConcurrentDictionary <string, BlockingCollection <INamedItemInfo> > packageToFunctionsMap = new ConcurrentDictionary <string, BlockingCollection <INamedItemInfo> >();
            bool loaded = false;

            // ~/Documents/R/RTVS/FunctionsIndex.dx -> function to package map, also contains function description
            // ~/Documents/R/RTVS/[PackageName]/[FunctionName].sig -> function signatures

            // Function index format:
            //      Each line is a triplet of function name followed
            //      by the package name followed by the function description
            //      There are no tabs in the function description.

            try
            {
                if (File.Exists(IndexFilePath))
                {
                    using (StreamReader sr = new StreamReader(IndexFilePath))
                    {
                        char[] separator = new char[] { '\t' };

                        while (true)
                        {
                            string line = sr.ReadLine();
                            if (line == null)
                            {
                                break;
                            }

                            string[] parts = line.Split(separator, StringSplitOptions.RemoveEmptyEntries);
                            if (parts.Length == 3)
                            {
                                string functionName        = parts[0];
                                string packageName         = parts[1];
                                string functionDescription = parts[2];

                                if (functionName == "completed" && packageName == "completed" && functionDescription == "completed")
                                {
                                    loaded = true;
                                    break;
                                }

                                functionToPackageMap[functionName] = packageName;

                                BlockingCollection <INamedItemInfo> functions;
                                if (!packageToFunctionsMap.TryGetValue(packageName, out functions))
                                {
                                    functions = new BlockingCollection <INamedItemInfo>();
                                    packageToFunctionsMap[packageName] = functions;
                                }

                                functions.Add(new NamedItemInfo(functionName, functionDescription));
                            }
                        }
                    }
                }
            }
            catch (IOException) { }

            if (!loaded)
            {
                return(false);
            }

            if (LoadFunctions(functionToPackageMap))
            {
                EditorShell.DispatchOnUIThread(() =>
                {
                    _functionToPackageMap  = functionToPackageMap;
                    _packageToFunctionsMap = packageToFunctionsMap;
                    _functionToInfoMap     = functionToInfoMap;
                });
            }

            return(loaded);
        }