|
// 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.
using System.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.MoveStaticMembers;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities.MoveStaticMembers;
using Roslyn.Test.Utilities;
using Xunit;
using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeRefactoringVerifier<
Microsoft.CodeAnalysis.CSharp.CodeRefactorings.MoveStaticMembers.CSharpMoveStaticMembersRefactoringProvider>;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.MoveStaticMembers;
[UseExportProvider]
[Trait(Traits.Feature, Traits.Features.CodeActionsMoveStaticMembers)]
public class CSharpMoveStaticMembersTests
{
private static readonly TestComposition s_testServices = FeaturesTestCompositions.Features.AddParts(typeof(TestMoveStaticMembersService));
#region Perform New Type Action From Options
[Fact]
public async Task TestMoveField()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Field = 1;
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestField");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestField = 1;
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveProperty()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Property { get; set; }
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestProperty");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestProperty { get; set; }
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveEvent()
{
var initialMarkup = @"
using System;
namespace TestNs1
{
public class Class1
{
public static event EventHandler Test[||]Event;
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestEvent");
var expectedResult1 = @"
using System;
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"using System;
namespace TestNs1
{
internal static class Class1Helpers
{
public static event EventHandler TestEvent;
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethod()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveExtensionMethod()
{
var initialMarkup = @"
namespace TestNs1
{
public static class Class1
{
public static int Test[||]Method(this Other other)
{
return other.OtherInt + 2;
}
}
public class Other
{
public int OtherInt;
public Other()
{
OtherInt = 5;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public static class Class1
{
}
public class Other
{
public int OtherInt;
public Other()
{
OtherInt = 5;
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod(this Other other)
{
return other.OtherInt + 2;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveConstField()
{
// const is static so we should work here
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public const int Test[||]Field = 1;
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestField");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public const int TestField = 1;
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveNothing()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray<string>.Empty;
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodWithTrivia()
{
var initialMarkup = @"
namespace TestNs1
{
// some comment we don't want to move
public class Class1
{
// some comment we want to move
public static int Test[||]Method()
{
return 0;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
// some comment we don't want to move
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
// some comment we want to move
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMultipleMethods()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static bool TestMethodBool()
{
return false;
}
public static int Test[||]MethodInt()
{
return 0;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethodInt", "TestMethodBool");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static bool TestMethodBool()
{
return false;
}
public static int TestMethodInt()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveSingleMethodFromMultiple()
{
// move the method that this was not triggered on
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]MethodInt()
{
return 0;
}
public static bool TestMethodBool()
{
return false;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethodBool");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
public static int TestMethodInt()
{
return 0;
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static bool TestMethodBool()
{
return false;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveOneOfEach()
{
var initialMarkup = @"
using System;
namespace TestNs1
{
public class Class1
{
public static int TestField;
public static bool TestProperty { get; set; }
public static event EventHandler TestEvent;
public static int Test[||]Method()
{
return 0;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create(
"TestMethod",
"TestField",
"TestProperty",
"TestEvent");
var expectedResult1 = @"
using System;
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"using System;
namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestField;
public static bool TestProperty { get; set; }
public static event EventHandler TestEvent;
public static int Test[||]Method()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestInNestedClass()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public class NestedClass1
{
public static int Test[||]Field = 1;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestField");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
public class NestedClass1
{
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestField = 1;
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestInNestedNamespace()
{
// collapse the namespaces in the new file
var initialMarkup = @"
namespace TestNs1
{
namespace InnerNs
{
public class Class1
{
public static int Test[||]Field = 1;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestField");
var expectedResult1 = @"
namespace TestNs1
{
namespace InnerNs
{
public class Class1
{
}
}
}";
var expectedResult2 = @"namespace TestNs1.InnerNs
{
internal static class Class1Helpers
{
public static int TestField = 1;
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveFieldNoNamespace()
{
var initialMarkup = @"
public class Class1
{
public static int Test[||]Field = 1;
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestField");
var expectedResult1 = @"
public class Class1
{
}";
var expectedResult2 = @"internal static class Class1Helpers
{
public static int TestField = 1;
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveFieldNewNamespace()
{
var initialMarkup = @"
public class Class1
{
public static int Test[||]Field = 1;
}";
var selectedDestinationName = "NewNs.Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestField");
var expectedResult1 = @"
public class Class1
{
}";
var expectedResult2 = @"namespace NewNs
{
internal static class Class1Helpers
{
public static int TestField = 1;
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodWithNamespacedSelectedDestination()
{
// in the case that we have an extra namespace in the destination name
// we append it on to the old type's namespace
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
}";
var selectedDestinationName = "ExtraNs.Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1.ExtraNs
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodFileScopedNamespace()
{
// We still keep normal namespacing rules in the new file
var initialMarkup = @"
namespace TestNs1;
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1;
public class Class1
{
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await new Test(selectedDestinationName, selectedMembers, newFileName)
{
TestCode = initialMarkup,
FixedState =
{
Sources =
{
expectedResult1,
(newFileName, expectedResult2)
}
},
LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp10
}.RunAsync().ConfigureAwait(false);
}
[Fact]
public async Task TestMoveGenericMethod()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static T Test[||]Method<T>(T item)
{
return item;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static T TestMethod<T>(T item)
{
return item;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodWithGenericClass()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1<T>
{
public static T Test[||]Method(T item)
{
return item;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1<T>
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers<T>
{
public static T Test[||]Method(T item)
{
return item;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodAndRefactorUsage()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
public class Class2
{
public static int TestMethod2()
{
return Class1.TestMethod();
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
public class Class2
{
public static int TestMethod2()
{
return Class1Helpers.TestMethod();
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodAndRefactorUsageWithTrivia()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
public class Class2
{
public static int TestMethod2()
{
// keep this comment, and the random spaces here
return Class1. TestMethod( );
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
public class Class2
{
public static int TestMethod2()
{
// keep this comment, and the random spaces here
return Class1Helpers. TestMethod( );
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodAndRefactorSourceUsage()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
public static int TestMethod2()
{
return TestMethod();
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
public static int TestMethod2()
{
return Class1Helpers.TestMethod();
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveFieldAndRefactorSourceUsage()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Field = 0;
public static int TestMethod2()
{
return TestField;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestField");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
public static int TestMethod2()
{
return Class1Helpers.TestField;
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestField = 0;
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMovePropertyAndRefactorSourceUsage()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
private static int _testProperty;
public static int Test[||]Property
{
get => _testProperty;
set
{
_testProperty = value;
}
}
public static int TestMethod2()
{
return TestProperty;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestProperty", "_testProperty");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
public static int TestMethod2()
{
return Class1Helpers.TestProperty;
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
private static int _testProperty;
public static int Test[||]Property
{
get => _testProperty;
set
{
_testProperty = value;
}
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveGenericMethodAndRefactorImpliedUsage()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static T Test[||]Method<T>(T item)
{
return item;
}
}
public class Class2
{
public static int TestMethod2()
{
return Class1.TestMethod(5);
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
public class Class2
{
public static int TestMethod2()
{
return Class1Helpers.TestMethod(5);
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static T TestMethod<T>(T item)
{
return item;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveGenericMethodAndRefactorUsage()
{
var initialMarkup = @"
using System;
namespace TestNs1
{
public class Class1
{
public static Type Test[||]Method<T>()
{
return typeof(T);
}
}
public class Class2
{
public static Type TestMethod2()
{
return Class1.TestMethod<int>();
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
using System;
namespace TestNs1
{
public class Class1
{
}
public class Class2
{
public static Type TestMethod2()
{
return Class1Helpers.TestMethod<int>();
}
}
}";
var expectedResult2 = @"using System;
namespace TestNs1
{
internal static class Class1Helpers
{
public static Type TestMethod<T>()
{
return typeof(T);
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodFromGenericClassAndRefactorUsage()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1<T>
{
public static T TestGeneric { get; set; }
public static T Test[||]Method()
{
return TestGeneric;
}
}
public class Class2
{
public static int TestMethod2()
{
return Class1<int>.TestMethod();
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod", "TestGeneric");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1<T>
{
}
public class Class2
{
public static int TestMethod2()
{
return Class1Helpers<int>.TestMethod();
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers<T>
{
public static T TestGeneric { get; set; }
public static T TestMethod()
{
return TestGeneric;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodFromGenericClassAndRefactorPartialTypeArgUsage()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1<T1, T2, T3>
where T1 : new()
{
public static T1 Test[||]Method()
{
return new T1();
}
public static T2 TestGeneric2 { get; set; }
public T3 TestGeneric3 { get; set; }
}
public class Class2
{
public static int TestMethod2()
{
return Class1<int, string, double>.TestMethod();
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1<T1, T2, T3>
where T1 : new()
{
public static T2 TestGeneric2 { get; set; }
public T3 TestGeneric3 { get; set; }
}
public class Class2
{
public static int TestMethod2()
{
return Class1Helpers<int>.TestMethod();
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers<T1> where T1 : new()
{
public static T1 TestMethod()
{
return new T1();
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodAndRefactorUsageDifferentNamespace()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
}
namespace TestNs2
{
using TestNs1;
public class Class2
{
public static int TestMethod2()
{
return Class1.TestMethod();
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}
namespace TestNs2
{
using TestNs1;
public class Class2
{
public static int TestMethod2()
{
return Class1Helpers.TestMethod();
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodAndRefactorUsageNewNamespace()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
public class Class2
{
public static int TestMethod2()
{
return Class1.TestMethod();
}
}
}";
var selectedDestinationName = "ExtraNs.Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
using TestNs1.ExtraNs;
namespace TestNs1
{
public class Class1
{
}
public class Class2
{
public static int TestMethod2()
{
return Class1Helpers.TestMethod();
}
}
}";
var expectedResult2 = @"namespace TestNs1.ExtraNs
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodAndRefactorUsageSeparateFile()
{
var initialMarkup1 = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
}";
var initialMarkup2 = @"
using TestNs1;
public class Class2
{
public static int TestMethod2()
{
return Class1.TestMethod();
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult3 = @"
using TestNs1;
public class Class2
{
public static int TestMethod2()
{
return Class1Helpers.TestMethod();
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await new Test(selectedDestinationName, selectedMembers, newFileName)
{
TestState =
{
Sources =
{
initialMarkup1,
initialMarkup2
}
},
FixedState =
{
Sources =
{
expectedResult1,
expectedResult3,
(newFileName, expectedResult2)
}
}
}.RunAsync().ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodAndRefactorClassAlias()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
}
namespace TestNs2
{
using C1 = TestNs1.Class1;
class Class2
{
public static int TestMethod2()
{
return C1.TestMethod();
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}
namespace TestNs2
{
using TestNs1;
using C1 = TestNs1.Class1;
class Class2
{
public static int TestMethod2()
{
return Class1Helpers.TestMethod();
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodAndRefactorNamespaceAlias()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
}
namespace TestNs2
{
using C1 = TestNs1;
class Class2
{
public static int TestMethod2()
{
return C1.Class1.TestMethod();
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}
namespace TestNs2
{
using TestNs1;
using C1 = TestNs1;
class Class2
{
public static int TestMethod2()
{
return Class1Helpers.TestMethod();
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodAndRefactorConflictingName()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int F[||]oo()
{
return 0;
}
}
}
namespace TestNs2
{
using TestNs1;
class Class2
{
class Class1Helpers
{
public static int Foo()
{
return 1;
}
}
public static int TestMethod2()
{
return Class1.Foo() + Class1Helpers.Foo();
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("Foo");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}
namespace TestNs2
{
using TestNs1;
class Class2
{
class Class1Helpers
{
public static int Foo()
{
return 1;
}
}
public static int TestMethod2()
{
return TestNs1.Class1Helpers.Foo() + Class1Helpers.Foo();
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int Foo()
{
return 0;
}
}
}";
await new Test(selectedDestinationName, selectedMembers, newFileName)
{
TestCode = initialMarkup,
FixedState =
{
Sources =
{
expectedResult1,
(newFileName, expectedResult2)
}
},
// the test parser thinks "TestNs1.Class1Helpers" is a member access expression
// but we made a qualified name. The text should still be the same
CodeActionValidationMode = Testing.CodeActionValidationMode.None
}.RunAsync().ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodAndRefactorQualifiedName()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
}
namespace TestNs2
{
class Class2
{
public static int TestMethod2()
{
return TestNs1.Class1.TestMethod();
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
using TestNs1;
namespace TestNs1
{
public class Class1
{
}
}
namespace TestNs2
{
class Class2
{
public static int TestMethod2()
{
return Class1Helpers.TestMethod();
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodAndRefactorStaticUsing()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
}
namespace TestNs2
{
using static TestNs1.Class1;
class Class2
{
public static int TestMethod2()
{
return TestMethod();
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}
namespace TestNs2
{
using TestNs1;
using static TestNs1.Class1;
class Class2
{
public static int TestMethod2()
{
return Class1Helpers.TestMethod();
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodAndRefactorNamespaceAliasWithExtraNamespace()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
}
namespace TestNs2
{
using C1 = TestNs1;
class Class2
{
public static int TestMethod2()
{
return C1.Class1.TestMethod();
}
}
}";
var selectedDestinationName = "ExtraNs.Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}
namespace TestNs2
{
using TestNs1.ExtraNs;
using C1 = TestNs1;
class Class2
{
public static int TestMethod2()
{
return Class1Helpers.TestMethod();
}
}
}";
var expectedResult2 = @"namespace TestNs1.ExtraNs
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveExtensionMethodDoNotRefactor()
{
var initialMarkup = @"
namespace TestNs1
{
public static class Class1
{
public static int Test[||]Method(this Other other)
{
return other.OtherInt + 2;
}
}
public class Class2
{
public int GetOtherInt()
{
var other = new Other();
return other.TestMethod();
}
}
public class Other
{
public int OtherInt;
public Other()
{
OtherInt = 5;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public static class Class1
{
}
public class Class2
{
public int GetOtherInt()
{
var other = new Other();
return other.TestMethod();
}
}
public class Other
{
public int OtherInt;
public Other()
{
OtherInt = 5;
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod(this Other other)
{
return other.OtherInt + 2;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveExtensionMethodRefactorImports()
{
var initialMarkup = @"
namespace TestNs1
{
using TestNs2;
public static class Class1
{
public static int Test[||]Method(this Other other)
{
return other.OtherInt + 2;
}
}
}
namespace TestNs2
{
using TestNs1;
public class Class2
{
public int GetOtherInt()
{
var other = new Other();
return other.TestMethod();
}
}
public class Other
{
public int OtherInt;
public Other()
{
OtherInt = 5;
}
}
}";
var selectedDestinationName = "ExtraNs.Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
using TestNs2;
public static class Class1
{
}
}
namespace TestNs2
{
using TestNs1;
using TestNs1.ExtraNs;
public class Class2
{
public int GetOtherInt()
{
var other = new Other();
return other.TestMethod();
}
}
public class Other
{
public int OtherInt;
public Other()
{
OtherInt = 5;
}
}
}";
var expectedResult2 = @"using TestNs2;
namespace TestNs1.ExtraNs
{
internal static class Class1Helpers
{
public static int TestMethod(this Other other)
{
return other.OtherInt + 2;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveExtensionMethodRefactorMultipleImports()
{
var initialMarkup = @"
namespace TestNs1
{
using TestNs2;
public static class Class1
{
public static int Test[||]Method(this Other other)
{
return other.OtherInt + 2;
}
}
}
namespace TestNs2
{
using TestNs1;
public class Class2
{
public int GetOtherInt()
{
var other = new Other();
return other.TestMethod();
}
public int GetOtherInt2()
{
var other = new Other();
return other.TestMethod();
}
}
public class Other
{
public int OtherInt;
public Other()
{
OtherInt = 5;
}
}
}";
var selectedDestinationName = "ExtraNs.Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
using TestNs2;
public static class Class1
{
}
}
namespace TestNs2
{
using TestNs1;
using TestNs1.ExtraNs;
public class Class2
{
public int GetOtherInt()
{
var other = new Other();
return other.TestMethod();
}
public int GetOtherInt2()
{
var other = new Other();
return other.TestMethod();
}
}
public class Other
{
public int OtherInt;
public Other()
{
OtherInt = 5;
}
}
}";
var expectedResult2 = @"using TestNs2;
namespace TestNs1.ExtraNs
{
internal static class Class1Helpers
{
public static int TestMethod(this Other other)
{
return other.OtherInt + 2;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodFromStaticClass()
{
var initialMarkup = @"
namespace TestNs1
{
public static class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public static class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodRetainFileBanner()
{
var initialMarkup = @"// Here is an example of a license or something
// we would want to keep at the top of a file
namespace TestNs1
{
public static class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"// Here is an example of a license or something
// we would want to keep at the top of a file
namespace TestNs1
{
public static class Class1
{
}
}";
var expectedResult2 = @"// Here is an example of a license or something
// we would want to keep at the top of a file
namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
#endregion
#region Perform Existing Type Action From Options
[Fact]
public async Task TestMoveFieldToExistingType()
{
var initialSourceMarkup = @"
public class Class1
{
public static int Test[||]Field = 1;
}";
var initialDestinationMarkup = @"
public class Class1Helpers
{
}";
var selectedDestinationName = "Class1Helpers";
var selectedMembers = ImmutableArray.Create("TestField");
var fixedSourceMarkup = @"
public class Class1
{
}";
var fixedDestinationMarkup = @"
public class Class1Helpers
{
public static int TestField = 1;
}";
await TestMovementExistingFileAsync(
initialSourceMarkup,
initialDestinationMarkup,
fixedSourceMarkup,
fixedDestinationMarkup,
selectedMembers,
selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMovePropertyToExistingType()
{
var initialSourceMarkup = @"
public class Class1
{
public static int Test[||]Property { get; set; }
}";
var initialDestinationMarkup = @"
public class Class1Helpers
{
}";
var selectedDestinationName = "Class1Helpers";
var selectedMembers = ImmutableArray.Create("TestProperty");
var fixedSourceMarkup = @"
public class Class1
{
}";
var fixedDestinationMarkup = @"
public class Class1Helpers
{
public static int TestProperty { get; set; }
}";
await TestMovementExistingFileAsync(
initialSourceMarkup,
initialDestinationMarkup,
fixedSourceMarkup,
fixedDestinationMarkup,
selectedMembers,
selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveEventToExistingType()
{
var initialSourceMarkup = @"
using System;
public class Class1
{
public static event EventHandler Test[||]Event;
}";
var initialDestinationMarkup = @"
public class Class1Helpers
{
}";
var selectedDestinationName = "Class1Helpers";
var selectedMembers = ImmutableArray.Create("TestEvent");
var fixedSourceMarkup = @"
using System;
public class Class1
{
}";
var fixedDestinationMarkup = @"
using System;
public class Class1Helpers
{
public static event EventHandler TestEvent;
}";
await TestMovementExistingFileAsync(
initialSourceMarkup,
initialDestinationMarkup,
fixedSourceMarkup,
fixedDestinationMarkup,
selectedMembers,
selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodToExistingType()
{
var initialSourceMarkup = @"
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}";
var initialDestinationMarkup = @"
public class Class1Helpers
{
}";
var selectedDestinationName = "Class1Helpers";
var selectedMembers = ImmutableArray.Create("TestMethod");
var fixedSourceMarkup = @"
public class Class1
{
}";
var fixedDestinationMarkup = @"
public class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}";
await TestMovementExistingFileAsync(
initialSourceMarkup,
initialDestinationMarkup,
fixedSourceMarkup,
fixedDestinationMarkup,
selectedMembers,
selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveExtensionMethodToExistingType()
{
var initialSourceMarkup = @"
public static class Class1
{
public static int Test[||]Method(this Other other)
{
return other.OtherInt + 2;
}
}
public class Other
{
public int OtherInt;
public Other()
{
OtherInt = 5;
}
}";
var initialDestinationMarkup = @"
public static class Class1Helpers
{
}";
var selectedDestinationName = "Class1Helpers";
var selectedMembers = ImmutableArray.Create("TestMethod");
var fixedSourceMarkup = @"
public static class Class1
{
}
public class Other
{
public int OtherInt;
public Other()
{
OtherInt = 5;
}
}";
var fixedDestinationMarkup = @"
public static class Class1Helpers
{
public static int TestMethod(this Other other)
{
return other.OtherInt + 2;
}
}";
await TestMovementExistingFileAsync(
initialSourceMarkup,
initialDestinationMarkup,
fixedSourceMarkup,
fixedDestinationMarkup,
selectedMembers,
selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveConstFieldToExistingType()
{
var initialSourceMarkup = @"
public class Class1
{
public const int Test[||]Field = 1;
}";
var initialDestinationMarkup = @"
public class Class1Helpers
{
}";
var selectedDestinationName = "Class1Helpers";
var selectedMembers = ImmutableArray.Create("TestField");
var fixedSourceMarkup = @"
public class Class1
{
}";
var fixedDestinationMarkup = @"
public class Class1Helpers
{
public const int TestField = 1;
}";
await TestMovementExistingFileAsync(
initialSourceMarkup,
initialDestinationMarkup,
fixedSourceMarkup,
fixedDestinationMarkup,
selectedMembers,
selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodToExistingTypeWithNamespace()
{
var initialSourceMarkup = @"
namespace TestNs
{
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}
}";
var initialDestinationMarkup = @"
namespace TestNs
{
public class Class1Helpers
{
}
}";
var selectedDestinationName = "TestNs.Class1Helpers";
var selectedMembers = ImmutableArray.Create("TestMethod");
var fixedSourceMarkup = @"
namespace TestNs
{
public class Class1
{
}
}";
var fixedDestinationMarkup = @"
namespace TestNs
{
public class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementExistingFileAsync(
initialSourceMarkup,
initialDestinationMarkup,
fixedSourceMarkup,
fixedDestinationMarkup,
selectedMembers,
selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodToExistingTypeWithNewNamespace()
{
var initialSourceMarkup = @"
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}";
var initialDestinationMarkup = @"
namespace TestNs
{
public class Class1Helpers
{
}
}";
var selectedDestinationName = "TestNs.Class1Helpers";
var selectedMembers = ImmutableArray.Create("TestMethod");
var fixedSourceMarkup = @"
public class Class1
{
}";
var fixedDestinationMarkup = @"
namespace TestNs
{
public class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementExistingFileAsync(
initialSourceMarkup,
initialDestinationMarkup,
fixedSourceMarkup,
fixedDestinationMarkup,
selectedMembers,
selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodToExistingTypeRefactorSourceUsage()
{
var initialSourceMarkup = @"
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
public static int TestMethod2()
{
return TestMethod();
}
}";
var initialDestinationMarkup = @"
public class Class1Helpers
{
}";
var selectedDestinationName = "Class1Helpers";
var selectedMembers = ImmutableArray.Create("TestMethod");
var fixedSourceMarkup = @"
public class Class1
{
public static int TestMethod2()
{
return Class1Helpers.TestMethod();
}
}";
var fixedDestinationMarkup = @"
public class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}";
await TestMovementExistingFileAsync(
initialSourceMarkup,
initialDestinationMarkup,
fixedSourceMarkup,
fixedDestinationMarkup,
selectedMembers,
selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestMoveMethodToExistingTypeRefactorDestinationUsage()
{
var initialSourceMarkup = @"
public class Class1
{
public static int Test[||]Method()
{
return 0;
}
}";
var initialDestinationMarkup = @"
public class Class1Helpers
{
public static int TestMethod2()
{
return Class1.TestMethod();
}
}";
var selectedDestinationName = "Class1Helpers";
var selectedMembers = ImmutableArray.Create("TestMethod");
var fixedSourceMarkup = @"
public class Class1
{
}";
var fixedDestinationMarkup = @"
public class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
public static int TestMethod2()
{
return Class1Helpers.TestMethod();
}
}";
await TestMovementExistingFileAsync(
initialSourceMarkup,
initialDestinationMarkup,
fixedSourceMarkup,
fixedDestinationMarkup,
selectedMembers,
selectedDestinationName).ConfigureAwait(false);
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/66734")]
public async Task TestMoveMethodToExistingTypeInSameFile()
{
var initialSourceMarkup = """
public static class WorkflowTypes
{
public const string FirstType = "firstType";
}
public static class WorkflowValidations
{
private static readonly System.Collections.Generic.List<string> validWorkflowTypes = new System.Collections.Generic.List<string>()
{
"firstType"
};
// Moving this method and above dependency into WorkflowTypes static class
public static bool IsValid[||]WorkflowType(this string workflowType) => validWorkflowTypes.Contains(workflowType);
}
""";
var selectedDestinationName = "WorkflowTypes";
var selectedMembers = ImmutableArray.Create("IsValidWorkflowType", "validWorkflowTypes");
var fixedSourceMarkup = """
public static class WorkflowTypes
{
public const string FirstType = "firstType";
private static readonly System.Collections.Generic.List<string> validWorkflowTypes = new System.Collections.Generic.List<string>()
{
"firstType"
};
// Moving this method and above dependency into WorkflowTypes static class
public static bool IsValidWorkflowType(this string workflowType) => validWorkflowTypes.Contains(workflowType);
}
public static class WorkflowValidations
{
}
""";
await TestMovementExistingFileAsync(
initialSourceMarkup,
// We're testing a move inside the same file, so just use an empty destination.
initialDestinationMarkup: string.Empty,
fixedSourceMarkup,
fixedDestinationMarkup: string.Empty,
selectedMembers,
selectedDestinationName).ConfigureAwait(false);
}
#endregion
#region Selections and caret position
[Fact]
public async Task TestSelectInMethodParens()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int TestMethod([||])
{
return 0;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectWholeFieldDeclaration()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
[|public static int TestField = 1;|]
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestField");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestField = 1;
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectBeforeKeywordOfDeclaration()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
[||]public static int TestField = 1;
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestField");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestField = 1;
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectInKeyWordOfDeclaration1()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
pub[||]lic static int TestField = 1;
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestField");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestField = 1;
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectInKeyWordOfDeclaration2()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public st[||]atic int TestField = 1;
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestField");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestField = 1;
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectInTypeIdentifierMethodDeclaration()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static i[||]nt TestMethod()
{
return 0;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestMethod");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestMethod()
{
return 0;
}
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectInFieldInitializerAfterSemicolon()
{
// However, a semicolon after the initializer is still considered a declaration
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int TestField = 1;[||]
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("TestField");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int TestField = 1;
}
}";
await TestMovementNewFileAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectInMultipleFieldIdentifiers()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
[|public static int Goo = 10, Foo = 9;|]
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("Goo", "Foo");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int Goo = 10;
public static int Foo = 9;
}
}";
await TestMovementNewFileWithSelectionAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectMultipleMembers1()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
[|public static int Goo = 10, Foo = 9;
public static int DoSomething()
{
return 5;
}|]
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("Goo", "Foo", "DoSomething");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int Goo = 10;
public static int Foo = 9;
public static int DoSomething()
{
return 5;
}
}
}";
await TestMovementNewFileWithSelectionAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectMultipleMembers2()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int DoSomething()
{
return [|5;
}
public static int Goo = 10, Foo = 9;|]
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("Goo", "Foo");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
public static int DoSomething()
{
return 5;
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int Goo = 10;
public static int Foo = 9;
}
}";
await TestMovementNewFileWithSelectionAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectMultipleMembers3()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Go[|o = 10, Foo = 9;
public static int DoSometh|]ing()
{
return 5;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("Goo", "Foo", "DoSomething");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int Goo = 10;
public static int Foo = 9;
public static int DoSomething()
{
return 5;
}
}
}";
await TestMovementNewFileWithSelectionAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectMultipleMembers4()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int Goo = 10, F[|oo = 9;
public static in|]t DoSomething()
{
return 5;
}
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("Foo");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
public static int Goo = 10;
public static int DoSomething()
{
return 5;
}
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int Foo = 9;
}
}";
await TestMovementNewFileWithSelectionAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectOneOfMultipleFieldIdentifiers()
{
// However, a semicolon after the initializer is still considered a declaration
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int G[||]oo = 10, Foo = 9;
}
}";
var selectedDestinationName = "Class1Helpers";
var newFileName = "Class1Helpers.cs";
var selectedMembers = ImmutableArray.Create("Goo");
var expectedResult1 = @"
namespace TestNs1
{
public class Class1
{
public static int Foo = 9;
}
}";
var expectedResult2 = @"namespace TestNs1
{
internal static class Class1Helpers
{
public static int Goo = 10;
}
}";
await TestMovementNewFileWithSelectionAsync(initialMarkup, expectedResult1, expectedResult2, newFileName, selectedMembers, selectedDestinationName).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectInTypeIdentifierOfFieldDeclaration_NoAction()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static i[||]nt TestField = 1;
}
}";
await TestNoRefactoringAsync(initialMarkup).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectInFieldInitializerEquals_NoAction()
{
// The initializer isn't a member declaration
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int TestField =[||] 1;
}
}";
await TestNoRefactoringAsync(initialMarkup).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectMethodBody_NoAction()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int TestMethod()
{
retu[||]rn 0;
}
}
}";
await TestNoRefactoringAsync(initialMarkup).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectMethodBracket_NoAction()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int TestMethod()
[|{|]
return 0;
}
}
}";
await TestNoRefactoringAsync(initialMarkup).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectMalformedMethod_NoAction()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public st[||] {|CS1519:int|} TestMethod()
{
return 0;
}
}
}";
await new Test("", ImmutableArray<string>.Empty, "")
{
TestCode = initialMarkup,
}.RunAsync().ConfigureAwait(false);
}
[Fact]
public async Task TestSelectMalformedField_NoAction1()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public st[||] {|CS1519:int|} TestField = 0;
}
}";
await new Test("", ImmutableArray<string>.Empty, "")
{
TestCode = initialMarkup,
}.RunAsync().ConfigureAwait(false);
}
[Fact]
public async Task TestSelectMalformedField_NoAction2()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public st [|{|CS1519:int|} Test|]Field = 0;
}
}";
await new Test("", ImmutableArray<string>.Empty, "")
{
TestCode = initialMarkup,
}.RunAsync().ConfigureAwait(false);
}
[Fact]
public async Task TestSelectMalformedField_NoAction3()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
[|public st {|CS1519:int|} TestField = 0;|]
}
}";
await new Test("", ImmutableArray<string>.Empty, "")
{
TestCode = initialMarkup,
}.RunAsync().ConfigureAwait(false);
}
[Fact]
public async Task TestSelectMalformedField_NoAction4()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
[|publicc {|CS1585:static|} int TestField = 0;|]
}
}";
await new Test("", ImmutableArray<string>.Empty, "")
{
TestCode = initialMarkup,
}.RunAsync().ConfigureAwait(false);
}
[Fact]
public async Task TestSelectPropertyBody_NoAction()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public static int TestProperty { get; [||]set; }
}
}";
await TestNoRefactoringAsync(initialMarkup).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectNonStaticProperty_NoAction()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
public int Test[||]Property { get; set; }
}
}";
await TestNoRefactoringAsync(initialMarkup).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectStaticConstructor1_NoAction()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
[|static Class1()|]
{
}
}
}";
await TestNoRefactoringAsync(initialMarkup).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectStaticConstructor2_NoAction()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
static Cl[||]ass1()
{
}
}
}";
await TestNoRefactoringAsync(initialMarkup).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectOperator_NoAction()
{
var initialMarkup = @"
namespace TestNs1
{
public class Class1
{
[|public static Class1 operator +(Class1 a, Class1 b)|]
{
return new Class1();
}
}
}";
await TestNoRefactoringAsync(initialMarkup).ConfigureAwait(false);
}
[Fact]
public async Task TestSelectTopLevelStatement_NoAction1()
{
var initialMarkup = @"
using System;
[||]Console.WriteLine(5);
";
await new Test("", ImmutableArray<string>.Empty, "")
{
TestCode = initialMarkup,
LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp10,
TestState =
{
OutputKind = OutputKind.ConsoleApplication
},
}.RunAsync().ConfigureAwait(false);
}
[Fact]
public async Task TestSelectTopLevelStatement_NoAction2()
{
var initialMarkup = @"
using System;
[|Console.WriteLine(5);|]
";
await new Test("", ImmutableArray<string>.Empty, "")
{
TestCode = initialMarkup,
LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp10,
TestState =
{
OutputKind = OutputKind.ConsoleApplication
},
}.RunAsync().ConfigureAwait(false);
}
[Fact]
public async Task TestSelectTopLevelLocalFunction_NoAction()
{
var initialMarkup = @"
DoSomething();
static int Do[||]Something()
{
return 5;
}
";
await new Test("", ImmutableArray<string>.Empty, "")
{
TestCode = initialMarkup,
LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp10,
TestState =
{
OutputKind = OutputKind.ConsoleApplication
},
}.RunAsync().ConfigureAwait(false);
}
#endregion
private class Test : VerifyCS.Test
{
public Test(
string destinationType,
ImmutableArray<string> selection,
string? destinationName,
bool testPreselection = false,
bool createNew = true)
{
_destinationType = destinationType;
_selection = selection;
_destinationName = destinationName;
_testPreselection = testPreselection;
_createNew = createNew;
}
private readonly string _destinationType;
private readonly ImmutableArray<string> _selection;
private readonly string? _destinationName;
private readonly bool _createNew;
private readonly bool _testPreselection;
protected override Task<Workspace> CreateWorkspaceImplAsync()
{
var hostServices = s_testServices.GetHostServices();
var workspace = new AdhocWorkspace(hostServices);
var testOptionsService = (TestMoveStaticMembersService)workspace.Services.GetRequiredService<IMoveStaticMembersOptionsService>();
testOptionsService.DestinationName = _destinationType;
testOptionsService.SelectedMembers = _selection;
testOptionsService.Filename = _destinationName;
testOptionsService.CreateNew = _createNew;
testOptionsService.ExpectedPrecheckedMembers = _testPreselection ? _selection : ImmutableArray<string>.Empty;
return Task.FromResult<Workspace>(workspace);
}
}
private static async Task TestMovementNewFileAsync(
string initialMarkup,
string expectedSource,
string expectedNewFile,
string newFileName,
ImmutableArray<string> selectedMembers,
string newTypeName)
=> await new Test(newTypeName, selectedMembers, newFileName)
{
TestCode = initialMarkup,
FixedState =
{
Sources =
{
expectedSource,
(newFileName, expectedNewFile)
}
},
}.RunAsync().ConfigureAwait(false);
private static async Task TestMovementNewFileWithSelectionAsync(
string initialMarkup,
string expectedSource,
string expectedNewFile,
string newFileName,
ImmutableArray<string> selectedMembers,
string newTypeName)
=> await new Test(newTypeName, selectedMembers, newFileName, testPreselection: true)
{
TestCode = initialMarkup,
FixedState =
{
Sources =
{
expectedSource,
(newFileName, expectedNewFile)
}
},
}.RunAsync().ConfigureAwait(false);
private static async Task TestMovementExistingFileAsync(
string intialSourceMarkup,
string initialDestinationMarkup,
string fixedSourceMarkup,
string fixedDestinationMarkup,
ImmutableArray<string> selectedMembers,
string selectedDestinationType,
string? selectedDestinationFile = null)
{
var test = new Test(selectedDestinationType, selectedMembers, selectedDestinationFile, createNew: false);
test.TestState.Sources.Add(intialSourceMarkup);
test.FixedState.Sources.Add(fixedSourceMarkup);
if (selectedDestinationFile != null)
{
test.TestState.Sources.Add((selectedDestinationFile, initialDestinationMarkup));
test.FixedState.Sources.Add((selectedDestinationFile, fixedDestinationMarkup));
}
else
{
test.TestState.Sources.Add(initialDestinationMarkup);
test.FixedState.Sources.Add(fixedDestinationMarkup);
}
await test.RunAsync().ConfigureAwait(false);
}
private static async Task TestNoRefactoringAsync(string initialMarkup)
{
await new Test("", ImmutableArray<string>.Empty, "")
{
TestCode = initialMarkup,
}.RunAsync().ConfigureAwait(false);
}
}
|