diff --git a/src/EditorFeatures/Core/GoToDefinition/GoToDefinitionCommandHandler.cs b/src/EditorFeatures/Core/GoToDefinition/GoToDefinitionCommandHandler.cs index c92177d100e08..f9131fb3b2e8c 100644 --- a/src/EditorFeatures/Core/GoToDefinition/GoToDefinitionCommandHandler.cs +++ b/src/EditorFeatures/Core/GoToDefinition/GoToDefinitionCommandHandler.cs @@ -2,12 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System.ComponentModel.Composition; using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; -using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Notification; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; @@ -15,6 +12,7 @@ using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor.Commanding.Commands; using Microsoft.VisualStudio.Utilities; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Editor.GoToDefinition { @@ -32,7 +30,7 @@ public GoToDefinitionCommandHandler() public string DisplayName => EditorFeaturesResources.Go_to_Definition; - private static (Document, IGoToDefinitionService) GetDocumentAndService(ITextSnapshot snapshot) + private static (Document?, IGoToDefinitionService?) GetDocumentAndService(ITextSnapshot snapshot) { var document = snapshot.GetOpenDocumentInCurrentContextWithChanges(); return (document, document?.GetLanguageService()); @@ -56,9 +54,11 @@ public bool ExecuteCommand(GoToDefinitionCommandArgs args, CommandExecutionConte // This can be removed once typescript implements LSP support for goto def. if (service != null && !subjectBuffer.IsInLspEditorContext()) { + Contract.ThrowIfNull(document); var caretPos = args.TextView.GetCaretPoint(subjectBuffer); - if (caretPos.HasValue && TryExecuteCommand(document, caretPos.Value, service, context)) + if (caretPos.HasValue) { + ExecuteCommand(document, caretPos.Value, service, context); return true; } } @@ -66,23 +66,16 @@ public bool ExecuteCommand(GoToDefinitionCommandArgs args, CommandExecutionConte return false; } - // Internal for testing purposes only. - internal static bool TryExecuteCommand(ITextSnapshot snapshot, int caretPosition, CommandExecutionContext context) - => TryExecuteCommand(snapshot.GetOpenDocumentInCurrentContextWithChanges(), caretPosition, context); - - internal static bool TryExecuteCommand(Document document, int caretPosition, CommandExecutionContext context) - => TryExecuteCommand(document, caretPosition, document.GetLanguageService(), context); - - internal static bool TryExecuteCommand(Document document, int caretPosition, IGoToDefinitionService goToDefinitionService, CommandExecutionContext context) + private static void ExecuteCommand(Document document, int caretPosition, IGoToDefinitionService? goToDefinitionService, CommandExecutionContext context) { - string errorMessage = null; + string? errorMessage = null; using (context.OperationContext.AddScope(allowCancellation: true, EditorFeaturesResources.Navigating_to_definition)) { if (goToDefinitionService != null && goToDefinitionService.TryGoToDefinition(document, caretPosition, context.OperationContext.UserCancellationToken)) { - return true; + return; } errorMessage = FeaturesResources.Cannot_navigate_to_the_symbol_under_the_caret; @@ -95,11 +88,15 @@ internal static bool TryExecuteCommand(Document document, int caretPosition, IGo // and also will take it into consideration when measuring command handling duration. context.OperationContext.TakeOwnership(); var workspace = document.Project.Solution.Workspace; - var notificationService = workspace.Services.GetService(); + var notificationService = workspace.Services.GetRequiredService(); notificationService.SendNotification(errorMessage, title: EditorFeaturesResources.Go_to_Definition, severity: NotificationSeverity.Information); } + } - return true; + public static class TestAccessor + { + public static void ExecuteCommand(Document document, int caretPosition, IGoToDefinitionService goToDefinitionService, CommandExecutionContext context) + => GoToDefinitionCommandHandler.ExecuteCommand(document, caretPosition, goToDefinitionService, context); } } } diff --git a/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionCommandHandlerTests.vb b/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionCommandHandlerTests.vb index cfc8a9bd7d3a0..d9ebc64fa1cc1 100644 --- a/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionCommandHandlerTests.vb +++ b/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionCommandHandlerTests.vb @@ -4,7 +4,6 @@ Imports Microsoft.CodeAnalysis.Editor.CSharp.GoToDefinition Imports Microsoft.CodeAnalysis.Editor.GoToDefinition -Imports Microsoft.CodeAnalysis.Editor.Host Imports Microsoft.CodeAnalysis.Editor.Shared.Utilities Imports Microsoft.CodeAnalysis.Editor.UnitTests.Utilities Imports Microsoft.CodeAnalysis.Editor.UnitTests.Utilities.GoToHelpers @@ -12,22 +11,22 @@ Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces Imports Microsoft.CodeAnalysis.Navigation Imports Microsoft.CodeAnalysis.Text Imports Microsoft.VisualStudio.Commanding +Imports Microsoft.VisualStudio.Text.Editor.Commanding.Commands Imports Roslyn.Utilities Namespace Microsoft.CodeAnalysis.Editor.UnitTests.GoToDefinition <[UseExportProvider]> Public Class GoToDefinitionCancellationTests - Public Sub TestCancellation() ' Run without cancelling. - Dim updates As Integer = Cancel(Integer.MaxValue, False) + Dim updates = Cancel(Integer.MaxValue, False) Assert.InRange(updates, 0, Integer.MaxValue) Dim i As Integer = 0 While i < updates - Dim n As Integer = Cancel(i, True) + Dim n = Cancel(i, True) Assert.Equal(n, i + 1) - i = i + 1 + i += 1 End While End Sub @@ -66,13 +65,14 @@ class C Dim mockDocumentNavigationService = DirectCast(workspace.Services.GetService(Of IDocumentNavigationService)(), MockDocumentNavigationService) - GoToDefinitionCommandHandler.TryExecuteCommand(view.TextSnapshot, baseDocument.CursorPosition.Value, TestCommandExecutionContext.Create()) + Dim handler = New GoToDefinitionCommandHandler() + handler.ExecuteCommand(New GoToDefinitionCommandArgs(view, baseDocument.GetTextBuffer()), TestCommandExecutionContext.Create()) Assert.True(mockDocumentNavigationService._triedNavigationToSpan) Assert.Equal(New TextSpan(78, 2), mockDocumentNavigationService._span) workspace.SetDocumentContext(linkDocument.Id) - GoToDefinitionCommandHandler.TryExecuteCommand(view.TextSnapshot, baseDocument.CursorPosition.Value, TestCommandExecutionContext.Create()) + handler.ExecuteCommand(New GoToDefinitionCommandArgs(view, baseDocument.GetTextBuffer()), TestCommandExecutionContext.Create()) Assert.True(mockDocumentNavigationService._triedNavigationToSpan) Assert.Equal(New TextSpan(121, 2), mockDocumentNavigationService._span) End Using @@ -104,7 +104,7 @@ class C Dim goToDefService = New CSharpGoToDefinitionService(threadingContext, presenter) Dim waitContext = New TestUIThreadOperationContext(updatesBeforeCancel) - GoToDefinitionCommandHandler.TryExecuteCommand(document, cursorPosition, goToDefService, New CommandExecutionContext(waitContext)) + GoToDefinitionCommandHandler.TestAccessor.ExecuteCommand(document, cursorPosition, goToDefService, New CommandExecutionContext(waitContext)) Assert.Equal(navigatedTo OrElse mockDocumentNavigationService._triedNavigationToSpan, Not expectedCancel)