|
// 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.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Remote.Testing;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Xunit;
using static Microsoft.CodeAnalysis.Editor.UnitTests.Classification.FormattedClassifications;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Classification;
public sealed partial class SyntacticClassifierTests : AbstractCSharpClassifierTests
{
protected override async Task<ImmutableArray<ClassifiedSpan>> GetClassificationSpansAsync(string code, ImmutableArray<TextSpan> spans, ParseOptions? options, TestHost testHost)
{
using var workspace = CreateWorkspace(code, options, testHost);
var document = workspace.CurrentSolution.Projects.First().Documents.First();
return await GetSyntacticClassificationsAsync(document, spans);
}
[Theory, CombinatorialData]
public async Task VarAtTypeMemberLevel(TestHost testHost)
{
await TestAsync(
"""
class C
{
var goo }
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Identifier("var"),
Field("goo"),
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestNamespace(TestHost testHost)
{
await TestAsync(
"""
namespace N
{
}
""",
testHost,
Keyword("namespace"),
Namespace("N"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestFileScopedNamespace(TestHost testHost)
{
await TestAsync(
"""
namespace N;
""",
testHost,
Keyword("namespace"),
Namespace("N"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task VarAsLocalVariableType(TestHost testHost)
{
await TestInMethodAsync("var goo = 42",
testHost,
Keyword("var"),
Local("goo"),
Operators.Equals,
Number("42"));
}
[Theory, CombinatorialData]
public async Task VarOptimisticallyColored(TestHost testHost)
{
await TestInMethodAsync("var",
testHost,
Keyword("var"));
}
[Theory, CombinatorialData]
public async Task VarNotColoredInClass(TestHost testHost)
{
await TestInClassAsync("var",
testHost,
Identifier("var"));
}
[Theory, CombinatorialData]
public async Task VarInsideLocalAndExpressions(TestHost testHost)
{
await TestInMethodAsync(
@"var var = (var)var as var;",
testHost,
Keyword("var"),
Local("var"),
Operators.Equals,
Punctuation.OpenParen,
Identifier("var"),
Punctuation.CloseParen,
Identifier("var"),
Keyword("as"),
Identifier("var"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task VarAsMethodParameter(TestHost testHost)
{
await TestAsync(
"""
class C
{
void M(var v)
{
}
}
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenParen,
Identifier("var"),
Parameter("v"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task YieldYield(TestHost testHost)
{
await TestAsync(
"""
using System.Collections.Generic;
class yield
{
IEnumerable<yield> M()
{
yield yield = new yield();
yield return yield;
}
}
""",
testHost,
Keyword("using"),
Identifier("System"),
Operators.Dot,
Identifier("Collections"),
Operators.Dot,
Identifier("Generic"),
Punctuation.Semicolon,
Keyword("class"),
Class("yield"),
Punctuation.OpenCurly,
Identifier("IEnumerable"),
Punctuation.OpenAngle,
Identifier("yield"),
Punctuation.CloseAngle,
Method("M"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Identifier("yield"),
Local("yield"),
Operators.Equals,
Keyword("new"),
Identifier("yield"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
ControlKeyword("yield"),
ControlKeyword("return"),
Identifier("yield"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task YieldYieldAsSpans(TestHost testHost)
{
await TestAsync(
"""
using System.Collections.Generic;
class yield
{
IEnumerable<yield> M()
{
[|yield yield = new yield();|]
[|yield return yield;|]
}
}
""",
testHost,
Identifier("yield"),
Local("yield"),
Operators.Equals,
Keyword("new"),
Identifier("yield"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
ControlKeyword("yield"),
ControlKeyword("return"),
Identifier("yield"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task YieldReturn(TestHost testHost)
{
await TestInMethodAsync("yield return 42",
testHost,
ControlKeyword("yield"),
ControlKeyword("return"),
Number("42"));
}
[Theory, CombinatorialData]
public async Task YieldFixed(TestHost testHost)
{
await TestInMethodAsync(
"""
yield return this.items[0]; yield break; fixed (int* i = 0) {
}
""",
testHost,
ControlKeyword("yield"),
ControlKeyword("return"),
Keyword("this"),
Operators.Dot,
Identifier("items"),
Punctuation.OpenBracket,
Number("0"),
Punctuation.CloseBracket,
Punctuation.Semicolon,
ControlKeyword("yield"),
ControlKeyword("break"),
Punctuation.Semicolon,
Keyword("fixed"),
Punctuation.OpenParen,
Keyword("int"),
Operators.Asterisk,
Local("i"),
Operators.Equals,
Number("0"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
[WorkItem("https://github.com/dotnet/roslyn/issues/40741")]
public async Task TestAwait(TestHost testHost)
{
await TestAsync(
"""
using System.Threading.Tasks;
class X
{
async Task M()
{
await M();
}
}
""",
testHost,
Keyword("using"),
Identifier("System"),
Operators.Dot,
Identifier("Threading"),
Operators.Dot,
Identifier("Tasks"),
Punctuation.Semicolon,
Keyword("class"),
Class("X"),
Punctuation.OpenCurly,
Keyword("async"),
Identifier("Task"),
Method("M"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
ControlKeyword("await"),
Identifier("M"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task PartialClass(TestHost testHost)
{
await TestAsync("public partial class Goo",
testHost,
Keyword("public"),
Keyword("partial"),
Keyword("class"),
Class("Goo"));
}
[Theory, CombinatorialData]
public async Task PartialMethod(TestHost testHost)
{
await TestInClassAsync(
"""
public partial void M()
{
}
""",
testHost,
Keyword("public"),
Keyword("partial"),
Keyword("void"),
Method("M"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
/// <summary>
/// Partial is only valid in a type declaration
/// </summary>
[Theory, CombinatorialData]
[WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/536313")]
public async Task PartialAsLocalVariableType(TestHost testHost)
{
await TestInMethodAsync(
@"partial p1 = 42;",
testHost,
Identifier("partial"),
Local("p1"),
Operators.Equals,
Number("42"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task PartialClassStructInterface(TestHost testHost)
{
await TestAsync(
"""
partial class T1
{
}
partial struct T2
{
}
partial interface T3
{
}
""",
testHost,
Keyword("partial"),
Keyword("class"),
Class("T1"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("partial"),
Keyword("struct"),
Struct("T2"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("partial"),
Keyword("interface"),
Interface("T3"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
private static readonly string[] s_contextualKeywordsOnlyValidInMethods = ["where", "from", "group", "join", "select", "into", "let", "by", "orderby", "on", "equals", "ascending", "descending"];
/// <summary>
/// Check for items only valid within a method declaration
/// </summary>
[Theory, CombinatorialData]
public async Task ContextualKeywordsOnlyValidInMethods(TestHost testHost)
{
foreach (var kw in s_contextualKeywordsOnlyValidInMethods)
{
await TestInNamespaceAsync(kw + " goo",
testHost,
Identifier(kw),
Field("goo"));
}
}
[Theory, CombinatorialData]
public async Task VerbatimStringLiterals1(TestHost testHost)
{
await TestInMethodAsync("""
@"goo"
""",
testHost,
Verbatim("""
@"goo"
"""));
}
[Theory, CombinatorialData]
public async Task VerbatimStringLiteralsUtf8_01(TestHost testHost)
{
await TestInMethodAsync(@"@""goo""u8",
testHost,
Verbatim("""
@"goo"
"""),
Keyword("u8"));
}
[Theory, CombinatorialData]
public async Task VerbatimStringLiteralsUtf8_02(TestHost testHost)
{
await TestInMethodAsync(@"@""goo""U8",
testHost,
Verbatim("""
@"goo"
"""),
Keyword("U8"));
}
/// <summary>
/// Should show up as soon as we get the @\" typed out
/// </summary>
[Theory, CombinatorialData]
public async Task VerbatimStringLiterals2(TestHost testHost)
{
await TestAsync("""
@"
""",
testHost,
Verbatim("""
@"
"""));
}
/// <summary>
/// Parser does not currently support strings of this type
/// </summary>
[Theory, CombinatorialData]
public async Task VerbatimStringLiterals3(TestHost testHost)
{
await TestAsync("""
goo @"
""",
testHost,
Identifier("goo"),
Verbatim("""
@"
"""));
}
/// <summary>
/// Uncompleted ones should span new lines
/// </summary>
[Theory, CombinatorialData]
public async Task VerbatimStringLiterals4(TestHost testHost)
{
var code = """
@" goo bar
""";
await TestAsync(code,
testHost,
Verbatim("""
@" goo bar
"""));
}
[Theory, CombinatorialData]
public async Task VerbatimStringLiterals5(TestHost testHost)
{
var code = """
@" goo bar
and
on a new line "
more stuff
""";
await TestInMethodAsync(code,
testHost,
Verbatim("""
@" goo bar
and
on a new line "
"""),
Identifier("more"),
Local("stuff"));
}
[Theory, CombinatorialData]
public async Task VerbatimStringLiteralsUtf8_03(TestHost testHost)
{
var code = """
@" goo bar
and
on a new line "u8
more stuff
""";
await TestInMethodAsync(code,
testHost,
Verbatim("""
@" goo bar
and
on a new line "
"""),
Keyword("u8"),
Identifier("more"),
Local("stuff"));
}
[Theory, CombinatorialData]
public async Task VerbatimStringLiteralsUtf8_04(TestHost testHost)
{
var code = """
@" goo bar
and
on a new line "U8
more stuff
""";
await TestInMethodAsync(code,
testHost,
Verbatim("""
@" goo bar
and
on a new line "
"""),
Keyword("U8"),
Identifier("more"),
Local("stuff"));
}
[Theory, WorkItem("https://github.com/dotnet/roslyn/issues/44423")]
[CombinatorialData]
public async Task VerbatimStringLiterals6(bool script, TestHost testHost)
{
var code = @"string s = @""""""/*"";";
var parseOptions = script ? Options.Script : null;
await TestAsync(
code,
code,
testHost,
parseOptions,
Keyword("string"),
script ? Field("s") : Local("s"),
Operators.Equals,
Verbatim(""""
@"""/*"
""""),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task VerbatimStringLiteralsUtf8_05(bool script, TestHost testHost)
{
var code = @"string s = @""""""/*""u8;";
var parseOptions = script ? Options.Script : null;
await TestAsync(
code,
code,
testHost,
parseOptions,
Keyword("string"),
script ? Field("s") : Local("s"),
Operators.Equals,
Verbatim(""""
@"""/*"
""""),
Keyword("u8"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task VerbatimStringLiteralsUtf8_06(bool script, TestHost testHost)
{
var code = @"string s = @""""""/*""u8;";
var parseOptions = script ? Options.Script : null;
await TestAsync(
code,
code,
testHost,
parseOptions,
Keyword("string"),
script ? Field("s") : Local("s"),
Operators.Equals,
Verbatim(""""
@"""/*"
""""),
Keyword("u8"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task StringLiteral1(TestHost testHost)
{
await TestAsync("""
"goo"
""",
testHost,
String("""
"goo"
"""));
}
[Theory, CombinatorialData]
public async Task StringLiteralUtf8_01(TestHost testHost)
{
await TestAsync("""
"goo"u8
""",
testHost,
String("""
"goo"
"""),
Keyword("u8"));
}
[Theory, CombinatorialData]
public async Task StringLiteralUtf8_02(TestHost testHost)
{
await TestAsync("""
"goo"U8
""",
testHost,
String("""
"goo"
"""),
Keyword("U8"));
}
[Theory, CombinatorialData]
public async Task StringLiteral2(TestHost testHost)
{
await TestAsync("""
""
""",
testHost,
String("""
""
"""));
}
[Theory, CombinatorialData]
public async Task StringLiteralUtf8_03(TestHost testHost)
{
await TestAsync("""
""u8
""",
testHost,
String("""
""
"""),
Keyword("u8"));
}
[Theory, CombinatorialData]
public async Task StringLiteralUtf8_04(TestHost testHost)
{
await TestAsync("""
""U8
""",
testHost,
String("""
""
"""),
Keyword("U8"));
}
[Theory, CombinatorialData]
public async Task CharacterLiteral1(TestHost testHost)
{
var code = @"'f'";
await TestInMethodAsync(code,
testHost,
String("'f'"));
}
[Theory, CombinatorialData]
public async Task LinqFrom1(TestHost testHost)
{
var code = @"from it in goo";
await TestInExpressionAsync(code,
testHost,
Keyword("from"),
Identifier("it"),
Keyword("in"),
Identifier("goo"));
}
[Theory, CombinatorialData]
public async Task LinqFrom2(TestHost testHost)
{
var code = @"from it in goo.Bar()";
await TestInExpressionAsync(code,
testHost,
Keyword("from"),
Identifier("it"),
Keyword("in"),
Identifier("goo"),
Operators.Dot,
Identifier("Bar"),
Punctuation.OpenParen,
Punctuation.CloseParen);
}
[Theory, CombinatorialData]
public async Task LinqFrom3(TestHost testHost)
{
// query expression are not statement expressions, but the parser parses them anyways to give better errors
var code = @"from it in ";
await TestInMethodAsync(code,
testHost,
Keyword("from"),
Identifier("it"),
Keyword("in"));
}
[Theory, CombinatorialData]
public async Task LinqFrom4(TestHost testHost)
{
var code = @"from it in ";
await TestInExpressionAsync(code,
testHost,
Keyword("from"),
Identifier("it"),
Keyword("in"));
}
[Theory, CombinatorialData]
public async Task LinqWhere1(TestHost testHost)
{
var code = "from it in goo where it > 42";
await TestInExpressionAsync(code,
testHost,
Keyword("from"),
Identifier("it"),
Keyword("in"),
Identifier("goo"),
Keyword("where"),
Identifier("it"),
Operators.GreaterThan,
Number("42"));
}
[Theory, CombinatorialData]
public async Task LinqWhere2(TestHost testHost)
{
var code = """
from it in goo where it > "bar"
""";
await TestInExpressionAsync(code,
testHost,
Keyword("from"),
Identifier("it"),
Keyword("in"),
Identifier("goo"),
Keyword("where"),
Identifier("it"),
Operators.GreaterThan,
String("""
"bar"
"""));
}
[Theory, WorkItem("https://github.com/dotnet/roslyn/issues/44423")]
[CombinatorialData]
public async Task VarContextualKeywordAtNamespaceLevel(bool script, TestHost testHost)
{
var code = @"var goo = 2;";
var parseOptions = script ? Options.Script : null;
await TestAsync(code,
code,
testHost,
parseOptions,
script ? Identifier("var") : Keyword("var"),
script ? Field("goo") : Local("goo"),
Operators.Equals,
Number("2"),
Punctuation.Semicolon);
}
[Theory, WorkItem("https://github.com/dotnet/roslyn/issues/44423")]
[CombinatorialData]
public async Task LinqKeywordsAtNamespaceLevel(bool script, TestHost testHost)
{
// the contextual keywords are actual keywords since we parse top level field declaration and only give a semantic error
var code = """
object goo = from goo in goo
join goo in goo on goo equals goo
group goo by goo into goo
let goo = goo
where goo
orderby goo ascending, goo descending
select goo;
""";
var parseOptions = script ? Options.Script : null;
await TestAsync(
code,
code,
testHost,
parseOptions,
Keyword("object"),
script ? Field("goo") : Local("goo"),
Operators.Equals,
Keyword("from"),
Identifier("goo"),
Keyword("in"),
Identifier("goo"),
Keyword("join"),
Identifier("goo"),
Keyword("in"),
Identifier("goo"),
Keyword("on"),
Identifier("goo"),
Keyword("equals"),
Identifier("goo"),
Keyword("group"),
Identifier("goo"),
Keyword("by"),
Identifier("goo"),
Keyword("into"),
Identifier("goo"),
Keyword("let"),
Identifier("goo"),
Operators.Equals,
Identifier("goo"),
Keyword("where"),
Identifier("goo"),
Keyword("orderby"),
Identifier("goo"),
Keyword("ascending"),
Punctuation.Comma,
Identifier("goo"),
Keyword("descending"),
Keyword("select"),
Identifier("goo"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task ContextualKeywordsAsFieldName(TestHost testHost)
{
await TestAsync(
"""
class C
{
int yield, get, set, value, add, remove, global, partial, where, alias;
}
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("int"),
Field("yield"),
Punctuation.Comma,
Field("get"),
Punctuation.Comma,
Field("set"),
Punctuation.Comma,
Field("value"),
Punctuation.Comma,
Field("add"),
Punctuation.Comma,
Field("remove"),
Punctuation.Comma,
Field("global"),
Punctuation.Comma,
Field("partial"),
Punctuation.Comma,
Field("where"),
Punctuation.Comma,
Field("alias"),
Punctuation.Semicolon,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task LinqKeywordsInFieldInitializer(TestHost testHost)
{
await TestAsync(
"""
class C
{
int a = from a in a
join a in a on a equals a
group a by a into a
let a = a
where a
orderby a ascending, a descending
select a;
}
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("int"),
Field("a"),
Operators.Equals,
Keyword("from"),
Identifier("a"),
Keyword("in"),
Identifier("a"),
Keyword("join"),
Identifier("a"),
Keyword("in"),
Identifier("a"),
Keyword("on"),
Identifier("a"),
Keyword("equals"),
Identifier("a"),
Keyword("group"),
Identifier("a"),
Keyword("by"),
Identifier("a"),
Keyword("into"),
Identifier("a"),
Keyword("let"),
Identifier("a"),
Operators.Equals,
Identifier("a"),
Keyword("where"),
Identifier("a"),
Keyword("orderby"),
Identifier("a"),
Keyword("ascending"),
Punctuation.Comma,
Identifier("a"),
Keyword("descending"),
Keyword("select"),
Identifier("a"),
Punctuation.Semicolon,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task LinqKeywordsAsTypeName(TestHost testHost)
{
await TestAsync(
"""
class var
{
}
struct from
{
}
interface join
{
}
enum on
{
}
delegate equals { }
class group
{
}
class by
{
}
class into
{
}
class let
{
}
class where
{
}
class orderby
{
}
class ascending
{
}
class descending
{
}
class select
{
}
""",
testHost,
Keyword("class"),
Class("var"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("struct"),
Struct("from"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("interface"),
Interface("join"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("enum"),
Enum("on"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("delegate"),
Identifier("equals"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("group"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("by"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("into"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("let"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("where"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("orderby"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("ascending"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("descending"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("select"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task LinqKeywordsAsMethodParameters(TestHost testHost)
{
await TestAsync(
"""
class C
{
orderby M(var goo, from goo, join goo, on goo, equals goo, group goo, by goo, into goo, let goo, where goo, orderby goo, ascending goo, descending goo, select goo)
{
}
}
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Identifier("orderby"),
Method("M"),
Punctuation.OpenParen,
Identifier("var"),
Parameter("goo"),
Punctuation.Comma,
Identifier("from"),
Parameter("goo"),
Punctuation.Comma,
Identifier("join"),
Parameter("goo"),
Punctuation.Comma,
Identifier("on"),
Parameter("goo"),
Punctuation.Comma,
Identifier("equals"),
Parameter("goo"),
Punctuation.Comma,
Identifier("group"),
Parameter("goo"),
Punctuation.Comma,
Identifier("by"),
Parameter("goo"),
Punctuation.Comma,
Identifier("into"),
Parameter("goo"),
Punctuation.Comma,
Identifier("let"),
Parameter("goo"),
Punctuation.Comma,
Identifier("where"),
Parameter("goo"),
Punctuation.Comma,
Identifier("orderby"),
Parameter("goo"),
Punctuation.Comma,
Identifier("ascending"),
Parameter("goo"),
Punctuation.Comma,
Identifier("descending"),
Parameter("goo"),
Punctuation.Comma,
Identifier("select"),
Parameter("goo"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task LinqKeywordsInLocalVariableDeclarations(TestHost testHost)
{
await TestAsync(
"""
class C
{
void M()
{
var goo = (var)goo as var;
from goo = (from)goo as from;
join goo = (join)goo as join;
on goo = (on)goo as on;
equals goo = (equals)goo as equals;
group goo = (group)goo as group;
by goo = (by)goo as by;
into goo = (into)goo as into;
orderby goo = (orderby)goo as orderby;
ascending goo = (ascending)goo as ascending;
descending goo = (descending)goo as descending;
select goo = (select)goo as select;
}
}
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("var"),
Local("goo"),
Operators.Equals,
Punctuation.OpenParen,
Identifier("var"),
Punctuation.CloseParen,
Identifier("goo"),
Keyword("as"),
Identifier("var"),
Punctuation.Semicolon,
Identifier("from"),
Local("goo"),
Operators.Equals,
Punctuation.OpenParen,
Identifier("from"),
Punctuation.CloseParen,
Identifier("goo"),
Keyword("as"),
Identifier("from"),
Punctuation.Semicolon,
Identifier("join"),
Local("goo"),
Operators.Equals,
Punctuation.OpenParen,
Identifier("join"),
Punctuation.CloseParen,
Identifier("goo"),
Keyword("as"),
Identifier("join"),
Punctuation.Semicolon,
Identifier("on"),
Local("goo"),
Operators.Equals,
Punctuation.OpenParen,
Identifier("on"),
Punctuation.CloseParen,
Identifier("goo"),
Keyword("as"),
Identifier("on"),
Punctuation.Semicolon,
Identifier("equals"),
Local("goo"),
Operators.Equals,
Punctuation.OpenParen,
Identifier("equals"),
Punctuation.CloseParen,
Identifier("goo"),
Keyword("as"),
Identifier("equals"),
Punctuation.Semicolon,
Identifier("group"),
Local("goo"),
Operators.Equals,
Punctuation.OpenParen,
Identifier("group"),
Punctuation.CloseParen,
Identifier("goo"),
Keyword("as"),
Identifier("group"),
Punctuation.Semicolon,
Identifier("by"),
Local("goo"),
Operators.Equals,
Punctuation.OpenParen,
Identifier("by"),
Punctuation.CloseParen,
Identifier("goo"),
Keyword("as"),
Identifier("by"),
Punctuation.Semicolon,
Identifier("into"),
Local("goo"),
Operators.Equals,
Punctuation.OpenParen,
Identifier("into"),
Punctuation.CloseParen,
Identifier("goo"),
Keyword("as"),
Identifier("into"),
Punctuation.Semicolon,
Identifier("orderby"),
Local("goo"),
Operators.Equals,
Punctuation.OpenParen,
Identifier("orderby"),
Punctuation.CloseParen,
Identifier("goo"),
Keyword("as"),
Identifier("orderby"),
Punctuation.Semicolon,
Identifier("ascending"),
Local("goo"),
Operators.Equals,
Punctuation.OpenParen,
Identifier("ascending"),
Punctuation.CloseParen,
Identifier("goo"),
Keyword("as"),
Identifier("ascending"),
Punctuation.Semicolon,
Identifier("descending"),
Local("goo"),
Operators.Equals,
Punctuation.OpenParen,
Identifier("descending"),
Punctuation.CloseParen,
Identifier("goo"),
Keyword("as"),
Identifier("descending"),
Punctuation.Semicolon,
Identifier("select"),
Local("goo"),
Operators.Equals,
Punctuation.OpenParen,
Identifier("select"),
Punctuation.CloseParen,
Identifier("goo"),
Keyword("as"),
Identifier("select"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task LinqKeywordsAsFieldNames(TestHost testHost)
{
await TestAsync(
"""
class C
{
int var, from, join, on, into, equals, let, orderby, ascending, descending, select, group, by, partial;
}
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("int"),
Field("var"),
Punctuation.Comma,
Field("from"),
Punctuation.Comma,
Field("join"),
Punctuation.Comma,
Field("on"),
Punctuation.Comma,
Field("into"),
Punctuation.Comma,
Field("equals"),
Punctuation.Comma,
Field("let"),
Punctuation.Comma,
Field("orderby"),
Punctuation.Comma,
Field("ascending"),
Punctuation.Comma,
Field("descending"),
Punctuation.Comma,
Field("select"),
Punctuation.Comma,
Field("group"),
Punctuation.Comma,
Field("by"),
Punctuation.Comma,
Field("partial"),
Punctuation.Semicolon,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task LinqKeywordsAtFieldLevelInvalid(TestHost testHost)
{
await TestAsync(
"""
class C
{
string Property { from a in a join a in a on a equals a group a by a into a let a = a where a orderby a ascending,
a descending select a; }
}
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("string"),
Property("Property"),
Punctuation.OpenCurly,
Identifier("from"),
Identifier("a"),
Keyword("in"),
Identifier("a"),
Identifier("join"),
Identifier("a"),
Keyword("in"),
Identifier("a"),
Identifier("on"),
Identifier("a"),
Identifier("equals"),
Identifier("a"),
Identifier("group"),
Identifier("a"),
Identifier("by"),
Identifier("a"),
Identifier("into"),
Identifier("a"),
Identifier("let"),
Identifier("a"),
Operators.Equals,
Identifier("a"),
Identifier("where"),
Identifier("a"),
Identifier("orderby"),
Identifier("a"),
Identifier("ascending"),
Punctuation.Comma,
Identifier("a"),
Identifier("descending"),
Identifier("select"),
Identifier("a"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task CommentSingle(TestHost testHost)
{
var code = "// goo";
await TestAsync(code,
testHost,
Comment("// goo"));
}
[Theory, CombinatorialData]
public async Task CommentAsTrailingTrivia1(TestHost testHost)
{
var code = "class Bar { // goo";
await TestAsync(code,
testHost,
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Comment("// goo"));
}
[Theory, CombinatorialData]
public async Task CommentAsLeadingTrivia1(TestHost testHost)
{
var code = """
class Bar {
// goo
void Method1() { }
}
""";
await TestAsync(code,
testHost,
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Comment("// goo"),
Keyword("void"),
Method("Method1"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task ShebangAsFirstCommentInScript(TestHost testHost)
{
var code = """
#!/usr/bin/env scriptcs
System.Console.WriteLine();
""";
var expected = new[]
{
Comment("#!/usr/bin/env scriptcs"),
Identifier("System"),
Operators.Dot,
Identifier("Console"),
Operators.Dot,
Identifier("WriteLine"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon
};
await TestAsync(code, code, testHost, Options.Script, expected);
}
[Theory, CombinatorialData]
public async Task ShebangAsFirstCommentInNonScript(TestHost testHost)
{
var code = """
#!/usr/bin/env scriptcs
System.Console.WriteLine();
""";
var expected = new[]
{
PPKeyword("#"),
PPText("!/usr/bin/env scriptcs"),
Identifier("System"),
Operators.Dot,
Identifier("Console"),
Operators.Dot,
Identifier("WriteLine"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon
};
await TestAsync(code, code, testHost, Options.Regular, expected);
}
[Theory, CombinatorialData]
public async Task ShebangNotAsFirstCommentInScript(TestHost testHost)
{
var code = """
#!/usr/bin/env scriptcs
System.Console.WriteLine();
""";
var expected = new[]
{
PPKeyword("#"),
PPText("!/usr/bin/env scriptcs"),
Identifier("System"),
Operators.Dot,
Identifier("Console"),
Operators.Dot,
Identifier("WriteLine"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon
};
await TestAsync(code, code, testHost, Options.Script, expected);
}
[Theory, CombinatorialData]
public async Task CommentAsMethodBodyContent(TestHost testHost)
{
var code = """
class Bar {
void Method1() {
// goo
}
}
""";
await TestAsync(code,
testHost,
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Keyword("void"),
Method("Method1"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Comment("// goo"),
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task CommentMix1(TestHost testHost)
{
await TestAsync(
"""
// comment1 /*
class cl
{
}
//comment2 */
""",
testHost,
Comment("// comment1 /*"),
Keyword("class"),
Class("cl"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Comment("//comment2 */"));
}
[Theory, CombinatorialData]
public async Task CommentMix2(TestHost testHost)
{
await TestInMethodAsync(
@"/**/int /**/i = 0;",
testHost,
Comment("/**/"),
Keyword("int"),
Comment("/**/"),
Local("i"),
Operators.Equals,
Number("0"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task XmlDocCommentOnClass(TestHost testHost)
{
var code = """
/// <summary>something</summary>
class Bar { }
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Text(" "),
XmlDoc.Delimiter("<"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
XmlDoc.Text("something"),
XmlDoc.Delimiter("</"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task XmlDocCommentOnClassWithIndent(TestHost testHost)
{
var code = """
/// <summary>
/// something
/// </summary>
class Bar { }
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Text(" "),
XmlDoc.Delimiter("<"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
XmlDoc.Delimiter("///"),
XmlDoc.Text(" something"),
XmlDoc.Delimiter("///"),
XmlDoc.Text(" "),
XmlDoc.Delimiter("</"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task XmlDocComment_EntityReference(TestHost testHost)
{
var code = """
/// <summary>A</summary>
class Bar { }
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Text(" "),
XmlDoc.Delimiter("<"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
XmlDoc.EntityReference("A"),
XmlDoc.Delimiter("</"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task XmlDocComment_ExteriorTriviaInsideCloseTag(TestHost testHost)
{
var code = """
/// <summary>something</
/// summary>
class Bar { }
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Text(" "),
XmlDoc.Delimiter("<"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
XmlDoc.Text("something"),
XmlDoc.Delimiter("</"),
XmlDoc.Delimiter("///"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531155")]
[CombinatorialData]
public async Task XmlDocComment_ExteriorTriviaInsideCRef(TestHost testHost)
{
var code = """
/// <see cref="System.
/// Int32"/>
class C
{
}
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Text(" "),
XmlDoc.Delimiter("<"),
XmlDoc.Name("see"),
XmlDoc.AttributeName("cref"),
XmlDoc.Delimiter("="),
XmlDoc.AttributeQuotes("""
"
"""),
Identifier("System"),
Operators.Dot,
XmlDoc.Delimiter("///"),
Identifier("Int32"),
XmlDoc.AttributeQuotes("""
"
"""),
XmlDoc.Delimiter("/>"),
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task XmlDocCommentOnClassWithExteriorTrivia(TestHost testHost)
{
var code = """
/// <summary>
/// something
/// </summary>
class Bar { }
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Text(" "),
XmlDoc.Delimiter("<"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
XmlDoc.Delimiter("///"),
XmlDoc.Text(" something"),
XmlDoc.Delimiter("///"),
XmlDoc.Text(" "),
XmlDoc.Delimiter("</"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task XmlDocComment_ExteriorTriviaNoText(TestHost testHost)
{
var code =
"""
///<summary>
///something
///</summary>
class Bar { }
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Delimiter("<"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
XmlDoc.Delimiter("///"),
XmlDoc.Text("something"),
XmlDoc.Delimiter("///"),
XmlDoc.Delimiter("</"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task XmlDocComment_EmptyElement(TestHost testHost)
{
var code = """
/// <summary />
class Bar { }
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Text(" "),
XmlDoc.Delimiter("<"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter("/>"),
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task XmlDocComment_Attribute(TestHost testHost)
{
var code = """
/// <summary attribute="value">something</summary>
class Bar { }
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Text(" "),
XmlDoc.Delimiter("<"),
XmlDoc.Name("summary"),
XmlDoc.AttributeName("attribute"),
XmlDoc.Delimiter("="),
XmlDoc.AttributeQuotes("""
"
"""),
XmlDoc.AttributeValue(@"value"),
XmlDoc.AttributeQuotes("""
"
"""),
XmlDoc.Delimiter(">"),
XmlDoc.Text("something"),
XmlDoc.Delimiter("</"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task XmlDocComment_AttributeInEmptyElement(TestHost testHost)
{
var code = """
/// <summary attribute="value" />
class Bar { }
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Text(" "),
XmlDoc.Delimiter("<"),
XmlDoc.Name("summary"),
XmlDoc.AttributeName("attribute"),
XmlDoc.Delimiter("="),
XmlDoc.AttributeQuotes("""
"
"""),
XmlDoc.AttributeValue(@"value"),
XmlDoc.AttributeQuotes("""
"
"""),
XmlDoc.Delimiter("/>"),
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task XmlDocComment_ExtraSpaces(TestHost testHost)
{
var code = """
/// < summary attribute = "value" />
class Bar { }
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Text(" "),
XmlDoc.Delimiter("<"),
XmlDoc.Name("summary"),
XmlDoc.AttributeName("attribute"),
XmlDoc.Delimiter("="),
XmlDoc.AttributeQuotes("""
"
"""),
XmlDoc.AttributeValue(@"value"),
XmlDoc.AttributeQuotes("""
"
"""),
XmlDoc.Delimiter("/>"),
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task XmlDocComment_XmlComment(TestHost testHost)
{
var code = """
///<!--comment-->
class Bar { }
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Delimiter("<!--"),
XmlDoc.Comment("comment"),
XmlDoc.Delimiter("-->"),
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task XmlDocComment_XmlCommentWithExteriorTrivia(TestHost testHost)
{
var code = """
///<!--first
///second-->
class Bar { }
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Delimiter("<!--"),
XmlDoc.Comment("first"),
XmlDoc.Delimiter("///"),
XmlDoc.Comment("second"),
XmlDoc.Delimiter("-->"),
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task XmlDocComment_XmlCommentInElement(TestHost testHost)
{
var code = """
///<summary><!--comment--></summary>
class Bar { }
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Delimiter("<"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
XmlDoc.Delimiter("<!--"),
XmlDoc.Comment("comment"),
XmlDoc.Delimiter("-->"),
XmlDoc.Delimiter("</"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
[WorkItem("https://github.com/dotnet/roslyn/pull/31410")]
public async Task XmlDocComment_MalformedXmlDocComment(TestHost testHost)
{
var code = """
///<summary>
///<a: b, c />.
///</summary>
class C { }
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Delimiter("<"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
XmlDoc.Delimiter("///"),
XmlDoc.Delimiter("<"),
XmlDoc.Name("a"),
XmlDoc.Name(":"),
XmlDoc.Name("b"),
XmlDoc.Text(","),
XmlDoc.Text("c"),
XmlDoc.Delimiter("/>"),
XmlDoc.Text("."),
XmlDoc.Delimiter("///"),
XmlDoc.Delimiter("</"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task MultilineXmlDocComment_ExteriorTrivia(TestHost testHost)
{
var code =
"""
/**<summary>
*comment
*</summary>*/
class Bar { }
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("/**"),
XmlDoc.Delimiter("<"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
XmlDoc.Delimiter("*"),
XmlDoc.Text("comment"),
XmlDoc.Delimiter("*"),
XmlDoc.Delimiter("</"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
XmlDoc.Delimiter("*/"),
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task XmlDocComment_CDataWithExteriorTrivia(TestHost testHost)
{
var code = """
///<![CDATA[first
///second]]>
class Bar { }
""";
await TestAsync(code,
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Delimiter("<![CDATA["),
XmlDoc.CDataSection("first"),
XmlDoc.Delimiter("///"),
XmlDoc.CDataSection("second"),
XmlDoc.Delimiter("]]>"),
Keyword("class"),
Class("Bar"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task XmlDocComment_ProcessingDirective(TestHost testHost)
{
await TestAsync(
"""
/// <summary><?goo
/// ?></summary>
public class Program
{
static void Main()
{
}
}
""",
testHost,
XmlDoc.Delimiter("///"),
XmlDoc.Text(" "),
XmlDoc.Delimiter("<"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
XmlDoc.ProcessingInstruction("<?"),
XmlDoc.ProcessingInstruction("goo"),
XmlDoc.Delimiter("///"),
XmlDoc.ProcessingInstruction(" "),
XmlDoc.ProcessingInstruction("?>"),
XmlDoc.Delimiter("</"),
XmlDoc.Name("summary"),
XmlDoc.Delimiter(">"),
Keyword("public"),
Keyword("class"),
Class("Program"),
Punctuation.OpenCurly,
Keyword("static"),
Keyword("void"),
Method("Main"),
Static("Main"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
[WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/536321")]
public async Task KeywordTypeParameters(TestHost testHost)
{
var code = @"class C<int> { }";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenAngle,
Keyword("int"),
Punctuation.CloseAngle,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
[WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/536853")]
public async Task TypeParametersWithAttribute(TestHost testHost)
{
var code = @"class C<[Attr] T> { }";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenAngle,
Punctuation.OpenBracket,
Identifier("Attr"),
Punctuation.CloseBracket,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task ClassTypeDeclaration1(TestHost testHost)
{
var code = "class C1 { } ";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C1"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task ClassTypeDeclaration2(TestHost testHost)
{
var code = "class ClassName1 { } ";
await TestAsync(code,
testHost,
Keyword("class"),
Class("ClassName1"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task StructTypeDeclaration1(TestHost testHost)
{
var code = "struct Struct1 { }";
await TestAsync(code,
testHost,
Keyword("struct"),
Struct("Struct1"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task InterfaceDeclaration1(TestHost testHost)
{
var code = "interface I1 { }";
await TestAsync(code,
testHost,
Keyword("interface"),
Interface("I1"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task EnumDeclaration1(TestHost testHost)
{
var code = "enum Weekday { }";
await TestAsync(code,
testHost,
Keyword("enum"),
Enum("Weekday"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, WorkItem(4302, "DevDiv_Projects/Roslyn")]
[CombinatorialData]
public async Task ClassInEnum(TestHost testHost)
{
var code = "enum E { Min = System.Int32.MinValue }";
await TestAsync(code,
testHost,
Keyword("enum"),
Enum("E"),
Punctuation.OpenCurly,
EnumMember("Min"),
Operators.Equals,
Identifier("System"),
Operators.Dot,
Identifier("Int32"),
Operators.Dot,
Identifier("MinValue"),
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task DelegateDeclaration1(TestHost testHost)
{
var code = "delegate void Action();";
await TestAsync(code,
testHost,
Keyword("delegate"),
Keyword("void"),
Delegate("Action"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task GenericTypeArgument(TestHost testHost)
{
await TestInMethodAsync(
"C<T>",
"M",
"default(T)",
testHost,
Keyword("default"),
Punctuation.OpenParen,
Identifier("T"),
Punctuation.CloseParen);
}
[Theory, CombinatorialData]
public async Task GenericParameter(TestHost testHost)
{
var code = "class C1<P1> {}";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C1"),
Punctuation.OpenAngle,
TypeParameter("P1"),
Punctuation.CloseAngle,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task GenericParameters(TestHost testHost)
{
var code = "class C1<P1,P2> {}";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C1"),
Punctuation.OpenAngle,
TypeParameter("P1"),
Punctuation.Comma,
TypeParameter("P2"),
Punctuation.CloseAngle,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task GenericParameter_Interface(TestHost testHost)
{
var code = "interface I1<P1> {}";
await TestAsync(code,
testHost,
Keyword("interface"),
Interface("I1"),
Punctuation.OpenAngle,
TypeParameter("P1"),
Punctuation.CloseAngle,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task GenericParameter_Struct(TestHost testHost)
{
var code = "struct S1<P1> {}";
await TestAsync(code,
testHost,
Keyword("struct"),
Struct("S1"),
Punctuation.OpenAngle,
TypeParameter("P1"),
Punctuation.CloseAngle,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task GenericParameter_Delegate(TestHost testHost)
{
var code = "delegate void D1<P1> {}";
await TestAsync(code,
testHost,
Keyword("delegate"),
Keyword("void"),
Delegate("D1"),
Punctuation.OpenAngle,
TypeParameter("P1"),
Punctuation.CloseAngle,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task GenericParameter_Method(TestHost testHost)
{
await TestInClassAsync(
"""
T M<T>(T t)
{
return default(T);
}
""",
testHost,
Identifier("T"),
Method("M"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Identifier("T"),
Parameter("t"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
ControlKeyword("return"),
Keyword("default"),
Punctuation.OpenParen,
Identifier("T"),
Punctuation.CloseParen,
Punctuation.Semicolon,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TernaryExpression(TestHost testHost)
{
await TestInExpressionAsync("true ? 1 : 0",
testHost,
Keyword("true"),
Operators.QuestionMark,
Number("1"),
Operators.Colon,
Number("0"));
}
[Theory, CombinatorialData]
public async Task BaseClass(TestHost testHost)
{
await TestAsync(
"""
class C : B
{
}
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.Colon,
Identifier("B"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestLabel(TestHost testHost)
{
await TestInMethodAsync("goo:",
testHost,
Label("goo"),
Punctuation.Colon);
}
[Theory, CombinatorialData]
public async Task Attribute(TestHost testHost)
{
await TestAsync(
@"[assembly: Goo]",
testHost,
Punctuation.OpenBracket,
Keyword("assembly"),
Punctuation.Colon,
Identifier("Goo"),
Punctuation.CloseBracket);
}
[Theory, CombinatorialData]
public async Task TestAngleBracketsOnGenericConstraints_Bug932262(TestHost testHost)
{
await TestAsync(
"""
class C<T> where T : A<T>
{
}
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Identifier("A"),
Punctuation.OpenAngle,
Identifier("T"),
Punctuation.CloseAngle,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestYieldPositive(TestHost testHost)
{
await TestInMethodAsync(
@"yield return goo;",
testHost,
ControlKeyword("yield"),
ControlKeyword("return"),
Identifier("goo"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestYieldNegative(TestHost testHost)
{
await TestInMethodAsync(
@"int yield;",
testHost,
Keyword("int"),
Local("yield"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestFromPositive(TestHost testHost)
{
await TestInExpressionAsync(
@"from x in y",
testHost,
Keyword("from"),
Identifier("x"),
Keyword("in"),
Identifier("y"));
}
[Theory, CombinatorialData]
public async Task TestFromNegative(TestHost testHost)
{
await TestInMethodAsync(
@"int from;",
testHost,
Keyword("int"),
Local("from"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task AttributeTargetSpecifiersModule(TestHost testHost)
{
await TestAsync(
@"[module: Obsolete]",
testHost,
Punctuation.OpenBracket,
Keyword("module"),
Punctuation.Colon,
Identifier("Obsolete"),
Punctuation.CloseBracket);
}
[Theory, CombinatorialData]
public async Task AttributeTargetSpecifiersAssembly(TestHost testHost)
{
await TestAsync(
@"[assembly: Obsolete]",
testHost,
Punctuation.OpenBracket,
Keyword("assembly"),
Punctuation.Colon,
Identifier("Obsolete"),
Punctuation.CloseBracket);
}
[Theory, CombinatorialData]
public async Task AttributeTargetSpecifiersOnDelegate(TestHost testHost)
{
await TestInClassAsync(
"""
[type: A]
[return: A]
delegate void M();
""",
testHost,
Punctuation.OpenBracket,
Keyword("type"),
Punctuation.Colon,
Identifier("A"),
Punctuation.CloseBracket,
Punctuation.OpenBracket,
Keyword("return"),
Punctuation.Colon,
Identifier("A"),
Punctuation.CloseBracket,
Keyword("delegate"),
Keyword("void"),
Delegate("M"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task AttributeTargetSpecifiersOnMethod(TestHost testHost)
{
await TestInClassAsync(
"""
[return: A]
[method: A]
void M()
{
}
""",
testHost,
Punctuation.OpenBracket,
Keyword("return"),
Punctuation.Colon,
Identifier("A"),
Punctuation.CloseBracket,
Punctuation.OpenBracket,
Keyword("method"),
Punctuation.Colon,
Identifier("A"),
Punctuation.CloseBracket,
Keyword("void"),
Method("M"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task AttributeTargetSpecifiersOnCtor(TestHost testHost)
{
await TestAsync(
"""
class C
{
[method: A]
C()
{
}
}
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Punctuation.OpenBracket,
Keyword("method"),
Punctuation.Colon,
Identifier("A"),
Punctuation.CloseBracket,
Class("C"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task AttributeTargetSpecifiersOnDtor(TestHost testHost)
{
await TestAsync(
"""
class C
{
[method: A]
~C()
{
}
}
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Punctuation.OpenBracket,
Keyword("method"),
Punctuation.Colon,
Identifier("A"),
Punctuation.CloseBracket,
Operators.Tilde,
Class("C"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task AttributeTargetSpecifiersOnOperator(TestHost testHost)
{
await TestInClassAsync(
"""
[method: A]
[return: A]
static T operator +(T a, T b)
{
}
""",
testHost,
Punctuation.OpenBracket,
Keyword("method"),
Punctuation.Colon,
Identifier("A"),
Punctuation.CloseBracket,
Punctuation.OpenBracket,
Keyword("return"),
Punctuation.Colon,
Identifier("A"),
Punctuation.CloseBracket,
Keyword("static"),
Identifier("T"),
Keyword("operator"),
Operators.Plus,
Punctuation.OpenParen,
Identifier("T"),
Parameter("a"),
Punctuation.Comma,
Identifier("T"),
Parameter("b"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task AttributeTargetSpecifiersOnEventDeclaration(TestHost testHost)
{
await TestInClassAsync(
"""
[event: A]
event A E
{
[param: Test]
[method: Test]
add
{
}
[param: Test]
[method: Test]
remove
{
}
}
""",
testHost,
Punctuation.OpenBracket,
Keyword("event"),
Punctuation.Colon,
Identifier("A"),
Punctuation.CloseBracket,
Keyword("event"),
Identifier("A"),
Event("E"),
Punctuation.OpenCurly,
Punctuation.OpenBracket,
Keyword("param"),
Punctuation.Colon,
Identifier("Test"),
Punctuation.CloseBracket,
Punctuation.OpenBracket,
Keyword("method"),
Punctuation.Colon,
Identifier("Test"),
Punctuation.CloseBracket,
Keyword("add"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.OpenBracket,
Keyword("param"),
Punctuation.Colon,
Identifier("Test"),
Punctuation.CloseBracket,
Punctuation.OpenBracket,
Keyword("method"),
Punctuation.Colon,
Identifier("Test"),
Punctuation.CloseBracket,
Keyword("remove"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task AttributeTargetSpecifiersOnPropertyAccessors(TestHost testHost)
{
await TestInClassAsync(
"""
int P
{
[return: T]
[method: T]
get
{
}
[param: T]
[method: T]
set
{
}
}
""",
testHost,
Keyword("int"),
Property("P"),
Punctuation.OpenCurly,
Punctuation.OpenBracket,
Keyword("return"),
Punctuation.Colon,
Identifier("T"),
Punctuation.CloseBracket,
Punctuation.OpenBracket,
Keyword("method"),
Punctuation.Colon,
Identifier("T"),
Punctuation.CloseBracket,
Keyword("get"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.OpenBracket,
Keyword("param"),
Punctuation.Colon,
Identifier("T"),
Punctuation.CloseBracket,
Punctuation.OpenBracket,
Keyword("method"),
Punctuation.Colon,
Identifier("T"),
Punctuation.CloseBracket,
Keyword("set"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task AttributeTargetSpecifiersOnIndexers(TestHost testHost)
{
await TestInClassAsync(
"""
[property: A]
int this[int i] { get; set; }
""",
testHost,
Punctuation.OpenBracket,
Keyword("property"),
Punctuation.Colon,
Identifier("A"),
Punctuation.CloseBracket,
Keyword("int"),
Keyword("this"),
Punctuation.OpenBracket,
Keyword("int"),
Parameter("i"),
Punctuation.CloseBracket,
Punctuation.OpenCurly,
Keyword("get"),
Punctuation.Semicolon,
Keyword("set"),
Punctuation.Semicolon,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task AttributeTargetSpecifiersOnIndexerAccessors(TestHost testHost)
{
await TestInClassAsync(
"""
int this[int i]
{
[return: T]
[method: T]
get
{
}
[param: T]
[method: T]
set
{
}
}
""",
testHost,
Keyword("int"),
Keyword("this"),
Punctuation.OpenBracket,
Keyword("int"),
Parameter("i"),
Punctuation.CloseBracket,
Punctuation.OpenCurly,
Punctuation.OpenBracket,
Keyword("return"),
Punctuation.Colon,
Identifier("T"),
Punctuation.CloseBracket,
Punctuation.OpenBracket,
Keyword("method"),
Punctuation.Colon,
Identifier("T"),
Punctuation.CloseBracket,
Keyword("get"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.OpenBracket,
Keyword("param"),
Punctuation.Colon,
Identifier("T"),
Punctuation.CloseBracket,
Punctuation.OpenBracket,
Keyword("method"),
Punctuation.Colon,
Identifier("T"),
Punctuation.CloseBracket,
Keyword("set"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task AttributeTargetSpecifiersOnField(TestHost testHost)
{
await TestInClassAsync(
"""
[field: A]
const int a = 0;
""",
testHost,
Punctuation.OpenBracket,
Keyword("field"),
Punctuation.Colon,
Identifier("A"),
Punctuation.CloseBracket,
Keyword("const"),
Keyword("int"),
Constant("a"),
Static("a"),
Operators.Equals,
Number("0"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestAllKeywords(TestHost testHost)
{
await TestAsync(
"""
using System;
#region TaoRegion
namespace MyNamespace
{
abstract class Goo : Bar
{
bool goo = default(bool);
byte goo1;
char goo2;
const int goo3 = 999;
decimal goo4;
delegate void D();
delegate* managed<int, int> mgdfun;
delegate* unmanaged<int, int> unmgdfun;
double goo5;
enum MyEnum
{
one,
two,
three
};
event D MyEvent;
float goo6;
static int x;
long goo7;
sbyte goo8;
short goo9;
int goo10 = sizeof(int);
string goo11;
uint goo12;
ulong goo13;
volatile ushort goo14;
struct SomeStruct
{
}
protected virtual void someMethod()
{
}
public Goo(int i)
{
bool var = i is int;
try
{
while (true)
{
continue;
break;
}
switch (goo)
{
case true:
break;
default:
break;
}
}
catch (System.Exception)
{
}
finally
{
}
checked
{
int i2 = 10000;
i2++;
}
do
{
}
while (true);
if (false)
{
}
else
{
}
unsafe
{
fixed (int* p = &x)
{
}
char* buffer = stackalloc char[16];
}
for (int i1 = 0; i1 < 10; i1++)
{
}
System.Collections.ArrayList al = new System.Collections.ArrayList();
foreach (object o in al)
{
object o1 = o;
}
lock (this)
{
}
}
Goo method(Bar i, out int z)
{
z = 5;
return i as Goo;
}
public static explicit operator Goo(int i)
{
return new Baz(1);
}
public static implicit operator Goo(double x)
{
return new Baz(1);
}
public extern void doSomething();
internal void method2(object o)
{
if (o == null)
goto Output;
if (o is Baz)
return;
else
throw new System.Exception();
Output:
Console.WriteLine("Finished");
}
}
sealed class Baz : Goo
{
readonly int field;
public Baz(int i) : base(i)
{
}
public void someOtherMethod(ref int i, System.Type c)
{
int f = 1;
someOtherMethod(ref f, typeof(int));
}
protected override void someMethod()
{
unchecked
{
int i = 1;
i++;
}
}
private void method(params object[] args)
{
}
private string aMethod(object o) => o switch
{
int => string.Empty,
_ when true => throw new System.Exception()
};
}
interface Bar
{
}
}
#endregion TaoRegion
""",
testHost,
[new CSharpParseOptions(LanguageVersion.CSharp8)],
Keyword("using"),
Identifier("System"),
Punctuation.Semicolon,
PPKeyword("#"),
PPKeyword("region"),
PPText("TaoRegion"),
Keyword("namespace"),
Namespace("MyNamespace"),
Punctuation.OpenCurly,
Keyword("abstract"),
Keyword("class"),
Class("Goo"),
Punctuation.Colon,
Identifier("Bar"),
Punctuation.OpenCurly,
Keyword("bool"),
Field("goo"),
Operators.Equals,
Keyword("default"),
Punctuation.OpenParen,
Keyword("bool"),
Punctuation.CloseParen,
Punctuation.Semicolon,
Keyword("byte"),
Field("goo1"),
Punctuation.Semicolon,
Keyword("char"),
Field("goo2"),
Punctuation.Semicolon,
Keyword("const"),
Keyword("int"),
Constant("goo3"),
Static("goo3"),
Operators.Equals,
Number("999"),
Punctuation.Semicolon,
Keyword("decimal"),
Field("goo4"),
Punctuation.Semicolon,
Keyword("delegate"),
Keyword("void"),
Delegate("D"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
Keyword("delegate"),
Operators.Asterisk,
Keyword("managed"),
Punctuation.OpenAngle,
Keyword("int"),
Punctuation.Comma,
Keyword("int"),
Punctuation.CloseAngle,
Field("mgdfun"),
Punctuation.Semicolon,
Keyword("delegate"),
Operators.Asterisk,
Keyword("unmanaged"),
Punctuation.OpenAngle,
Keyword("int"),
Punctuation.Comma,
Keyword("int"),
Punctuation.CloseAngle,
Field("unmgdfun"),
Punctuation.Semicolon,
Keyword("double"),
Field("goo5"),
Punctuation.Semicolon,
Keyword("enum"),
Enum("MyEnum"),
Punctuation.OpenCurly,
EnumMember("one"),
Punctuation.Comma,
EnumMember("two"),
Punctuation.Comma,
EnumMember("three"),
Punctuation.CloseCurly,
Punctuation.Semicolon,
Keyword("event"),
Identifier("D"),
Event("MyEvent"),
Punctuation.Semicolon,
Keyword("float"),
Field("goo6"),
Punctuation.Semicolon,
Keyword("static"),
Keyword("int"),
Field("x"),
Static("x"),
Punctuation.Semicolon,
Keyword("long"),
Field("goo7"),
Punctuation.Semicolon,
Keyword("sbyte"),
Field("goo8"),
Punctuation.Semicolon,
Keyword("short"),
Field("goo9"),
Punctuation.Semicolon,
Keyword("int"),
Field("goo10"),
Operators.Equals,
Keyword("sizeof"),
Punctuation.OpenParen,
Keyword("int"),
Punctuation.CloseParen,
Punctuation.Semicolon,
Keyword("string"),
Field("goo11"),
Punctuation.Semicolon,
Keyword("uint"),
Field("goo12"),
Punctuation.Semicolon,
Keyword("ulong"),
Field("goo13"),
Punctuation.Semicolon,
Keyword("volatile"),
Keyword("ushort"),
Field("goo14"),
Punctuation.Semicolon,
Keyword("struct"),
Struct("SomeStruct"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("protected"),
Keyword("virtual"),
Keyword("void"),
Method("someMethod"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("public"),
Class("Goo"),
Punctuation.OpenParen,
Keyword("int"),
Parameter("i"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("bool"),
Local("var"),
Operators.Equals,
Identifier("i"),
Keyword("is"),
Keyword("int"),
Punctuation.Semicolon,
ControlKeyword("try"),
Punctuation.OpenCurly,
ControlKeyword("while"),
Punctuation.OpenParen,
Keyword("true"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
ControlKeyword("continue"),
Punctuation.Semicolon,
ControlKeyword("break"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
ControlKeyword("switch"),
Punctuation.OpenParen,
Identifier("goo"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
ControlKeyword("case"),
Keyword("true"),
Punctuation.Colon,
ControlKeyword("break"),
Punctuation.Semicolon,
ControlKeyword("default"),
Punctuation.Colon,
ControlKeyword("break"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
ControlKeyword("catch"),
Punctuation.OpenParen,
Identifier("System"),
Operators.Dot,
Identifier("Exception"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
ControlKeyword("finally"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("checked"),
Punctuation.OpenCurly,
Keyword("int"),
Local("i2"),
Operators.Equals,
Number("10000"),
Punctuation.Semicolon,
Identifier("i2"),
Operators.PlusPlus,
Punctuation.Semicolon,
Punctuation.CloseCurly,
ControlKeyword("do"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
ControlKeyword("while"),
Punctuation.OpenParen,
Keyword("true"),
Punctuation.CloseParen,
Punctuation.Semicolon,
ControlKeyword("if"),
Punctuation.OpenParen,
Keyword("false"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
ControlKeyword("else"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("unsafe"),
Punctuation.OpenCurly,
Keyword("fixed"),
Punctuation.OpenParen,
Keyword("int"),
Operators.Asterisk,
Local("p"),
Operators.Equals,
Operators.Ampersand,
Identifier("x"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("char"),
Operators.Asterisk,
Local("buffer"),
Operators.Equals,
Keyword("stackalloc"),
Keyword("char"),
Punctuation.OpenBracket,
Number("16"),
Punctuation.CloseBracket,
Punctuation.Semicolon,
Punctuation.CloseCurly,
ControlKeyword("for"),
Punctuation.OpenParen,
Keyword("int"),
Local("i1"),
Operators.Equals,
Number("0"),
Punctuation.Semicolon,
Identifier("i1"),
Operators.LessThan,
Number("10"),
Punctuation.Semicolon,
Identifier("i1"),
Operators.PlusPlus,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Identifier("System"),
Operators.Dot,
Identifier("Collections"),
Operators.Dot,
Identifier("ArrayList"),
Local("al"),
Operators.Equals,
Keyword("new"),
Identifier("System"),
Operators.Dot,
Identifier("Collections"),
Operators.Dot,
Identifier("ArrayList"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
ControlKeyword("foreach"),
Punctuation.OpenParen,
Keyword("object"),
Local("o"),
ControlKeyword("in"),
Identifier("al"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("object"),
Local("o1"),
Operators.Equals,
Identifier("o"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Keyword("lock"),
Punctuation.OpenParen,
Keyword("this"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Identifier("Goo"),
Method("method"),
Punctuation.OpenParen,
Identifier("Bar"),
Parameter("i"),
Punctuation.Comma,
Keyword("out"),
Keyword("int"),
Parameter("z"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Identifier("z"),
Operators.Equals,
Number("5"),
Punctuation.Semicolon,
ControlKeyword("return"),
Identifier("i"),
Keyword("as"),
Identifier("Goo"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Keyword("public"),
Keyword("static"),
Keyword("explicit"),
Keyword("operator"),
Identifier("Goo"),
Punctuation.OpenParen,
Keyword("int"),
Parameter("i"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
ControlKeyword("return"),
Keyword("new"),
Identifier("Baz"),
Punctuation.OpenParen,
Number("1"),
Punctuation.CloseParen,
Punctuation.Semicolon,
Punctuation.CloseCurly,
Keyword("public"),
Keyword("static"),
Keyword("implicit"),
Keyword("operator"),
Identifier("Goo"),
Punctuation.OpenParen,
Keyword("double"),
Parameter("x"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
ControlKeyword("return"),
Keyword("new"),
Identifier("Baz"),
Punctuation.OpenParen,
Number("1"),
Punctuation.CloseParen,
Punctuation.Semicolon,
Punctuation.CloseCurly,
Keyword("public"),
Keyword("extern"),
Keyword("void"),
Method("doSomething"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
Keyword("internal"),
Keyword("void"),
Method("method2"),
Punctuation.OpenParen,
Keyword("object"),
Parameter("o"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
ControlKeyword("if"),
Punctuation.OpenParen,
Identifier("o"),
Operators.EqualsEquals,
Keyword("null"),
Punctuation.CloseParen,
ControlKeyword("goto"),
Identifier("Output"),
Punctuation.Semicolon,
ControlKeyword("if"),
Punctuation.OpenParen,
Identifier("o"),
Keyword("is"),
Identifier("Baz"),
Punctuation.CloseParen,
ControlKeyword("return"),
Punctuation.Semicolon,
ControlKeyword("else"),
ControlKeyword("throw"),
Keyword("new"),
Identifier("System"),
Operators.Dot,
Identifier("Exception"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
Label("Output"),
Punctuation.Colon,
Identifier("Console"),
Operators.Dot,
Identifier("WriteLine"),
Punctuation.OpenParen,
String("""
"Finished"
"""),
Punctuation.CloseParen,
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Keyword("sealed"),
Keyword("class"),
Class("Baz"),
Punctuation.Colon,
Identifier("Goo"),
Punctuation.OpenCurly,
Keyword("readonly"),
Keyword("int"),
Field("field"),
Punctuation.Semicolon,
Keyword("public"),
Class("Baz"),
Punctuation.OpenParen,
Keyword("int"),
Parameter("i"),
Punctuation.CloseParen,
Punctuation.Colon,
Keyword("base"),
Punctuation.OpenParen,
Identifier("i"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("public"),
Keyword("void"),
Method("someOtherMethod"),
Punctuation.OpenParen,
Keyword("ref"),
Keyword("int"),
Parameter("i"),
Punctuation.Comma,
Identifier("System"),
Operators.Dot,
Identifier("Type"),
Parameter("c"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("int"),
Local("f"),
Operators.Equals,
Number("1"),
Punctuation.Semicolon,
Identifier("someOtherMethod"),
Punctuation.OpenParen,
Keyword("ref"),
Identifier("f"),
Punctuation.Comma,
Keyword("typeof"),
Punctuation.OpenParen,
Keyword("int"),
Punctuation.CloseParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
Punctuation.CloseCurly,
Keyword("protected"),
Keyword("override"),
Keyword("void"),
Method("someMethod"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("unchecked"),
Punctuation.OpenCurly,
Keyword("int"),
Local("i"),
Operators.Equals,
Number("1"),
Punctuation.Semicolon,
Identifier("i"),
Operators.PlusPlus,
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Keyword("private"),
Keyword("void"),
Method("method"),
Punctuation.OpenParen,
Keyword("params"),
Keyword("object"),
Punctuation.OpenBracket,
Punctuation.CloseBracket,
Parameter("args"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("private"),
Keyword("string"),
Method("aMethod"),
Punctuation.OpenParen,
Keyword("object"),
Parameter("o"),
Punctuation.CloseParen,
Operators.EqualsGreaterThan,
Identifier("o"),
ControlKeyword("switch"),
Punctuation.OpenCurly,
Keyword("int"),
Operators.EqualsGreaterThan,
Keyword("string"),
Operators.Dot,
Identifier("Empty"),
Punctuation.Comma,
Keyword("_"),
ControlKeyword("when"),
Keyword("true"),
Operators.EqualsGreaterThan,
ControlKeyword("throw"),
Keyword("new"),
Identifier("System"),
Operators.Dot,
Identifier("Exception"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.CloseCurly,
Punctuation.Semicolon,
Punctuation.CloseCurly,
Keyword("interface"),
Interface("Bar"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
PPKeyword("#"),
PPKeyword("endregion"),
PPText("TaoRegion"));
}
[Theory, CombinatorialData]
public async Task TestAllOperators(TestHost testHost)
{
await TestAsync(
"""
using IO = System.IO;
public class Goo<T>
{
public void method()
{
int[] a = new int[5];
int[] var = {
1,
2,
3,
4,
5
};
int i = a[i];
Goo<T> f = new Goo<int>();
f.method();
i = i + i - i * i / i % i & i | i ^ i;
bool b = true & false | true ^ false;
b = !b;
i = ~i;
b = i < i && i > i;
int? ii = 5;
int f = true ? 1 : 0;
i++;
i--;
b = true && false || true;
i << 5;
i >> 5;
i >>> 5;
b = i == i && i != i && i <= i && i >= i;
i += 5.0;
i -= i;
i *= i;
i /= i;
i %= i;
i &= i;
i |= i;
i ^= i;
i <<= i;
i >>= i;
i >>>= i;
i ??= i;
object s = x => x + 1;
Point point;
unsafe
{
Point* p = &point;
p->x = 10;
}
IO::BinaryReader br = null;
}
}
""",
testHost,
Keyword("using"),
Identifier("IO"),
Operators.Equals,
Identifier("System"),
Operators.Dot,
Identifier("IO"),
Punctuation.Semicolon,
Keyword("public"),
Keyword("class"),
Class("Goo"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenCurly,
Keyword("public"),
Keyword("void"),
Method("method"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("int"),
Punctuation.OpenBracket,
Punctuation.CloseBracket,
Local("a"),
Operators.Equals,
Keyword("new"),
Keyword("int"),
Punctuation.OpenBracket,
Number("5"),
Punctuation.CloseBracket,
Punctuation.Semicolon,
Keyword("int"),
Punctuation.OpenBracket,
Punctuation.CloseBracket,
Local("var"),
Operators.Equals,
Punctuation.OpenCurly,
Number("1"),
Punctuation.Comma,
Number("2"),
Punctuation.Comma,
Number("3"),
Punctuation.Comma,
Number("4"),
Punctuation.Comma,
Number("5"),
Punctuation.CloseCurly,
Punctuation.Semicolon,
Keyword("int"),
Local("i"),
Operators.Equals,
Identifier("a"),
Punctuation.OpenBracket,
Identifier("i"),
Punctuation.CloseBracket,
Punctuation.Semicolon,
Identifier("Goo"),
Punctuation.OpenAngle,
Identifier("T"),
Punctuation.CloseAngle,
Local("f"),
Operators.Equals,
Keyword("new"),
Identifier("Goo"),
Punctuation.OpenAngle,
Keyword("int"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
Identifier("f"),
Operators.Dot,
Identifier("method"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
Identifier("i"),
Operators.Equals,
Identifier("i"),
Operators.Plus,
Identifier("i"),
Operators.Minus,
Identifier("i"),
Operators.Asterisk,
Identifier("i"),
Operators.Slash,
Identifier("i"),
Operators.Percent,
Identifier("i"),
Operators.Ampersand,
Identifier("i"),
Operators.Bar,
Identifier("i"),
Operators.Caret,
Identifier("i"),
Punctuation.Semicolon,
Keyword("bool"),
Local("b"),
Operators.Equals,
Keyword("true"),
Operators.Ampersand,
Keyword("false"),
Operators.Bar,
Keyword("true"),
Operators.Caret,
Keyword("false"),
Punctuation.Semicolon,
Identifier("b"),
Operators.Equals,
Operators.Exclamation,
Identifier("b"),
Punctuation.Semicolon,
Identifier("i"),
Operators.Equals,
Operators.Tilde,
Identifier("i"),
Punctuation.Semicolon,
Identifier("b"),
Operators.Equals,
Identifier("i"),
Operators.LessThan,
Identifier("i"),
Operators.AmpersandAmpersand,
Identifier("i"),
Operators.GreaterThan,
Identifier("i"),
Punctuation.Semicolon,
Keyword("int"),
Operators.QuestionMark,
Local("ii"),
Operators.Equals,
Number("5"),
Punctuation.Semicolon,
Keyword("int"),
Local("f"),
Operators.Equals,
Keyword("true"),
Operators.QuestionMark,
Number("1"),
Operators.Colon,
Number("0"),
Punctuation.Semicolon,
Identifier("i"),
Operators.PlusPlus,
Punctuation.Semicolon,
Identifier("i"),
Operators.MinusMinus,
Punctuation.Semicolon,
Identifier("b"),
Operators.Equals,
Keyword("true"),
Operators.AmpersandAmpersand,
Keyword("false"),
Operators.BarBar,
Keyword("true"),
Punctuation.Semicolon,
Identifier("i"),
Operators.LessThanLessThan,
Number("5"),
Punctuation.Semicolon,
Identifier("i"),
Operators.GreaterThanGreaterThan,
Number("5"),
Punctuation.Semicolon,
Identifier("i"),
Operators.GreaterThanGreaterThanGreaterThan,
Number("5"),
Punctuation.Semicolon,
Identifier("b"),
Operators.Equals,
Identifier("i"),
Operators.EqualsEquals,
Identifier("i"),
Operators.AmpersandAmpersand,
Identifier("i"),
Operators.ExclamationEquals,
Identifier("i"),
Operators.AmpersandAmpersand,
Identifier("i"),
Operators.LessThanEquals,
Identifier("i"),
Operators.AmpersandAmpersand,
Identifier("i"),
Operators.GreaterThanEquals,
Identifier("i"),
Punctuation.Semicolon,
Identifier("i"),
Operators.PlusEquals,
Number("5.0"),
Punctuation.Semicolon,
Identifier("i"),
Operators.MinusEquals,
Identifier("i"),
Punctuation.Semicolon,
Identifier("i"),
Operators.AsteriskEquals,
Identifier("i"),
Punctuation.Semicolon,
Identifier("i"),
Operators.SlashEquals,
Identifier("i"),
Punctuation.Semicolon,
Identifier("i"),
Operators.PercentEquals,
Identifier("i"),
Punctuation.Semicolon,
Identifier("i"),
Operators.AmpersandEquals,
Identifier("i"),
Punctuation.Semicolon,
Identifier("i"),
Operators.BarEquals,
Identifier("i"),
Punctuation.Semicolon,
Identifier("i"),
Operators.CaretEquals,
Identifier("i"),
Punctuation.Semicolon,
Identifier("i"),
Operators.LessThanLessThanEquals,
Identifier("i"),
Punctuation.Semicolon,
Identifier("i"),
Operators.GreaterThanGreaterThanEquals,
Identifier("i"),
Punctuation.Semicolon,
Identifier("i"),
Operators.GreaterThanGreaterThanGreaterThanEquals,
Identifier("i"),
Punctuation.Semicolon,
Identifier("i"),
Operators.QuestionQuestionEquals,
Identifier("i"),
Punctuation.Semicolon,
Keyword("object"),
Local("s"),
Operators.Equals,
Parameter("x"),
Operators.EqualsGreaterThan,
Identifier("x"),
Operators.Plus,
Number("1"),
Punctuation.Semicolon,
Identifier("Point"),
Local("point"),
Punctuation.Semicolon,
Keyword("unsafe"),
Punctuation.OpenCurly,
Identifier("Point"),
Operators.Asterisk,
Local("p"),
Operators.Equals,
Operators.Ampersand,
Identifier("point"),
Punctuation.Semicolon,
Identifier("p"),
Operators.MinusGreaterThan,
Identifier("x"),
Operators.Equals,
Number("10"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Identifier("IO"),
Operators.ColonColon,
Identifier("BinaryReader"),
Local("br"),
Operators.Equals,
Keyword("null"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestPartialMethodWithNamePartial(TestHost testHost)
{
await TestAsync(
"""
partial class C
{
partial void partial(string bar);
partial void partial(string baz)
{
}
partial int Goo();
partial int Goo()
{
}
public partial void partial void
}
""",
testHost,
Keyword("partial"),
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("partial"),
Keyword("void"),
Method("partial"),
Punctuation.OpenParen,
Keyword("string"),
Parameter("bar"),
Punctuation.CloseParen,
Punctuation.Semicolon,
Keyword("partial"),
Keyword("void"),
Method("partial"),
Punctuation.OpenParen,
Keyword("string"),
Parameter("baz"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("partial"),
Keyword("int"),
Method("Goo"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
Keyword("partial"),
Keyword("int"),
Method("Goo"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("public"),
Keyword("partial"),
Keyword("void"),
Field("partial"),
Keyword("void"),
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task ValueInSetterAndAnonymousTypePropertyName(TestHost testHost)
{
await TestAsync(
"""
class C
{
int P
{
set
{
var t = new { value = value };
}
}
}
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("int"),
Property("P"),
Punctuation.OpenCurly,
Keyword("set"),
Punctuation.OpenCurly,
Keyword("var"),
Local("t"),
Operators.Equals,
Keyword("new"),
Punctuation.OpenCurly,
Identifier("value"),
Operators.Equals,
Identifier("value"),
Punctuation.CloseCurly,
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538680")]
[CombinatorialData]
public async Task TestValueInLabel(TestHost testHost)
{
await TestAsync(
"""
class C
{
int X
{
set
{
value:
;
}
}
}
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("int"),
Property("X"),
Punctuation.OpenCurly,
Keyword("set"),
Punctuation.OpenCurly,
Label("value"),
Punctuation.Colon,
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541150")]
[CombinatorialData]
public async Task TestGenericVar(TestHost testHost)
{
await TestAsync(
"""
using System;
static class Program
{
static void Main()
{
var x = 1;
}
}
class var<T>
{
}
""",
testHost,
Keyword("using"),
Identifier("System"),
Punctuation.Semicolon,
Keyword("static"),
Keyword("class"),
Class("Program"),
Static("Program"),
Punctuation.OpenCurly,
Keyword("static"),
Keyword("void"),
Method("Main"),
Static("Main"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("var"),
Local("x"),
Operators.Equals,
Number("1"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("var"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541154")]
[CombinatorialData]
public async Task TestInaccessibleVar(TestHost testHost)
{
await TestAsync(
"""
using System;
class A
{
private class var
{
}
}
class B : A
{
static void Main()
{
var x = 1;
}
}
""",
testHost,
Keyword("using"),
Identifier("System"),
Punctuation.Semicolon,
Keyword("class"),
Class("A"),
Punctuation.OpenCurly,
Keyword("private"),
Keyword("class"),
Class("var"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("B"),
Punctuation.Colon,
Identifier("A"),
Punctuation.OpenCurly,
Keyword("static"),
Keyword("void"),
Method("Main"),
Static("Main"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("var"),
Local("x"),
Operators.Equals,
Number("1"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541613")]
[CombinatorialData]
public async Task TestEscapedVar(TestHost testHost)
{
await TestAsync(
"""
class Program
{
static void Main(string[] args)
{
@var v = 1;
}
}
""",
testHost,
Keyword("class"),
Class("Program"),
Punctuation.OpenCurly,
Keyword("static"),
Keyword("void"),
Method("Main"),
Static("Main"),
Punctuation.OpenParen,
Keyword("string"),
Punctuation.OpenBracket,
Punctuation.CloseBracket,
Parameter("args"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Identifier("@var"),
Local("v"),
Operators.Equals,
Number("1"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542432")]
[CombinatorialData]
public async Task TestVar(TestHost testHost)
{
await TestAsync(
"""
class Program
{
class var<T>
{
}
static var<int> GetVarT()
{
return null;
}
static void Main()
{
var x = GetVarT();
var y = new var<int>();
}
}
""",
testHost,
Keyword("class"),
Class("Program"),
Punctuation.OpenCurly,
Keyword("class"),
Class("var"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("static"),
Identifier("var"),
Punctuation.OpenAngle,
Keyword("int"),
Punctuation.CloseAngle,
Method("GetVarT"),
Static("GetVarT"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
ControlKeyword("return"),
Keyword("null"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Keyword("static"),
Keyword("void"),
Method("Main"),
Static("Main"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("var"),
Local("x"),
Operators.Equals,
Identifier("GetVarT"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
Keyword("var"),
Local("y"),
Operators.Equals,
Keyword("new"),
Identifier("var"),
Punctuation.OpenAngle,
Keyword("int"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543123")]
[CombinatorialData]
public async Task TestVar2(TestHost testHost)
{
await TestAsync(
"""
class Program
{
void Main(string[] args)
{
foreach (var v in args)
{
}
}
}
""",
testHost,
Keyword("class"),
Class("Program"),
Punctuation.OpenCurly,
Keyword("void"),
Method("Main"),
Punctuation.OpenParen,
Keyword("string"),
Punctuation.OpenBracket,
Punctuation.CloseBracket,
Parameter("args"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
ControlKeyword("foreach"),
Punctuation.OpenParen,
Identifier("var"),
Local("v"),
ControlKeyword("in"),
Identifier("args"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task InterpolatedStrings1(TestHost testHost)
{
var code = """
var x = "World";
var y = $"Hello, {x}";
""";
await TestInMethodAsync(code,
testHost,
Keyword("var"),
Local("x"),
Operators.Equals,
String("""
"World"
"""),
Punctuation.Semicolon,
Keyword("var"),
Local("y"),
Operators.Equals,
String("""
$"
"""),
String("Hello, "),
Punctuation.OpenCurly,
Identifier("x"),
Punctuation.CloseCurly,
String("""
"
"""),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task InterpolatedStrings2(TestHost testHost)
{
var code = """
var a = "Hello";
var b = "World";
var c = $"{a}, {b}";
""";
await TestInMethodAsync(code,
testHost,
Keyword("var"),
Local("a"),
Operators.Equals,
String("""
"Hello"
"""),
Punctuation.Semicolon,
Keyword("var"),
Local("b"),
Operators.Equals,
String("""
"World"
"""),
Punctuation.Semicolon,
Keyword("var"),
Local("c"),
Operators.Equals,
String("""
$"
"""),
Punctuation.OpenCurly,
Identifier("a"),
Punctuation.CloseCurly,
String(", "),
Punctuation.OpenCurly,
Identifier("b"),
Punctuation.CloseCurly,
String("""
"
"""),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task InterpolatedStrings3(TestHost testHost)
{
var code = """
var a = "Hello";
var b = "World";
var c = $@"{a}, {b}";
""";
await TestInMethodAsync(code,
testHost,
Keyword("var"),
Local("a"),
Operators.Equals,
String("""
"Hello"
"""),
Punctuation.Semicolon,
Keyword("var"),
Local("b"),
Operators.Equals,
String("""
"World"
"""),
Punctuation.Semicolon,
Keyword("var"),
Local("c"),
Operators.Equals,
Verbatim("""
$@"
"""),
Punctuation.OpenCurly,
Identifier("a"),
Punctuation.CloseCurly,
Verbatim(", "),
Punctuation.OpenCurly,
Identifier("b"),
Punctuation.CloseCurly,
Verbatim("""
"
"""),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task ExceptionFilter1(TestHost testHost)
{
var code = """
try
{
}
catch when (true)
{
}
""";
await TestInMethodAsync(code,
testHost,
ControlKeyword("try"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
ControlKeyword("catch"),
ControlKeyword("when"),
Punctuation.OpenParen,
Keyword("true"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task ExceptionFilter2(TestHost testHost)
{
var code = """
try
{
}
catch (System.Exception) when (true)
{
}
""";
await TestInMethodAsync(code,
testHost,
ControlKeyword("try"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
ControlKeyword("catch"),
Punctuation.OpenParen,
Identifier("System"),
Operators.Dot,
Identifier("Exception"),
Punctuation.CloseParen,
ControlKeyword("when"),
Punctuation.OpenParen,
Keyword("true"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task OutVar(TestHost testHost)
{
var code = """
F(out var);
""";
await TestInMethodAsync(code,
testHost,
Identifier("F"),
Punctuation.OpenParen,
Keyword("out"),
Identifier("var"),
Punctuation.CloseParen,
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task ReferenceDirective(TestHost testHost)
{
var code = """
#r "file.dll"
""";
await TestAsync(code,
testHost,
PPKeyword("#"),
PPKeyword("r"),
String("""
"file.dll"
"""));
}
[Theory, CombinatorialData]
public async Task LoadDirective(TestHost testHost)
{
var code = """
#load "file.csx"
""";
await TestAsync(code,
testHost,
PPKeyword("#"),
PPKeyword("load"),
String("""
"file.csx"
"""));
}
[Theory, CombinatorialData]
public async Task IncompleteAwaitInNonAsyncContext(TestHost testHost)
{
var code = """
void M()
{
var x = await
}
""";
await TestInClassAsync(code,
testHost,
Keyword("void"),
Method("M"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("var"),
Local("x"),
Operators.Equals,
Keyword("await"),
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task CompleteAwaitInNonAsyncContext(TestHost testHost)
{
var code = """
void M()
{
var x = await;
}
""";
await TestInClassAsync(code,
testHost,
Keyword("void"),
Method("M"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("var"),
Local("x"),
Operators.Equals,
Identifier("await"),
Punctuation.Semicolon,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TupleDeclaration(TestHost testHost)
{
await TestInMethodAsync("(int, string) x",
testHost,
ParseOptions(TestOptions.Regular, Options.Script),
Punctuation.OpenParen,
Keyword("int"),
Punctuation.Comma,
Keyword("string"),
Punctuation.CloseParen,
Local("x"));
}
[Theory, CombinatorialData]
public async Task TupleDeclarationWithNames(TestHost testHost)
{
await TestInMethodAsync("(int a, string b) x",
testHost,
ParseOptions(TestOptions.Regular, Options.Script),
Punctuation.OpenParen,
Keyword("int"),
Identifier("a"),
Punctuation.Comma,
Keyword("string"),
Identifier("b"),
Punctuation.CloseParen,
Local("x"));
}
[Theory, CombinatorialData]
public async Task TupleLiteral(TestHost testHost)
{
await TestInMethodAsync("var values = (1, 2)",
testHost,
ParseOptions(TestOptions.Regular, Options.Script),
Keyword("var"),
Local("values"),
Operators.Equals,
Punctuation.OpenParen,
Number("1"),
Punctuation.Comma,
Number("2"),
Punctuation.CloseParen);
}
[Theory, CombinatorialData]
public async Task TupleLiteralWithNames(TestHost testHost)
{
await TestInMethodAsync("var values = (a: 1, b: 2)",
testHost,
ParseOptions(TestOptions.Regular, Options.Script),
Keyword("var"),
Local("values"),
Operators.Equals,
Punctuation.OpenParen,
Identifier("a"),
Punctuation.Colon,
Number("1"),
Punctuation.Comma,
Identifier("b"),
Punctuation.Colon,
Number("2"),
Punctuation.CloseParen);
}
[Theory, CombinatorialData]
public async Task TestConflictMarkers1(TestHost testHost)
{
await TestAsync(
"""
class C
{
<<<<<<< Start
public void Goo();
=======
public void Bar();
>>>>>>> End
}
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Comment("<<<<<<< Start"),
Keyword("public"),
Keyword("void"),
Method("Goo"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
Comment("======="),
Keyword("public"),
Keyword("void"),
Identifier("Bar"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
Comment(">>>>>>> End"),
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestConflictMarkers2(TestHost testHost)
{
await TestAsync(
"""
class C
{
<<<<<<< Start
public void Goo();
||||||| Baseline
int removed;
=======
public void Bar();
>>>>>>> End
}
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Comment("<<<<<<< Start"),
Keyword("public"),
Keyword("void"),
Method("Goo"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
Comment("||||||| Baseline"),
Keyword("int"),
Identifier("removed"),
Punctuation.Semicolon,
Comment("======="),
Keyword("public"),
Keyword("void"),
Identifier("Bar"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
Comment(">>>>>>> End"),
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestUnmanagedConstraint_InsideMethod(TestHost testHost)
{
await TestInMethodAsync("""
var unmanaged = 0;
unmanaged++;
""",
testHost,
Keyword("var"),
Local("unmanaged"),
Operators.Equals,
Number("0"),
Punctuation.Semicolon,
Identifier("unmanaged"),
Operators.PlusPlus,
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestUnmanagedConstraint_Type_Keyword(TestHost testHost)
{
await TestAsync(
"class X<T> where T : unmanaged { }",
testHost,
Keyword("class"),
Class("X"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestUnmanagedConstraint_Type_ExistingInterface(TestHost testHost)
{
await TestAsync("""
interface unmanaged {}
class X<T> where T : unmanaged { }
""",
testHost,
Keyword("interface"),
Interface("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("X"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestUnmanagedConstraint_Type_ExistingInterfaceButOutOfScope(TestHost testHost)
{
await TestAsync("""
namespace OtherScope
{
interface unmanaged {}
}
class X<T> where T : unmanaged { }
""",
testHost,
Keyword("namespace"),
Namespace("OtherScope"),
Punctuation.OpenCurly,
Keyword("interface"),
Interface("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("X"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestUnmanagedConstraint_Method_Keyword(TestHost testHost)
{
await TestAsync("""
class X
{
void M<T>() where T : unmanaged { }
}
""",
testHost,
Keyword("class"),
Class("X"),
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestUnmanagedConstraint_Method_ExistingInterface(TestHost testHost)
{
await TestAsync("""
interface unmanaged {}
class X
{
void M<T>() where T : unmanaged { }
}
""",
testHost,
Keyword("interface"),
Interface("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("X"),
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestUnmanagedConstraint_Method_ExistingInterfaceButOutOfScope(TestHost testHost)
{
await TestAsync("""
namespace OtherScope
{
interface unmanaged {}
}
class X
{
void M<T>() where T : unmanaged { }
}
""",
testHost,
Keyword("namespace"),
Namespace("OtherScope"),
Punctuation.OpenCurly,
Keyword("interface"),
Interface("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("X"),
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestUnmanagedConstraint_Delegate_Keyword(TestHost testHost)
{
await TestAsync(
"delegate void D<T>() where T : unmanaged;",
testHost,
Keyword("delegate"),
Keyword("void"),
Delegate("D"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("unmanaged"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestUnmanagedConstraint_Delegate_ExistingInterface(TestHost testHost)
{
await TestAsync("""
interface unmanaged {}
delegate void D<T>() where T : unmanaged;
""",
testHost,
Keyword("interface"),
Interface("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("delegate"),
Keyword("void"),
Delegate("D"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("unmanaged"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestUnmanagedConstraint_Delegate_ExistingInterfaceButOutOfScope(TestHost testHost)
{
await TestAsync("""
namespace OtherScope
{
interface unmanaged {}
}
delegate void D<T>() where T : unmanaged;
""",
testHost,
Keyword("namespace"),
Namespace("OtherScope"),
Punctuation.OpenCurly,
Keyword("interface"),
Interface("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Keyword("delegate"),
Keyword("void"),
Delegate("D"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("unmanaged"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestUnmanagedConstraint_LocalFunction_Keyword(TestHost testHost)
{
await TestAsync("""
class X
{
void N()
{
void M<T>() where T : unmanaged { }
}
}
""",
testHost,
Keyword("class"),
Class("X"),
Punctuation.OpenCurly,
Keyword("void"),
Method("N"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestUnmanagedConstraint_LocalFunction_ExistingInterface(TestHost testHost)
{
await TestAsync("""
interface unmanaged {}
class X
{
void N()
{
void M<T>() where T : unmanaged { }
}
}
""",
testHost,
Keyword("interface"),
Interface("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("X"),
Punctuation.OpenCurly,
Keyword("void"),
Method("N"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestUnmanagedConstraint_LocalFunction_ExistingInterfaceButOutOfScope(TestHost testHost)
{
await TestAsync("""
namespace OtherScope
{
interface unmanaged {}
}
class X
{
void N()
{
void M<T>() where T : unmanaged { }
}
}
""",
testHost,
Keyword("namespace"),
Namespace("OtherScope"),
Punctuation.OpenCurly,
Keyword("interface"),
Interface("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("X"),
Punctuation.OpenCurly,
Keyword("void"),
Method("N"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("unmanaged"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestDeclarationIsPattern(TestHost testHost)
{
await TestInMethodAsync("""
object foo;
if (foo is Action action)
{
}
""",
testHost,
Keyword("object"),
Local("foo"),
Punctuation.Semicolon,
ControlKeyword("if"),
Punctuation.OpenParen,
Identifier("foo"),
Keyword("is"),
Identifier("Action"),
Local("action"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestDeclarationSwitchPattern(TestHost testHost)
{
await TestInMethodAsync("""
object y;
switch (y)
{
case int x:
break;
}
""",
testHost,
Keyword("object"),
Local("y"),
Punctuation.Semicolon,
ControlKeyword("switch"),
Punctuation.OpenParen,
Identifier("y"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
ControlKeyword("case"),
Keyword("int"),
Local("x"),
Punctuation.Colon,
ControlKeyword("break"),
Punctuation.Semicolon,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestDeclarationExpression(TestHost testHost)
{
await TestInMethodAsync("""
int (foo, bar) = (1, 2);
""",
testHost,
Keyword("int"),
Punctuation.OpenParen,
Local("foo"),
Punctuation.Comma,
Local("bar"),
Punctuation.CloseParen,
Operators.Equals,
Punctuation.OpenParen,
Number("1"),
Punctuation.Comma,
Number("2"),
Punctuation.CloseParen,
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
[WorkItem("https://github.com/dotnet/roslyn/issues/18956")]
public async Task TestListPattern(TestHost testHost)
{
await TestInMethodAsync("""
switch (new int[0])
{
case [1, 2]:
break;
case [1, .. var end]:
break;
}
""",
testHost,
ControlKeyword("switch"),
Punctuation.OpenParen,
Keyword("new"),
Keyword("int"),
Punctuation.OpenBracket,
Number("0"),
Punctuation.CloseBracket,
Punctuation.CloseParen,
Punctuation.OpenCurly,
ControlKeyword("case"),
Punctuation.OpenBracket,
Number("1"),
Punctuation.Comma,
Number("2"),
Punctuation.CloseBracket,
Punctuation.Colon,
ControlKeyword("break"),
Punctuation.Semicolon,
ControlKeyword("case"),
Punctuation.OpenBracket,
Number("1"),
Punctuation.Comma,
Punctuation.DotDot,
Keyword("var"),
Local("end"),
Punctuation.CloseBracket,
Punctuation.Colon,
ControlKeyword("break"),
Punctuation.Semicolon,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
[WorkItem("https://github.com/dotnet/roslyn/issues/18956")]
public async Task TestListPattern2(TestHost testHost)
{
await TestInMethodAsync("""
_ = x switch
{
[var start, .. var end] => 1
}
""",
testHost,
Identifier("_"),
Operators.Equals,
Identifier("x"),
ControlKeyword("switch"),
Punctuation.OpenCurly,
Punctuation.OpenBracket,
Keyword("var"),
Local("start"),
Punctuation.Comma,
Punctuation.DotDot,
Keyword("var"),
Local("end"),
Punctuation.CloseBracket,
Operators.EqualsGreaterThan,
Number("1"),
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
[WorkItem("https://github.com/dotnet/roslyn/issues/18956")]
public async Task TestVarPattern(TestHost testHost)
{
await TestInMethodAsync("""
_ = 1 is var x;
""",
testHost,
Identifier("_"),
Operators.Equals,
Number("1"),
Keyword("is"),
Keyword("var"),
Local("x"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestTupleTypeSyntax(TestHost testHost)
{
await TestInClassAsync("""
public (int a, int b) Get() => null;
""",
testHost,
Keyword("public"),
Punctuation.OpenParen,
Keyword("int"),
Identifier("a"),
Punctuation.Comma,
Keyword("int"),
Identifier("b"),
Punctuation.CloseParen,
Method("Get"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Operators.EqualsGreaterThan,
Keyword("null"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestOutParameter(TestHost testHost)
{
await TestInMethodAsync("""
if (int.TryParse("1", out int x))
{
}
""",
testHost,
ControlKeyword("if"),
Punctuation.OpenParen,
Keyword("int"),
Operators.Dot,
Identifier("TryParse"),
Punctuation.OpenParen,
String("""
"1"
"""),
Punctuation.Comma,
Keyword("out"),
Keyword("int"),
Local("x"),
Punctuation.CloseParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestOutParameter2(TestHost testHost)
{
await TestInClassAsync("""
int F = int.TryParse("1", out int x) ? x : -1;
""",
testHost,
Keyword("int"),
Field("F"),
Operators.Equals,
Keyword("int"),
Operators.Dot,
Identifier("TryParse"),
Punctuation.OpenParen,
String("""
"1"
"""),
Punctuation.Comma,
Keyword("out"),
Keyword("int"),
Local("x"),
Punctuation.CloseParen,
Operators.QuestionMark,
Identifier("x"),
Operators.Colon,
Operators.Minus,
Number("1"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestUsingDirective(TestHost testHost)
{
var code = @"using System.Collections.Generic;";
await TestAsync(code,
testHost,
Keyword("using"),
Identifier("System"),
Operators.Dot,
Identifier("Collections"),
Operators.Dot,
Identifier("Generic"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestUsingAliasDirectiveForIdentifier(TestHost testHost)
{
var code = @"using Col = System.Collections;";
await TestAsync(code,
testHost,
Keyword("using"),
Identifier("Col"),
Operators.Equals,
Identifier("System"),
Operators.Dot,
Identifier("Collections"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestUsingAliasDirectiveForClass(TestHost testHost)
{
var code = @"using Con = System.Console;";
await TestAsync(code,
testHost,
Keyword("using"),
Identifier("Con"),
Operators.Equals,
Identifier("System"),
Operators.Dot,
Identifier("Console"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestUsingStaticDirective(TestHost testHost)
{
var code = @"using static System.Console;";
await TestAsync(code,
testHost,
Keyword("using"),
Keyword("static"),
Identifier("System"),
Operators.Dot,
Identifier("Console"),
Punctuation.Semicolon);
}
[Theory, WorkItem("https://github.com/dotnet/roslyn/issues/33039")]
[CombinatorialData]
public async Task ForEachVariableStatement(TestHost testHost)
{
await TestInMethodAsync("""
foreach (var (x, y) in new[] { (1, 2) });
""",
testHost,
ControlKeyword("foreach"),
Punctuation.OpenParen,
Identifier("var"),
Punctuation.OpenParen,
Local("x"),
Punctuation.Comma,
Local("y"),
Punctuation.CloseParen,
ControlKeyword("in"),
Keyword("new"),
Punctuation.OpenBracket,
Punctuation.CloseBracket,
Punctuation.OpenCurly,
Punctuation.OpenParen,
Number("1"),
Punctuation.Comma,
Number("2"),
Punctuation.CloseParen,
Punctuation.CloseCurly,
Punctuation.CloseParen,
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task CatchDeclarationStatement(TestHost testHost)
{
await TestInMethodAsync("""
try { } catch (Exception ex) { }
""",
testHost,
ControlKeyword("try"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
ControlKeyword("catch"),
Punctuation.OpenParen,
Identifier("Exception"),
Local("ex"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestNotNullConstraint_InsideMethod(TestHost testHost)
{
await TestInMethodAsync("""
var notnull = 0;
notnull++;
""",
testHost,
Keyword("var"),
Local("notnull"),
Operators.Equals,
Number("0"),
Punctuation.Semicolon,
Identifier("notnull"),
Operators.PlusPlus,
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestNotNullConstraint_Type_Keyword(TestHost testHost)
{
await TestAsync(
"class X<T> where T : notnull { }",
testHost,
Keyword("class"),
Class("X"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestNotNullConstraint_Type_ExistingInterface(TestHost testHost)
{
await TestAsync("""
interface notnull {}
class X<T> where T : notnull { }
""",
testHost,
Keyword("interface"),
Interface("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("X"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestNotNullConstraint_Type_ExistingInterfaceButOutOfScope(TestHost testHost)
{
await TestAsync("""
namespace OtherScope
{
interface notnull {}
}
class X<T> where T : notnull { }
""",
testHost,
Keyword("namespace"),
Namespace("OtherScope"),
Punctuation.OpenCurly,
Keyword("interface"),
Interface("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("X"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestNotNullConstraint_Method_Keyword(TestHost testHost)
{
await TestAsync("""
class X
{
void M<T>() where T : notnull { }
}
""",
testHost,
Keyword("class"),
Class("X"),
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestNotNullConstraint_Method_ExistingInterface(TestHost testHost)
{
await TestAsync("""
interface notnull {}
class X
{
void M<T>() where T : notnull { }
}
""",
testHost,
Keyword("interface"),
Interface("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("X"),
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestNotNullConstraint_Method_ExistingInterfaceButOutOfScope(TestHost testHost)
{
await TestAsync("""
namespace OtherScope
{
interface notnull {}
}
class X
{
void M<T>() where T : notnull { }
}
""",
testHost,
Keyword("namespace"),
Namespace("OtherScope"),
Punctuation.OpenCurly,
Keyword("interface"),
Interface("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("X"),
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestNotNullConstraint_Delegate_Keyword(TestHost testHost)
{
await TestAsync(
"delegate void D<T>() where T : notnull;",
testHost,
Keyword("delegate"),
Keyword("void"),
Delegate("D"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("notnull"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestNotNullConstraint_Delegate_ExistingInterface(TestHost testHost)
{
await TestAsync("""
interface notnull {}
delegate void D<T>() where T : notnull;
""",
testHost,
Keyword("interface"),
Interface("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("delegate"),
Keyword("void"),
Delegate("D"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("notnull"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestNotNullConstraint_Delegate_ExistingInterfaceButOutOfScope(TestHost testHost)
{
await TestAsync("""
namespace OtherScope
{
interface notnull {}
}
delegate void D<T>() where T : notnull;
""",
testHost,
Keyword("namespace"),
Namespace("OtherScope"),
Punctuation.OpenCurly,
Keyword("interface"),
Interface("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Keyword("delegate"),
Keyword("void"),
Delegate("D"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("notnull"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestNotNullConstraint_LocalFunction_Keyword(TestHost testHost)
{
await TestAsync("""
class X
{
void N()
{
void M<T>() where T : notnull { }
}
}
""",
testHost,
Keyword("class"),
Class("X"),
Punctuation.OpenCurly,
Keyword("void"),
Method("N"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestNotNullConstraint_LocalFunction_ExistingInterface(TestHost testHost)
{
await TestAsync("""
interface notnull {}
class X
{
void N()
{
void M<T>() where T : notnull { }
}
}
""",
testHost,
Keyword("interface"),
Interface("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("X"),
Punctuation.OpenCurly,
Keyword("void"),
Method("N"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestNotNullConstraint_LocalFunction_ExistingInterfaceButOutOfScope(TestHost testHost)
{
await TestAsync("""
namespace OtherScope
{
interface notnull {}
}
class X
{
void N()
{
void M<T>() where T : notnull { }
}
}
""",
testHost,
Keyword("namespace"),
Namespace("OtherScope"),
Punctuation.OpenCurly,
Keyword("interface"),
Interface("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Keyword("class"),
Class("X"),
Punctuation.OpenCurly,
Keyword("void"),
Method("N"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("notnull"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
[WorkItem("https://github.com/dotnet/roslyn/issues/45807")]
public async Task FunctionPointer(TestHost testHost)
{
var code = """
class C
{
delegate* unmanaged[Stdcall, SuppressGCTransition] <int, int> x;
}
""";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("delegate"),
Operators.Asterisk,
Keyword("unmanaged"),
Punctuation.OpenBracket,
Identifier("Stdcall"),
Punctuation.Comma,
Identifier("SuppressGCTransition"),
Punctuation.CloseBracket,
Punctuation.OpenAngle,
Keyword("int"),
Punctuation.Comma,
Keyword("int"),
Punctuation.CloseAngle,
Field("x"),
Punctuation.Semicolon,
Punctuation.CloseCurly);
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/48094")]
public async Task TestXmlAttributeNameSpan1()
{
var source = @"/// <param name=""value""></param>";
using var workspace = CreateWorkspace(source, options: null, TestHost.InProcess);
var document = workspace.CurrentSolution.Projects.First().Documents.First();
var classifications = await GetSyntacticClassificationsAsync(document, [new TextSpan(0, source.Length)]);
AssertEx.Equal(
[
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentDelimiter, new TextSpan(0, 3)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentText, new TextSpan(3, 1)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentDelimiter, new TextSpan(4, 1)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentName, new TextSpan(5, 5)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentAttributeName, new TextSpan(11, 4)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentDelimiter, new TextSpan(15, 1)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentAttributeQuotes, new TextSpan(16, 1)),
new ClassifiedSpan(ClassificationTypeNames.Identifier, new TextSpan(17, 5)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentAttributeQuotes, new TextSpan(22, 1)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentDelimiter, new TextSpan(23, 1)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentDelimiter, new TextSpan(24, 2)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentName, new TextSpan(26, 5)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentDelimiter, new TextSpan(31, 1))
], classifications);
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/48094")]
public async Task TestXmlAttributeNameSpan2()
{
var source = """
/// <param
/// name="value"></param>
""";
using var workspace = CreateWorkspace(source, options: null, TestHost.InProcess);
var document = workspace.CurrentSolution.Projects.First().Documents.First();
var classifications = await GetSyntacticClassificationsAsync(document, [new TextSpan(0, source.Length)]);
AssertEx.Equal(
[
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentDelimiter, new TextSpan(2, 3)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentText, new TextSpan(5, 1)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentDelimiter, new TextSpan(6, 1)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentName, new TextSpan(7, 5)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentDelimiter, new TextSpan(14, 3)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentAttributeName, new TextSpan(18, 4)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentDelimiter, new TextSpan(22, 1)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentAttributeQuotes, new TextSpan(23, 1)),
new ClassifiedSpan(ClassificationTypeNames.Identifier, new TextSpan(24, 5)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentAttributeQuotes, new TextSpan(29, 1)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentDelimiter, new TextSpan(30, 1)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentDelimiter, new TextSpan(31, 2)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentName, new TextSpan(33, 5)),
new ClassifiedSpan(ClassificationTypeNames.XmlDocCommentDelimiter, new TextSpan(38, 1))
], classifications);
}
[Theory, WorkItem("https://github.com/dotnet/roslyn/issues/52290")]
[CombinatorialData]
public async Task TestStaticLocalFunction(TestHost testHost)
{
var code = """
class C
{
public static void M()
{
static void LocalFunc() { }
}
}
""";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("public"),
Keyword("static"),
Keyword("void"),
Method("M"),
Static("M"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("static"),
Keyword("void"),
Method("LocalFunc"),
Static("LocalFunc"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, WorkItem("https://github.com/dotnet/roslyn/issues/52290")]
[CombinatorialData]
public async Task TestConstantLocalVariable(TestHost testHost)
{
var code = """
class C
{
public static void M()
{
const int Zero = 0;
}
}
""";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("public"),
Keyword("static"),
Keyword("void"),
Method("M"),
Static("M"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("const"),
Keyword("int"),
Constant("Zero"),
Static("Zero"),
Operators.Equals,
Number("0"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestRawStringLiteral(TestHost testHost)
{
var code = """"
class C
{
public static void M(int x)
{
var s = """Hello world""";
}
}
"""";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("public"),
Keyword("static"),
Keyword("void"),
Method("M"),
Static("M"),
Punctuation.OpenParen,
Keyword("int"),
Parameter("x"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("var"),
Local("s"),
Operators.Equals,
String(""""
"""Hello world"""
""""),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestRawStringLiteralUtf8_01(TestHost testHost)
{
var code = """"
class C
{
public static void M(int x)
{
var s = """Hello world"""u8;
}
}
"""";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("public"),
Keyword("static"),
Keyword("void"),
Method("M"),
Static("M"),
Punctuation.OpenParen,
Keyword("int"),
Parameter("x"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("var"),
Local("s"),
Operators.Equals,
String(""""
"""Hello world"""
""""),
Keyword("u8"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestRawStringLiteralUtf8_02(TestHost testHost)
{
var code = """"
class C
{
public static void M(int x)
{
var s = """Hello world"""U8;
}
}
"""";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("public"),
Keyword("static"),
Keyword("void"),
Method("M"),
Static("M"),
Punctuation.OpenParen,
Keyword("int"),
Parameter("x"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("var"),
Local("s"),
Operators.Equals,
String(""""
"""Hello world"""
""""),
Keyword("U8"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestRawStringLiteralMultiline(TestHost testHost)
{
var code = """"
class C
{
public static void M(int x)
{
var s = """
Hello world
""";
}
}
"""";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("public"),
Keyword("static"),
Keyword("void"),
Method("M"),
Static("M"),
Punctuation.OpenParen,
Keyword("int"),
Parameter("x"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("var"),
Local("s"),
Operators.Equals,
String(""""
"""
Hello world
"""
""""),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestRawStringLiteralMultilineUtf8_01(TestHost testHost)
{
var code = """"
class C
{
public static void M(int x)
{
var s = """
Hello world
"""u8;
}
}
"""";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("public"),
Keyword("static"),
Keyword("void"),
Method("M"),
Static("M"),
Punctuation.OpenParen,
Keyword("int"),
Parameter("x"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("var"),
Local("s"),
Operators.Equals,
String(""""
"""
Hello world
"""
""""),
Keyword("u8"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestRawStringLiteralMultilineUtf8_02(TestHost testHost)
{
var code = """"
class C
{
public static void M(int x)
{
var s = """
Hello world
"""U8;
}
}
"""";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("public"),
Keyword("static"),
Keyword("void"),
Method("M"),
Static("M"),
Punctuation.OpenParen,
Keyword("int"),
Parameter("x"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("var"),
Local("s"),
Operators.Equals,
String(""""
"""
Hello world
"""
""""),
Keyword("U8"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestRawStringLiteralInterpolation1(TestHost testHost)
{
var code = """"
class C
{
public static void M(int x)
{
var s = $"""{x}""";
}
}
"""";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("public"),
Keyword("static"),
Keyword("void"),
Method("M"),
Static("M"),
Punctuation.OpenParen,
Keyword("int"),
Parameter("x"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("var"),
Local("s"),
Operators.Equals,
String(""""
$"""
""""),
Punctuation.OpenCurly,
Identifier("x"),
Punctuation.CloseCurly,
String(""""
"""
""""),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestRawStringLiteralInterpolation2(TestHost testHost)
{
var code = """"
class C
{
public static void M(int x)
{
var s = $$"""{{x}}""";
}
}
"""";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("public"),
Keyword("static"),
Keyword("void"),
Method("M"),
Static("M"),
Punctuation.OpenParen,
Keyword("int"),
Parameter("x"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("var"),
Local("s"),
Operators.Equals,
String(""""
$$"""
""""),
PunctuationText("{{"),
Identifier("x"),
PunctuationText("}}"),
String(""""
"""
""""),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestRawStringLiteralInterpolation3(TestHost testHost)
{
var code = """"
class C
{
public static void M(int x)
{
var s = $$"""{{{x}}}""";
}
}
"""";
await TestAsync(code,
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("public"),
Keyword("static"),
Keyword("void"),
Method("M"),
Static("M"),
Punctuation.OpenParen,
Keyword("int"),
Parameter("x"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("var"),
Local("s"),
Operators.Equals,
String(""""
$$"""
""""),
String("{"),
PunctuationText("{{"),
Identifier("x"),
PunctuationText("}}"),
String("}"),
String(""""
"""
""""),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task CheckedUserDefinedOperators_01(TestHost testHost)
{
await TestInClassAsync(
"""
static T operator checked -(T a)
{
}
""",
testHost,
Keyword("static"),
Identifier("T"),
Keyword("operator"),
Keyword("checked"),
Operators.Minus,
Punctuation.OpenParen,
Identifier("T"),
Parameter("a"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task CheckedUserDefinedOperators_02(TestHost testHost)
{
await TestInClassAsync(
"""
static T operator checked +(T a, T b)
{
}
""",
testHost,
Keyword("static"),
Identifier("T"),
Keyword("operator"),
Keyword("checked"),
Operators.Plus,
Punctuation.OpenParen,
Identifier("T"),
Parameter("a"),
Punctuation.Comma,
Identifier("T"),
Parameter("b"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task CheckedUserDefinedOperators_03(TestHost testHost)
{
await TestInClassAsync(
"""
static explicit operator checked T(T a)
{
}
""",
testHost,
Keyword("static"),
Keyword("explicit"),
Keyword("operator"),
Keyword("checked"),
Identifier("T"),
Punctuation.OpenParen,
Identifier("T"),
Parameter("a"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task CheckedUserDefinedOperators_04(TestHost testHost)
{
await TestInClassAsync(
"""
static T I1.operator checked -(T a)
{
}
""",
testHost,
Keyword("static"),
Identifier("T"),
Identifier("I1"),
Operators.Dot,
Keyword("operator"),
Keyword("checked"),
Operators.Minus,
Punctuation.OpenParen,
Identifier("T"),
Parameter("a"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task CheckedUserDefinedOperators_05(TestHost testHost)
{
await TestInClassAsync(
"""
static T I1.operator checked +(T a, T b)
{
}
""",
testHost,
Keyword("static"),
Identifier("T"),
Identifier("I1"),
Operators.Dot,
Keyword("operator"),
Keyword("checked"),
Operators.Plus,
Punctuation.OpenParen,
Identifier("T"),
Parameter("a"),
Punctuation.Comma,
Identifier("T"),
Parameter("b"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task CheckedUserDefinedOperators_06(TestHost testHost)
{
await TestInClassAsync(
"""
static explicit I1.operator checked T(T a)
{
}
""",
testHost,
Keyword("static"),
Keyword("explicit"),
Identifier("I1"),
Operators.Dot,
Keyword("operator"),
Keyword("checked"),
Identifier("T"),
Punctuation.OpenParen,
Identifier("T"),
Parameter("a"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task UnsignedRightShift_01(TestHost testHost)
{
await TestInClassAsync(
"""
static T operator >>>(T a, int b)
{
}
""",
testHost,
Keyword("static"),
Identifier("T"),
Keyword("operator"),
Operators.GreaterThanGreaterThanGreaterThan,
Punctuation.OpenParen,
Identifier("T"),
Parameter("a"),
Punctuation.Comma,
Keyword("int"),
Parameter("b"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task UnsignedRightShift_02(TestHost testHost)
{
await TestInClassAsync(
"""
static T I1.operator checked >>>(T a, T b)
{
}
""",
testHost,
Keyword("static"),
Identifier("T"),
Identifier("I1"),
Operators.Dot,
Keyword("operator"),
Keyword("checked"),
Operators.GreaterThanGreaterThanGreaterThan,
Punctuation.OpenParen,
Identifier("T"),
Parameter("a"),
Punctuation.Comma,
Identifier("T"),
Parameter("b"),
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestExclamationExclamation(TestHost testHost)
{
await TestAsync(
"""
class C
{
void M(string v!!)
{
}
}
""",
testHost,
Keyword("class"),
Class("C"),
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenParen,
Keyword("string"),
Parameter("v"),
Operators.Exclamation,
Operators.Exclamation,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
/// <seealso cref="SemanticClassifierTests.LocalFunctionUse"/>
/// <seealso cref="TotalClassifierTests.LocalFunctionDeclarationAndUse"/>
[Theory, CombinatorialData]
public async Task LocalFunctionDeclaration(TestHost testHost)
{
await TestAsync(
"""
using System;
class C
{
void M(Action action)
{
[|localFunction();
staticLocalFunction();
M(localFunction);
M(staticLocalFunction);
void localFunction() { }
static void staticLocalFunction() { }|]
}
}
""",
testHost,
Identifier("localFunction"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
Identifier("staticLocalFunction"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.Semicolon,
Identifier("M"),
Punctuation.OpenParen,
Identifier("localFunction"),
Punctuation.CloseParen,
Punctuation.Semicolon,
Identifier("M"),
Punctuation.OpenParen,
Identifier("staticLocalFunction"),
Punctuation.CloseParen,
Punctuation.Semicolon,
Keyword("void"),
Method("localFunction"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Keyword("static"),
Keyword("void"),
Method("staticLocalFunction"),
Static("staticLocalFunction"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task ScopedParameter(TestHost testHost)
{
await TestInMethodAsync(@"interface I { void F(scoped R r); }",
testHost,
Keyword("interface"),
Interface("I"),
Punctuation.OpenCurly,
Keyword("void"),
Method("F"),
Punctuation.OpenParen,
Keyword("scoped"),
Identifier("R"),
Parameter("r"),
Punctuation.CloseParen,
Punctuation.Semicolon,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task ScopedLocalDeclaration(TestHost testHost)
{
await TestInMethodAsync(@"scoped var v;",
testHost,
Keyword("scoped"),
Identifier("var"),
Local("v"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task ScopedOutDeclaration(TestHost testHost)
{
await TestInMethodAsync(@"F(x, out scoped R y);",
testHost,
Identifier("F"),
Punctuation.OpenParen,
Identifier("x"),
Punctuation.Comma,
Keyword("out"),
Keyword("scoped"),
Identifier("R"),
Local("y"),
Punctuation.CloseParen,
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task LambdaDefaultParameter_01(TestHost testHost)
{
await TestAsync(
"""
using System;
class Program
{
void M()
{
const int n = 100;
const int m = 200;
var lam = (int x = n + m) => x;
}
}
""",
testHost,
Keyword("using"),
Identifier("System"),
Punctuation.Semicolon,
Keyword("class"),
Class("Program"),
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("const"),
Keyword("int"),
Constant("n"),
Static("n"),
Operators.Equals,
Number("100"),
Punctuation.Semicolon,
Keyword("const"),
Keyword("int"),
Constant("m"),
Static("m"),
Operators.Equals,
Number("200"),
Punctuation.Semicolon,
Keyword("var"),
Local("lam"),
Operators.Equals,
Punctuation.OpenParen,
Keyword("int"),
Parameter("x"),
Operators.Equals,
Identifier("n"),
Operators.Plus,
Identifier("m"),
Punctuation.CloseParen,
Operators.EqualsGreaterThan,
Identifier("x"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task LambdaDefaultParameter_02(TestHost testHost)
{
await TestAsync(
"""
class Program
{
void M()
{
var lam = (string s = "a string") => s;
}
}
""",
testHost,
Keyword("class"),
Class("Program"),
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenParen,
Punctuation.CloseParen,
Punctuation.OpenCurly,
Keyword("var"),
Local("lam"),
Operators.Equals,
Punctuation.OpenParen,
Keyword("string"),
Parameter("s"),
Operators.Equals,
String("""
"a string"
"""),
Punctuation.CloseParen,
Operators.EqualsGreaterThan,
Identifier("s"),
Punctuation.Semicolon,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task LambdaParamsArray(TestHost testHost)
{
await TestInMethodAsync("var lam = (params int[] xs) => xs.Length;",
testHost,
Keyword("var"),
Local("lam"),
Operators.Equals,
Punctuation.OpenParen,
Keyword("params"),
Keyword("int"),
Punctuation.OpenBracket,
Punctuation.CloseBracket,
Parameter("xs"),
Punctuation.CloseParen,
Operators.EqualsGreaterThan,
Identifier("xs"),
Operators.Dot,
Identifier("Length"),
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task LambdaParamsArray_Multiple(TestHost testHost)
{
await TestInMethodAsync("var lam = (int a, int b = 1, params int[] xs, params int[] ys.Length) => { };",
testHost,
Keyword("var"),
Local("lam"),
Operators.Equals,
Punctuation.OpenParen,
Keyword("int"),
Local("a"),
Punctuation.Comma,
Keyword("int"),
Identifier("b"),
Operators.Equals,
Number("1"),
Punctuation.Comma,
Keyword("params"),
Keyword("int"),
Punctuation.OpenBracket,
Punctuation.CloseBracket,
Local("xs"),
Punctuation.Comma,
Keyword("params"),
Keyword("int"),
Punctuation.OpenBracket,
Punctuation.CloseBracket,
Local("ys"),
Operators.Dot,
Identifier("Length"),
Punctuation.CloseParen,
Operators.EqualsGreaterThan,
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.Semicolon);
}
[Theory, CombinatorialData]
public async Task TestAllowsRefStructConstraint_01(TestHost testHost)
{
await TestAsync(
"class X<T> where T : allows ref struct { }",
testHost,
Keyword("class"),
Class("X"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("allows"),
Keyword("ref"),
Keyword("struct"),
Punctuation.OpenCurly,
Punctuation.CloseCurly);
}
[Theory, CombinatorialData]
public async Task TestAllowsRefStructConstraint_02(TestHost testHost)
{
await TestAsync(
"class X { void M<T>() where T : allows ref struct { } }",
testHost,
Keyword("class"),
Class("X"),
Punctuation.OpenCurly,
Keyword("void"),
Method("M"),
Punctuation.OpenAngle,
TypeParameter("T"),
Punctuation.CloseAngle,
Punctuation.OpenParen,
Punctuation.CloseParen,
Keyword("where"),
Identifier("T"),
Punctuation.Colon,
Keyword("allows"),
Keyword("ref"),
Keyword("struct"),
Punctuation.OpenCurly,
Punctuation.CloseCurly,
Punctuation.CloseCurly);
}
}
|