|
' 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.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Utilities
Imports Microsoft.CodeAnalysis.LanguageService
Imports Microsoft.CodeAnalysis.Shared.Extensions
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.VisualStudio.LanguageServices.Implementation.ExtractInterface
Imports Microsoft.VisualStudio.LanguageServices.Utilities
Imports Roslyn.Test.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.Length)
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) New MemberSymbolViewModel(member, Nothing))
Return New ExtractInterfaceDialogViewModel(
workspaceDoc.Project.Services.GetService(Of ISyntaxFactsService)(),
notificationService:=New TestNotificationService(),
uiThreadOperationExecutor:=Nothing,
defaultInterfaceName:=defaultInterfaceName,
conflictingTypeNames:=conflictingTypeNames.AsImmutableOrEmpty(),
memberViewModels:=memberViewModels.ToImmutableArray(),
defaultNamespace:=defaultNamespace,
generatedNameTypeParameterSuffix:=generatedNameTypeParameterSuffix,
languageName:=doc.Project.Language,
canAddDocument:=True)
End Using
End Function
End Class
End Namespace
|