// 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.Threading.Tasks;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;

namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.AddExplicitCast
{
    public partial class AddExplicitCastTests
    {
        #region "Fix all occurrences tests"

        [Fact]
        [Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
        [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
        public async Task CS0266TestFixAllInDocument()
        {
            var input = @"
<Workspace>
    <Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
        <Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

public class Program1
{
    class Base { }
    class Derived : Base { }

    class Test
    {
        private Derived d;
        private Base b;
        public Derived D { get => d; set => d = value; }
        public Base B { get => b; set => b = value; }
    }

    Base ReturnBase()
    {
        Base b = new Base();
        return b;
    }

    Base ReturnBase(Derived d)
    {
        Base b = new Base();
        return b;
    }

    Derived ReturnDerived(Base b)
    {
        return b;
    }

    <![CDATA[ IEnumerable<Derived> ReturnDerived() ]]>
    {
        Base b;
        yield return b;
    }

    <![CDATA[ IEnumerable<Derived> ReturnDerived()
    {
        Base b;
        return b;
    } ]]>

    <![CDATA[ async Task<Derived> M() ]]>
    {
        Base b;
        return b;
    }

    Derived ReturnDerived2(Base b)
    {
        return ReturnBase();
    }

    Derived Foo()
    {
        <![CDATA[ Func<Base, Base> func = d => d; ]]>
        Base b;
        return func(b);
    }
    public Program1()
    {
        Base b;
        Derived d = {|FixAllInDocument:b|};
        d = new Base() { };

        Derived d2 = ReturnBase();
        Derived d2 = ReturnBase(b);

        Test t = new Test();
        t.D = b;
        t.d = b;
        d = t.B;

        <![CDATA[ Func<Base, Derived> foo = d => d; ]]>

        <![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
        d2 = foo2(d);
    }
}
        </Document>
        <Document>
public class Program2
{
    interface Base1 { }
    interface Base2 : Base1 { }
    interface Base3 { }
    class Derived1 : Base2, Base3 { }
    class Derived2 : Derived1 { }

    class Test
    {
        static public explicit operator Derived2(Test t) { return new Derived2();  }
    }

     Derived2 returnDerived2_1() {
        return new Derived1();
    }

     Derived2 returnDerived2_2() {
        return new Test();
    }

    private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
    {
        Derived2 derived2 = b1;
        derived2 = b3;
        Base2 base2 = b1;
        derived2 = d1;
        Derived2 d2 = new Test();
    }
}
        </Document>
    </Project>
    <Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
        <Document>
public class Program3
{
    class Base { }
    class Derived : Base { }
    class Derived2 : Derived { }

    Derived2 returnD2(Base b)
    {
        Derived d;
        return d = b;
    }
}
        </Document>
    </Project>
</Workspace>";

            var expected = @"
<Workspace>
    <Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
        <Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

public class Program1
{
    class Base { }
    class Derived : Base { }

    class Test
    {
        private Derived d;
        private Base b;
        public Derived D { get => d; set => d = value; }
        public Base B { get => b; set => b = value; }
    }

    Base ReturnBase()
    {
        Base b = new Base();
        return b;
    }

    Base ReturnBase(Derived d)
    {
        Base b = new Base();
        return b;
    }

    Derived ReturnDerived(Base b)
    {
        return (Derived)b;
    }

    <![CDATA[ IEnumerable<Derived> ReturnDerived() ]]>
    {
        Base b;
        yield return (Derived)b;
    }

    <![CDATA[ IEnumerable<Derived> ReturnDerived()
    {
        Base b;
        return (IEnumerable<Derived>)b;
    } ]]>

    <![CDATA[ async Task<Derived> M() ]]>
    {
        Base b;
        return (Derived)b;
    }

    Derived ReturnDerived2(Base b)
    {
        return (Derived)ReturnBase();
    }

    Derived Foo()
    {
        <![CDATA[ Func<Base, Base> func = d => d; ]]>
        Base b;
        return (Derived)func(b);
    }
    public Program1()
    {
        Base b;
        Derived d = (Derived)b;
        d = new Base() { };

        Derived d2 = (Derived)ReturnBase();
        Derived d2 = ReturnBase(b);

        Test t = new Test();
        t.D = (Derived)b;
        t.d = b;
        d = (Derived)t.B;

        <![CDATA[ Func<Base, Derived> foo = d => (Derived)d; ]]>

        <![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
        d2 = (Derived)foo2(d);
    }
}
        </Document>
        <Document>
public class Program2
{
    interface Base1 { }
    interface Base2 : Base1 { }
    interface Base3 { }
    class Derived1 : Base2, Base3 { }
    class Derived2 : Derived1 { }

    class Test
    {
        static public explicit operator Derived2(Test t) { return new Derived2();  }
    }

     Derived2 returnDerived2_1() {
        return new Derived1();
    }

     Derived2 returnDerived2_2() {
        return new Test();
    }

    private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
    {
        Derived2 derived2 = b1;
        derived2 = b3;
        Base2 base2 = b1;
        derived2 = d1;
        Derived2 d2 = new Test();
    }
}
        </Document>
    </Project>
    <Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
        <Document>
public class Program3
{
    class Base { }
    class Derived : Base { }
    class Derived2 : Derived { }

    Derived2 returnD2(Base b)
    {
        Derived d;
        return d = b;
    }
}
        </Document>
    </Project>
</Workspace>";

            await TestInRegularAndScriptAsync(input, expected);
        }

        [Fact]
        [Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
        [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
        public async Task CS0266TestFixAllInProject()
        {
            var input = @"
<Workspace>
    <Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
        <Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

public class Program1
{
    class Base { }
    class Derived : Base { }

    class Test
    {
        private Derived d;
        private Base b;
        public Derived D { get => d; set => d = value; }
        public Base B { get => b; set => b = value; }
    }

    Base ReturnBase()
    {
        Base b = new Base();
        return b;
    }

    Base ReturnBase(Derived d)
    {
        Base b = new Base();
        return b;
    }

    Derived ReturnDerived(Base b)
    {
        return b;
    }

    <![CDATA[ IEnumerable<Derived> ReturnDerived() ]]>
    {
        Base b;
        yield return b;
    }

    <![CDATA[ IEnumerable<Derived> ReturnDerived()
    {
        Base b;
        return b;
    } ]]>

    <![CDATA[ async Task<Derived> M() ]]>
    {
        Base b;
        return b;
    }

    Derived ReturnDerived2(Base b)
    {
        return ReturnBase();
    }

    Derived Foo()
    {
        <![CDATA[ Func<Base, Base> func = d => d; ]]>
        Base b;
        return func(b);
    }
    public Program1()
    {
        Base b;
        Derived d = {|FixAllInProject:b|};
        d = new Base() { };

        Derived d2 = ReturnBase();
        Derived d2 = ReturnBase(b);

        Test t = new Test();
        t.D = b;
        t.d = b;
        d = t.B;

        <![CDATA[ Func<Base, Derived> foo = d => d; ]]>

        <![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
        d2 = foo2(d);
    }
}
        </Document>
        <Document>
public class Program2
{
    interface Base1 { }
    interface Base2 : Base1 { }
    interface Base3 { }
    class Derived1 : Base2, Base3 { }
    class Derived2 : Derived1 { }

    class Test
    {
        static public explicit operator Derived2(Test t) { return new Derived2();  }
    }

     Derived2 returnDerived2_1() {
        return new Derived1();
    }

     Derived2 returnDerived2_2() {
        return new Test();
    }

    private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
    {
        Derived2 derived2 = b1;
        derived2 = b3;
        Base2 base2 = b1;
        derived2 = d1;
        Derived2 d2 = new Test();
    }
}
        </Document>
    </Project>
    <Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
        <Document>
public class Program3
{
    class Base { }
    class Derived : Base { }
    class Derived2 : Derived { }

    Derived2 returnD2(Base b)
    {
        Derived d;
        return d = b;
    }
}
        </Document>
    </Project>
</Workspace>";

            var expected = @"
<Workspace>
    <Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
        <Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

public class Program1
{
    class Base { }
    class Derived : Base { }

    class Test
    {
        private Derived d;
        private Base b;
        public Derived D { get => d; set => d = value; }
        public Base B { get => b; set => b = value; }
    }

    Base ReturnBase()
    {
        Base b = new Base();
        return b;
    }

    Base ReturnBase(Derived d)
    {
        Base b = new Base();
        return b;
    }

    Derived ReturnDerived(Base b)
    {
        return (Derived)b;
    }

    <![CDATA[ IEnumerable<Derived> ReturnDerived() ]]>
    {
        Base b;
        yield return (Derived)b;
    }

    <![CDATA[ IEnumerable<Derived> ReturnDerived()
    {
        Base b;
        return (IEnumerable<Derived>)b;
    } ]]>

    <![CDATA[ async Task<Derived> M() ]]>
    {
        Base b;
        return (Derived)b;
    }

    Derived ReturnDerived2(Base b)
    {
        return (Derived)ReturnBase();
    }

    Derived Foo()
    {
        <![CDATA[ Func<Base, Base> func = d => d; ]]>
        Base b;
        return (Derived)func(b);
    }
    public Program1()
    {
        Base b;
        Derived d = (Derived)b;
        d = new Base() { };

        Derived d2 = (Derived)ReturnBase();
        Derived d2 = ReturnBase(b);

        Test t = new Test();
        t.D = (Derived)b;
        t.d = b;
        d = (Derived)t.B;

        <![CDATA[ Func<Base, Derived> foo = d => (Derived)d; ]]>

        <![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
        d2 = (Derived)foo2(d);
    }
}
        </Document>
        <Document>
public class Program2
{
    interface Base1 { }
    interface Base2 : Base1 { }
    interface Base3 { }
    class Derived1 : Base2, Base3 { }
    class Derived2 : Derived1 { }

    class Test
    {
        static public explicit operator Derived2(Test t) { return new Derived2();  }
    }

     Derived2 returnDerived2_1() {
        return new Derived1();
    }

     Derived2 returnDerived2_2() {
        return (Derived2)new Test();
    }

    private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
    {
        Derived2 derived2 = (Derived2)b1;
        derived2 = (Derived2)b3;
        Base2 base2 = (Base2)b1;
        derived2 = (Derived2)d1;
        Derived2 d2 = (Derived2)new Test();
    }
}
        </Document>
    </Project>
    <Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
        <Document>
public class Program3
{
    class Base { }
    class Derived : Base { }
    class Derived2 : Derived { }

    Derived2 returnD2(Base b)
    {
        Derived d;
        return d = b;
    }
}
        </Document>
    </Project>
</Workspace>";

            await TestInRegularAndScriptAsync(input, expected);
        }

        [Fact]
        [Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
        [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
        public async Task CS0266TestFixAllInSolution()
        {
            var input = @"
<Workspace>
    <Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
        <Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

public class Program1
{
    class Base { }
    class Derived : Base { }

    class Test
    {
        private Derived d;
        private Base b;
        public Derived D { get => d; set => d = value; }
        public Base B { get => b; set => b = value; }
    }

    Base ReturnBase()
    {
        Base b = new Base();
        return b;
    }

    Base ReturnBase(Derived d)
    {
        Base b = new Base();
        return b;
    }

    Derived ReturnDerived(Base b)
    {
        return b;
    }

    <![CDATA[ IEnumerable<Derived> ReturnDerived() ]]>
    {
        Base b;
        yield return b;
    }

    <![CDATA[ IEnumerable<Derived> ReturnDerived()
    {
        Base b;
        return b;
    } ]]>

    <![CDATA[ async Task<Derived> M() ]]>
    {
        Base b;
        return b;
    }

    Derived ReturnDerived2(Base b)
    {
        return ReturnBase();
    }

    Derived Foo()
    {
        <![CDATA[ Func<Base, Base> func = d => d; ]]>
        Base b;
        return func(b);
    }
    public Program1()
    {
        Base b;
        Derived d = {|FixAllInSolution:b|};
        d = new Base() { };

        Derived d2 = ReturnBase();
        Derived d2 = ReturnBase(b);

        Test t = new Test();
        t.D = b;
        t.d = b;
        d = t.B;

        <![CDATA[ Func<Base, Derived> foo = d => d; ]]>

        <![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
        d2 = foo2(d);
    }
}
        </Document>
        <Document>
public class Program2
{
    interface Base1 { }
    interface Base2 : Base1 { }
    interface Base3 { }
    class Derived1 : Base2, Base3 { }
    class Derived2 : Derived1 { }

    class Test
    {
        static public explicit operator Derived2(Test t) { return new Derived2();  }
    }

     Derived2 returnDerived2_1() {
        return new Derived1();
    }

     Derived2 returnDerived2_2() {
        return new Test();
    }

    private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
    {
        Derived2 derived2 = b1;
        derived2 = b3;
        Base2 base2 = b1;
        derived2 = d1;
        Derived2 d2 = new Test();
    }
}
        </Document>
    </Project>
    <Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
        <Document>
public class Program3
{
    class Base { }
    class Derived : Base { }
    class Derived2 : Derived { }

    Derived2 returnD2(Base b)
    {
        Derived d;
        return d = b;
    }
}
        </Document>
    </Project>
</Workspace>";

            var expected = @"
<Workspace>
    <Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
        <Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

public class Program1
{
    class Base { }
    class Derived : Base { }

    class Test
    {
        private Derived d;
        private Base b;
        public Derived D { get => d; set => d = value; }
        public Base B { get => b; set => b = value; }
    }

    Base ReturnBase()
    {
        Base b = new Base();
        return b;
    }

    Base ReturnBase(Derived d)
    {
        Base b = new Base();
        return b;
    }

    Derived ReturnDerived(Base b)
    {
        return (Derived)b;
    }

    <![CDATA[ IEnumerable<Derived> ReturnDerived() ]]>
    {
        Base b;
        yield return (Derived)b;
    }

    <![CDATA[ IEnumerable<Derived> ReturnDerived()
    {
        Base b;
        return (IEnumerable<Derived>)b;
    } ]]>

    <![CDATA[ async Task<Derived> M() ]]>
    {
        Base b;
        return (Derived)b;
    }

    Derived ReturnDerived2(Base b)
    {
        return (Derived)ReturnBase();
    }

    Derived Foo()
    {
        <![CDATA[ Func<Base, Base> func = d => d; ]]>
        Base b;
        return (Derived)func(b);
    }
    public Program1()
    {
        Base b;
        Derived d = (Derived)b;
        d = new Base() { };

        Derived d2 = (Derived)ReturnBase();
        Derived d2 = ReturnBase(b);

        Test t = new Test();
        t.D = (Derived)b;
        t.d = b;
        d = (Derived)t.B;

        <![CDATA[ Func<Base, Derived> foo = d => (Derived)d; ]]>

        <![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
        d2 = (Derived)foo2(d);
    }
}
        </Document>
        <Document>
public class Program2
{
    interface Base1 { }
    interface Base2 : Base1 { }
    interface Base3 { }
    class Derived1 : Base2, Base3 { }
    class Derived2 : Derived1 { }

    class Test
    {
        static public explicit operator Derived2(Test t) { return new Derived2();  }
    }

     Derived2 returnDerived2_1() {
        return new Derived1();
    }

     Derived2 returnDerived2_2() {
        return (Derived2)new Test();
    }

    private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
    {
        Derived2 derived2 = (Derived2)b1;
        derived2 = (Derived2)b3;
        Base2 base2 = (Base2)b1;
        derived2 = (Derived2)d1;
        Derived2 d2 = (Derived2)new Test();
    }
}
        </Document>
    </Project>
    <Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
        <Document>
public class Program3
{
    class Base { }
    class Derived : Base { }
    class Derived2 : Derived { }

    Derived2 returnD2(Base b)
    {
        Derived d;
        return (Derived2)(d = (Derived)b);
    }
}
        </Document>
    </Project>
</Workspace>";

            await TestInRegularAndScriptAsync(input, expected);
        }

        [Fact]
        [Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
        [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
        public async Task CS1503TestFixAllInDocument()
        {
            var input = @"
<Workspace>
    <Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
        <Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
    class Base { }
    class Derived : Base { }

    class Test
    {
        private Derived d;
        private Base b;
        public Test(Derived derived)
        {
            d = derived;
            B = derived;
        }

        public Derived D { get => d; set => d = value; }
        public Base B { get => b; set => b = value; }

        public void testing(Derived d) { }
        private void testing(Base b) { }
    }

    class Test2 : Test
    {
        public Test2(Base b) : base(b) { }
    }

    class Test3
    {
        public Test3(Derived b) { }
        public Test3(int i, Base b) : this(b) { }

        public void testing(int i, Derived d) { }
        private void testing(int i, Base d) { }
    }

    Base ReturnBase()
    {
        Base b = new Base();
        return b;
    }

    void PassDerived(Derived d) { }
    void PassDerived(int i, Derived d) { }

    public Program1()
    {
        Base b;
        Derived d = b;

        PassDerived({|FixAllInDocument:b|});
        PassDerived(ReturnBase());
        PassDerived(1, b);
        PassDerived(1, ReturnBase());

        <![CDATA[ List<Derived> list = new List<Derived>(); ]]>
        list.Add(b);

        Test t = new Test();
        t.testing(b);

        <![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
        Derived d2 = foo2(b);
        d2 = foo2(d);
    }
}
        </Document>
        <Document>
public class Program2
{
    interface Base1 { }
    interface Base2 : Base1 { }
    interface Base3 { }
    class Derived1 : Base2, Base3 { }
    class Derived2 : Derived1 { }

    void Foo1(Derived2 b) { }
    void Foo2(Base2 b) { }

    void Foo3(Derived2 b1) { }
    void Foo3(int i) { }

    private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
    {
        Foo1(b1);
        Foo1(d1);
        Foo2(b1);
        Foo3(b1);
    }
}
        </Document>
    </Project>
    <Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
        <Document>
class Program3
{
    interface Base1 { }
    interface Base2 : Base1 { }
    interface Base3 { }
    class Derived1 : Base2, Base3 { }
    class Derived2 : Derived1 { }

    void Foo1(Derived2 b) { }
    void Foo2(Base2 b) { }

    void Foo3(Derived2 b1) { }
    void Foo3(int i) { }

    private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
    {
        Foo1(b1);
        Foo1(d1);
        Foo2(b1);
        Foo3(b1);
    }
}
        </Document>
    </Project>
</Workspace>";

            var expected = @"
<Workspace>
    <Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
        <Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
    class Base { }
    class Derived : Base { }

    class Test
    {
        private Derived d;
        private Base b;
        public Test(Derived derived)
        {
            d = derived;
            B = derived;
        }

        public Derived D { get => d; set => d = value; }
        public Base B { get => b; set => b = value; }

        public void testing(Derived d) { }
        private void testing(Base b) { }
    }

    class Test2 : Test
    {
        public Test2(Base b) : base((Derived)b) { }
    }

    class Test3
    {
        public Test3(Derived b) { }
        public Test3(int i, Base b) : this((Derived)b) { }

        public void testing(int i, Derived d) { }
        private void testing(int i, Base d) { }
    }

    Base ReturnBase()
    {
        Base b = new Base();
        return b;
    }

    void PassDerived(Derived d) { }
    void PassDerived(int i, Derived d) { }

    public Program1()
    {
        Base b;
        Derived d = b;

        PassDerived((Derived)b);
        PassDerived((Derived)ReturnBase());
        PassDerived(1, (Derived)b);
        PassDerived(1, (Derived)ReturnBase());

        <![CDATA[ List<Derived> list = new List<Derived>(); ]]>
        list.Add((Derived)b);

        Test t = new Test();
        t.testing((Derived)b);

        <![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
        Derived d2 = foo2((Derived)b);
        d2 = foo2(d);
    }
}
        </Document>
        <Document>
public class Program2
{
    interface Base1 { }
    interface Base2 : Base1 { }
    interface Base3 { }
    class Derived1 : Base2, Base3 { }
    class Derived2 : Derived1 { }

    void Foo1(Derived2 b) { }
    void Foo2(Base2 b) { }

    void Foo3(Derived2 b1) { }
    void Foo3(int i) { }

    private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
    {
        Foo1(b1);
        Foo1(d1);
        Foo2(b1);
        Foo3(b1);
    }
}
        </Document>
    </Project>
    <Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
        <Document>
class Program3
{
    interface Base1 { }
    interface Base2 : Base1 { }
    interface Base3 { }
    class Derived1 : Base2, Base3 { }
    class Derived2 : Derived1 { }

    void Foo1(Derived2 b) { }
    void Foo2(Base2 b) { }

    void Foo3(Derived2 b1) { }
    void Foo3(int i) { }

    private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
    {
        Foo1(b1);
        Foo1(d1);
        Foo2(b1);
        Foo3(b1);
    }
}
        </Document>
    </Project>
</Workspace>";

            await TestInRegularAndScriptAsync(input, expected);
        }

        [Fact]
        [Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
        [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
        public async Task CS1503TestFixAllInProject()
        {
            var input = @"
<Workspace>
    <Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
        <Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
    class Base { }
    class Derived : Base { }

    class Test
    {
        private Derived d;
        private Base b;
        public Test(Derived derived)
        {
            d = derived;
            B = derived;
        }

        public Derived D { get => d; set => d = value; }
        public Base B { get => b; set => b = value; }

        public void testing(Derived d) { }
        private void testing(Base b) { }
    }

    class Test2 : Test
    {
        public Test2(Base b) : base(b) { }
    }

    class Test3
    {
        public Test3(Derived b) { }
        public Test3(int i, Base b) : this(b) { }

        public void testing(int i, Derived d) { }
        private void testing(int i, Base d) { }
    }

    Base ReturnBase()
    {
        Base b = new Base();
        return b;
    }

    void PassDerived(Derived d) { }
    void PassDerived(int i, Derived d) { }

    public Program1()
    {
        Base b;
        Derived d = b;

        PassDerived({|FixAllInProject:b|});
        PassDerived(ReturnBase());
        PassDerived(1, b);
        PassDerived(1, ReturnBase());

        <![CDATA[ List<Derived> list = new List<Derived>(); ]]>
        list.Add(b);

        Test t = new Test();
        t.testing(b);

        <![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
        Derived d2 = foo2(b);
        d2 = foo2(d);
    }
}
        </Document>
        <Document>
public class Program2
{
    interface Base1 { }
    interface Base2 : Base1 { }
    interface Base3 { }
    class Derived1 : Base2, Base3 { }
    class Derived2 : Derived1 { }

    class Test
    {
        static public explicit operator Derived1(Test t) { return new Derived1(); }
        static public explicit operator Derived2(Test t) { return new Derived2(); }
    }

    void Foo1(Derived2 b) { }
    void Foo2(Base2 b) { }

    void Foo3(Derived2 b1) { }
    void Foo3(int i) { }

    void Foo4(int i, string j, Derived1 d) { }
    void Foo4(string j, int i, Derived1 d) { }

    void Foo5(string j, int i, Derived2 d, int x = 1) { }

    void Foo5(string j, int i, Derived1 d, params Derived2[] d2list) { }

    void Foo6(Derived1 d, params Derived2[] d2list) { }

    private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
    {
        Foo1(b1);
        Foo1(d1);

        Foo2(b1);

        Foo3(b1);

        Foo4(1, """", b1);
        Foo4(i: 1, j: """", b1); // one operation, fix

        Foo5("""", 1, b1); // multiple operations, no fix-all

        Foo5(d: b1, i: 1, j: """", x: 1); // all arguments out of order - match
        Foo5(1, """", x: 1, d: b1); // part of arguments out of order - mismatch

        Foo5(1, """", d: b1, b2, b3, d1); // part of arguments out of order - mismatch
        Foo5("""", 1, d: b1, b2, b3, d1); // part of arguments out of order - match

        var d2list = new Derived2[] { };
        Foo5(d2list: d2list, j: """", i: 1, d: b2);
        var d1list = new Derived1[] { };
        Foo5(d2list: d1list, j: """", i: 1, d: b2); 

        Foo6(b1);

        Foo6(new Test()); // params is optional,  object creation can be cast with explicit cast operator
        Foo6(new Test(), new Derived1()); // object creation cannot be cast without explicit cast operator
        Foo6(new Derived1(), new Test());
    }
}
        </Document>
    </Project>
    <Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
        <Document>
class Program3
{
    interface Base1 { }
    interface Base2 : Base1 { }
    interface Base3 { }
    class Derived1 : Base2, Base3 { }
    class Derived2 : Derived1 { }

    void Foo1(Derived2 b) { }
    void Foo2(Base2 b) { }

    void Foo3(Derived2 b1) { }
    void Foo3(int i) { }

    private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
    {
        Foo1(b1);
        Foo1(d1);
        Foo2(b1);
        Foo3(b1);
    }
}
        </Document>
    </Project>
</Workspace>";

            var expected = @"
<Workspace>
    <Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
        <Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
    class Base { }
    class Derived : Base { }

    class Test
    {
        private Derived d;
        private Base b;
        public Test(Derived derived)
        {
            d = derived;
            B = derived;
        }

        public Derived D { get => d; set => d = value; }
        public Base B { get => b; set => b = value; }

        public void testing(Derived d) { }
        private void testing(Base b) { }
    }

    class Test2 : Test
    {
        public Test2(Base b) : base((Derived)b) { }
    }

    class Test3
    {
        public Test3(Derived b) { }
        public Test3(int i, Base b) : this((Derived)b) { }

        public void testing(int i, Derived d) { }
        private void testing(int i, Base d) { }
    }

    Base ReturnBase()
    {
        Base b = new Base();
        return b;
    }

    void PassDerived(Derived d) { }
    void PassDerived(int i, Derived d) { }

    public Program1()
    {
        Base b;
        Derived d = b;

        PassDerived((Derived)b);
        PassDerived((Derived)ReturnBase());
        PassDerived(1, (Derived)b);
        PassDerived(1, (Derived)ReturnBase());

        <![CDATA[ List<Derived> list = new List<Derived>(); ]]>
        list.Add((Derived)b);

        Test t = new Test();
        t.testing((Derived)b);

        <![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
        Derived d2 = foo2((Derived)b);
        d2 = foo2(d);
    }
}
        </Document>
        <Document>
public class Program2
{
    interface Base1 { }
    interface Base2 : Base1 { }
    interface Base3 { }
    class Derived1 : Base2, Base3 { }
    class Derived2 : Derived1 { }

    class Test
    {
        static public explicit operator Derived1(Test t) { return new Derived1(); }
        static public explicit operator Derived2(Test t) { return new Derived2(); }
    }

    void Foo1(Derived2 b) { }
    void Foo2(Base2 b) { }

    void Foo3(Derived2 b1) { }
    void Foo3(int i) { }

    void Foo4(int i, string j, Derived1 d) { }
    void Foo4(string j, int i, Derived1 d) { }

    void Foo5(string j, int i, Derived2 d, int x = 1) { }

    void Foo5(string j, int i, Derived1 d, params Derived2[] d2list) { }

    void Foo6(Derived1 d, params Derived2[] d2list) { }

    private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
    {
        Foo1((Derived2)b1);
        Foo1((Derived2)d1);

        Foo2((Base2)b1);

        Foo3((Derived2)b1);

        Foo4(1, """", (Derived1)b1);
        Foo4(i: 1, j: """", (Derived1)b1); // one operation, fix

        Foo5("""", 1, b1); // multiple operations, no fix-all

        Foo5(d: (Derived2)b1, i: 1, j: """", x: 1); // all arguments out of order - match
        Foo5(1, """", x: 1, d: b1); // part of arguments out of order - mismatch

        Foo5(1, """", d: b1, b2, b3, d1); // part of arguments out of order - mismatch
        Foo5("""", 1, d: (Derived1)b1, (Derived2)b2, (Derived2)b3, (Derived2)d1); // part of arguments out of order - match

        var d2list = new Derived2[] { };
        Foo5(d2list: d2list, j: """", i: 1, d: (Derived1)b2);
        var d1list = new Derived1[] { };
        Foo5(d2list: (Derived2[])d1list, j: """", i: 1, d: (Derived1)b2); 

        Foo6((Derived1)b1);

        Foo6((Derived1)new Test()); // params is optional,  object creation can be cast with explicit cast operator
        Foo6((Derived1)new Test(), new Derived1()); // object creation cannot be cast without explicit cast operator
        Foo6(new Derived1(), (Derived2)new Test());
    }
}
        </Document>
    </Project>
    <Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
        <Document>
class Program3
{
    interface Base1 { }
    interface Base2 : Base1 { }
    interface Base3 { }
    class Derived1 : Base2, Base3 { }
    class Derived2 : Derived1 { }

    void Foo1(Derived2 b) { }
    void Foo2(Base2 b) { }

    void Foo3(Derived2 b1) { }
    void Foo3(int i) { }

    private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
    {
        Foo1(b1);
        Foo1(d1);
        Foo2(b1);
        Foo3(b1);
    }
}
        </Document>
    </Project>
</Workspace>";

            await TestInRegularAndScriptAsync(input, expected);
        }

        [Fact]
        [Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)]
        [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
        public async Task CS1503TestFixAllInSolution()
        {
            var input = @"
<Workspace>
    <Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
        <Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
    class Base { }
    class Derived : Base { }

    class Test
    {
        private Derived d;
        private Base b;
        public Test(Derived derived)
        {
            d = derived;
            B = derived;
        }

        public Derived D { get => d; set => d = value; }
        public Base B { get => b; set => b = value; }

        public void testing(Derived d) { }
        private void testing(Base b) { }
    }

    class Test2 : Test
    {
        public Test2(Base b) : base(b) { }
    }

    class Test3
    {
        public Test3(Derived b) { }
        public Test3(int i, Base b) : this(b) { }

        public void testing(int i, Derived d) { }
        private void testing(int i, Base d) { }
    }

    Base ReturnBase()
    {
        Base b = new Base();
        return b;
    }

    void PassDerived(Derived d) { }
    void PassDerived(int i, Derived d) { }

    public Program1()
    {
        Base b;
        Derived d = b;

        PassDerived({|FixAllInSolution:b|});
        PassDerived(ReturnBase());
        PassDerived(1, b);
        PassDerived(1, ReturnBase());

        <![CDATA[ List<Derived> list = new List<Derived>(); ]]>
        list.Add(b);

        Test t = new Test();
        t.testing(b);

        <![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
        Derived d2 = foo2(b);
        d2 = foo2(d);
    }
}
        </Document>
        <Document>
public class Program2
{
    interface Base1 { }
    interface Base2 : Base1 { }
    interface Base3 { }
    class Derived1 : Base2, Base3 { }
    class Derived2 : Derived1 { }

    void Foo1(Derived2 b) { }
    void Foo2(Base2 b) { }

    void Foo3(Derived2 b1) { }
    void Foo3(int i) { }

    private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
    {
        Foo1(b1);
        Foo1(d1);
        Foo2(b1);
        Foo3(b1);
    }
}
        </Document>
    </Project>
    <Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
        <Document>
class Program3
{
    interface Base { }
    class Derived1 : Base { }
    class Derived2 : Derived1 { }

    class Test
    {
        public Test(string s, Base b, int i, params object[] list) : this(d: b, s: s, i: i) { } // 2 operations, no fix in fix-all
        Test(string s, Derived1 d, int i) { }
        Test(string s, Derived2 d, int i) { }
    }

    void Foo(Derived1 d, int a, int b, params int[] list) { }
    void Foo(Derived2 d, params int[] list) { }


    private void M2(Base b, Derived1 d1, Derived2 d2)
    {
        Foo(b, 1, 2); // 2 operations, no fix in fix-all
        var intlist = new int[] { };
        Foo(b, 1, 2, list: intlist); // 2 operations
    }
}
        </Document>
    </Project>
</Workspace>";

            var expected = @"
<Workspace>
    <Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
        <Document>
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program1
{
    class Base { }
    class Derived : Base { }

    class Test
    {
        private Derived d;
        private Base b;
        public Test(Derived derived)
        {
            d = derived;
            B = derived;
        }

        public Derived D { get => d; set => d = value; }
        public Base B { get => b; set => b = value; }

        public void testing(Derived d) { }
        private void testing(Base b) { }
    }

    class Test2 : Test
    {
        public Test2(Base b) : base((Derived)b) { }
    }

    class Test3
    {
        public Test3(Derived b) { }
        public Test3(int i, Base b) : this((Derived)b) { }

        public void testing(int i, Derived d) { }
        private void testing(int i, Base d) { }
    }

    Base ReturnBase()
    {
        Base b = new Base();
        return b;
    }

    void PassDerived(Derived d) { }
    void PassDerived(int i, Derived d) { }

    public Program1()
    {
        Base b;
        Derived d = b;

        PassDerived((Derived)b);
        PassDerived((Derived)ReturnBase());
        PassDerived(1, (Derived)b);
        PassDerived(1, (Derived)ReturnBase());

        <![CDATA[ List<Derived> list = new List<Derived>(); ]]>
        list.Add((Derived)b);

        Test t = new Test();
        t.testing((Derived)b);

        <![CDATA[ Func<Derived, Base> foo2 = d => d; ]]>
        Derived d2 = foo2((Derived)b);
        d2 = foo2(d);
    }
}
        </Document>
        <Document>
public class Program2
{
    interface Base1 { }
    interface Base2 : Base1 { }
    interface Base3 { }
    class Derived1 : Base2, Base3 { }
    class Derived2 : Derived1 { }

    void Foo1(Derived2 b) { }
    void Foo2(Base2 b) { }

    void Foo3(Derived2 b1) { }
    void Foo3(int i) { }

    private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2)
    {
        Foo1((Derived2)b1);
        Foo1((Derived2)d1);
        Foo2((Base2)b1);
        Foo3((Derived2)b1);
    }
}
        </Document>
    </Project>
    <Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
        <Document>
class Program3
{
    interface Base { }
    class Derived1 : Base { }
    class Derived2 : Derived1 { }

    class Test
    {
        public Test(string s, Base b, int i, params object[] list) : this(d: b, s: s, i: i) { } // 2 operations, no fix in fix-all
        Test(string s, Derived1 d, int i) { }
        Test(string s, Derived2 d, int i) { }
    }

    void Foo(Derived1 d, int a, int b, params int[] list) { }
    void Foo(Derived2 d, params int[] list) { }


    private void M2(Base b, Derived1 d1, Derived2 d2)
    {
        Foo(b, 1, 2); // 2 operations, no fix in fix-all
        var intlist = new int[] { };
        Foo(b, 1, 2, list: intlist); // 2 operations
    }
}
        </Document>
    </Project>
</Workspace>";

            await TestInRegularAndScriptAsync(input, expected);
        }
        #endregion
    }
}
