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()); } }
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)); } }
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); } } } }
/// <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()); } }
public void Invoke(IUIThreadOperationContext context) { using var scope = context.AddScope(allowCancellation: true, CodeAction.Message); this.Invoke( new UIThreadOperationContextProgressTracker(scope), context.UserCancellationToken ); }
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);