Esempio n. 1
0
            public IEnumerable <SuggestedActionSet>?GetSuggestedActions(
                ISuggestedActionCategorySet requestedActionCategories,
                SnapshotSpan range,
                IUIThreadOperationContext?operationContext,
                CancellationToken cancellationToken)
            {
                AssertIsForeground();

                if (IsDisposed)
                {
                    return(null);
                }

                if (_workspaceStatusService != null)
                {
                    using (operationContext?.AddScope(allowCancellation: true, description: EditorFeaturesWpfResources.Gathering_Suggestions_Waiting_for_the_solution_to_fully_load))
                    {
                        // This needs to run under threading context otherwise, we can deadlock on VS
                        ThreadingContext.JoinableTaskFactory.Run(() => _workspaceStatusService.WaitUntilFullyLoadedAsync(cancellationToken));
                    }
                }

                using (Logger.LogBlock(FunctionId.SuggestedActions_GetSuggestedActions, cancellationToken))
                {
                    var document = range.Snapshot.GetOpenDocumentInCurrentContextWithChanges();
                    if (document == null)
                    {
                        // this is here to fail test and see why it is failed.
                        Trace.WriteLine("given range is not current");
                        return(null);
                    }

                    var workspace = document.Project.Solution.Workspace;
                    var supportsFeatureService = workspace.Services.GetRequiredService <ITextBufferSupportsFeatureService>();

                    var selectionOpt = TryGetCodeRefactoringSelection(range);

                    Func <string, IDisposable?> addOperationScope =
                        description => operationContext?.AddScope(allowCancellation: true, string.Format(EditorFeaturesWpfResources.Gathering_Suggestions_0, description));

                    // We convert the code fixes and refactorings to UnifiedSuggestedActionSets instead of
                    // SuggestedActionSets so that we can share logic between local Roslyn and LSP.
                    var fixes = GetCodeFixes(
                        supportsFeatureService, requestedActionCategories, workspace,
                        document, range, addOperationScope, cancellationToken);
                    var refactorings = GetRefactorings(
                        supportsFeatureService, requestedActionCategories, workspace,
                        document, selectionOpt, addOperationScope, cancellationToken);

                    var filteredSets = UnifiedSuggestedActionsSource.FilterAndOrderActionSets(fixes, refactorings, selectionOpt);
                    if (!filteredSets.HasValue)
                    {
                        return(null);
                    }

                    return(filteredSets.Value.Select(s => ConvertToSuggestedActionSet(s)).WhereNotNull());
                }
            }
Esempio n. 2
0
            public IEnumerable <SuggestedActionSet>?GetSuggestedActions(
                ISuggestedActionCategorySet requestedActionCategories,
                SnapshotSpan range,
                IUIThreadOperationContext?operationContext,
                CancellationToken cancellationToken)
            {
                AssertIsForeground();

                using var state = _state.TryAddReference();
                if (state is null)
                {
                    return(null);
                }

                if (state.Target.Workspace == null)
                {
                    return(null);
                }

                using (operationContext?.AddScope(allowCancellation: true, description: EditorFeaturesResources.Gathering_Suggestions_Waiting_for_the_solution_to_fully_load))
                {
                    // This needs to run under threading context otherwise, we can deadlock on VS
                    var statusService = state.Target.Workspace.Services.GetRequiredService <IWorkspaceStatusService>();
                    ThreadingContext.JoinableTaskFactory.Run(() => statusService.WaitUntilFullyLoadedAsync(cancellationToken));
                }

                using (Logger.LogBlock(FunctionId.SuggestedActions_GetSuggestedActions, cancellationToken))
                {
                    var document = range.Snapshot.GetOpenDocumentInCurrentContextWithChanges();
                    if (document == null)
                    {
                        // this is here to fail test and see why it is failed.
                        Trace.WriteLine("given range is not current");
                        return(null);
                    }

                    var workspace = document.Project.Solution.Workspace;
                    var supportsFeatureService = workspace.Services.GetRequiredService <ITextBufferSupportsFeatureService>();

                    var selection = TryGetCodeRefactoringSelection(state, range);

                    Func <string, IDisposable?> addOperationScope =
                        description => operationContext?.AddScope(allowCancellation: true, string.Format(EditorFeaturesResources.Gathering_Suggestions_0, description));

                    // We convert the code fixes and refactorings to UnifiedSuggestedActionSets instead of
                    // SuggestedActionSets so that we can share logic between local Roslyn and LSP.
                    var fixes = GetCodeFixesAsync(
                        state, supportsFeatureService, requestedActionCategories, workspace, document, range,
                        addOperationScope, CodeActionRequestPriority.None, isBlocking: true, cancellationToken).WaitAndGetResult(cancellationToken);
                    var refactorings = GetRefactoringsAsync(
                        state, supportsFeatureService, requestedActionCategories, GlobalOptions, workspace, document, selection,
                        addOperationScope, CodeActionRequestPriority.None, isBlocking: true, cancellationToken).WaitAndGetResult(cancellationToken);

                    return(ConvertToSuggestedActionSets(state, selection, fixes, refactorings));
                }
            }
