File: RemoveUnnecessaryCast\RemoveUnnecessaryCastTests_AsTests.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.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.RemoveUnnecessaryCast;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
using Xunit.Abstractions;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.RemoveUnnecessaryCast;
 
[Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryCast)]
public sealed partial class RemoveUnnecessaryCastTests_AsTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest_NoEditor
{
    public RemoveUnnecessaryCastTests_AsTests(ITestOutputHelper logger)
      : base(logger)
    {
    }
 
    internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
        => (new CSharpRemoveUnnecessaryCastDiagnosticAnalyzer(), new CSharpRemoveUnnecessaryCastCodeFixProvider());
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545979")]
    public Task DoNotRemoveCastToErrorType()
        => TestMissingInRegularAndScriptAsync(
            """
            class Program
            {
                static void Main()
                {
                    object s = ";
                    foreach (object x in ([|s as ErrorType|]))
                    {
                    }
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545146")]
    public Task ParenthesizeToKeepParseTheSame2()
        => TestInRegularAndScriptAsync(
        """
        using System;
 
        class C
        {
            static void Main()
            {
                Action a = Console.WriteLine;
                ([|a as Action|])();
            }
        }
        """,
 
        """
        using System;
 
        class C
        {
            static void Main()
            {
                Action a = Console.WriteLine;
                a();
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545138")]
    public Task DoNotRemoveTypeParameterCastToObject()
        => TestMissingInRegularAndScriptAsync(
            """
            class С
            {
                void Goo<T>(T obj)
            {
                int x = (int)([|obj as object|]);
            }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545139")]
    public Task DoNotRemoveCastInIsTest()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class С
            {
                static void Main()
            {
                DayOfWeek[] a = {
                };
                Console.WriteLine([|a as object|] is int[]);
            }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545142")]
    public Task DoNotRemoveCastNeedForUserDefinedOperator()
        => TestMissingInRegularAndScriptAsync(
            """
            class A
            {
                public static implicit operator A(string x)
                {
                    return new A();
                }
            }
 
            class Program
            {
                static void Main()
                {
                    A x = [|null as string|];
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545143")]
    public Task DoNotRemovePointerCast1()
        => TestMissingInRegularAndScriptAsync(
            """
            unsafe class C
            {
                static unsafe void Main()
                {
                    var x = (int)([|null as int*|]);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545144")]
    public Task DoNotRemoveCastToObjectFromDelegateComparison()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                static void Main()
                {
                    Action a = Console.WriteLine;
                    Action b = Console.WriteLine;
                    Console.WriteLine(a == ([|b as object|]));
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545145")]
    public Task DoNotRemoveCastToAnonymousMethodWhenOnLeftOfAsCast()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void Main()
                {
                    var x = [|delegate {
                    } as Action|]
 
                    as Action;
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545157")]
    public Task DoNotRemoveIdentityCastWhichAffectsOverloadResolution1()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                static void Main()
                {
                    Goo(x => [|x as string|]);
                }
 
                static void Goo(Func<int, object> x)
                {
                }
 
                static void Goo(Func<string, object> x)
                {
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545158")]
    public Task DoNotRemoveIdentityCastWhichAffectsOverloadResolution2()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                static void Main()
                {
                    var x = [|1 as IComparable<int>|];
                    Goo(x);
                }
 
                static void Goo(IComparable<int> x)
                {
                }
 
                static void Goo(int x)
                {
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545158")]
    public Task DoNotRemoveIdentityCastWhichAffectsOverloadResolution3()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                static void Main()
                {
                    var x = [|1 as IComparable<int>|];
                    var y = x;
                    Goo(y);
                }
 
                static void Goo(IComparable<int> x)
                {
                }
 
                static void Goo(int x)
                {
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545747")]
    public Task DoNotRemoveCastWhichChangesTypeOfInferredLocal()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                static void Main()
                {
                    var x = [|"" as object|];
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545159")]
    public Task DoNotRemoveNeededCastToIListOfObject()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
            using System.Collections.Generic;
 
            class C
            {
                static void Main()
                {
                    Action<object>[] x = {
                    };
                    Goo(x);
                }
 
                static void Goo<T>(Action<T>[] x)
                {
                    var y = (IList<Action<object>>)([|x as IList<object>|]);
                    Console.WriteLine(y.Count);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545287"), WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/880752")]
    public Task RemoveUnneededCastInParameterDefaultValue()
        => TestInRegularAndScriptAsync(
        """
        class Program
        {
            static void M1(string i1 = [|null as string|])
            {
            }
        }
        """,
 
        """
        class Program
        {
            static void M1(string i1 = null)
            {
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545289")]
    public Task RemoveUnneededCastInReturnStatement()
        => TestInRegularAndScriptAsync(
        """
        class Program
        {
            static string M2()
            {
                return [|"" as string|];
            }
        }
        """,
 
        """
        class Program
        {
            static string M2()
            {
                return "";
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545288")]
    public Task RemoveUnneededCastInLambda1()
        => TestInRegularAndScriptAsync(
        """
        using System;
        class Program
        {
            static void M1()
            {
                Func<string> f1 = () => [|"" as string|];
            }
        }
        """,
 
        """
        using System;
        class Program
        {
            static void M1()
            {
                Func<string> f1 = () => "";
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545288")]
    public Task RemoveUnneededCastInLambda2()
        => TestInRegularAndScriptAsync(
        """
        using System;
        class Program
        {
            static void M1()
            {
                Func<string> f1 = () => { return [|"" as string|]; };
            }
        }
        """,
 
        """
        using System;
        class Program
        {
            static void M1()
            {
                Func<string> f1 = () => { return ""; };
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545288")]
    public Task RemoveUnneededCastInLambda3()
        => TestInRegularAndScriptAsync(
        """
        using System;
        class Program
        {
            static void M1()
            {
                Func<string> f1 = _ => { return [|"" as string|]; };
            }
        }
        """,
 
        """
        using System;
        class Program
        {
            static void M1()
            {
                Func<string> f1 = _ => { return ""; };
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545288")]
    public Task RemoveUnneededCastInLambda4()
        => TestInRegularAndScriptAsync(
        """
        using System;
        class Program
        {
            static void M1()
            {
                Func<string> f1 = _ => [|"" as string|];
            }
        }
        """,
 
        """
        using System;
        class Program
        {
            static void M1()
            {
                Func<string> f1 = _ => "";
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545291")]
    public Task RemoveUnneededCastInConditionalExpression1()
        => TestInRegularAndScriptAsync(
        """
        class Test
        {
            public static void Main()
            {
                int b = 5;
 
                string f1 = (b == 5) ? [|"a" as string|] : "b" as string;
            }
        }
        """,
 
        """
        class Test
        {
            public static void Main()
            {
                int b = 5;
 
                string f1 = (b == 5) ? "a" : "b" as string;
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545291")]
    public Task RemoveUnneededCastInConditionalExpression2()
        => TestInRegularAndScriptAsync(
        """
        class Test
        {
            public static void Main()
            {
                int b = 5;
 
                string f1 = (b == 5) ? "a" as string : [|"b" as string|];
            }
        }
        """,
 
        """
        class Test
        {
            public static void Main()
            {
                int b = 5;
 
                string f1 = (b == 5) ? "a" as string : "b";
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545291")]
    public Task DoNotRemoveNeededCastInConditionalExpression()
        => TestMissingInRegularAndScriptAsync(
            """
            class Test
            {
                public static void Main()
                {
                    int b = 5;
                    var f1 = (b == 5) ? "" : [|"" as object|];
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545459")]
    public Task DoNotRemoveIllegalAsCastInsideADelegateConstructor()
        => TestMissingAsync(
        """
        using System;
        class Test
        {
            delegate void D(int x);
 
            static void Main(string[] args)
            {
                var cd1 = new D([|M1 as Action<int>|]);
            }
 
            public static void M1(int i) { }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545422")]
    public Task RemoveUnneededCastInsideCaseLabel()
        => TestInRegularAndScriptAsync(
        """
        class Test
        {
            static void Main()
            {
                switch ("")
                {
                    case [|"" as string|]:
                        break;
                }
            }
        }
        """,
 
        """
        class Test
        {
            static void Main()
            {
                switch ("")
                {
                    case "":
                        break;
                }
            }
        }
        """);
 
    [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545595")]
    [Fact(Skip = "529787")]
    public Task RemoveUnneededCastInCollectionInitializer()
        => TestInRegularAndScriptAsync(
        """
        using System.Collections.Generic;
 
        class Program
        {
            static void Main()
            {
                var z = new List<string> { [|"" as string|] };
            }
        }
        """,
 
        """
        using System.Collections.Generic;
 
        class Program
        {
            static void Main()
            {
                var z = new List<string> { "" };
            }
        }
        """);
 
    [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529787")]
    [Fact(Skip = "529787")]
    public Task DoNotRemoveNecessaryCastWhichInCollectionInitializer1()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
            using System.Collections.Generic;
 
            class X : List<int>
            {
                void Add(object x)
                {
                    Console.WriteLine(1);
                }
 
                void Add(string x)
                {
                    Console.WriteLine(2);
                }
 
                static void Main()
                {
                    var z = new X { [|"" as object|] };
                }
            }
            """);
 
    [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529787")]
    [Fact(Skip = "529787")]
    public Task DoNotRemoveNecessaryCastWhichInCollectionInitializer2()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
            using System.Collections.Generic;
 
            class X : List<int>
            {
                void Add(object x)
                {
                    Console.WriteLine(1);
                }
 
                void Add(string x)
                {
                    Console.WriteLine(2);
                }
 
                static void Main()
                {
                    X z = new X { [|"" as object|] };
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545607")]
    public Task RemoveUnneededCastInArrayInitializer()
        => TestInRegularAndScriptAsync(
        """
        class X
        {
            static void Goo()
            {
                string x = ";
                var s = new object[] { [|x as object|] };
            }
        }
        """,
 
        """
        class X
        {
            static void Goo()
            {
                string x = ";
                var s = new object[] { x };
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545608")]
    public Task DoNotRemoveNecessaryCastWithImplicitUserDefinedConversion()
        => TestMissingInRegularAndScriptAsync(
            """
            class X
            {
                static void Goo()
                {
                    X x = null;
                    object y = [|x as string|];
                }
 
                public static implicit operator string(X x)
                {
                    return ";
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545941")]
    public Task DoNotRemoveNecessaryCastWithImplicitConversionInThrow()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class E
            {
                public static implicit operator Exception(E e)
                {
                    return new Exception();
                }
 
                static void Main()
                {
                    throw [|new E() as Exception|];
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545981")]
    public Task DoNotRemoveNecessaryCastInThrow()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void Main()
                {
                    object ex = new Exception();
                    throw [|ex as Exception|];
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545941")]
    public Task RemoveUnnecessaryCastInThrow()
        => TestInRegularAndScriptAsync(
        """
        using System;
 
        class E
        {
            static void Main()
            {
                throw [|new Exception() as Exception|];
            }
        }
        """,
 
        """
        using System;
 
        class E
        {
            static void Main()
            {
                throw new Exception();
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545945")]
    public Task DoNotRemoveNecessaryDowncast()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                void Goo(object y)
                {
                    var x = [|y as string|];
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545606")]
    public Task DoNotRemoveNecessaryCastFromNullToTypeParameter()
        => TestMissingInRegularAndScriptAsync(
            """
            class X
            {
                static void Goo<T, S>() where T : class, S
                {
                    S y = [|null as T|];
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545744")]
    public Task DoNotRemoveNecessaryCastInImplicitlyTypedArray()
        => TestMissingInRegularAndScriptAsync(
            """
            class X
            {
                static void Goo()
                {
                    string x = ";
                    var s = new[] { [|x as object|] };
                    s[0] = 1;
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545750")]
    public Task RemoveUnnecessaryCastToBaseType()
        => TestInRegularAndScriptAsync(
        """
        class X
        {
            static void Main()
            {
                var s = ([|new X() as object|]).ToString();
            }
 
            public override string ToString()
            {
                return ";
            }
        }
        """,
 
        """
        class X
        {
            static void Main()
            {
                var s = new X().ToString();
            }
 
            public override string ToString()
            {
                return ";
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545855")]
    public Task DoRemoveIllegalAsCastOnLambda()
        => TestMissingInRegularAndScriptAsync(
        """
        using System;
        using System.Collections.Generic;
        using System.Reflection;
 
        static class Program
        {
            static void Main()
            {
                FieldInfo[] fields = typeof(Exception).GetFields();
                Console.WriteLine(fields.Any([|(field => field.IsStatic) as Func<FieldInfo, bool>|]));
            }
 
            static bool Any<T>(this IEnumerable<T> s, Func<T, bool> predicate)
            {
                return false;
            }
 
            static bool Any<T>(this ICollection<T> s, Func<T, bool> predicate)
            {
                return true;
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529816")]
    public Task RemoveUnnecessaryCastInQueryExpression()
        => TestInRegularAndScriptAsync(
        """
        using System;
 
        class A
        {
            int Select(Func<int, string> x) { return 1; }
 
            static void Main()
            {
                Console.WriteLine(from y in new A() select [|"" as string|]);
            }
        }
        """,
 
        """
        using System;
 
        class A
        {
            int Select(Func<int, string> x) { return 1; }
 
            static void Main()
            {
                Console.WriteLine(from y in new A() select "");
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529816")]
    public Task DoNotRemoveNecessaryCastInQueryExpression()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class A
            {
                int Select(Func<int, string> x)
                {
                    return 1;
                }
 
                int Select(Func<int, object> x)
                {
                    return 2;
                }
 
                static void Main()
                {
                    Console.WriteLine(from y in new A()
                                      select [|"" as object|]);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529831")]
    public Task DoNotRemoveNecessaryCastFromTypeParameterToInterface()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            interface IIncrementable
            {
                int Value { get; }
 
                void Increment();
            }
 
            struct S : IIncrementable
            {
                public int Value { get; private set; }
 
                public void Increment()
                {
                    Value++;
                }
            }
 
            class C : IIncrementable
            {
                public int Value { get; private set; }
 
                public void Increment()
                {
                    Value++;
                }
            }
 
            static class Program
            {
                static void Main()
                {
                    Goo(new S(), new C());
                }
 
                static void Goo<TAny, TClass>(TAny x, TClass y)
                    where TAny : IIncrementable
                    where TClass : class, IIncrementable
                {
                    ([|x as IIncrementable|]).Increment(); // False Unnecessary Cast
                    ((IIncrementable)y).Increment(); // Unnecessary Cast - OK
 
                    Console.WriteLine(x.Value);
                    Console.WriteLine(y.Value);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529831")]
    public Task RemoveUnnecessaryCastFromTypeParameterToInterface()
        => TestInRegularAndScriptAsync(
        """
        using System;
 
        interface IIncrementable
        {
            int Value { get; }
            void Increment();
        }
 
        struct S : IIncrementable
        {
            public int Value { get; private set; }
            public void Increment() { Value++; }
        }
 
        class C: IIncrementable
        {
            public int Value { get; private set; }
            public void Increment() { Value++; }
        }
 
        static class Program
        {
            static void Main()
            {
                Goo(new S(), new C());
            }
 
            static void Goo<TAny, TClass>(TAny x, TClass y) 
                where TAny : IIncrementable
                where TClass : class, IIncrementable
            {
                ((IIncrementable)x).Increment(); // False Unnecessary Cast
                ([|y as IIncrementable|]).Increment(); // Unnecessary Cast - OK
 
                Console.WriteLine(x.Value);
                Console.WriteLine(y.Value);
            }
        }
        """,
        """
         using System;
 
         interface IIncrementable
         {
             int Value { get; }
             void Increment();
         }
 
         struct S : IIncrementable
         {
             public int Value { get; private set; }
             public void Increment() { Value++; }
         }
 
         class C: IIncrementable
         {
             public int Value { get; private set; }
             public void Increment() { Value++; }
         }
 
         static class Program
         {
             static void Main()
             {
                 Goo(new S(), new C());
             }
 
             static void Goo<TAny, TClass>(TAny x, TClass y) 
                 where TAny : IIncrementable
                 where TClass : class, IIncrementable
             {
                 ((IIncrementable)x).Increment(); // False Unnecessary Cast
                 y.Increment(); // Unnecessary Cast - OK
 
                 Console.WriteLine(x.Value);
                 Console.WriteLine(y.Value);
             }
         }
         """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545877")]
    public Task DoNotCrashOnIncompleteMethodDeclaration()
        => TestInRegularAndScriptAsync(
            """
            using System;
 
            class A
            {
                static void Main()
                {
                    string
                    Goo(x => 1, [|"" as string|]);
                }
 
                static void Goo<T, S>(T x, )
                {
                }
            }
            """,
            """
            using System;
 
            class A
            {
                static void Main()
                {
                    string
                    Goo(x => 1, "");
                }
 
                static void Goo<T, S>(T x, )
                {
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529791")]
    public Task RemoveUnnecessaryCastToNullable1()
        => TestInRegularAndScriptAsync(
        """
        class X
        {
            static void Goo()
            {
                object x = (string)null;
                object y = [|null as int?|];
            }
        }
        """,
 
        """
        class X
        {
            static void Goo()
            {
                object x = (string)null;
                object y = null;
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545850")]
    public Task RemoveSurroundingParentheses()
        => TestInRegularAndScriptAsync(
        """
        class Program
        {
            static void Main()
            {
                string x = "";
                ([|x as string|]).ToString();
            }
        }
        """,
 
        """
        class Program
        {
            static void Main()
            {
                string x = "";
                x.ToString();
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529846")]
    public Task DoNotRemoveNecessaryCastFromTypeParameterToObject()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                static void Goo<T>(T x, object y)
                {
                    if (([|x as object|]) == y)
                    {
                    }
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545858")]
    public Task DoNotRemoveNecessaryCastFromDelegateTypeToMulticastDelegate()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void Main()
                {
                    Action x = Console.WriteLine;
                    Action y = Console.WriteLine;
                    Console.WriteLine(([|x as MulticastDelegate|]) == y);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529842")]
    public Task DoNotRemoveNecessaryCastInTernaryExpression()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class X
            {
                public static implicit operator string(X x)
                {
                    return x.ToString();
                }
 
                static void Main()
                {
                    bool b = true;
                    X x = new X();
                    Console.WriteLine(b ? [|null as string|] : x);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545882"), WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/880752")]
    public Task RemoveCastInConstructorInitializer1()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                C(string x) { }
                C() : this([|"" as string|]) { }
            }
            """,
 
            """
            class C
            {
                C(string x) { }
                C() : this("") { }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545958"), WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/880752")]
    public Task RemoveCastInConstructorInitializer2()
        => TestInRegularAndScriptAsync(
            """
            using System.Collections;
 
            class C
            {
                C(int x) { }
                C(object x) { }
                C() : this([|"" as IEnumerable|]) { }
            }
            """,
 
            """
            using System.Collections;
 
            class C
            {
                C(int x) { }
                C(object x) { }
                C() : this("") { }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545957")]
    public Task DoNotRemoveCastInConstructorInitializer3()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                C(string x)
                {
                }
 
                C() : this([|"" as object|])
                {
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545842")]
    public Task RemoveCastToNullableInArithmeticExpression()
        => TestInRegularAndScriptAsync(
            """
            static class C
            {
                static void Main()
                {
                    int? x = 1;
                    long y = 2;
                    long? z = x + ([|y as long?|]);
                }
            }
            """,
 
            """
            static class C
            {
                static void Main()
                {
                    int? x = 1;
                    long y = 2;
                    long? z = x + y;
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545942")]
    public Task DoNotRemoveCastFromStringTypeToObjectInReferenceEquality()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                static void Main()
                {
                    object x = "";
                    Console.WriteLine(x == ([|"" as object|]));
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545962")]
    public Task DoNotRemoveCastWhenExpressionDoesntBind()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                static void Main()
                {
                    ([|x as IDisposable|]).Dispose();
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545944")]
    public Task DoNotRemoveNecessaryCastBeforePointerDereference1()
        => TestMissingInRegularAndScriptAsync(
            """
            unsafe class C
            {
                int x = *([|null as int*|]);
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545978")]
    public Task DoNotRemoveNecessaryCastBeforePointerDereference2()
        => TestMissingInRegularAndScriptAsync(
            """
            unsafe class C
            {
                static void Main()
                {
                    void* p = null;
                    int x = *([|p as int*|]);
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26640")]
    public Task DoNotRemoveCastToByteFromIntInConditionalExpression_CSharp8()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                object M1(bool b)
                {
                    return [|b ? (1 as byte?) : (0 as byte?)|];
                }
            }
            """, new TestParameters(parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp8)));
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26640")]
    public Task DoNotRemoveCastToByteFromIntInConditionalExpression_CSharp9()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                object M1(bool b)
                {
                    return [|b ? (1 as byte?) : (0 as byte?)|];
                }
            }
            """, new TestParameters(parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp9)));
 
    #region Interface Casts
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545889")]
    public Task DoNotRemoveCastToInterfaceForUnsealedType()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class X : IDisposable
            {
                static void Main()
                {
                    X x = new Y();
                    ([|x as IDisposable|]).Dispose();
                }
 
                public void Dispose()
                {
                    Console.WriteLine("X.Dispose");
                }
            }
 
            class Y : X, IDisposable
            {
                void IDisposable.Dispose()
                {
                    Console.WriteLine("Y.Dispose");
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545890")]
    public Task DoRemoveCastToInterfaceForSealedType1()
        => TestInRegularAndScriptAsync(
            """
            using System;
 
            interface I
            {
                void Goo(int x = 0);
            }
 
            sealed class C : I
            {
                public void Goo(int x = 0)
                {
                    Console.WriteLine(x);
                }
 
                static void Main()
                {
                    ([|new C() as I|]).Goo();
                }
            }
            """,
            """
            using System;
 
            interface I
            {
                void Goo(int x = 0);
            }
 
            sealed class C : I
            {
                public void Goo(int x = 0)
                {
                    Console.WriteLine(x);
                }
 
                static void Main()
                {
                    new C().Goo();
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545890")]
    public Task DoRemoveCastToInterfaceForSealedType2()
        => TestInRegularAndScriptAsync(
            """
            using System;
 
            interface I
            {
                string Goo { get; }
            }
 
            sealed class C : I
            {
                public string Goo
                {
                    get
                    {
                        return "Nikov Rules";
                    }
                }
 
                static void Main()
                {
                    Console.WriteLine(([|new C() as I|]).Goo);
                }
            }
            """,
            """
            using System;
 
            interface I
            {
                string Goo { get; }
            }
 
            sealed class C : I
            {
                public string Goo
                {
                    get
                    {
                        return "Nikov Rules";
                    }
                }
 
                static void Main()
                {
                    Console.WriteLine(new C().Goo);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545890")]
    public Task DoNotRemoveCastToInterfaceForSealedType3()
        => TestMissingAsync(
            """
            using System;
 
            interface I
            {
                string Goo { get; }
            }
 
            sealed class C : I
            {
                public C Instance { get { return new C(); } }
 
                public string Goo
                {
                    get
                    {
                        return "Nikov Rules";
                    }
                }
 
                static void Main()
                {
                    Console.WriteLine(([|Instance as I|]).Goo);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545890")]
    public Task DoNotRemoveCastToInterfaceForSealedType4()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            interface I
            {
                void Goo(int x = 0);
            }
 
            sealed class C : I
            {
                public void Goo(int x = 1)
                {
                    Console.WriteLine(x);
                }
 
                static void Main()
                {
                    ([|new C() as I|]).Goo();
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545890")]
    public Task DoRemoveCastToInterfaceForSealedTypeWhenDefaultValuesAreDifferentButParameterIsPassed()
        => TestInRegularAndScriptAsync(
            """
            using System;
 
            interface I
            {
                void Goo(int x = 0);
            }
 
            sealed class C : I
            {
                public void Goo(int x = 1)
                {
                    Console.WriteLine(x);
                }
 
                static void Main()
                {
                    ([|new C() as I|]).Goo(2);
                }
            }
            """,
            """
            using System;
 
            interface I
            {
                void Goo(int x = 0);
            }
 
            sealed class C : I
            {
                public void Goo(int x = 1)
                {
                    Console.WriteLine(x);
                }
 
                static void Main()
                {
                    new C().Goo(2);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545888")]
    public Task DoNotRemoveCastToInterfaceForSealedType6()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            interface I
            {
                void Goo(int x = 0, int y = 0);
            }
 
            sealed class C : I
            {
                public void Goo(int y = 0, int x = 0)
                {
                    Console.WriteLine(x);
                }
 
                static void Main()
                {
                    ([|new C() as I|]).Goo(x: 1);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545888")]
    public Task DoNotRemoveCastToInterfaceForSealedType7()
        => TestMissingAsync(
            """
            using System;
 
            interface I
            {
                int this[int x = 0, int y = 0] { get; }
            }
 
            sealed class C : I
            {
                public int this[int x = 0, int y = 0]
                {
                    get
                    {
                        return x * 2;
                    }
                }
 
                static void Main()
                {
                    Console.WriteLine(([|new C() as I|])[x: 1]);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545888")]
    public Task DoNotRemoveCastToInterfaceForSealedType8()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            interface I
            {
                int this[int x = 0, int y = 0] { get; }
            }
 
            sealed class C : I
            {
                public int this(int y = 0, int x = 0)
                {
                    get
                    {
                        return x * 2;
                    }
                }
 
                static void Main()
                {
                    Console.WriteLine(([|new C() as I|])[x: 1]);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545883")]
    public Task DoNotRemoveCastToInterfaceForSealedType9()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
            using System.IO;
 
            sealed class C : MemoryStream
            {
                static void Main()
                {
                    C s = new C();
                    ([|s as IDisposable|]).Dispose();
                }
 
                new public void Dispose()
                {
                    Console.WriteLine("new Dispose()");
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545887")]
    public Task DoNotRemoveCastToInterfaceForStruct1()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            interface IIncrementable
            {
                int Value { get; }
 
                void Increment();
            }
 
            struct S : IIncrementable
            {
                public int Value { get; private set; }
 
                public void Increment()
                {
                    Value++;
                }
 
                static void Main()
                {
                    var s = new S();
                    ([|s as IIncrementable|]).Increment();
                    Console.WriteLine(s.Value);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545834")]
    public Task RemoveCastToInterfaceForStruct2()
        => TestInRegularAndScriptAsync(
        """
        using System;
        using System.Collections.Generic;
 
        class Program
        {
            static void Main()
            {
                ([|GetEnumerator() as IDisposable|]).Dispose();
            }
 
            static List<int>.Enumerator GetEnumerator()
            {
                var x = new List<int> { 1, 2, 3 };
                return x.GetEnumerator();
            }
        }
        """,
 
        """
        using System;
        using System.Collections.Generic;
 
        class Program
        {
            static void Main()
            {
                GetEnumerator().Dispose();
            }
 
            static List<int>.Enumerator GetEnumerator()
            {
                var x = new List<int> { 1, 2, 3 };
                return x.GetEnumerator();
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544655")]
    public Task RemoveCastToICloneableForDelegate()
        => TestInRegularAndScriptAsync(
        """
        using System;
 
        class C
        {
            static void Main()
            {
                Action a = () => { };
                var c = ([|a as ICloneable|]).Clone();
            }
        }
        """,
 
        """
        using System;
 
        class C
        {
            static void Main()
            {
                Action a = () => { };
                var c = a.Clone();
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545926")]
    public Task RemoveCastToICloneableForArray()
        => TestInRegularAndScriptAsync(
        """
        using System;
 
        class C
        {
            static void Main()
            {
                var a = new[] { 1, 2, 3 };
                var c = ([|a as ICloneable|]).Clone(); 
            }
        }
        """,
 
        """
        using System;
 
        class C
        {
            static void Main()
            {
                var a = new[] { 1, 2, 3 };
                var c = a.Clone(); 
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529897")]
    public Task RemoveCastToIConvertibleForEnum()
        => TestInRegularAndScriptAsync(
        """
        using System;
 
        class Program
        {
            static void Main()
            {
                Enum e = DayOfWeek.Monday;
                var y = ([|e as IConvertible|]).GetTypeCode();
            }
        }
        """,
 
        """
        using System;
 
        class Program
        {
            static void Main()
            {
                Enum e = DayOfWeek.Monday;
                var y = e.GetTypeCode();
            }
        }
        """);
 
    #endregion
 
    #region ParamArray Parameter Casts
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545141")]
    public Task DoNotRemoveCastToObjectInParamArrayArg1()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void Main()
                {
                    Goo([|null as object|]);
                }
 
                static void Goo(params object[] x)
                {
                    Console.WriteLine(x.Length);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529911")]
    public Task DoNotRemoveCastToIntArrayInParamArrayArg2()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void Main()
                {
                    Goo([|null as int[]|]);
                }
 
                static void Goo(params object[] x)
                {
                    Console.WriteLine(x.Length);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529911")]
    public Task DoNotRemoveCastToObjectArrayInParamArrayArg3()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void Main()
                {
                    Goo([|null as object[]|]);
                }
 
                static void Goo(params object[][] x)
                {
                    Console.WriteLine(x.Length);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529911")]
    public Task RemoveCastToObjectArrayInParamArrayArg1()
        => TestInRegularAndScriptAsync(
        """
        class C
        {
            static void Goo(params object[] x) { }
 
            static void Main()
            {
                Goo([|null as object[]|]);
            }
        }
        """,
 
        """
        class C
        {
            static void Goo(params object[] x) { }
 
            static void Main()
            {
                Goo(null);
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529911")]
    public Task RemoveCastToStringArrayInParamArrayArg2()
        => TestInRegularAndScriptAsync(
        """
        class C
        {
            static void Goo(params object[] x) { }
 
            static void Main()
            {
                Goo([|null as string[]|]);
            }
        }
        """,
 
        """
        class C
        {
            static void Goo(params object[] x) { }
 
            static void Main()
            {
                Goo(null);
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529911")]
    public Task RemoveCastToIntArrayInParamArrayArg3()
        => TestInRegularAndScriptAsync(
        """
        class C
        {
            static void Goo(params int[] x) { }
 
            static void Main()
            {
                Goo([|null as int[]|]);
            }
        }
        """,
 
        """
        class C
        {
            static void Goo(params int[] x) { }
 
            static void Main()
            {
                Goo(null);
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529911")]
    public Task RemoveCastToObjectArrayInParamArrayArg4()
        => TestInRegularAndScriptAsync(
        """
        class C
        {
            static void Goo(params object[] x) { }
 
            static void Main()
            {
                Goo([|null as object[]|], null);
            }
        }
        """,
 
        """
        class C
        {
            static void Goo(params object[] x) { }
 
            static void Main()
            {
                Goo(null, null);
            }
        }
        """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529911")]
    public Task RemoveCastToObjectInParamArrayArg5()
        => TestInRegularAndScriptAsync(
        """
        class C
        {
            static void Goo(params object[] x) { }
 
            static void Main()
            {
                Goo([|null as object|], null);
            }
        }
        """,
 
        """
        class C
        {
            static void Goo(params object[] x) { }
 
            static void Main()
            {
                Goo(null, null);
            }
        }
        """);
 
    [Fact]
    public Task RemoveCastToObjectArrayInParamArrayWithNamedArgument()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                static void Main()
                {
                    Goo(x: [|null as object[]|]);
                }
 
                static void Goo(params object[] x) { }
            }
            """,
            """
            class C
            {
                static void Main()
                {
                    Goo(x: null);
                }
 
                static void Goo(params object[] x) { }
            }
            """);
 
    #endregion
 
    #region ForEach Statements
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545961")]
    public Task DoNotRemoveNecessaryCastInForEach1()
        => TestMissingInRegularAndScriptAsync(
            """
            using System.Collections;
 
            class Program
            {
                static void Main()
                {
                    object s = ";
                    foreach (object x in [|s as IEnumerable|])
                    {
                    }
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545961")]
    public Task DoNotRemoveNecessaryCastInForEach2()
        => TestMissingInRegularAndScriptAsync(
            """
            using System.Collections.Generic;
 
            class Program
            {
                static void Main()
                {
                    object s = ";
                    foreach (object x in [|s as IEnumerable<char>|])
                    {
                    }
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545961")]
    public Task DoNotRemoveNecessaryCastInForEach3()
        => TestMissingInRegularAndScriptAsync(
            """
            using System.Collections;
 
            class D
            {
                public IEnumerator GetEnumerator()
                {
                    yield return 1;
                }
            }
 
            class C
            {
                public static implicit operator D(C c)
                {
                    return new D();
                }
 
                static void Main()
                {
                    object s = ";
                    foreach (object x in [|new C() as D|])
                    {
                    }
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545961")]
    public Task DoNotRemoveNecessaryCastInForEach4()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
            using System.Collections;
 
            class D
            {
                public IEnumerator GetEnumerator()
                {
                    yield return 1;
                }
            }
 
            class C
            {
                public IEnumerator GetEnumerator()
                {
                    yield return 2;
                }
 
                public static implicit operator D(C c)
                {
                    return new D();
                }
 
                static void Main()
                {
                    object s = ";
                    foreach (object x in [|new C() as D|])
                    {
                        Console.WriteLine(x);
                    }
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545961")]
    public Task DoNotRemoveNecessaryCastInForEach5()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                static void Main()
                {
                    string[] s = {
                        "A"
                    };
                    foreach (var x in [|s as Array|])
                    {
                        var y = x;
                        y = 1;
                    }
                }
            }
            """);
 
    #endregion
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545925")]
    public Task DoNotRemoveCastIfOverriddenMethodHasIncompatibleParameterList()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            abstract class Y
            {
                public abstract void Goo(int x = 1);
            }
 
            class X : Y
            {
                static void Main()
                {
                    ([|new X() as Y|]).Goo();
                }
 
                public override void Goo(int x = 2)
                {
                    Console.WriteLine(x);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545925")]
    public Task RemoveCastIfOverriddenMethodHaveCompatibleParameterList()
        => TestInRegularAndScriptAsync(
            """
            using System;
 
            abstract class Y
            {
                public abstract void Goo(int x = 1);
            }
 
            class X : Y
            {
                static void Main()
                {
                    ([|new X() as Y|]).Goo();
                }
 
                public override void Goo(int x = 1)
                {
                    Console.WriteLine(x);
                }
            }
            """,
 
            """
            using System;
 
            abstract class Y
            {
                public abstract void Goo(int x = 1);
            }
 
            class X : Y
            {
                static void Main()
                {
                    new X().Goo();
                }
 
                public override void Goo(int x = 1)
                {
                    Console.WriteLine(x);
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529916")]
    public Task RemoveCastInReceiverForMethodGroup()
        => TestInRegularAndScriptAsync(
            """
            using System;
 
            static class Program
            {
                static void Main()
                {
                    Action a = ([|"" as string|]).Goo;
                }
 
                static void Goo(this string x) { }
            }
            """,
 
            """
            using System;
 
            static class Program
            {
                static void Main()
                {
                    Action a = "".Goo;
                }
 
                static void Goo(this string x) { }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/609497")]
    public Task Bugfix_609497()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
            using System.Threading.Tasks;
 
            class Program
            {
                static void Main()
                {
                    Goo().Wait();
                }
 
                static async Task Goo()
                {
                    Task task = Task.FromResult(0);
                    Console.WriteLine(await ([|task as dynamic|]));
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/624252")]
    [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/608180")]
    public Task DoNotRemoveCastIfArgumentIsRestricted_TypedReference()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                static void Main(string[] args)
                {
                }
 
                static void v(dynamic x)
                {
                    var y = default(TypedReference);
                    dd([|x as object|], y);
                }
 
                static void dd(object obj, TypedReference d)
                {
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/627107")]
    public Task DoNotRemoveCastOnArgumentsWithOtherDynamicArguments()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                static void Main()
                {
                    C<string>.InvokeGoo(0);
                }
            }
 
            class C<T>
            {
                public static void InvokeGoo(dynamic x)
                {
                    Console.WriteLine(Goo(x, [|"" as object|], ""));
                }
 
                static void Goo(int x, string y, T z)
                {
                }
 
                static bool Goo(int x, object y, object z)
                {
                    return true;
                }
            
                static bool Goo(long x, object y, object z)
                {
                    return true;
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/627107")]
    public Task DoNotRemoveCastOnArgumentsWithOtherDynamicArguments_Bracketed()
        => TestMissingInRegularAndScriptAsync(
            """
            class C<T>
            {
                int this[int x, T s, string d = "abc"]
                {
                    get
                    {
                        return 0;
                    }
 
                    set
                    {
                    }
                }
 
                int this[int x, object s, object d]
                {
                    get
                    {
                        return 0;
                    }
 
                    set
                    {
                    }
                }
            
                int this[long x, object s, string d]
                {
                    get
                    {
                        return 0;
                    }
            
                    set
                    {
                    }
                }
            
                void Goo(dynamic xx)
                {
                    var y = this[x: xx, s: "", d: [|"" as object|]];
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/627107")]
    public Task DoNotRemoveCastOnArgumentsWithDynamicReceiverOpt()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                static bool Goo(dynamic d)
                {
                    d([|"" as object|]);
                    return true;
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/627107")]
    public Task DoNotRemoveCastOnArgumentsWithDynamicReceiverOpt_1()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                static bool Goo(dynamic d)
                {
                    d.goo([|"" as object|]);
                    return true;
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/627107")]
    public Task DoNotRemoveCastOnArgumentsWithDynamicReceiverOpt_2()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                static bool Goo(dynamic d)
                {
                    d.goo.bar.goo([|"" as object|]);
                    return true;
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/627107")]
    public Task DoNotRemoveCastOnArgumentsWithDynamicReceiverOpt_3()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                static bool Goo(dynamic d)
                {
                    d.goo().bar().goo([|"" as object|]);
                    return true;
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/627107")]
    public Task DoNotRemoveCastOnArgumentsWithOtherDynamicArguments_1()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                static void Main()
                {
                    C<string>.InvokeGoo(0);
                }
            }
 
            class C<T>
            {
                public static void InvokeGoo(dynamic x)
                {
                    Console.WriteLine(Goo([|"" as object|], x, ""));
                }
 
                static void Goo(string y, int x, T z)
                {
                }
 
                static bool Goo(object y, int x, object z)
                {
                    return true;
                }
 
                static bool Goo(object y, long x, object z)
                {
                    return true;
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529846")]
    public Task DoNotUnnecessaryCastFromTypeParameterToObject()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                static void Goo<T>(T x, object y)
                {
                    if (([|x as object|]) == y)
                    {
                    }
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/640136")]
    public Task RemoveUnnecessaryCastAndParseCorrect()
        => TestInRegularAndScriptAsync(
            """
            using System;
            using System.Threading.Tasks;
 
            class C
            {
                void Goo(Task<Action> x)
                {
                    (([|x as Task<Action>|]).Result)();
                }
            }
            """,
 
            """
            using System;
            using System.Threading.Tasks;
 
            class C
            {
                void Goo(Task<Action> x)
                {
                    (x.Result)();
                }
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/626026")]
    public Task DoNotRemoveCastIfUserDefinedExplicitCast()
        => TestMissingInRegularAndScriptAsync(
            """
            class Program
            {
                static void Main(string[] args)
                {
                    B bar = new B();
                    A a = [|bar as A|];
                }
            }
 
            public class A
            {
                public static explicit operator A(B b)
                {
                    return new A();
                }
            }
 
            public struct B
            {
            }
            """);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/770187")]
    public Task DoNotRemoveNecessaryCastInSwitchExpression()
        => TestMissingInRegularAndScriptAsync(
            """
            namespace ConsoleApplication23
            {
                class Program
                {
                    static void Main(string[] args)
                    {
                        int goo = 0;
                        switch ([|goo as E?|])
                        {
                            case E.A:
                            case E.B:
                                return;
                        }
                    }
                }
 
                enum E
                {
                    A,
                    B,
                    C
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/2761")]
    [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/844482")]
    public Task DoNotRemoveCastFromBaseToDerivedWithExplicitReference()
        => TestMissingInRegularAndScriptAsync(
            """
            class Program
            {
                static void Main(string[] args)
                {
                    C x = null;
                    C y = null;
                    y = [|x as D|];
                }
            }
 
            class C
            {
            }
 
            class D : C
            {
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/3254")]
    public Task DoNotRemoveCastToTypeParameterWithExceptionConstraint()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                private static void RequiresCondition<TException>(bool condition, string messageOnFalseCondition) where TException : Exception
                {
                    if (!condition)
                    {
                        throw [|Activator.CreateInstance(typeof(TException), messageOnFalseCondition) as TException|];
                    }
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/3254")]
    public Task DoNotRemoveCastToTypeParameterWithExceptionSubTypeConstraint()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                private static void RequiresCondition<TException>(bool condition, string messageOnFalseCondition) where TException : ArgumentException
                {
                    if (!condition)
                    {
                        throw [|Activator.CreateInstance(typeof(TException), messageOnFalseCondition) as TException|];
                    }
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/8111")]
    public Task DoNotRemoveCastThatChangesShapeOfAnonymousTypeObject()
        => TestMissingInRegularAndScriptAsync(
            """
            class Program
            {
                static void Main(object o)
                {
                    object thing = new { shouldBeAString = [|o as string|] };
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/8111")]
    public Task RemoveCastThatDoesntChangeShapeOfAnonymousTypeObject()
        => TestInRegularAndScriptAsync(
            """
            class Program
            {
                static void Main(string o)
                {
                    object thing = new { shouldBeAString = [|o as string|] };
                }
            }
            """,
 
            """
            class Program
            {
                static void Main(string o)
                {
                    object thing = new { shouldBeAString = o };
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/18978")]
    public Task DoNotRemoveCastOnCallToMethodWithParamsArgs()
        => TestMissingInRegularAndScriptAsync(
            """
            class Program
            {
                public static void Main(string[] args)
                {
                    var takesArgs = new[] { "Hello", "World" };
                    TakesParams([|takesArgs as object|]);
                }
 
                private static void TakesParams(params object[] goo)
                {
                    Console.WriteLine(goo.Length);
                }
            }
            """);
 
    [Fact]
    public Task DoRemoveCastOnCallToMethodWithIncorrectParamsArgs()
        => TestInRegularAndScriptAsync(
            """
            class Program
            {
                public static void Main(string[] args)
                {
                    TakesParams([|null as string|]);
                }
 
                private static void TakesParams(params string wrongDefined)
                {
                    Console.WriteLine(wrongDefined.Length);
                }
            }
            """,
            """
            class Program
            {
                public static void Main(string[] args)
                {
                    TakesParams(null);
                }
 
                private static void TakesParams(params string wrongDefined)
                {
                    Console.WriteLine(wrongDefined.Length);
                }
            }
            """);
 
    [Fact]
    public Task DoNotRemoveCastOnCallToMethodWithCorrectParamsArgs()
        => TestMissingInRegularAndScriptAsync(
            """
            class Program
            {
                public static void Main(string[] args)
                {
                    TakesParams([|null as string|]);
                }
 
                private static void TakesParams(params string[] wrongDefined)
                {
                    Console.WriteLine(wrongDefined.Length);
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/18978")]
    public Task RemoveCastOnCallToMethodWithParamsArgsIfImplicitConversionExists()
        => TestInRegularAndScriptAsync(
            """
            class Program
            {
                public static void Main(string[] args)
                {
                    var takesArgs = new[] { "Hello", "World" };
                    TakesParams([|takesArgs as System.IComparable[]|]);
                }
 
                private static void TakesParams(params object[] goo)
                {
                    System.Console.WriteLine(goo.Length);
                }
            }
            """,
            """
            class Program
            {
                public static void Main(string[] args)
                {
                    var takesArgs = new[] { "Hello", "World" };
                    TakesParams(takesArgs);
                }
 
                private static void TakesParams(params object[] goo)
                {
                    System.Console.WriteLine(goo.Length);
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/20630")]
    public Task DoNotRemoveCastOnCallToAttributeWithParamsArgs()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
            using System.Reflection;
 
            sealed class MarkAttribute : Attribute
            {
              public readonly string[] Arr;
 
              public MarkAttribute(params string[] arr)
              {
                Arr = arr;
              }
            }
            [Mark([|null as string|])]   // wrong instance of: IDE0004 Cast is redundant.
            static class Program
            {
              static void Main()
              {
              }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/29264")]
    public Task RemoveCastOnDictionaryIndexer()
        => TestInRegularAndScriptAsync(
            """
            using System;
            using System.Reflection;
            using System.Collections.Generic;
 
            static class Program
            {
                static void Main()
                {
                    Dictionary<string, string> Icons = new Dictionary<string, string>
                    {
                        [[|"" as string|]] = null,
                    };
                }
            }
            """,
            """
            using System;
            using System.Reflection;
            using System.Collections.Generic;
 
            static class Program
            {
                static void Main()
                {
                    Dictionary<string, string> Icons = new Dictionary<string, string>
                    {
                        [""] = null,
                    };
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/20630")]
    public Task DoNotRemoveCastOnCallToAttributeWithParamsArgsAndProperty()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
            sealed class MarkAttribute : Attribute
            {
                public MarkAttribute(params string[] arr)
                {
                }
                public int Prop { get; set; }
            }
 
            [Mark([|null as string|], Prop = 1)] 
            static class Program
            {
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/20630")]
    public Task DoNotRemoveCastOnCallToAttributeWithParamsArgsPropertyAndOtherArg()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
            sealed class MarkAttribute : Attribute
            {
                public MarkAttribute(bool otherArg, params string[] arr)
                {
                }
                public int Prop { get; set; }
            }
 
            [Mark(true, [|null as string|], Prop = 1)] 
            static class Program
            {
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/20630")]
    public Task DoNotRemoveCastOnCallToAttributeWithParamsArgsNamedArgsAndProperty()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
            sealed class MarkAttribute : Attribute
            {
                public MarkAttribute(bool otherArg, params string[] arr)
                {
                }
                public int Prop { get; set; }
            }
 
            [Mark(arr: [|null as string|], otherArg: true, Prop = 1)]
            static class Program
            {
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/20630")]
    public Task DoRemoveCastOnCallToAttributeWithInvalidParamsArgs()
        => TestInRegularAndScriptAsync(
            """
            using System;
            sealed class MarkAttribute : Attribute
            {
                public MarkAttribute(bool otherArg, params string wrongDefined)
                {
                }
                public int Prop { get; set; }
            }
 
            [Mark(true, [|null as string|], Prop = 1)]
            static class Program
            {
            }
            """,
            """
            using System;
            sealed class MarkAttribute : Attribute
            {
                public MarkAttribute(bool otherArg, params string wrongDefined)
                {
                }
                public int Prop { get; set; }
            }
 
            [Mark(true, null, Prop = 1)]
            static class Program
            {
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/20630")]
    public Task DoNotRemoveCastOfNullToParamsArg()
        => TestMissingAsync(
            """
            using System;
            using System.Reflection;
 
            class MarkAttribute : Attribute
            {
              public readonly string[] Arr;
 
              public MarkAttribute(params string[] arr)
              {
                Arr = arr;
              }
            }
 
            [Mark([|(string)|]null)]
            static class Program
            {
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/20630")]
    public Task RemoveCastOnCallToAttributeWithParamsArgsWithImplicitCast()
        => TestInRegularAndScriptAsync(
            """
            using System;
            sealed class MarkAttribute : Attribute
            {
                public MarkAttribute(bool otherArg, params object[] arr)
                {
                }
                public int Prop { get; set; }
            }
 
            [Mark(arr: [|new[] { "Hello", "World" } as object[]|], otherArg: true, Prop = 1)]
            static class Program
            {
            }
            """,
            """
            using System;
            sealed class MarkAttribute : Attribute
            {
                public MarkAttribute(bool otherArg, params object[] arr)
                {
                }
                public int Prop { get; set; }
            }
 
            [Mark(arr: new[] { "Hello", "World" }, otherArg: true, Prop = 1)]
            static class Program
            {
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25456#issuecomment-373549735")]
    public Task DoNotIntroduceDefaultLiteralInSwitchCase()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                void M()
                {
                    switch ("")
                    {
                        case [|default as string|]:
                            break;
                    }
                }
            }
            """, parameters: new TestParameters(new CSharpParseOptions(LanguageVersion.CSharp7_1)));
 
    [Fact]
    public Task DoNotIntroduceDefaultLiteralInSwitchCase_CastInsideParentheses()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                void M()
                {
                    switch ("")
                    {
                        case ([|default as string|]):
                            break;
                    }
                }
            }
            """, parameters: new TestParameters(new CSharpParseOptions(LanguageVersion.CSharp7_1)));
 
    [Fact]
    public Task DoNotIntroduceDefaultLiteralInSwitchCase_DefaultInsideParentheses()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                void M()
                {
                    switch ("")
                    {
                        case [|(default) as string|]:
                            break;
                    }
                }
            }
            """, parameters: new TestParameters(new CSharpParseOptions(LanguageVersion.CSharp7_1)));
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/27239")]
    public Task DoNotOfferToRemoveCastWhereNoConversionExists()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                void M()
                {
                    object o = null;
                    TypedReference r2 = [|o as TypedReference|];
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/28412")]
    public Task DoNotOfferToRemoveCastWhenAccessingHiddenProperty()
        => TestMissingInRegularAndScriptAsync("""
            using System.Collections.Generic;
            class Fruit
            {
                public IDictionary<string, object> Properties { get; set; }
            }
            class Apple : Fruit
            {
                public new IDictionary<string, object> Properties { get; }
            }
            class Tester
            {
                public void Test()
                {
                    var a = new Apple();
                    ([|a as Fruit|]).Properties["Color"] = "Red";
                }
            }
            """);
}