File: ExtractInterface\ExtractInterfaceViewModelTests.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 System.Threading.Tasks
Imports System.Collections.Immutable
Imports System.Linq
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Utilities
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
Imports Microsoft.CodeAnalysis.LanguageService
Imports Microsoft.CodeAnalysis.Shared.Extensions
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.VisualStudio.LanguageServices.Implementation.ExtractInterface
Imports Roslyn.Test.Utilities
Imports Microsoft.VisualStudio.LanguageServices.Utilities
 
Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.ExtractInterface
    <[UseExportProvider]>
    <Trait(Traits.Feature, Traits.Features.ExtractInterface)>
    Public Class ExtractInterfaceViewModelTests
        <Fact>
        Public Async Function TestExtractInterface_MembersCheckedByDefault() As Task
            Dim markup = <Text><![CDATA[
class $$MyClass
{
    public void Goo()
    {
    }
}"]]></Text>
 
            Dim viewModel = Await GetViewModelAsync(markup, LanguageNames.CSharp, "IMyClass")
            Assert.True(viewModel.MemberContainers.Single().IsChecked)
        End Function
 
        <Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/716122")>
        Public Async Function TestExtractInterface_InterfaceNameIsTrimmedOnSubmit() As Task
            Dim markup = <Text><![CDATA[
public class C$$
{
    public void Goo() { }
}"]]></Text>
 
            Dim viewModel = Await GetViewModelAsync(markup, LanguageNames.CSharp, "IC")
            viewModel.DestinationViewModel.TypeName = "                 IC2     "
            Dim submitSucceeded = viewModel.TrySubmit()
            Assert.True(submitSucceeded, String.Format("Submit failed unexpectedly."))
        End Function
 
        <Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/716122")>
        Public Async Function TestExtractInterface_FileNameIsTrimmedOnSubmit() As Task
            Dim markup = <Text><![CDATA[
public class C$$
{
    public void Goo() { }
}"]]></Text>
 
            Dim viewModel = Await GetViewModelAsync(markup, LanguageNames.CSharp, "IC")
            viewModel.DestinationViewModel.FileName = "                 IC2.cs     "
            Dim submitSucceeded = viewModel.TrySubmit()
            Assert.True(submitSucceeded, String.Format("Submit failed unexpectedly."))
        End Function
 
        <Fact>
        Public Async Function TestExtractInterface_SuccessfulCommit() As Task
            Dim markup = <Text><![CDATA[
class $$MyClass
{
    public void Goo()
    {
    }
}"]]></Text>
 
            Dim viewModel = Await GetViewModelAsync(markup, LanguageNames.CSharp, "IMyClass")
            Dim submitSucceeded = viewModel.TrySubmit()
            Assert.True(submitSucceeded, String.Format("Submit failed unexpectedly."))
        End Function
 
        <Fact>
        Public Async Function TestExtractInterface_SuccessfulCommit_NonemptyStrictSubsetOfMembersSelected() As Task
            Dim markup = <Text><![CDATA[
class $$MyClass
{
    public void Goo()
    {
    }

    public void Bar()
    {
    }
}"]]></Text>
 
            Dim viewModel = Await GetViewModelAsync(markup, LanguageNames.CSharp, "IMyClass")
            viewModel.MemberContainers.First().IsChecked = False
            Dim submitSucceeded = viewModel.TrySubmit()
            Assert.True(submitSucceeded, String.Format("Submit failed unexpectedly."))
        End Function
 
        <Fact>
        Public Async Function TestExtractInterface_FailedCommit_InterfaceNameConflict() As Task
            Dim markup = <Text><![CDATA[
class $$MyClass
{
    public void Goo()
    {
    }
}"]]></Text>
 
            Dim viewModel = Await GetViewModelAsync(markup, LanguageNames.CSharp, "IMyClass", conflictingTypeNames:=New List(Of String) From {"IMyClass"})
            Dim submitSucceeded = viewModel.TrySubmit()
            Assert.False(submitSucceeded)
        End Function
 
        <Fact>
        Public Async Function TestExtractInterface_FailedCommit_InterfaceNameNotAnIdentifier() As Task
            Dim markup = <Text><![CDATA[
class $$MyClass
{
    public void Goo()
    {
    }
}"]]></Text>
 
            Dim viewModel = Await GetViewModelAsync(markup, LanguageNames.CSharp, "IMyClass")
            viewModel.DestinationViewModel.TypeName = "SomeNamespace.IMyClass"
            Dim submitSucceeded = viewModel.TrySubmit()
            Assert.False(submitSucceeded)
        End Function
 
        <Fact>
        Public Async Function TestExtractInterface_FailedCommit_BadFileExtension() As Task
            Dim markup = <Text><![CDATA[
class $$MyClass
{
    public void Goo()
    {
    }
}"]]></Text>
 
            Dim viewModel = Await GetViewModelAsync(markup, LanguageNames.CSharp, "IMyClass")
            viewModel.DestinationViewModel.FileName = "FileName.vb"
            Dim submitSucceeded = viewModel.TrySubmit()
            Assert.False(submitSucceeded)
        End Function
 
        <Fact>
        Public Async Function TestExtractInterface_FailedCommit_BadFileName() As Task
            Dim markup = <Text><![CDATA[
class $$MyClass
{
    public void Goo()
    {
    }
}"]]></Text>
 
            Dim viewModel = Await GetViewModelAsync(markup, LanguageNames.CSharp, "IMyClass")
            viewModel.DestinationViewModel.FileName = "Bad*FileName.cs"
            Dim submitSucceeded = viewModel.TrySubmit()
            Assert.False(submitSucceeded)
        End Function
 
        <Fact>
        Public Async Function TestExtractInterface_FailedCommit_BadFileName2() As Task
            Dim markup = <Text><![CDATA[
class $$MyClass
{
    public void Goo()
    {
    }
}"]]></Text>
 
            Dim viewModel = Await GetViewModelAsync(markup, LanguageNames.CSharp, "IMyClass")
            viewModel.DestinationViewModel.FileName = "?BadFileName.cs"
            Dim submitSucceeded = viewModel.TrySubmit()
            Assert.False(submitSucceeded)
        End Function
 
        <Fact>
        Public Async Function TestExtractInterface_FailedCommit_NoMembersSelected() As Task
            Dim markup = <Text><![CDATA[
class $$MyClass
{
    public void Goo()
    {
    }
}"]]></Text>
 
            Dim viewModel = Await GetViewModelAsync(markup, LanguageNames.CSharp, "IMyClass")
            viewModel.MemberContainers.Single().IsChecked = False
            Dim submitSucceeded = viewModel.TrySubmit()
            Assert.False(submitSucceeded)
        End Function
 
        <Fact>
        Public Async Function TestExtractInterface_MemberDisplay_Method() As Task
            Dim markup = <Text><![CDATA[
using System;
class $$MyClass
{
    public void Goo<T>(T t, System.Diagnostics.CorrelationManager v, ref int w, Nullable<System.Int32> x = 7, string y = "hi", params int[] z)
    {
    }
}"]]></Text>
 
            Dim viewModel = Await GetViewModelAsync(markup, LanguageNames.CSharp, "IMyClass")
            Assert.Equal("Goo<T>(T, CorrelationManager, ref int, [int?], [string], params int[])", viewModel.MemberContainers.Single().SymbolName)
        End Function
 
        <Fact>
        Public Async Function TestExtractInterface_MemberDisplay_Property() As Task
            Dim markup = <Text><![CDATA[
using System;
class $$MyClass
{
    public int Goo
    {
        get { return 5; }
        set { }
    }
}"]]></Text>
 
            Dim viewModel = Await GetViewModelAsync(markup, LanguageNames.CSharp, "IMyClass")
            Assert.Equal("Goo", viewModel.MemberContainers.Where(Function(c) c.Symbol.IsKind(SymbolKind.Property)).Single().SymbolName)
        End Function
 
        <Fact>
        Public Async Function TestExtractInterface_MemberDisplay_Indexer() As Task
            Dim markup = <Text><![CDATA[
using System;
class $$MyClass
{
    public int this[Nullable<Int32> x, string y = "hi"] { get { return 1; } set { } }
}"]]></Text>
 
            Dim viewModel = Await GetViewModelAsync(markup, LanguageNames.CSharp, "IMyClass")
            Assert.Equal("this[int?, [string]]", viewModel.MemberContainers.Where(Function(c) c.Symbol.IsKind(SymbolKind.Property)).Single().SymbolName)
        End Function
 
        <Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37176")>
        Public Async Function TestExtractInterface_MemberDisplay_NullableReferenceType() As Task
            Dim markup = <Text><![CDATA[
#nullable enable
using System.Collections.Generic;
class $$MyClass
{
    public void M(string? s, IEnumerable<string?> e) { }
}"]]></Text>
 
            Dim viewModel = Await GetViewModelAsync(markup, LanguageNames.CSharp, "IMyClass")
            Assert.Equal("M(string?, IEnumerable<string?>)", viewModel.MemberContainers.Single(Function(c) c.Symbol.IsKind(SymbolKind.Method)).SymbolName)
        End Function
 
        <Fact>
        Public Async Function TestExtractInterface_MembersSorted() As Task
            Dim markup = <Text><![CDATA[
public class $$MyClass
{
    public void Goo(string s) { }
    public void Goo(int i) { }
    public void Goo(int i, string s) { }
    public void Goo() { }
    public void Goo(int i, int i2) { }
}"]]></Text>
 
            Dim viewModel = Await GetViewModelAsync(markup, LanguageNames.CSharp, "IMyClass")
            Assert.Equal(5, viewModel.MemberContainers.Count)
            Assert.Equal("Goo()", viewModel.MemberContainers.ElementAt(0).SymbolName)
            Assert.Equal("Goo(int)", viewModel.MemberContainers.ElementAt(1).SymbolName)
            Assert.Equal("Goo(int, int)", viewModel.MemberContainers.ElementAt(2).SymbolName)
            Assert.Equal("Goo(int, string)", viewModel.MemberContainers.ElementAt(3).SymbolName)
            Assert.Equal("Goo(string)", viewModel.MemberContainers.ElementAt(4).SymbolName)
        End Function
 
        Private Shared Async Function GetViewModelAsync(markup As XElement,
                              languageName As String,
                              defaultInterfaceName As String,
                              Optional defaultNamespace As String = "",
                              Optional generatedNameTypeParameterSuffix As String = "",
                              Optional conflictingTypeNames As List(Of String) = Nothing,
                              Optional isValidIdentifier As Boolean = True) As Tasks.Task(Of ExtractInterfaceDialogViewModel)
 
            Dim workspaceXml =
            <Workspace>
                <Project Language=<%= languageName %> CommonReferences="true">
                    <Document><%= markup.NormalizedValue.Replace(vbCrLf, vbLf) %></Document>
                </Project>
            </Workspace>
 
            Using workspace = EditorTestWorkspace.Create(workspaceXml)
                Dim doc = workspace.Documents.Single()
                Dim workspaceDoc = workspace.CurrentSolution.GetDocument(doc.Id)
                If (Not doc.CursorPosition.HasValue) Then
                    Assert.True(False, "Missing caret location in document.")
                End If
 
                Dim tree = Await workspaceDoc.GetSyntaxTreeAsync()
                Dim token = Await tree.GetTouchingWordAsync(doc.CursorPosition.Value, workspaceDoc.Project.Services.GetService(Of ISyntaxFactsService)(), CancellationToken.None)
                Dim symbol = (Await workspaceDoc.GetSemanticModelAsync()).GetDeclaredSymbol(token.Parent)
                Dim extractableMembers = DirectCast(symbol, INamedTypeSymbol).GetMembers().Where(Function(s) Not (TypeOf s Is IMethodSymbol) OrElse DirectCast(s, IMethodSymbol).MethodKind <> MethodKind.Constructor)
 
                Dim memberViewModels = extractableMembers.Select(Function(member As ISymbol)
                                                                     Return New MemberSymbolViewModel(member, Nothing)
                                                                 End Function)
 
                Return New ExtractInterfaceDialogViewModel(
                    workspaceDoc.Project.Services.GetService(Of ISyntaxFactsService)(),
                    notificationService:=New TestNotificationService(),
                    uiThreadOperationExecutor:=Nothing,
                    defaultInterfaceName:=defaultInterfaceName,
                    conflictingTypeNames:=If(conflictingTypeNames, New List(Of String)),
                    memberViewModels:=memberViewModels.ToImmutableArray(),
                    defaultNamespace:=defaultNamespace,
                    generatedNameTypeParameterSuffix:=generatedNameTypeParameterSuffix,
                    languageName:=doc.Project.Language)
            End Using
        End Function
    End Class
End Namespace