File: Parsing\RefReadonlyTests.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Syntax\Microsoft.CodeAnalysis.CSharp.Syntax.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Syntax.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using Xunit;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit.Abstractions;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Parsing
{
    [CompilerTrait(CompilerFeature.ReadOnlyReferences)]
    public class RefReadonlyTests : ParsingTests
    {
        public RefReadonlyTests(ITestOutputHelper output) : base(output) { }
 
        protected override SyntaxTree ParseTree(string text, CSharpParseOptions options)
        {
            return SyntaxFactory.ParseSyntaxTree(text, options: options);
        }
 
        [Fact]
        public void RefReadonlyReturn_CSharp7()
        {
            var text = @"
unsafe class Program
{
    delegate ref readonly int D1();
 
    static ref readonly T M<T>()
    {
        return ref (new T[1])[0];
    }
 
    public virtual ref readonly int* P1 => throw null;
 
    public ref readonly int[][] this[int i] => throw null;
}
";
 
            var comp = CreateCompilationWithMscorlib461(text, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_1), options: TestOptions.UnsafeDebugDll);
            comp.VerifyDiagnostics(
                // (4,18): error CS8302: Feature 'readonly references' is not available in C# 7.1. Please use language version 7.2 or greater.
                //     delegate ref readonly int D1();
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "readonly").WithArguments("readonly references", "7.2").WithLocation(4, 18),
                // (6,16): error CS8302: Feature 'readonly references' is not available in C# 7.1. Please use language version 7.2 or greater.
                //     static ref readonly T M<T>()
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "readonly").WithArguments("readonly references", "7.2").WithLocation(6, 16),
                // (11,24): error CS8302: Feature 'readonly references' is not available in C# 7.1. Please use language version 7.2 or greater.
                //     public virtual ref readonly int* P1 => throw null;
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "readonly").WithArguments("readonly references", "7.2").WithLocation(11, 24),
                // (13,16): error CS8302: Feature 'readonly references' is not available in C# 7.1. Please use language version 7.2 or greater.
                //     public ref readonly int[][] this[int i] => throw null;
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "readonly").WithArguments("readonly references", "7.2").WithLocation(13, 16)
            );
        }
 
        [Fact]
        public void InArgs_CSharp7()
        {
            var text = @"
class Program
{
    static void M(in int x)
    {
    }
 
    int this[in int x]
    {
        get
        {
            return 1;
        }
    }
 
    static void Test1()
    {
        int x = 1;
        M(in x);
 
        _ = (new Program())[in x];
    }
}
";
 
            var comp = CreateCompilationWithMscorlib461(text, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_1), options: TestOptions.UnsafeDebugDll);
            comp.VerifyDiagnostics(
                // (4,19): error CS8302: Feature 'readonly references' is not available in C# 7.1. Please use language version 7.2 or greater.
                //     static void M(in int x)
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "in").WithArguments("readonly references", "7.2").WithLocation(4, 19),
                // (8,14): error CS8302: Feature 'readonly references' is not available in C# 7.1. Please use language version 7.2 or greater.
                //     int this[in int x]
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "in").WithArguments("readonly references", "7.2").WithLocation(8, 14),
                // (19,11): error CS8302: Feature 'readonly references' is not available in C# 7.1. Please use language version 7.2 or greater.
                //         M(in x);
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "in").WithArguments("readonly references", "7.2").WithLocation(19, 11),
                // (21,29): error CS8302: Feature 'readonly references' is not available in C# 7.1. Please use language version 7.2 or greater.
                //         _ = (new Program())[in x];
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "in").WithArguments("readonly references", "7.2").WithLocation(21, 29)
            );
        }
 
        [Fact]
        public void RefReadonlyReturn_Unexpected()
        {
            var text = @"
 
class Program
{
    static void Main()
    {
    }
 
    ref readonly int Field;
 
    public static ref readonly Program  operator  +(Program x, Program y)
    {
        throw null;
    }
 
    // this parses fine
    static async ref readonly Task M<T>()
    {
        throw null;
    }
 
    public ref readonly virtual int* P1 => throw null;
 
}
";
 
            ParseAndValidate(text, TestOptions.Regular9,
                // (11,41): error CS1519: Invalid token 'operator' in class, record, struct, or interface member declaration
                //     public static ref readonly Program  operator  +(Program x, Program y)
                Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "operator").WithArguments("operator").WithLocation(11, 41),
                // (11,41): error CS1519: Invalid token 'operator' in class, record, struct, or interface member declaration
                //     public static ref readonly Program  operator  +(Program x, Program y)
                Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "operator").WithArguments("operator").WithLocation(11, 41),
                // (12,5): error CS1519: Invalid token '{' ref readonly class, struct, or interface member declaration
                //     {
                Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "{").WithArguments("{").WithLocation(12, 5),
                // (12,5): error CS1519: Invalid token '{' in class, record, struct, or interface member declaration
                //     {
                Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "{").WithArguments("{").WithLocation(12, 5),
                // (17,5): error CS8803: Top-level statements must precede namespace and type declarations.
                //     static async ref readonly Task M<T>()
                Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, @"static async ref readonly Task M<T>()
    {
        throw null;
    }").WithLocation(17, 5),
                // (22,25): error CS1031: Type expected
                //     public ref readonly virtual int* P1 => throw null;
                Diagnostic(ErrorCode.ERR_TypeExpected, "virtual").WithLocation(22, 25),
                // (24,1): error CS1022: Type or namespace definition, or end-of-file expected
                // }
                Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(24, 1));
        }
 
        [Fact]
        public void RefReadonlyReturn_UnexpectedBindTime()
        {
            var text = @"
 
class Program
{
    static void Main()
    {
        ref readonly int local = ref (new int[1])[0];
 
        (ref readonly int, ref readonly int Alice)? t = null;
 
        System.Collections.Generic.List<ref readonly int> x = null;
 
        Use(local);
        Use(t);
        Use(x);
    }
 
    static void Use<T>(T dummy)
    {
    }
}
";
            var comp = CreateCompilationWithMscorlib461(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef });
            comp.VerifyDiagnostics(
                // (9,10): error CS1073: Unexpected token 'ref'
                //         (ref readonly int, ref readonly int Alice)? t = null;
                Diagnostic(ErrorCode.ERR_UnexpectedToken, "ref").WithArguments("ref").WithLocation(9, 10),
                // (9,28): error CS1073: Unexpected token 'ref'
                //         (ref readonly int, ref readonly int Alice)? t = null;
                Diagnostic(ErrorCode.ERR_UnexpectedToken, "ref").WithArguments("ref").WithLocation(9, 28),
                // (11,41): error CS1073: Unexpected token 'ref'
                //         System.Collections.Generic.List<ref readonly int> x = null;
                Diagnostic(ErrorCode.ERR_UnexpectedToken, "ref").WithArguments("ref").WithLocation(11, 41));
        }
 
        [Fact]
        public void RefReadOnlyLocalsAreDisallowed()
        {
            CreateCompilation(@"
class Test
{
    void M()
    {
        int value = 0;
        ref int valid = ref value;
        ref readonly int invalid = ref readonly value;
    }
}").GetParseDiagnostics().Verify(
                // (8,40): error CS1525: Invalid expression term 'readonly'
                //         ref readonly int invalid = ref readonly value;
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "readonly").WithArguments("readonly").WithLocation(8, 40),
                // (8,40): error CS1002: ; expected
                //         ref readonly int invalid = ref readonly value;
                Diagnostic(ErrorCode.ERR_SemicolonExpected, "readonly").WithLocation(8, 40),
                // (8,40): error CS0106: The modifier 'readonly' is not valid for this item
                //         ref readonly int invalid = ref readonly value;
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "readonly").WithArguments("readonly").WithLocation(8, 40),
                // (8,54): error CS1001: Identifier expected
                //         ref readonly int invalid = ref readonly value;
                Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(8, 54));
        }
 
        [Fact]
        public void LocalsWithRefReadOnlyExpressionsAreDisallowed()
        {
            CreateCompilation(@"
class Test
{
    void M()
    {
        int value = 0;
        ref int valid = ref value;
        ref int invalid = ref readonly value;
    }
}").GetParseDiagnostics().Verify(
                // (8,31): error CS1525: Invalid expression term 'readonly'
                //         ref int invalid = ref readonly value;
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "readonly").WithArguments("readonly").WithLocation(8, 31),
                // (8,31): error CS1002: ; expected
                //         ref int invalid = ref readonly value;
                Diagnostic(ErrorCode.ERR_SemicolonExpected, "readonly").WithLocation(8, 31),
                // (8,31): error CS0106: The modifier 'readonly' is not valid for this item
                //         ref int invalid = ref readonly value;
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "readonly").WithArguments("readonly").WithLocation(8, 31),
                // (8,45): error CS1001: Identifier expected
                //         ref int invalid = ref readonly value;
                Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(8, 45));
        }
 
        [Fact]
        public void ReturnRefReadOnlyAreDisallowed()
        {
            CreateCompilation(@"
class Test
{
    int value = 0;
 
    ref readonly int Valid() => ref value;
    ref readonly int Invalid() => ref readonly value;
 
}").GetParseDiagnostics().Verify(
                // (7,39): error CS1525: Invalid expression term 'readonly'
                //     ref readonly int Invalid() => ref readonly value;
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "readonly").WithArguments("readonly").WithLocation(7, 39),
                // (7,39): error CS1002: ; expected
                //     ref readonly int Invalid() => ref readonly value;
                Diagnostic(ErrorCode.ERR_SemicolonExpected, "readonly").WithLocation(7, 39),
                // (7,53): error CS1519: Invalid token ';' ref readonly class, struct, or interface member declaration
                //     ref readonly int Invalid() => ref readonly value;
                Diagnostic(ErrorCode.ERR_InvalidMemberDecl, ";").WithArguments(";").WithLocation(7, 53),
                // (7,53): error CS1519: Invalid token ';' ref readonly class, struct, or interface member declaration
                //     ref readonly int Invalid() => ref readonly value;
                Diagnostic(ErrorCode.ERR_InvalidMemberDecl, ";").WithArguments(";").WithLocation(7, 53));
        }
 
        [Fact]
        public void RefReadOnlyForEachAreDisallowed()
        {
            CreateCompilation(@"
class Test
{
    void M()
    {
        var ar = new int[] { 1, 2, 3 };
 
        foreach(ref readonly v in ar)
        {
        }
    }
}").GetParseDiagnostics().Verify(
                // (8,17): error CS1525: Invalid expression term 'ref'
                //         foreach(ref readonly v in ar)
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref ").WithArguments("ref").WithLocation(8, 17),
                // (8,21): error CS1525: Invalid expression term 'readonly'
                //         foreach(ref readonly v in ar)
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "readonly").WithArguments("readonly").WithLocation(8, 21),
                // (8,21): error CS1515: 'in' expected
                //         foreach(ref readonly v in ar)
                Diagnostic(ErrorCode.ERR_InExpected, "readonly").WithLocation(8, 21),
                // (8,21): error CS0230: Type and identifier are both required in a foreach statement
                //         foreach(ref readonly v in ar)
                Diagnostic(ErrorCode.ERR_BadForeachDecl, "readonly").WithLocation(8, 21),
                // (8,21): error CS1525: Invalid expression term 'readonly'
                //         foreach(ref readonly v in ar)
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "readonly").WithArguments("readonly").WithLocation(8, 21),
                // (8,21): error CS1026: ) expected
                //         foreach(ref readonly v in ar)
                Diagnostic(ErrorCode.ERR_CloseParenExpected, "readonly").WithLocation(8, 21),
                // (8,21): error CS0106: The modifier 'readonly' is not valid for this item
                //         foreach(ref readonly v in ar)
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "readonly").WithArguments("readonly").WithLocation(8, 21),
                // (8,32): error CS1001: Identifier expected
                //         foreach(ref readonly v in ar)
                Diagnostic(ErrorCode.ERR_IdentifierExpected, "in").WithLocation(8, 32),
                // (8,32): error CS1003: Syntax error, ',' expected
                //         foreach(ref readonly v in ar)
                Diagnostic(ErrorCode.ERR_SyntaxError, "in").WithArguments(",").WithLocation(8, 32),
                // (8,35): error CS1002: ; expected
                //         foreach(ref readonly v in ar)
                Diagnostic(ErrorCode.ERR_SemicolonExpected, "ar").WithLocation(8, 35),
                // (8,37): error CS1002: ; expected
                //         foreach(ref readonly v in ar)
                Diagnostic(ErrorCode.ERR_SemicolonExpected, ")").WithLocation(8, 37),
                // (8,37): error CS1513: } expected
                //         foreach(ref readonly v in ar)
                Diagnostic(ErrorCode.ERR_RbraceExpected, ")").WithLocation(8, 37));
        }
 
        [Fact]
        public void RefReadOnlyAtCallSite()
        {
            CreateCompilation(@"
class Test
{
    void M(in int p)
    {
    }
    void N()
    {
        int x = 0;
        M(ref readonly x);
    }
}").GetParseDiagnostics().Verify(
                // (10,15): error CS1525: Invalid expression term 'readonly'
                //         M(ref readonly x);
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "readonly").WithArguments("readonly").WithLocation(10, 15),
                // (10,15): error CS1026: ) expected
                //         M(ref readonly x);
                Diagnostic(ErrorCode.ERR_CloseParenExpected, "readonly").WithLocation(10, 15),
                // (10,15): error CS1002: ; expected
                //         M(ref readonly x);
                Diagnostic(ErrorCode.ERR_SemicolonExpected, "readonly").WithLocation(10, 15),
                // (10,15): error CS0106: The modifier 'readonly' is not valid for this item
                //         M(ref readonly x);
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "readonly").WithArguments("readonly").WithLocation(10, 15),
                // (10,25): error CS1001: Identifier expected
                //         M(ref readonly x);
                Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(10, 25),
                // (10,25): error CS1003: Syntax error, ',' expected
                //         M(ref readonly x);
                Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(",").WithLocation(10, 25));
        }
 
        [Fact]
        public void InAtCallSite()
        {
            CreateCompilation(@"
class Test
{
    void M(in int p)
    {
    }
    void N()
    {
        int x = 0;
        M(in x);
    }
}").GetParseDiagnostics().Verify();
        }
 
        [Fact]
        public void NothingAtCallSite()
        {
            CreateCompilation(@"
class Test
{
    void M(in int p)
    {
    }
    void N()
    {
        int x = 0;
        M(x);
    }
}").GetParseDiagnostics().Verify();
        }
 
        [Fact]
        public void InverseReadOnlyRefShouldBeIllegal()
        {
            CreateCompilation(@"
class Test
{
    void M(readonly ref int p)
    {
    }
}").VerifyDiagnostics(
                // (4,12): error CS9190: 'readonly' modifier must be specified after 'ref'.
                //     void M(readonly ref int p)
                Diagnostic(ErrorCode.ERR_RefReadOnlyWrongOrdering, "readonly").WithLocation(4, 12));
        }
 
        [Fact]
        public void RefReadOnlyReturnIllegalInOperators()
        {
            CreateCompilation(@"
public class Test
{
    public static ref readonly bool operator!(Test obj) => throw null;
}").GetParseDiagnostics().Verify(
                // (4,37): error CS1519: Invalid token 'operator' in class, record, struct, or interface member declaration
                //     public static ref readonly bool operator!(Test obj) => throw null;
                Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "operator").WithArguments("operator").WithLocation(4, 37),
                // (4,37): error CS1519: Invalid token 'operator' in class, record, struct, or interface member declaration
                //     public static ref readonly bool operator!(Test obj) => throw null;
                Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "operator").WithArguments("operator").WithLocation(4, 37),
                // (4,55): error CS8124: Tuple must contain at least two elements.
                //     public static ref readonly bool operator!(Test obj) => throw null;
                Diagnostic(ErrorCode.ERR_TupleTooFewElements, ")").WithLocation(4, 55),
                // (4,57): error CS1519: Invalid token '=>' in class, record, struct, or interface member declaration
                //     public static ref readonly bool operator!(Test obj) => throw null;
                Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=>").WithArguments("=>").WithLocation(4, 57));
        }
 
        [Fact]
        public void InNotAllowedInReturnType()
        {
            CreateCompilation(@"
class Test
{
    in int M() => throw null;
}").VerifyDiagnostics(
                // (4,5): error CS1519: Invalid token 'in' in class, record, struct, or interface member declaration
                //     in int M() => throw null;
                Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "in").WithArguments("in").WithLocation(4, 5));
        }
 
        [Fact, WorkItem(25264, "https://github.com/dotnet/roslyn/issues/25264")]
        public void TestNewRefArray()
        {
            UsingStatement("new ref[];",
                // (1,8): error CS1031: Type expected
                // new ref[];
                Diagnostic(ErrorCode.ERR_TypeExpected, "[").WithLocation(1, 8));
 
            N(SyntaxKind.ExpressionStatement);
            {
                N(SyntaxKind.ObjectCreationExpression);
                {
                    N(SyntaxKind.NewKeyword);
                    N(SyntaxKind.RefType);
                    {
                        N(SyntaxKind.RefKeyword);
                        N(SyntaxKind.ArrayType);
                        {
                            M(SyntaxKind.IdentifierName);
                            {
                                M(SyntaxKind.IdentifierToken);
                            }
                            N(SyntaxKind.ArrayRankSpecifier);
                            {
                                N(SyntaxKind.OpenBracketToken);
                                N(SyntaxKind.OmittedArraySizeExpression);
                                {
                                    N(SyntaxKind.OmittedArraySizeExpressionToken);
                                }
                                N(SyntaxKind.CloseBracketToken);
                            }
                        }
                    }
                    M(SyntaxKind.ArgumentList);
                    {
                        M(SyntaxKind.OpenParenToken);
                        M(SyntaxKind.CloseParenToken);
                    }
                }
                N(SyntaxKind.SemicolonToken);
            }
            EOF();
        }
 
        [Fact]
        public void RefReadonlyParameter()
        {
            var source = "void M(ref readonly int p);";
            UsingDeclaration(source, TestOptions.Regular11);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12);
            verifyNodes();
 
            UsingDeclaration(source);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.RefKeyword);
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.PredefinedType);
                            {
                                N(SyntaxKind.IntKeyword);
                            }
                            N(SyntaxKind.IdentifierToken, "p");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Fact]
        public void Readonly_Duplicate_01()
        {
            var source = "void M(ref readonly readonly int p);";
            UsingDeclaration(source, TestOptions.Regular11);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12);
            verifyNodes();
 
            UsingDeclaration(source);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.RefKeyword);
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.PredefinedType);
                            {
                                N(SyntaxKind.IntKeyword);
                            }
                            N(SyntaxKind.IdentifierToken, "p");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Fact]
        public void Readonly_Duplicate_02()
        {
            var source = "void M(readonly readonly int p);";
            UsingDeclaration(source, TestOptions.Regular11);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12);
            verifyNodes();
 
            UsingDeclaration(source);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.PredefinedType);
                            {
                                N(SyntaxKind.IntKeyword);
                            }
                            N(SyntaxKind.IdentifierToken, "p");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Fact]
        public void Readonly_Duplicate_03()
        {
            var source = "void M(readonly ref readonly int p);";
            UsingDeclaration(source, TestOptions.Regular11);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12);
            verifyNodes();
 
            UsingDeclaration(source);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.RefKeyword);
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.PredefinedType);
                            {
                                N(SyntaxKind.IntKeyword);
                            }
                            N(SyntaxKind.IdentifierToken, "p");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Fact]
        public void Readonly_Duplicate_04()
        {
            var source = "void M(readonly readonly ref int p);";
            UsingDeclaration(source, TestOptions.Regular11);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12);
            verifyNodes();
 
            UsingDeclaration(source);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.RefKeyword);
                            N(SyntaxKind.PredefinedType);
                            {
                                N(SyntaxKind.IntKeyword);
                            }
                            N(SyntaxKind.IdentifierToken, "p");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Fact]
        public void Readonly_Duplicate_05()
        {
            var source = "void M(ref readonly ref readonly int p);";
            UsingDeclaration(source, TestOptions.Regular11);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12);
            verifyNodes();
 
            UsingDeclaration(source);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.RefKeyword);
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.RefKeyword);
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.PredefinedType);
                            {
                                N(SyntaxKind.IntKeyword);
                            }
                            N(SyntaxKind.IdentifierToken, "p");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Fact]
        public void RefReadonlyWithThis()
        {
            var source = "void M(this ref readonly int p);";
            UsingDeclaration(source, TestOptions.Regular11);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12);
            verifyNodes();
 
            UsingDeclaration(source);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.ThisKeyword);
                            N(SyntaxKind.RefKeyword);
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.PredefinedType);
                            {
                                N(SyntaxKind.IntKeyword);
                            }
                            N(SyntaxKind.IdentifierToken, "p");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Fact]
        public void RefReadonlyWithThis_02()
        {
            var source = "void M(ref this readonly int p);";
            UsingDeclaration(source, TestOptions.Regular11);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12);
            verifyNodes();
 
            UsingDeclaration(source);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.RefKeyword);
                            N(SyntaxKind.ThisKeyword);
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.PredefinedType);
                            {
                                N(SyntaxKind.IntKeyword);
                            }
                            N(SyntaxKind.IdentifierToken, "p");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Fact]
        public void RefReadonlyWithThis_03()
        {
            var source = "void M(ref readonly this int p);";
            UsingDeclaration(source, TestOptions.Regular11);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12);
            verifyNodes();
 
            UsingDeclaration(source);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.RefKeyword);
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.ThisKeyword);
                            N(SyntaxKind.PredefinedType);
                            {
                                N(SyntaxKind.IntKeyword);
                            }
                            N(SyntaxKind.IdentifierToken, "p");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Fact]
        public void RefReadonlyWithScoped_01()
        {
            var source = "void M(scoped ref readonly int p);";
            UsingDeclaration(source, TestOptions.Regular11);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12);
            verifyNodes();
 
            UsingDeclaration(source);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.ScopedKeyword);
                            N(SyntaxKind.RefKeyword);
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.PredefinedType);
                            {
                                N(SyntaxKind.IntKeyword);
                            }
                            N(SyntaxKind.IdentifierToken, "p");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Fact]
        public void RefReadonlyWithScoped_02()
        {
            var source = "void M(ref scoped readonly int p);";
            var expectedDiagnostics = new[]
            {
                // (1,19): error CS1001: Identifier expected
                // void M(ref scoped readonly int p);
                Diagnostic(ErrorCode.ERR_IdentifierExpected, "readonly").WithLocation(1, 19),
                // (1,19): error CS1003: Syntax error, ',' expected
                // void M(ref scoped readonly int p);
                Diagnostic(ErrorCode.ERR_SyntaxError, "readonly").WithArguments(",").WithLocation(1, 19)
            };
 
            UsingDeclaration(source, TestOptions.Regular11, expectedDiagnostics);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12, expectedDiagnostics);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.RegularPreview, expectedDiagnostics);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.RefKeyword);
                            N(SyntaxKind.IdentifierName);
                            {
                                N(SyntaxKind.IdentifierToken, "scoped");
                            }
                            M(SyntaxKind.IdentifierToken);
                        }
                        M(SyntaxKind.CommaToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.PredefinedType);
                            {
                                N(SyntaxKind.IntKeyword);
                            }
                            N(SyntaxKind.IdentifierToken, "p");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Fact]
        public void RefReadonlyWithScoped_03()
        {
            var source = "void M(readonly scoped ref int p);";
            var expectedDiagnostics = new[]
            {
                // (1,24): error CS1001: Identifier expected
                // void M(readonly scoped ref int p);
                Diagnostic(ErrorCode.ERR_IdentifierExpected, "ref").WithLocation(1, 24),
                // (1,24): error CS1003: Syntax error, ',' expected
                // void M(readonly scoped ref int p);
                Diagnostic(ErrorCode.ERR_SyntaxError, "ref").WithArguments(",").WithLocation(1, 24)
            };
 
            UsingDeclaration(source, TestOptions.Regular11, expectedDiagnostics);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12, expectedDiagnostics);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.RegularPreview, expectedDiagnostics);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.IdentifierName);
                            {
                                N(SyntaxKind.IdentifierToken, "scoped");
                            }
                            M(SyntaxKind.IdentifierToken);
                        }
                        M(SyntaxKind.CommaToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.RefKeyword);
                            N(SyntaxKind.PredefinedType);
                            {
                                N(SyntaxKind.IntKeyword);
                            }
                            N(SyntaxKind.IdentifierToken, "p");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Fact]
        public void ReadonlyWithScoped()
        {
            var source = "void M(scoped readonly int p);";
            var expectedDiagnostics = new[]
            {
                // (1,15): error CS1001: Identifier expected
                // void M(scoped readonly int p);
                Diagnostic(ErrorCode.ERR_IdentifierExpected, "readonly").WithLocation(1, 15),
                // (1,15): error CS1003: Syntax error, ',' expected
                // void M(scoped readonly int p);
                Diagnostic(ErrorCode.ERR_SyntaxError, "readonly").WithArguments(",").WithLocation(1, 15)
            };
 
            UsingDeclaration(source, TestOptions.Regular11, expectedDiagnostics);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12, expectedDiagnostics);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.RegularPreview, expectedDiagnostics);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.IdentifierName);
                            {
                                N(SyntaxKind.IdentifierToken, "scoped");
                            }
                            M(SyntaxKind.IdentifierToken);
                        }
                        M(SyntaxKind.CommaToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.PredefinedType);
                            {
                                N(SyntaxKind.IntKeyword);
                            }
                            N(SyntaxKind.IdentifierToken, "p");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Fact]
        public void ReadonlyWithScoped_02()
        {
            var source = "void M(scoped readonly ref int p);";
            var expectedDiagnostics = new[]
            {
                // (1,15): error CS1001: Identifier expected
                // void M(scoped readonly ref int p);
                Diagnostic(ErrorCode.ERR_IdentifierExpected, "readonly").WithLocation(1, 15),
                // (1,15): error CS1003: Syntax error, ',' expected
                // void M(scoped readonly ref int p);
                Diagnostic(ErrorCode.ERR_SyntaxError, "readonly").WithArguments(",").WithLocation(1, 15)
            };
 
            UsingDeclaration(source, TestOptions.Regular11, expectedDiagnostics);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12, expectedDiagnostics);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.RegularPreview, expectedDiagnostics);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.IdentifierName);
                            {
                                N(SyntaxKind.IdentifierToken, "scoped");
                            }
                            M(SyntaxKind.IdentifierToken);
                        }
                        M(SyntaxKind.CommaToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.RefKeyword);
                            N(SyntaxKind.PredefinedType);
                            {
                                N(SyntaxKind.IntKeyword);
                            }
                            N(SyntaxKind.IdentifierToken, "p");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Fact]
        public void RefReadonly_ScopedParameterName()
        {
            var source = "void M(ref readonly int scoped);";
            UsingDeclaration(source, TestOptions.Regular11);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12);
            verifyNodes();
 
            UsingDeclaration(source);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.RefKeyword);
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.PredefinedType);
                            {
                                N(SyntaxKind.IntKeyword);
                            }
                            N(SyntaxKind.IdentifierToken, "scoped");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Fact]
        public void RefReadonly_ScopedTypeName()
        {
            var source = "void M(ref readonly scoped p);";
            UsingDeclaration(source, TestOptions.Regular11);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12);
            verifyNodes();
 
            UsingDeclaration(source);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.RefKeyword);
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.IdentifierName);
                            {
                                N(SyntaxKind.IdentifierToken, "scoped");
                            }
                            N(SyntaxKind.IdentifierToken, "p");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Fact]
        public void RefReadonly_ScopedBothNames()
        {
            var source = "void M(ref readonly scoped scoped);";
            UsingDeclaration(source, TestOptions.Regular11);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular12);
            verifyNodes();
 
            UsingDeclaration(source, TestOptions.Regular9);
            verifyNodes();
 
            UsingDeclaration(source);
            verifyNodes();
 
            void verifyNodes()
            {
                N(SyntaxKind.MethodDeclaration);
                {
                    N(SyntaxKind.PredefinedType);
                    {
                        N(SyntaxKind.VoidKeyword);
                    }
                    N(SyntaxKind.IdentifierToken, "M");
                    N(SyntaxKind.ParameterList);
                    {
                        N(SyntaxKind.OpenParenToken);
                        N(SyntaxKind.Parameter);
                        {
                            N(SyntaxKind.RefKeyword);
                            N(SyntaxKind.ReadOnlyKeyword);
                            N(SyntaxKind.IdentifierName);
                            {
                                N(SyntaxKind.IdentifierToken, "scoped");
                            }
                            N(SyntaxKind.IdentifierToken, "scoped");
                        }
                        N(SyntaxKind.CloseParenToken);
                    }
                    N(SyntaxKind.SemicolonToken);
                }
                EOF();
            }
        }
 
        [Theory, CombinatorialData]
        public void ArgumentModifier_RefReadonly(
            [CombinatorialValues(LanguageVersion.CSharp11, LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
        {
            UsingExpression("M(ref x, in y, ref readonly z)", TestOptions.Regular.WithLanguageVersion(languageVersion),
                // (1,20): error CS1525: Invalid expression term 'readonly'
                // M(ref x, in y, ref readonly z)
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "readonly").WithArguments("readonly").WithLocation(1, 20),
                // (1,20): error CS1003: Syntax error, ',' expected
                // M(ref x, in y, ref readonly z)
                Diagnostic(ErrorCode.ERR_SyntaxError, "readonly").WithArguments(",").WithLocation(1, 20),
                // (1,29): error CS1003: Syntax error, ',' expected
                // M(ref x, in y, ref readonly z)
                Diagnostic(ErrorCode.ERR_SyntaxError, "z").WithArguments(",").WithLocation(1, 29));
 
            N(SyntaxKind.InvocationExpression);
            {
                N(SyntaxKind.IdentifierName);
                {
                    N(SyntaxKind.IdentifierToken, "M");
                }
                N(SyntaxKind.ArgumentList);
                {
                    N(SyntaxKind.OpenParenToken);
                    N(SyntaxKind.Argument);
                    {
                        N(SyntaxKind.RefKeyword);
                        N(SyntaxKind.IdentifierName);
                        {
                            N(SyntaxKind.IdentifierToken, "x");
                        }
                    }
                    N(SyntaxKind.CommaToken);
                    N(SyntaxKind.Argument);
                    {
                        N(SyntaxKind.InKeyword);
                        N(SyntaxKind.IdentifierName);
                        {
                            N(SyntaxKind.IdentifierToken, "y");
                        }
                    }
                    N(SyntaxKind.CommaToken);
                    N(SyntaxKind.Argument);
                    {
                        N(SyntaxKind.RefKeyword);
                        M(SyntaxKind.IdentifierName);
                        {
                            M(SyntaxKind.IdentifierToken);
                        }
                    }
                    M(SyntaxKind.CommaToken);
                    N(SyntaxKind.Argument);
                    {
                        N(SyntaxKind.IdentifierName);
                        {
                            N(SyntaxKind.IdentifierToken, "z");
                        }
                    }
                    N(SyntaxKind.CloseParenToken);
                }
            }
            EOF();
        }
 
        [Theory, CombinatorialData]
        public void ArgumentModifier_ReadonlyRef(
            [CombinatorialValues(LanguageVersion.CSharp11, LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
        {
            UsingExpression("M(readonly ref x)", TestOptions.Regular.WithLanguageVersion(languageVersion),
                // (1,3): error CS1041: Identifier expected; 'readonly' is a keyword
                // M(readonly ref x)
                Diagnostic(ErrorCode.ERR_IdentifierExpectedKW, "readonly").WithArguments("", "readonly").WithLocation(1, 3));
 
            N(SyntaxKind.InvocationExpression);
            {
                N(SyntaxKind.IdentifierName);
                {
                    N(SyntaxKind.IdentifierToken, "M");
                }
                N(SyntaxKind.ArgumentList);
                {
                    N(SyntaxKind.OpenParenToken);
                    N(SyntaxKind.Argument);
                    {
                        N(SyntaxKind.RefKeyword);
                        N(SyntaxKind.IdentifierName);
                        {
                            N(SyntaxKind.IdentifierToken, "x");
                        }
                    }
                    N(SyntaxKind.CloseParenToken);
                }
            }
            EOF();
        }
 
        [Theory, CombinatorialData]
        public void ArgumentModifier_Readonly(
            [CombinatorialValues(LanguageVersion.CSharp11, LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
        {
            UsingExpression("M(readonly x)", TestOptions.Regular.WithLanguageVersion(languageVersion),
                // (1,3): error CS1041: Identifier expected; 'readonly' is a keyword
                // M(readonly x)
                Diagnostic(ErrorCode.ERR_IdentifierExpectedKW, "readonly").WithArguments("", "readonly").WithLocation(1, 3));
 
            N(SyntaxKind.InvocationExpression);
            {
                N(SyntaxKind.IdentifierName);
                {
                    N(SyntaxKind.IdentifierToken, "M");
                }
                N(SyntaxKind.ArgumentList);
                {
                    N(SyntaxKind.OpenParenToken);
                    N(SyntaxKind.Argument);
                    {
                        N(SyntaxKind.IdentifierName);
                        {
                            N(SyntaxKind.IdentifierToken, "x");
                        }
                    }
                    N(SyntaxKind.CloseParenToken);
                }
            }
            EOF();
        }
    }
}