File: EditAndContinue\StatementEditingTests.cs
Web Access
Project: src\src\Features\CSharpTest\Microsoft.CodeAnalysis.CSharp.Features.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Features.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 System.IO;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.UnitTests;
using Microsoft.CodeAnalysis.EditAndContinue;
using Microsoft.CodeAnalysis.EditAndContinue.UnitTests;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests;
 
[UseExportProvider]
public class StatementEditingTests : EditingTestBase
{
    private readonly string s_asyncIteratorStateMachineAttributeSource = @"
namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
    public sealed class AsyncIteratorStateMachineAttribute : StateMachineAttribute
    {
        public AsyncIteratorStateMachineAttribute(Type stateMachineType)
            : base(stateMachineType)
        {
        }
    }
}
";
 
    #region Strings
 
    [Fact]
    public void StringLiteral_update()
    {
        var src1 = @"
var x = ""Hello1"";
";
        var src2 = @"
var x = ""Hello2"";
";
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Update [x = \"Hello1\"]@8 -> [x = \"Hello2\"]@8");
    }
 
    [Fact]
    public void InterpolatedStringText_update()
    {
        var src1 = @"
var x = $""Hello1"";
";
        var src2 = @"
var x = $""Hello2"";
";
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Update [x = $\"Hello1\"]@8 -> [x = $\"Hello2\"]@8");
    }
 
    [Fact]
    public void Interpolation_update()
    {
        var src1 = @"
var x = $""Hello{123}"";
";
        var src2 = @"
var x = $""Hello{124}"";
";
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Update [x = $\"Hello{123}\"]@8 -> [x = $\"Hello{124}\"]@8");
    }
 
    [Fact]
    public void InterpolationFormatClause_update()
    {
        var src1 = @"
var x = $""Hello{123:N1}"";
";
        var src2 = @"
var x = $""Hello{123:N2}"";
";
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Update [x = $\"Hello{123:N1}\"]@8 -> [x = $\"Hello{123:N2}\"]@8");
    }
 
    #endregion
 
    #region Variable Declaration
 
    [Fact]
    public void VariableDeclaration_Insert()
    {
        var src1 = "if (x == 1) { x++; }";
        var src2 = "var x = 1; if (x == 1) { x++; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [var x = 1;]@2",
            "Insert [var x = 1]@2",
            "Insert [x = 1]@6");
    }
 
    [Fact]
    public void VariableDeclaration_Update()
    {
        var src1 = "int x = F(1), y = G(2);";
        var src2 = "int x = F(3), y = G(4);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [x = F(1)]@6 -> [x = F(3)]@6",
            "Update [y = G(2)]@16 -> [y = G(4)]@16");
    }
 
    [Fact]
    public void ParenthesizedVariableDeclaration_Update()
    {
        var src1 = @"
var (x1, (x2, x3)) = (1, (2, true));
var (a1, a2) = (1, () => { return 7; });
";
        var src2 = @"
var (x1, (x2, x4)) = (1, (2, true));
var (a1, a3) = (1, () => { return 8; });
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [x3]@18 -> [x4]@18",
            "Update [a2]@51 -> [a3]@51");
    }
 
    [Fact]
    public void ParenthesizedVariableDeclaration_Insert()
    {
        var src1 = @"var (z1, z2) = (1, 2);";
        var src2 = @"var (z1, z2, z3) = (1, 2, 5);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [var (z1, z2) = (1, 2);]@2 -> [var (z1, z2, z3) = (1, 2, 5);]@2",
            "Insert [z3]@15");
    }
 
    [Fact]
    public void ParenthesizedVariableDeclaration_Delete()
    {
        var src1 = @"var (y1, y2, y3) = (1, 2, 7);";
        var src2 = @"var (y1, y2) = (1, 4);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [var (y1, y2, y3) = (1, 2, 7);]@2 -> [var (y1, y2) = (1, 4);]@2",
            "Delete [y3]@15");
    }
 
    [Fact]
    public void ParenthesizedVariableDeclaration_Insert_Mixed1()
    {
        var src1 = @"int a; (var z1, a) = (1, 2);";
        var src2 = @"int a; (var z1, a, var z3) = (1, 2, 5);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [(var z1, a) = (1, 2);]@9 -> [(var z1, a, var z3) = (1, 2, 5);]@9",
            "Insert [z3]@25");
    }
 
    [Fact]
    public void ParenthesizedVariableDeclaration_Insert_Mixed2()
    {
        var src1 = @"int a; (var z1, var z2) = (1, 2);";
        var src2 = @"int a; (var z1, var z2, a) = (1, 2, 5);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [(var z1, var z2) = (1, 2);]@9 -> [(var z1, var z2, a) = (1, 2, 5);]@9");
    }
 
    [Fact]
    public void ParenthesizedVariableDeclaration_Delete_Mixed1()
    {
        var src1 = @"int a; (var y1, var y2, a) = (1, 2, 7);";
        var src2 = @"int a; (var y1, var y2) = (1, 4);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [(var y1, var y2, a) = (1, 2, 7);]@9 -> [(var y1, var y2) = (1, 4);]@9");
    }
 
    [Fact]
    public void ParenthesizedVariableDeclaration_Delete_Mixed2()
    {
        var src1 = @"int a; (var y1, a, var y3) = (1, 2, 7);";
        var src2 = @"int a; (var y1, a) = (1, 4);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [(var y1, a, var y3) = (1, 2, 7);]@9 -> [(var y1, a) = (1, 4);]@9",
            "Delete [y3]@25");
    }
 
    [Fact]
    public void VariableDeclaraions_Reorder()
    {
        var src1 = @"var (a, b) = (1, 2); var (c, d) = (3, 4);";
        var src2 = @"var (c, d) = (3, 4); var (a, b) = (1, 2);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [var (c, d) = (3, 4);]@23 -> @2");
    }
 
    [Fact]
    public void VariableDeclaraions_Reorder_Mixed()
    {
        var src1 = @"int a; (a, int b) = (1, 2); (int c, int d) = (3, 4);";
        var src2 = @"int a; (int c, int d) = (3, 4); (a, int b) = (1, 2);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [(int c, int d) = (3, 4);]@30 -> @9");
    }
 
    [Fact]
    public void VariableNames_Reorder()
    {
        var src1 = @"var (a, b) = (1, 2);";
        var src2 = @"var (b, a) = (2, 1);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [var (a, b) = (1, 2);]@2 -> [var (b, a) = (2, 1);]@2",
            "Reorder [b]@10 -> @7");
    }
 
    [Fact]
    public void VariableNames_Reorder_Mixed()
    {
        var src1 = @"int a; (a, int b) = (1, 2);";
        var src2 = @"int a; (int b, a) = (2, 1);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [(a, int b) = (1, 2);]@9 -> [(int b, a) = (2, 1);]@9");
    }
 
    [Fact]
    public void VariableNamesAndDeclaraions_Reorder()
    {
        var src1 = @"var (a, b) = (1, 2); var (c, d) = (3, 4);";
        var src2 = @"var (d, c) = (3, 4); var (a, b) = (1, 2);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [var (c, d) = (3, 4);]@23 -> @2",
            "Reorder [d]@31 -> @7");
    }
 
    [Fact]
    public void ParenthesizedVariableDeclaration_Reorder()
    {
        var src1 = @"var (a, (b, c)) = (1, (2, 3));";
        var src2 = @"var ((b, c), a) = ((2, 3), 1);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [var (a, (b, c)) = (1, (2, 3));]@2 -> [var ((b, c), a) = ((2, 3), 1);]@2",
            "Reorder [a]@7 -> @15");
    }
 
    [Fact]
    public void ParenthesizedVariableDeclaration_DoubleReorder()
    {
        var src1 = @"var (a, (b, c)) = (1, (2, 3));";
        var src2 = @"var ((c, b), a) = ((2, 3), 1);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [var (a, (b, c)) = (1, (2, 3));]@2 -> [var ((c, b), a) = ((2, 3), 1);]@2",
            "Reorder [b]@11 -> @11",
            "Reorder [c]@14 -> @8");
    }
 
    [Fact]
    public void ParenthesizedVariableDeclaration_ComplexReorder()
    {
        var src1 = @"var (a, (b, c)) = (1, (2, 3)); var (x, (y, z)) = (4, (5, 6));";
        var src2 = @"var (x, (y, z)) = (4, (5, 6)); var ((c, b), a) = (1, (2, 3)); ";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [var (x, (y, z)) = (4, (5, 6));]@33 -> @2",
            "Update [var (a, (b, c)) = (1, (2, 3));]@2 -> [var ((c, b), a) = (1, (2, 3));]@33",
            "Reorder [b]@11 -> @42",
            "Reorder [c]@14 -> @39");
    }
 
    #endregion
 
    #region Switch Statement
 
    [Fact]
    public void Switch1()
    {
        var src1 = "switch (a) { case 1: f(); break; } switch (b) { case 2: g(); break; }";
        var src2 = "switch (b) { case 2: f(); break; } switch (a) { case 1: g(); break; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [switch (b) { case 2: g(); break; }]@37 -> @2",
            "Update [case 1: f(); break;]@15 -> [case 2: f(); break;]@15",
            "Move [case 1: f(); break;]@15 -> @15",
            "Update [case 2: g(); break;]@50 -> [case 1: g(); break;]@50",
            "Move [case 2: g(); break;]@50 -> @50");
    }
 
    [Fact]
    public void Switch_Case_Reorder()
    {
        var src1 = "switch (expr) { case 1: f(); break;   case 2: case 3: case 4: g(); break; }";
        var src2 = "switch (expr) { case 2: case 3: case 4: g(); break;   case 1: f(); break; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [case 2: case 3: case 4: g(); break;]@40 -> @18");
    }
 
    [Fact]
    public void Switch_Case_Update()
    {
        var src1 = "switch (expr) { case 1: f(); break; }";
        var src2 = "switch (expr) { case 2: f(); break; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [case 1: f(); break;]@18 -> [case 2: f(); break;]@18");
    }
 
    [Fact]
    public void CasePatternLabel_UpdateDelete()
    {
        var src1 = @"
switch(shape)
{
    case Point p: return 0;
    case Circle c: return 1;
}
";
 
        var src2 = @"
switch(shape)
{
    case Circle circle: return 1;
}
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [case Circle c: return 1;]@55 -> [case Circle circle: return 1;]@26",
            "Update [c]@67 -> [circle]@38",
            "Delete [case Point p: return 0;]@26",
            "Delete [case Point p:]@26",
            "Delete [p]@37",
            "Delete [return 0;]@40");
    }
 
    #endregion
 
    #region Switch Expression
 
    [Fact]
    public void MethodUpdate_UpdateSwitchExpression1()
    {
        var src1 = @"
class C
{
    static int F(int a) => a switch { 0 => 0, _ => 1 };
}";
        var src2 = @"
class C
{
    static int F(int a) => a switch { 0 => 0, _ => 2 };
}";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifyEdits("Update [static int F(int a) => a switch { 0 => 0, _ => 1 };]@18 -> [static int F(int a) => a switch { 0 => 0, _ => 2 };]@18");
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void MethodUpdate_UpdateSwitchExpression2()
    {
        var src1 = @"
class C
{
    static int F(int a) => a switch { 0 => 0, _ => 1 };
}";
        var src2 = @"
class C
{
    static int F(int a) => a switch { 1 => 0, _ => 2 };
}";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifyEdits("Update [static int F(int a) => a switch { 0 => 0, _ => 1 };]@18 -> [static int F(int a) => a switch { 1 => 0, _ => 2 };]@18");
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void MethodUpdate_UpdateSwitchExpression3()
    {
        var src1 = @"
class C
{
    static int F(int a) => a switch { 0 => 0, _ => 1 };
}";
        var src2 = @"
class C
{
    static int F(int a) => a switch { 0 => 0, 1 => 1, _ => 2 };
}";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifyEdits("Update [static int F(int a) => a switch { 0 => 0, _ => 1 };]@18 -> [static int F(int a) => a switch { 0 => 0, 1 => 1, _ => 2 };]@18");
 
        edits.VerifySemanticDiagnostics();
    }
 
    #endregion
 
    #region Try Catch Finally
 
    [Fact]
    public void TryInsert1()
    {
        var src1 = "x++;";
        var src2 = "try { x++; } catch { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [try { x++; } catch { }]@2",
            "Insert [{ x++; }]@6",
            "Insert [catch { }]@15",
            "Move [x++;]@2 -> @8",
            "Insert [{ }]@21");
    }
 
    [Fact]
    public void TryInsert2()
    {
        var src1 = "{ x++; }";
        var src2 = "try { x++; } catch { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [try { x++; } catch { }]@2",
            "Move [{ x++; }]@2 -> @6",
            "Insert [catch { }]@15",
            "Insert [{ }]@21");
    }
 
    [Fact]
    public void TryDelete1()
    {
        var src1 = "try { x++; } catch { }";
        var src2 = "x++;";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [x++;]@8 -> @2",
            "Delete [try { x++; } catch { }]@2",
            "Delete [{ x++; }]@6",
            "Delete [catch { }]@15",
            "Delete [{ }]@21");
    }
 
    [Fact]
    public void TryDelete2()
    {
        var src1 = "try { x++; } catch { }";
        var src2 = "{ x++; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ x++; }]@6 -> @2",
            "Delete [try { x++; } catch { }]@2",
            "Delete [catch { }]@15",
            "Delete [{ }]@21");
    }
 
    [Fact]
    public void TryReorder()
    {
        var src1 = "try { x++; } catch { /*1*/ } try { y++; } catch { /*2*/ }";
        var src2 = "try { y++; } catch { /*2*/ } try { x++; } catch { /*1*/ } ";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [try { y++; } catch { /*2*/ }]@31 -> @2");
    }
 
    [Fact]
    public void Finally_DeleteHeader()
    {
        var src1 = "try { /*1*/ } catch (E1 e) { /*2*/ } finally { /*3*/ }";
        var src2 = "try { /*1*/ } catch (E1 e) { /*2*/ } { /*3*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ /*3*/ }]@47 -> @39",
            "Delete [finally { /*3*/ }]@39");
    }
 
    [Fact]
    public void Finally_InsertHeader()
    {
        var src1 = "try { /*1*/ } catch (E1 e) { /*2*/ } { /*3*/ }";
        var src2 = "try { /*1*/ } catch (E1 e) { /*2*/ } finally { /*3*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [finally { /*3*/ }]@39",
            "Move [{ /*3*/ }]@39 -> @47");
    }
 
    [Fact]
    public void CatchUpdate()
    {
        var src1 = "try { } catch (Exception e) { }";
        var src2 = "try { } catch (IOException e) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [(Exception e)]@16 -> [(IOException e)]@16");
    }
 
    [Fact]
    public void CatchInsert()
    {
        var src1 = "try { /*1*/ } catch (Exception e) { /*2*/ } ";
        var src2 = "try { /*1*/ } catch (IOException e) { /*3*/ } catch (Exception e) { /*2*/ } ";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [catch (IOException e) { /*3*/ }]@16",
            "Insert [(IOException e)]@22",
            "Insert [{ /*3*/ }]@38");
    }
 
    [Fact]
    public void CatchBodyUpdate()
    {
        var src1 = "try { } catch (E e) { x++; }";
        var src2 = "try { } catch (E e) { y++; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [x++;]@24 -> [y++;]@24");
    }
 
    [Fact]
    public void CatchDelete()
    {
        var src1 = "try { } catch (IOException e) { } catch (Exception e) { } ";
        var src2 = "try { } catch (IOException e) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Delete [catch (Exception e) { }]@36",
            "Delete [(Exception e)]@42",
            "Delete [{ }]@56");
    }
 
    [Fact]
    public void CatchReorder1()
    {
        var src1 = "try { } catch (IOException e) { } catch (Exception e) { } ";
        var src2 = "try { } catch (Exception e) { } catch (IOException e) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [catch (Exception e) { }]@36 -> @10");
    }
 
    [Fact]
    public void CatchReorder2()
    {
        var src1 = "try { } catch (IOException e) { } catch (Exception e) { } catch { }";
        var src2 = "try { } catch (A e) { } catch (Exception e) { } catch (IOException e) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [catch (Exception e) { }]@36 -> @26",
            "Reorder [catch { }]@60 -> @10",
            "Insert [(A e)]@16");
    }
 
    [Fact]
    public void CatchFilterReorder2()
    {
        var src1 = "try { } catch (Exception e) when (e != null) { } catch (Exception e) { } catch { }";
        var src2 = "try { } catch when (s == 1) { } catch (Exception e) { } catch (Exception e) when (e != null) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [catch (Exception e) { }]@51 -> @34",
            "Reorder [catch { }]@75 -> @10",
            "Insert [when (s == 1)]@16");
    }
 
    [Fact]
    public void CatchInsertDelete()
    {
        var src1 = @"
try { x++; } catch (E e) { /*1*/ } catch (Exception e) { /*2*/ } 
try { Console.WriteLine(); } finally { /*3*/ }";
 
        var src2 = @"
try { x++; } catch (Exception e) { /*2*/ }  
try { Console.WriteLine(); } catch (E e) { /*1*/ } finally { /*3*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [catch (E e) { /*1*/ }]@79",
            "Insert [(E e)]@85",
            "Move [{ /*1*/ }]@29 -> @91",
            "Delete [catch (E e) { /*1*/ }]@17",
            "Delete [(E e)]@23");
    }
 
    [Fact]
    public void Catch_DeleteHeader1()
    {
        var src1 = "try { /*1*/ } catch (E1 e) { /*2*/ } catch (E2 e) { /*3*/ }";
        var src2 = "try { /*1*/ } catch (E1 e) { /*2*/ } { /*3*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ /*3*/ }]@52 -> @39",
            "Delete [catch (E2 e) { /*3*/ }]@39",
            "Delete [(E2 e)]@45");
    }
 
    [Fact]
    public void Catch_InsertHeader1()
    {
        var src1 = "try { /*1*/ } catch (E1 e) { /*2*/ } { /*3*/ }";
        var src2 = "try { /*1*/ } catch (E1 e) { /*2*/ } catch (E2 e) { /*3*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [catch (E2 e) { /*3*/ }]@39",
            "Insert [(E2 e)]@45",
            "Move [{ /*3*/ }]@39 -> @52");
    }
 
    [Fact]
    public void Catch_DeleteHeader2()
    {
        var src1 = "try { /*1*/ } catch (E1 e) { /*2*/ } catch { /*3*/ }";
        var src2 = "try { /*1*/ } catch (E1 e) { /*2*/ } { /*3*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ /*3*/ }]@45 -> @39",
            "Delete [catch { /*3*/ }]@39");
    }
 
    [Fact]
    public void Catch_InsertHeader2()
    {
        var src1 = "try { /*1*/ } catch (E1 e) { /*2*/ } { /*3*/ }";
        var src2 = "try { /*1*/ } catch (E1 e) { /*2*/ } catch { /*3*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [catch { /*3*/ }]@39",
            "Move [{ /*3*/ }]@39 -> @45");
    }
 
    [Fact]
    public void Catch_InsertFilter1()
    {
        var src1 = "try { /*1*/ } catch (E1 e) { /*2*/ }";
        var src2 = "try { /*1*/ } catch (E1 e) when (e == null) { /*2*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [when (e == null)]@29");
    }
 
    [Fact]
    public void Catch_InsertFilter2()
    {
        var src1 = "try { /*1*/ } catch when (e == null) { /*2*/ }";
        var src2 = "try { /*1*/ } catch (E1 e) when (e == null) { /*2*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [(E1 e)]@22");
    }
 
    [Fact]
    public void Catch_InsertFilter3()
    {
        var src1 = "try { /*1*/ } catch { /*2*/ }";
        var src2 = "try { /*1*/ } catch (E1 e) when (e == null) { /*2*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [(E1 e)]@22",
            "Insert [when (e == null)]@29");
    }
 
    [Fact]
    public void Catch_DeleteDeclaration1()
    {
        var src1 = "try { /*1*/ } catch (E1 e) { /*2*/ }";
        var src2 = "try { /*1*/ } catch { /*2*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Delete [(E1 e)]@22");
    }
 
    [Fact]
    public void Catch_DeleteFilter1()
    {
        var src1 = "try { /*1*/ } catch (E1 e) when (e == null) { /*2*/ }";
        var src2 = "try { /*1*/ } catch (E1 e) { /*2*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Delete [when (e == null)]@29");
    }
 
    [Fact]
    public void Catch_DeleteFilter2()
    {
        var src1 = "try { /*1*/ } catch (E1 e) when (e == null) { /*2*/ }";
        var src2 = "try { /*1*/ } catch when (e == null) { /*2*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Delete [(E1 e)]@22");
    }
 
    [Fact]
    public void Catch_DeleteFilter3()
    {
        var src1 = "try { /*1*/ } catch (E1 e) when (e == null) { /*2*/ }";
        var src2 = "try { /*1*/ } catch { /*2*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Delete [(E1 e)]@22",
            "Delete [when (e == null)]@29");
    }
 
    [Fact]
    public void TryCatchFinally_DeleteHeader()
    {
        var src1 = "try { /*1*/ } catch { /*2*/ } finally { /*3*/ }";
        var src2 = "{ /*1*/ } { /*2*/ } { /*3*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ /*1*/ }]@6 -> @2",
            "Move [{ /*2*/ }]@22 -> @12",
            "Move [{ /*3*/ }]@40 -> @22",
            "Delete [try { /*1*/ } catch { /*2*/ } finally { /*3*/ }]@2",
            "Delete [catch { /*2*/ }]@16",
            "Delete [finally { /*3*/ }]@32");
    }
 
    [Fact]
    public void TryCatchFinally_InsertHeader()
    {
        var src1 = "{ /*1*/ } { /*2*/ } { /*3*/ }";
        var src2 = "try { /*1*/ } catch { /*2*/ } finally { /*3*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [try { /*1*/ } catch { /*2*/ } finally { /*3*/ }]@2",
            "Move [{ /*1*/ }]@2 -> @6",
            "Insert [catch { /*2*/ }]@16",
            "Insert [finally { /*3*/ }]@32",
            "Move [{ /*2*/ }]@12 -> @22",
            "Move [{ /*3*/ }]@22 -> @40");
    }
 
    [Fact]
    public void TryFilterFinally_InsertHeader()
    {
        var src1 = "{ /*1*/ } if (a == 1) { /*2*/ } { /*3*/ }";
        var src2 = "try { /*1*/ } catch when (a == 1) { /*2*/ } finally { /*3*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [try { /*1*/ } catch when (a == 1) { /*2*/ } finally { /*3*/ }]@2",
            "Move [{ /*1*/ }]@2 -> @6",
            "Insert [catch when (a == 1) { /*2*/ }]@16",
            "Insert [finally { /*3*/ }]@46",
            "Insert [when (a == 1)]@22",
            "Move [{ /*2*/ }]@24 -> @36",
            "Move [{ /*3*/ }]@34 -> @54",
            "Delete [if (a == 1) { /*2*/ }]@12");
    }
 
    #endregion
 
    #region Blocks
 
    [Fact]
    public void Block_Insert()
    {
        var src1 = "";
        var src2 = "{ x++; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [{ x++; }]@2",
            "Insert [x++;]@4");
    }
 
    [Fact]
    public void Block_Delete()
    {
        var src1 = "{ x++; }";
        var src2 = "";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Delete [{ x++; }]@2",
            "Delete [x++;]@4");
    }
 
    [Fact]
    public void Block_Reorder()
    {
        var src1 = "{ x++; } { y++; }";
        var src2 = "{ y++; } { x++; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [{ y++; }]@11 -> @2");
    }
 
    [Fact]
    public void Block_AddLine()
    {
        var src1 = "{ x++; }";
        var src2 = @"{ //
                            x++; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits();
    }
 
    #endregion
 
    #region Checked/Unchecked
 
    [Fact]
    public void Checked_Insert()
    {
        var src1 = "";
        var src2 = "checked { x++; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [checked { x++; }]@2",
            "Insert [{ x++; }]@10",
            "Insert [x++;]@12");
    }
 
    [Fact]
    public void Checked_Delete()
    {
        var src1 = "checked { x++; }";
        var src2 = "";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Delete [checked { x++; }]@2",
            "Delete [{ x++; }]@10",
            "Delete [x++;]@12");
    }
 
    [Fact]
    public void Checked_Update()
    {
        var src1 = "checked { x++; }";
        var src2 = "unchecked { x++; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [checked { x++; }]@2 -> [unchecked { x++; }]@2");
    }
 
    [Fact]
    public void Checked_DeleteHeader()
    {
        var src1 = "checked { x++; }";
        var src2 = "{ x++; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ x++; }]@10 -> @2",
            "Delete [checked { x++; }]@2");
    }
 
    [Fact]
    public void Checked_InsertHeader()
    {
        var src1 = "{ x++; }";
        var src2 = "checked { x++; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [checked { x++; }]@2",
            "Move [{ x++; }]@2 -> @10");
    }
 
    [Fact]
    public void Unchecked_InsertHeader()
    {
        var src1 = "{ x++; }";
        var src2 = "unchecked { x++; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [unchecked { x++; }]@2",
            "Move [{ x++; }]@2 -> @12");
    }
 
    #endregion
 
    #region Unsafe
 
    [Fact]
    public void Unsafe_Insert()
    {
        var src1 = "";
        var src2 = "unsafe { x++; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [unsafe { x++; }]@2",
            "Insert [{ x++; }]@9",
            "Insert [x++;]@11");
    }
 
    [Fact]
    public void Unsafe_Delete()
    {
        var src1 = "unsafe { x++; }";
        var src2 = "";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Delete [unsafe { x++; }]@2",
            "Delete [{ x++; }]@9",
            "Delete [x++;]@11");
    }
 
    [Fact]
    public void Unsafe_DeleteHeader()
    {
        var src1 = "unsafe { x++; }";
        var src2 = "{ x++; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ x++; }]@9 -> @2",
            "Delete [unsafe { x++; }]@2");
    }
 
    [Fact]
    public void Unsafe_InsertHeader()
    {
        var src1 = "{ x++; }";
        var src2 = "unsafe { x++; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [unsafe { x++; }]@2",
            "Move [{ x++; }]@2 -> @9");
    }
 
    #endregion
 
    #region Using Statement
 
    [Fact]
    public void Using1()
    {
        var src1 = @"using (a) { using (b) { Goo(); } }";
        var src2 = @"using (a) { using (c) { using (b) { Goo(); } } }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [using (c) { using (b) { Goo(); } }]@14",
            "Insert [{ using (b) { Goo(); } }]@24",
            "Move [using (b) { Goo(); }]@14 -> @26");
    }
 
    [Fact]
    public void Using_DeleteHeader()
    {
        var src1 = @"using (a) { Goo(); }";
        var src2 = @"{ Goo(); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ Goo(); }]@12 -> @2",
            "Delete [using (a) { Goo(); }]@2");
    }
 
    [Fact]
    public void Using_InsertHeader()
    {
        var src1 = @"{ Goo(); }";
        var src2 = @"using (a) { Goo(); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [using (a) { Goo(); }]@2",
            "Move [{ Goo(); }]@2 -> @12");
    }
 
    #endregion
 
    #region Lock Statement
 
    [Fact]
    public void Lock1()
    {
        var src1 = @"lock (a) { lock (b) { Goo(); } }";
        var src2 = @"lock (a) { lock (c) { lock (b) { Goo(); } } }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [lock (c) { lock (b) { Goo(); } }]@13",
            "Insert [{ lock (b) { Goo(); } }]@22",
            "Move [lock (b) { Goo(); }]@13 -> @24");
    }
 
    [Fact]
    public void Lock_DeleteHeader()
    {
        var src1 = @"lock (a) { Goo(); }";
        var src2 = @"{ Goo(); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ Goo(); }]@11 -> @2",
            "Delete [lock (a) { Goo(); }]@2");
    }
 
    [Fact]
    public void Lock_InsertHeader()
    {
        var src1 = @"{ Goo(); }";
        var src2 = @"lock (a) { Goo(); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [lock (a) { Goo(); }]@2",
            "Move [{ Goo(); }]@2 -> @11");
    }
 
    #endregion
 
    #region ForEach Statement
 
    [Fact]
    public void ForEach1()
    {
        var src1 = @"foreach (var a in e) { foreach (var b in f) { Goo(); } }";
        var src2 = @"foreach (var a in e) { foreach (var c in g) { foreach (var b in f) { Goo(); } } }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [foreach (var c in g) { foreach (var b in f) { Goo(); } }]@25",
            "Insert [{ foreach (var b in f) { Goo(); } }]@46",
            "Move [foreach (var b in f) { Goo(); }]@25 -> @48");
 
        var actual = ToMatchingPairs(edits.Match);
 
        var expected = new MatchingPairs
        {
            { "foreach (var a in e) { foreach (var b in f) { Goo(); } }", "foreach (var a in e) { foreach (var c in g) { foreach (var b in f) { Goo(); } } }" },
            { "{ foreach (var b in f) { Goo(); } }", "{ foreach (var c in g) { foreach (var b in f) { Goo(); } } }" },
            { "foreach (var b in f) { Goo(); }", "foreach (var b in f) { Goo(); }" },
            { "{ Goo(); }", "{ Goo(); }" },
            { "Goo();", "Goo();" }
        };
 
        expected.AssertEqual(actual);
    }
 
    [Fact]
    public void ForEach_Swap1()
    {
        var src1 = @"foreach (var a in e) { foreach (var b in f) { Goo(); } }";
        var src2 = @"foreach (var b in f) { foreach (var a in e) { Goo(); } }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [foreach (var b in f) { Goo(); }]@25 -> @2",
            "Move [foreach (var a in e) { foreach (var b in f) { Goo(); } }]@2 -> @25",
            "Move [Goo();]@48 -> @48");
 
        var actual = ToMatchingPairs(edits.Match);
 
        var expected = new MatchingPairs
        {
            { "foreach (var a in e) { foreach (var b in f) { Goo(); } }", "foreach (var a in e) { Goo(); }" },
            { "{ foreach (var b in f) { Goo(); } }", "{ Goo(); }" },
            { "foreach (var b in f) { Goo(); }", "foreach (var b in f) { foreach (var a in e) { Goo(); } }" },
            { "{ Goo(); }", "{ foreach (var a in e) { Goo(); } }" },
            { "Goo();", "Goo();" }
        };
 
        expected.AssertEqual(actual);
    }
 
    [Fact]
    public void Foreach_DeleteHeader()
    {
        var src1 = @"foreach (var a in b) { Goo(); }";
        var src2 = @"{ Goo(); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ Goo(); }]@23 -> @2",
            "Delete [foreach (var a in b) { Goo(); }]@2");
    }
 
    [Fact]
    public void Foreach_InsertHeader()
    {
        var src1 = @"{ Goo(); }";
        var src2 = @"foreach (var a in b) { Goo(); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [foreach (var a in b) { Goo(); }]@2",
            "Move [{ Goo(); }]@2 -> @23");
    }
 
    [Fact]
    public void ForeachVariable_Update1()
    {
        var src1 = @"
foreach (var (a1, a2) in e) { }
foreach ((var b1, var b2) in e) { }
foreach (var a in e1) { }
";
 
        var src2 = @"
foreach (var (a1, a3) in e) { }
foreach ((var b3, int b2) in e) { }
foreach (_ in e1) { }
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [foreach ((var b1, var b2) in e) { }]@37 -> [foreach ((var b3, int b2) in e) { }]@37",
            "Update [foreach (var a in e1) { }]@74 -> [foreach (_ in e1) { }]@74",
            "Update [a2]@22 -> [a3]@22",
            "Update [b1]@51 -> [b3]@51");
    }
 
    [Fact]
    public void ForeachVariable_Update2()
    {
        var src1 = @"
foreach (_ in e2) { }
foreach (_ in e3) {  A(); }
";
 
        var src2 = @"
foreach (var b in e2) { }
foreach (_ in e4) { A(); }
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [foreach (_ in e2) { }]@4 -> [foreach (var b in e2) { }]@4",
            "Update [foreach (_ in e3) {  A(); }]@27 -> [foreach (_ in e4) { A(); }]@31");
    }
 
    [Fact]
    public void ForeachVariable_Insert()
    {
        var src1 = @"
foreach (var (a3, a4) in e) { }
foreach ((var b4, var b5) in e) { }
";
 
        var src2 = @"
foreach (var (a3, a5, a4) in e) { }
foreach ((var b6, var b4, var b5) in e) { }
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [foreach (var (a3, a4) in e) { }]@4 -> [foreach (var (a3, a5, a4) in e) { }]@4",
            "Update [foreach ((var b4, var b5) in e) { }]@37 -> [foreach ((var b6, var b4, var b5) in e) { }]@41",
            "Insert [a5]@22",
            "Insert [b6]@55");
    }
 
    [Fact]
    public void ForeachVariable_Delete()
    {
        var src1 = @"
foreach (var (a11, a12, a13) in e) { F(); }
foreach ((var b7, var b8, var b9) in e) { G(); }
";
 
        var src2 = @"
foreach (var (a12, a13) in e1) { F(); }
foreach ((var b7, var b9) in e) { G(); }
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [foreach (var (a11, a12, a13) in e) { F(); }]@4 -> [foreach (var (a12, a13) in e1) { F(); }]@4",
            "Update [foreach ((var b7, var b8, var b9) in e) { G(); }]@49 -> [foreach ((var b7, var b9) in e) { G(); }]@45",
            "Delete [a11]@18",
            "Delete [b8]@71");
    }
 
    [Fact]
    public void ForeachVariable_Reorder()
    {
        var src1 = @"
foreach (var (a, b) in e1) { }
foreach ((var x, var y) in e2) { }
";
 
        var src2 = @"
foreach ((var x, var y) in e2) { }
foreach (var (a, b) in e1) { }
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [foreach ((var x, var y) in e2) { }]@36 -> @4");
    }
 
    [Fact]
    public void ForeachVariableEmbedded_Reorder()
    {
        var src1 = @"
foreach (var (a, b) in e1) { 
    foreach ((var x, var y) in e2) { }
}
";
 
        var src2 = @"
foreach ((var x, var y) in e2) { }
foreach (var (a, b) in e1) { }
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [foreach ((var x, var y) in e2) { }]@39 -> @4");
    }
 
    #endregion
 
    #region For Statement
 
    [Fact]
    public void For1()
    {
        var src1 = @"for (int a = 0; a < 10; a++) { for (int a = 0; a < 20; a++) { Goo(); } }";
        var src2 = @"for (int a = 0; a < 10; a++) { for (int b = 0; b < 10; b++) { for (int a = 0; a < 20; a++) { Goo(); } } }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [for (int b = 0; b < 10; b++) { for (int a = 0; a < 20; a++) { Goo(); } }]@33",
            "Insert [int b = 0]@38",
            "Insert [b < 10]@49",
            "Insert [b++]@57",
            "Insert [{ for (int a = 0; a < 20; a++) { Goo(); } }]@62",
            "Insert [b = 0]@42",
            "Move [for (int a = 0; a < 20; a++) { Goo(); }]@33 -> @64");
    }
 
    [Fact]
    public void For_DeleteHeader()
    {
        var src1 = @"for (int i = 10, j = 0; i > j; i--, j++) { Goo(); }";
        var src2 = @"{ Goo(); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ Goo(); }]@43 -> @2",
            "Delete [for (int i = 10, j = 0; i > j; i--, j++) { Goo(); }]@2",
            "Delete [int i = 10, j = 0]@7",
            "Delete [i = 10]@11",
            "Delete [j = 0]@19",
            "Delete [i > j]@26",
            "Delete [i--]@33",
            "Delete [j++]@38");
    }
 
    [Fact]
    public void For_InsertHeader()
    {
        var src1 = @"{ Goo(); }";
        var src2 = @"for (int i = 10, j = 0; i > j; i--, j++) { Goo(); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [for (int i = 10, j = 0; i > j; i--, j++) { Goo(); }]@2",
            "Insert [int i = 10, j = 0]@7",
            "Insert [i > j]@26",
            "Insert [i--]@33",
            "Insert [j++]@38",
            "Move [{ Goo(); }]@2 -> @43",
            "Insert [i = 10]@11",
            "Insert [j = 0]@19");
    }
 
    [Fact]
    public void For_DeclaratorsToInitializers()
    {
        var src1 = @"for (var i = 10; i < 10; i++) { }";
        var src2 = @"for (i = 10; i < 10; i++) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [i = 10]@7",
            "Delete [var i = 10]@7",
            "Delete [i = 10]@11");
    }
 
    [Fact]
    public void For_InitializersToDeclarators()
    {
        var src1 = @"for (i = 10, j = 0; i < 10; i++) { }";
        var src2 = @"for (var i = 10, j = 0; i < 10; i++) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [var i = 10, j = 0]@7",
            "Insert [i = 10]@11",
            "Insert [j = 0]@19",
            "Delete [i = 10]@7",
            "Delete [j = 0]@15");
    }
 
    [Fact]
    public void For_Declarations_Reorder()
    {
        var src1 = @"for (var i = 10, j = 0; i > j; i++, j++) { }";
        var src2 = @"for (var j = 0, i = 10; i > j; i++, j++) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Reorder [j = 0]@19 -> @11");
    }
 
    [Fact]
    public void For_Declarations_Insert()
    {
        var src1 = @"for (var i = 0, j = 1; i > j; i++, j++) { }";
        var src2 = @"for (var i = 0, j = 1, k = 2; i > j; i++, j++) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [var i = 0, j = 1]@7 -> [var i = 0, j = 1, k = 2]@7",
            "Insert [k = 2]@25");
    }
 
    [Fact]
    public void For_Declarations_Delete()
    {
        var src1 = @"for (var i = 0, j = 1, k = 2; i > j; i++, j++) { }";
        var src2 = @"for (var i = 0, j = 1; i > j; i++, j++) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [var i = 0, j = 1, k = 2]@7 -> [var i = 0, j = 1]@7",
            "Delete [k = 2]@25");
    }
 
    [Fact]
    public void For_Initializers_Reorder()
    {
        var src1 = @"for (i = 10, j = 0; i > j; i++, j++) { }";
        var src2 = @"for (j = 0, i = 10; i > j; i++, j++) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Reorder [j = 0]@15 -> @7");
    }
 
    [Fact]
    public void For_Initializers_Insert()
    {
        var src1 = @"for (i = 10; i < 10; i++) { }";
        var src2 = @"for (i = 10, j = 0; i < 10; i++) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Insert [j = 0]@15");
    }
 
    [Fact]
    public void For_Initializers_Delete()
    {
        var src1 = @"for (i = 10, j = 0; i < 10; i++) { }";
        var src2 = @"for (i = 10; i < 10; i++) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Delete [j = 0]@15");
    }
 
    [Fact]
    public void For_Initializers_Update()
    {
        var src1 = @"for (i = 1; i < 10; i++) { }";
        var src2 = @"for (i = 2; i < 10; i++) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Update [i = 1]@7 -> [i = 2]@7");
    }
 
    [Fact]
    public void For_Initializers_Update_Lambda()
    {
        var src1 = @"for (int i = 10, j = F(() => 1); i > j; i++) { }";
        var src2 = @"for (int i = 10, j = F(() => 2); i > j; i++) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Update [() => 1]@25 -> [() => 2]@25");
    }
 
    [Fact]
    public void For_Condition_Update()
    {
        var src1 = @"for (int i = 0; i < 10; i++) { }";
        var src2 = @"for (int i = 0; i < 20; i++) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Update [i < 10]@18 -> [i < 20]@18");
    }
 
    [Fact]
    public void For_Condition_Lambda()
    {
        var src1 = @"for (int i = 0; F(() => 1); i++) { }";
        var src2 = @"for (int i = 0; F(() => 2); i++) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Update [() => 1]@20 -> [() => 2]@20");
    }
 
    [Fact]
    public void For_Incrementors_Reorder()
    {
        var src1 = @"for (int i = 10, j = 0; i > j; i--, j++) { }";
        var src2 = @"for (int i = 10, j = 0; i > j; j++, i--) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Reorder [j++]@38 -> @33");
    }
 
    [Fact]
    public void For_Incrementors_Insert()
    {
        var src1 = @"for (int i = 10, j = 0; i > j; i--) { }";
        var src2 = @"for (int i = 10, j = 0; i > j; j++, i--) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Insert [j++]@33");
    }
 
    [Fact]
    public void For_Incrementors_Delete()
    {
        var src1 = @"for (int i = 10, j = 0; i > j; j++, i--) { }";
        var src2 = @"for (int i = 10, j = 0; i > j; j++) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Delete [i--]@38");
    }
 
    [Fact]
    public void For_Incrementors_Update()
    {
        var src1 = @"for (int i = 10, j = 0; i > j; j++) { }";
        var src2 = @"for (int i = 10, j = 0; i > j; i++) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Update [j++]@33 -> [i++]@33");
    }
 
    [Fact]
    public void For_Incrementors_Update_Lambda()
    {
        var src1 = @"for (int i = 10, j = 0; i > j; F(() => 1)) { }";
        var src2 = @"for (int i = 10, j = 0; i > j; F(() => 2)) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Update [() => 1]@35 -> [() => 2]@35");
    }
 
    #endregion
 
    #region While Statement
 
    [Fact]
    public void While1()
    {
        var src1 = @"while (a) { while (b) { Goo(); } }";
        var src2 = @"while (a) { while (c) { while (b) { Goo(); } } }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [while (c) { while (b) { Goo(); } }]@14",
            "Insert [{ while (b) { Goo(); } }]@24",
            "Move [while (b) { Goo(); }]@14 -> @26");
    }
 
    [Fact]
    public void While_DeleteHeader()
    {
        var src1 = @"while (a) { Goo(); }";
        var src2 = @"{ Goo(); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ Goo(); }]@12 -> @2",
            "Delete [while (a) { Goo(); }]@2");
    }
 
    [Fact]
    public void While_InsertHeader()
    {
        var src1 = @"{ Goo(); }";
        var src2 = @"while (a) { Goo(); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [while (a) { Goo(); }]@2",
            "Move [{ Goo(); }]@2 -> @12");
    }
 
    #endregion
 
    #region Do Statement
 
    [Fact]
    public void Do1()
    {
        var src1 = @"do { do { Goo(); } while (b); } while (a);";
        var src2 = @"do { do { do { Goo(); } while(b); } while(c); } while(a);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [do { do { Goo(); } while(b); } while(c);]@7",
            "Insert [{ do { Goo(); } while(b); }]@10",
            "Move [do { Goo(); } while (b);]@7 -> @12");
    }
 
    [Fact]
    public void Do_DeleteHeader()
    {
        var src1 = @"do { Goo(); } while (a);";
        var src2 = @"{ Goo(); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ Goo(); }]@5 -> @2",
            "Delete [do { Goo(); } while (a);]@2");
    }
 
    [Fact]
    public void Do_InsertHeader()
    {
        var src1 = @"{ Goo(); }";
        var src2 = @"do { Goo(); } while (a);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [do { Goo(); } while (a);]@2",
            "Move [{ Goo(); }]@2 -> @5");
    }
 
    #endregion
 
    #region If Statement
 
    [Fact]
    public void IfStatement_TestExpression_Update()
    {
        var src1 = "var x = 1; if (x == 1) { x++; }";
        var src2 = "var x = 1; if (x == 2) { x++; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [if (x == 1) { x++; }]@13 -> [if (x == 2) { x++; }]@13");
    }
 
    [Fact]
    public void ElseClause_Insert()
    {
        var src1 = "if (x == 1) x++; ";
        var src2 = "if (x == 1) x++; else y++;";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [else y++;]@19",
            "Insert [y++;]@24");
    }
 
    [Fact]
    public void ElseClause_InsertMove()
    {
        var src1 = "if (x == 1) x++; else y++;";
        var src2 = "if (x == 1) x++; else if (x == 2) y++;";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [if (x == 2) y++;]@24",
            "Move [y++;]@24 -> @36");
    }
 
    [Fact]
    public void If1()
    {
        var src1 = @"if (a) if (b) Goo();";
        var src2 = @"if (a) if (c) if (b) Goo();";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [if (c) if (b) Goo();]@9",
            "Move [if (b) Goo();]@9 -> @16");
    }
 
    [Fact]
    public void If_DeleteHeader()
    {
        var src1 = @"if (a) { Goo(); }";
        var src2 = @"{ Goo(); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ Goo(); }]@9 -> @2",
            "Delete [if (a) { Goo(); }]@2");
    }
 
    [Fact]
    public void If_InsertHeader()
    {
        var src1 = @"{ Goo(); }";
        var src2 = @"if (a) { Goo(); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [if (a) { Goo(); }]@2",
            "Move [{ Goo(); }]@2 -> @9");
    }
 
    [Fact]
    public void Else_DeleteHeader()
    {
        var src1 = @"if (a) { Goo(/*1*/); } else { Goo(/*2*/); }";
        var src2 = @"if (a) { Goo(/*1*/); } { Goo(/*2*/); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ Goo(/*2*/); }]@30 -> @25",
            "Delete [else { Goo(/*2*/); }]@25");
    }
 
    [Fact]
    public void Else_InsertHeader()
    {
        var src1 = @"if (a) { Goo(/*1*/); } { Goo(/*2*/); }";
        var src2 = @"if (a) { Goo(/*1*/); } else { Goo(/*2*/); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [else { Goo(/*2*/); }]@25",
            "Move [{ Goo(/*2*/); }]@25 -> @30");
    }
 
    [Fact]
    public void ElseIf_DeleteHeader()
    {
        var src1 = @"if (a) { Goo(/*1*/); } else if (b) { Goo(/*2*/); }";
        var src2 = @"if (a) { Goo(/*1*/); } { Goo(/*2*/); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ Goo(/*2*/); }]@37 -> @25",
            "Delete [else if (b) { Goo(/*2*/); }]@25",
            "Delete [if (b) { Goo(/*2*/); }]@30");
    }
 
    [Fact]
    public void ElseIf_InsertHeader()
    {
        var src1 = @"if (a) { Goo(/*1*/); } { Goo(/*2*/); }";
        var src2 = @"if (a) { Goo(/*1*/); } else if (b) { Goo(/*2*/); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [else if (b) { Goo(/*2*/); }]@25",
            "Insert [if (b) { Goo(/*2*/); }]@30",
            "Move [{ Goo(/*2*/); }]@25 -> @37");
    }
 
    [Fact]
    public void IfElseElseIf_InsertHeader()
    {
        var src1 = @"{ /*1*/ } { /*2*/ } { /*3*/ }";
        var src2 = @"if (a) { /*1*/ } else if (b) { /*2*/ } else { /*3*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [if (a) { /*1*/ } else if (b) { /*2*/ } else { /*3*/ }]@2",
            "Move [{ /*1*/ }]@2 -> @9",
            "Insert [else if (b) { /*2*/ } else { /*3*/ }]@19",
            "Insert [if (b) { /*2*/ } else { /*3*/ }]@24",
            "Move [{ /*2*/ }]@12 -> @31",
            "Insert [else { /*3*/ }]@41",
            "Move [{ /*3*/ }]@22 -> @46");
    }
 
    [Fact]
    public void IfElseElseIf_DeleteHeader()
    {
        var src1 = @"if (a) { /*1*/ } else if (b) { /*2*/ } else { /*3*/ }";
        var src2 = @"{ /*1*/ } { /*2*/ } { /*3*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Move [{ /*1*/ }]@9 -> @2",
            "Move [{ /*2*/ }]@31 -> @12",
            "Move [{ /*3*/ }]@46 -> @22",
            "Delete [if (a) { /*1*/ } else if (b) { /*2*/ } else { /*3*/ }]@2",
            "Delete [else if (b) { /*2*/ } else { /*3*/ }]@19",
            "Delete [if (b) { /*2*/ } else { /*3*/ }]@24",
            "Delete [else { /*3*/ }]@41");
    }
 
    #endregion
 
    #region Switch Statement
 
    [Fact]
    public void SwitchStatement_Update_Expression()
    {
        var src1 = "var x = 1; switch (x + 1) { case 1: break; }";
        var src2 = "var x = 1; switch (x + 2) { case 1: break; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [switch (x + 1) { case 1: break; }]@13 -> [switch (x + 2) { case 1: break; }]@13");
    }
 
    [Fact]
    public void SwitchStatement_Update_SectionLabel()
    {
        var src1 = "var x = 1; switch (x) { case 1: break; }";
        var src2 = "var x = 1; switch (x) { case 2: break; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [case 1: break;]@26 -> [case 2: break;]@26");
    }
 
    [Fact]
    public void SwitchStatement_Update_AddSectionLabel()
    {
        var src1 = "var x = 1; switch (x) { case 1: break; }";
        var src2 = "var x = 1; switch (x) { case 1: case 2: break; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [case 1: break;]@26 -> [case 1: case 2: break;]@26");
    }
 
    [Fact]
    public void SwitchStatement_Update_DeleteSectionLabel()
    {
        var src1 = "var x = 1; switch (x) { case 1: case 2: break; }";
        var src2 = "var x = 1; switch (x) { case 1: break; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [case 1: case 2: break;]@26 -> [case 1: break;]@26");
    }
 
    [Fact]
    public void SwitchStatement_Update_BlockInSection()
    {
        var src1 = "var x = 1; switch (x) { case 1: { x++; break; } }";
        var src2 = "var x = 1; switch (x) { case 1: { x--; break; } }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [x++;]@36 -> [x--;]@36");
    }
 
    [Fact]
    public void SwitchStatement_Update_BlockInDefaultSection()
    {
        var src1 = "var x = 1; switch (x) { default: { x++; break; } }";
        var src2 = "var x = 1; switch (x) { default: { x--; break; } }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [x++;]@37 -> [x--;]@37");
    }
 
    [Fact]
    public void SwitchStatement_Insert_Section()
    {
        var src1 = "var x = 1; switch (x) { case 1: break; }";
        var src2 = "var x = 1; switch (x) { case 1: break; case 2: break; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [case 2: break;]@41",
            "Insert [break;]@49");
    }
 
    [Fact]
    public void SwitchStatement_Delete_Section()
    {
        var src1 = "var x = 1; switch (x) { case 1: break; case 2: break; }";
        var src2 = "var x = 1; switch (x) { case 1: break; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Delete [case 2: break;]@41",
            "Delete [break;]@49");
    }
 
    #endregion
 
    #region Lambdas
 
    [Fact]
    public void Lambdas_AddAttribute()
    {
        var src1 = "Func<int, int> x = (a) => a;";
        var src2 = "Func<int, int> x = [A][return:A]([A]a) => a;";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [(a) => a]@21 -> [[A][return:A]([A]a) => a]@21",
            "Update [a]@22 -> [[A]a]@35");
 
        GetTopEdits(edits).VerifySemanticDiagnostics(
            [
                Diagnostic(RudeEditKind.ChangingAttributesNotSupportedByRuntime, "([A]a)", GetResource("lambda")),
                Diagnostic(RudeEditKind.ChangingAttributesNotSupportedByRuntime, "([A]a)", GetResource("lambda")),
                Diagnostic(RudeEditKind.ChangingAttributesNotSupportedByRuntime, "([A]a)", GetResource("parameter"))
            ],
            capabilities: EditAndContinueCapabilities.Baseline);
 
        GetTopEdits(edits).VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.ChangeCustomAttributes);
    }
 
    [Fact]
    public void Lambdas_InVariableDeclarator()
    {
        var src1 = "Action x = a => a, y = b => b;";
        var src2 = "Action x = (a) => a, y = b => b + 1;";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [a => a]@13 -> [(a) => a]@13",
            "Update [b => b]@25 -> [b => b + 1]@27",
            "Insert [(a)]@13",
            "Insert [a]@14",
            "Delete [a]@13");
    }
 
    [Fact]
    public void Lambdas_InExpressionStatement()
    {
        var src1 = "F(a => a, b => b);";
        var src2 = "F(b => b, a => a+1);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [b => b]@12 -> @4",
            "Update [a => a]@4 -> [a => a+1]@12");
    }
 
    [Fact]
    public void Lambdas_ReorderArguments()
    {
        var src1 = "F(G(a => {}), G(b => {}));";
        var src2 = "F(G(b => {}), G(a => {}));";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [b => {}]@18 -> @6");
    }
 
    [Fact]
    public void Lambdas_InWhile()
    {
        var src1 = "while (F(a => a)) { /*1*/ }";
        var src2 = "do { /*1*/ } while (F(a => a));";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [do { /*1*/ } while (F(a => a));]@2",
            "Move [{ /*1*/ }]@20 -> @5",
            "Move [a => a]@11 -> @24",
            "Delete [while (F(a => a)) { /*1*/ }]@2");
    }
 
    [Fact]
    public void Lambdas_InLambda_ChangeInLambdaSignature()
    {
        var src1 = "F(() => { G(x => y); });";
        var src2 = "F(q => { G(() => y); });";
 
        var edits = GetMethodEdits(src1, src2);
 
        // changes were made to the outer lambda signature:
        edits.VerifyEdits(
            "Update [() => { G(x => y); }]@4 -> [q => { G(() => y); }]@4",
            "Insert [q]@4",
            "Delete [()]@4");
    }
 
    [Fact]
    public void Lambdas_InLambda_ChangeOnlyInLambdaBody()
    {
        var src1 = "F(() => { G(x => y); });";
        var src2 = "F(() => { G(() => y); });";
 
        var edits = GetMethodEdits(src1, src2);
 
        // no changes to the method were made, only within the outer lambda body:
        edits.VerifyEdits();
    }
 
    [Fact]
    public void Lambdas_Insert_First_Static()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        var f = new Func<int, int>(a => a);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.AddStaticFieldToExistingType | EditAndContinueCapabilities.AddMethodToExistingType);
 
        edits.VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "a", GetResource("lambda"))],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void Lambdas_Insert_First_Static_InGenericContext_Method()
    {
        var src1 = @"
using System;
class C
{
    void F<T>()
    {
    }
}";
        var src2 = @"
using System;
class C
{
    void F<T>()
    {
        var f = new Func<int, int>(a => a);
    }
}";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities:
                EditAndContinueCapabilities.NewTypeDefinition |
                EditAndContinueCapabilities.AddMethodToExistingType |
                EditAndContinueCapabilities.AddStaticFieldToExistingType |
                EditAndContinueCapabilities.GenericAddMethodToExistingType |
                EditAndContinueCapabilities.GenericAddFieldToExistingType |
                EditAndContinueCapabilities.GenericUpdateMethod);
 
        edits.VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "a", GetResource("lambda"))],
            capabilities: EditAndContinueCapabilities.GenericUpdateMethod);
    }
 
    [Fact]
    public void Lambdas_Insert_First_Static_InGenericContext_Type()
    {
        var src1 = @"
using System;
class C<T>
{
    void F()
    {
    }
}";
        var src2 = @"
using System;
class C<T>
{
    void F()
    {
        var f = new Func<int, int>(a => a);
    }
}";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities:
                EditAndContinueCapabilities.NewTypeDefinition |
                EditAndContinueCapabilities.AddMethodToExistingType |
                EditAndContinueCapabilities.AddStaticFieldToExistingType |
                EditAndContinueCapabilities.GenericAddMethodToExistingType |
                EditAndContinueCapabilities.GenericAddFieldToExistingType |
                EditAndContinueCapabilities.GenericUpdateMethod);
 
        edits.VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "a", GetResource("lambda"))],
            capabilities: EditAndContinueCapabilities.GenericUpdateMethod);
    }
 
    [Fact]
    public void Lambdas_Insert_First_Static_InGenericContext_LocalFunction()
    {
        var src1 = @"
using System;
class C
{
    void F()
    {
        void L<T>()
        {
        }
    }
}";
        var src2 = @"
using System;
class C
{
    void F()
    {
        void L<T>()
        {
            var f = new Func<int, int>(a => a);
        }
    }
}";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities:
                EditAndContinueCapabilities.NewTypeDefinition |
                EditAndContinueCapabilities.AddMethodToExistingType |
                EditAndContinueCapabilities.GenericAddMethodToExistingType |
                EditAndContinueCapabilities.GenericUpdateMethod);
 
        edits.VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "a", GetResource("lambda"))],
            capabilities: EditAndContinueCapabilities.GenericUpdateMethod);
    }
 
    [Fact]
    public void Lambdas_Insert_Static_Nested()
    {
        var src1 = @"
using System;
 
class C
{
    static int G(Func<int, int> f) => 0;
 
    void F()
    {
        G(a => a);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    static int G(Func<int, int> f) => 0;
   
    void F()
    {
        G(a => G(b => b) + a);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddStaticFieldToExistingType);
 
        edits.VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "b", GetResource("lambda"))],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void Lambdas_Insert_ThisOnly_Top1()
    {
        var src1 = @"
using System;
 
class C
{
    int x = 0;
    int G(Func<int, int> f) => 0;
 
    void F()
    {
 
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int x = 0;
    int G(Func<int, int> f) => 0;
   
    void F()
    {
        G(a => x);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/1291")]
    public void Lambdas_Insert_ThisOnly_Top2()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        int y = 1;
        {
            int x = 2;
            var f1 = new Func<int, int>(a => y);
        }
    }
}
";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        int y = 1;
        {
            int x = 2;
            var f2 = from a in new[] { 1 } select a + y;
            var f3 = from a in new[] { 1 } where x > 0 select a;
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Insert_ThisOnly_Nested1()
    {
        var src1 = @"
using System;
 
class C
{
    int x = 0;
    int G(Func<int, int> f) => 0;
 
    void F()
    {
        G(a => a);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int x = 0;
    int G(Func<int, int> f) => 0;
   
    void F()
    {
        G(a => G(b => x));
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Insert_ThisOnly_Nested2()
    {
        var src1 = @"
using System;
 
class C
{
    int x = 0;
 
    void F()
    {
        var f1 = new Func<int, int>(a => 
        {
            var f2 = new Func<int, int>(b => 
            {
                return b;
            });
 
            return a;
        });
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int x = 0;
   
    void F()
    {
        var f1 = new Func<int, int>(a => 
        {
            var f2 = new Func<int, int>(b => 
            {
                return b;
            });
 
            var f3 = new Func<int, int>(c => 
            {
                return c + x;
            });
 
            return a;
        });
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Insert_PrimaryParameterOnly_Top()
    {
        var src1 = @"
using System;
 
class C(int x)
{
    int G(Func<int, int> f) => 0;
 
    void F()
    {
        
    }
}
";
        var src2 = @"
using System;
 
class C(int x)
{
    int G(Func<int, int> f) => 0;
   
    void F()
    {
        G(a => x);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Insert_PrimaryParameterOnly_Nested()
    {
        var src1 = @"
using System;
 
class C(int x)
{
    void F()
    {
        var f1 = new Func<int, int>(a => 
        {
            var f2 = new Func<int, int>(b => 
            {
                return b;
            });
 
            return a;
        });
    }
}
";
        var src2 = @"
using System;
 
class C(int x)
{
    void F()
    {
        var f1 = new Func<int, int>(a => 
        {
            var f2 = new Func<int, int>(b => 
            {
                return b;
            });
 
            var f3 = new Func<int, int>(c => 
            {
                return c + x;
            });
 
            return a;
        });
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Insert_ThisOnly_Second()
    {
        var src1 = @"
using System;
 
class C
{
    int x = 0;
 
    void F()
    {
        var f1 = new Func<int, int>(a => x);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int x = 0;
   
    void F()
    {
        var f1 = new Func<int, int>(a => x);
        var f2 = new Func<int, int>(b => x);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType);
 
        edits.VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "b", GetResource("lambda"))],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void Lambdas_Insert_ThisAndPrimaryParameter()
    {
        var src1 = @"
using System;
 
class C(int y)
{
    int x = 0;
 
    void F()
    {
        var f1 = new Func<int, int>(a => x);
    }
}
";
        var src2 = @"
using System;
 
class C(int y)
{
    int x = 0;
   
    void F()
    {
        var f1 = new Func<int, int>(a => x);
        var f2 = new Func<int, int>(b => y);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType);
 
        edits.VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "b", GetResource("lambda"))],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void Lambdas_Insert_Closure_Second()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int x = 1;
        var f1 = new Func<int, int>(a => x);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        int x = 1;
        var f1 = new Func<int, int>(a => x);
        var f2 = new Func<int, int>(b => x);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType);
 
        edits.VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "b", GetResource("lambda"))],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void Lambdas_InsertAndDelete_Scopes1()
    {
        var src1 = @"
using System;
 
class C
{
    void G(Func<int, int> f) {}
 
    int x = 0, y = 0;                      // Group #0
 
    void F()
    {
        int x0 = 0, y0 = 0;                // Group #1 
                                         
        { int x1 = 0, y1 = 0;              // Group #2 
                                           
            { int x2 = 0, y2 = 0;          // Group #1 
                                            
                { int x3 = 0, y3 = 0;      // Group #2 
                                           
                    G(a => x3 + x1);       
                    G(b => x0 + y0 + x2);
                    G(c => x);
                }
            }
        }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G(Func<int, int> f) {}
 
    int x = 0, y = 0;                       // Group #0
 
    void F()
    {
        int x0 = 0, y0 = 0;                 // Group #1
                                           
        { int x1 = 0, y1 = 0;               // Group #2 
                                           
            { int x2 = 0, y2 = 0;           // Group #1
                                           
                { int x3 = 0, y3 = 0;       // Group #2 
                                            
                    G(a => x3 + x1);        
                    G(b => x0 + y0 + x2);
                    G(c => x);
 
                    G(d => x);              // OK
                    G(e => x0 + y0);        // OK
                    G(f => x1 + y0);        // runtime rude edit - connecting Group #1 and Group #2
                    G(g => x3 + x1);        // runtime rude edit - multi-scope (conservative)
                    G(h => x + y0);         // runtime rude edit - connecting Group #0 and Group #1
                    G(i => x + x3);         // runtime rude edit - connecting Group #0 and Group #2
                }
            }
        }
    }
}
";
        var insert = GetTopEdits(src1, src2);
 
        insert.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
 
        var delete = GetTopEdits(src2, src1);
 
        delete.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Insert_ForEach1()
    {
        var src1 = @"
using System;
 
class C
{
    void G(Func<int, int> f) {}
 
    void F()                       
    {                              
        foreach (int x0 in new[] { 1 })  // Group #0             
        {                                // Group #1
            int x1 = 0;                  
                                         
            G(a => x0);   
            G(a => x1);
        }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G(Func<int, int> f) {}
 
    void F()                       
    {                              
        foreach (int x0 in new[] { 1 })  // Group #0             
        {                                // Group #1
            int x1 = 0;                  
                                         
            G(a => x0);   
            G(a => x1);
 
            G(a => x0 + x1);             // runtime rude edit: connecting previously disconnected closures
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Insert_ForEach2()
    {
        var src1 = @"
using System;
 
class C
{
    void G(Func<int, int> f1, Func<int, int> f2, Func<int, int> f3) {}
 
    void F()                       
    {               
        int x0 = 0;                              // Group #0  
        foreach (int x1 in new[] { 1 })          // Group #1                   
            G(a => x0, a => x1, null);                     
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G(Func<int, int> f1, Func<int, int> f2, Func<int, int> f3) {}
 
    void F()                       
    {               
        int x0 = 0;                              // Group #0  
        foreach (int x1 in new[] { 1 })          // Group #1            
            G(a => x0, a => x1, a => x0 + x1);   // runtime rude edit: connecting previously disconnected closures            
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Insert_For1()
    {
        var src1 = @"
using System;
 
class C
{
    bool G(Func<int, int> f) => true;
 
    void F()                       
    {                              
        for (int x0 = 0, x1 = 0; G(a => x0) && G(a => x1);)
        {
            int x2 = 0;
            G(a => x2); 
        }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    bool G(Func<int, int> f) => true;
 
    void F()                       
    {                              
        for (int x0 = 0, x1 = 0; G(a => x0) && G(a => x1);)
        {
            int x2 = 0;
            G(a => x2); 
 
            G(a => x0 + x1);  // ok
            G(a => x0 + x2);  // runtime rude edit: connecting previously disconnected closures
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Insert_Switch1()
    {
        var src1 = @"
using System;
 
class C
{
    bool G(Func<int> f) => true;
 
    int a = 1;
 
    void F()                       
    {        
        int x2 = 1;
        G(() => x2);
                      
        switch (a)
        {
            case 1:
                int x0 = 1;
                G(() => x0);
                break;
 
            case 2:
                int x1 = 1;
                G(() => x1);
                break;
        }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    bool G(Func<int> f) => true;
 
    int a = 1;
 
    void F()                       
    {                
        int x2 = 1;
        G(() => x2);
 
        switch (a)
        {
            case 1:
                int x0 = 1;
                G(() => x0);
                goto case 2;
 
            case 2:
                int x1 = 1;
                G(() => x1);
                goto default;
 
            default:
                x0 = 1;
                x1 = 2;
                G(() => x0 + x1);       // ok
                G(() => x0 + x2);       // runtime rude edit
                break;
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Insert_Using1()
    {
        var src1 = @"
using System;
 
class C
{
    static bool G<T>(Func<T> f) => true;
    static int H(object a, object b) => 1;
 
    static IDisposable D() => null;
    
    static void F()                       
    {                              
        using (IDisposable x0 = D(), y0 = D())
        {
            int x1 = 1;
        
            G(() => x0);
            G(() => y0);
            G(() => x1);
        }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    static bool G<T>(Func<T> f) => true;
    static int H(object a, object b) => 1;
 
    static IDisposable D() => null;
    
    static void F()                       
    {                              
        using (IDisposable x0 = D(), y0 = D())
        {
            int x1 = 1;
        
            G(() => x0);
            G(() => y0);
            G(() => x1);
 
            G(() => H(x0, y0)); // ok
            G(() => H(x0, x1)); // runtime rude edit
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Insert_Catch1()
    {
        var src1 = @"
using System;
 
class C
{
    static bool G<T>(Func<T> f) => true;
    static int H(object a, object b) => 1;
    
    static void F()                       
    {                              
        try
        {
        }
        catch (Exception x0)
        {
            int x1 = 1;
            G(() => x0);
            G(() => x1);
        }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    static bool G<T>(Func<T> f) => true;
    static int H(object a, object b) => 1;
    
    static void F()                       
    {                              
        try
        {
        }
        catch (Exception x0)
        {
            int x1 = 1;
            G(() => x0);
            G(() => x1);
 
            G(() => x0); //ok
            G(() => H(x0, x1)); // runtime rude edit
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/1504")]
    public void Lambdas_Insert_CatchFilter1()
    {
        var src1 = @"
using System;
 
class C
{
    static bool G<T>(Func<T> f) => true;
    
    static void F()                       
    {                              
        Exception x1 = null;
    
        try
        {
            G(() => x1);
        }
        catch (Exception x0) when (G(() => x0))
        {
        }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    static bool G<T>(Func<T> f) => true;
    
    static void F()                       
    {                 
        Exception x1 = null;
             
        try
        {
            G(() => x1);
        }
        catch (Exception x0) when (G(() => x0) && 
                                   G(() => x0) &&    // ok
                                   G(() => x0 != x1)) // runtime rude edit
        {
            G(() => x0); // ok
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Insert_Static_Second()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        var f = new Func<int, int>(a => a);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        var f = new Func<int, int>(a => a);
        var g = new Func<int, int>(b => b);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddStaticFieldToExistingType);
 
        edits.VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "b", CSharpFeaturesResources.lambda)],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void Lambdas_Update_ParameterRefness_NoBodyChange()
    {
        var src1 = @"F((ref int a) => a = 1);";
        var src2 = @"F((out int a) => a = 1);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [ref int a]@5 -> [out int a]@5");
    }
 
    [Fact]
    public void Lambdas_Update_Signature1()
    {
        var src1 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Func<long, long> f) {}
 
    void F()
    {
        G1(<N:0>a => a</N:0>);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Func<long, long> f) {}
 
    void F()
    {
        G2(<N:0>a => a</N:0>);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
            [
                RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")])
            ]));
    }
 
    [Fact]
    public void Lambdas_Update_Signature2()
    {
        var src1 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Func<int, int, int> f) {}
 
    void F()
    {
        G1(<N:0>a => a</N:0>);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Func<int, int, int> f) {}
 
    void F()
    {
        G2(<N:0>(a, b) => a + b</N:0>);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
            [
                RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")])
            ]));
    }
 
    [Fact]
    public void Lambdas_Update_Signature3()
    {
        var src1 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Func<int, long> f) {}
 
    void F()
    {
        G1(<N:0>a => a</N:0>);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Func<int, long> f) {}
 
    void F()
    {
        G2(<N:0>a => a</N:0>);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
            [
                RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")])
            ]));
    }
 
    [Fact]
    public void Lambdas_Update_Signature_Nullable()
    {
        var src1 = @"
using System;
 
class C
{
    void G1(Func<string, string> f) {}
    void G2(Func<string?, string?> f) {}
 
    void F()
    {
        G1(a => a);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G1(Func<string, string> f) {}
    void G2(Func<string?, string?> f) {}
 
    void F()
    {
        G2(a => a);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Lambdas_Update_Signature_SyntaxOnly1()
    {
        var src1 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Func<int, int> f) {}
 
    void F()
    {
        G1(a => a);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Func<int, int> f) {}
 
    void F()
    {
        G2((a) => a);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Lambdas_Update_Signature_ReturnType1()
    {
        var src1 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Action<int> f) {}
 
    void F()
    {
        G1(<N:0>a => { return 1; }</N:0>);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Action<int> f) {}
 
    void F()
    {
        G2(<N:0>a => { }</N:0>);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
            [
                RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")])
            ]));
    }
 
    [Fact]
    public void Lambdas_Update_Signature_ReturnType2()
    {
        var src1 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Action<int> f) {}
 
    void F()
    {
        var x = <N:0>int (int a) => a</N:0>;
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Action<int> f) {}
 
    void F()
    {
        var x = <N:0>long (int a) => a</N:0>;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
            [
                RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")])
            ]));
    }
 
    [Fact]
    public void Lambdas_Update_Signature_ReturnType_Anonymous()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        var x = <N:0>(int* a, int b) => a</N:0>;
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        var x = <N:0>(int* a, int b) => b</N:0>;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
            [
                RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")])
            ]));
    }
 
    [Fact]
    public void Lambdas_Update_Signature_BodySyntaxOnly()
    {
        var src1 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Func<int, int> f) {}
 
    void F()
    {
        G1(a => { return 1; });
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Func<int, int> f) {}
 
    void F()
    {
        G2(a => 2);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Lambdas_Update_Signature_ParameterName1()
    {
        var src1 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Func<int, int> f) {}
 
    void F()
    {
        G1(a => 1);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Func<int, int> f) {}
 
    void F()
    {
        G2(b => 2);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Lambdas_Update_Signature_ParameterRefness1()
    {
        var src1 = @"
using System;
 
delegate int D1(ref int a);
delegate int D2(int a);
 
class C
{
    void G1(D1 f) {}
    void G2(D2 f) {}
 
    void F()
    {
        G1(<N:0>(ref int a) => 1</N:0>);
    }
}
";
        var src2 = @"
using System;
 
delegate int D1(ref int a);
delegate int D2(int a);
 
class C
{
    void G1(D1 f) {}
    void G2(D2 f) {}
 
    void F()
    {
        G2(<N:0>(int a) => 2</N:0>);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
            [
                RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")])
            ]));
    }
 
    [Fact]
    public void Lambdas_Update_Signature_ParameterRefness2()
    {
        var src1 = @"
using System;
 
delegate int D1(ref int a);
delegate int D2(out int a);
 
class C
{
    void G(D1 f) {}
    void G(D2 f) {}
 
    void F()
    {
        G((ref int a) => a = 1);
    }
}
";
        var src2 = @"
using System;
 
delegate int D1(ref int a);
delegate int D2(out int a);
 
class C
{
    void G(D1 f) {}
    void G(D2 f) {}
 
    void F()
    {
        G((out int a) => a = 1);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    // Add corresponding test to VB
    [Fact(Skip = "TODO")]
    public void Lambdas_Update_Signature_CustomModifiers1()
    {
        var delegateSource = @"
.class public auto ansi sealed D1
       extends [mscorlib]System.MulticastDelegate
{
  .method public specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
  {
  }
 
  .method public newslot virtual instance int32 [] modopt([mscorlib]System.Int64) Invoke(
      int32 modopt([mscorlib]System.Runtime.CompilerServices.IsConst) a, 
      int32 modopt([mscorlib]System.Runtime.CompilerServices.IsConst) b) runtime managed
  {
  }
}
 
.class public auto ansi sealed D2
       extends [mscorlib]System.MulticastDelegate
{
  .method public specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
  {
  }
 
  .method public newslot virtual instance int32 [] modopt([mscorlib]System.Boolean) Invoke(
      int32 modopt([mscorlib]System.Runtime.CompilerServices.IsConst) a, 
      int32 modopt([mscorlib]System.Runtime.CompilerServices.IsConst) b) runtime managed
  {
  }
}
 
.class public auto ansi sealed D3
       extends [mscorlib]System.MulticastDelegate
{
  .method public specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
  {
  }
 
  .method public newslot virtual instance int32 [] modopt([mscorlib]System.Boolean) Invoke(
      int32 modopt([mscorlib]System.Runtime.CompilerServices.IsConst) a, 
      int32 modopt([mscorlib]System.Runtime.CompilerServices.IsConst) b) runtime managed
  {
  }
}";
 
        var src1 = @"
using System;
 
class C
{
    void G1(D1 f) {}
    void G2(D2 f) {}
 
    void F()
    {
        G1(a => a);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G1(D1 f) {}
    void G2(D2 f) {}
 
    void F()
    {
        G2(a => a);
    }
}
";
        MetadataReference delegateDefs;
        using (var tempAssembly = IlasmUtilities.CreateTempAssembly(delegateSource))
        {
            delegateDefs = MetadataReference.CreateFromImage(File.ReadAllBytes(tempAssembly.Path));
        }
 
        var edits = GetTopEdits(src1, src2);
 
        // TODO
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Lambdas_Update_Signature_MatchingErrorType()
    {
        var src1 = @"
using System;
 
class C
{
    void G(Func<Unknown, Unknown> f) {}
 
    void F()
    {
        G(a => 1);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G(Func<Unknown, Unknown> f) {}
 
    void F()
    {
        G(a => 2);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            ActiveStatementsDescription.Empty,
            semanticEdits:
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember<INamedTypeSymbol>("C").GetMembers("F").Single(), preserveLocalVariables: true)
            ]);
    }
 
    [Fact]
    public void Lambdas_Update_Signature_NonMatchingErrorType()
    {
        var src1 = @"
using System;
 
class C
{
    void G1(Func<Unknown1, Unknown1> f) {}
    void G2(Func<Unknown2, Unknown2> f) {}
 
    void F()
    {
        G1(<N:0>a => 1</N:0>);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G1(Func<Unknown1, Unknown1> f) {}
    void G2(Func<Unknown2, Unknown2> f) {}
 
    void F()
    {
        G2(<N:0>a => 2</N:0>);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
            [
                RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")])
            ]));
    }
 
    [Fact]
    public void Lambdas_Update_DelegateType1()
    {
        var src1 = @"
using System;
 
delegate int D1(int a);
delegate int D2(int a);
 
class C
{
    void G1(D1 f) {}
    void G2(D2 f) {}
 
    void F()
    {
        G1(a => a);
    }
}
";
        var src2 = @"
using System;
 
delegate int D1(int a);
delegate int D2(int a);
 
class C
{
    void G1(D1 f) {}
    void G2(D2 f) {}
 
    void F()
    {
        G2(a => a);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Lambdas_Update_SourceType1()
    {
        var src1 = @"
using System;
 
delegate C D1(C a);
delegate C D2(C a);
 
class C
{
    void G1(D1 f) {}
    void G2(D2 f) {}
 
    void F()
    {
        G1(a => a);
    }
}
";
        var src2 = @"
using System;
 
delegate C D1(C a);
delegate C D2(C a);
 
class C
{
    void G1(D1 f) {}
    void G2(D2 f) {}
 
    void F()
    {
        G2(a => a);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Lambdas_Update_SourceType2()
    {
        var src1 = @"
using System;
 
delegate C D1(C a);
delegate B D2(B a);
 
class B { }
 
class C
{
    void G1(D1 f) {}
    void G2(D2 f) {}
 
    void F()
    {
        G1(<N:0>a => a</N:0>);
    }
}
";
        var src2 = @"
using System;
 
delegate C D1(C a);
delegate B D2(B a);
 
class B { }
 
class C
{
    void G1(D1 f) {}
    void G2(D2 f) {}
 
    void F()
    {
        G2(<N:0>a => a</N:0>);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
            [
                RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")])
            ]));
    }
 
    [Fact]
    public void Lambdas_Update_SourceTypeAndMetadataType1()
    {
        var src1 = @"
namespace System
{
    delegate string D1(string a);
    delegate String D2(String a);
 
    class String { }
 
    class C
    {
        void G1(D1 f) {}
        void G2(D2 f) {}
 
        void F()
        {
            G1(<N:0>a => a</N:0>);
        }
    }
}
";
        var src2 = @"
namespace System
{
    delegate string D1(string a);
    delegate String D2(String a);
 
    class String { }
 
    class C
    {
        void G1(D1 f) {}
        void G2(D2 f) {}
 
        void F()
        {
            G2(<N:0>a => a</N:0>);
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("System.C.F"), syntaxMap, rudeEdits:
            [
                RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")])
            ]));
    }
 
    [Fact]
    public void Lambdas_Update_Generic1()
    {
        var src1 = @"
delegate T D1<S, T>(S a, T b);
delegate T D2<S, T>(T a, S b);
 
class C
{
    void G1(D1<int, int> f) {}
    void G2(D2<int, int> f) {}
 
    void F()
    {
        G1((a, b) => a + b);
    }
}
";
        var src2 = @"
delegate T D1<S, T>(S a, T b);
delegate T D2<S, T>(T a, S b);
 
class C
{
    void G1(D1<int, int> f) {}
    void G2(D2<int, int> f) {}
 
    void F()
    {
        G2((a, b) => a + b);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Lambdas_Update_Generic2()
    {
        var src1 = @"
delegate int D1<S, T>(S a, T b);
delegate int D2<S, T>(T a, S b);
 
class C
{
    void G1(D1<int, int> f) {}
    void G2(D2<int, string> f) {}
 
    void F()
    {
        G1(<N:0>(a, b) => 1</N:0>);
    }
}
";
        var src2 = @"
delegate int D1<S, T>(S a, T b);
delegate int D2<S, T>(T a, S b);
 
class C
{
    void G1(D1<int, int> f) {}
    void G2(D2<int, string> f) {}
 
    void F()
    {
        G2(<N:0>(a, b) => 1</N:0>);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap,
                    rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), [GetResource("lambda")])]),
            ]);
    }
 
    [Fact]
    public void Lambdas_Update_CapturedParameters1()
    {
        var src1 = @"
using System;
 
class C
{
    void F(int x1)
    {
        var f1 = new Func<int, int, int>((a1, a2) => 
        {
            var f2 = new Func<int, int>(a3 => x1 + a2);
            return a1;
        });
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F(int x1)
    {
        var f1 = new Func<int, int, int>((a1, a2) => 
        {
            var f2 = new Func<int, int>(a3 => x1 + a2 + 1);
            return a1;
        });
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/2223")]
    public void Lambdas_Update_CapturedParameters2()
    {
        var src1 = @"
using System;
 
class C
{
    void F(int x1)
    {
        var f1 = new Func<int, int, int>((a1, a2) => 
        {
            var f2 = new Func<int, int>(a3 => x1 + a2);
            return a1;
        });
 
        var f3 = new Func<int, int, int>((a1, a2) => 
        {
            var f4 = new Func<int, int>(a3 => x1 + a2);
            return a1;
        });
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F(int x1)
    {
        var f1 = new Func<int, int, int>((a1, a2) => 
        {
            var f2 = new Func<int, int>(a3 => x1 + a2 + 1);
            return a1;
        });
 
        var f3 = new Func<int, int, int>((a1, a2) => 
        {
            var f4 = new Func<int, int>(a3 => x1 + a2 + 1);
            return a1;
        });
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Lambdas_Update_CeaseCapture_This()
    {
        var src1 = @"
using System;
 
class C
{
    int x = 1;
 
    void F()
    {
        var f = new Func<int, int>(<N:0>a => a + x</N:0>);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int x = 1;
   
    void F()
    {
        var f = new Func<int, int>(<N:0>a => a</N:0>);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = GetSyntaxMap(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_CeaseCapture_Closure1()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int y = 1;
        var f1 = new Func<int, int>(a1 => 
        {
            var f2 = new Func<int, int>(a2 => y + a2);
            return a1;
        });
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        int y = 1;
        var f1 = new Func<int, int>(a1 => 
        {
            var f2 = new Func<int, int>(a2 => a2);
            return a1 + y;
        });
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        // y is no longer captured in f2
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/51297")]
    public void Lambdas_Update_CeaseCapture_IndexerParameter_WithExpressionBody()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] => new Func<int, int>(a3 => a1 + a2);
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] => new Func<int, int>(a3 => a2);
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")),
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: true),
            ],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/51297")]
    public void Lambdas_Update_CeaseCapture_IndexerParameter_WithExpressionBody_LambdaBlock()
    {
        var src1 = @"
using System;
 
class C
{
    int this[int a] => new Func<int>(() => { return a + 1; })();
}
";
        var src2 = @"
using System;
 
class C
{
    int this[int a] => new Func<int>(() => { return 2; })();   // not capturing a anymore
}";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [int this[int a] => new Func<int>(() => { return a + 1; })();]@35 -> [int this[int a] => new Func<int>(() => { return 2; })();]@35",
            "Update [=> new Func<int>(() => { return a + 1; })()]@51 -> [=> new Func<int>(() => { return 2; })()]@51");
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")),
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: true),
            ],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/51297")]
    public void Lambdas_Update_CeaseCapture_IndexerParameter_WithExpressionBody_Delegate()
    {
        var src1 = @"
using System;
 
class C
{
    int this[int a] => new Func<int>(delegate { return a + 1; })();
}
";
        var src2 = @"
using System;
 
class C
{
    int this[int a] => new Func<int>(delegate { return 2; })();   // not capturing a anymore
}";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [int this[int a] => new Func<int>(delegate { return a + 1; })();]@35 -> [int this[int a] => new Func<int>(delegate { return 2; })();]@35",
            "Update [=> new Func<int>(delegate { return a + 1; })()]@51 -> [=> new Func<int>(delegate { return 2; })()]@51");
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")),
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: true),
            ],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Update_CeaseCapture_IndexerParameter_WithExpressionBody_Getter()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] { get => new(a3 => a1 + a2); }
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] { get { return new Func<int, int>(a3 => a2); } }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/51297")]
    public void Lambdas_Update_CeaseCapture_IndexerParameter_WithExpressionBody_Partial()
    {
        var srcA1 = @"
partial class C
{
}";
        var srcB1 = @"
partial class C
{
    int this[int a] => new System.Func<int>(() => a + 1);
}";
 
        var srcA2 = @"
partial class C
{
    int this[int a] => new System.Func<int>(() => 2); // no capture
}";
        var srcB2 = @"
partial class C
{
}";
 
        EditAndContinueValidation.VerifySemantics(
            [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)],
            [
                DocumentResults(
                    semanticEdits: [
                        SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")),
                        SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: true),
                    ]),
                DocumentResults(),
            ],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Update_CeaseCapture_IndexerParameter_ParameterDelete()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] { get { return new Func<int, int>(a3 => a1 + a2); } }
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> this[int a2] { get { return new Func<int, int>(a3 => a2); } }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.this[]"), deletedSymbolContainerProvider: c => c.GetMember("C")),
                SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.this[]")),
                SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")),
                SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_Item"))
            ],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Update_CeaseCapture_MethodParameter()
    {
        var src1 = @"
using System;
 
class C
{
    void F(int a1, int a2)
    {
        var f2 = new Func<int, int>(a3 => a1 + a2);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F(int a1, int a2)
    {
        var f2 = new Func<int, int>(a3 => a1);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/51297")]
    public void Lambdas_Update_CeaseCapture_MethodParameter_WithExpressionBody()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> F(int a1, int a2) => new Func<int, int>(a3 => a1 + a2);
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> F(int a1, int a2) => new Func<int, int>(a3 => a1);
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_CeaseCapture_MethodParameter_ParameterDelete()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> F(int a1, int a2) => new Func<int, int>(a3 => a1 + a2);
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> F(int a1) => new Func<int, int>(a3 => a1);
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.F"), deletedSymbolContainerProvider: c => c.GetMember("C")),
                SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.F"))
            ],
            capabilities: EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.AddMethodToExistingType);
    }
 
    [Fact]
    public void Lambdas_Update_CeaseCapture_MethodParameter_ParameterTypeChange()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> F(int a1, int a2) => new Func<int, int>(a3 => a1 + a2);
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> F(byte a1) => new Func<int, int>(a3 => a1);
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.F"), deletedSymbolContainerProvider: c => c.GetMember("C")),
                SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.F"))
            ],
            capabilities: EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.AddMethodToExistingType);
    }
 
    [Fact]
    public void Lambdas_Update_CeaseCapture_MethodParameter_LocalToParameter()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> F(int a1) { int a2 = 1; return new Func<int, int>(a3 => a1 + a2); }
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> F(int a1, int a2) { return new Func<int, int>(a3 => a1 + a2); }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.F"), deletedSymbolContainerProvider: c => c.GetMember("C")),
                SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.F"))
            ],
            capabilities: EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.AddMethodToExistingType);
    }
 
    [Fact]
    public void Lambdas_Update_CeaseCapture_MethodParameter_ParameterToLocal()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> F(int a1, int a2) { return new Func<int, int>(a3 => a1 + a2); }
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> F(int a1) { int a2 = 1; return new Func<int, int>(a3 => a1 + a2); }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.F"), deletedSymbolContainerProvider: c => c.GetMember("C")),
                SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.F"))
            ],
            capabilities: EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.AddMethodToExistingType);
    }
 
    [Fact]
    public void Lambdas_Update_CeaseCapture_LambdaParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        var f1 = new Func<int, int, int>((a1, a2) => 
        {
            var f2 = new Func<int, int>(a3 => 
            {
                var f3 = new Func<int, int>(a4 => a1 + a2 + a3);
                return 1;
            });
            return a1;
        });
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        var f1 = new Func<int, int, int>((a1, a2) => 
        {
            var f2 = new Func<int, int>(a3 => 
            {
                var f3 = new Func<int, int>(a4 => a2);
                return 1;
            });
            return a1;
        });
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems?id=234448")]
    public void Lambdas_Update_CeaseCapture_SetterValueParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    int D
    {
        get { return 0; }
        set { new Action(() => { Console.Write(value); }).Invoke(); }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int D
    {
        get { return 0; }
        set { }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_D")));
    }
 
    [Fact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems?id=234448")]
    public void Lambdas_Update_CeaseCapture_IndexerSetterValueParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    int this[int a1, int a2]
    {
        get { return 0; }
        set { new Action(() => { Console.Write(value); }).Invoke(); }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int this[int a1, int a2]
    {
        get { return 0; }
        set { }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item")));
    }
 
    [Fact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems?id=234448")]
    public void Lambdas_Update_CeaseCapture_EventAdderValueParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    event Action D
    {
        add { new Action(() => { Console.Write(value); }).Invoke(); }
        remove { }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    event Action D
    {
        add {  }
        remove { }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.add_D")));
    }
 
    [Fact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems?id=234448")]
    public void Lambdas_Update_CeaseCapture_EventRemoverValueParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    event Action D
    {
        add { }
        remove { new Action(() => { Console.Write(value); }).Invoke(); }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    event Action D
    {
        add { }
        remove { }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.remove_D")));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68731")]
    public void Lambdas_Update_CeaseCapture_ConstructorInitializer_This()
    {
        var src1 = "class C { C(int x) : this(() => x) {} C(Func<int> f) {} }";
        var src2 = "class C { C(int x) : this(() => 1) {} C(Func<int> f) {} }";
 
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember<INamedTypeSymbol>("C").InstanceConstructors.Single(m => m.Parameters is [{ Name: "x" }]), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68731")]
    public void Lambdas_Update_CeaseCapture_ConstructorInitializer_Base()
    {
        var src1 = "class C : B { C(int x) : base(() => x) {} } class B { public B(Func<int> f) {} }";
        var src2 = "class C : B { C(int x) : base(() => 1) {} } class B { public B(Func<int> f) {} }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C..ctor"), preserveLocalVariables: true));
    }
 
    [Theory, CombinatorialData]
    public void Lambdas_Update_CeaseCapture_PrimaryParameter_InPrimaryConstructor_First(
        [CombinatorialValues("class", "struct", "record", "record struct")] string keyword)
    {
        var src1 = keyword + " C(int x, int y) { System.Func<int> z = () => x; }";
        var src2 = keyword + " C(int x, int y) { System.Func<int> z = () => 1; }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember<INamedTypeSymbol>("C").InstanceConstructors.Single(m => m.Parameters is [_, _]), preserveLocalVariables: true));
    }
 
    [Theory, CombinatorialData]
    public void Lambdas_Update_CeaseCapture_PrimaryParameter_InPrimaryConstructor_Second(
        [CombinatorialValues("class", "struct", "record", "record struct")] string keyword)
    {
        var src1 = keyword + " C(int x, int y) { System.Func<int> z = () => x + y; }";
        var src2 = keyword + " C(int x, int y) { System.Func<int> z = () => x; }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember<INamedTypeSymbol>("C").InstanceConstructors.Single(m => m.Parameters is [_, _]), preserveLocalVariables: true));
    }
 
    [Theory, CombinatorialData]
    [WorkItem("https://github.com/dotnet/roslyn/issues/68731")]
    public void Lambdas_Update_CeaseCapture_PrimaryParameter_InPrimaryConstructor_BaseInitializer(
        [CombinatorialValues("class", "record")] string keyword)
    {
        var src1 = keyword + " C(int x, int y) : B(() => x);";
        var src2 = keyword + " C(int x, int y) : B(() => 1);";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember<INamedTypeSymbol>("C").InstanceConstructors.Single(m => m.Parameters is [_, _]), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_CeaseCapture_PrimaryParameter_Method_First()
    {
        var src1 = "class C(int x, int y) { System.Func<int> M() => () => x; }";
        var src2 = "class C(int x, int y) { System.Func<int> M() => () => 1; }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_CeaseCapture_PrimaryParameter_Method_Second()
    {
        var src1 = "class C(int x, int y) { System.Func<int> M() => () => x + y; }";
        var src2 = "class C(int x, int y) { System.Func<int> M() => () => x; }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_CeaseCapture_PrimaryParameter_Method_ThisToPrimaryCapture()
    {
        var src1 = "class C(int x, int y) { System.Func<int> M() => () => x; }";
        var src2 = "class C(int x, int y) { System.Func<int> M() => () => this.M()(); }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_CeaseCapture_PrimaryParameter_Method_PrimaryToThisCapture()
    {
        var src1 = "class C(int x, int y) { System.Func<int> M() => () => this.M()(); }";
        var src2 = "class C(int x, int y) { System.Func<int> M() => () => x; }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_DeleteCapture1()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int y = 1;
        var f1 = new Func<int, int>(a1 => 
        {
            var f2 = new Func<int, int>(a2 => y + a2);
            return y;
        });
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    { // error
        var f1 = new Func<int, int>(a1 => 
        {
            var f2 = new Func<int, int>(a2 => a2);
            return a1;
        });
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        // y is no longer captured in f2
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_Capturing_IndexerGetterParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] => new Func<int, int>(a3 => a2);
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] => new Func<int, int>(a3 => a1 + a2);
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")),
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: true)
            ]);
    }
 
    [Fact]
    public void Lambdas_Update_Capturing_IndexerGetterParameter2()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] { get { return new Func<int, int>(a3 => a2); } }
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] { get { return new Func<int, int>(a3 => a1 + a2); } }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_Capturing_IndexerGetterParameter_ParameterInsert()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> this[int a1] => new(a3 => a1);
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] => new(a3 => a1 + a2);
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.this[]"), deletedSymbolContainerProvider: c => c.GetMember("C")),
                SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")),
                SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.this[]")),
                SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_Item")),
            ],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Update_Capturing_IndexerSetterParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] { get { return null; } set { var f = new Func<int, int>(a3 => a2); } }
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] { get { return null; } set { var f = new Func<int, int>(a3 => a1 + a2); } }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_Capturing_IndexerSetterValueParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    int this[int a1, int a2]
    {
        get { return 0; }
        set {  }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int this[int a1, int a2]
    {
        get { return 0; }
        set { new Action(() => { Console.Write(value); }).Invoke(); }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Update_Capturing_EventAdderValueParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    event Action D
    {
        add {  }
        remove { }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    event Action D
    {
        add {  }
        remove { new Action(() => { Console.Write(value); }).Invoke(); }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.remove_D"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Update_Capturing_EventRemoverValueParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    event Action D
    {
        add { }
        remove {  }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    event Action D
    {
        add { }
        remove { new Action(() => { Console.Write(value); }).Invoke(); }
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.remove_D"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Update_Capturing_MethodParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    void F(int a1, int a2)
    {
        var f2 = new Func<int, int>(a3 => a1);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F(int a1, int a2)
    {
        var f2 = new Func<int, int>(a3 => a1 + a2);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_Capturing_MethodParameter2()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> F(int a1, int a2) => new Func<int, int>(a3 => a1);
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> F(int a1, int a2) => new Func<int, int>(a3 => a1 + a2);
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_Capturing_MethodParameter_ParameterInsert()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> F(int a1) => new Func<int, int>(a3 => a1);
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> F(int a1, int a2) => new Func<int, int>(a3 => a1 + a2);
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.F"), deletedSymbolContainerProvider: c => c.GetMember("C")),
                SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.F"))
            ],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Update_Capturing_MethodParameter_ParameterInsert_Partial()
    {
        var src1 = @"
using System;
 
partial class C
{
    public partial Func<int, int> F(int a1);
}
 
partial class C
{
    public partial Func<int, int> F(int a1) => new Func<int, int>(a3 => a1);
}
";
        var src2 = @"
using System;
 
partial class C
{
    public partial Func<int, int> F(int a1, int a2);
}
 
partial class C
{
    public partial Func<int, int> F(int a1, int a2) => new Func<int, int>(a3 => a1 + a2);
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Delete, c => c.GetMember<IMethodSymbol>("C.F").PartialImplementationPart, deletedSymbolContainerProvider: c => c.GetMember("C"), partialType: "C"),
                SemanticEdit(SemanticEditKind.Insert, c => c.GetMember<IMethodSymbol>("C.F").PartialImplementationPart, partialType: "C")
            ],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Update_Capturing_LambdaParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        var f1 = new Func<int, int, int>((a1, a2) => 
        {
            var f2 = new Func<int, int>(a3 => a2);
            return a1;
        });
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        var f1 = new Func<int, int, int>((a1, a2) => 
        {
            var f2 = new Func<int, int>(a3 => a1 + a2);
            return a1;
        });
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68731")]
    public void Lambdas_Update_Capturing_ConstructorInitializer_This()
    {
        var src1 = "class C { C(int x) : this(() => 1) {} C(Func<int> f) {} }";
        var src2 = "class C { C(int x) : this(() => x) {} C(Func<int> f) {} }";
 
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember<INamedTypeSymbol>("C").InstanceConstructors.Single(m => m.Parameters is [{ Name: "x" }]), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68731")]
    public void Lambdas_Update_Capturing_ConstructorInitializer_Base()
    {
        var src1 = "class C : B { C(int x) : base(() => 1) {} } class B { public B(Func<int> f) {} }";
        var src2 = "class C : B { C(int x) : base(() => x) {} } class B { public B(Func<int> f) {} }";
 
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C..ctor"), preserveLocalVariables: true));
    }
 
    [Theory, CombinatorialData]
    public void Lambdas_Update_Capturing_PrimaryParameter_InPrimaryConstructor_First(
        [CombinatorialValues("class", "struct", "record", "record struct")] string keyword)
    {
        var src1 = keyword + " C(int x, int y) { System.Func<int> z = () => 1; }";
        var src2 = keyword + " C(int x, int y) { System.Func<int> z = () => x; }";
 
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember<INamedTypeSymbol>("C").InstanceConstructors.Single(m => m.Parameters is [_, _]), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Theory, CombinatorialData]
    public void Lambdas_Update_Capturing_PrimaryParameter_InPrimaryConstructor_Second(
        [CombinatorialValues("class", "struct", "record", "record struct")] string keyword)
    {
        var src1 = keyword + " C(int x, int y) { System.Func<int> z = () => x; }";
        var src2 = keyword + " C(int x, int y) { System.Func<int> z = () => x + y; }";
 
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember<INamedTypeSymbol>("C").InstanceConstructors.Single(m => m.Parameters is [_, _]), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Theory]
    [WorkItem("https://github.com/dotnet/roslyn/issues/68731")]
    [CombinatorialData]
    public void Lambdas_Update_Capturing_PrimaryParameter_InPrimaryConstructor_BaseInitializer(
        [CombinatorialValues("class", "record")] string keyword)
    {
        var src1 = keyword + " C(int x, int y) : B(() => 1);";
        var src2 = keyword + " C(int x, int y) : B(() => x);";
 
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember<INamedTypeSymbol>("C").InstanceConstructors.Single(m => m.Parameters is [_, _]), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_Update_Capturing_PrimaryParameter_Method_First()
    {
        var src1 = "class C(int x, int y) { System.Func<int> M() => () => 1; }";
        var src2 = "class C(int x, int y) { System.Func<int> M() => () => x; }";
 
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_Capturing_PrimaryParameter_Method_Second()
    {
        var src1 = "class C(int x, int y) { System.Func<int> M() => () => x; }";
        var src2 = "class C(int x, int y) { System.Func<int> M() => () => x + y; }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_Capturing_PrimaryParameter_Method_ThisToPrimaryCapture()
    {
        var src1 = "class C(int x, int y) { System.Func<int> M() => () => this.M()(); }";
        var src2 = "class C(int x, int y) { System.Func<int> M() => () => x; }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_Capturing_PrimaryParameter_Method_PrimaryToThisCapture()
    {
        var src1 = "class C(int x, int y) { System.Func<int> M() => () => x; }";
        var src2 = "class C(int x, int y) { System.Func<int> M() => () => this.M()(); }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69152")]
    public void Lambdas_Update_PrimaryParameterOutsideOfLambda()
    {
        var src1 = @"
using System;
 
class C(int x)
{
    void F()
    {
        var f = new Func<int, int>(a => 1);
    }
}
";
        var src2 = @"
using System;
 
class C(int x)
{
    void F()
    {
        var f = new Func<int, int>(a => 2);
        var y = x;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Lambdas_Update_StaticToThisOnly1()
    {
        var src1 = @"
using System;
 
class C
{
    int x = 1;
 
    void F()
    {
        var f = new Func<int, int>(a => a);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int x = 1;
   
    void F()
    {
        var f = new Func<int, int>(a => a + x);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_StaticToThisOnly_Partial()
    {
        var src1 = @"
using System;
 
partial class C
{
    int x = 1;
    partial void F(); // def
}
 
partial class C
{
    partial void F()  // impl
    {
        var f = new Func<int, int>(a => a);
    }
}
";
        var src2 = @"
using System;
 
partial class C
{
    int x = 1;
    partial void F(); // def
}
 
partial class C
{
    partial void F()  // impl
    {
        var f = new Func<int, int>(a => a + x);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember<IMethodSymbol>("C.F").PartialImplementationPart, preserveLocalVariables: true, partialType: "C"));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69152")]
    public void Lambdas_Update_StaticToPrimaryParameterOnly_Partial()
    {
        var src1 = @"
using System;
 
partial class C(int x)
{
    partial void F(); // def
}
 
partial class C
{
    partial void F()  // impl
    {
        var f = new Func<int, int>(a => a);
    }
}
";
        var src2 = @"
using System;
 
partial class C(int x)
{
    partial void F(); // def
}
 
partial class C
{
    partial void F()  // impl
    {
        var f = new Func<int, int>(a => a + x);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember<IMethodSymbol>("C.F").PartialImplementationPart, preserveLocalVariables: true, partialType: "C"));
    }
 
    [Fact]
    public void Lambdas_Update_StaticToThisOnly3()
    {
        var src1 = @"
using System;
 
class C
{
    int x = 1;
 
    void F()
    {
        var f1 = new Func<int, int>(a1 => a1);
        var f2 = new Func<int, int>(a2 => a2 + x);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int x = 1;
   
    void F()
    {
        var f1 = new Func<int, int>(a1 => a1 + x);
        var f2 = new Func<int, int>(a2 => a2 + x);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69152")]
    public void Lambdas_Update_StaticToPrimaryParameterOnly3()
    {
        var src1 = @"
using System;
 
class C(int x)
{
    void F()
    {
        var f1 = new Func<int, int>(a1 => a1);
        var f2 = new Func<int, int>(a2 => a2 + x);
    }
}
";
        var src2 = @"
using System;
 
class C(int x)
{
    void F()
    {
        var f1 = new Func<int, int>(a1 => a1 + x);
        var f2 = new Func<int, int>(a2 => a2 + x);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_StaticToPrimaryParameterOnly()
    {
        var src1 = @"
using System;
 
class C(int x)
{
    void F()
    {
        var f = new Func<int, int>(a => a);
    }
}
";
        var src2 = @"
using System;
 
class C(int x)
{
    void F()
    {
        var f = new Func<int, int>(a => a + x);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_StaticToClosure1()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int x = 1;
        var f1 = new Func<int, int>(a1 => a1);
        var f2 = new Func<int, int>(a2 => a2 + x);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        int x = 1;
        var f1 = new Func<int, int>(a1 => 
        { 
            return a1 + 
                x+ // 1 
                x; // 2
        });
 
        var f2 = new Func<int, int>(a2 => a2 + x);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_ThisOnlyToClosure1()
    {
        var src1 = @"
using System;
 
class C
{
    int x = 1;
 
    void F()
    {
        int y = 1;
        var f1 = new Func<int, int>(a1 => a1 + x);
        var f2 = new Func<int, int>(a2 => a2 + x + y);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int x = 1;
 
    void F()
    {
        int y = 1;
        var f1 = new Func<int, int>(a1 => a1 + x + y);
        var f2 = new Func<int, int>(a2 => a2 + x + y);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_Nested1()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int y = 1;
        var f1 = new Func<int, int>(a1 => 
        {
            var f2 = new Func<int, int>(a2 => a2 + y);
            return a1;
        });
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        int y = 1;
        var f1 = new Func<int, int>(a1 => 
        {
            var f2 = new Func<int, int>(a2 => a2 + y);
            return a1 + y;
        });
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Lambdas_Update_Nested2()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int y = 1;
        var f1 = new Func<int, int>(a1 => 
        {
            var f2 = new Func<int, int>(a2 => a2);
            return a1;
        });
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        int y = 1;
        var f1 = new Func<int, int>(a1 => 
        {
            var f2 = new Func<int, int>(a2 => a1 + a2);
            return a1;
        });
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_Accessing_Closure1()
    {
        var src1 = @"
using System;
 
class C
{
    void G(Func<int, int> f) {}
 
    void F()
    {
        int x0 = 0, y0 = 0;                
                                         
        G(a => x0);
        G(a => y0);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G(Func<int, int> f) {}
 
    void F()
    {
        int x0 = 0, y0 = 0;                
                                         
        G(a => x0);
        G(a => y0 + x0);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_Accessing_Closure2()
    {
        var src1 = @"
using System;
 
class C
{
    void G(Func<int, int> f) {}
 
    int x = 0;                     // Group #0
                                   
    void F()                       
    {                              
        { int x0 = 0, y0 = 0;      // Group #0             
            { int x1 = 0, y1 = 0;  // Group #1               
                                         
                G(a => x + x0);   
                G(a => x0);
                G(a => y0);
                G(a => x1);
            }
        }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G(Func<int, int> f) {}
    int x = 0;                     // Group #0
 
    void F()
    {
        { int x0 = 0, y0 = 0;      // Group #0          
            { int x1 = 0, y1 = 0;  // Group #1              
                                         
                G(a => x);         // error: disconnecting previously connected closures
                G(a => x0);
                G(a => y0);
                G(a => x1);
            }
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_Accessing_Closure3()
    {
        var src1 = @"
using System;
 
class C
{
    void G(Func<int, int> f) {}
 
    int x = 0;                     // Group #0
                                   
    void F()                       
    {                              
        { int x0 = 0, y0 = 0;      // Group #0             
            { int x1 = 0, y1 = 0;  // Group #1               
                                         
                G(a => x);   
                G(a => x0);
                G(a => y0);
                G(a => x1);
                G(a => y1);
            }
        }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G(Func<int, int> f) {}
    int x = 0;                     // Group #0
 
    void F()
    {
        { int x0 = 0, y0 = 0;      // Group #0          
            { int x1 = 0, y1 = 0;  // Group #1              
                                         
                G(a => x);         
                G(a => x0);
                G(a => y0);
                G(a => x1);
                G(a => y1 + x0);   // error: connecting previously disconnected closures
            }
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_Accessing_Closure4()
    {
        var src1 = @"
using System;
 
class C
{
    void G(Func<int, int> f) {}
 
    int x = 0;                     // Group #0
                                   
    void F()                       
    {                              
        { int x0 = 0, y0 = 0;      // Group #0             
            { int x1 = 0, y1 = 0;  // Group #1               
                                         
                G(a => x + x0);   
                G(a => x0);
                G(a => y0);
                G(a => x1);
                G(a => y1);
            }
        }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G(Func<int, int> f) {}
    int x = 0;                     // Group #0
 
    void F()
    {
        { int x0 = 0, y0 = 0;      // Group #0          
            { int x1 = 0, y1 = 0;  // Group #1              
                                         
                G(a => x);         // error: disconnecting previously connected closures
                G(a => x0);
                G(a => y0);
                G(a => x1);
                G(a => y1 + x0);   // error: connecting previously disconnected closures
            }
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Update_Accessing_Closure_NestedLambdas()
    {
        var src1 = @"
using System;
 
class C
{
    void G(Func<int, Func<int, int>> f) {}
 
    void F()                       
    {                              
        { int x0 = 0;      // Group #0             
            { int x1 = 0;  // Group #1               
                                         
                G(a => b => x0);
                G(a => b => x1);
            }
        }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G(Func<int, Func<int, int>> f) {}
 
    void F()
    {
        { int x0 = 0;      // Group #0          
            { int x1 = 0;  // Group #1              
                                         
                G(a => b => x0);
                G(a => b => x1);
 
                G(a => b => x0);      // ok
                G(a => b => x1);      // ok
                G(a => b => x0 + x1); // runtime rude edit
            }
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void Lambdas_CapturedLocal_Rename()
    {
        var src1 = @"
using System;
 
class C
{
    static void F()
    <N:0>{
        int x = 1;
        Func<int> f = () => x;
    }</N:0>
}";
        var src2 = @"
using System;
 
class C
{
    static void F()
    <N:0>{
        int <S:0>X</S:0> = 1;
        Func<int> f = () => X;
    }</N:0>
}";
 
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
            [
                RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), ["x", "X"])
            ]));
    }
 
    [Fact]
    public void Lambdas_CapturedLocal_ChangeType()
    {
        var src1 = @"
using System;
 
class C
{
    static void F()
    <N:0>{
        int <S:0>x</S:0> = 1;
        Func<int> f = <N:1>() => x</N:1>;
    }</N:0>
}";
        var src2 = @"
using System;
 
class C
{
    static void F()
    <N:0>{
        byte <S:0>x</S:0> = 1;
        Func<int> f = <N:1>() => x</N:1>;
    }</N:0>
}";
 
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            SemanticEdit(
                SemanticEditKind.Update,
                c => c.GetMember("C.F"),
                syntaxMap,
                rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.ChangingCapturedVariableType, syntaxMap.Position(0), ["x", "int"])]));
    }
 
    [Fact]
    public void Lambdas_CapturedParameter_Rename_BlockBody()
    {
        var src1 = @"
using System;
 
class C
{
    static void F(int x)
    <N:0>{
        Func<int> f = <N:1>() => x</N:1>;
    }</N:0>
}";
        var src2 = @"
using System;
 
class C
{
    static void F(int <S:0>X</S:0>)
    <N:0>{
        Func<int> f = <N:1>() => X</N:1>;
    }</N:0>
}";
 
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap,
                    rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), ["x", "X"])]),
            ],
            capabilities: EditAndContinueCapabilities.UpdateParameters);
    }
 
    [Fact]
    public void Lambdas_CapturedParameter_Rename_ExpressionBody()
    {
        var src1 = @"
using System;
 
class C
{
    static void G(Func<int> f) {}
    static void F(int x) <N:0>=> G(<N:1>() => x</N:1>)</N:0>;
}";
        var src2 = @"
using System;
 
class C
{
    static void G(Func<int> f) {}
    static void F(int <S:0>X</S:0>) <N:0>=> G(<N:1>() => X</N:1>)</N:0>;
}";
 
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap,
                    rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), ["x", "X"])]),
            ],
            capabilities: EditAndContinueCapabilities.UpdateParameters);
    }
 
    [Fact]
    public void Lambdas_CapturedParameter_Rename_Lambda_BlockBody()
    {
        var src1 = @"
using System;
 
class C
{
    static void F()    
    <N:0>{
        Func<int> f1 = <N:1>x =>
        <N:2>{
            Func<int> f2 = <N:3>() => x</N:3>;
        }</N:1,2>;
    }</N:0>
}";
        var src2 = @"
using System;
 
class C
{
    static void F()    
    <N:0>{
        Func<int> f1 = <N:1>X =>
        <N:2>{
            Func<int> f2 = <N:3>() => X</N:3>;
        }</N:1,2>;
    }</N:0>
}";
 
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap,
                    rudeEdits: [RuntimeRudeEdit(marker: 2, RudeEditKind.RenamingCapturedVariable, syntaxMap.NodePosition(1), ["x", "X"])]),
            ],
            capabilities: EditAndContinueCapabilities.UpdateParameters);
    }
 
    [Fact]
    public void Lambdas_CapturedParameter_Rename_Lambda_ExpressionBody()
    {
        var src1 = @"
using System;
 
class C
{
    static int G(Func<int> f) => 1;
 
    static void F()    
    {
        Func<int, int> <N:0>f1 = <N:1>x => <N:2>G(<N:3>() => x</N:3>)</N:0,1,2>;
    }
}";
        var src2 = @"
using System;
 
class C
{
    static int G(Func<int> f) => 1;
 
    static void F()    
    {
        Func<int, int> <N:0>f1 = <N:1>X => <N:2>G(<N:3>() => X</N:3>)</N:0,1,2>;
    }
}";
 
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap,
                    rudeEdits: [RuntimeRudeEdit(marker: 2, RudeEditKind.RenamingCapturedVariable, syntaxMap.NodePosition(1), ["x", "X"])]),
            ],
            capabilities: EditAndContinueCapabilities.UpdateParameters);
    }
 
    [Fact]
    public void Lambdas_CapturedParameter_Rename_ConstructorDeclaration()
    {
        var src1 = @"
using System;
 
class B(Func<int> f);
 
class C
{
    <N:0>C(int x, int y) : base(() => x)
    {
        Func<int> g = () => y;
    }</N:0>
}";
        var src2 = @"
using System;
 
class B(Func<int> f);
 
class C
{
    <N:0>C(int <S:0>X</S:0>, int Y) : base(() => X)
    {
        Func<int> g = () => Y;
    }</N:0>
}";
 
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C..ctor"), syntaxMap,
                    // only the first rude edit is reported for each node:
                    rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), ["x", "X"])]),
            ],
            capabilities: EditAndContinueCapabilities.UpdateParameters);
    }
 
    [Fact]
    public void Lambdas_CapturedParameter_Rename_PrimaryConstructorDeclaration()
    {
        var src1 = @"
using System;
 
class B(Func<int> f);
 
<N:0>class C(int x) : B(() => x);</N:0>
";
        var src2 = @"
using System;
 
class B(Func<int> f);
 
<N:0>class C(int <S:0>X</S:0>) : B(() => X);</N:0>
";
 
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C..ctor"), syntaxMap,
                    rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), ["x", "X"])]),
            ],
            capabilities: EditAndContinueCapabilities.UpdateParameters);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68708")]
    public void Lambdas_CapturedParameter_ChangeType()
    {
        var src1 = @"
using System;
 
class C
{
    static void F(int x)
    {
        Func<int> f = () => x;
    }
}";
        var src2 = @"
using System;
 
class C
{
    static void F(byte x)
    {
        Func<int> f = () => x;
    }
}";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.F"), deletedSymbolContainerProvider: c => c.GetMember("C")),
                SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.F"))
            ],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType);
    }
 
    [Fact]
    public void Lambdas_CapturedParameter_ChangeType_Indexer1()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int> this[int a] { get => () => a; }
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int> this[byte a] => () => a;
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.this[]"), deletedSymbolContainerProvider: c => c.GetMember("C")),
                SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.this[]")),
                SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")),
                SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_Item"))
            ],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType);
    }
 
    [Fact]
    public void Lambdas_CapturedParameter_ChangeType_Indexer_NoBodyChange()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int> this[int a ] => () => a;
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int> this[byte a] => () => a;
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")),
                SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_Item")),
                SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.this[]"), deletedSymbolContainerProvider: c => c.GetMember("C")),
                SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.this[]")),
            ],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType);
    }
 
    [Fact]
    public void Lambdas_ReorderCapturedParameters()
    {
        var src1 = @"
using System;
using System.Diagnostics;
 
class Program
{
    static void Main(int x, int y)
    {
        Func<int> f = () => x + y;
    }
}";
        var src2 = @"
using System;
using System.Diagnostics;
 
class Program
{
    static void Main(int y, int x)
    {
        Func<int> f = () => x + y;
    }
}";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            ActiveStatementsDescription.Empty,
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.Main"), preserveLocalVariables: true)
            ],
            capabilities: EditAndContinueTestVerifier.Net6RuntimeCapabilities);
    }
 
    [Fact]
    public void Lambdas_Parameter_To_Discard1()
    {
        var src1 = "var x = new System.Func<int, int, int>((a, b) => 1);";
        var src2 = "var x = new System.Func<int, int, int>((a, _) => 1);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [b]@45 -> [_]@45");
 
        GetTopEdits(edits).VerifySemantics(SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Parameter_To_Discard2()
    {
        var src1 = "var x = new System.Func<int, int, int>((int a, int b) => 1);";
        var src2 = "var x = new System.Func<int, int, int>((_, _) => 1);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [int a]@42 -> [_]@42",
            "Update [int b]@49 -> [_]@45");
 
        GetTopEdits(edits).VerifySemantics(SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_Parameter_To_Discard3()
    {
        var src1 = "var x = new System.Func<int, int, int>((a, b) => 1);";
        var src2 = "var x = new System.Func<int, int, int>((_, _) => 1);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [a]@42 -> [_]@42",
            "Update [b]@45 -> [_]@45");
 
        GetTopEdits(edits).VerifySemantics(SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Lambdas_StackAlloc_Update()
    {
        var src1 = @"
using System;
class C
{
    Delegate F() => () => { Span<int> s = stackalloc int[10]; };
}";
        var src2 = @"
using System;
class C
{
    Delegate F() => () => { Span<int> s = stackalloc int[20]; };
}";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            Diagnostic(RudeEditKind.StackAllocUpdate, "stackalloc int[20]", GetResource("lambda")));
    }
 
    [Fact]
    public void Lambdas_StackAlloc_Insert()
    {
        var src1 = @"
using System;
class C
{
    Delegate F() => () => { };
}";
        var src2 = @"
using System;
class C
{
    Delegate F() => () => { Span<int> s = stackalloc int[10]; };
}";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            Diagnostic(RudeEditKind.StackAllocUpdate, "stackalloc int[10]", GetResource("lambda")));
    }
 
    [Fact]
    public void Lambdas_StackAlloc_Delete()
    {
        var src1 = @"
using System;
class C
{
    Delegate F() => () => { Span<int> s = stackalloc int[10]; };
}";
        var src2 = @"
using System;
class C
{
    Delegate F() => () => { };
}";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            Diagnostic(RudeEditKind.StackAllocUpdate, "()", GetResource("lambda")));
    }
 
    [Fact]
    public void Lambdas_StackAlloc_UpdateAround()
    {
        var src1 = "unsafe class C { void M() { F(1, () => { int* a = stackalloc int[10]; }); } }";
        var src2 = "unsafe class C { void M() { F(2, () => { int* a = stackalloc int[10]; }); } }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Lambdas_AsyncModifier_Add()
    {
        var src1 = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    public void F()
    {
        var f = new Func<Task<int>>(() => Task.FromResult(1));
    }
}";
        var src2 = @"
using System;
using System.Threading.Tasks;
 
class Test
{
    public void F()
    {
        var f = new Func<Task<int>>(async () => 1);
    }
}";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.MakeMethodAsyncNotSupportedByRuntime, "()")],
            capabilities: EditAndContinueCapabilities.Baseline);
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.AddExplicitInterfaceImplementation);
    }
 
    #endregion
 
    #region Local Functions
 
    [Fact]
    public void LocalFunctions_InExpressionStatement()
    {
        var src1 = "F(a => a, b => b);";
        var src2 = "int x(int a) => a + 1; F(b => b, x);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [a => a]@4 -> [int x(int a) => a + 1;]@2",
            "Move [a => a]@4 -> @2",
            "Update [F(a => a, b => b);]@2 -> [F(b => b, x);]@25",
            "Insert [(int a)]@7",
            "Insert [int a]@8",
            "Delete [a]@4");
    }
 
    [Fact]
    public void LocalFunctions_ReorderAndUpdate()
    {
        var src1 = "int x(int a) => a; int y(int b) => b;";
        var src2 = "int y(int b) => b; int x(int a) => a + 1;";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [int y(int b) => b;]@21 -> @2",
            "Update [int x(int a) => a;]@2 -> [int x(int a) => a + 1;]@21");
    }
 
    [Fact]
    public void LocalFunctions_InWhile()
    {
        var src1 = "do { /*1*/ } while (F(x));int x(int a) => a + 1;";
        var src2 = "while (F(a => a)) { /*1*/ }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Insert [while (F(a => a)) { /*1*/ }]@2",
            "Update [int x(int a) => a + 1;]@28 -> [a => a]@11",
            "Move [int x(int a) => a + 1;]@28 -> @11",
            "Move [{ /*1*/ }]@5 -> @20",
            "Insert [a]@11",
            "Delete [do { /*1*/ } while (F(x));]@2",
            "Delete [(int a)]@33",
            "Delete [int a]@34");
    }
 
    [Fact]
    public void LocalFunctions_InLocalFunction_NoChangeInSignature()
    {
        var src1 = "int x() { int y(int a) => a; return y(b); }";
        var src2 = "int x() { int y() => c; return y(); }";
 
        var edits = GetMethodEdits(src1, src2);
        // no changes to the method were made, only within the outer local function body:
        edits.VerifyEdits();
    }
 
    [Fact]
    public void LocalFunctions_InLocalFunction_ChangeInSignature()
    {
        var src1 = "int x() { int y(int a) => a; return y(b); }";
        var src2 = "int x(int z) { int y() => c; return y(); }";
 
        var edits = GetMethodEdits(src1, src2);
        // changes were made to the outer local function signature:
        edits.VerifyEdits("Insert [int z]@8");
    }
 
    [Fact]
    public void LocalFunctions_InLambda()
    {
        var src1 = "F(() => { int y(int a) => a; G(y); });";
        var src2 = "F(q => { G(() => y); });";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [() => { int y(int a) => a; G(y); }]@4 -> [q => { G(() => y); }]@4",
            "Insert [q]@4",
            "Delete [()]@4");
    }
 
    [Fact]
    public void LocalFunctions_Update_ParameterRefness_NoBodyChange()
    {
        var src1 = @"void f(ref int a) => a = 1;";
        var src2 = @"void f(out int a) => a = 1;";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [ref int a]@9 -> [out int a]@9");
    }
 
    [Fact]
    public void LocalFunctions_Insert_Static()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        int f(int a) => a;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType);
    }
 
    [Fact]
    public void LocalFunctions_Insert_Static_InGenericContext_Method()
    {
        var src1 = @"
using System;
 
class C
{
    void F<T>()
    {
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F<T>()
    {
        int f(int a) => a;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities:
                EditAndContinueCapabilities.AddMethodToExistingType |
                EditAndContinueCapabilities.GenericAddMethodToExistingType |
                EditAndContinueCapabilities.GenericUpdateMethod);
 
        edits.VerifySemanticDiagnostics(
            [
                Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "f", GetResource("local function")),
                Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "void F<T>()", GetResource("method"))
            ],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void LocalFunctions_Insert_Static_InGenericContext_Type()
    {
        var src1 = @"
using System;
 
class C<T>
{
    void F()
    {
    }
}
";
        var src2 = @"
using System;
 
class C<T>
{
    void F()
    {
        int f(int a) => a;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities:
                EditAndContinueCapabilities.AddMethodToExistingType |
                EditAndContinueCapabilities.GenericAddMethodToExistingType |
                EditAndContinueCapabilities.GenericUpdateMethod);
 
        edits.VerifySemanticDiagnostics(
            [
                Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "f", GetResource("local function")),
                Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "void F()", GetResource("method"))
            ],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void LocalFunctions_Insert_Static_InGenericContext_LocalFunction()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        void L<T>()
        {
            void M()
            {
            }
        }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        void L<T>()
        {
            void M()
            {
                int f(int a) => a;
            }
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities:
                EditAndContinueCapabilities.AddMethodToExistingType |
                EditAndContinueCapabilities.GenericAddMethodToExistingType |
                EditAndContinueCapabilities.GenericUpdateMethod);
 
        edits.VerifySemanticDiagnostics(
            [
                Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "L", GetResource("local function")),
                Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "f", GetResource("local function"))
            ],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void LocalFunctions_Insert_Static_Nested_ExpressionBodies()
    {
        var src1 = @"
using System;
 
class C
{
    static int G(Func<int, int> f) => 0;
    
    void F()
    {
        int localF(int a) => a;
        G(localF);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    static int G(Func<int, int> f) => 0;
 
    void F()
    {
        int localF(int a) => a;
        int localG(int a) => G(localF) + a;
        G(localG);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType);
    }
 
    [Fact]
    public void LocalFunctions_Insert_Static_Nested_BlockBodies()
    {
        var src1 = @"
using System;
 
class C
{
    static int G(Func<int, int> f) => 0;
    
    void F()
    {
        int localF(int a) { return a; }
        G(localF);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    static int G(Func<int, int> f) => 0;
 
    void F()
    {
        int localF(int a) { return a; }
        int localG(int a) { return G(localF) + a; }
        G(localG);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType);
    }
 
    [Fact]
    public void LocalFunctions_LocalFunction_Replace_Lambda()
    {
        var src1 = @"
using System;
 
class C
{
    static int G(Func<int, int> f) => 0;
    
    void F()
    {
        G(<N:0>a => a</N:0>);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    static int G(Func<int, int> f) => 0;
 
    void F()
    {
        <N:0>int <S:0>localF</S:0>(int a) { return a; }</N:0>
        G(localF);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.SwitchBetweenLambdaAndLocalFunction, syntaxMap.Position(0), [GetResource("local function")])
                ])
            ]);
    }
 
    [Fact]
    public void LocalFunctions_Lambda_Replace_LocalFunction()
    {
        var src1 = @"
using System;
 
class C
{
    static int G(Func<int, int> f) => 0;
 
    void F()
    {
        <N:0>int localF(int a) { return a; }</N:0>
        G(localF);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    static int G(Func<int, int> f) => 0;
    
    void F()
    {
        G(<N:0>a => a</N:0>);
    }
}
";
 
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
            [
                RuntimeRudeEdit(0, RudeEditKind.SwitchBetweenLambdaAndLocalFunction, syntaxMap.NodePosition(0), arguments: [])
            ]));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Insert_ThisOnly_Top1()
    {
        var src1 = @"
using System;
 
class C
{
    int x = 0;
 
    void F()
    {
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int x = 0;
 
    void F()
    {
        int G(int a) => x; 
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/1291"), WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Insert_ThisOnly_Top2()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        int y = 1;
        {
            int x = 2;
            int f1(int a) => y; 
        }
    }
}
";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        int y = 1;
        {
            int x = 2;
            var f2 = from a in new[] { 1 } select a + y;
            var f3 = from a in new[] { 1 } where x > 0 select a;
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Insert_ThisOnly_Nested1()
    {
        var src1 = @"
using System;
 
class C
{
    int x = 0;
    int G(Func<int, int> f) => 0;
 
    void F()
    {
        int f(int a) => a;
        G(f);
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int x = 0;
    int G(Func<int, int> f) => 0;
 
    void F()
    {
        int f(int a) => x;
        int g(int a) => G(f);
        G(g);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Insert_ThisOnly_Nested2()
    {
        var src1 = @"
using System;
 
class C
{
    int x = 0;
 
    void F()
    {
        int f1(int a) 
        {
            int f2(int b)
            {
                return b;
            };
 
            return a;
        };
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int x = 0;
 
    void F()
    {
        int f1(int a)
        {
            int f2(int b)
            {
                return b;
            };
 
            int f3(int c)
            {
                return c + x;
            };
 
            return a;
        };
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_InsertAndDelete_Scopes1()
    {
        var src1 = @"
using System;
 
class C
{
    void G(Func<int, int> f) {}
 
    int x = 0, y = 0;                      // Group #0
 
    void F()
    {
        int x0 = 0, y0 = 0;                // Group #1 
 
        { int x1 = 0, y1 = 0;              // Group #2 
 
            { int x2 = 0, y2 = 0;          // Group #1 
 
                { int x3 = 0, y3 = 0;      // Group #2 
 
                    int f1(int a) => x3 + x1;
                    int f2(int a) => x0 + y0 + x2;
                    int f3(int a) => x;
                }
            }
        }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G(Func<int, int> f) {}
 
    int x = 0, y = 0;                       // Group #0
 
    void F()
    {
        int x0 = 0, y0 = 0;                 // Group #1
 
        { int x1 = 0, y1 = 0;               // Group #2 
 
            { int x2 = 0, y2 = 0;           // Group #1
 
                { int x3 = 0, y3 = 0;       // Group #2 
 
                    int f1(int a) => x3 + x1;
                    int f2(int a) => x0 + y0 + x2;
                    int f3(int a) => x;
 
                    int f4(int a) => x;         // OK
                    int f5(int a) => x0 + y0;   // OK
                    int f6(int a) => x1 + y0;   // runtime rude edit - connecting Group #1 and Group #2
                    int f7(int a) => x3 + x1;   // runtime rude edit - multi-scope (conservative)
                    int f8(int a) => x + y0;    // runtime rude edit - connecting Group #0 and Group #1
                    int f9(int a) => x + x3;    // runtime rude edit - connecting Group #0 and Group #2
                }
            }
        }
    }
}
";
        var insert = GetTopEdits(src1, src2);
        insert.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
 
        var delete = GetTopEdits(src2, src1);
        delete.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Insert_ForEach1()
    {
        var src1 = @"
using System;
 
class C
{
    void G(Func<int, int> f) {}
 
    void F()                       
    {                              
        foreach (int x0 in new[] { 1 })  // Group #0             
        {                                // Group #1
            int x1 = 0;
 
            int f0(int a) => x0;
            int f1(int a) => x1;
        }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G(Func<int, int> f) {}
 
    void F()                       
    {                              
        foreach (int x0 in new[] { 1 })  // Group #0             
        {                                // Group #1
            int x1 = 0;                  
 
            int f0(int a) => x0;
            int f1(int a) => x1;
 
            int f2(int a) => x0 + x1;   // runtime rude edit: connecting previously disconnected closures
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Insert_Switch1()
    {
        var src1 = @"
using System;
 
class C
{
    bool G(Func<int> f) => true;
 
    int a = 1;
 
    void F()                       
    {        
        int x2 = 1;
        int f2() => x2;
 
        switch (a)
        {
            case 1:
                int x0 = 1;
                int f0() => x0;
                break;
 
            case 2:
                int x1 = 1;
                int f1() => x1;
                break;
        }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    bool G(Func<int> f) => true;
 
    int a = 1;
 
    void F()                       
    {                
        int x2 = 1;
        int f2() => x2;
 
        switch (a)
        {
            case 1:
                int x0 = 1;
                int f0() => x0;
                goto case 2;
 
            case 2:
                int x1 = 1;
                int f1() => x1;
                goto default;
 
            default:
                x0 = 1;
                x1 = 2;
                int f01() => x0 + x1;   // ok
                int f02() => x0 + x2;   // runtime rude edit
                break;
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Insert_Catch1()
    {
        var src1 = @"
using System;
 
class C
{
    static void F()                       
    {                              
        try
        {
        }
        catch (Exception x0)
        {
            int x1 = 1;
            int f0() => x0;
            int f1() => x1;
        }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    static void F()                       
    {                              
        try
        {
        }
        catch (Exception x0)
        {
            int x1 = 1;
            int f0() => x0;
            int f1() => x1;
 
            int f00() => x0; //ok
            int f01() => F(x0, x1); // runtime rude edit
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void LocalFunctions_Insert_NotSupported()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        void M()
        {
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "M", FeaturesResources.local_function)],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_CeaseCapture_This()
    {
        var src1 = @"
using System;
 
class C
{
    int x = 1;
 
    void F()
    {
        int f(int a) => a + x;
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int x = 1;
 
    void F()
    {
        int f(int a) => a;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void LocalFunctions_Update_Signature1()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        <N:0>int f(int a) => a;</N:0>
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        <N:0>long <S:0>f</S:0>(long a) => a;</N:0>
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.Position(0), [GetResource("local function")])
                ])
            ]);
    }
 
    [Fact]
    public void LocalFunctions_Update_Signature2()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        <N:0>int f(int a) => a;</N:0>
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        <N:0>int <S:0>f</S:0>(int a, int b) => a + b;</N:0>
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.Position(0), [GetResource("local function")])
                ])
            ]);
    }
 
    [Fact]
    public void LocalFunctions_Update_Signature3()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        <N:0>int f(int a) => a;</N:0>
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        <N:0>long <S:0>f</S:0>(int a) => a;</N:0>
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.Position(0), [GetResource("local function")])
                ])
            ]);
    }
 
    [Fact]
    public void LocalFunctions_Update_Signature_ReturnType1()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        <N:0>int f(int a) { return 1; }</N:0>
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        <N:0>void <S:0>f</S:0>(int a) { }</N:0>
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.Position(0), [GetResource("local function")])
                ])
            ]);
    }
 
    [Fact]
    public void LocalFunctions_Update_Signature_BodySyntaxOnly()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int f(int a) => a;
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void G1(Func<int, int> f) {}
    void G2(Func<int, int> f) {}
 
    void F()
    {
        int f(int a) { return a; }
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType);
    }
 
    [Fact]
    public void LocalFunctions_Update_Signature_ParameterName1()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int f(int a) => 1;
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        int f(int b) => 2;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void LocalFunctions_Update_Signature_ParameterRefness1()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        <N:0>int <S:0>f</S:0>(ref int a) => 1;</N:0>
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        <N:0>int <S:0>f</S:0>(int a) => 2;</N:0>
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.Position(0), [GetResource("local function")])
                ])
            ]);
    }
 
    [Fact]
    public void LocalFunctions_Update_Signature_ParameterRefness2()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int f(out int a) => 1;
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        int f(ref int a) => 2;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void LocalFunctions_Update_Signature_ParameterRefness3()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int f(ref int a) => 1;
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        int f(out int a) => 1;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void LocalFunctions_Signature_SemanticErrors()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        Unknown f(Unknown a) => 1;
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        Unknown f(Unknown a) => 2;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        // There are semantics errors in the case. The errors are captured during the emit execution.
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void LocalFunctions_Update_CapturedParameters1()
    {
        var src1 = @"
using System;
 
class C
{
    void F(int x1)
    {
        int f1(int a1, int a2)
        {
            int f2(int a3) => x1 + a2;
            return a1;
        };
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F(int x1)
    {
        int f1(int a1, int a2)
        {
            int f2(int a3) => x1 + a2 + 1;
            return a1;
        };
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/2223")]
    public void LocalFunctions_Update_CapturedParameters2()
    {
        var src1 = @"
using System;
 
class C
{
    void F(int x1)
    {
        int f1(int a1, int a2)
        {
            int f2(int a3) => x1 + a2;
            return a1;
        };
 
        int f3(int a1, int a2)
        {
            int f4(int a3) => x1 + a2;
            return a1;
        };
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F(int x1)
    {
        int f1(int a1, int a2)
        {
            int f2(int a3) => x1 + a2 + 1;
            return a1;
        };
 
        int f3(int a1, int a2)
        {
            int f4(int a3) => x1 + a2 + 1;
            return a1;
        };
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_CeaseCapture_Closure1()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int y = 1;
        int f1(int a1)
        {
            int f2(int a2) => y + a2;
            return a1;
        };
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        int y = 1;
        int f1(int a1)
        {
            int f2(int a2) => a2;
            return a1 + y;
        };
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        // y is no longer captured in f2
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_CeaseCapture_IndexerParameter()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] { get { int f(int a3) => a1 + a2; return f; } }
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] { get { int f(int a3) => a2; return f; } }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_CeaseCapture_MethodParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    void F(int a1, int a2)
    {
        int f2(int a3) => a1 + a2;
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F(int a1, int a2)
    {
        int f2(int a3) => a1;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_CeaseCapture_LambdaParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int f1(int a1, int a2)
        {
            int f2(int a3) => a1 + a2;
            return a1;
        };
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        int f1(int a1, int a2)
        {
            int f2(int a3) => a2;
            return a1;
        };
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_CeaseCapture_SetterValueParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    int D
    {
        get { return 0; }
        set { void f() { Console.Write(value); } f(); }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int D
    {
        get { return 0; }
        set { }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_D")));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_CeaseCapture_IndexerSetterValueParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    int this[int a1, int a2]
    {
        get { return 0; }
        set { void f() { Console.Write(value); } f(); }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int this[int a1, int a2]
    {
        get { return 0; }
        set { }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item")));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_CeaseCapture_EventAdderValueParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    event Action D
    {
        add { void f() { Console.Write(value); } f(); }
        remove { }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    event Action D
    {
        add {  }
        remove { }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.add_D")));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_CeaseCapture_EventRemoverValueParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    event Action D
    {
        add { }
        remove { void f() { Console.Write(value); } f(); }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    event Action D
    {
        add { }
        remove { }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.remove_D")));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_DeleteCapture1()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int y = 1;
        int f1(int a1)
        {
            int f2(int a2) => y + a2;
            return y;
        };
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    { // error
        int f1(int a1)
        {
            int f2(int a2) => a2;
            return a1;
        };
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_Capturing_IndexerGetterParameter2()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] { get { int f(int a3) => a2; return f; } }
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] { get { int f(int a3) => a1 + a2; return f; } }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_Capturing_IndexerSetterParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] { get { return null; } set { int f(int a3) => a2; } }
}
";
        var src2 = @"
using System;
 
class C
{
    Func<int, int> this[int a1, int a2] { get { return null; } set { int f(int a3) => a1 + a2; } }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_Capturing_IndexerSetterValueParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    int this[int a1, int a2]
    {
        get { return 0; }
        set {  }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int this[int a1, int a2]
    {
        get { return 0; }
        set { void f() { Console.Write(value); } f(); }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.UpdateParameters);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_Capturing_EventAdderValueParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    event Action D
    {
        add {  }
        remove { }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    event Action D
    {
        add {  }
        remove { void f() { Console.Write(value); } f(); }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.remove_D"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.UpdateParameters);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_Capturing_EventRemoverValueParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    event Action D
    {
        add { }
        remove {  }
    }
}
";
        var src2 = @"
using System;
 
class C
{
    event Action D
    {
        add { }
        remove { void f() { Console.Write(value); } f(); }
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.remove_D"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.UpdateParameters);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_Capturing_MethodParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    void F(int a1, int a2)
    {
        int f2(int a3) => a1;
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F(int a1, int a2)
    {
        int f2(int a3) => a1 + a2;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_Capturing_LambdaParameter1()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int f1(int a1, int a2)
        {
            int f2(int a3) => a2;
            return a1;
        };
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        int f1(int a1, int a2)
        {
            int f2(int a3) => a1 + a2;
            return a1;
        };
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_StaticToThisOnly1()
    {
        var src1 = @"
using System;
 
class C
{
    int x = 1;
 
    void F()
    {
        int f(int a) => a;
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int x = 1;
 
    void F()
    {
        int f(int a) => a + x;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_StaticToThisOnly_Partial()
    {
        var src1 = @"
using System;
 
partial class C
{
    int x = 1;
    partial void F(); // def
}
 
partial class C
{
    partial void F()  // impl
    {
        int f(int a) => a;
    }
}
";
        var src2 = @"
using System;
 
partial class C
{
    int x = 1;
    partial void F(); // def
}
 
partial class C
{
    partial void F()  // impl
    {
        int f(int a) => a + x;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember<IMethodSymbol>("C.F").PartialImplementationPart, preserveLocalVariables: true, partialType: "C"));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_StaticToThisOnly3()
    {
        var src1 = @"
using System;
 
class C
{
    int x = 1;
 
    void F()
    {
        int f1(int a1) => a1;
        int f2(int a2) => a2 + x;
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int x = 1;
 
    void F()
    {
        int f1(int a1) => a1 + x;
        int f2(int a2) => a2 + x;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_StaticToClosure1()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int x = 1;
        int f1(int a1) => a1;
        int f2(int a2) => a2 + x;
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    { 
        int x = 1;       
        int f1(int a1) 
        {
            return a1 + 
                x+ // 1 
                x; // 2
        };
 
        int f2(int a2) => a2 + x;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_ThisOnlyToClosure1()
    {
        var src1 = @"
using System;
 
class C
{
    int x = 1;
 
    void F()
    {
        int y = 1;
        int f1(int a1) => a1 + x;
        int f2(int a2) => a2 + x + y;
    }
}
";
        var src2 = @"
using System;
 
class C
{
    int x = 1;
 
    void F()
    {
        int y = 1;
        int f1(int a1) => a1 + x + y;
        int f2(int a2) => a2 + x + y;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void LocalFunctions_Update_Nested1()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int y = 1;
        int f1(int a1) 
        {
            int f2(int a2) => a2 + y;
            return a1;
        };
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        int y = 1;
        int f1(int a1) 
        {
            int f2(int a2) => a2 + y;
            return a1 + y;
        };
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_Update_Nested2()
    {
        var src1 = @"
using System;
 
class C
{
    void F()
    {
        int y = 1;
        int f1(int a1)
        {
            int f2(int a2) => a2;
            return a1;
        };
    }
}
";
        var src2 = @"
using System;
 
class C
{
    void F()
    {
        int y = 1;
        int f1(int a1)
        {
            int f2(int a2) => a1 + a2;
            return a1;
        };
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void LocalFunctions_Update_Generic()
    {
        var src1 = @"
class C
{
    void F()
    {
        int L<T>() => 1;
        int M<T>() => 1;
        int N<T>() => 1;
        int O<T>() => 1;
    }
}";
        var src2 = @"
class C
{
    void F()
    {
        int L<T>() => 1;
        int M<T>() => 2;
        int N<T>() => 1 ;
        int O<T>() =>  1;
    }
}";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            [
                Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "M", GetResource("local function"))
            ],
            capabilities: EditAndContinueCapabilities.Baseline);
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.GenericUpdateMethod);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void LocalFunctions_RenameCapturedLocal()
    {
        var src1 = @"
using System;
using System.Diagnostics;
 
class C
{
    static void F()
    <N:0>{
        int x = 1;
        int f() => x;
    }</N:0>
}";
        var src2 = @"
using System;
using System.Diagnostics;
 
class C
{
    static void F()
    <N:0>{
        int <S:0>X</S:0> = 1;
        int f() => X;
    }</N:0>
}";
 
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), ["x", "X"])
                ])
            ],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void LocalFunctions_RenameCapturedParameter()
    {
        var src1 = @"
using System;
using System.Diagnostics;
 
class C
{
    static void F(int x)
    <N:0>{
        int f() => x;
    }</N:0>
}";
        var src2 = @"
using System;
using System.Diagnostics;
 
class C
{
    static void F(int <S:0>X</S:0>)
    <N:0>{
        int f() => X;
    }</N:0>
}";
 
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), ["x", "X"])
                ])
            ],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.UpdateParameters);
    }
 
    [Fact]
    public void LocalFunctions_Update()
    {
        var src1 = @"
using System;
 
class C
{
    void M()
    {
        N(3);
        
        void N(int x)
        {
            if (x > 3)
            {
                x.ToString();
            }
            else
            {
                N(x - 1);
            }
        }
    }
}";
        var src2 = @"
using System;
 
class C
{
    void M()
    {
        N(3);
        
        void N(int x)
        {
            Console.WriteLine(""Hello"");
        }
    }
}";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void LocalFunction_In_Parameter_InsertWhole()
    {
        var src1 = @"class Test { void M() { } }";
        var src2 = @"class Test { void M() { void local(in int b) { throw null; } } }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [void M() { }]@13 -> [void M() { void local(in int b) { throw null; } }]@13");
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType);
    }
 
    [Fact]
    public void LocalFunction_In_Parameter_InsertParameter()
    {
        var src1 = @"class C { void F() { <N:0>void local() { throw null; }</N:0> } }";
        var src2 = @"class C { void F() { <N:0>void <S:0>local</S:0>(in int b) { throw null; }</N:0> } }";
 
        var edits = GetTopEdits(src1, src2);
 
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
            [
                RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.Position(0), arguments: [GetResource("local function")])
            ]));
    }
 
    [Fact]
    public void LocalFunction_In_Parameter_Update()
    {
        var src1 = @"class C { void F() { <N:0>void local(int b) { throw null; }</N:0> } }";
        var src2 = @"class C { void F() { <N:0>void <S:0>local</S:0>(in int b) { throw null; }</N:0> } }";
 
        var edits = GetTopEdits(src1, src2);
 
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
            [
                RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.Position(0), arguments: [GetResource("local function")])
            ]));
    }
 
    [Fact]
    public void LocalFunction_ReadOnlyRef_ReturnType_Insert()
    {
        var src1 = @"class Test { void M() { } }";
        var src2 = @"class Test { void M() { ref readonly int local() { throw null; } } }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [void M() { }]@13 -> [void M() { ref readonly int local() { throw null; } }]@13");
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType);
    }
 
    [Fact]
    public void LocalFunction_ReadOnlyRef_ReturnType_Update()
    {
        var src1 = @"class C { void F() { <N:0>int local() { throw null; }</N:0> } }";
        var src2 = @"class C { void F() { <N:0>ref readonly int <S:0>local</S:0>() { throw null; }</N:0> } }";
 
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
            [
                RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.Position(0), arguments: [GetResource("local function")])
            ]));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37128")]
    public void LocalFunction_AddToInterfaceMethod()
    {
        var src1 = @"
using System;
interface I
{
    static int X = M(() => 1);
    static int M() => 1;
 
    static void F()
    {
        void g() { }
    }
}
";
        var src2 = @"
using System;
interface I
{
    static int X = M(() => { void f3() {} return 2; });
    static int M() => 1;
 
    static void F()
    {
        int f1() => 1;
        f1();
 
        void g() { void f2() {} f2(); }
 
        var l = new Func<int>(() => 1);
        l();
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        // lambdas are ok as they are emitted to a nested type
        edits.VerifySemanticDiagnostics(
            targetFrameworks: [TargetFramework.NetCoreApp],
            diagnostics:
            [
                Diagnostic(RudeEditKind.InsertLocalFunctionIntoInterfaceMethod, "f1", CSharpFeaturesResources.local_function),
                Diagnostic(RudeEditKind.InsertLocalFunctionIntoInterfaceMethod, "f2", CSharpFeaturesResources.local_function),
                Diagnostic(RudeEditKind.InsertLocalFunctionIntoInterfaceMethod, "f3", CSharpFeaturesResources.local_function)
            ]);
    }
 
    [Fact]
    public void LocalFunction_AddStatic()
    {
        var src1 = @"class Test { void M() { int local() { throw null; } } }";
        var src2 = @"class Test { void M() { static int local() { throw null; } } }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [void M() { int local() { throw null; } }]@13 -> [void M() { static int local() { throw null; } }]@13");
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void LocalFunction_RemoveStatic()
    {
        var src1 = @"class Test { void M() { static int local() { throw null; } } }";
        var src2 = @"class Test { void M() { int local() { throw null; } } }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [void M() { static int local() { throw null; } }]@13 -> [void M() { int local() { throw null; } }]@13");
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void LocalFunction_AddUnsafe()
    {
        var src1 = @"class Test { void M() { int local() { throw null; } } }";
        var src2 = @"class Test { void M() { unsafe int local() { throw null; } } }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [void M() { int local() { throw null; } }]@13 -> [void M() { unsafe int local() { throw null; } }]@13");
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void LocalFunction_RemoveUnsafe()
    {
        var src1 = @"class Test { void M() { unsafe int local() { throw null; } } }";
        var src2 = @"class Test { void M() { int local() { throw null; } } }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [void M() { unsafe int local() { throw null; } }]@13 -> [void M() { int local() { throw null; } }]@13");
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37054")]
    public void LocalFunction_AddAsync()
    {
        var src1 = @"class Test { void M() { Task<int> local() => throw null; } }";
        var src2 = @"class Test { void M() { async Task<int> local() => throw null; } }";
 
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37054")]
    public void LocalFunction_RemoveAsync()
    {
        var src1 = @"class Test { void M() { async int local() { throw null; } } }";
        var src2 = @"class Test { void M() { int local() { throw null; } } }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            Diagnostic(RudeEditKind.ChangingFromAsynchronousToSynchronous, "local", FeaturesResources.local_function));
    }
 
    [Fact]
    public void LocalFunction_AddAttribute()
    {
        var src1 = "void L() { }";
        var src2 = "[A]void L() { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [void L() { }]@2 -> [[A]void L() { }]@2");
 
        // Get top edits so we can validate rude edits
        GetTopEdits(edits).VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.ChangingAttributesNotSupportedByRuntime, "L", FeaturesResources.local_function)],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void LocalFunction_RemoveAttribute()
    {
        var src1 = "[A]void L() { }";
        var src2 = "void L() { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [[A]void L() { }]@2 -> [void L() { }]@2");
 
        // Get top edits so we can validate rude edits
        GetTopEdits(edits).VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.ChangingAttributesNotSupportedByRuntime, "L", FeaturesResources.local_function)],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void LocalFunction_ReorderAttribute()
    {
        var src1 = "[A, B]void L() { }";
        var src2 = "[B, A]void L() { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Update [[A, B]void L() { }]@2 -> [[B, A]void L() { }]@2");
 
        // Get top edits so we can validate rude edits
        GetTopEdits(edits).VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void LocalFunction_CombineAttributeLists()
    {
        var src1 = "[A][B]void L() { }";
        var src2 = "[A, B]void L() { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [[A][B]void L() { }]@2 -> [[A, B]void L() { }]@2");
 
        GetTopEdits(edits).VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void LocalFunction_SplitAttributeLists()
    {
        var src1 = "[A, B]void L() { }";
        var src2 = "[A][B]void L() { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [[A, B]void L() { }]@2 -> [[A][B]void L() { }]@2");
 
        GetTopEdits(edits).VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void LocalFunction_ChangeAttributeListTarget1()
    {
        var src1 = "[return: A]void L() { }";
        var src2 = "[A]void L() { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Update [[return: A]void L() { }]@2 -> [[A]void L() { }]@2");
 
        GetTopEdits(edits).VerifySemanticDiagnostics(
            [
                Diagnostic(RudeEditKind.ChangingAttributesNotSupportedByRuntime, "L", FeaturesResources.local_function),
                Diagnostic(RudeEditKind.ChangingAttributesNotSupportedByRuntime, "L", FeaturesResources.local_function)
            ],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void LocalFunction_ChangeAttributeListTarget2()
    {
        var src1 = "[A]void L() { }";
        var src2 = "[return: A]void L() { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Update [[A]void L() { }]@2 -> [[return: A]void L() { }]@2");
 
        GetTopEdits(edits).VerifySemanticDiagnostics(
            [
                Diagnostic(RudeEditKind.ChangingAttributesNotSupportedByRuntime, "L", FeaturesResources.local_function),
                Diagnostic(RudeEditKind.ChangingAttributesNotSupportedByRuntime, "L", FeaturesResources.local_function)
            ],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void LocalFunction_ReturnType_AddAttribute()
    {
        var src1 = "int L() { return 1; }";
        var src2 = "[return: A]int L() { return 1; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [int L() { return 1; }]@2 -> [[return: A]int L() { return 1; }]@2");
 
        GetTopEdits(edits).VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.ChangingAttributesNotSupportedByRuntime, "L", FeaturesResources.local_function)],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void LocalFunction_ReturnType_RemoveAttribute()
    {
        var src1 = "[return: A]int L() { return 1; }";
        var src2 = "int L() { return 1; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [[return: A]int L() { return 1; }]@2 -> [int L() { return 1; }]@2");
 
        GetTopEdits(edits).VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.ChangingAttributesNotSupportedByRuntime, "L", FeaturesResources.local_function)],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void LocalFunction_ReturnType_ReorderAttribute()
    {
        var src1 = "[return: A, B]int L() { return 1; }";
        var src2 = "[return: B, A]int L() { return 1; }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Update [[return: A, B]int L() { return 1; }]@2 -> [[return: B, A]int L() { return 1; }]@2");
 
        GetTopEdits(edits).VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void LocalFunction_Parameter_AddAttribute()
    {
        var src1 = "void L(int i) { }";
        var src2 = "void L([A]int i) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [int i]@9 -> [[A]int i]@9");
 
        GetTopEdits(edits).VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.ChangingAttributesNotSupportedByRuntime, "L", FeaturesResources.parameter)],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void LocalFunction_Parameter_RemoveAttribute()
    {
        var src1 = "void L([A]int i) { }";
        var src2 = "void L(int i) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [[A]int i]@9 -> [int i]@9");
 
        GetTopEdits(edits).VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.ChangingAttributesNotSupportedByRuntime, "L", FeaturesResources.parameter)],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void LocalFunction_Parameter_ReorderAttribute()
    {
        var src1 = "void L([A, B]int i) { }";
        var src2 = "void L([B, A]int i) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Update [[A, B]int i]@9 -> [[B, A]int i]@9");
 
        GetTopEdits(edits).VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void LocalFunction_TypeParameter_AddAttribute()
    {
        var src1 = "void L<T>(T i) { }";
        var src2 = "void L<[A] T>(T i) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [T]@9 -> [[A] T]@9");
 
        GetTopEdits(edits).VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.ChangingAttributesNotSupportedByRuntime, "L", FeaturesResources.type_parameter)],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void LocalFunction_TypeParameter_RemoveAttribute()
    {
        var src1 = "void L<[A] T>(T i) { }";
        var src2 = "void L<T>(T i) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [[A] T]@9 -> [T]@9");
 
        GetTopEdits(edits).VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.ChangingAttributesNotSupportedByRuntime, "L", FeaturesResources.type_parameter)],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void LocalFunction_TypeParameter_ReorderAttribute()
    {
        var src1 = "void L<[A, B] T>(T i) { }";
        var src2 = "void L<[B, A] T>(T i) { }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits("Update [[A, B] T]@9 -> [[B, A] T]@9");
 
        GetTopEdits(edits).VerifySemanticDiagnostics();
    }
 
    [Theory]
    // insert:
    [InlineData("void L<A>() {}", "void <S:0>L</S:0><A,B>() {}", new[] { "Update [<A>]@13 -> [<A,B>]@24", "Insert [B]@27" })]
    [InlineData("void L() {}", "void <S:0>L</S:0><A>() {}", new[] { "Insert [<A>]@24", "Insert [A]@25" })]
    // delete:
    [InlineData("void L<A>() {}", "void <S:0>L</S:0>() {}", new[] { "Delete [<A>]@13", "Delete [A]@14" })]
    [InlineData("void L<A,B>() {}", "void <S:0>L</S:0><B>() {}", new[] { "Update [<A,B>]@13 -> [<B>]@24", "Delete [A]@14" })]
    // update:
    [InlineData("void L<A>() {}", "void <S:0>L</S:0><B>() {}", new[] { "Update [A]@14 -> [B]@25" })]
    // reorder:
    [InlineData("void L<A,B>() {}", "void <S:0>L</S:0><B,A>() {}", new[] { "Reorder [B]@16 -> @25" })]
    // reorder and update:
    [InlineData("void L<A,B>() {}", "void <S:0>L</S:0><B,C>() {}", new[] { "Reorder [B]@16 -> @25", "Update [A]@14 -> [C]@27" })]
    public void VerifyChangingLocalFunctionTypeParameters(string localFunctionSource1, string localFunctionSource2, string[] expectedMethodEdits)
    {
        var src1 = $"<N:0>{localFunctionSource1}</N:0>";
        var src2 = $"<N:0>{localFunctionSource2}</N:0>";
 
        GetMethodEdits(src1, src2).VerifyEdits(expectedMethodEdits);
 
        var edits = GetTopEdits(src1, src2, MethodKind.Regular);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingTypeParameters, syntaxMap.Position(0), [GetResource("local function")])
                ])
            ]);
    }
 
    [Theory]
    [InlineData("Enum", "Delegate")]
    [InlineData("IDisposable", "IDisposable, new()")]
    public void LocalFunctions_TypeParameter_Constraint_Clause_Update(string oldConstraint, string newConstraint)
    {
        var src1 = "<N:0>void L<A>() where A : " + oldConstraint + " {}</N:0>";
        var src2 = "<N:0>void <S:0>L</S:0><A>() where A : " + newConstraint + " {}</N:0>";
 
        GetMethodEdits(src1, src2).VerifyEdits(
            "Update [where A : " + oldConstraint + "]@19 -> [where A : " + newConstraint + "]@30");
 
        var edits = GetTopEdits(src1, src2, MethodKind.Regular);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingTypeParameters, syntaxMap.Position(0), [GetResource("local function")])
                ])
            ]);
    }
 
    [Theory]
    [InlineData("nonnull")]
    [InlineData("struct")]
    [InlineData("class")]
    [InlineData("new()")]
    [InlineData("unmanaged")]
    [InlineData("System.IDisposable")]
    [InlineData("System.Delegate")]
    public void LocalFunctions_TypeParameter_Constraint_Clause_Delete(string oldConstraint)
    {
        var src1 = "<N:0>void L<A>() where A : " + oldConstraint + " {}</N:0>";
        var src2 = "<N:0>void <S:0>L</S:0><A>() {}</N:0>";
 
        GetMethodEdits(src1, src2).VerifyEdits(
            "Delete [where A : " + oldConstraint + "]@19");
 
        var edits = GetTopEdits(src1, src2, MethodKind.Regular);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingTypeParameters, syntaxMap.Position(0), [GetResource("local function")])
                ])
            ]);
    }
 
    [Fact]
    public void LocalFunctions_TypeParameter_Constraint_Clause_Add()
    {
        var src1 = "<N:0>void L<A,B>() where A : new() {}</N:0>";
        var src2 = "<N:0>void <S:0>L</S:0><A,B>() where A : new() where B : System.IDisposable {}</N:0>";
 
        GetMethodEdits(src1, src2).VerifyEdits(
            "Insert [where B : System.IDisposable]@48");
 
        var edits = GetTopEdits(src1, src2, MethodKind.Regular);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingTypeParameters, syntaxMap.Position(0), [GetResource("local function")])
                ])
            ]);
    }
 
    [Fact]
    public void LocalFunctions_Stackalloc_Update()
    {
        var src1 = @"
using System;
class C
{
    void F()
    {
        void L1()
        {
            Span<int> s = stackalloc int[10];
        }
        void L2()
        {
            Span<int> s = stackalloc int[10];
        }
    }
}";
        var src2 = @"
using System;
class C
{
    void F()
    {
        void L1()
        {
            Span<int> s = stackalloc int[20];
        }
        void L2()
        {
            Span<int> s = stackalloc int[10 ];
        }
    }
}";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            Diagnostic(RudeEditKind.StackAllocUpdate, "stackalloc int[20]", GetResource("local function")));
    }
 
    [Fact]
    public void LocalFunctions_Stackalloc_Insert()
    {
        var src1 = @"
using System;
class C
{
    void F()
    {
        void L1()
        {
        }
    }
}";
        var src2 = @"
using System;
class C
{
    void F()
    {
        void L1()
        {
            Span<int> s = stackalloc int[10];
        }
    }
}";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            Diagnostic(RudeEditKind.StackAllocUpdate, "stackalloc int[10]", GetResource("local function")));
    }
 
    [Fact]
    public void LocalFunctions_Stackalloc_Delete()
    {
        var src1 = @"
using System;
class C
{
    void F()
    {
        void L1()
        {
            Span<int> s = stackalloc int[10];
        }
    }
}";
        var src2 = @"
using System;
class C
{
    void F()
    {
        void L1()
        {
        }
    }
}";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            Diagnostic(RudeEditKind.StackAllocUpdate, "L1", GetResource("local function")));
    }
 
    [Fact]
    public void LocalFunctions_Stackalloc_InNestedLocalFunction()
    {
        var src1 = @"
using System;
class C
{
    void F()
    {
        void L()
        {
            void M()
            {
                Span<int> s = stackalloc int[10];
            }
 
            Console.WriteLine(1);
        }
    }
}";
        var src2 = @"
using System;
class C
{
    void F()
    {
        void L()
        {
            void M()
            {
                Span<int> s = stackalloc int[10];
            }
 
            Console.WriteLine(2);
        }
    }
}";
 
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void LocalFunctions_AsyncModifier_Add()
    {
        var src1 = @"
class Test
{
    public void F()
    {
        Task<int> WaitAsync()
        {
            return 1;
        }
    }
}";
        var src2 = @"
class Test
{
    public void F()
    {
        async Task<int> WaitAsync()
        {
            await Task.Delay(1000);
            return 1;
        }
    }
}";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.MakeMethodAsyncNotSupportedByRuntime, "WaitAsync")],
            capabilities: EditAndContinueCapabilities.Baseline);
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.AddExplicitInterfaceImplementation);
    }
 
    [Fact]
    public void LocalFunctions_Iterator_Add()
    {
        var src1 = @"
class Test
{
    public void F()
    {
        IEnumerable<int> Iter()
        {
            return null;
        }
    }
}";
        var src2 = @"
class Test
{
    public void F()
    {
        IEnumerable<int> Iter()
        {
            yield return 1;
        }
    }
}";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics(
            [Diagnostic(RudeEditKind.MakeMethodIteratorNotSupportedByRuntime, "Iter")],
            capabilities: EditAndContinueCapabilities.Baseline);
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.AddExplicitInterfaceImplementation);
    }
 
    [Fact]
    public void LocalFunctions_WithoutBody_SemanticError()
    {
        var src1 = "Console.WriteLine(1); int C(int X);";
        var src2 = "Console.WriteLine(2); int C(int X);";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.<Main>$"))],
            [Diagnostic(RudeEditKind.UpdateMightNotHaveAnyEffect, "Console.WriteLine(2);", GetResource("top-level code"))]);
    }
 
    #endregion
 
    #region Queries
 
    [Fact]
    public void Queries_UpdateAround_BlockBody()
    {
        var src1 = "class C { void M() { F(1, from goo in bar select baz); } }";
        var src2 = "class C { void M() { F(2, from goo in bar select baz); } }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Queries_UpdateAround_ExpressionBody()
    {
        var src1 = "class C { void M() => F(1, from goo in bar select baz); }";
        var src2 = "class C { void M() => F(2, from goo in bar select baz); }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Queries_Update_Signature_Select1()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>select a</N:0>;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        var result = from a in new[] {1.0} <N:0>select a</N:0>;
    }
}
";
 
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("select clause")])
                ])
            ]);
    }
 
    [Fact]
    public void Queries_Update_Signature_Select2()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>select a</N:0>;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>select a.ToString()</N:0>;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("select clause")])
                ])
            ]);
    }
 
    [Fact]
    public void Queries_Update_Signature_From1()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        var result = <N:0>from a in new[] {1}</N:0> from b in new[] {2} select b;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        var result = <N:0>from long a in new[] {1}</N:0> from b in new[] {2} select b;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("from clause")])
                ])
            ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType);
    }
 
    [Fact]
    public void Queries_Update_Signature_From2()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        var result = from System.Int64 a in new[] {1} from b in new[] {2} select b;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        var result = from long a in new[] {1} from b in new[] {2} select b;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Queries_Update_Signature_From3()
    {
        var src1 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} from b in new[] {2} select b;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new List<int>() from b in new List<int>() select b;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Queries_Update_Signature_Let1()
    {
        var src1 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>let b = 1</N:0> select a;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>let b = 1.0</N:0> select a;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("let clause")])
                ])
            ]);
    }
 
    [Fact]
    public void Queries_Update_Signature_OrderBy1()
    {
        var src1 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} orderby <N:0>a + 1 descending</N:0>, a + 2 ascending select a;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} orderby <N:0>a + 1.0 descending</N:0>, a + 2 ascending select a;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("orderby clause")])
                ])
            ]);
    }
 
    [Fact]
    public void Queries_Update_Signature_OrderBy2()
    {
        var src1 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} orderby a + 1 descending, <N:0>a + 2 ascending</N:0> select a;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} orderby a + 1 descending, <N:0>a + 2.0 ascending</N:0> select a;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("orderby clause")])
                ])
            ]);
    }
 
    [Fact]
    public void Queries_Update_Signature_Join1()
    {
        var src1 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>join b in new[] {1} on a equals b</N:0> select b;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>join b in new[] {1.0} on a equals b</N:0> select b;
    }
}
";
 
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("join clause")])
                ])
            ]);
    }
 
    [Fact]
    public void Queries_Update_Signature_Join2()
    {
        var src1 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>join b in new[] {1} on a equals b</N:0> select b;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>join byte b in new[] {1} on a equals b</N:0> select b;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("join clause")])
                ])
            ]);
    }
 
    [Fact]
    public void Queries_Update_Signature_Join3()
    {
        var src1 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>join b in new[] {1} on a + 1 equals b</N:0> select b;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>join b in new[] {1} on a + 1.0 equals b</N:0> select b;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("join clause")])
                ])
            ]);
    }
 
    [Fact]
    public void Queries_Update_Signature_Join4()
    {
        var src1 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>join b in new[] {1} on a equals b + 1</N:0> select b;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>join b in new[] {1} on a equals b + 1.0</N:0> select b;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("join clause")])
                ])
            ]);
    }
 
    [Fact]
    public void Queries_Update_Signature_GroupBy1()
    {
        var src1 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>group a + 1 by a</N:0> into z select z;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>group a + 1.0 by a</N:0> into z select z;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("groupby clause")])
                ])
            ]);
    }
 
    [Fact]
    public void Queries_Update_Signature_GroupBy2()
    {
        var src1 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>group a by a</N:0> into z select z;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>group a by a + 1.0</N:0> into z select z;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("groupby clause")])
                ])
            ]);
    }
 
    [Fact]
    public void Queries_Update_Signature_GroupBy_MatchingErrorTypes()
    {
        var src1 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    Unknown G1(int a) => null;
    Unknown G2(int a) => null;
 
    void F()
    {
        var result = from a in new[] {1} group G1(a) by a into z select z;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    Unknown G1(int a) => null;
    Unknown G2(int a) => null;
    
    void F()
    {
        var result = from a in new[] {1} group G2(a) by a into z select z;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Queries_Update_Signature_GroupBy_NonMatchingErrorTypes()
    {
        var src1 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    Unknown1 G1(int a) => null;
    Unknown2 G2(int a) => null;
 
    void F()
    {
        var result = from a in new[] {1} <N:0>group G1(a) by a</N:0> into z select z;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    Unknown1 G1(int a) => null;
    Unknown2 G2(int a) => null;
    
    void F()
    {
        var result = from a in new[] {1} <N:0>group G2(a) by a</N:0> into z select z;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("groupby clause")])
                ])
            ]);
    }
 
    [Fact]
    public void Queries_FromSelect_Update1()
    {
        var src1 = "F(from a in b from x in y select c);";
        var src2 = "F(from a in c from x in z select c + 1);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [from a in b]@4 -> [from a in c]@4",
            "Update [from x in y]@16 -> [from x in z]@16",
            "Update [select c]@28 -> [select c + 1]@28");
    }
 
    [Fact]
    public void Queries_FromSelect_Update2()
    {
        var src1 = "F(from a in b from x in y select c);";
        var src2 = "F(from a in b from x in z select c);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [from x in y]@16 -> [from x in z]@16");
    }
 
    [Fact]
    public void Queries_FromSelect_Update3()
    {
        var src1 = "F(from a in await b from x in y select c);";
        var src2 = "F(from a in await c from x in y select c);";
 
        var edits = GetMethodEdits(src1, src2, MethodKind.Async);
 
        edits.VerifyEdits(
            "Update [await b]@34 -> [await c]@34");
    }
 
    [Fact]
    public void Queries_Select_Reduced1()
    {
        var src1 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} where a > 0 select a;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} where a > 0 select a + 1;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Queries_Select_Reduced2()
    {
        var src1 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} where a > 0 select a + 1;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
