|
// 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;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.KeywordHighlighting.KeywordHighlighters;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.KeywordHighlighting;
[Trait(Traits.Feature, Traits.Features.KeywordHighlighting)]
public class SwitchStatementHighlighterTests : AbstractCSharpKeywordHighlighterTests
{
internal override Type GetHighlighterType()
=> typeof(SwitchStatementHighlighter);
[Fact]
public async Task TestExample1_OnSwitchKeyword()
{
await TestAsync(
"""
class C
{
void M()
{
{|Cursor:[|switch|]|} (i)
{
[|case|] 0:
CaseZero();
[|break|];
[|case|] 1:
CaseOne();
[|break|];
[|default|]:
CaseOthers();
[|break|];
}
}
}
""");
}
[Fact]
public async Task TestExample1_OnCaseKeyword()
{
await TestAsync(
"""
class C
{
void M()
{
[|switch|] (i)
{
{|Cursor:[|case|]|} 0:
CaseZero();
[|break|];
[|case|] 1:
CaseOne();
[|break|];
[|default|]:
CaseOthers();
[|break|];
}
}
}
""");
}
[Fact]
public async Task TestExample1_AfterCaseColon()
{
await TestAsync(
"""
class C
{
void M()
{
[|switch|] (i)
{
[|case|] 0:{|Cursor:|}
CaseZero();
[|break|];
[|case|] 1:
CaseOne();
[|break|];
[|default|]:
CaseOthers();
[|break|];
}
}
}
""");
}
[Fact]
public async Task TestExample1_NotOnCaseValue()
{
await TestAsync(
"""
class C
{
void M()
{
switch (i)
{
case {|Cursor:0|}:
CaseZero();
break;
case 1:
CaseOne();
break;
default:
CaseOthers();
break;
}
}
}
""");
}
[Fact]
public async Task TestExample1_OnBreakStatement()
{
await TestAsync(
"""
class C
{
void M()
{
[|switch|] (i)
{
[|case|] 0:
CaseZero();
{|Cursor:[|break|];|}
[|case|] 1:
CaseOne();
[|break|];
[|default|]:
CaseOthers();
[|break|];
}
}
}
""");
}
[Fact]
public async Task TestExample1_OnDefaultLabel()
{
await TestAsync(
"""
class C
{
void M()
{
[|switch|] (i)
{
[|case|] 0:
CaseZero();
[|break|];
[|case|] 1:
CaseOne();
[|break|];
{|Cursor:[|default|]:|}
CaseOthers();
[|break|];
}
}
}
""");
}
[Fact]
public async Task TestExample2_OnGotoCaseKeywords()
{
await TestAsync(
"""
class C
{
void M()
{
[|switch|] (i)
{
[|case|] 0:
CaseZero();
{|Cursor:[|goto case|]|} 1;
[|case|] 1:
CaseOne();
[|goto default|];
[|default|]:
CaseOthers();
[|break|];
}
}
}
""");
}
[Fact]
public async Task TestExample2_AfterGotoCaseSemicolon()
{
await TestAsync(
"""
class C
{
void M()
{
[|switch|] (i)
{
[|case|] 0:
CaseZero();
[|goto case|] 1;{|Cursor:|}
[|case|] 1:
CaseOne();
[|goto default|];
[|default|]:
CaseOthers();
[|break|];
}
}
}
""");
}
[Fact]
public async Task TestExample2_NotOnGotoCaseValue()
{
await TestAsync(
"""
class C
{
void M()
{
switch (i)
{
case 0:
CaseZero();
goto case {|Cursor:1|};
case 1:
CaseOne();
goto default;
default:
CaseOthers();
break;
}
}
}
""");
}
[Fact]
public async Task TestExample2_OnGotoDefaultStatement()
{
await TestAsync(
"""
class C
{
void M()
{
[|switch|] (i)
{
[|case|] 0:
CaseZero();
[|goto case|] 1;
[|case|] 1:
CaseOne();
{|Cursor:[|goto default|];|}
[|default|]:
CaseOthers();
[|break|];
}
}
}
""");
}
[Fact]
public async Task TestNestedExample1_OnSwitchKeyword()
{
await TestAsync(
"""
class C
{
void M()
{
foreach (var a in x)
{
if (a)
{
break;
}
else
{
{|Cursor:[|switch|]|} (b)
{
[|case|] 0:
while (true)
{
do
{
break;
}
while (false);
break;
}
[|break|];
}
}
for (int i = 0; i < 10; i++)
{
break;
}
}
}
}
""");
}
[Fact]
public async Task TestNestedExample1_OnCaseKeyword()
{
await TestAsync(
"""
class C
{
void M()
{
foreach (var a in x)
{
if (a)
{
break;
}
else
{
[|switch|] (b)
{
{|Cursor:[|case|]|} 0:
while (true)
{
do
{
break;
}
while (false);
break;
}
[|break|];
}
}
for (int i = 0; i < 10; i++)
{
break;
}
}
}
}
""");
}
[Fact]
public async Task TestNestedExample1_NotBeforeCaseValue()
{
await TestAsync(
"""
class C
{
void M()
{
foreach (var a in x)
{
if (a)
{
break;
}
else
{
switch (b)
{
case {|Cursor:|}0:
while (true)
{
do
{
break;
}
while (false);
break;
}
break;
}
}
for (int i = 0; i < 10; i++)
{
break;
}
}
}
}
""");
}
[Fact]
public async Task TestNestedExample1_AfterCaseColon()
{
await TestAsync(
"""
class C
{
void M()
{
foreach (var a in x)
{
if (a)
{
break;
}
else
{
[|switch|] (b)
{
[|case|] 0:{|Cursor:|}
while (true)
{
do
{
break;
}
while (false);
break;
}
[|break|];
}
}
for (int i = 0; i < 10; i++)
{
break;
}
}
}
}
""");
}
[Fact]
public async Task TestNestedExample1_OnBreakStatement()
{
await TestAsync(
"""
class C
{
void M()
{
foreach (var a in x)
{
if (a)
{
break;
}
else
{
[|switch|] (b)
{
[|case|] 0:
while (true)
{
do
{
break;
}
while (false);
break;
}
{|Cursor:[|break|];|}
}
}
for (int i = 0; i < 10; i++)
{
break;
}
}
}
}
""");
}
[Fact]
public async Task Bug3483()
{
await TestAsync(
"""
class C
{
static void M()
{
[|switch|] (2)
{
[|case|] 1:
{|Cursor:[|goto|]|}
}
}
}
""");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25039")]
public async Task TestWithUnrelatedGotoStatement_OnGotoCaseGotoKeyword()
{
await TestAsync(
"""
class C
{
void M()
{
label:
[|switch|] (i)
{
[|case|] 0:
CaseZero();
[|{|Cursor:goto|} case|] 1;
[|case|] 1:
CaseOne();
[|goto default|];
[|default|]:
CaseOthers();
goto label;
}
}
}
""");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25039")]
public async Task TestWithUnrelatedGotoStatement_OnGotoDefaultGotoKeyword()
{
await TestAsync(
"""
class C
{
void M()
{
label:
[|switch|] (i)
{
[|case|] 0:
CaseZero();
[|goto case|] 1;
[|case|] 1:
CaseOne();
[|{|Cursor:goto|} default|];
[|default|]:
CaseOthers();
goto label;
}
}
}
""");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25039")]
public async Task TestWithUnrelatedGotoStatement_NotOnGotoLabelGotoKeyword()
{
await TestAsync(
"""
class C
{
void M()
{
label:
switch (i)
{
case 0:
CaseZero();
goto case 1;
case 1:
CaseOne();
goto default;
default:
CaseOthers();
{|Cursor:goto|} label;
}
}
}
""");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25039")]
public async Task TestWithNestedStatements_OnSwitchKeyword()
{
await TestAsync(
"""
class C
{
void M()
{
{|Cursor:[|switch|]|} (i)
{
[|case|] 0:
{
CaseZero();
[|goto case|] 1;
}
[|case|] 1:
{
CaseOne();
[|goto default|];
}
[|default|]:
{
CaseOthers();
[|break|];
}
}
}
}
""");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25039")]
public async Task TestWithNestedStatements_OnBreakKeyword()
{
await TestAsync(
"""
class C
{
void M()
{
[|switch|] (i)
{
[|case|] 0:
{
CaseZero();
[|goto case|] 1;
}
[|case|] 1:
{
CaseOne();
[|goto default|];
}
[|default|]:
{
CaseOthers();
{|Cursor:[|break|]|};
}
}
}
}
""");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25039")]
public async Task TestWithGotoCaseAndBreakInsideLoop_OnSwitchKeyword()
{
await TestAsync(
"""
class C
{
void M()
{
{|Cursor:[|switch|]|} (true)
{
[|case|] true:
while (true)
{
[|goto case|] true;
break;
switch (true)
{
case true:
goto case true;
break;
}
}
}
}
}
""");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25039")]
public async Task TestWithGotoCaseAndBreakInsideLoop_OnGotoCaseGotoKeyword()
{
await TestAsync(
"""
class C
{
void M()
{
[|switch|] (true)
{
[|case|] true:
while (true)
{
[|{|Cursor:goto|} case|] true;
break;
switch (true)
{
case true:
goto case true;
break;
}
}
}
}
}
""");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25039")]
public async Task TestWithGotoCaseAndBreakInsideLoop_NotOnLoopBreakKeyword()
{
await TestAsync(
"""
class C
{
void M()
{
switch (true)
{
case true:
while (true)
{
goto case true;
{|Cursor:break|};
switch (true)
{
case true:
goto case true;
break;
}
}
}
}
}
""");
}
[Fact]
public async Task TestWithWhenClauseAndPattern_OnSwitchKeyword()
{
await TestAsync(
"""
class C
{
void M()
{
{|Cursor:[|switch|]|} (true)
{
[|case|] true when true:
[|break|];
[|case|] bool b:
[|break|];
}
}
}
""");
}
[Fact]
public async Task TestWithWhenClauseAndPattern_NotOnWhenKeyword()
{
await TestAsync(
"""
class C
{
void M()
{
switch (true)
{
case true {|Cursor:when|} true:
break;
case bool b:
break;
}
}
}
""");
}
[Fact]
public async Task TestWithWhenClauseAndPattern_AfterWhenCaseColon()
{
await TestAsync(
"""
class C
{
void M()
{
[|switch|] (true)
{
[|case|] true when true:{|Cursor:|}
[|break|];
[|case|] bool b:
[|break|];
}
}
}
""");
}
[Fact]
public async Task TestWithWhenClauseAndPattern_AfterPatternCaseColon()
{
await TestAsync(
"""
class C
{
void M()
{
[|switch|] (true)
{
[|case|] true when true:
[|break|];
[|case|] bool b:{|Cursor:|}
[|break|];
}
}
}
""");
}
[Fact]
public async Task TestWithWhenClauseAndPattern_NotOnWhenValue()
{
await TestAsync(
"""
class C
{
void M()
{
switch (true)
{
case true when {|Cursor:true|}:
break;
case bool b:
break;
}
}
}
""");
}
[Fact]
public async Task TestWithWhenClauseAndPattern_NotOnPattern()
{
await TestAsync(
"""
class C
{
void M()
{
switch (true)
{
case true when true:
break;
case {|Cursor:bool b|}:
break;
}
}
}
""");
}
}
|