|
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.
Imports System.Threading
Imports Microsoft.CodeAnalysis.Editor.CSharp.Navigation
Imports Microsoft.CodeAnalysis.Editor.Shared.Utilities
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Utilities.GoToHelpers
Imports Microsoft.CodeAnalysis.Editor.VisualBasic.Navigation
Imports Microsoft.CodeAnalysis.Navigation
Imports Microsoft.VisualStudio.Text
Namespace Microsoft.CodeAnalysis.Editor.UnitTests.GoToDefinition
Public MustInherit Class GoToDefinitionTestsBase
Public Shared Async Function TestAsync(
workspaceDefinition As XElement,
Optional expectedResult As Boolean = True) As Task
Using workspace = EditorTestWorkspace.Create(workspaceDefinition, composition:=GoToTestHelpers.Composition)
Dim solution = workspace.CurrentSolution
Dim cursorDocument = workspace.Documents.First(Function(d) d.CursorPosition.HasValue)
Dim cursorPosition = cursorDocument.CursorPosition.Value
' Set up mocks. The IDocumentNavigationService should be called if there is one,
' location and the INavigableItemsPresenter should be called if there are
' multiple locations.
' prepare a notification listener
Dim textView = cursorDocument.GetTextView()
Dim textBuffer = textView.TextBuffer
textView.Caret.MoveTo(New SnapshotPoint(textBuffer.CurrentSnapshot, cursorPosition))
Dim cursorBuffer = cursorDocument.GetTextBuffer()
Dim document = workspace.CurrentSolution.GetDocument(cursorDocument.Id)
Dim mockDocumentNavigationService = DirectCast(workspace.Services.GetService(Of IDocumentNavigationService)(), MockDocumentNavigationService)
Dim mockSymbolNavigationService = DirectCast(workspace.Services.GetService(Of ISymbolNavigationService)(), MockSymbolNavigationService)
Dim presenterCalled As Boolean = False
Dim threadingContext = workspace.ExportProvider.GetExportedValue(Of IThreadingContext)()
Dim presenter = New MockStreamingFindUsagesPresenter(Sub() presenterCalled = True)
Dim goToDefService = If(document.Project.Language = LanguageNames.CSharp,
DirectCast(New CSharpDefinitionLocationService(threadingContext, presenter), IDefinitionLocationService),
New VisualBasicDefinitionLocationService(threadingContext, presenter))
Dim defLocationAndSpan = Await goToDefService.GetDefinitionLocationAsync(
document, cursorPosition, CancellationToken.None)
Dim defLocation = defLocationAndSpan?.Location
Dim actualResult = defLocation IsNot Nothing AndAlso
Await defLocation.NavigateToAsync(NavigationOptions.Default, CancellationToken.None)
Assert.Equal(expectedResult, actualResult)
Dim expectedLocations As New List(Of FilePathAndSpan)
For Each testDocument In workspace.Documents
For Each selectedSpan In testDocument.SelectedSpans
expectedLocations.Add(New FilePathAndSpan(testDocument.FilePath, selectedSpan))
Next
Next
expectedLocations.Sort()
Dim expectedPresenterLocations = workspace.Documents.
Where(Function(d) d.AnnotatedSpans.ContainsKey("PresenterLocation")).
Select(Function(d) (d.Id, spans:=d.AnnotatedSpans("PresenterLocation")))
Dim context = presenter.Context
If expectedResult Then
If expectedLocations.Count = 0 Then
If expectedPresenterLocations.Any() Then
' multiple results shown in the streaming presenter.
Assert.True(presenterCalled)
Dim presenterReferences = context.GetReferences()
Assert.Equal(presenterReferences.Length, expectedPresenterLocations.Sum(Function(t) t.spans.Length))
For Each tuple In expectedPresenterLocations
For Each sourceSpan In tuple.spans
Assert.True(presenterReferences.Any(Function(r) r.SourceSpan.Document.Id = tuple.Id AndAlso r.SourceSpan.SourceSpan = sourceSpan))
Next
Next
Else
' if there is not expected locations, it means symbol navigation is used
Assert.True(mockSymbolNavigationService._triedNavigationToSymbol, "a navigation took place")
Assert.Null(mockDocumentNavigationService._documentId)
Assert.False(presenterCalled)
End If
Else
Assert.False(mockSymbolNavigationService._triedNavigationToSymbol)
If mockDocumentNavigationService._triedNavigationToSpan Then
Dim definitionDocument = workspace.GetTestDocument(mockDocumentNavigationService._documentId)
Assert.Single(definitionDocument.SelectedSpans)
Assert.Equal(definitionDocument.SelectedSpans.Single(), mockDocumentNavigationService._span)
' The INavigableItemsPresenter should not have been called
Assert.False(presenterCalled)
ElseIf mockDocumentNavigationService._triedNavigationToPosition Then
Dim definitionDocument = workspace.GetTestDocument(mockDocumentNavigationService._documentId)
Assert.Single(definitionDocument.SelectedSpans)
Dim expected = definitionDocument.SelectedSpans.Single()
Assert.Equal(expected.Start, mockDocumentNavigationService._position)
' The INavigableItemsPresenter should not have been called
Assert.False(presenterCalled)
Else
Assert.True(presenterCalled)
Dim actualLocations As New List(Of FilePathAndSpan)
Dim items = context.GetDefinitions()
For Each location In items
For Each docSpan In location.SourceSpans
actualLocations.Add(New FilePathAndSpan(docSpan.Document.FilePath, docSpan.SourceSpan))
Next
Next
actualLocations.Sort()
Assert.Equal(expectedLocations, actualLocations)
' The IDocumentNavigationService should not have been called
Assert.Null(mockDocumentNavigationService._documentId)
End If
End If
Else
Assert.False(mockSymbolNavigationService._triedNavigationToSymbol)
Assert.Null(mockDocumentNavigationService._documentId)
Assert.False(presenterCalled)
End If
End Using
End Function
End Class
End Namespace
|