using System.Collections.Generic;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} where a > 0 select a;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Queries_FromSelect_Delete()
    {
        var src1 = "F(from a in b from c in d select a + c);";
        var src2 = "F(from a in b select c + 1);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [select a + c]@28 -> [select c + 1]@16",
            "Delete [from c in d]@16");
    }
 
    [Fact]
    public void Queries_JoinInto_Update()
    {
        var src1 = "F(from a in b join b in c on a equals b into g1 select g1);";
        var src2 = "F(from a in b join b in c on a equals b into g2 select g2);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [select g1]@50 -> [select g2]@50",
            "Update [into g1]@42 -> [into g2]@42");
    }
 
    [Fact]
    public void Queries_JoinIn_Update()
    {
        var src1 = "F(from a in b join b in await A(1) on a equals b select g);";
        var src2 = "F(from a in b join b in await A(2) on a equals b select g);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [await A(1)]@26 -> [await A(2)]@26");
    }
 
    [Fact]
    public void Queries_GroupBy_Update()
    {
        var src1 = "F(from a in b  group a by a.x into g  select g);";
        var src2 = "F(from a in b  group z by z.y into h  select h);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [group a by a.x]@17 -> [group z by z.y]@17",
            "Update [into g  select g]@32 -> [into h  select h]@32",
            "Update [select g]@40 -> [select h]@40");
    }
 
    [Fact]
    public void Queries_OrderBy_Reorder()
    {
        var src1 = "F(from a in b  orderby a.x, a.b descending, a.c ascending  select a.d);";
        var src2 = "F(from a in b  orderby a.x, a.c ascending, a.b descending  select a.d);";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [a.c ascending]@46 -> @30");
    }
 
    [Fact]
    public void Queries_GroupBy_Reduced1()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>group a by a</N:0>;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>group a + 1.0 by a</N:0>;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("groupby clause")])
                ])
            ]);
    }
 
    [Fact]
    public void Queries_GroupBy_Reduced2()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} group a by a;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} group a + 1 by a;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Queries_GroupBy_Reduced3()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>group a + 1.0 by a</N:0>;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} <N:0>group a by a</N:0>;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        var syntaxMap = edits.GetSyntaxMap();
 
        edits.VerifySemantics(
            [
                SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits:
                [
                    RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("groupby clause")])
                ])
            ]);
    }
 
    [Fact]
    public void Queries_GroupBy_Reduced4()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} group a + 1 by a;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
    void F()
    {
        var result = from a in new[] {1} group a by a;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Queries_OrderBy_Continuation_Update()
    {
        var src1 = "F(from a in b  orderby a.x, a.b descending  select a.d  into z  orderby a.c ascending select z);";
        var src2 = "F(from a in b  orderby a.x, a.c ascending  select a.d  into z  orderby a.b descending select z);";
 
        var edits = GetMethodEdits(src1, src2);
 
        var actual = ToMatchingPairs(edits.Match);
 
        var expected = new MatchingPairs
        {
            { "F(from a in b  orderby a.x, a.b descending  select a.d  into z  orderby a.c ascending select z);", "F(from a in b  orderby a.x, a.c ascending  select a.d  into z  orderby a.b descending select z);" },
            { "from a in b", "from a in b" },
            { "orderby a.x, a.b descending  select a.d  into z  orderby a.c ascending select z", "orderby a.x, a.c ascending  select a.d  into z  orderby a.b descending select z" },
            { "orderby a.x, a.b descending", "orderby a.x, a.c ascending" },
            { "a.x", "a.x" },
            { "a.b descending", "a.c ascending" },
            { "select a.d", "select a.d" },
            { "into z  orderby a.c ascending select z", "into z  orderby a.b descending select z" },
            { "orderby a.c ascending select z", "orderby a.b descending select z" },
            { "orderby a.c ascending", "orderby a.b descending" },
            { "a.c ascending", "a.b descending" },
            { "select z", "select z" }
        };
 
        expected.AssertEqual(actual);
 
        edits.VerifyEdits(
            "Update [a.b descending]@30 -> [a.c ascending]@30",
            "Update [a.c ascending]@74 -> [a.b descending]@73");
    }
 
    [Fact]
    public void Queries_CapturedTransparentIdentifiers_FromClause1()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
	int Z(Func<int> f)
	{
		return 1;
	}
 
    void F()
    {
		var result = from a in new[] { 1 }
		             from b in new[] { 2 }
		             where Z(() => a) > 0
		             where Z(() => b) > 0
		             where Z(() => a) > 0
		             where Z(() => b) > 0
		             select a;
    }
}";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
	int Z(Func<int> f)
	{
		return 1;
	}
 
    void F()
    {
		var result = from a in new[] { 1 }
		             from b in new[] { 2 }
		             where Z(() => a) > 1  // update
		             where Z(() => b) > 2  // update
		             where Z(() => a) > 3  // update
		             where Z(() => b) > 4  // update
		             select a;
    }
}";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Queries_CapturedTransparentIdentifiers_LetClause1()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
	int Z(Func<int> f)
	{
		return 1;
	}
 
    void F()
    {
		var result = from a in new[] { 1 }
		             let b = Z(() => a)
		             select a + b;
    }
}";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
	int Z(Func<int> f)
	{
		return 1;
	}
 
    void F()
    {
		var result = from a in new[] { 1 }
		             let b = Z(() => a + 1)
		             select a - b;
    }
}";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Queries_CapturedTransparentIdentifiers_JoinClause1()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
	int Z(Func<int> f)
	{
		return 1;
	}
 
    void F()
    {
		var result = from a in new[] { 1 }
                     join b in new[] { 3 } on Z(() => a + 1) equals Z(() => b - 1) into g
                     select Z(() => g.First());
    }
}";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
	int Z(Func<int> f)
	{
		return 1;
	}
 
    void F()
    {
		var result = from a in new[] { 1 }
                     join b in new[] { 3 } on Z(() => a + 1) equals Z(() => b - 1) into g
                     select Z(() => g.Last());
    }
}";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Queries_CeaseCapturingTransparentIdentifiers1()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
	int Z(Func<int> f)
	{
		return 1;
	}
 
    void F()
    {
		var result = from a in new[] { 1 }
		             from b in new[] { 2 }
		             where Z(() => a + b) > 0
		             select a;
    }
}";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
	int Z(Func<int> f)
	{
		return 1;
	}
 
    void F()
    {
		var result = from a in new[] { 1 }
		             from b in new[] { 2 }
		             where Z(() => a + 1) > 0
		             select a;
    }
}";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Queries_CapturingTransparentIdentifiers1()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
	int Z(Func<int> f)
	{
		return 1;
	}
 
    void F()
    {
		var result = from a in new[] { 1 }
		             from b in new[] { 2 }
		             where Z(() => a + 1) > 0
		             select a;
    }
}";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
	int Z(Func<int> f)
	{
		return 1;
	}
 
    void F()
    {
		var result = from a in new[] { 1 }
		             from b in new[] { 2 }
		             where Z(() => a + b) > 0
		             select a;
    }
}";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Queries_AccessingCapturedTransparentIdentifier1()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
    int Z(Func<int> f) => 1;
 
    void F()
    {
        var result = from a in new[] { 1 }
                     where Z(() => a) > 0
                     select 1;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
    int Z(Func<int> f) => 1;
   
    void F()
    {
        var result = from a in new[] { 1 } 
                     where Z(() => a) > 0
                     select a;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics();
    }
 
    [Fact]
    public void Queries_AccessingCapturedTransparentIdentifier2()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
    int Z(Func<int> f) => 1;
 
    void F()
    {
        var result = from a in new[] { 1 }
                     from b in new[] { 1 }
                     where Z(() => a) > 0
                     select b;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
    int Z(Func<int> f) => 1;
   
    void F()
    {
        var result = from a in new[] { 1 } 
                     from b in new[] { 1 }
                     where Z(() => a) > 0
                     select a + b;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Queries_AccessingCapturedTransparentIdentifier3()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
    int Z(Func<int> f) => 1;
 
    void F()
    {
        var result = from a in new[] { 1 }
                     where Z(() => a) > 0
                     select Z(() => 1);
    }
}
";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
    int Z(Func<int> f) => 1;
   
    void F()
    {
        var result = from a in new[] { 1 } 
                     where Z(() => a) > 0
                     select Z(() => a);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Queries_NotAccessingCapturedTransparentIdentifier1()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
    int Z(Func<int> f) => 1;
 
    void F()
    {
        var result = from a in new[] { 1 }
                     from b in new[] { 1 }
                     where Z(() => a) > 0
                     select a + b;
    }
}
";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
    int Z(Func<int> f) => 1;
   
    void F()
    {
        var result = from a in new[] { 1 } 
                     from b in new[] { 1 }
                     where Z(() => a) > 0
                     select b;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Queries_NotAccessingCapturedTransparentIdentifier2()
    {
        var src1 = @"
using System;
using System.Linq;
 
class C
{
    int Z(Func<int> f) => 1;
 
    void F()
    {
        var result = from a in new[] { 1 }
                     where Z(() => a) > 0
                     select Z(() => 1);
    }
}
";
        var src2 = @"
using System;
using System.Linq;
 
class C
{
    int Z(Func<int> f) => 1;
   
    void F()
    {
        var result = from a in new[] { 1 } 
                     where Z(() => a) > 0
                     select Z(() => a);
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void Queries_Insert_Static_First()
    {
        var src1 = @"
using System;
using System.Collections.Generic;
using System.Linq;
 
class C
{
    IEnumerable<int> F()
    {
        return null;
    }
}
";
        var src2 = @"
using System;
using System.Collections.Generic;
using System.Linq;
 
class C
{
    IEnumerable<int> F()
    {
        return from x in new[] {1,2,3}
               where x > 1
               group x by x + 1 into z
               select z.Key;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics(
            capabilities:
                EditAndContinueCapabilities.NewTypeDefinition |
                EditAndContinueCapabilities.AddStaticFieldToExistingType |
                EditAndContinueCapabilities.AddMethodToExistingType);
 
        edits.VerifySemanticDiagnostics(
            [
                Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "where", GetResource("where clause")),
                Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "group", GetResource("groupby clause")),
                Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "select", GetResource("select clause"))
            ],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void Queries_Insert_ThisOnly_Second()
    {
        var src1 = @"
using System;
using System.Collections.Generic;
using System.Linq;
 
class C
{
    int y;
 
    IEnumerable<int> F()
    {
        var f = () => y;
        return null;
    }
}
";
        var src2 = @"
using System;
using System.Collections.Generic;
using System.Linq;
 
class C
{
    int y;
 
    IEnumerable<int> F()
    {
        var f = () => y;
        return from x in new[] {1,2,3}
               where x > y
               group x by x + y into z
               select z.Key + y;
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics(
            capabilities:
                EditAndContinueCapabilities.NewTypeDefinition |
                EditAndContinueCapabilities.AddStaticFieldToExistingType |
                EditAndContinueCapabilities.AddMethodToExistingType);
 
        edits.VerifySemanticDiagnostics(
            [
                Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "where", GetResource("where clause")),
                Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "group", GetResource("groupby clause")),
                Diagnostic(RudeEditKind.InsertNotSupportedByRuntime, "select", GetResource("select clause"))
            ],
            capabilities: EditAndContinueCapabilities.Baseline);
    }
 
    [Fact]
    public void Queries_StackAlloc()
    {
        var src1 = @"
using System;
using System.Collections.Generic;
using System.Linq;
 
class C
{
    IEnumerable<int> F()
    {
        return from x in new[] {1,2,3}
               where G(stackalloc int[1]) > 1
               group G(stackalloc int[2]) by G(stackalloc int[3]) into z
               select z.Key + G(stackalloc int[4]);
    }
    
    int G(Span<int> span) => span.Length;
}";
        var src2 = @"
using System;
using System.Collections.Generic;
using System.Linq;
 
class C
{
    IEnumerable<int> F()
    {
        return from x in new[] {1,2,3}
               where G(stackalloc int[10]) > 1
               group G(stackalloc int[20]) by G(stackalloc int[30]) into z
               select z.Key + G(stackalloc int[40]);
    }
    
    int G(Span<int> span) => span.Length;
}";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            Diagnostic(RudeEditKind.StackAllocUpdate, "stackalloc int[10]", GetResource("where clause")),
            Diagnostic(RudeEditKind.StackAllocUpdate, "stackalloc int[40]", GetResource("select clause")),
            Diagnostic(RudeEditKind.StackAllocUpdate, "stackalloc int[20]", GetResource("groupby clause")),
            Diagnostic(RudeEditKind.StackAllocUpdate, "stackalloc int[30]", GetResource("groupby clause")));
    }
 
    #endregion
 
    #region Yield
 
    [Fact]
    public void Yield_Update1()
    {
        var src1 = @"
class C
{
    static IEnumerable<int> F()
    {
        yield return 1;
        yield return 2;
        yield break;
    }
}
";
        var src2 = @"
class C
{
    static IEnumerable<int> F()
    {
        yield return 3;
        yield break;
        yield return 4;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void Yield_Delete1()
    {
        var src1 = @"
yield return 1;
yield return 2;
yield return 3;
";
        var src2 = @"
yield return 1;
yield return 3;
";
 
        var bodyEdits = GetMethodEdits(src1, src2, kind: MethodKind.Iterator);
 
        bodyEdits.VerifyEdits(
            "Delete [yield return 2;]@42");
    }
 
    [Fact]
    public void Yield_Delete2()
    {
        var src1 = @"
class C
{
    static IEnumerable<int> F()
    {
        yield return 1;
        yield return 2;
        yield return 3;
    }
}
";
        var src2 = @"
class C
{
    static IEnumerable<int> F()
    {
        yield return 1;
        yield return 3;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void Yield_Insert1()
    {
        var src1 = @"
yield return 1;
yield return 3;
";
        var src2 = @"
yield return 1;
yield return 2;
yield return 3;
yield return 4;
";
 
        var bodyEdits = GetMethodEdits(src1, src2, kind: MethodKind.Iterator);
 
        bodyEdits.VerifyEdits(
            "Insert [yield return 2;]@42",
            "Insert [yield return 4;]@76");
    }
 
    [Fact]
    public void Yield_Insert2()
    {
        var src1 = @"
class C
{
    static IEnumerable<int> F()
    {
        yield return 1;
        yield return 3;
    }
}
";
        var src2 = @"
class C
{
    static IEnumerable<int> F()
    {
        yield return 1;
        yield return 2;
        yield return 3;
        yield return 4;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void Yield_Update_GenericType()
    {
        var src1 = @"
class C<T>
{
    static IEnumerable<int> F()
    {
        yield return 1;
    }
}
";
        var src2 = @"
class C<T>
{
    static IEnumerable<int> F()
    {
        yield return 2;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities:
                EditAndContinueCapabilities.GenericUpdateMethod |
                EditAndContinueCapabilities.GenericAddFieldToExistingType |
                EditAndContinueCapabilities.AddInstanceFieldToExistingType);
 
        edits.VerifySemanticDiagnostics(
            [
                Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "static IEnumerable<int> F()", GetResource("method"))
            ],
            capabilities:
                EditAndContinueCapabilities.GenericUpdateMethod |
                EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void Yield_Update_GenericMethod()
    {
        var src1 = @"
class C
{
    static IEnumerable<int> F<T>()
    {
        yield return 1;
    }
}
";
        var src2 = @"
class C
{
    static IEnumerable<int> F<T>()
    {
        yield return 2;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities:
                EditAndContinueCapabilities.GenericUpdateMethod |
                EditAndContinueCapabilities.GenericAddFieldToExistingType |
                EditAndContinueCapabilities.AddInstanceFieldToExistingType);
 
        edits.VerifySemanticDiagnostics(
            [
                Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "static IEnumerable<int> F<T>()", GetResource("method"))
            ],
            capabilities:
                EditAndContinueCapabilities.GenericUpdateMethod |
                EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void Yield_Update_GenericLocalFunction()
    {
        var src1 = @"
class C
{
    void F()
    {
        IEnumerable<int> L<T>()
        {
            yield return 1;
        }
    }
}
";
        var src2 = @"
class C
{
    void F()
    {
        IEnumerable<int> L<T>()
        {
            yield return 2;
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities:
                EditAndContinueCapabilities.GenericUpdateMethod |
                EditAndContinueCapabilities.GenericAddFieldToExistingType |
                EditAndContinueCapabilities.AddInstanceFieldToExistingType);
 
        edits.VerifySemanticDiagnostics(
            [
                Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "L", GetResource("local function"))
            ],
            capabilities:
                EditAndContinueCapabilities.GenericUpdateMethod |
                EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void MissingIteratorStateMachineAttribute()
    {
        var src1 = @"
using System.Collections.Generic;
 
class C
{
    static IEnumerable<int> F()
    {
        yield return 1;
    }
}
";
        var src2 = @"
using System.Collections.Generic;
 
class C
{
    static IEnumerable<int> F()
    {
        yield return 2;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            targetFrameworks: [TargetFramework.Mscorlib40AndSystemCore],
            diagnostics:
            [
                Diagnostic(RudeEditKind.UpdatingStateMachineMethodMissingAttribute, "static IEnumerable<int> F()", "System.Runtime.CompilerServices.IteratorStateMachineAttribute")
            ]);
    }
 
    [Fact]
    public void MissingIteratorStateMachineAttribute2()
    {
        var src1 = @"
using System.Collections.Generic;
 
class C
{
    static IEnumerable<int> F()
    {
        return null;
    }
}
";
        var src2 = @"
using System.Collections.Generic;
 
class C
{
    static IEnumerable<int> F()
    {
        yield return 2;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            targetFrameworks: [TargetFramework.Mscorlib40AndSystemCore],
            capabilities: EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.AddExplicitInterfaceImplementation);
    }
 
    #endregion
 
    #region Await
 
    /// <summary>
    /// Tests spilling detection logic of <see cref="CSharpEditAndContinueAnalyzer.ReportStateMachineSuspensionPointRudeEdits"/>.
    /// </summary>
    [Theory]
    [InlineData("await F(old);")]
    [InlineData("if (await F(1)) { Console.WriteLine(old); }")]
    [InlineData("if (await F(old)) { Console.WriteLine(1); }")]
    [InlineData("if (F(1, await F(1))) { Console.WriteLine(old); }")]
    [InlineData("if (await F(1)) { Console.WriteLine(1); }", "while (await F(1)) { Console.WriteLine(1); }")]
    [InlineData("do { Console.WriteLine(old); } while (await F(old));")]
    [InlineData("for (var x = await F(old); await G(old); await H(old)) { Console.WriteLine(old); }")]
    [InlineData("foreach (var x in await F(old)) { Console.WriteLine(old); }")]
    [InlineData("using (var x = await F(old)) { Console.WriteLine(1); }")]
    [InlineData("lock (await F(old)) { Console.WriteLine(old); }")]
    [InlineData("lock (a = await F(old)) { Console.WriteLine(old); }")]
    [InlineData("var a = await F(old), b = await G(old);")]
    [InlineData("a = await F(old);")]
    [InlineData("switch (await F(2)) { case 1: return b = await F(old); }")]
    [InlineData("return await F(old);")]
    public void AwaitSpilling_OK(string oldStatement, string newStatement = null)
    {
        var src1 = @"
class C
{
    static async Task<int> F()
    {
        " + oldStatement + @"
    }
}
";
        newStatement ??= oldStatement.Replace("old", "@new");
 
        var src2 = @"
class C
{
    static async Task<int> F()
    {
        " + newStatement + @"
    }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void AwaitSpilling_ExpressionBody()
    {
        var src1 = @"
class C
{
    static async Task<int> G() => await F(1);
}
";
        var src2 = @"
class C
{
    static async Task<int> G() => await F(2);
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    /// <summary>
    /// Tests spilling detection logic of <see cref="CSharpEditAndContinueAnalyzer.ReportStateMachineSuspensionPointRudeEdits"/>.
    /// </summary>
    [Theory]
    [InlineData("F(old, await F(1));")]
    [InlineData("F(1, await F(old));")]
    [InlineData("F(await F(old));")]
    [InlineData("await F(await F(old));")]
    [InlineData("if (F(old, await F(1))) { Console.WriteLine(1); }", new[] { "F(@new, await F(1))" })]
    [InlineData("var a = F(1, await F(old)), b = F(1, await G(old));", new[] { "var a = F(1, await F(@new)), b = F(1, await G(@new));", "var a = F(1, await F(@new)), b = F(1, await G(@new));" })]
    [InlineData("b = F(1, await F(old));")]
    [InlineData("b += await F(old);")]
    public void AwaitSpilling_Errors(string oldStatement, string[] errorMessages = null)
    {
        var src1 = @"
class C
{
    static async Task<int> F()
    {
        " + oldStatement + @"
    }
}
";
        var newStatement = oldStatement.Replace("old", "@new");
 
        var src2 = @"
class C
{
    static async Task<int> F()
    {
        " + newStatement + @"
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        // consider: these edits can be allowed if we get more sophisticated
        var expectedDiagnostics = from errorMessage in errorMessages ?? [newStatement]
                                  select Diagnostic(RudeEditKind.AwaitStatementUpdate, errorMessage);
 
        edits.VerifySemanticDiagnostics(expectedDiagnostics.ToArray());
    }
 
    [Fact]
    public void AwaitSpilling_Errors_LocalFunction()
    {
        var src1 = @"
class C
{
    static void F()
    {
        async Task<int> L()
        {
            F(old, await F(1));
        }
    }
}
";
        var src2 = @"
class C
{
    static void F()
    {
        async Task<int> L()
        {
            F(old, await F(2));
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            Diagnostic(RudeEditKind.AwaitStatementUpdate, "F(old, await F(2));"));
    }
 
    [Fact]
    public void Await_Delete1()
    {
        var src1 = @"
await F(1);
await F(2);
await F(3);
";
        var src2 = @"
await F(1);
await F(3);
";
 
        var bodyEdits = GetMethodEdits(src1, src2, kind: MethodKind.Async);
 
        bodyEdits.VerifyEdits(
            "Delete [await F(2);]@37",
            "Delete [await F(2)]@37");
    }
 
    [Fact]
    public void Await_Delete2()
    {
        var src1 = @"
class C
{
    static async Task<int> F()
    {
        await F(1);
        {
            await F(2);
        }
        await F(3);
    }
}
";
        var src2 = @"
class C
{
    static async Task<int> F()
    {
        await F(1);
        {
            F(2);
        }
        await F(3);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void Await_Delete3()
    {
        var src1 = @"
class C
{
    static async Task<int> F()
    {
        await F(await F(1));
    }
}
";
        var src2 = @"
class C
{
    static async Task<int> F()
    {
        await F(1);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void Await_Delete4()
    {
        var src1 = @"
class C
{
    static async Task<int> F() => await F(await F(1));
}
";
        var src2 = @"
class C
{
    static async Task<int> F() => await F(1);
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void Await_Delete5()
    {
        var src1 = @"
class C
{
    static async Task<int> F() => await F(1);
}
";
        var src2 = @"
class C
{
    static async Task<int> F() => F(1);
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void AwaitForEach_Delete1()
    {
        var src1 = @"
class C
{
    static async Task<int> F() 
    {
        await foreach (var x in G()) { } 
    }
}
";
        var src2 = @"
class C
{
    static async Task<int> F()
    {
        foreach (var x in G()) { } 
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void AwaitForEach_Delete2()
    {
        var src1 = @"
class C
{
    static async Task<int> F() 
    {
        await foreach (var (x, y) in G()) { } 
    }
}
";
        var src2 = @"
class C
{
    static async Task<int> F()
    {
        foreach (var (x, y) in G()) { } 
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void AwaitForEach_Delete3()
    {
        var src1 = @"
class C
{
    static async Task<int> F() 
    {
        await foreach (var x in G()) { } 
    }
}
";
        var src2 = @"
class C
{
    static async Task<int> F()
    {
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void AwaitUsing_Delete1()
    {
        var src1 = @"
class C
{
    static async Task<int> F() 
    {
        await using D x = new D(), y = new D();
    }
}
";
        var src2 = @"
class C
{
    static async Task<int> F()
    {
        await using D x = new D();
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void AwaitUsing_Delete2()
    {
        var src1 = @"
class C
{
    static async Task<int> F() 
    {
        await using D x = new D(), y = new D();
    }
}
";
        var src2 = @"
class C
{
    static async Task<int> F()
    {
        await using D y = new D();
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void AwaitUsing_Delete3()
    {
        var src1 = @"
class C
{
    static async Task<int> F() 
    {
        await using D x = new D(), y = new D();
    }
}
";
        var src2 = @"
class C
{
    static async Task<int> F()
    {
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void AwaitUsing_Delete4()
    {
        var src1 = @"
class C
{
    static async Task<int> F() 
    {
        await using D x = new D(), y = new D();
    }
}
";
        var src2 = @"
class C
{
    static async Task<int> F()
    {
        using D x = new D(), y = new D();
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void Await_Insert1()
    {
        var src1 = @"
await F(1);
await F(3);
";
        var src2 = @"
await F(1);
await F(2);
await F(3);
await F(4);
";
 
        var bodyEdits = GetMethodEdits(src1, src2, kind: MethodKind.Async);
 
        bodyEdits.VerifyEdits(
            "Insert [await F(2);]@37",
            "Insert [await F(4);]@63",
            "Insert [await F(2)]@37",
            "Insert [await F(4)]@63");
    }
 
    [Fact]
    public void Await_Insert2()
    {
        var src1 = @"
class C
{
    static async IEnumerable<int> F()
    {
        await F(1);
        await F(3);
    }
}
";
        var src2 = @"
class C
{
    static async IEnumerable<int> F()
    {
        await F(1);
        await F(2);
        await F(3);
        await F(4);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void Await_Insert3()
    {
        var src1 = @"
class C
{
    static async IEnumerable<int> F()
    {
        await F(1);
        await F(3);
    }
}
";
        var src2 = @"
class C
{
    static async IEnumerable<int> F()
    {
        await F(await F(1));
        await F(await F(2));
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            Diagnostic(RudeEditKind.AwaitStatementUpdate, "await F(await F(1));"),
            Diagnostic(RudeEditKind.AwaitStatementUpdate, "await F(await F(2));"));
    }
 
    [Fact]
    public void Await_Insert4()
    {
        var src1 = @"
class C
{
    static async Task<int> F() => await F(1);
}
";
        var src2 = @"
class C
{
    static async Task<int> F() => await F(await F(1));
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            Diagnostic(RudeEditKind.AwaitStatementUpdate, "await F(await F(1))"));
    }
 
    [Fact]
    public void Await_Insert5()
    {
        var src1 = @"
class C
{
    static Task<int> F() => F(1);
}
";
        var src2 = @"
class C
{
    static async Task<int> F() => await F(1);
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.AddExplicitInterfaceImplementation);
    }
 
    [Fact]
    public void AwaitForEach_Insert_Ok()
    {
        var src1 = @"
class C
{
    static async Task F() 
    {
        foreach (var x in G()) { } 
    }
}
";
        var src2 = @"
class C
{
    static async Task F()
    {
        await foreach (var x in G()) { } 
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void AwaitForEach_Insert()
    {
        var src1 = @"
class C
{
    static async Task<int> F() 
    {
        await Task.FromResult(1);
 
        foreach (var x in G()) { } 
    }
}
";
        var src2 = @"
class C
{
    static async Task<int> F()
    {
        await Task.FromResult(1);
 
        await foreach (var x in G()) { } 
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void AwaitUsing_Insert1()
    {
        var src1 = @"
class C
{
    static async Task<int> F() 
    {
        await using D x = new D();
    }
}
";
        var src2 = @"
class C
{
    static async Task<int> F()
    {
        await using D x = new D(), y = new D();
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void AwaitUsing_Insert2()
    {
        var src1 = @"
class C
{
    static async Task<int> F() 
    {
        await G();
        using D x = new D();
    }
}
";
        var src2 = @"
class C
{
    static async Task<int> F()
    {
        await G();
        await using D x = new D();
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void Await_Update()
    {
        var src1 = s_asyncIteratorStateMachineAttributeSource + @"
class C
{
    static async IAsyncEnumerable<int> F() 
    {
        await foreach (var x in G()) { }
        await Task.FromResult(1);
        await Task.FromResult(1);
        await Task.FromResult(1);
        yield return 1;
        yield break;
        yield break;
    }
}
";
        var src2 = s_asyncIteratorStateMachineAttributeSource + @"
class C
{
    static async IAsyncEnumerable<int> F()
    {
        await foreach (var (x,y) in G()) { }
        await foreach (var x in G()) { }
        await using D x = new D(), y = new D();
        await Task.FromResult(1);
        await Task.FromResult(1);
        yield return 1;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)],
            capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void Await_Update_GenericType()
    {
        var src1 = @"
class C<T>
{
    static async Task F()
    {
        await Task.FromResult(1);
    }
}
";
        var src2 = @"
class C<T>
{
    static async Task F()
    {
        await Task.FromResult(2);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities:
                EditAndContinueCapabilities.GenericUpdateMethod |
                EditAndContinueCapabilities.GenericAddFieldToExistingType |
                EditAndContinueCapabilities.AddInstanceFieldToExistingType);
 
        edits.VerifySemanticDiagnostics(
            [
                Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "static async Task F()", GetResource("method"))
            ],
            capabilities:
                EditAndContinueCapabilities.GenericUpdateMethod |
                EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void Await_Update_GenericMethod()
    {
        var src1 = @"
class C
{
    static async Task F<T>()
    {
        await Task.FromResult(1);
    }
}
";
        var src2 = @"
class C
{
    static async Task F<T>()
    {
        await Task.FromResult(2);
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities:
                EditAndContinueCapabilities.GenericUpdateMethod |
                EditAndContinueCapabilities.GenericAddFieldToExistingType |
                EditAndContinueCapabilities.AddInstanceFieldToExistingType);
 
        edits.VerifySemanticDiagnostics(
            [
                Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "static async Task F<T>()", GetResource("method"))
            ],
            capabilities:
                EditAndContinueCapabilities.GenericUpdateMethod |
                EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void Await_Update_GenericLocalFunction()
    {
        var src1 = @"
class C
{
    void F()
    {
        void M()
        {
            async Task L<T>()
            {
                await Task.FromResult(1);
            }
        }
    }
}
";
        var src2 = @"
class C
{
    void F()
    {
        void M()
        {
            async Task L<T>()
            {
                await Task.FromResult(2);
            }
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            capabilities:
                EditAndContinueCapabilities.GenericUpdateMethod |
                EditAndContinueCapabilities.GenericAddFieldToExistingType |
                EditAndContinueCapabilities.AddInstanceFieldToExistingType);
 
        edits.VerifySemanticDiagnostics(
            [
                Diagnostic(RudeEditKind.UpdatingGenericNotSupportedByRuntime, "L", GetResource("local function"))
            ],
            capabilities:
                EditAndContinueCapabilities.GenericUpdateMethod |
                EditAndContinueCapabilities.AddInstanceFieldToExistingType);
    }
 
    [Fact]
    public void MissingAsyncStateMachineAttribute()
    {
        var src1 = @"
using System.Threading.Tasks;
 
class C
{
    static async Task<int> F()
    {
        await new Task();
        return 1;
    }
}
";
        var src2 = @"
using System.Threading.Tasks;
 
class C
{
    static async Task<int> F()
    {
        await new Task();
        return 2;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            targetFrameworks: [TargetFramework.MinimalAsync],
            diagnostics:
            [
                Diagnostic(RudeEditKind.UpdatingStateMachineMethodMissingAttribute, "static async Task<int> F()", "System.Runtime.CompilerServices.AsyncStateMachineAttribute")
            ]);
    }
 
    [Fact]
    public void MissingAsyncStateMachineAttribute_MakeMethodAsync()
    {
        var src1 = @"
using System.Threading.Tasks;
 
class C
{
    static Task<int> F()
    {
        return null;
    }
}
";
        var src2 = @"
using System.Threading.Tasks;
 
class C
{
    static async Task<int> F()
    {
        await new Task();
        return 2;
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            targetFrameworks: [TargetFramework.MinimalAsync],
            capabilities: EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.AddExplicitInterfaceImplementation);
    }
 
    [Fact]
    public void MissingAsyncStateMachineAttribute_LocalFunction()
    {
        var src1 = @"
using System.Threading.Tasks;
 
class C
{
    void F()
    {
        async IAsyncEnumerable<int> L()
        {
            await new Task();
            yield return 1;
        }
    }
}
";
        var src2 = @"
using System.Threading.Tasks;
 
class C
{
    void F()
    {
        async IAsyncEnumerable<int> L()
        {
            await new Task();
            yield return 2;
        }
    }
}
";
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemanticDiagnostics(
            targetFrameworks: [TargetFramework.MinimalAsync],
            diagnostics:
            [
                Diagnostic(RudeEditKind.UpdatingStateMachineMethodMissingAttribute, "L", "System.Runtime.CompilerServices.AsyncIteratorStateMachineAttribute")
            ]);
    }
 
    [Fact]
    public void SemanticError_AwaitInPropertyAccessor()
    {
        var src1 = @"
using System.Threading.Tasks;
 
class C
{
   public Task<int> P
   {
       get 
       { 
           await Task.Delay(1);
           return 1;
       }
   }
}
";
        var src2 = @"
using System.Threading.Tasks;
 
class C
{
   public Task<int> P
   {
       get 
       { 
           await Task.Delay(2);
           return 1;
       }
   }
}
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemanticDiagnostics();
    }
 
    #endregion
 
    #region Out Var
 
    [Fact]
    public void OutVarType_Update()
    {
        var src1 = @"
M(out var y);
";
        var src2 = @"
M(out int y);
";
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [M(out var y);]@4 -> [M(out int y);]@4");
    }
 
    [Fact]
    public void OutVarNameAndType_Update()
    {
        var src1 = @"
M(out var y);
";
        var src2 = @"
M(out int z);
";
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [M(out var y);]@4 -> [M(out int z);]@4",
            "Update [y]@14 -> [z]@14");
    }
 
    [Fact]
    public void OutVar_Insert()
    {
        var src1 = @"
M();
";
        var src2 = @"
M(out int y);
";
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [M();]@4 -> [M(out int y);]@4",
            "Insert [y]@14");
    }
 
    [Fact]
    public void OutVar_Delete()
    {
        var src1 = @"
M(out int y);
";
 
        var src2 = @"
M();
";
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [M(out int y);]@4 -> [M();]@4",
            "Delete [y]@14");
    }
 
    #endregion
 
    #region Pattern
 
    [Fact]
    public void ConstantPattern_Update()
    {
        var src1 = @"
if ((o is null) && (y == 7)) return 3;
if (a is 7) return 5;
";
 
        var src2 = @"
if ((o1 is null) && (y == 7)) return 3;
if (a is 77) return 5;
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [if ((o is null) && (y == 7)) return 3;]@4 -> [if ((o1 is null) && (y == 7)) return 3;]@4",
            "Update [if (a is 7) return 5;]@44 -> [if (a is 77) return 5;]@45");
    }
 
    [Fact]
    public void DeclarationPattern_Update()
    {
        var src1 = @"
if (!(o is int i) && (y == 7)) return;
if (!(a is string s)) return;
if (!(b is string t)) return;
if (!(c is int j)) return;
";
 
        var src2 = @"
if (!(o1 is int i) && (y == 7)) return;
if (!(a is int s)) return;
if (!(b is string t1)) return;
if (!(c is int)) return;
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [if (!(o is int i) && (y == 7)) return;]@4 -> [if (!(o1 is int i) && (y == 7)) return;]@4",
            "Update [if (!(a is string s)) return;]@44 -> [if (!(a is int s)) return;]@45",
            "Update [if (!(c is int j)) return;]@106 -> [if (!(c is int)) return;]@105",
            "Update [t]@93 -> [t1]@91",
            "Delete [j]@121");
    }
 
    [Fact]
    public void DeclarationPattern_Reorder()
    {
        var src1 = @"if ((a is int i) && (b is int j)) { A(); }";
        var src2 = @"if ((b is int j) && (a is int i)) { A(); }";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [if ((a is int i) && (b is int j)) { A(); }]@2 -> [if ((b is int j) && (a is int i)) { A(); }]@2",
            "Reorder [j]@32 -> @16");
    }
 
    [Fact]
    public void VarPattern_Update()
    {
        var src1 = @"
if (o is (var x, var y)) return;
if (o4 is (string a, var (b, c))) return;
if (o2 is var (e, f, g)) return;
if (o3 is var (k, l, m)) return;
";
 
        var src2 = @"
if (o is (int x, int y1)) return;
if (o1 is (var a, (var b, string c1))) return;
if (o7 is var (g, e, f)) return;
if (o3 is (string k, int l2, int m)) return;
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [if (o is (var x, var y)) return;]@4 -> [if (o is (int x, int y1)) return;]@4",
            "Update [if (o4 is (string a, var (b, c))) return;]@38 -> [if (o1 is (var a, (var b, string c1))) return;]@39",
            "Update [if (o2 is var (e, f, g)) return;]@81 -> [if (o7 is var (g, e, f)) return;]@87",
            "Reorder [g]@102 -> @102",
            "Update [if (o3 is var (k, l, m)) return;]@115 -> [if (o3 is (string k, int l2, int m)) return;]@121",
            "Update [y]@25 -> [y1]@25",
            "Update [c]@67 -> [c1]@72",
            "Update [l]@133 -> [l2]@146");
    }
 
    [Fact]
    public void PositionalPattern_Update1()
    {
        var src1 = @"var r = (x, y, z) switch { (0, var b, int c) when c > 1 => 2, _ => 4 };";
        var src2 = @"var r = ((x, y, z)) switch { (_, int b1, double c1) when c1 > 2 => c1, _ => 4 };";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [(x, y, z) switch { (0, var b, int c) when c > 1 => 2, _ => 4 }]@10 -> [((x, y, z)) switch { (_, int b1, double c1) when c1 > 2 => c1, _ => 4 }]@10",
            "Update [(0, var b, int c) when c > 1 => 2]@29 -> [(_, int b1, double c1) when c1 > 2 => c1]@31",
            "Reorder [c]@44 -> @39",
            "Update [c]@44 -> [b1]@39",
            "Update [b]@37 -> [c1]@50",
            "Update [when c > 1]@47 -> [when c1 > 2]@54");
    }
 
    [Fact]
    public void PositionalPattern_Update2()
    {
        var src1 = @"var r = (x, y, z) switch { (var a, 3, 4) => a, (1, 1, Point { X: 0 } p) => 3, _ => 4 };";
 
        var src2 = @"var r = ((x, y, z)) switch { (var a1, 3, 4) => a1 * 2, (1, 1, Point { Y: 0 } p1) => 3, _ => 4 };";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [(x, y, z) switch { (var a, 3, 4) => a, (1, 1, Point { X: 0 } p) => 3, _ => 4 }]@10 -> [((x, y, z)) switch { (var a1, 3, 4) => a1 * 2, (1, 1, Point { Y: 0 } p1) => 3, _ => 4 }]@10",
            "Update [(var a, 3, 4) => a]@29 -> [(var a1, 3, 4) => a1 * 2]@31",
            "Update [(1, 1, Point { X: 0 } p) => 3]@49 -> [(1, 1, Point { Y: 0 } p1) => 3]@57",
            "Update [a]@34 -> [a1]@36",
            "Update [p]@71 -> [p1]@79");
    }
 
    [Fact]
    public void PositionalPattern_Reorder()
    {
        var src1 = @"var r = (x, y, z) switch {
(1, 2, 3) => 0,
(var a, 3, 4) => a,
(0, var b, int c) when c > 1 => 2,
(1, 1, Point { X: 0 } p) => 3,
_ => 4
};
";
 
        var src2 = @"var r = ((x, y, z)) switch {
(1, 1, Point { X: 0 } p) => 3,
(0, var b, int c) when c > 1 => 2,
(var a, 3, 4) => a,
(1, 2, 3) => 0,
_ => 4
};
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            @"Update [(x, y, z) switch {
(1, 2, 3) => 0,
(var a, 3, 4) => a,
(0, var b, int c) when c > 1 => 2,
(1, 1, Point { X: 0 } p) => 3,
_ => 4
}]@10 -> [((x, y, z)) switch {
(1, 1, Point { X: 0 } p) => 3,
(0, var b, int c) when c > 1 => 2,
(var a, 3, 4) => a,
(1, 2, 3) => 0,
_ => 4
}]@10",
            "Reorder [(var a, 3, 4) => a]@47 -> @100",
            "Reorder [(0, var b, int c) when c > 1 => 2]@68 -> @64",
            "Reorder [(1, 1, Point { X: 0 } p) => 3]@104 -> @32");
    }
 
    [Fact]
    public void PropertyPattern_Update()
    {
        var src1 = @"
if (address is { State: ""WA"" }) return 1;
if (obj is { Color: Color.Purple }) return 2;
if (o is string { Length: 5 } s) return 3;
";
 
        var src2 = @"
if (address is { ZipCode: 98052 }) return 4;
if (obj is { Size: Size.M }) return 2;
if (o is string { Length: 7 } s7) return 5;
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [if (address is { State: \"WA\" }) return 1;]@4 -> [if (address is { ZipCode: 98052 }) return 4;]@4",
            "Update [if (obj is { Color: Color.Purple }) return 2;]@47 -> [if (obj is { Size: Size.M }) return 2;]@50",
            "Update [if (o is string { Length: 5 } s) return 3;]@94 -> [if (o is string { Length: 7 } s7) return 5;]@90",
            "Update [return 1;]@36 -> [return 4;]@39",
            "Update [s]@124 -> [s7]@120",
            "Update [return 3;]@127 -> [return 5;]@124");
    }
 
    [Fact]
    public void RecursivePatterns_Reorder()
    {
        var src1 = @"var r = obj switch
{
    string s when s.Length > 0 => (s, obj1) switch
    {
        (""a"", int i) => i,
        _ => 0
    },
    int i => i * i,
    _ => -1
};
";
 
        var src2 = @"var r = obj switch
{
    int i => i * i,
    string s when s.Length > 0 => (s, obj1) switch
    {
        (""a"", int i) => i,
        _ => 0
    },
    _ => -1
};
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [int i => i * i]@140 -> @29",
            "Move [i]@102 -> @33",
            "Move [i]@144 -> @123");
    }
 
    [Fact]
    public void CasePattern_UpdateInsert()
    {
        var src1 = @"
switch(shape)
{
    case Circle c: return 1;
    default: return 4;
}
";
 
        var src2 = @"
switch(shape)
{
    case Circle c1: return 1;
    case Point p: return 0;
    default: return 4;
}
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [case Circle c: return 1;]@26 -> [case Circle c1: return 1;]@26",
            "Insert [case Point p: return 0;]@57",
            "Insert [case Point p:]@57",
            "Insert [return 0;]@71",
            "Update [c]@38 -> [c1]@38",
            "Insert [p]@68");
    }
 
    [Fact]
    public void CasePattern_UpdateDelete()
    {
        var src1 = @"
switch(shape)
{
    case Point p: return 0;
    case Circle c: A(c); break;
    default: return 4;
}
";
 
        var src2 = @"
switch(shape)
{
    case Circle c1: A(c1); break;
    default: return 4;
}
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [case Circle c: A(c); break;]@55 -> [case Circle c1: A(c1); break;]@26",
            "Update [A(c);]@70 -> [A(c1);]@42",
            "Update [c]@67 -> [c1]@38",
            "Delete [case Point p: return 0;]@26",
            "Delete [case Point p:]@26",
            "Delete [p]@37",
            "Delete [return 0;]@40");
    }
 
    [Fact]
    public void WhenCondition_Update()
    {
        var src1 = @"
switch(shape)
{
    case Circle c when (c < 10): return 1;
    case Circle c when (c > 100): return 2;
}
";
 
        var src2 = @"
switch(shape)
{
    case Circle c when (c < 5): return 1;
    case Circle c2 when (c2 > 100): return 2;
}
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [case Circle c when (c < 10): return 1;]@26 -> [case Circle c when (c < 5): return 1;]@26",
            "Update [case Circle c when (c > 100): return 2;]@70 -> [case Circle c2 when (c2 > 100): return 2;]@69",
            "Update [when (c < 10)]@40 -> [when (c < 5)]@40",
            "Update [c]@82 -> [c2]@81",
            "Update [when (c > 100)]@84 -> [when (c2 > 100)]@84");
    }
 
    [Fact]
    public void CasePatternWithWhenCondition_UpdateReorder()
    {
        var src1 = @"
switch(shape)
{
    case Rectangle r: return 0;
    case Circle c when (c.Radius < 10): return 1;
    case Circle c when (c.Radius > 100): return 2;
}
";
 
        var src2 = @"
switch(shape)
{
    case Circle c when (c.Radius > 99): return 2;
    case Circle c when (c.Radius < 10): return 1;
    case Rectangle r: return 0;
}
";
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [case Circle c when (c.Radius < 10): return 1;]@59 -> @77",
            "Reorder [case Circle c when (c.Radius > 100): return 2;]@110 -> @26",
            "Update [case Circle c when (c.Radius > 100): return 2;]@110 -> [case Circle c when (c.Radius > 99): return 2;]@26",
            "Move [c]@71 -> @38",
            "Update [when (c.Radius > 100)]@124 -> [when (c.Radius > 99)]@40",
            "Move [c]@122 -> @89");
    }
 
    #endregion
 
    #region Ref
 
    [Fact]
    public void Ref_Update()
    {
        var src1 = @"
ref int a = ref G(new int[] { 1, 2 });
ref int G(int[] p) { return ref p[1];  }
";
 
        var src2 = @"
ref int32 a = ref G1(new int[] { 1, 2 });
ref int G1(int[] p) { return ref p[2]; }
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [ref int G(int[] p) { return ref p[1];  }]@44 -> [ref int G1(int[] p) { return ref p[2]; }]@47",
            "Update [ref int a = ref G(new int[] { 1, 2 })]@4 -> [ref int32 a = ref G1(new int[] { 1, 2 })]@4",
            "Update [a = ref G(new int[] { 1, 2 })]@12 -> [a = ref G1(new int[] { 1, 2 })]@14");
    }
 
    [Fact]
    public void Ref_Insert()
    {
        var src1 = @"
int a = G(new int[] { 1, 2 });
int G(int[] p) { return p[1];  }
";
 
        var src2 = @"
ref int32 a = ref G1(new int[] { 1, 2 });
ref int G1(int[] p) { return ref p[2]; }
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [int G(int[] p) { return p[1];  }]@36 -> [ref int G1(int[] p) { return ref p[2]; }]@47",
            "Update [int a = G(new int[] { 1, 2 })]@4 -> [ref int32 a = ref G1(new int[] { 1, 2 })]@4",
            "Update [a = G(new int[] { 1, 2 })]@8 -> [a = ref G1(new int[] { 1, 2 })]@14");
    }
 
    [Fact]
    public void Ref_Delete()
    {
        var src1 = @"
ref int a = ref G(new int[] { 1, 2 });
ref int G(int[] p) { return ref p[1];  }
";
 
        var src2 = @"
int32 a = G1(new int[] { 1, 2 });
int G1(int[] p) { return p[2]; }
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [ref int G(int[] p) { return ref p[1];  }]@44 -> [int G1(int[] p) { return p[2]; }]@39",
            "Update [ref int a = ref G(new int[] { 1, 2 })]@4 -> [int32 a = G1(new int[] { 1, 2 })]@4",
            "Update [a = ref G(new int[] { 1, 2 })]@12 -> [a = G1(new int[] { 1, 2 })]@10");
    }
 
    #endregion
 
    #region Tuples
 
    [Fact]
    public void TupleType_LocalVariables()
    {
        var src1 = @"
(int a, string c) x = (a, string2);
(int a, int b) y = (3, 4);
(int a, int b, int c) z = (5, 6, 7);
";
 
        var src2 = @"
(int a, int b)  x = (a, string2);
(int a, int b, string c) z1 = (5, 6, 7);
(int a, int b) y2 = (3, 4);
";
 
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(
            "Reorder [(int a, int b, int c) z = (5, 6, 7);]@69 -> @39",
            "Update [(int a, string c) x = (a, string2)]@4 -> [(int a, int b)  x = (a, string2)]@4",
            "Update [(int a, int b, int c) z = (5, 6, 7)]@69 -> [(int a, int b, string c) z1 = (5, 6, 7)]@39",
            "Update [z = (5, 6, 7)]@91 -> [z1 = (5, 6, 7)]@64",
            "Update [y = (3, 4)]@56 -> [y2 = (3, 4)]@96");
    }
 
    [Fact]
    public void TupleElementName()
    {
        var src1 = @"class C { (int a, int b) F(); }";
        var src2 = @"class C { (int x, int b) F(); }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [(int a, int b) F();]@10 -> [(int x, int b) F();]@10");
    }
 
    [Fact]
    public void TupleInField()
    {
        var src1 = @"class C { private (int, int) _x = (1, 2); }";
        var src2 = @"class C { private (int, string) _y = (1, 2); }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [(int, int) _x = (1, 2)]@18 -> [(int, string) _y = (1, 2)]@18",
            "Update [_x = (1, 2)]@29 -> [_y = (1, 2)]@32");
    }
 
    [Fact]
    public void TupleInProperty()
    {
        var src1 = @"class C { public (int, int) Property1 { get { return (1, 2); } } }";
        var src2 = @"class C { public (int, string) Property2 { get { return (1, string.Empty); } } }";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [public (int, int) Property1 { get { return (1, 2); } }]@10 -> [public (int, string) Property2 { get { return (1, string.Empty); } }]@10",
            "Update [get { return (1, 2); }]@40 -> [get { return (1, string.Empty); }]@43");
    }
 
    [Fact]
    public void TupleInDelegate()
    {
        var src1 = @"public delegate void EventHandler1((int, int) x);";
        var src2 = @"public delegate void EventHandler2((int, int) y);";
 
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifyEdits(
            "Update [public delegate void EventHandler1((int, int) x);]@0 -> [public delegate void EventHandler2((int, int) y);]@0",
            "Update [(int, int) x]@35 -> [(int, int) y]@35");
    }
 
    #endregion
 
    #region With Expressions
 
    [Fact]
    public void WithExpression_PropertyAdd()
    {
        var src1 = @"var x = y with { X = 1 };";
        var src2 = @"var x = y with { X = 1, Y = 2 };";
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(@"Update [x = y with { X = 1 }]@6 -> [x = y with { X = 1, Y = 2 }]@6");
    }
 
    [Fact]
    public void WithExpression_PropertyDelete()
    {
        var src1 = @"var x = y with { X = 1, Y = 2 };";
        var src2 = @"var x = y with { X = 1 };";
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(@"Update [x = y with { X = 1, Y = 2 }]@6 -> [x = y with { X = 1 }]@6");
    }
 
    [Fact]
    public void WithExpression_PropertyChange()
    {
        var src1 = @"var x = y with { X = 1 };";
        var src2 = @"var x = y with { Y = 1 };";
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(@"Update [x = y with { X = 1 }]@6 -> [x = y with { Y = 1 }]@6");
    }
 
    [Fact]
    public void WithExpression_PropertyValueChange()
    {
        var src1 = @"var x = y with { X = 1, Y = 1 };";
        var src2 = @"var x = y with { X = 1, Y = 2 };";
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(@"Update [x = y with { X = 1, Y = 1 }]@6 -> [x = y with { X = 1, Y = 2 }]@6");
    }
 
    [Fact]
    public void WithExpression_PropertyValueReorder()
    {
        var src1 = @"var x = y with { X = 1, Y = 1 };";
        var src2 = @"var x = y with { Y = 1, X = 1 };";
        var edits = GetMethodEdits(src1, src2);
 
        edits.VerifyEdits(@"Update [x = y with { X = 1, Y = 1 }]@6 -> [x = y with { Y = 1, X = 1 }]@6");
    }
 
    #endregion
 
    #region Top Level Statements
 
    [Fact]
    public void TopLevelStatement_Lambda_Update()
    {
        var src1 = @"
using System;
 
var x = new Func<int>(() => 1);
";
        var src2 = @"
using System;
 
var x = new Func<int>(() => 2);
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.<Main>$"), preserveLocalVariables: true)]);
    }
 
    [Fact]
    public void TopLevelStatement_Lambda_Insert()
    {
        var src1 = @"
using System;
 
Console.WriteLine(1);
";
        var src2 = @"
using System;
 
Console.WriteLine(1);
var x = new Func<int>(() => 2);
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.<Main>$"), preserveLocalVariables: true)],
            [Diagnostic(RudeEditKind.UpdateMightNotHaveAnyEffect, "Console.WriteLine(1);", GetResource("top-level code"))],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddStaticFieldToExistingType | EditAndContinueCapabilities.NewTypeDefinition);
    }
 
    [Fact]
    public void TopLevelStatement_Capture_Args()
    {
        var src1 = @"
using System;
 
var x = new Func<string[]>(() => null);
";
        var src2 = @"
using System;
 
var x = new Func<string[]>(() => args);
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.<Main>$"), preserveLocalVariables: true)]);
    }
 
    [Fact]
    public void TopLevelStatement_CeaseCapture_Args()
    {
        var src1 = @"
using System;
 
var x = new Func<string[]>(() => args);
";
        var src2 = @"
using System;
 
var x = new Func<string[]>(() => null);
";
        var edits = GetTopEdits(src1, src2);
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.<Main>$"), preserveLocalVariables: true));
    }
 
    [Fact]
    public void TopLevelStatement_CeaseCapture_Args_Closure()
    {
        var src1 = @"
using System;
 
var f1 = new Func<int, int>(a1 => 
{
    var f2 = new Func<int, int>(a2 => args.Length + a2);
    return a1;
});
";
        var src2 = @"
using System;
 
var f1 = new Func<int, int>(a1 => 
{
    var f2 = new Func<int, int>(a2 => a2);
    return a1 + args.Length;
});
";
        var edits = GetTopEdits(src1, src2);
 
        // y is no longer captured in f2
        edits.VerifySemantics(
            SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.<Main>$"), preserveLocalVariables: true));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")]
    public void TopLevelStatement_InsertMultiScopeCapture()
    {
        var src1 = """
        using System;
 
        foreach (int x0 in new[] { 1 })  // Group #0
        {                                // Group #1
            int x1 = 0;
 
            int f0(int a) => x0;
            int f1(int a) => x1;
        }
        """;
 
        var src2 = """
        using System;
 
        foreach (int x0 in new[] { 1 })  // Group #0
        {                                // Group #1
            int x1 = 0;
 
            int f0(int a) => x0;
            int f1(int a) => x1;
 
            int f2(int a) => x0 + x1;   // runtime rude edit: connecting previously disconnected closures
        }
        """;
        var edits = GetTopEdits(src1, src2);
 
        edits.VerifySemantics(
            [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.<Main>$"), preserveLocalVariables: true)],
            [Diagnostic(RudeEditKind.UpdateMightNotHaveAnyEffect, """
                foreach (int x0 in new[] { 1 })  // Group #0
                {                                // Group #1
                    int x1 = 0;
 
                    int f0(int a) => x0;
                    int f1(int a) => x1;
 
                    int f2(int a) => x0 + x1;   // runtime rude edit: connecting previously disconnected closures
                }
                """, GetResource("top-level code"))],
            capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.UpdateParameters);
    }
 
    #endregion
}