|
// 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.
#nullable disable
using System.Linq;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.CodeAnalysis.Editor.Commanding.Commands;
using Microsoft.CodeAnalysis.Editor.Implementation.Organizing;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Editor.UnitTests;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Organizing;
public class OrganizeTypeDeclarationTests : AbstractOrganizerTests
{
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
[InlineData("record class")]
[InlineData("record struct")]
public async Task TestFieldsWithoutInitializers1(string typeKind)
{
var initial =
$@"{typeKind} C {{
int A;
int B;
int C;
}}";
var final =
$@"{typeKind} C {{
int A;
int B;
int C;
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("struct")]
[InlineData("record")]
[InlineData("record class")]
[InlineData("record struct")]
public async Task TestNestedTypes(string typeKind)
{
var initial =
$@"class C {{
{typeKind} Nested1 {{ }}
{typeKind} Nested2 {{ }}
int A;
}}";
var final =
$@"class C {{
int A;
{typeKind} Nested1 {{ }}
{typeKind} Nested2 {{ }}
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestFieldsWithoutInitializers2(string typeKind)
{
var initial =
$@"{typeKind} C {{
int C;
int B;
int A;
}}";
var final =
$@"{typeKind} C {{
int A;
int B;
int C;
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
[InlineData("record struct")]
public async Task TestFieldsWithInitializers1(string typeKind)
{
var initial =
$@"{typeKind} C {{
int C = 0;
int B;
int A;
}}";
var final =
$@"{typeKind} C {{
int A;
int B;
int C = 0;
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestFieldsWithInitializers2(string typeKind)
{
var initial =
$@"{typeKind} C {{
int C = 0;
int B = 0;
int A;
}}";
var final =
$@"{typeKind} C {{
int A;
int C = 0;
int B = 0;
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestEventFieldDeclaration(string typeKind)
{
var initial =
$@"{typeKind} C {{
public void Goo() {{}}
public event EventHandler MyEvent;
}}";
var final =
$@"{typeKind} C {{
public event EventHandler MyEvent;
public void Goo() {{}}
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestEventDeclaration(string typeKind)
{
var initial =
$@"{typeKind} C {{
public void Goo() {{}}
public event EventHandler Event
{{
remove {{ }}
add {{ }}
}}
public static int Property {{ get; set; }}
}}";
var final =
$@"{typeKind} C {{
public static int Property {{ get; set; }}
public event EventHandler Event
{{
remove {{ }}
add {{ }}
}}
public void Goo() {{}}
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestOperator(string typeKind)
{
var initial =
$@"{typeKind} C {{
public void Goo() {{}}
public static int operator +(Goo<T> a, int b)
{{
return 1;
}}
}}";
var final =
$@"{typeKind} C {{
public static int operator +(Goo<T> a, int b)
{{
return 1;
}}
public void Goo() {{}}
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestIndexer(string typeKind)
{
var initial =
$@"{typeKind} C {{
public void Goo() {{}}
public T this[int i]
{{
get
{{
return default(T);
}}
}}
C() {{}}
}}";
var final =
$@"{typeKind} C {{
C() {{}}
public T this[int i]
{{
get
{{
return default(T);
}}
}}
public void Goo() {{}}
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestConstructorAndDestructors(string typeKind)
{
var initial =
$@"{typeKind} C {{
public ~Goo() {{}}
enum Days {{Sat, Sun}};
public Goo() {{}}
}}";
var final =
$@"{typeKind} C {{
public Goo() {{}}
public ~Goo() {{}}
enum Days {{Sat, Sun}};
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestInterface(string typeKind)
{
var initial =
$@"{typeKind} C {{}}
interface I
{{
void Goo();
int Property {{ get; set; }}
event EventHandler Event;
}}";
var final =
$@"{typeKind} C {{}}
interface I
{{
event EventHandler Event;
int Property {{ get; set; }}
void Goo();
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestStaticInstance(string typeKind)
{
var initial =
$@"{typeKind} C {{
int A;
static int B;
int C;
static int D;
}}";
var final =
$@"{typeKind} C {{
static int B;
static int D;
int A;
int C;
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
[InlineData("record struct")]
public async Task TestAccessibility(string typeKind)
{
var initial =
$@"{typeKind} C {{
int A;
private int B;
internal int C;
protected int D;
public int E;
protected internal int F;
}}";
var final =
$@"{typeKind} C {{
public int E;
protected int D;
protected internal int F;
internal int C;
int A;
private int B;
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestStaticAccessibility(string typeKind)
{
var initial =
$@"{typeKind} C {{
int A1;
private int B1;
internal int C1;
protected int D1;
public int E1;
static int A2;
static private int B2;
static internal int C2;
static protected int D2;
static public int E2;
}}";
var final =
$@"{typeKind} C {{
public static int E2;
protected static int D2;
internal static int C2;
static int A2;
private static int B2;
public int E1;
protected int D1;
internal int C1;
int A1;
private int B1;
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestGenerics(string typeKind)
{
var initial =
$@"{typeKind} C {{
void B<X,Y>();
void B<Z>();
void B();
void A<X,Y>();
void A<Z>();
void A();
}}";
var final =
$@"{typeKind} C {{
void A();
void A<Z>();
void A<X,Y>();
void B();
void B<Z>();
void B<X,Y>();
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestInsidePPRegion(string typeKind)
{
var initial =
$@"{typeKind} C {{
#if true
int c;
int b;
int a;
#endif
}}";
var final =
$@"{typeKind} C {{
#if true
int a;
int b;
int c;
#endif
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestInsidePPRegion2(string typeKind)
{
var initial =
$@"{typeKind} C {{
#if true
int z;
int y;
int x;
#endif
#if true
int c;
int b;
int a;
#endif
}}";
var final =
$@"{typeKind} C {{
#if true
int x;
int y;
int z;
#endif
#if true
int a;
int b;
int c;
#endif
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestInsidePPRegion3(string typeKind)
{
var initial =
$@"{typeKind} C {{
int z;
int y;
#if true
int x;
int c;
#endif
int b;
int a;
}}";
var final =
$@"{typeKind} C {{
int y;
int z;
#if true
int c;
int x;
#endif
int a;
int b;
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestInsidePPRegion4(string typeKind)
{
var initial =
$@"{typeKind} C {{
int c() {{
}}
int b {{
}}
int a {{
#if true
#endif
}}
}}";
var final =
$@"{typeKind} C {{
int a {{
#if true
#endif
}}
int b {{
}}
int c() {{
}}
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestInsidePPRegion5(string typeKind)
{
var initial =
$@"{typeKind} C {{
int c() {{
}}
int b {{
}}
int a {{
#if true
#else
#endif
}}
}}";
var final =
$@"{typeKind} C {{
int a {{
#if true
#else
#endif
}}
int b {{
}}
int c() {{
}}
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestInsidePPRegion6(string typeKind)
{
var initial =
$@"{typeKind} C {{
#region
int e() {{
}}
int d() {{
}}
int c() {{
#region
}}
#endregion
int b {{
}}
int a {{
}}
#endregion
}}";
var final =
$@"{typeKind} C {{
#region
int d() {{
}}
int e() {{
}}
int c() {{
#region
}}
#endregion
int a {{
}}
int b {{
}}
#endregion
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestPinned(string typeKind)
{
var initial =
$@"{typeKind} C {{
int z() {{
}}
int y() {{
}}
int x() {{
#if true
}}
int n;
int m;
int c() {{
#endif
}}
int b() {{
}}
int a() {{
}}
}}";
var final =
$@"{typeKind} C {{
int y() {{
}}
int z() {{
}}
int x() {{
#if true
}}
int m;
int n;
int c() {{
#endif
}}
int a() {{
}}
int b() {{
}}
}}";
await CheckAsync(initial, final);
}
[Theory, Trait(Traits.Feature, Traits.Features.Organizing)]
[InlineData("class")]
[InlineData("record")]
public async Task TestSensitivity(string typeKind)
{
var initial =
$@"{typeKind} C {{
int Bb;
int B;
int bB;
int b;
int Aa;
int a;
int A;
int aa;
int aA;
int AA;
int bb;
int BB;
int bBb;
int bbB;
int あ;
int ア;
int ア;
int ああ;
int あア;
int あア;
int アあ;
int cC;
int Cc;
int アア;
int アア;
int アあ;
int アア;
int アア;
int BBb;
int BbB;
int bBB;
int BBB;
int c;
int C;
int bbb;
int Bbb;
int cc;
int cC;
int CC;
}}";
var final =
$@"{typeKind} C {{
int a;
int A;
int aa;
int aA;
int Aa;
int AA;
int b;
int B;
int bb;
int bB;
int Bb;
int BB;
int bbb;
int bbB;
int bBb;
int bBB;
int Bbb;
int BbB;
int BBb;
int BBB;
int c;
int C;
int cc;
int cC;
int cC;
int Cc;
int CC;
int ア;
int ア;
int あ;
int アア;
int アア;
int アア;
int アア;
int アあ;
int アあ;
int あア;
int あア;
int ああ;
}}";
await CheckAsync(initial, final);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537614")]
[InlineData("class")]
[InlineData("record")]
public async Task TestWhitespaceBetweenMethods1(string typeKind)
{
var initial =
$@"{typeKind} Program
{{
void B()
{{
}}
void A()
{{
}}
}}";
var final =
$@"{typeKind} Program
{{
void A()
{{
}}
void B()
{{
}}
}}";
await CheckAsync(initial, final);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537614")]
[InlineData("class")]
[InlineData("record")]
public async Task TestWhitespaceBetweenMethods2(string typeKind)
{
var initial =
$@"{typeKind} Program
{{
void B()
{{
}}
void A()
{{
}}
}}";
var final =
$@"{typeKind} Program
{{
void A()
{{
}}
void B()
{{
}}
}}";
await CheckAsync(initial, final);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537614")]
[InlineData("class")]
[InlineData("record")]
public async Task TestWhitespaceBetweenMethods3(string typeKind)
{
var initial =
$@"{typeKind} Program
{{
void B()
{{
}}
void A()
{{
}}
}}";
var final =
$@"{typeKind} Program
{{
void A()
{{
}}
void B()
{{
}}
}}";
await CheckAsync(initial, final);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537614")]
[InlineData("class")]
[InlineData("record")]
public async Task TestWhitespaceBetweenMethods4(string typeKind)
{
var initial =
$@"{typeKind} Program
{{
void B()
{{
}}
void A()
{{
}}
}}";
var final =
$@"{typeKind} Program
{{
void A()
{{
}}
void B()
{{
}}
}}";
await CheckAsync(initial, final);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537614")]
[InlineData("class")]
[InlineData("record")]
public async Task TestWhitespaceBetweenMethods5(string typeKind)
{
var initial =
$@"{typeKind} Program
{{
void B()
{{
}}
void A()
{{
}}
}}";
var final =
$@"{typeKind} Program
{{
void A()
{{
}}
void B()
{{
}}
}}";
await CheckAsync(initial, final);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537614")]
[InlineData("class")]
[InlineData("record")]
public async Task TestWhitespaceBetweenMethods6(string typeKind)
{
var initial =
$@"{typeKind} Program
{{
void B()
{{
}}
void A()
{{
}}
}}";
var final =
$@"{typeKind} Program
{{
void A()
{{
}}
void B()
{{
}}
}}";
await CheckAsync(initial, final);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537614")]
[InlineData("class")]
[InlineData("record")]
public async Task TestMoveComments1(string typeKind)
{
var initial =
$@"{typeKind} Program
{{
// B
void B()
{{
}}
void A()
{{
}}
}}";
var final =
$@"{typeKind} Program
{{
void A()
{{
}}
// B
void B()
{{
}}
}}";
await CheckAsync(initial, final);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537614")]
[InlineData("class")]
[InlineData("record")]
public async Task TestMoveComments2(string typeKind)
{
var initial =
$@"{typeKind} Program
{{
// B
void B()
{{
}}
// A
void A()
{{
}}
}}";
var final =
$@"{typeKind} Program
{{
// A
void A()
{{
}}
// B
void B()
{{
}}
}}";
await CheckAsync(initial, final);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537614")]
[InlineData("class")]
[InlineData("record")]
public async Task TestMoveDocComments1(string typeKind)
{
var initial =
$@"{typeKind} Program
{{
/// B
void B()
{{
}}
void A()
{{
}}
}}";
var final =
$@"{typeKind} Program
{{
void A()
{{
}}
/// B
void B()
{{
}}
}}";
await CheckAsync(initial, final);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537614")]
[InlineData("class")]
[InlineData("record")]
public async Task TestMoveDocComments2(string typeKind)
{
var initial =
$@"{typeKind} Program
{{
/// B
void B()
{{
}}
void A()
{{
}}
}}";
var final =
$@"{typeKind} Program
{{
void A()
{{
}}
/// B
void B()
{{
}}
}}";
await CheckAsync(initial, final);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537614")]
[InlineData("class")]
[InlineData("record")]
public async Task TestDoNotMoveBanner(string typeKind)
{
var initial =
$@"{typeKind} Program
{{
// Banner
void B()
{{
}}
void A()
{{
}}
}}";
var final =
$@"{typeKind} Program
{{
// Banner
void A()
{{
}}
void B()
{{
}}
}}";
await CheckAsync(initial, final);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537614")]
[InlineData("class")]
[InlineData("record")]
public async Task TestDoNotMoveBanner2(string typeKind)
{
var initial =
$@"{typeKind} Program
{{
// Banner
// More banner
// Bannery stuff
void B()
{{
}}
void A()
{{
}}
}}";
var final =
$@"{typeKind} Program
{{
// Banner
// More banner
// Bannery stuff
void A()
{{
}}
void B()
{{
}}
}}";
await CheckAsync(initial, final);
}
[WpfFact]
[Trait(Traits.Feature, Traits.Features.Organizing)]
[Trait(Traits.Feature, Traits.Features.Interactive)]
public void OrganizingCommandsDisabledInSubmission()
{
using var workspace = EditorTestWorkspace.Create(XElement.Parse("""
<Workspace>
<Submission Language="C#" CommonReferences="true">
class C
{
object $$goo;
}
</Submission>
</Workspace>
"""),
workspaceKind: WorkspaceKind.Interactive,
composition: EditorTestCompositions.EditorFeaturesWpf);
// Force initialization.
workspace.GetOpenDocumentIds().Select(id => workspace.GetTestDocument(id).GetTextView()).ToList();
var textView = workspace.Documents.Single().GetTextView();
var handler = new OrganizeDocumentCommandHandler(
workspace.GetService<IThreadingContext>(),
workspace.ExportProvider.GetExportedValue<IAsynchronousOperationListenerProvider>());
var state = handler.GetCommandState(new SortAndRemoveUnnecessaryImportsCommandArgs(textView, textView.TextBuffer));
Assert.True(state.IsUnspecified);
state = handler.GetCommandState(new OrganizeDocumentCommandArgs(textView, textView.TextBuffer));
Assert.True(state.IsUnspecified);
}
}
|