File: Venus\DocumentServiceTests.vb
Web Access
Project: src\src\VisualStudio\Core\Test\Microsoft.VisualStudio.LanguageServices.UnitTests.vbproj (Microsoft.VisualStudio.LanguageServices.UnitTests)
' 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
Imports Microsoft.CodeAnalysis.Classification
Imports Microsoft.CodeAnalysis.Editor.UnitTests
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Classification
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Classification.FormattedClassifications
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
Imports Microsoft.CodeAnalysis.Host
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.Text.Shared.Extensions
Imports Microsoft.VisualStudio.LanguageServices.Implementation.Venus
Imports Microsoft.VisualStudio.Text
Imports Roslyn.Test.Utilities
 
Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.Venus
 
    <UseExportProvider>
    Public Class DocumentServiceTests
        <WpfFact, Trait(Traits.Feature, Traits.Features.Venus)>
        Public Async Function TestSpanMappingService() As Task
            Using workspace = EditorTestWorkspace.Create(
                <Workspace>
                    <Project Language="C#" CommonReferences="true">
                        <Document>class outter { {|Document:class C { $$ }|} }</Document>
                    </Project>
                </Workspace>, composition:=EditorTestCompositions.EditorFeatures)
 
                Dim subjectDocument = workspace.Documents.Single()
                Dim projectedDocument = workspace.CreateProjectionBufferDocument("class projected { {|Document:|} }", {subjectDocument})
 
                Dim service = New ContainedDocument.DocumentServiceProvider(projectedDocument.GetTextBuffer())
                Dim spanMapper = service.GetService(Of ISpanMappingService)
 
                Dim position = subjectDocument.CursorPosition.Value
                Dim spans = Await spanMapper.MapSpansAsync(workspace.CurrentSolution.GetDocument(subjectDocument.Id), {New TextSpan(position, length:=0)}, CancellationToken.None)
 
                Assert.Equal(1, spans.Count)
                Assert.Equal(projectedDocument.CursorPosition.Value, spans(0).Span.Start)
                Assert.Equal(subjectDocument.FilePath, spans(0).FilePath)
            End Using
        End Function
 
        <WpfFact, Trait(Traits.Feature, Traits.Features.Venus)>
        Public Async Function TestSpanMappingService_InvalidPosition() As Task
            Using workspace = EditorTestWorkspace.Create(
                <Workspace>
                    <Project Language="C#" CommonReferences="true">
                        <Document>class outter { {|Document:class C$$ { }|} }</Document>
                    </Project>
                </Workspace>, composition:=EditorTestCompositions.EditorFeatures)
 
                Dim subjectDocument = workspace.Documents.Single()
                Dim projectedDocument = workspace.CreateProjectionBufferDocument("class projected { {|Document:|} }", {subjectDocument})
 
                Dim service = New ContainedDocument.DocumentServiceProvider(projectedDocument.GetTextBuffer())
                Dim spanMapper = service.GetService(Of ISpanMappingService)
 
                Dim position = subjectDocument.CursorPosition.Value
                Dim spans = Await spanMapper.MapSpansAsync(workspace.CurrentSolution.GetDocument(subjectDocument.Id), {New TextSpan(position, length:=0), New TextSpan(start:=1, length:=0), New TextSpan(position + 1, length:=0)}, CancellationToken.None)
 
                ' order of input is maintained
                Assert.Equal(3, spans.Count)
 
                Assert.Equal(projectedDocument.CursorPosition.Value, spans(0).Span.Start)
                Assert.Equal(subjectDocument.FilePath, spans(0).FilePath)
 
                ' but return default for invalid span
                Assert.True(spans(1).IsDefault)
 
                Assert.Equal(projectedDocument.CursorPosition.Value + 1, spans(2).Span.Start)
                Assert.Equal(subjectDocument.FilePath, spans(2).FilePath)
            End Using
        End Function
 
        <Fact, Trait(Traits.Feature, Traits.Features.Venus)>
        Public Sub TestDocumentOperation()
            Using workspace = EditorTestWorkspace.Create(
                <Workspace>
                    <Project Language="C#" CommonReferences="true">
                        <Document>class outter { {|Document:class C$$ { }|} }</Document>
                    </Project>
                </Workspace>, composition:=EditorTestCompositions.EditorFeatures)
 
                Dim subjectDocument = workspace.Documents.Single()
                Dim projectedDocument = workspace.CreateProjectionBufferDocument("class projected { {|Document:|} }", {subjectDocument})
 
                Dim service = New ContainedDocument.DocumentServiceProvider(projectedDocument.GetTextBuffer())
                Dim documentOperations = service.GetService(Of IDocumentOperationService)
 
                ' contained document supports both document modification and diagnostics
                ' soon, contained document will be only used to support old venus and razor but not new razor
                ' which will use their own implementation of these services
                Assert.True(documentOperations.CanApplyChange)
                Assert.True(documentOperations.SupportDiagnostics)
            End Using
        End Sub
 
        <Fact, Trait(Traits.Feature, Traits.Features.Workspace)>
        Public Async Function TestSourceGeneratedDocumentOperation() As Task
            Using workspace = EditorTestWorkspace.Create(
                <Workspace>
                    <Project Language="C#" CommonReferences="true">
                        <DocumentFromSourceGenerator>class C { }</DocumentFromSourceGenerator>
                    </Project>
                </Workspace>, composition:=EditorTestCompositions.EditorFeatures)
 
                Dim subjectDocument = workspace.Documents.Single()
                Dim openDocument = subjectDocument.GetOpenTextContainer()
                Dim sourceGeneratedDocumentId = workspace.GetDocumentIdInCurrentContext(openDocument)
                Dim document = Assert.IsType(Of SourceGeneratedDocument)(Await workspace.CurrentSolution.GetDocumentAsync(sourceGeneratedDocumentId, includeSourceGenerated:=True))
                Dim documentServices = document.State.DocumentServiceProvider
                Dim documentOperations = documentServices.GetService(Of IDocumentOperationService)()
 
                Assert.False(documentOperations.CanApplyChange)
                Assert.True(documentOperations.SupportDiagnostics)
            End Using
        End Function
 
        <Fact, Trait(Traits.Feature, Traits.Features.Venus)>
        Public Async Function TestExcerptService_SingleLine() As Task
            Using workspace = EditorTestWorkspace.Create(
                <Workspace>
                    <Project Language="C#" CommonReferences="true">
                        <Document>class outter { {|Document:class C { }|} }</Document>
                    </Project>
                </Workspace>, composition:=EditorTestCompositions.EditorFeatures)
 
                Dim subjectDocument = workspace.Documents.Single()
                Dim projectedDocument = workspace.CreateProjectionBufferDocument("class projected { {|Document:|} }", {subjectDocument})
 
                Dim service = New ContainedDocument.DocumentServiceProvider(projectedDocument.GetTextBuffer())
                Dim excerptService = service.GetService(Of IDocumentExcerptService)
 
                Dim result = Await excerptService.TryExcerptAsync(workspace.CurrentSolution.GetDocument(subjectDocument.Id), GetNamedSpan(subjectDocument), ExcerptMode.SingleLine, ClassificationOptions.Default, CancellationToken.None)
                Assert.True(result.HasValue)
 
                Dim content = result.Value.Content.ToString()
                Assert.Equal(projectedDocument.GetTextBuffer().CurrentSnapshot.GetText(), content)
 
                Dim expcetedFormatted = {FormattedClassifications.Text("class projected { "),
                                         Keyword("class"),
                                         FormattedClassifications.Text(" "),
                                         [Class]("C"),
                                         FormattedClassifications.Text(" "),
                                         Punctuation.OpenCurly,
                                         FormattedClassifications.Text(" "),
                                         Punctuation.CloseCurly,
                                         FormattedClassifications.Text(" }")}
 
                Dim actualFormatted = result.Value.ClassifiedSpans.Select(Function(a) New FormattedClassification(content.Substring(a.TextSpan.Start, a.TextSpan.Length), a.ClassificationType))
                Assert.Equal(expcetedFormatted, actualFormatted)
 
                Assert.Equal(GetNamedSpan(projectedDocument), result.Value.MappedSpan)
            End Using
        End Function
 
        <Fact, Trait(Traits.Feature, Traits.Features.Venus)>
        Public Async Function TestExcerptService_Tooltip_Singleline() As Task
            Using workspace = EditorTestWorkspace.Create(
                <Workspace>
                    <Project Language="C#" CommonReferences="true">
                        <Document>class outter { {|Document:class C { }|} }</Document>
                    </Project>
                </Workspace>, composition:=EditorTestCompositions.EditorFeatures)
 
                Dim subjectDocument = workspace.Documents.Single()
                Dim projectedDocument = workspace.CreateProjectionBufferDocument("class projected { {|Document:|} }", {subjectDocument})
 
                Dim service = New ContainedDocument.DocumentServiceProvider(projectedDocument.GetTextBuffer())
                Dim excerptService = service.GetService(Of IDocumentExcerptService)
 
                ' make sure single line buffer doesn't throw on ExcerptMode.Tooltip
                Dim result = Await excerptService.TryExcerptAsync(workspace.CurrentSolution.GetDocument(subjectDocument.Id), GetNamedSpan(subjectDocument), ExcerptMode.Tooltip, ClassificationOptions.Default, CancellationToken.None)
                Assert.True(result.HasValue)
 
                Dim content = result.Value.Content.ToString()
                Assert.Equal(projectedDocument.GetTextBuffer().CurrentSnapshot.GetText(), content)
 
                Dim expcetedFormatted = {FormattedClassifications.Text("class projected { "),
                                         Keyword("class"),
                                         FormattedClassifications.Text(" "),
                                         [Class]("C"),
                                         FormattedClassifications.Text(" "),
                                         Punctuation.OpenCurly,
                                         FormattedClassifications.Text(" "),
                                         Punctuation.CloseCurly,
                                         FormattedClassifications.Text(" }")}
 
                Dim actualFormatted = result.Value.ClassifiedSpans.Select(Function(a) New FormattedClassification(content.Substring(a.TextSpan.Start, a.TextSpan.Length), a.ClassificationType))
                Assert.Equal(expcetedFormatted, actualFormatted)
 
                Assert.Equal(GetNamedSpan(projectedDocument), result.Value.MappedSpan)
            End Using
        End Function
 
        <Fact, Trait(Traits.Feature, Traits.Features.Venus)>
        Public Async Function TestExcerptService_Tooltip_MultiLines() As Task
            Using workspace = EditorTestWorkspace.Create(
                <Workspace>
                    <Project Language="C#" CommonReferences="true">
                        <Document>class outter { {|Document:class C { }|} }</Document>
                    </Project>
                </Workspace>, composition:=EditorTestCompositions.EditorFeatures)
 
                Dim projectedContent = <Code>class projected 
{|Content:                        {|WithoutLeadingWhitespace:{ 
                            private void SurfaceMethod() { }
 
                            |}{|Document:|}{|LastText:
 
                            private void SurfaceMethod2() { }
                        }|}|}</Code>
 
                Dim subjectDocument = workspace.Documents.Single()
                Dim projectedDocument = workspace.CreateProjectionBufferDocument(projectedContent.NormalizedValue(), {subjectDocument})
 
                Dim service = New ContainedDocument.DocumentServiceProvider(projectedDocument.GetTextBuffer())
                Dim excerptService = service.GetService(Of IDocumentExcerptService)
 
                Dim result = Await excerptService.TryExcerptAsync(workspace.CurrentSolution.GetDocument(subjectDocument.Id), GetNamedSpan(subjectDocument), ExcerptMode.Tooltip, ClassificationOptions.Default, CancellationToken.None)
                Assert.True(result.HasValue)
 
                Dim content = result.Value.Content.ToString()
 
                ' calculate expected span
                Dim contentSpan = GetNamedSpan(projectedDocument, "Content")
                Dim expectedContent = projectedDocument.GetTextBuffer().CurrentSnapshot.GetText(contentSpan.ToSpan())
                Assert.Equal(expectedContent, content)
 
                Dim firstText = projectedDocument.GetTextBuffer().CurrentSnapshot.GetText(GetNamedSpan(projectedDocument, "WithoutLeadingWhitespace").ToSpan())
                Dim documentSpan = GetNamedSpan(projectedDocument, "Document").ToSpan()
                Dim lastText = projectedDocument.GetTextBuffer().CurrentSnapshot.GetText(Span.FromBounds(documentSpan.End, projectedDocument.GetTextBuffer().CurrentSnapshot.Length))
 
                Dim expcetedFormatted = {FormattedClassifications.Text(firstText),
                                         Keyword("class"),
                                         FormattedClassifications.Text(" "),
                                         [Class]("C"),
                                         FormattedClassifications.Text(" "),
                                         Punctuation.OpenCurly,
                                         FormattedClassifications.Text(" "),
                                         Punctuation.CloseCurly,
                                         FormattedClassifications.Text(lastText)}
 
                Dim actualFormatted = result.Value.ClassifiedSpans.Select(Function(a) New FormattedClassification(content.Substring(a.TextSpan.Start, a.TextSpan.Length), a.ClassificationType))
                Assert.Equal(expcetedFormatted, actualFormatted)
 
                ' ExcerptResult.MappedSpan is relative to ExcerptResult.Content.
                ' recalculate expected span relative to the content span
                Assert.Equal(New TextSpan(documentSpan.Start - contentSpan.Start, documentSpan.Length), result.Value.MappedSpan)
            End Using
        End Function
 
        <Fact, Trait(Traits.Feature, Traits.Features.Venus)>
        Public Async Function TestExcerptService_LeadingWhiteSpace() As Task
            Using workspace = EditorTestWorkspace.Create(
                <Workspace>
                    <Project Language="C#" CommonReferences="true">
                        <Document>class outter { {|Document:            class C { }         |} }</Document>
                    </Project>
                </Workspace>, composition:=EditorTestCompositions.EditorFeatures)
 
                Dim projectedContent = <Code>class projected 
{ 
    {|Document:|}
}</Code>
 
                Dim subjectDocument = workspace.Documents.Single()
                Dim projectedDocument = workspace.CreateProjectionBufferDocument(projectedContent.NormalizedValue(), {subjectDocument})
 
                Dim service = New ContainedDocument.DocumentServiceProvider(projectedDocument.GetTextBuffer())
                Dim excerptService = service.GetService(Of IDocumentExcerptService)
 
                Dim result = Await excerptService.TryExcerptAsync(workspace.CurrentSolution.GetDocument(subjectDocument.Id), GetNamedSpan(subjectDocument), ExcerptMode.SingleLine, ClassificationOptions.Default, CancellationToken.None)
                Assert.True(result.HasValue)
 
                Dim content = result.Value.Content.ToString()
 
                ' confirm leading whitespace is removed
                Dim expcetedFormatted = {Keyword("class"),
                                         FormattedClassifications.Text(" "),
                                         [Class]("C"),
                                         FormattedClassifications.Text(" "),
                                         Punctuation.OpenCurly,
                                         FormattedClassifications.Text(" "),
                                         Punctuation.CloseCurly,
                                         FormattedClassifications.Text("         ")}
 
                Dim actualFormatted = result.Value.ClassifiedSpans.Select(Function(a) New FormattedClassification(content.Substring(a.TextSpan.Start, a.TextSpan.Length), a.ClassificationType))
                Assert.Equal(expcetedFormatted, actualFormatted)
            End Using
        End Function
 
        Private Shared Function GetNamedSpan(document As TestHostDocument, Optional spanName As String = "Document") As TextSpan
            Return document.AnnotatedSpans(spanName).First()
        End Function
    End Class
End Namespace