提交 55283d13 编写于 作者: B Balaji Krishnan

Add MoveType tests

Tests for following code actions in C# and VB:
1. Move type to new file
2. Rename type to match filename
3. Rename file to match typename
上级 767427bb
......@@ -158,7 +158,7 @@
<Compile Include="CodeActions\LambdaSimplifier\LambdaSimplifierTests.cs" />
<Compile Include="CodeActions\MoveType\CSharpMoveTypeTestsBase.cs" />
<Compile Include="CodeActions\MoveType\MoveTypeTests.MoveToNewFile.cs" />
<Compile Include="CodeActions\MoveType\MoveTypeTests.RenameFile.cs" />
<Compile Include="CodeActions\MoveType\MoveTypeTests.RenameFileOrType.cs" />
<Compile Include="CodeActions\ReplacePropertyWithMethods\ReplacePropertyWithMethodsTests.cs" />
<Compile Include="Completion\CompletionServiceTests.cs" />
<Compile Include="Diagnostics\AddUsing\AddUsingTests_NuGet.cs" />
......
......@@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeActions.MoveType
public partial class MoveTypeTests : CSharpMoveTypeTestsBase
{
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)]
public async Task ClassesWithNoContainerNamespace()
public async Task MoveTypeWithNoContainerNamespace()
{
var code =
@"[||]class Class1 { }
......@@ -23,7 +23,157 @@ class Class2 { }";
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)]
public async Task ClassesWithContainerNamespace()
public async Task MoveTypeWithWithUsingsAndNoContainerNamespace()
{
var code =
@"// Banner Text
using System;
[||]class Class1 { }
class Class2 { }";
var codeAfterMove =
@"// Banner Text
class Class2 { }";
var expectedDocumentName = "Class1.cs";
var destinationDocumentText =
@"class Class1 { }";
await TestMoveTypeToNewFileAsync(code, codeAfterMove, expectedDocumentName, destinationDocumentText);
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)]
public async Task MoveTypeWithWithMembers()
{
var code =
@"// Banner Text
using System;
[||]class Class1
{
void Print(int x)
{
Console.WriteLine(x);
}
}
class Class2 { }";
var codeAfterMove =
@"// Banner Text
class Class2 { }";
var expectedDocumentName = "Class1.cs";
var destinationDocumentText =
@"
using System;
class Class1
{
void Print(int x)
{
Console.WriteLine(x);
}
}";
await TestMoveTypeToNewFileAsync(code, codeAfterMove, expectedDocumentName, destinationDocumentText);
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)]
public async Task MoveTypeWithWithMembers2()
{
var code =
@"// Banner Text
using System;
[||]class Class1
{
void Print(int x)
{
Console.WriteLine(x);
}
}
class Class2
{
void Print(int x)
{
Console.WriteLine(x);
}
}";
var codeAfterMove =
@"// Banner Text
using System;
class Class2
{
void Print(int x)
{
Console.WriteLine(x);
}
}";
var expectedDocumentName = "Class1.cs";
var destinationDocumentText =
@"
using System;
class Class1
{
void Print(int x)
{
Console.WriteLine(x);
}
}";
await TestMoveTypeToNewFileAsync(code, codeAfterMove, expectedDocumentName, destinationDocumentText);
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)]
public async Task MoveAnInterface()
{
var code =
@"[||]interface IMoveType { }
class Class2 { }";
var codeAfterMove = @"class Class2 { }";
var expectedDocumentName = "IMoveType.cs";
var destinationDocumentText = @"interface IMoveType { }";
await TestMoveTypeToNewFileAsync(code, codeAfterMove, expectedDocumentName, destinationDocumentText);
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)]
public async Task MoveAStruct()
{
var code =
@"[||]struct MyStruct { }
class Class2 { }";
var codeAfterMove = @"class Class2 { }";
var expectedDocumentName = "MyStruct.cs";
var destinationDocumentText = @"struct MyStruct { }";
await TestMoveTypeToNewFileAsync(code, codeAfterMove, expectedDocumentName, destinationDocumentText);
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)]
public async Task MoveAnEnum()
{
var code =
@"[||]enum MyEnum { }
class Class2 { }";
var codeAfterMove = @"class Class2 { }";
var expectedDocumentName = "MyEnum.cs";
var destinationDocumentText = @"enum MyEnum { }";
await TestMoveTypeToNewFileAsync(code, codeAfterMove, expectedDocumentName, destinationDocumentText);
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)]
public async Task MoveTypeWithWithContainerNamespace()
{
var code =
@"namespace N1
......
......@@ -9,14 +9,42 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeActions.MoveType
public partial class MoveTypeTests : CSharpMoveTypeTestsBase
{
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)]
public async Task SingleClassInFileWithNoContainerNamespace()
public async Task SingleClassInFile()
{
var code =
@"[||]class Class1";
@"[||]class Class1 { }";
var expectedDocumentName = "Class1.cs";
await TestRenameFileToMatchTypeAsync(code, expectedDocumentName);
var codeWithTypeRenamedToMatchFileName =
@"class test1 { }";
await TestRenameTypeToMatchFileAsync(code, codeWithTypeRenamedToMatchFileName);
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)]
public async Task TypeNameMatchesFileName()
{
// testworkspace creates files like test1.cs, test2.cs and so on..
// so type name matches filename here and rename file action should not be offered.
var code =
@"[||]class test1 { }";
await TestRenameFileToMatchTypeAsync(code, expectedCodeAction: false);
await TestRenameTypeToMatchFileAsync(code, expectedCodeAction: false);
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)]
public async Task MoreThanOneTypeInFile()
{
var code =
@"[||]class Class1 { }
class Class2 { }";
await TestRenameFileToMatchTypeAsync(code, expectedCodeAction: false);
await TestRenameTypeToMatchFileAsync(code, expectedCodeAction: false);
}
}
}
......@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.UnitTests;
......@@ -14,6 +15,8 @@ namespace Microsoft.CodeAnalysis.Editor.UnitTests.MoveType
public abstract class AbstractMoveTypeTestsBase : AbstractCodeActionTest
{
private const string SpanMarker = "[||]";
private const string RenameFileCodeActionTitle = "Rename File";
private const string RenameTypeCodeActionTitle = "Rename Type";
private string StripSpanMarkers(string text)
{
......@@ -21,12 +24,90 @@ private string StripSpanMarkers(string text)
return text.Remove(index, SpanMarker.Length);
}
protected async Task TestRenameTypeToMatchFileAsync(
string originalCode,
string expectedCode = null,
bool expectedCodeAction = true,
bool compareTokens = true)
{
using (var workspace = await CreateWorkspaceFromFileAsync(originalCode, parseOptions: null, compilationOptions: null))
{
if (expectedCodeAction)
{
Assert.True(expectedCode != null, $"{nameof(expectedCode)} should be present if {nameof(expectedCodeAction)} is true.");
var documentId = workspace.Documents[0].Id;
var documentName = workspace.Documents[0].Name;
var oldSolutionAndNewSolution = await TestOperationAsync(
workspace, expectedCode, RenameTypeCodeActionTitle, compareTokens);
// the original source document does not exist in the new solution.
var newSolution = oldSolutionAndNewSolution.Item2;
var document = newSolution.GetDocument(documentId);
Assert.NotNull(document);
Assert.Equal(documentName, document.Name);
}
else
{
var actions = await GetCodeActionsAsync(workspace, fixAllActionEquivalenceKey: null);
var renameFileAction = actions.Any(action => action.Title.StartsWith(RenameTypeCodeActionTitle));
Assert.False(renameFileAction, "Rename Type to match file name code action was not expected, but shows up.");
}
}
}
protected async Task TestRenameFileToMatchTypeAsync(
string originalCode,
string expectedDocumentName)
string expectedDocumentName = null,
bool expectedCodeAction = true,
bool compareTokens = true)
{
using (var workspace = await CreateWorkspaceFromFileAsync(originalCode, parseOptions: null, compilationOptions: null))
{
if (expectedCodeAction)
{
// TODO: Implement this.
await Task.Delay(1);
Assert.True(expectedDocumentName != null, $"{nameof(expectedDocumentName)} should be present if {nameof(expectedCodeAction)} is true.");
var oldDocumentId = workspace.Documents[0].Id;
var expectedText = StripSpanMarkers(originalCode);
// a new document with the same text as old document is added.
var oldSolutionAndNewSolution = await TestOperationAsync(
workspace, expectedText, RenameFileCodeActionTitle, compareTokens);
// the original source document does not exist in the new solution.
var newSolution = oldSolutionAndNewSolution.Item2;
Assert.Null(newSolution.GetDocument(oldDocumentId));
}
else
{
var actions = await GetCodeActionsAsync(workspace, fixAllActionEquivalenceKey: null);
var renameFileAction = actions.Any(action => action.Title.StartsWith(RenameFileCodeActionTitle));
Assert.False(renameFileAction, "Rename File to match type code action was not expected, but shows up.");
}
}
}
private async Task<Tuple<Solution, Solution>> TestOperationAsync(
Workspaces.TestWorkspace workspace,
string expectedCode,
string operation,
bool compareTokens)
{
var actions = await GetCodeActionsAsync(workspace, fixAllActionEquivalenceKey: null);
var action = actions.Single(a => a.Title.StartsWith(operation));
var operations = await action.GetOperationsAsync(CancellationToken.None);
return await TestOperationsAsync(workspace,
expectedText: expectedCode,
operations: operations,
conflictSpans: null,
renameSpans: null,
warningSpans: null,
compareTokens: compareTokens,
expectedChangedDocumentId: null);
}
protected async Task TestMoveTypeToNewFileAsync(
......@@ -50,7 +131,6 @@ private string StripSpanMarkers(string text)
}
var sourceDocumentId = workspace.Documents[0].Id;
var refactoring = await GetCodeRefactoringAsync(workspace);
// Verify the newly added document and its text
var oldSolutionAndNewSolution = await TestAddDocumentAsync(workspace,
......
......@@ -138,7 +138,7 @@
<Compile Include="CodeActions\InvertIf\InvertIfTests.vb" />
<Compile Include="CodeActions\MoveType\BasicMoveTypeTestsBase.vb" />
<Compile Include="CodeActions\MoveType\MoveTypeTests.MoveToNewFile.vb" />
<Compile Include="CodeActions\MoveType\MoveTypeTests.RenameFile.vb" />
<Compile Include="CodeActions\MoveType\MoveTypeTests.RenameFileOrType.vb" />
<Compile Include="CodeActions\Preview\PreviewTests.vb" />
<Compile Include="CodeActions\ReplacePropertyWithMethods\ReplacePropertyWithMethodsTests.vb" />
<Compile Include="Completion\CompletionServiceTests.vb" />
......
......@@ -34,8 +34,31 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CodeRefactorings.M
Return TestOptions.Script
End Function
Protected Overloads Function TestRenameFileToMatchTypeAsync(originalCode As XElement, expectedDocumentName As String) As Task
Return MyBase.TestRenameFileToMatchTypeAsync(originalCode.ConvertTestSourceTag(), expectedDocumentName)
Protected Overloads Function TestRenameTypeToMatchFileAsync(
originalCode As XElement,
Optional expectedCode As XElement = Nothing,
Optional expectedCodeAction As Boolean = True,
Optional compareTokens As Boolean = True
) As Task
Dim expectedText As String = Nothing
If Not expectedCode Is Nothing Then
expectedText = expectedCode.ConvertTestSourceTag()
End If
Return MyBase.TestRenameTypeToMatchFileAsync(
originalCode.ConvertTestSourceTag(), expectedText, expectedCodeAction, compareTokens)
End Function
Protected Overloads Function TestRenameFileToMatchTypeAsync(
originalCode As XElement,
Optional expectedDocumentName As String = Nothing,
Optional expectedCodeAction As Boolean = True,
Optional compareTokens As Boolean = True
) As Task
Return MyBase.TestRenameFileToMatchTypeAsync(
originalCode.ConvertTestSourceTag(), expectedDocumentName, expectedCodeAction, compareTokens)
End Function
Protected Overloads Function TestMoveTypeToNewFileAsync(
......
......@@ -5,7 +5,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CodeRefactorings.M
Inherits BasicMoveTypeTestsBase
<WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)>
Public Async Function ClassesWithNoContainerNamespace() As Task
Public Async Function MultipleTypesInFileWithNoContainerNamespace() As Task
Dim code =
<File>
[||]Class Class1
......
......@@ -13,6 +13,43 @@ End Class
Dim expectedDocumentName = "Class1.vb"
Await TestRenameFileToMatchTypeAsync(code, expectedDocumentName)
Dim codeAfterRenamingType =
<File>
Class test1
End Class
</File>
Await TestRenameTypeToMatchFileAsync(code, codeAfterRenamingType)
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)>
Public Async Function TypeNameMatchesFileName() As Task
' testworkspace creates files Like test1.cs, test2.cs And so on..
' so type name matches filename here And rename file action should Not be offered.
Dim code =
<File>
[||]Class test1
End Class
</File>
Await TestRenameFileToMatchTypeAsync(code, expectedCodeAction:=False)
Await TestRenameTypeToMatchFileAsync(code, expectedCodeAction:=False)
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)>
Public Async Function MoreThanOneTypeInFile() As Task
Dim code =
<File>
[||]Class Class1
End Class
Class Class2
End Class
</File>
Await TestRenameFileToMatchTypeAsync(code, expectedCodeAction:=False)
Await TestRenameTypeToMatchFileAsync(code, expectedCodeAction:=False)
End Function
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册