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); } } } }
public CodeCleanUpExecutionContext(IUIThreadOperationContext operationContext, FixIdContainer EnabledFixIds) { Requires.NotNull(operationContext, nameof(operationContext)); Requires.NotNull(EnabledFixIds, nameof(EnabledFixIds)); this.OperationContext = operationContext; this.EnabledFixIds = EnabledFixIds; }
/// <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 ); }
public void Invoke(IUIThreadOperationContext context) { // we're going to return immediately from Invoke and kick off our own async work to invoke the // code action. Once this returns, the editor will close the threaded wait dialog it created. // So we need to take ownership of it and start our own TWD instead to track this. context.TakeOwnership(); _ = InvokeAsync(); }
/// <summary> /// Get <see cref="Document"/> from <see cref="Text.Extensions.GetOpenDocumentInCurrentContextWithChanges(ITextSnapshot)"/> /// once <see cref="IWorkspaceStatusService.WaitUntilFullyLoadedAsync(CancellationToken)"/> returns /// </summary> public static Document?GetFullyLoadedOpenDocumentInCurrentContextWithChanges( this ITextSnapshot snapshot, IUIThreadOperationContext operationContext, IThreadingContext threadingContext) { // make sure this is only called from UI thread threadingContext.ThrowIfNotOnUIThread(); return(threadingContext.JoinableTaskFactory.Run(() => snapshot.GetFullyLoadedOpenDocumentInCurrentContextWithChangesAsync(operationContext))); }
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 async Task AugumentPeekSessionAsync( IList <IPeekableItem> peekableItems, IUIThreadOperationContext context, SnapshotPoint triggerPoint, Document document) { var cancellationToken = context.UserCancellationToken; var services = document.Project.Solution.Workspace.Services; if (!document.SupportsSemanticModel) { // For documents without semantic models, just try to use the goto-def service // as a reasonable place to peek at. var goToDefinitionService = document.GetLanguageService <IGoToDefinitionService>(); if (goToDefinitionService == null) { return; } var navigableItems = await goToDefinitionService.FindDefinitionsAsync(document, triggerPoint.Position, cancellationToken).ConfigureAwait(false); await foreach (var item in GetPeekableItemsForNavigableItemsAsync( navigableItems, document.Project, _peekResultFactory, cancellationToken).ConfigureAwait(false)) { peekableItems.Add(item); } } else { var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var semanticInfo = await SymbolFinder.GetSemanticInfoAtPositionAsync( semanticModel, triggerPoint.Position, services, cancellationToken).ConfigureAwait(false); var symbol = semanticInfo.GetAnySymbol(includeType: true); if (symbol == null) { return; } symbol = symbol.GetOriginalUnreducedDefinition(); // Get the symbol back from the originating workspace var symbolMappingService = services.GetRequiredService <ISymbolMappingService>(); var mappingResult = await symbolMappingService.MapSymbolAsync(document, symbol, cancellationToken).ConfigureAwait(false); mappingResult ??= new SymbolMappingResult(document.Project, symbol); peekableItems.AddRange(await _peekableItemFactory.GetPeekableItemsAsync( mappingResult.Symbol, mappingResult.Project, _peekResultFactory, cancellationToken).ConfigureAwait(false)); } }
private static void ShowError(ChangeSignatureFailureKind reason, IUIThreadOperationContext operationContext, INotificationService notificationService) { switch (reason) { case ChangeSignatureFailureKind.DefinedInMetadata: ShowMessage(FeaturesResources.The_member_is_defined_in_metadata, NotificationSeverity.Error, operationContext, notificationService); break; case ChangeSignatureFailureKind.IncorrectKind: ShowMessage(FeaturesResources.You_can_only_change_the_signature_of_a_constructor_indexer_method_or_delegate, NotificationSeverity.Error, operationContext, notificationService); break; }
private void Organize(ITextBuffer subjectBuffer, IUIThreadOperationContext operationContext) { var cancellationToken = operationContext.UserCancellationToken; var document = subjectBuffer.CurrentSnapshot.GetFullyLoadedOpenDocumentInCurrentContextWithChangesAsync(operationContext).WaitAndGetResult(cancellationToken); if (document != null) { var newDocument = OrganizingService.OrganizeAsync(document, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken); if (document != newDocument) { ApplyTextChange(document, newDocument); } } }
private void SortImports(ITextBuffer subjectBuffer, IUIThreadOperationContext operationContext) { var cancellationToken = operationContext.UserCancellationToken; var document = subjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document != null) { var newDocument = Formatter.OrganizeImportsAsync(document, cancellationToken).WaitAndGetResult(cancellationToken); if (document != newDocument) { ApplyTextChange(document, newDocument); } } }
private void SortAndRemoveUnusedImports(ITextBuffer subjectBuffer, IUIThreadOperationContext operationContext) { var cancellationToken = operationContext.UserCancellationToken; var document = subjectBuffer.CurrentSnapshot.GetFullyLoadedOpenDocumentInCurrentContextWithChangesAsync(operationContext).WaitAndGetResult(cancellationToken); if (document != null) { var newDocument = document.GetLanguageService <IRemoveUnnecessaryImportsService>().RemoveUnnecessaryImportsAsync(document, cancellationToken).WaitAndGetResult(cancellationToken); newDocument = OrganizeImportsService.OrganizeImportsAsync(newDocument, cancellationToken).WaitAndGetResult(cancellationToken); if (document != newDocument) { ApplyTextChange(document, newDocument); } } }
private void SortImports(ITextBuffer subjectBuffer, IUIThreadOperationContext operationContext) { var cancellationToken = operationContext.UserCancellationToken; var document = subjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document != null) { var organizeImportsService = document.GetRequiredLanguageService <IOrganizeImportsService>(); var options = document.GetOrganizeImportsOptionsAsync(_globalOptions, cancellationToken).AsTask().WaitAndGetResult(cancellationToken); var newDocument = organizeImportsService.OrganizeImportsAsync(document, options, cancellationToken).WaitAndGetResult(cancellationToken); if (document != newDocument) { ApplyTextChange(document, newDocument); } } }
private void SortAndRemoveUnusedImports(ITextBuffer subjectBuffer, IUIThreadOperationContext operationContext) { var cancellationToken = operationContext.UserCancellationToken; var document = subjectBuffer.CurrentSnapshot.GetFullyLoadedOpenDocumentInCurrentContextWithChanges( operationContext, _threadingContext); if (document != null) { var formattingOptions = document.SupportsSyntaxTree ? document.GetSyntaxFormattingOptionsAsync(_globalOptions, cancellationToken).AsTask().WaitAndGetResult(cancellationToken) : null; var newDocument = document.GetLanguageService <IRemoveUnnecessaryImportsService>().RemoveUnnecessaryImportsAsync(document, formattingOptions, cancellationToken).WaitAndGetResult(cancellationToken); newDocument = Formatter.OrganizeImportsAsync(newDocument, cancellationToken).WaitAndGetResult(cancellationToken); if (document != newDocument) { ApplyTextChange(document, newDocument); } } }
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(); } }
private void ApplyRename(Solution newSolution, IUIThreadOperationContext operationContext) { var changes = _baseSolution.GetChanges(newSolution); var changedDocumentIDs = changes.GetProjectChanges().SelectMany(c => c.GetChangedDocuments()).ToList(); if (!_renameInfo.TryOnBeforeGlobalSymbolRenamed(_workspace, changedDocumentIDs, this.ReplacementText)) { var notificationService = _workspace.Services.GetService <INotificationService>(); notificationService.SendNotification( EditorFeaturesResources.Rename_operation_was_cancelled_or_is_not_valid, EditorFeaturesResources.Rename_Symbol, NotificationSeverity.Error); return; } using var undoTransaction = _workspace.OpenGlobalUndoTransaction(EditorFeaturesResources.Inline_Rename); var finalSolution = newSolution.Workspace.CurrentSolution; foreach (var id in changedDocumentIDs) { // If the document supports syntax tree, then create the new solution from the // updated syntax root. This should ensure that annotations are preserved, and // prevents the solution from having to reparse documents when we already have // the trees for them. If we don't support syntax, then just use the text of // the document. var newDocument = newSolution.GetDocument(id); if (newDocument.SupportsSyntaxTree) { // We pass CancellationToken.None here because we don't have a usable token to pass. The IUIThreadOperationContext // passed here as a cancellation token, but the caller in CommitCore has already turned off cancellation // because we're committed to the update at this point. If we ever want to pass cancellation here, we'd want to move this // part back out of this method and before the point where we've already opened a global transaction. var root = newDocument.GetSyntaxRootSynchronously(CancellationToken.None); finalSolution = finalSolution.WithDocumentSyntaxRoot(id, root); } else { var newText = newDocument.GetTextSynchronously(CancellationToken.None); finalSolution = finalSolution.WithDocumentText(id, newText); } // Make sure to include any document rename as well finalSolution = finalSolution.WithDocumentName(id, newDocument.Name); } if (_workspace.TryApplyChanges(finalSolution)) { // Since rename can apply file changes as well, and those file // changes can generate new document ids, include added documents // as well as changed documents. This also ensures that any document // that was removed is not included var finalChanges = _workspace.CurrentSolution.GetChanges(_baseSolution); var finalChangedIds = finalChanges .GetProjectChanges() .SelectMany(c => c.GetChangedDocuments().Concat(c.GetAddedDocuments())) .ToList(); if (!_renameInfo.TryOnAfterGlobalSymbolRenamed(_workspace, finalChangedIds, this.ReplacementText)) { var notificationService = _workspace.Services.GetService <INotificationService>(); operationContext.TakeOwnership(); notificationService.SendNotification( EditorFeaturesResources.Rename_operation_was_not_properly_completed_Some_file_might_not_have_been_updated, EditorFeaturesResources.Rename_Symbol, NotificationSeverity.Information); } undoTransaction.Commit(); } }
public DefaultBackgroundWorkIndicatorContext(IUIThreadOperationContext context) { _context = context; }
/// <returns> /// True: if a failure notification was displayed or the user did not want to proceed in a best effort scenario. /// Extract Method does not proceed further and is done. /// False: the user proceeded to a best effort scenario. /// </returns> private bool TryNotifyFailureToUser(Document document, ExtractMethodResult result, IUIThreadOperationContext waitContext) { // We are about to show a modal UI dialog so we should take over the command execution // wait context. That means the command system won't attempt to show its own wait dialog // and also will take it into consideration when measuring command handling duration. waitContext.TakeOwnership(); var project = document.Project; var solution = project.Solution; var notificationService = solution.Workspace.Services.GetService <INotificationService>(); // see whether we will allow best effort extraction and if it is possible. if (!solution.Options.GetOption(ExtractMethodOptions.AllowBestEffort, project.Language) || !result.Status.HasBestEffort() || result.Document == null) { if (notificationService != null) { notificationService.SendNotification( EditorFeaturesResources.Extract_method_encountered_the_following_issues + Environment.NewLine + string.Join("", result.Reasons.Select(r => Environment.NewLine + " " + r)), title: EditorFeaturesResources.Extract_Method, severity: NotificationSeverity.Error); } return(true); } // okay, best effort is turned on, let user know it is an best effort if (notificationService != null) { if (!notificationService.ConfirmMessageBox( EditorFeaturesResources.Extract_method_encountered_the_following_issues + Environment.NewLine + string.Join("", result.Reasons.Select(r => Environment.NewLine + " " + r)) + Environment.NewLine + Environment.NewLine + EditorFeaturesResources.Do_you_still_want_to_proceed_This_may_produce_broken_code, title: EditorFeaturesResources.Extract_Method, severity: NotificationSeverity.Warning)) { return(true); } } return(false); }
private bool Execute( ITextBuffer textBuffer, ITextView view, IUIThreadOperationContext waitContext) { var cancellationToken = waitContext.UserCancellationToken; var spans = view.Selection.GetSnapshotSpansOnBuffer(textBuffer); if (spans.Count(s => s.Length > 0) != 1) { return(false); } var document = textBuffer.CurrentSnapshot.GetFullyLoadedOpenDocumentInCurrentContextWithChangesAsync(waitContext).WaitAndGetResult(cancellationToken); if (document == null) { return(false); } var result = ExtractMethodService.ExtractMethodAsync( document, spans.Single().Span.ToTextSpan(), cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken); Contract.ThrowIfNull(result); if (!result.Succeeded && !result.SucceededWithSuggestion) { // if it failed due to out/ref parameter in async method, try it with different option var newResult = TryWithoutMakingValueTypesRef(document, spans, result, cancellationToken); if (newResult != null) { var notificationService = document.Project.Solution.Workspace.Services.GetService <INotificationService>(); if (notificationService != null) { // We are about to show a modal UI dialog so we should take over the command execution // wait context. That means the command system won't attempt to show its own wait dialog // and also will take it into consideration when measuring command handling duration. waitContext.TakeOwnership(); if (!notificationService.ConfirmMessageBox( EditorFeaturesResources.Extract_method_encountered_the_following_issues + Environment.NewLine + Environment.NewLine + string.Join(Environment.NewLine, result.Reasons) + Environment.NewLine + Environment.NewLine + EditorFeaturesResources.We_can_fix_the_error_by_not_making_struct_out_ref_parameter_s_Do_you_want_to_proceed, title: EditorFeaturesResources.Extract_Method, severity: NotificationSeverity.Error)) { // We handled the command, displayed a notification and did not produce code. return(true); } } // reset result result = newResult; } else if (TryNotifyFailureToUser(document, result, waitContext)) { // We handled the command, displayed a notification and did not produce code. return(true); } } // apply the change to buffer // get method name token ApplyChangesToBuffer(result, textBuffer, cancellationToken); // start inline rename var methodNameAtInvocation = result.InvocationNameToken; var snapshotAfterFormatting = textBuffer.CurrentSnapshot; var documentAfterFormatting = snapshotAfterFormatting.GetOpenDocumentInCurrentContextWithChanges(); _renameService.StartInlineSession(documentAfterFormatting, methodNameAtInvocation.Span, cancellationToken); // select invocation span view.TryMoveCaretToAndEnsureVisible(new SnapshotPoint(snapshotAfterFormatting, methodNameAtInvocation.Span.End)); view.SetSelection( methodNameAtInvocation.Span.ToSnapshotSpan(snapshotAfterFormatting)); return(true); }
static void ShowMessage(string errorMessage, NotificationSeverity severity, IUIThreadOperationContext operationContext, INotificationService notificationService) { operationContext.TakeOwnership(); notificationService.SendNotification(errorMessage, severity: severity); }
public VSTypeScriptWaitContextWrapper(IUIThreadOperationContext context) => _context = context;
/// <summary> /// Creates new instance of the <see cref="CommandExecutionContext"/>. /// </summary> public CommandExecutionContext(IUIThreadOperationContext operationContext) { this.OperationContext = operationContext ?? throw new ArgumentNullException(nameof(operationContext)); }
/// <summary> /// Creates new instance of the <see cref="CommandExecutionContext"/>. /// </summary> public CommandExecutionContext(IUIThreadOperationContext operationContext) { this.OperationContext = operationContext ?? throw new ArgumentNullException(nameof(operationContext)); this.Properties = new PropertyCollection(); }