Esempio n. 3
0
        private void CommitCore(IUIThreadOperationContext operationContext, bool previewChanges)
        {
            var eventName = previewChanges ? FunctionId.Rename_CommitCoreWithPreview : FunctionId.Rename_CommitCore;

            using (Logger.LogBlock(eventName, KeyValueLogMessage.Create(LogType.UserAction), operationContext.UserCancellationToken))
            {
                var newSolution = _conflictResolutionTask.Join(operationContext.UserCancellationToken).NewSolution;

                if (previewChanges)
                {
                    var previewService = _workspace.Services.GetService <IPreviewDialogService>();

                    operationContext.TakeOwnership();
                    newSolution = previewService.PreviewChanges(
                        string.Format(EditorFeaturesResources.Preview_Changes_0, EditorFeaturesResources.Rename),
                        "vs.csharp.refactoring.rename",
                        string.Format(EditorFeaturesResources.Rename_0_to_1_colon, this.OriginalSymbolName, this.ReplacementText),
                        _renameInfo.FullDisplayName,
                        _renameInfo.Glyph,
                        newSolution,
                        _triggerDocument.Project.Solution);

                    if (newSolution == null)
                    {
                        // User clicked cancel.
                        return;
                    }
                }

                // The user hasn't cancelled by now, so we're done waiting for them. Off to
                // rename!
                using var _ = operationContext.AddScope(allowCancellation: false, EditorFeaturesResources.Updating_files);

                Dismiss(rollbackTemporaryEdits: true);
                CancelAllOpenDocumentTrackingTasks();

                _triggerView.Caret.PositionChanged += LogPositionChanged;

                ApplyRename(newSolution, operationContext);

                LogRenameSession(RenameLogMessage.UserActionOutcome.Committed, previewChanges);

                EndRenameSession();

                _triggerView.Caret.PositionChanged -= LogPositionChanged;

                void LogPositionChanged(object sender, CaretPositionChangedEventArgs e)
                {
                    try
                    {
                        throw new InvalidOperationException("Caret position changed during application of rename");
                    }
                    catch (InvalidOperationException ex) when(FatalError.ReportAndCatch(ex))
                    {
                        // Unreachable code due to ReportAndCatch
                        Contract.ThrowIfTrue(true);
                    }
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Get <see cref="Document"/> from <see cref="Text.Extensions.GetOpenDocumentInCurrentContextWithChanges(ITextSnapshot)"/>
        /// once <see cref="IWorkspaceStatusService.WaitUntilFullyLoadedAsync(CancellationToken)"/> returns
        /// </summary>
        public static async Task <Document> GetFullyLoadedOpenDocumentInCurrentContextWithChangesAsync(
            this ITextSnapshot snapshot, IUIThreadOperationContext operationContext)
        {
            // just get a document from whatever we have
            var document = snapshot.TextBuffer.AsTextContainer().GetOpenDocumentInCurrentContext();

            if (document == null)
            {
                // we don't know about this buffer yet
                return(null);
            }

            var description = string.Format(EditorFeaturesResources.Operation_is_not_ready_for_0_yet_see_task_center_for_more_detail, document.Name);

            // partial mode is always cancellable
            using (operationContext.AddScope(allowCancellation: true, description))
            {
                var service = document.Project.Solution.Workspace.Services.GetService <IWorkspaceStatusService>();
                if (service != null)
                {
                    // TODO: decide for prototype, we don't do anything complex and just ask workspace whether it is fully loaded
                    // later we might need to go and change all these with more specific info such as document/project/solution
                    await service.WaitUntilFullyLoadedAsync(operationContext.UserCancellationToken).ConfigureAwait(false);
                }

                // get proper document
                return(snapshot.GetOpenDocumentInCurrentContextWithChanges());
            }
        }
Esempio n. 5
0
 public void Invoke(IUIThreadOperationContext context)
 {
     using var scope = context.AddScope(allowCancellation: true, CodeAction.Message);
     this.Invoke(
         new UIThreadOperationContextProgressTracker(scope),
         context.UserCancellationToken
         );
 }
Esempio n. 6
0
        private async Task ResetInteractiveAsync(
            IInteractiveWindow interactiveWindow,
            ImmutableArray <string> referencePaths,
            ImmutableArray <string> referenceSearchPaths,
            ImmutableArray <string> sourceSearchPaths,
            ImmutableArray <string> projectNamespaces,
            string projectDirectory,
            InteractiveHostPlatform?platform,
            IUIThreadOperationContext uiThreadOperationContext)
        {
            // First, open the repl window.
            var evaluator = (IResettableInteractiveEvaluator)interactiveWindow.Evaluator;

            // If the user hits the cancel button on the wait indicator, then we want to stop the
            // build.
            using (uiThreadOperationContext.UserCancellationToken.Register(() =>
                                                                           CancelBuildProject(), useSynchronizationContext: true))
            {
                // First, start a build.
                // If the build fails do not reset the REPL.
                var builtSuccessfully = await BuildProjectAsync().ConfigureAwait(true);

                if (!builtSuccessfully)
                {
                    return;
                }
            }

            // Then reset the REPL
            using var scope        = uiThreadOperationContext.AddScope(allowCancellation: true, EditorFeaturesWpfResources.Resetting_Interactive);
            evaluator.ResetOptions = new InteractiveEvaluatorResetOptions(platform);
            await interactiveWindow.Operations.ResetAsync(initialize : true).ConfigureAwait(true);

            // TODO: load context from an rsp file.

            // Now send the reference paths we've collected to the repl.
            await evaluator.SetPathsAsync(referenceSearchPaths, sourceSearchPaths, projectDirectory).ConfigureAwait(true);

            var editorOptions           = _editorOptionsFactoryService.GetOptions(interactiveWindow.CurrentLanguageBuffer);
            var importReferencesCommand = referencePaths.Select(_createReference);
            await interactiveWindow.SubmitAsync(importReferencesCommand).ConfigureAwait(true);

            // Project's default namespace might be different from namespace used within project.
            // Filter out namespace imports that do not exist in interactive compilation.
            var namespacesToImport = await GetNamespacesToImportAsync(projectNamespaces, interactiveWindow).ConfigureAwait(true);

            var importNamespacesCommand = namespacesToImport.Select(_createImport).Join(editorOptions.GetNewLineCharacter());

            if (!string.IsNullOrWhiteSpace(importNamespacesCommand))
            {
                await interactiveWindow.SubmitAsync(new[] { importNamespacesCommand }).ConfigureAwait(true);
            }
        }
        private void CommitCore(IUIThreadOperationContext operationContext, bool previewChanges)
        {
            var eventName = previewChanges ? FunctionId.Rename_CommitCoreWithPreview : FunctionId.Rename_CommitCore;

            using (Logger.LogBlock(eventName, KeyValueLogMessage.Create(LogType.UserAction), operationContext.UserCancellationToken))
            {
                var newSolution = _conflictResolutionTask.Join(operationContext.UserCancellationToken).NewSolution;

                if (previewChanges)
                {
                    var previewService = _workspace.Services.GetService <IPreviewDialogService>();

                    operationContext.TakeOwnership();
                    newSolution = previewService.PreviewChanges(
                        string.Format(EditorFeaturesResources.Preview_Changes_0, EditorFeaturesResources.Rename),
                        "vs.csharp.refactoring.rename",
                        string.Format(EditorFeaturesResources.Rename_0_to_1_colon, this.OriginalSymbolName, this.ReplacementText),
                        _renameInfo.FullDisplayName,
                        _renameInfo.Glyph,
                        newSolution,
                        _triggerDocument.Project.Solution);

                    if (newSolution == null)
                    {
                        // User clicked cancel.
                        return;
                    }
                }

                // The user hasn't cancelled by now, so we're done waiting for them. Off to
                // rename!
                using var _ = operationContext.AddScope(allowCancellation: false, EditorFeaturesResources.Updating_files);

                Dismiss(rollbackTemporaryEdits: true);
                CancelAllOpenDocumentTrackingTasks();

                ApplyRename(newSolution, operationContext);

                LogRenameSession(RenameLogMessage.UserActionOutcome.Committed, previewChanges);

                EndRenameSession();
            }
        }
 public IUIThreadOperationScope AddScope(bool allowCancellation, string description)
 => _context.AddScope(allowCancellation, description);