public int GetNameOfLocation(IVsTextBuffer pBuffer, int iLine, int iCol, out string?pbstrName, out int piLineOffset) { using (Logger.LogBlock(FunctionId.Debugging_VsLanguageDebugInfo_GetNameOfLocation, CancellationToken.None)) { string?name = null; var lineOffset = 0; if (_languageDebugInfo != null) { _uiThreadOperationExecutor.Execute( title: ServicesVSResources.Debugger, defaultDescription: ServicesVSResources.Determining_breakpoint_location, allowCancellation: true, showProgress: false, action: waitContext => { var cancellationToken = waitContext.UserCancellationToken; var textBuffer = _languageService.EditorAdaptersFactoryService.GetDataBuffer(pBuffer); if (textBuffer != null) { var nullablePoint = textBuffer.CurrentSnapshot.TryGetPoint(iLine, iCol); if (nullablePoint.HasValue) { var point = nullablePoint.Value; var document = point.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document != null) { // NOTE(cyrusn): We have to wait here because the debuggers' // GetNameOfLocation is a blocking call. In the future, it // would be nice if they could make it async. var debugLocationInfo = _languageDebugInfo.GetLocationInfoAsync(document, point, cancellationToken).WaitAndGetResult(cancellationToken); if (!debugLocationInfo.IsDefault) { name = debugLocationInfo.Name; lineOffset = debugLocationInfo.LineOffset; } } } } }); if (name != null) { pbstrName = name; piLineOffset = lineOffset; return(VSConstants.S_OK); } } // Note(DustinCa): Docs say that GetNameOfLocation should return S_FALSE if a name could not be found. // Also, that's what the old native code does, so we should do it here. pbstrName = null; piLineOffset = 0; return(VSConstants.S_FALSE); } }
private void OnRemoveUnusedReferencesForSelectedProject(object sender, EventArgs args) { if (VisualStudioCommandHandlerHelpers.TryGetSelectedProjectHierarchy(_serviceProvider, out var hierarchy)) { Project?project = null; ImmutableArray <ReferenceUpdate> referenceUpdates = default; var status = _threadOperationExecutor.Execute(ServicesVSResources.Remove_Unused_References, ServicesVSResources.Analyzing_project_references, allowCancellation: true, showProgress: true, (operationContext) => { (project, referenceUpdates) = GetUnusedReferencesForProjectHierarchy(hierarchy, operationContext.UserCancellationToken); }); if (status == UIThreadOperationStatus.Canceled) { return; } if (project is null || referenceUpdates.IsEmpty) { MessageDialog.Show(ServicesVSResources.Remove_Unused_References, ServicesVSResources.No_unused_references_were_found, MessageDialogCommandSet.Ok); return; } var dialog = _unusedReferenceDialogProvider.CreateDialog(); if (dialog.ShowModal(project, referenceUpdates) == false) { return; } // If we are removing, then that is a change or if we are newly marking a reference as TreatAsUsed, // then that is a change. var referenceChanges = referenceUpdates .Where(update => update.Action != UpdateAction.TreatAsUsed || !update.ReferenceInfo.TreatAsUsed) .ToImmutableArray(); // If there are no changes, then we can return if (referenceChanges.IsEmpty) { return; } // Since undo/redo is not supported, get confirmation that we should apply these changes. var result = MessageDialog.Show(ServicesVSResources.Remove_Unused_References, ServicesVSResources.This_action_cannot_be_undone_Do_you_wish_to_continue, MessageDialogCommandSet.YesNo); if (result == MessageDialogCommand.No) { return; } _threadOperationExecutor.Execute(ServicesVSResources.Remove_Unused_References, ServicesVSResources.Updating_project_references, allowCancellation: false, showProgress: true, (operationContext) => { ApplyUnusedReferenceUpdates(project, referenceChanges, CancellationToken.None); }); } return; }
public void AugmentPeekSession(IPeekSession session, IList <IPeekableItem> peekableItems) { if (!string.Equals(session.RelationshipName, PredefinedPeekRelationships.Definitions.Name, StringComparison.OrdinalIgnoreCase)) { return; } var triggerPoint = session.GetTriggerPoint(_textBuffer.CurrentSnapshot); if (!triggerPoint.HasValue) { return; } var document = triggerPoint.Value.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { return; } _uiThreadOperationExecutor.Execute(EditorFeaturesResources.Peek, EditorFeaturesResources.Loading_Peek_information, allowCancellation: true, showProgress: false, action: context => { _threadingContext.JoinableTaskFactory.Run(() => AugumentPeekSessionAsync(peekableItems, context, triggerPoint.Value, document)); }); }
private void SyncNamespaces(ImmutableArray <Project> projects) { if (projects.IsEmpty) { return; } var syncService = projects[0].GetRequiredLanguageService <ISyncNamespacesService>(); Solution?solution = null; var status = _threadOperationExecutor.Execute(ServicesVSResources.Sync_Namespaces, ServicesVSResources.Updating_namspaces, allowCancellation: true, showProgress: true, (operationContext) => { solution = ThreadHelper.JoinableTaskFactory.Run(() => syncService.SyncNamespacesAsync(projects, operationContext.UserCancellationToken)); }); if (status != UIThreadOperationStatus.Canceled && solution is not null) { if (_workspace.CurrentSolution.GetChanges(solution).GetProjectChanges().Any()) { _workspace.TryApplyChanges(solution); MessageDialog.Show(ServicesVSResources.Sync_Namespaces, ServicesVSResources.Namespaces_have_been_updated, MessageDialogCommandSet.Ok); } else { MessageDialog.Show(ServicesVSResources.Sync_Namespaces, ServicesVSResources.No_namespaces_needed_updating, MessageDialogCommandSet.Ok); } } }
private void SetSeverityHandler(object sender, EventArgs args) { var selectedItem = (MenuCommand)sender; var reportDiagnostic = TryMapSelectedItemToReportDiagnostic(selectedItem); if (reportDiagnostic == null) { return; } var selectedDiagnostic = TryGetSingleSelectedEntry(); if (selectedDiagnostic == null) { return; } var pathToAnalyzerConfigDoc = TryGetPathToAnalyzerConfigDoc(selectedDiagnostic, out var project); if (pathToAnalyzerConfigDoc != null) { var result = _uiThreadOperationExecutor.Execute( title: ServicesVSResources.Updating_severity, defaultDescription: ServicesVSResources.Updating_severity, allowCancellation: true, showProgress: true, action: context => { var newSolution = ConfigureSeverityAsync(context.UserCancellationToken).WaitAndGetResult(context.UserCancellationToken); var operations = ImmutableArray.Create <CodeActionOperation>(new ApplyChangesOperation(newSolution)); var scope = context.AddScope(allowCancellation: true, ServicesVSResources.Updating_severity); _editHandlerService.Apply( _workspace, fromDocument: null, operations: operations, title: ServicesVSResources.Updating_severity, progressTracker: new UIThreadOperationContextProgressTracker(scope), cancellationToken: context.UserCancellationToken); }); if (result == UIThreadOperationStatus.Completed && selectedDiagnostic.DocumentId != null) { // Kick off diagnostic re-analysis for affected document so that the configured diagnostic gets refreshed. Task.Run(() => { _diagnosticService.Reanalyze(_workspace, documentIds: SpecializedCollections.SingletonEnumerable(selectedDiagnostic.DocumentId), highPriority: true); }); } } return; // Local functions. async System.Threading.Tasks.Task <Solution> ConfigureSeverityAsync(CancellationToken cancellationToken) { var diagnostic = await selectedDiagnostic.ToDiagnosticAsync(project, cancellationToken).ConfigureAwait(false); return(await ConfigurationUpdater.ConfigureSeverityAsync(reportDiagnostic.Value, diagnostic, project, cancellationToken).ConfigureAwait(false)); } }
private void OnRemoveUnusedReferencesForSelectedProject(object sender, EventArgs args) { if ( VisualStudioCommandHandlerHelpers.TryGetSelectedProjectHierarchy( _serviceProvider, out var hierarchy ) ) { Solution?solution = null; string? projectFilePath = null; ImmutableArray <ReferenceUpdate> referenceUpdates = default; var status = _threadOperationExecutor.Execute( ServicesVSResources.Remove_Unused_References, ServicesVSResources.Analyzing_project_references, allowCancellation: true, showProgress: true, (operationContext) => { (solution, projectFilePath, referenceUpdates) = GetUnusedReferencesForProjectHierarchy( hierarchy, operationContext.UserCancellationToken ); } ); if (status == UIThreadOperationStatus.Canceled) { return; } if ( solution is null || projectFilePath is not string { Length : > 0 } ||
public TextExtent GetExtentOfWord(SnapshotPoint currentPosition) { using (Logger.LogBlock(FunctionId.TextStructureNavigator_GetExtentOfWord, CancellationToken.None)) { var result = default(TextExtent); _uiThreadOperationExecutor.Execute( title: EditorFeaturesResources.Text_Navigation, defaultDescription: EditorFeaturesResources.Finding_word_extent, allowCancellation: true, showProgress: false, action: context => { result = GetExtentOfWordWorker(currentPosition, context.UserCancellationToken); }); return(result); } }
public void Navigate(INavigableRelationship relationship) => _uiThreadOperationExecutor.Execute( title: EditorFeaturesResources.Go_to_Definition, defaultDescription: EditorFeaturesResources.Navigating_to_definition, allowCancellation: true, showProgress: false, action: context => GoToDefinitionHelpers.TryGoToDefinition( _definitions, _document.Project.Solution, _definitions[0].NameDisplayParts.GetFullText(), _threadingContext, _presenter, context.UserCancellationToken));
public int GetProximityExpressions(IVsTextBuffer pBuffer, int iLine, int iCol, int cLines, out IVsEnumBSTR?ppEnum) { var textBuffer = _editorAdaptersFactory.GetDataBuffer(pBuffer); if (textBuffer is null) { // Can't resolve the text buffer, let someone else deal with this breakpoint. ppEnum = null; return(VSConstants.E_NOTIMPL); } var snapshot = textBuffer.CurrentSnapshot; if (!ValidateLocation(snapshot, iLine, iCol)) { // The point disappeared between sessions. Do not evaluate proximity expressions here. ppEnum = null; return(VSConstants.E_FAIL); } var proximityExpressions = _uiThreadOperationExecutor.Execute( title: Resources.ProximityExpression_Dialog_Title, description: Resources.ProximityExpression_Dialog_Description, allowCancellation: true, showProgress: true, (cancellationToken) => _proximityExpressionResolver.TryResolveProximityExpressionsAsync(textBuffer, iLine, iCol, cancellationToken), _joinableTaskFactory); if (proximityExpressions is null) { ppEnum = null; return(VSConstants.E_FAIL); } ppEnum = new VsEnumBSTR(proximityExpressions); return(VSConstants.S_OK); }
public static T Execute <T>( this IUIThreadOperationExecutor iUIThreadOperationExecutor, string title, string description, bool allowCancellation, bool showProgress, Func <CancellationToken, Task <T> > func, JoinableTaskFactory jtf) { T obj = default; var result = iUIThreadOperationExecutor.Execute(title, description, allowCancellation, showProgress, (context) => jtf.Run(async() => obj = await func(context.UserCancellationToken))); if (result == UIThreadOperationStatus.Canceled) { return(default);
private bool CommitWorker(bool previewChanges) { AssertIsForeground(); VerifyNotDismissed(); // If the identifier was deleted (or didn't change at all) then cancel the operation. // Note: an alternative approach would be for the work we're doing (like detecting // conflicts) to quickly bail in the case of no change. However, that involves deeper // changes to the system and is less easy to validate that nothing happens. // // The only potential downside here would be if there was a language that wanted to // still 'rename' even if the identifier went away (or was unchanged). But that isn't // a case we're aware of, so it's fine to be opinionated here that we can quickly bail // in these cases. if (this.ReplacementText == string.Empty || this.ReplacementText == _initialRenameText) { Cancel(); return(false); } previewChanges = previewChanges || OptionSet.GetOption(RenameOptions.PreviewChanges); var result = _uiThreadOperationExecutor.Execute( title: EditorFeaturesResources.Rename, defaultDescription: EditorFeaturesResources.Computing_Rename_information, allowCancellation: true, showProgress: false, action: context => CommitCore(context, previewChanges)); if (result == UIThreadOperationStatus.Canceled) { LogRenameSession(RenameLogMessage.UserActionOutcome.Canceled | RenameLogMessage.UserActionOutcome.Committed, previewChanges); Dismiss(rollbackTemporaryEdits: true); EndRenameSession(); return(false); } return(true); }
private UIThreadOperationStatus InvokeWithWaitDialog( Action <IUIThreadOperationContext> action, string waitDialogTitle, string waitDialogMessage) { var cancelled = false; var result = _uiThreadOperationExecutor.Execute( waitDialogTitle, waitDialogMessage, allowCancellation: true, showProgress: true, action: waitContext => { try { action(waitContext); } catch (OperationCanceledException) { cancelled = true; } }); return(cancelled ? UIThreadOperationStatus.Canceled : result); }
public void AugmentPeekSession(IPeekSession session, IList <IPeekableItem> peekableItems) { if (!string.Equals(session.RelationshipName, PredefinedPeekRelationships.Definitions.Name, StringComparison.OrdinalIgnoreCase)) { return; } var triggerPoint = session.GetTriggerPoint(_textBuffer.CurrentSnapshot); if (!triggerPoint.HasValue) { return; } var document = triggerPoint.Value.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { return; } _uiThreadOperationExecutor.Execute(EditorFeaturesResources.Peek, EditorFeaturesResources.Loading_Peek_information, allowCancellation: true, showProgress: false, action: context => { var cancellationToken = context.UserCancellationToken; var services = document.Project.Solution.Workspace.Services; IEnumerable <IPeekableItem> results; 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 = goToDefinitionService.FindDefinitionsAsync(document, triggerPoint.Value.Position, cancellationToken) .WaitAndGetResult(cancellationToken); results = GetPeekableItemsForNavigableItems(navigableItems, document.Project, _peekResultFactory, cancellationToken); } else { var semanticModel = document.GetRequiredSemanticModelAsync(cancellationToken).AsTask().WaitAndGetResult(cancellationToken); var symbol = SymbolFinder.GetSemanticInfoAtPositionAsync( semanticModel, triggerPoint.Value.Position, services, cancellationToken).WaitAndGetResult(cancellationToken) .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 = symbolMappingService.MapSymbolAsync(document, symbol, cancellationToken) .WaitAndGetResult(cancellationToken); mappingResult ??= new SymbolMappingResult(document.Project, symbol); results = _peekableItemFactory.GetPeekableItemsAsync(mappingResult.Symbol, mappingResult.Project, _peekResultFactory, cancellationToken) .WaitAndGetResult(cancellationToken); } peekableItems.AddRange(results); }); }