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;
        }
Example #3
0
        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));
            });
        }
Example #4
0
        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));
            }
        }
Example #6
0
        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 } ||
Example #7
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);
                }
            }
Example #8
0
 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);
Example #11
0
        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);
        }
Example #12
0
        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);
        }
Example #13
0
        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);
            });
        }