File: ConvertForEachToFor\ConvertForEachToForTests.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.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.ConvertForEachToFor;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings;
using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ConvertForEachToFor;
 
[Trait(Traits.Feature, Traits.Features.CodeActionsConvertForEachToFor)]
public partial class ConvertForEachToForTests : AbstractCSharpCodeActionTest_NoEditor
{
    protected override CodeRefactoringProvider CreateCodeRefactoringProvider(TestWorkspace workspace, TestParameters parameters)
        => new CSharpConvertForEachToForCodeRefactoringProvider();
 
    private readonly CodeStyleOption2<bool> onWithSilent = new CodeStyleOption2<bool>(true, NotificationOption2.Silent);
 
    private OptionsCollection ImplicitTypeEverywhere
        => new(GetLanguage())
        {
            { CSharpCodeStyleOptions.VarElsewhere, onWithSilent },
            { CSharpCodeStyleOptions.VarWhenTypeIsApparent, onWithSilent },
            { CSharpCodeStyleOptions.VarForBuiltInTypes, onWithSilent },
        };
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31621")]
    public async Task EmptyBlockBody()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach[||](var a in array)
                    {
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        int a = array[i];
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task EmptyBody()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach[||](var a in array) ;
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++) ;
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task Body()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach[||](var a in array) Console.WriteLine(a);
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        int a = array[i];
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task BlockBody()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach[||](var a in array)
                    {
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        int a = array[i];
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31621")]
    public async Task Comment()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    /* comment */
                    foreach[||](var a in array) /* comment */
                    {
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    /* comment */
                    for (int {|Rename:i|} = 0; i < array.Length; i++) /* comment */
                    {
                        int a = array[i];
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31621")]
    public async Task Comment2()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach[||](var a in array)
                    /* comment */
                    {
                    }/* comment */
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    /* comment */
                    {
                        int a = array[i];
                    }/* comment */
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task Comment3()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach[||](var a in array) /* comment */;
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++) /* comment */;
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task Comment4()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach[||](var a in array) Console.WriteLine(a); // test
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        int a = array[i];
                        Console.WriteLine(a); // test
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task Comment5()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach [||] (var a in array) /* test */ Console.WriteLine(a); 
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++) /* test */
                    {
                        int a = array[i];
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task Comment6()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach [||] (var a in array) 
                        /* test */ Console.WriteLine(a); 
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        int a = array[i];
                        /* test */
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31621")]
    public async Task Comment7()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    // test
                    foreach[||](var a in new int[] { 1, 3, 4 })
                    {
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    // test
                    int[] {|Rename:array|} = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        int a = array[i];
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task TestCommentsInTheMiddleOfParentheses()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach [||] (var a /* test */ in array) ;
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++) ;
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task TestCommentsAtBeginningOfParentheses()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach [||] (/* test */ var a in array) ;
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++) ;
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task TestCommentsAtTheEndOfParentheses()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach [||] (var a in array /* test */) ;
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++) ;
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task CollectionStatement()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    foreach[||](var a in new int[] { 1, 3, 4 })
                    {
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    int[] {|Rename:array|} = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        int a = array[i];
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task CollectionConflict()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = 1;
 
                    foreach[||](var a in new int[] { 1, 3, 4 })
                    {
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = 1;
 
                    int[] {|Rename:array1|} = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array1.Length; i++)
                    {
                        int a = array1[i];
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task VariableWritten()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new[] { 1 };
                    foreach [||] (var a in array)
                    {
                        a = 1;
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new[] { 1 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        {|Warning:int a = array[i];|}
                        a = 1;
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task IndexConflict()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach [||] (var a in array)
                    {
                        int i = 0;
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i1|} = 0; i1 < array.Length; i1++)
                    {
                        int a = array[i1];
                        int i = 0;
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task StructPropertyReadFromAndDiscarded()
    {
        var text = """
            class Test
            {
                struct Struct
                {
                    public string Property { get; }
                }
 
                void Method()
                {
                    var array = new[] { new Struct() };
                    foreach [||] (var a in array)
                    {
                        _ = a.Property;
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                struct Struct
                {
                    public string Property { get; }
                }
 
                void Method()
                {
                    var array = new[] { new Struct() };
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        Struct a = array[i];
                        _ = a.Property;
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task StructPropertyReadFromAndAssignedToLocal()
    {
        var text = """
            class Test
            {
                struct Struct
                {
                    public string Property { get; }
                }
 
                void Method()
                {
                    var array = new[] { new Struct() };
                    foreach [||] (var a in array)
                    {
                        var b = a.Property;
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                struct Struct
                {
                    public string Property { get; }
                }
 
                void Method()
                {
                    var array = new[] { new Struct() };
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        Struct a = array[i];
                        var b = a.Property;
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task WrongCaretPosition()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach (var a in array)
                    {
                        [||] 
                    }
                }
            }
            """;
        await TestMissingInRegularAndScriptAsync(text);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    [WorkItem("https://github.com/dotnet/roslyn/issues/31621")]
    public async Task TestCaretBefore()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    [||] foreach(var a in array)
                    {
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        int a = array[i];
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    [WorkItem("https://github.com/dotnet/roslyn/issues/31621")]
    public async Task TestCaretAfter()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach(var a in array) [||]
                    {
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++) 
                    {
                        int a = array[i];
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    [WorkItem("https://github.com/dotnet/roslyn/issues/31621")]
    public async Task TestSelection()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    [|foreach(var a in array)
                    {
                    }|]
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        int a = array[i];
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31621")]
    public async Task Field()
    {
        var text = """
            class Test
            {
                int[] array = new int[] { 1, 3, 4 };
 
                void Method()
                {
                    foreach [||] (var a in array)
                    {
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                int[] array = new int[] { 1, 3, 4 };
 
                void Method()
                {
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        int a = array[i];
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task ArrayElement()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[][] { new int[] { 1, 3, 4 } };
                    foreach [||] (var a in array[0])
                    {
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[][] { new int[] { 1, 3, 4 } };
                    for (int {|Rename:i|} = 0; i < array[0].Length; i++)
                    {
                        int a = array[0][i];
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31621")]
    public async Task Parameter()
    {
        var text = """
            class Test
            {
                void Method(int[] array)
                {
                    foreach [||] (var a in array)
                    {
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method(int[] array)
                {
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        int a = array[i];
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31621")]
    public async Task Property()
    {
        var text = """
            class Test
            {
                int [] Prop { get; } = new int[] { 1, 2, 3 };
 
                void Method()
                {
                    foreach [||] (var a in Prop)
                    {
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                int [] Prop { get; } = new int[] { 1, 2, 3 };
 
                void Method()
                {
                    for (int {|Rename:i|} = 0; i < Prop.Length; i++)
                    {
                        int a = Prop[i];
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task Interface()
    {
        var text = """
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var array = (IList<int>)(new int[] { 1, 3, 4 });
                    foreach[||] (var a in array)
                    {
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        var expected = """
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var array = (IList<int>)(new int[] { 1, 3, 4 });
                    for (int {|Rename:i|} = 0; i < array.Count; i++)
                    {
                        int a = array[i];
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task IListOfT()
    {
        var text = """
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var list = new List<int>();
                    foreach [||](var a in list)
                    {
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        var expected = """
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var list = new List<int>();
                    for (int {|Rename:i|} = 0; i < list.Count; i++)
                    {
                        int a = list[i];
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task IReadOnlyListOfT()
    {
        var text = """
            using System.Collections;
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var list = new ReadOnly<int>();
                    foreach [||](var a in list)
                    {
                        Console.WriteLine(a);
                    }
 
                }
            }
 
            class ReadOnly<T> : IReadOnlyList<T>
            {
                public T this[int index] => throw new System.NotImplementedException();
                public int Count => throw new System.NotImplementedException();
                public IEnumerator<T> GetEnumerator() => throw new System.NotImplementedException();
                IEnumerator IEnumerable.GetEnumerator() => throw new System.NotImplementedException();
            }
            """;
        var expected = """
            using System.Collections;
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var list = new ReadOnly<int>();
                    for (int {|Rename:i|} = 0; i < list.Count; i++)
                    {
                        int a = list[i];
                        Console.WriteLine(a);
                    }
 
                }
            }
 
            class ReadOnly<T> : IReadOnlyList<T>
            {
                public T this[int index] => throw new System.NotImplementedException();
                public int Count => throw new System.NotImplementedException();
                public IEnumerator<T> GetEnumerator() => throw new System.NotImplementedException();
                IEnumerator IEnumerable.GetEnumerator() => throw new System.NotImplementedException();
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task IList()
    {
        var text = """
            using System;
            using System.Collections;
 
            class Test
            {
                void Method()
                {
                    var list = new List();
                    foreach [||](var a in list)
                    {
                        Console.WriteLine(a);
                    }
 
                }
            }
 
            class List : IList
            {
                public object this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
                public bool IsReadOnly => throw new NotImplementedException();
                public bool IsFixedSize => throw new NotImplementedException();
                public int Count => throw new NotImplementedException();
                public object SyncRoot => throw new NotImplementedException();
                public bool IsSynchronized => throw new NotImplementedException();
                public int Add(object value) => throw new NotImplementedException();
                public void Clear() => throw new NotImplementedException();
                public bool Contains(object value) => throw new NotImplementedException();
                public void CopyTo(Array array, int index) => throw new NotImplementedException();
                public IEnumerator GetEnumerator() => throw new NotImplementedException();
                public int IndexOf(object value) => throw new NotImplementedException();
                public void Insert(int index, object value) => throw new NotImplementedException();
                public void Remove(object value) => throw new NotImplementedException();
                public void RemoveAt(int index) => throw new NotImplementedException();
            }
            """;
        var expected = """
            using System;
            using System.Collections;
 
            class Test
            {
                void Method()
                {
                    var list = new List();
                    for (int {|Rename:i|} = 0; i < list.Count; i++)
                    {
                        object a = list[i];
                        Console.WriteLine(a);
                    }
 
                }
            }
 
            class List : IList
            {
                public object this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
                public bool IsReadOnly => throw new NotImplementedException();
                public bool IsFixedSize => throw new NotImplementedException();
                public int Count => throw new NotImplementedException();
                public object SyncRoot => throw new NotImplementedException();
                public bool IsSynchronized => throw new NotImplementedException();
                public int Add(object value) => throw new NotImplementedException();
                public void Clear() => throw new NotImplementedException();
                public bool Contains(object value) => throw new NotImplementedException();
                public void CopyTo(Array array, int index) => throw new NotImplementedException();
                public IEnumerator GetEnumerator() => throw new NotImplementedException();
                public int IndexOf(object value) => throw new NotImplementedException();
                public void Insert(int index, object value) => throw new NotImplementedException();
                public void Remove(object value) => throw new NotImplementedException();
                public void RemoveAt(int index) => throw new NotImplementedException();
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact(Skip = "https://github.com/dotnet/roslyn/issues/29740")]
    public async Task ImmutableArray()
    {
        var text = """
            <Workspace>
                <Project Language="C#" AssemblyName="Assembly1" CommonReferences="true">
                <MetadataReference>
            """ + typeof(ImmutableArray<>).Assembly.Location + """
            </MetadataReference>
                    <Document>
            using System;
            using System.Collections.Immutable;
 
            class Test
            {
                void Method()
                {
                    var list = ImmutableArray.Create(1);
                    foreach [||](var a in list)
                    {
                        Console.WriteLine(a);
                    }
                }
            }</Document>
                </Project>
            </Workspace>
            """;
 
        var expected = """
            using System;
            using System.Collections.Immutable;
 
            class Test
            {
                void Method()
                {
                    var list = ImmutableArray.Create(1);
                    for (int {|Rename:i|} = 0; i < list.Length; i++)
                    {
                        int a = list[i];
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task ExplicitInterface()
    {
        var text = """
            using System;
            using System.Collections;
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var list = new Explicit();
                    foreach [||] (var a in list)
                    {
                        Console.WriteLine(a);
                    }
                }
            }
 
            class Explicit : IReadOnlyList<int>
            {
                int IReadOnlyList<int>.this[int index] => throw new NotImplementedException();
                int IReadOnlyCollection<int>.Count => throw new NotImplementedException();
                IEnumerator<int> IEnumerable<int>.GetEnumerator() => throw new NotImplementedException();
                IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
            }
            """;
 
        var expected = """
            using System;
            using System.Collections;
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var list = new Explicit();
                    IReadOnlyList<int> {|Rename:list1|} = list;
                    for (int {|Rename:i|} = 0; i < list1.Count; i++)
                    {
                        int a = list1[i];
                        Console.WriteLine(a);
                    }
                }
            }
 
            class Explicit : IReadOnlyList<int>
            {
                int IReadOnlyList<int>.this[int index] => throw new NotImplementedException();
                int IReadOnlyCollection<int>.Count => throw new NotImplementedException();
                IEnumerator<int> IEnumerable<int>.GetEnumerator() => throw new NotImplementedException();
                IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task DoubleExplicitInterface()
    {
        var text = """
            using System;
            using System.Collections;
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var list = new Explicit();
                    foreach [||] (var a in list)
                    {
                        Console.WriteLine(a);
                    }
                }
            }
 
            class Explicit : IReadOnlyList<int>, IReadOnlyList<string>
            {
                int IReadOnlyList<int>.this[int index] => throw new NotImplementedException();
                int IReadOnlyCollection<int>.Count => throw new NotImplementedException();
                IEnumerator<int> IEnumerable<int>.GetEnumerator() => throw new NotImplementedException();
                IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
 
                string IReadOnlyList<string>.this[int index] => throw new NotImplementedException();
                int IReadOnlyCollection<string>.Count => throw new NotImplementedException();
                IEnumerator<string> IEnumerable<string>.GetEnumerator() => throw new NotImplementedException();
            }
            """;
        await TestMissingInRegularAndScriptAsync(text);
    }
 
    [Fact]
    public async Task DoubleExplicitInterfaceWithExplicitType()
    {
        var text = """
            using System;
            using System.Collections;
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var list = new Explicit();
                    foreach [||] (int a in list)
                    {
                        Console.WriteLine(a);
                    }
                }
            }
 
            class Explicit : IReadOnlyList<int>, IReadOnlyList<string>
            {
                int IReadOnlyList<int>.this[int index] => throw new NotImplementedException();
                int IReadOnlyCollection<int>.Count => throw new NotImplementedException();
                IEnumerator<int> IEnumerable<int>.GetEnumerator() => throw new NotImplementedException();
                IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
 
                string IReadOnlyList<string>.this[int index] => throw new NotImplementedException();
                int IReadOnlyCollection<string>.Count => throw new NotImplementedException();
                IEnumerator<string> IEnumerable<string>.GetEnumerator() => throw new NotImplementedException();
            }
            """;
 
        var expected = """
            using System;
            using System.Collections;
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var list = new Explicit();
                    IReadOnlyList<int> {|Rename:list1|} = list;
                    for (int {|Rename:i|} = 0; i < list1.Count; i++)
                    {
                        int a = list1[i];
                        Console.WriteLine(a);
                    }
                }
            }
 
            class Explicit : IReadOnlyList<int>, IReadOnlyList<string>
            {
                int IReadOnlyList<int>.this[int index] => throw new NotImplementedException();
                int IReadOnlyCollection<int>.Count => throw new NotImplementedException();
                IEnumerator<int> IEnumerable<int>.GetEnumerator() => throw new NotImplementedException();
                IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
 
                string IReadOnlyList<string>.this[int index] => throw new NotImplementedException();
                int IReadOnlyCollection<string>.Count => throw new NotImplementedException();
                IEnumerator<string> IEnumerable<string>.GetEnumerator() => throw new NotImplementedException();
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task MixedInterfaceImplementation()
    {
        var text = """
            using System;
            using System.Collections;
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var list = new Mixed();
                    foreach [||] (var a in list)
                    {
                        Console.WriteLine(a);
                    }
                }
            }
 
            class Mixed : IReadOnlyList<int>, IReadOnlyList<string>
            {
                public int this[int index] => throw new NotImplementedException();
                public int Count => throw new NotImplementedException();
                public IEnumerator<int> GetEnumerator() => throw new NotImplementedException();
                IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
 
                string IReadOnlyList<string>.this[int index] => throw new NotImplementedException();
                int IReadOnlyCollection<string>.Count => throw new NotImplementedException();
                IEnumerator<string> IEnumerable<string>.GetEnumerator() => throw new NotImplementedException();
            }
            """;
 
        var expected = """
            using System;
            using System.Collections;
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var list = new Mixed();
                    for (int {|Rename:i|} = 0; i < list.Count; i++)
                    {
                        int a = list[i];
                        Console.WriteLine(a);
                    }
                }
            }
 
            class Mixed : IReadOnlyList<int>, IReadOnlyList<string>
            {
                public int this[int index] => throw new NotImplementedException();
                public int Count => throw new NotImplementedException();
                public IEnumerator<int> GetEnumerator() => throw new NotImplementedException();
                IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
 
                string IReadOnlyList<string>.this[int index] => throw new NotImplementedException();
                int IReadOnlyCollection<string>.Count => throw new NotImplementedException();
                IEnumerator<string> IEnumerable<string>.GetEnumerator() => throw new NotImplementedException();
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task MixedInterfaceImplementationWithExplicitType()
    {
        var text = """
            using System;
            using System.Collections;
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var list = new Mixed();
                    foreach [||] (string a in list)
                    {
                        Console.WriteLine(a);
                    }
                }
            }
 
            class Mixed : IReadOnlyList<int>, IReadOnlyList<string>
            {
                public int this[int index] => throw new NotImplementedException();
                public int Count => throw new NotImplementedException();
                public IEnumerator<int> GetEnumerator() => throw new NotImplementedException();
                IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
 
                string IReadOnlyList<string>.this[int index] => throw new NotImplementedException();
                int IReadOnlyCollection<string>.Count => throw new NotImplementedException();
                IEnumerator<string> IEnumerable<string>.GetEnumerator() => throw new NotImplementedException();
            }
            """;
 
        var expected = """
            using System;
            using System.Collections;
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var list = new Mixed();
                    IReadOnlyList<string> {|Rename:list1|} = list;
                    for (int {|Rename:i|} = 0; i < list1.Count; i++)
                    {
                        string a = list1[i];
                        Console.WriteLine(a);
                    }
                }
            }
 
            class Mixed : IReadOnlyList<int>, IReadOnlyList<string>
            {
                public int this[int index] => throw new NotImplementedException();
                public int Count => throw new NotImplementedException();
                public IEnumerator<int> GetEnumerator() => throw new NotImplementedException();
                IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
 
                string IReadOnlyList<string>.this[int index] => throw new NotImplementedException();
                int IReadOnlyCollection<string>.Count => throw new NotImplementedException();
                IEnumerator<string> IEnumerable<string>.GetEnumerator() => throw new NotImplementedException();
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task PreserveUserExpression()
    {
        var text = """
            using System;
            using System.Collections;
            using System.Collections.Generic;
 
            namespace NS
            {
                class Test
                {
                    void Method()
                    {
                        foreach [||] (string a in new NS.Mixed())
                        {
                            Console.WriteLine(a);
                        }
                    }
                }
 
                class Mixed : IReadOnlyList<int>, IReadOnlyList<string>
                {
                    public int this[int index] => throw new NotImplementedException();
                    public int Count => throw new NotImplementedException();
                    public IEnumerator<int> GetEnumerator() => throw new NotImplementedException();
                    IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
 
                    string IReadOnlyList<string>.this[int index] => throw new NotImplementedException();
                    int IReadOnlyCollection<string>.Count => throw new NotImplementedException();
                    IEnumerator<string> IEnumerable<string>.GetEnumerator() => throw new NotImplementedException();
                }
            }
            """;
 
        var expected = """
            using System;
            using System.Collections;
            using System.Collections.Generic;
 
            namespace NS
            {
                class Test
                {
                    void Method()
                    {
                        IReadOnlyList<string> {|Rename:list|} = new NS.Mixed();
                        for (int {|Rename:i|} = 0; i < list.Count; i++)
                        {
                            string a = list[i];
                            Console.WriteLine(a);
                        }
                    }
                }
 
                class Mixed : IReadOnlyList<int>, IReadOnlyList<string>
                {
                    public int this[int index] => throw new NotImplementedException();
                    public int Count => throw new NotImplementedException();
                    public IEnumerator<int> GetEnumerator() => throw new NotImplementedException();
                    IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
 
                    string IReadOnlyList<string>.this[int index] => throw new NotImplementedException();
                    int IReadOnlyCollection<string>.Count => throw new NotImplementedException();
                    IEnumerator<string> IEnumerable<string>.GetEnumerator() => throw new NotImplementedException();
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task EmbededStatement()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    if (true)
                        foreach [||] (var a in new int[] {});
                }
            }
            """;
        await TestMissingInRegularAndScriptAsync(text);
    }
 
    [Fact]
    public async Task EmbededStatement2()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    if (true)
                        foreach [||] (var a in array) Console.WriteLine(a);
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    if (true)
                        for (int {|Rename:i|} = 0; i < array.Length; i++)
                        {
                            int a = array[i];
                            Console.WriteLine(a);
                        }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task IndexConflict2()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach [||] (var i in array)
                    {
                        Console.WriteLine(i);
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i1|} = 0; i1 < array.Length; i1++)
                    {
                        int i = array[i1];
                        Console.WriteLine(i);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task UseTypeAsUsedInForeach()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    foreach [||] (int a in array)
                    {
                        Console.WriteLine(i);
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 3, 4 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        int a = array[i];
                        Console.WriteLine(i);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task String()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    foreach [||] (var a in "test")
                    {
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    string {|Rename:str|} = "test";
                    for (int {|Rename:i|} = 0; i < str.Length; i++)
                    {
                        char a = str[i];
                        Console.WriteLine(a);
                    }
                }
            }
            """;
 
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task StringLocalConst()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    const string test = "test";
                    foreach [||] (var a in test)
                    {
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    const string test = "test";
                    for (int {|Rename:i|} = 0; i < test.Length; i++)
                    {
                        char a = test[i];
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task StringConst()
    {
        var text = """
            class Test
            {
                const string test = "test";
 
                void Method()
                {
                    foreach [||] (var a in test)
                    {
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                const string test = "test";
 
                void Method()
                {
                    for (int {|Rename:i|} = 0; i < test.Length; i++)
                    {
                        char a = test[i];
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task ElementExplicitCast()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new object[] { 1, 2, 3 };
                    foreach [||] (string a in array)
                    {
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var array = new object[] { 1, 2, 3 };
                    for (int {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        string a = (string)array[i];
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/50469")]
    public async Task PreventExplicitCastToVar()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var items = new[] { new { x = 1 } };
 
                    foreach [||] (var item in items)
                    {
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var items = new[] { new { x = 1 } };
 
                    for (int {|Rename:i|} = 0; i < items.Length; i++)
                    {
                        var item = items[i];
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task NotAssignable()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 2, 3 };
                    foreach [||] (string a in array)
                    {
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestMissingInRegularAndScriptAsync(text);
    }
 
    [Fact]
    public async Task ElementMissing()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var array = new int[] { 1, 2, 3 };
                    foreach [||] (in array)
                    {
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestMissingInRegularAndScriptAsync(text);
    }
 
    [Fact]
    public async Task ElementMissing2()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    foreach [||] (string a in )
                    {
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestMissingInRegularAndScriptAsync(text);
    }
 
    [Fact]
    public async Task StringExplicitType()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    foreach [||] (int a in "test")
                    {
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    string {|Rename:str|} = "test";
                    for (int {|Rename:i|} = 0; i < str.Length; i++)
                    {
                        int a = str[i];
                        Console.WriteLine(a);
                    }
                }
            }
            """;
 
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task Var()
    {
        var text = """
            using System;
            using System.Collections;
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var list = new Explicit();
                    foreach [||] (var a in list)
                    {
                        Console.WriteLine(a);
                    }
                }
            }
 
            class Explicit : IReadOnlyList<int>
            {
                int IReadOnlyList<int>.this[int index] => throw new NotImplementedException();
                int IReadOnlyCollection<int>.Count => throw new NotImplementedException();
                IEnumerator<int> IEnumerable<int>.GetEnumerator() => throw new NotImplementedException();
                IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
            }
            """;
 
        var expected = """
            using System;
            using System.Collections;
            using System.Collections.Generic;
 
            class Test
            {
                void Method()
                {
                    var list = new Explicit();
                    var {|Rename:list1|} = (IReadOnlyList<int>)list;
                    for (var {|Rename:i|} = 0; i < list1.Count; i++)
                    {
                        var a = list1[i];
                        Console.WriteLine(a);
                    }
                }
            }
 
            class Explicit : IReadOnlyList<int>
            {
                int IReadOnlyList<int>.this[int index] => throw new NotImplementedException();
                int IReadOnlyCollection<int>.Count => throw new NotImplementedException();
                IEnumerator<int> IEnumerable<int>.GetEnumerator() => throw new NotImplementedException();
                IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
            }
            """;
        await TestInRegularAndScriptAsync(text, expected, options: ImplicitTypeEverywhere);
    }
 
    [Fact]
    public async Task ArrayRank2()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    foreach [||] (int a in new int[,] { {1, 2} })
                    {
                        Console.WriteLine(a);
                    }
                }
            }
            """;
        await TestMissingAsync(text);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/48950")]
    public async Task NullableReferenceVar()
    {
        var text = """
            #nullable enable
            class Test
            {
                void Method()
                {
                    foreach [||] (var s in new string[10])
                    {
                        Console.WriteLine(s);
                    }
                }
            }
            """;
        var expected = """
            #nullable enable
            class Test
            {
                void Method()
                {
                    var {|Rename:array|} = new string[10];
                    for (var {|Rename:i|} = 0; i < array.Length; i++)
                    {
                        var s = array[i];
                        Console.WriteLine(s);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected, options: ImplicitTypeEverywhere);
    }
}