File: src\Analyzers\CSharp\Tests\UseImplicitOrExplicitType\UseImplicitTypeTests.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.
 
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Diagnostics.TypeStyle;
using Microsoft.CodeAnalysis.CSharp.TypeStyle;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
using Xunit.Abstractions;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.UseImplicitType;
 
[Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitType)]
public partial class UseImplicitTypeTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest_NoEditor
{
    public UseImplicitTypeTests(ITestOutputHelper? logger = null)
      : base(logger)
    {
    }
 
    internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
        => (new CSharpUseImplicitTypeDiagnosticAnalyzer(), new UseImplicitTypeCodeFixProvider());
 
    private static readonly CodeStyleOption2<bool> onWithSilent = new(true, NotificationOption2.Silent);
    private static readonly CodeStyleOption2<bool> onWithInfo = new(true, NotificationOption2.Suggestion);
    private static readonly CodeStyleOption2<bool> offWithInfo = new(false, NotificationOption2.Suggestion);
    private static readonly CodeStyleOption2<bool> onWithWarning = new(true, NotificationOption2.Warning);
    private static readonly CodeStyleOption2<bool> onWithError = new(true, NotificationOption2.Error);
 
    // specify all options explicitly to override defaults.
    internal OptionsCollection ImplicitTypeEverywhere()
        => new(GetLanguage())
        {
            { CSharpCodeStyleOptions.VarElsewhere, onWithInfo },
            { CSharpCodeStyleOptions.VarWhenTypeIsApparent, onWithInfo },
            { CSharpCodeStyleOptions.VarForBuiltInTypes, onWithInfo },
        };
 
    private OptionsCollection ImplicitTypeWhereApparent()
        => new(GetLanguage())
        {
            { CSharpCodeStyleOptions.VarElsewhere, offWithInfo },
            { CSharpCodeStyleOptions.VarWhenTypeIsApparent, onWithInfo },
            { CSharpCodeStyleOptions.VarForBuiltInTypes, offWithInfo },
        };
 
    private OptionsCollection ImplicitTypeWhereApparentAndForIntrinsics()
        => new(GetLanguage())
        {
            { CSharpCodeStyleOptions.VarElsewhere, offWithInfo },
            { CSharpCodeStyleOptions.VarWhenTypeIsApparent, onWithInfo },
            { CSharpCodeStyleOptions.VarForBuiltInTypes, onWithInfo },
        };
 
    internal OptionsCollection ImplicitTypeButKeepIntrinsics()
        => new(GetLanguage())
        {
            { CSharpCodeStyleOptions.VarElsewhere, onWithInfo },
            { CSharpCodeStyleOptions.VarForBuiltInTypes, offWithInfo },
            { CSharpCodeStyleOptions.VarWhenTypeIsApparent, onWithInfo },
        };
 
    private OptionsCollection ImplicitTypeEnforcements()
        => new(GetLanguage())
        {
            { CSharpCodeStyleOptions.VarElsewhere, onWithWarning },
            { CSharpCodeStyleOptions.VarWhenTypeIsApparent, onWithError },
            { CSharpCodeStyleOptions.VarForBuiltInTypes, onWithInfo },
        };
 
    private OptionsCollection ImplicitTypeSilentEnforcement()
        => new(GetLanguage())
        {
            { CSharpCodeStyleOptions.VarElsewhere, onWithSilent },
            { CSharpCodeStyleOptions.VarWhenTypeIsApparent, onWithSilent },
            { CSharpCodeStyleOptions.VarForBuiltInTypes, onWithSilent },
        };
 
    [Fact]
    public async Task NotOnFieldDeclaration()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                [|int|] _myfield = 5;
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotOnFieldLikeEvents()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                public event [|D|] _myevent;
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotOnConstants()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    const [|int|] x = 5;
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotOnNullLiteral()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    [|Program|] x = null;
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/27221")]
    public async Task NotOnRefVar()
    {
        await TestMissingInRegularAndScriptAsync("""
            class Program
            {
                void Method()
                {
                    ref [|var|] x = Method2();
                }
                ref int Method2() => throw null;
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotOnDynamic()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    [|dynamic|] x = 1;
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotOnAnonymousMethodExpression()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    [|Func<string, bool>|] comparer = delegate (string value) {
                        return value != "0";
                    };
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotOnLambdaExpression()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    [|Func<int, int>|] x = y => y * y;
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotOnMethodGroup()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    [|Func<string, string>|] copyStr = string.Copy;
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotOnDeclarationWithMultipleDeclarators()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    [|int|] x = 5, y = x;
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotOnDeclarationWithoutInitializer()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    [|Program|] x;
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotOnIFormattable()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    [|IFormattable|] s = $"Hello, {name}"
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotOnFormattableString()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    [|FormattableString|] s = $"Hello, {name}"
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotInCatchDeclaration()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    try
                    {
                    }
                    catch ([|Exception|] e)
                    {
                        throw;
                    }
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotDuringConflicts()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    [|Program|] p = new Program();
                }
 
                class var
                {
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotIfAlreadyImplicitlyTyped()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    [|var|] p = new Program();
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotOnImplicitConversion()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    int i = int.MaxValue;
                    [|long|] l = i;
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotOnBoxingImplicitConversion()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    int i = int.MaxValue;
                    [|object|] o = i;
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotOnRHS()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                void M()
                {
                    C c = new [|C|]();
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotOnVariablesUsedInInitalizerExpression()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                void M()
                {
                    [|int|] i = (i = 20);
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26894")]
    public async Task NotOnVariablesOfEnumTypeNamedAsEnumTypeUsedInInitalizerExpressionAtFirstPosition()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            enum A { X, Y }
 
            class C
            {
                void M()
                {
                    [|A|] A = A.X;
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26894")]
    public async Task NotOnVariablesNamedAsTypeUsedInInitalizerExpressionContainingTypeNameAtFirstPositionOfMemberAccess()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class A 
            { 
                public static A Instance;
            }
 
            class C
            {
                void M()
                {
                    [|A|] A = A.Instance;
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26894")]
    public async Task SuggestOnVariablesUsedInInitalizerExpressionAsInnerPartsOfQualifiedNameStartedWithGlobal()
    {
        await TestAsync(
            """
            enum A { X, Y }
 
            class C
            {
                void M()
                {
                    [|A|] A = global::A.X;
                }
            }
            """,
            """
            enum A { X, Y }
 
            class C
            {
                void M()
                {
                    var A = global::A.X;
                }
            }
            """, CSharpParseOptions.Default, options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26894")]
    public async Task SuggestOnVariablesUsedInInitalizerExpressionAsInnerPartsOfQualifiedName()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            namespace N
            {
                class A 
                { 
                    public static A Instance;
                }
            }
 
            class C
            {
                void M()
                {
                    [|N.A|] A = N.A.Instance;
                }
            }
            """,
            """
            using System;
 
            namespace N
            {
                class A 
                { 
                    public static A Instance;
                }
            }
 
            class C
            {
                void M()
                {
                    var A = N.A.Instance;
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26894")]
    public async Task SuggestOnVariablesUsedInInitalizerExpressionAsLastPartOfQualifiedName()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class A {}
 
            class X
            { 
                public static A A;
            }
 
            class C
            {
                void M()
                {
                    [|A|] A = X.A;
                }
            }
            """,
            """
            using System;
 
            class A {}
 
            class X
            { 
                public static A A;
            }
 
            class C
            {
                void M()
                {
                    var A = X.A;
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task NotOnAssignmentToInterfaceType()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                public void ProcessRead()
                {
                    [|IInterface|] i = new A();
                }
            }
 
            class A : IInterface
            {
            }
 
            interface IInterface
            {
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task NotOnArrayInitializerWithoutNewKeyword()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    [|int[]|] n1 = {
                        2,
                        4,
                        6,
                        8
                    };
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task SuggestVarOnLocalWithIntrinsicTypeString()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    [|string|] s = "hello";
                }
            }
            """,
            """
            using System;
 
            class C
            {
                static void M()
                {
                    var s = "hello";
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarOnIntrinsicType()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    [|int|] s = 5;
                }
            }
            """,
            """
            using System;
 
            class C
            {
                static void M()
                {
                    var s = 5;
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/27221")]
    public async Task SuggestVarOnRefIntrinsicType()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    ref [|int|] s = Ref();
                }
                static ref int Ref() => throw null;
            }
            """,
            """
            using System;
 
            class C
            {
                static void M()
                {
                    ref var s = Ref();
                }
                static ref int Ref() => throw null;
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/27221")]
    public async Task WithRefIntrinsicTypeInForeach()
    {
        var before = """
            class E
            {
                public ref int Current => throw null;
                public bool MoveNext() => throw null;
                public E GetEnumerator() => throw null;
 
                void M()
                {
                    foreach (ref [|int|] x in this) { }
                }
            }
            """;
        var after = """
            class E
            {
                public ref int Current => throw null;
                public bool MoveNext() => throw null;
                public E GetEnumerator() => throw null;
 
                void M()
                {
                    foreach (ref var x in this) { }
                }
            }
            """;
        await TestInRegularAndScriptAsync(before, after, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarOnFrameworkType()
    {
        await TestInRegularAndScriptAsync(
            """
            using System.Collections.Generic;
 
            class C
            {
                static void M()
                {
                    [|List<int>|] c = new List<int>();
                }
            }
            """,
            """
            using System.Collections.Generic;
 
            class C
            {
                static void M()
                {
                    var c = new List<int>();
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarOnUserDefinedType()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                void M()
                {
                    [|C|] c = new C();
                }
            }
            """,
            """
            using System;
 
            class C
            {
                void M()
                {
                    var c = new C();
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarOnGenericType()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C<T>
            {
                static void M()
                {
                    [|C<int>|] c = new C<int>();
                }
            }
            """,
            """
            using System;
 
            class C<T>
            {
                static void M()
                {
                    var c = new C<int>();
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarOnSeeminglyConflictingType()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class var<T>
            {
                void M()
                {
                    [|var<int>|] c = new var<int>();
                }
            }
            """,
            """
            using System;
 
            class var<T>
            {
                void M()
                {
                    var c = new var<int>();
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarOnSingleDimensionalArrayTypeWithNewOperator()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    [|int[]|] n1 = new int[4] { 2, 4, 6, 8 };
                }
            }
            """,
            """
            using System;
 
            class C
            {
                static void M()
                {
                    var n1 = new int[4] { 2, 4, 6, 8 };
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarOnSingleDimensionalArrayTypeWithNewOperator2()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    [|int[]|] n1 = new[] { 2, 4, 6, 8 };
                }
            }
            """,
            """
            using System;
 
            class C
            {
                static void M()
                {
                    var n1 = new[] { 2, 4, 6, 8 };
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarOnSingleDimensionalJaggedArrayType()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    [|int[][]|] cs = new[] {
                        new[] { 1, 2, 3, 4 },
                        new[] { 5, 6, 7, 8 }
                    };
                }
            }
            """,
            """
            using System;
 
            class C
            {
                static void M()
                {
                    var cs = new[] {
                        new[] { 1, 2, 3, 4 },
                        new[] { 5, 6, 7, 8 }
                    };
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarOnDeclarationWithObjectInitializer()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    [|Customer|] cc = new Customer { City = "Madras" };
                }
 
                private class Customer
                {
                    public string City { get; set; }
                }
            }
            """,
            """
            using System;
 
            class C
            {
                static void M()
                {
                    var cc = new Customer { City = "Madras" };
                }
 
                private class Customer
                {
                    public string City { get; set; }
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarOnDeclarationWithCollectionInitializer()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
            using System.Collections.Generic;
 
            class C
            {
                static void M()
                {
                    [|List<int>|] digits = new List<int> { 1, 2, 3 };
                }
            }
            """,
            """
            using System;
            using System.Collections.Generic;
 
            class C
            {
                static void M()
                {
                    var digits = new List<int> { 1, 2, 3 };
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarOnDeclarationWithCollectionAndObjectInitializers()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
            using System.Collections.Generic;
 
            class C
            {
                static void M()
                {
                    [|List<Customer>|] cs = new List<Customer>
                    {
                        new Customer { City = "Madras" }
                    };
                }
 
                private class Customer
                {
                    public string City { get; set; }
                }
            }
            """,
            """
            using System;
            using System.Collections.Generic;
 
            class C
            {
                static void M()
                {
                    var cs = new List<Customer>
                    {
                        new Customer { City = "Madras" }
                    };
                }
 
                private class Customer
                {
                    public string City { get; set; }
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarOnForStatement()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    for ([|int|] i = 0; i < 5; i++)
                    {
                    }
                }
            }
            """,
            """
            using System;
 
            class C
            {
                static void M()
                {
                    for (var i = 0; i < 5; i++)
                    {
                    }
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarOnForeachStatement()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
            using System.Collections.Generic;
 
            class C
            {
                static void M()
                {
                    var l = new List<int> { 1, 3, 5 };
                    foreach ([|int|] item in l)
                    {
                    }
                }
            }
            """,
            """
            using System;
            using System.Collections.Generic;
 
            class C
            {
                static void M()
                {
                    var l = new List<int> { 1, 3, 5 };
                    foreach (var item in l)
                    {
                    }
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarOnQueryExpression()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
            using System.Collections.Generic;
            using System.Linq;
 
            class C
            {
                static void M()
                {
                    var customers = new List<Customer>();
                    [|IEnumerable<Customer>|] expr = from c in customers
                                                 where c.City == "London"
                                                 select c;
                }
 
                private class Customer
                {
                    public string City { get; set; }
                }
            }
            }
            """,
            """
            using System;
            using System.Collections.Generic;
            using System.Linq;
 
            class C
            {
                static void M()
                {
                    var customers = new List<Customer>();
                    var expr = from c in customers
                                                 where c.City == "London"
                                                 select c;
                }
 
                private class Customer
                {
                    public string City { get; set; }
                }
            }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarInUsingStatement()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    using ([|Res|] r = new Res())
                    {
                    }
                }
 
                private class Res : IDisposable
                {
                    public void Dispose()
                    {
                        throw new NotImplementedException();
                    }
                }
            }
            """,
            """
            using System;
 
            class C
            {
                static void M()
                {
                    using (var r = new Res())
                    {
                    }
                }
 
                private class Res : IDisposable
                {
                    public void Dispose()
                    {
                        throw new NotImplementedException();
                    }
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarOnExplicitConversion()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    double x = 1234.7;
                    [|int|] a = (int)x;
                }
            }
            """,
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    double x = 1234.7;
                    var a = (int)x;
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarInConditionalAccessExpression()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    C obj = new C();
                    [|C|] anotherObj = obj?.Test();
                }
 
                C Test()
                {
                    return this;
                }
            }
            """,
            """
            using System;
 
            class C
            {
                static void M()
                {
                    C obj = new C();
                    var anotherObj = obj?.Test();
                }
 
                C Test()
                {
                    return this;
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarInCheckedExpression()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    long number1 = int.MaxValue + 20L;
                    [|int|] intNumber = checked((int)number1);
                }
            }
            """,
            """
            using System;
 
            class C
            {
                static void M()
                {
                    long number1 = int.MaxValue + 20L;
                    var intNumber = checked((int)number1);
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarInUnCheckedExpression()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    long number1 = int.MaxValue + 20L;
                    [|int|] intNumber = unchecked((int)number1);
                }
            }
            """,
            """
            using System;
 
            class C
            {
                static void M()
                {
                    long number1 = int.MaxValue + 20L;
                    var intNumber = unchecked((int)number1);
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarInAwaitExpression()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
            using System.Threading.Tasks;
 
            class C
            {
                public async void ProcessRead()
                {
                    [|string|] text = await ReadTextAsync(null);
                }
 
                private async Task<string> ReadTextAsync(string filePath)
                {
                    return string.Empty;
                }
            }
            """,
            """
            using System;
            using System.Threading.Tasks;
 
            class C
            {
                public async void ProcessRead()
                {
                    var text = await ReadTextAsync(null);
                }
 
                private async Task<string> ReadTextAsync(string filePath)
                {
                    return string.Empty;
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task SuggestVarInParenthesizedExpression()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                public void ProcessRead()
                {
                    [|int|] text = (5);
                }
            }
            """,
            """
            using System;
 
            class C
            {
                public void ProcessRead()
                {
                    var text = (5);
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact]
    public async Task DoNotSuggestVarOnBuiltInType_Literal_WithOption()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    [|int|] s = 5;
                }
            }
            """, new TestParameters(options: ImplicitTypeButKeepIntrinsics()));
    }
 
    [Fact]
    public async Task DoNotSuggestVarOnBuiltInType_WithOption()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                private const int maxValue = int.MaxValue;
 
                static void M()
                {
                    [|int|] s = (unchecked(maxValue + 10));
                }
            }
            """, new TestParameters(options: ImplicitTypeButKeepIntrinsics()));
    }
 
    [Fact]
    public async Task DoNotSuggestVarOnFrameworkTypeEquivalentToBuiltInType()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                private const int maxValue = int.MaxValue;
 
                static void M()
                {
                    [|Int32|] s = (unchecked(maxValue + 10));
                }
            }
            """, new TestParameters(options: ImplicitTypeButKeepIntrinsics()));
    }
 
    [Fact]
    public async Task SuggestVarWhereTypeIsEvident_DefaultExpression()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    [|C|] text = default(C);
                }
            }
            """,
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    var text = default(C);
                }
            }
            """, options: ImplicitTypeWhereApparent());
    }
 
    [Fact]
    public async Task SuggestVarWhereTypeIsEvident_Literals()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    [|int|] text = 5;
                }
            }
            """,
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    var text = 5;
                }
            }
            """, options: ImplicitTypeWhereApparentAndForIntrinsics());
    }
 
    [Fact]
    public async Task DoNotSuggestVarWhereTypeIsEvident_Literals()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    [|int|] text = 5;
                }
            }
            """, new TestParameters(options: ImplicitTypeWhereApparent()));
    }
 
    [Fact]
    public async Task SuggestVarWhereTypeIsEvident_ObjectCreationExpression()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    [|C|] c = new C();
                }
            }
            """,
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    var c = new C();
                }
            }
            """, options: ImplicitTypeWhereApparent());
    }
 
    [Fact]
    public async Task SuggestVarWhereTypeIsEvident_CastExpression()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    object o = DateTime.MaxValue;
                    [|DateTime|] date = (DateTime)o;
                }
            }
            """,
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    object o = DateTime.MaxValue;
                    var date = (DateTime)o;
                }
            }
            """, options: ImplicitTypeWhereApparent());
    }
 
    [Fact]
    public async Task DoNotSuggestVar_BuiltInTypesRulePrecedesOverTypeIsApparentRule1()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    object o = int.MaxValue;
                    [|int|] i = (Int32)o;
                }
            }
            """, new TestParameters(options: ImplicitTypeWhereApparent()));
    }
 
    [Fact]
    public async Task DoNotSuggestVar_BuiltInTypesRulePrecedesOverTypeIsApparentRule2()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    object o = int.MaxValue;
                    [|Int32|] i = (Int32)o;
                }
            }
            """, new TestParameters(options: ImplicitTypeWhereApparent()));
    }
 
    [Fact]
    public async Task DoNotSuggestVarWhereTypeIsEvident_IsExpression()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    A a = new A();
                    [|Boolean|] s = a is IInterface;
                }
            }
 
            class A : IInterface
            {
            }
 
            interface IInterface
            {
            }
            """, new TestParameters(options: ImplicitTypeWhereApparent()));
    }
 
    [Fact]
    public async Task SuggestVarWhereTypeIsEvident_AsExpression()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    A a = new A();
                    [|IInterface|] s = a as IInterface;
                }
            }
 
            class A : IInterface
            {
            }
 
            interface IInterface
            {
            }
            """,
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    A a = new A();
                    var s = a as IInterface;
                }
            }
 
            class A : IInterface
            {
            }
 
            interface IInterface
            {
            }
            """, options: ImplicitTypeWhereApparent());
    }
 
    [Fact]
    public async Task SuggestVarWhereTypeIsEvident_ConversionHelpers()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    [|DateTime|] a = DateTime.Parse("1");
                }
            }
            """,
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    var a = DateTime.Parse("1");
                }
            }
            """, options: ImplicitTypeWhereApparent());
    }
 
    [Fact]
    public async Task SuggestVarWhereTypeIsEvident_CreationHelpers()
    {
        await TestInRegularAndScriptAsync(
            """
            class C
            {
                public void Process()
                {
                    [|XElement|] a = XElement.Load();
                }
            }
 
            class XElement
            {
                internal static XElement Load() => return null;
            }
            """,
            """
            class C
            {
                public void Process()
                {
                    var a = XElement.Load();
                }
            }
 
            class XElement
            {
                internal static XElement Load() => return null;
            }
            """, options: ImplicitTypeWhereApparent());
    }
 
    [Fact]
    public async Task SuggestVarWhereTypeIsEvident_CreationHelpersWithInferredTypeArguments()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    [|Tuple<int, bool>|] a = Tuple.Create(0, true);
                }
            }
            """,
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    var a = Tuple.Create(0, true);
                }
            }
            """, options: ImplicitTypeWhereApparent());
    }
 
    [Fact]
    public async Task SuggestVarWhereTypeIsEvident_ConvertToType()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    int integralValue = 12534;
                    [|DateTime|] date = Convert.ToDateTime(integralValue);
                }
            }
            """,
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    int integralValue = 12534;
                    var date = Convert.ToDateTime(integralValue);
                }
            }
            """, options: ImplicitTypeWhereApparent());
    }
 
    [Fact]
    public async Task SuggestVarWhereTypeIsEvident_IConvertibleToType()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    int codePoint = 1067;
                    IConvertible iConv = codePoint;
                    [|DateTime|] date = iConv.ToDateTime(null);
                }
            }
            """,
            """
            using System;
 
            class C
            {
                public void Process()
                {
                    int codePoint = 1067;
                    IConvertible iConv = codePoint;
                    var date = iConv.ToDateTime(null);
                }
            }
            """, options: ImplicitTypeWhereApparent());
    }
 
    [Fact]
    public async Task SuggestVarNotificationLevelSilent()
    {
        var source =
            """
            using System;
            class C
            {
                static void M()
                {
                    [|C|] n1 = new C();
                }
            }
            """;
        await TestDiagnosticInfoAsync(source,
            options: ImplicitTypeSilentEnforcement(),
            diagnosticId: IDEDiagnosticIds.UseImplicitTypeDiagnosticId,
            diagnosticSeverity: DiagnosticSeverity.Hidden);
    }
 
    [Fact]
    public async Task SuggestVarNotificationLevelInfo()
    {
        var source =
            """
            using System;
            class C
            {
                static void M()
                {
                    [|int|] s = 5;
                }
            }
            """;
        await TestDiagnosticInfoAsync(source,
            options: ImplicitTypeEnforcements(),
            diagnosticId: IDEDiagnosticIds.UseImplicitTypeDiagnosticId,
            diagnosticSeverity: DiagnosticSeverity.Info);
    }
 
    [Fact]
    public async Task SuggestVarNotificationLevelWarning()
    {
        var source =
            """
            using System;
            class C
            {
                static void M()
                {
                    [|C[]|] n1 = new[] { new C() }; // type not apparent and not intrinsic
                }
            }
            """;
        await TestDiagnosticInfoAsync(source,
            options: ImplicitTypeEnforcements(),
            diagnosticId: IDEDiagnosticIds.UseImplicitTypeDiagnosticId,
            diagnosticSeverity: DiagnosticSeverity.Warning);
    }
 
    [Fact]
    public async Task SuggestVarNotificationLevelError()
    {
        var source =
            """
            using System;
            class C
            {
                static void M()
                {
                    [|C|] n1 = new C();
                }
            }
            """;
        await TestDiagnosticInfoAsync(source,
            options: ImplicitTypeEnforcements(),
            diagnosticId: IDEDiagnosticIds.UseImplicitTypeDiagnosticId,
            diagnosticSeverity: DiagnosticSeverity.Error);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23893")]
    public async Task SuggestVarOnLocalWithIntrinsicArrayType()
    {
        var before = @"class C { static void M() { [|int[]|] s = new int[0]; } }";
        var after = @"class C { static void M() { var s = new int[0]; } }";
 
        //The type is intrinsic and apparent
        await TestInRegularAndScriptAsync(before, after, options: ImplicitTypeEverywhere());
        await TestMissingInRegularAndScriptAsync(before, new TestParameters(options: ImplicitTypeButKeepIntrinsics()));
        await TestMissingInRegularAndScriptAsync(before, new TestParameters(options: ImplicitTypeWhereApparent())); // Preference of intrinsic types dominates
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23893")]
    public async Task SuggestVarOnLocalWithCustomArrayType()
    {
        var before = @"class C { static void M() { [|C[]|] s = new C[0]; } }";
        var after = @"class C { static void M() { var s = new C[0]; } }";
 
        //The type is not intrinsic but apparent
        await TestInRegularAndScriptAsync(before, after, options: ImplicitTypeEverywhere());
        await TestInRegularAndScriptAsync(before, after, options: ImplicitTypeButKeepIntrinsics());
        await TestInRegularAndScriptAsync(before, after, options: ImplicitTypeWhereApparent());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23893")]
    public async Task SuggestVarOnLocalWithNonApparentCustomArrayType()
    {
        var before = @"class C { static void M() { [|C[]|] s = new[] { new C() }; } }";
        var after = @"class C { static void M() { var s = new[] { new C() }; } }";
 
        //The type is not intrinsic and not apparent
        await TestInRegularAndScriptAsync(before, after, options: ImplicitTypeEverywhere());
        await TestInRegularAndScriptAsync(before, after, options: ImplicitTypeButKeepIntrinsics());
        await TestMissingInRegularAndScriptAsync(before, new TestParameters(options: ImplicitTypeWhereApparent()));
    }
 
    private static readonly string trivial2uple =
        """
        namespace System
        {
            public class ValueTuple
            {
                public static ValueTuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2) => new ValueTuple<T1, T2>(item1, item2);
            }
            public struct ValueTuple<T1, T2>
            {
                public T1 Item1;
                public T2 Item2;
 
                public ValueTuple(T1 item1, T2 item2) { }
            }
        }
        """;
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/11094")]
    public async Task SuggestVarOnLocalWithIntrinsicTypeTuple()
    {
        var before = @"class C { static void M() { [|(int a, string)|] s = (a: 1, ""hello""); } }";
        var after = @"class C { static void M() { var s = (a: 1, ""hello""); } }";
 
        await TestInRegularAndScriptAsync(before, after, options: ImplicitTypeEverywhere());
        await TestInRegularAndScriptAsync(before, after, options: ImplicitTypeWhereApparentAndForIntrinsics());
        await TestMissingInRegularAndScriptAsync(before, new TestParameters(options: ImplicitTypeWhereApparent()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/11094")]
    public async Task SuggestVarOnLocalWithNonApparentTupleType()
    {
        var before = @"class C { static void M(C c) { [|(int a, C b)|] s = (a: 1, b: c); } }";
        var after = @"class C { static void M(C c) { var s = (a: 1, b: c); } }";
 
        await TestInRegularAndScriptAsync(before, after, options: ImplicitTypeEverywhere());
        await TestMissingInRegularAndScriptAsync(before, new TestParameters(options: ImplicitTypeWhereApparentAndForIntrinsics()));
        await TestMissingInRegularAndScriptAsync(before, new TestParameters(options: ImplicitTypeWhereApparent()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/11154")]
    public async Task ValueTupleCreate()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    [|ValueTuple<int, int>|] s = ValueTuple.Create(1, 1);
                }
            }
            """ + trivial2uple,
            """
            using System;
 
            class C
            {
                static void M()
                {
                    var s = ValueTuple.Create(1, 1);
                }
            }
            """ + trivial2uple,
options: ImplicitTypeWhereApparent());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/11095")]
    public async Task ValueTupleCreate_2()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    [|(int, int)|] s = ValueTuple.Create(1, 1);
                }
            }
            """ + trivial2uple,
            """
            using System;
 
            class C
            {
                static void M()
                {
                    var s = ValueTuple.Create(1, 1);
                }
            }
            """ + trivial2uple,
options: ImplicitTypeWhereApparent());
    }
 
    [Fact]
    public async Task TupleWithDifferentNames()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                static void M()
                {
                    [|(int, string)|] s = (c: 1, d: "hello");
                }
            }
            """,
new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/14052")]
    public async Task DoNotOfferOnForEachConversionIfItChangesSemantics()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
            using System.Collections.Generic;
 
            interface IContractV1
            {
            }
 
            interface IContractV2 : IContractV1
            {
            }
 
            class ContractFactory
            {
                public IEnumerable<IContractV1> GetContracts()
                {
                }
            }
 
            class Program
            {
                static void M()
                {
                    var contractFactory = new ContractFactory();
                    foreach ([|IContractV2|] contract in contractFactory.GetContracts())
                    {
                    }
                }
            }
            """,
new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/14052")]
    public async Task OfferOnForEachConversionIfItDoesNotChangesSemantics()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
            using System.Collections.Generic;
 
            interface IContractV1
            {
            }
 
            interface IContractV2 : IContractV1
            {
            }
 
            class ContractFactory
            {
                public IEnumerable<IContractV1> GetContracts()
                {
                }
            }
 
            class Program
            {
                static void M()
                {
                    var contractFactory = new ContractFactory();
                    foreach ([|IContractV1|] contract in contractFactory.GetContracts())
                    {
                    }
                }
            }
            """,
            """
            using System;
            using System.Collections.Generic;
 
            interface IContractV1
            {
            }
 
            interface IContractV2 : IContractV1
            {
            }
 
            class ContractFactory
            {
                public IEnumerable<IContractV1> GetContracts()
                {
                }
            }
 
            class Program
            {
                static void M()
                {
                    var contractFactory = new ContractFactory();
                    foreach (var contract in contractFactory.GetContracts())
                    {
                    }
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/20437")]
    public async Task SuggestVarOnDeclarationExpressionSyntax()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                static void M()
                {
                    DateTime.TryParse(string.Empty, [|out DateTime|] date);
                }
            }
            """,
            """
            using System;
 
            class C
            {
                static void M()
                {
                    DateTime.TryParse(string.Empty, out var date);
                }
            }
            """,
options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23893")]
    public async Task DoNotSuggestVarOnDeclarationExpressionSyntaxWithIntrinsicType()
    {
        var before =
            """
            class C
            {
                static void M(out int x)
                {
                    M([|out int|] x);
                }
            }
            """;
        await TestMissingInRegularAndScriptAsync(before, new TestParameters(options: ImplicitTypeButKeepIntrinsics()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22768")]
    public async Task DoNotSuggestVarOnStackAllocExpressions_SpanType()
    {
        await TestMissingInRegularAndScriptAsync("""
            using System;
            namespace System
            {
                public readonly ref struct Span<T> 
                {
                    unsafe public Span(void* pointer, int length) { }
                }
            }
            class C
            {
                static void M()
                {
                    [|Span<int>|] x = stackalloc int [10];
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22768")]
    public async Task DoNotSuggestVarOnStackAllocExpressions_SpanType_NestedConditional()
    {
        await TestMissingInRegularAndScriptAsync("""
            using System;
            namespace System
            {
                public readonly ref struct Span<T> 
                {
                    unsafe public Span(void* pointer, int length) { }
                }
            }
            class C
            {
                static void M(bool choice)
                {
                    [|Span<int>|] x = choice ? stackalloc int [10] : stackalloc int [100];
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22768")]
    public async Task DoNotSuggestVarOnStackAllocExpressions_SpanType_NestedCast()
    {
        await TestMissingInRegularAndScriptAsync("""
            using System;
            namespace System
            {
                public readonly ref struct Span<T> 
                {
                    unsafe public Span(void* pointer, int length) { }
                }
            }
            class C
            {
                static void M()
                {
                    [|Span<int>|] x = (Span<int>)stackalloc int [100];
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22768")]
    public async Task SuggestVarOnLambdasWithNestedStackAllocs()
    {
        await TestInRegularAndScriptAsync("""
            using System.Linq;
            class C
            {
                unsafe static void M()
                {
                    [|int|] x = new int[] { 1, 2, 3 }.First(i =>
                    {
                        int* y = stackalloc int[10];
                        return i == 1;
                    });
                }
            }
            """, """
            using System.Linq;
            class C
            {
                unsafe static void M()
                {
                    var x = new int[] { 1, 2, 3 }.First(i =>
                    {
                        int* y = stackalloc int[10];
                        return i == 1;
                    });
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22768")]
    public async Task SuggestVarOnAnonymousMethodsWithNestedStackAllocs()
    {
        await TestInRegularAndScriptAsync("""
            using System.Linq;
            class C
            {
                unsafe static void M()
                {
                    [|int|] x = new int[] { 1, 2, 3 }.First(delegate (int i)
                    {
                        int* y = stackalloc int[10];
                        return i == 1;
                    });
                }
            }
            """, """
            using System.Linq;
            class C
            {
                unsafe static void M()
                {
                    var x = new int[] { 1, 2, 3 }.First(delegate (int i)
                    {
                        int* y = stackalloc int[10];
                        return i == 1;
                    });
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22768")]
    public async Task SuggestVarOnStackAllocsNestedInLambdas()
    {
        await TestInRegularAndScriptAsync("""
            using System.Linq;
            class C
            {
                unsafe static void M()
                {
                    var x = new int[] { 1, 2, 3 }.First(i =>
                    {
                        [|int*|] y = stackalloc int[10];
                        return i == 1;
                    });
                }
            }
            """, """
            using System.Linq;
            class C
            {
                unsafe static void M()
                {
                    var x = new int[] { 1, 2, 3 }.First(i =>
                    {
                        var y = stackalloc int[10];
                        return i == 1;
                    });
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22768")]
    public async Task SuggestVarOnStackAllocsNestedInAnonymousMethods()
    {
        await TestInRegularAndScriptAsync("""
            using System.Linq;
            class C
            {
                unsafe static void M()
                {
                    var x = new int[] { 1, 2, 3 }.First(delegate (int i)
                    {
                        [|int*|] y = stackalloc int[10];
                        return i == 1;
                    });
                }
            }
            """, """
            using System.Linq;
            class C
            {
                unsafe static void M()
                {
                    var x = new int[] { 1, 2, 3 }.First(delegate (int i)
                    {
                        var y = stackalloc int[10];
                        return i == 1;
                    });
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22768")]
    public async Task SuggestVarOnStackAllocsInOuterMethodScope()
    {
        await TestInRegularAndScriptAsync("""
            class C
            {
                unsafe static void M()
                {
                    [|int*|] x = stackalloc int [10];
                }
            }
            """, """
            class C
            {
                unsafe static void M()
                {
                    var x = stackalloc int [10];
                }
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23116")]
    public async Task DoSuggestForDeclarationExpressionIfItWouldNotChangeOverloadResolution2()
    {
        await TestInRegularAndScriptAsync("""
            class Program
            {
                static int Main(string[] args)
                {
                    TryGetValue("key", out [|int|] value);
                    return value;
                }
 
                public static bool TryGetValue(string key, out int value) => false;
                public static bool TryGetValue(string key, out bool value, int x) => false;
            }
            """, """
            class Program
            {
                static int Main(string[] args)
                {
                    TryGetValue("key", out var value);
                    return value;
                }
 
                public static bool TryGetValue(string key, out int value) => false;
                public static bool TryGetValue(string key, out bool value, int x) => false;
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23116")]
    public async Task DoNotSuggestForDeclarationExpressionIfItWouldChangeOverloadResolution()
    {
        await TestMissingInRegularAndScriptAsync("""
            class Program
            {
                static int Main(string[] args)
                {
                    TryGetValue("key", out [|int|] value);
                    return value;
                }
 
                public static bool TryGetValue(string key, out object value) => false;
 
                public static bool TryGetValue<T>(string key, out T value) => false;
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23116")]
    public async Task DoNotSuggestIfChangesGenericTypeInference()
    {
        await TestMissingInRegularAndScriptAsync("""
            class Program
            {
                static int Main(string[] args)
                {
                    TryGetValue("key", out [|int|] value);
                    return value;
                }
 
                public static bool TryGetValue<T>(string key, out T value) => false;
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23116")]
    public async Task SuggestIfDoesNotChangeGenericTypeInference1()
    {
        await TestInRegularAndScriptAsync("""
            class Program
            {
                static int Main(string[] args)
                {
                    TryGetValue<int>("key", out [|int|] value);
                    return value;
                }
 
                public static bool TryGetValue<T>(string key, out T value) => false;
            }
            """, """
            class Program
            {
                static int Main(string[] args)
                {
                    TryGetValue<int>("key", out var value);
                    return value;
                }
 
                public static bool TryGetValue<T>(string key, out T value) => false;
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23116")]
    public async Task SuggestIfDoesNotChangeGenericTypeInference2()
    {
        await TestInRegularAndScriptAsync("""
            class Program
            {
                static int Main(string[] args)
                {
                    TryGetValue(0, out [|int|] value);
                    return value;
                }
 
                public static bool TryGetValue<T>(T key, out T value) => false;
            }
            """, """
            class Program
            {
                static int Main(string[] args)
                {
                    TryGetValue(0, out var value);
                    return value;
                }
 
                public static bool TryGetValue<T>(T key, out T value) => false;
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23711")]
    public async Task SuggestVarForDelegateType()
    {
        await TestInRegularAndScriptAsync("""
            class Program
            {
                static void Main(string[] args)
                {
                    [|GetHandler|] handler = Handler;
                }
 
                private static GetHandler Handler;
 
                delegate object GetHandler();
            }
            """, """
            class Program
            {
                static void Main(string[] args)
                {
                    var handler = Handler;
                }
 
                private static GetHandler Handler;
 
                delegate object GetHandler();
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23711")]
    public async Task DoNotSuggestVarForDelegateType1()
    {
        await TestMissingInRegularAndScriptAsync("""
            class Program
            {
                static void Main(string[] args)
                {
                    [|GetHandler|] handler = () => new object();
                }
 
                private static GetHandler Handler;
 
                delegate object GetHandler();
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23711")]
    public async Task DoNotSuggestVarForDelegateType2()
    {
        await TestMissingInRegularAndScriptAsync("""
            class Program
            {
                static void Main(string[] args)
                {
                    [|GetHandler|] handler = Foo;
                }
 
                private static GetHandler Handler;
 
                private static object Foo() => new object();
 
                delegate object GetHandler();
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23711")]
    public async Task DoNotSuggestVarForDelegateType3()
    {
        await TestMissingInRegularAndScriptAsync("""
            class Program
            {
                static void Main(string[] args)
                {
                    [|GetHandler|] handler = delegate { return new object(); };
                }
 
                private static GetHandler Handler;
 
                delegate object GetHandler();
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/24262")]
    public async Task DoNotSuggestVarForInterfaceVariableInForeachStatement()
    {
        await TestMissingInRegularAndScriptAsync("""
            public interface ITest
            {
                string Value { get; }
            }
            public class TestInstance : ITest
            {
                string ITest.Value => "Hi";
            }
 
            public class Test
            {
                public TestInstance[] Instances { get; }
 
                public void TestIt()
                {
                    foreach ([|ITest|] test in Instances)
                    {
                        Console.WriteLine(test.Value);
                    }
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/24262")]
    public async Task DoNotSuggestVarForInterfaceVariableInDeclarationStatement()
    {
        await TestMissingInRegularAndScriptAsync("""
            public interface ITest
            {
                string Value { get; }
            }
            public class TestInstance : ITest
            {
                string ITest.Value => "Hi";
            }
 
            public class Test
            {
                public void TestIt()
                {
                    [|ITest|] test = new TestInstance();
                    Console.WriteLine(test.Value);
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/24262")]
    public async Task DoNotSuggestVarForAbstractClassVariableInForeachStatement()
    {
        await TestMissingInRegularAndScriptAsync("""
            public abstract class MyAbClass
            {
                string Value { get; }
            }
 
            public class TestInstance : MyAbClass
            {
                public string Value => "Hi";
            }
 
            public class Test
            {
                public TestInstance[] Instances { get; }
 
                public void TestIt()
                {
                    foreach ([|MyAbClass|] instance in Instances)
                    {
                        Console.WriteLine(instance);
                    }
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/24262")]
    public async Task DoNotSuggestVarForAbstractClassVariableInDeclarationStatement()
    {
        await TestMissingInRegularAndScriptAsync("""
            public abstract class MyAbClass
            {
                string Value { get; }
            }
 
            public class TestInstance : MyAbClass
            {
                public string Value => "Hi";
            }
 
            public class Test
            {
                public TestInstance[] Instances { get; }
 
                public void TestIt()
                {
                    [|MyAbClass|]  test = new TestInstance();
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task DoNoSuggestVarForRefForeachVar()
    {
        await TestMissingInRegularAndScriptAsync("""
            using System;
            namespace System
            {
                public readonly ref struct Span<T>
                {
                    unsafe public Span(void* pointer, int length) { }
 
                    public ref SpanEnum GetEnumerator() => throw new Exception();
 
                    public struct SpanEnum
                    {
                        public ref int Current => 0;
                        public bool MoveNext() => false;
                    }
                }
            }
            class C
            {
                public void M(Span<int> span)
                {
                    foreach ([|ref|] var rx in span)
                    {
                    }
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26923")]
    public async Task NoSuggestionOnForeachCollectionExpression()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
            using System.Collections.Generic;
 
            class C
            {
                static void Main(string[] args)
                {
                    foreach (string arg in [|args|])
                    {
 
                    }
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/39171")]
    public async Task NoSuggestionForSwitchExpressionDifferentTypes()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            class Program
            {
                interface IFruit { }
 
                class Apple : IFruit { }
 
                class Banana : IFruit { }
 
                public static void Test(string name)
                {
                    [|IFruit|] fruit = name switch
                    {
                        "apple" => new Apple(),
                        "banana" => new Banana(),
                        _ => null,
                    };
                }
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/39171")]
    public async Task SuggestSwitchExpressionSameOrInheritedTypes()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
 
            class Test { }
 
            class Test2 : Test { }
 
            class C
            {
                void M()
                {
                    var str = "one";
                    [|Test|] t = str switch
                    {
                        "one" => new Test(),
                        "two" => new Test2(),
                        _ => throw new InvalidOperationException("Unknown test."),
                    };
                }     
            }
            """,
            """
            using System;
 
            class Test { }
 
            class Test2 : Test { }
 
            class C
            {
                void M()
                {
                    var str = "one";
                    var t = str switch
                    {
                        "one" => new Test(),
                        "two" => new Test2(),
                        _ => throw new InvalidOperationException("Unknown test."),
                    };
                }     
            }
            """, options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32088")]
    public async Task DoNotSuggestVarOnDeclarationExpressionWithInferredTupleNames()
    {
        await TestMissingAsync(
            """
            using System.Collections.Generic;
            using System.Linq;
 
            static class Program
            {
                static void Main(string[] args)
                {
                    if (!_data.TryGetValue(0, [|out List<(int X, int Y)>|] value))
                        return;
 
                    var x = value.FirstOrDefault().X;
                }
 
                private static Dictionary<int, List<(int, int)>> _data =
                    new Dictionary<int, List<(int, int)>>();
            }
            """, parameters: new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32088")]
    public async Task DoSuggestVarOnDeclarationExpressionWithMatchingTupleNames()
    {
        await TestInRegularAndScriptAsync(
            """
            using System.Collections.Generic;
            using System.Linq;
 
            static class Program
            {
                static void Main(string[] args)
                {
                    if (!_data.TryGetValue(0, [|out List<(int X, int Y)>|] value))
                        return;
 
                    var x = value.FirstOrDefault().X;
                }
 
                private static Dictionary<int, List<(int X, int Y)>> _data =
                    new Dictionary<int, List<(int, int)>>();
            }
            """,
            """
            using System.Collections.Generic;
            using System.Linq;
 
            static class Program
            {
                static void Main(string[] args)
                {
                    if (!_data.TryGetValue(0, out var value))
                        return;
 
                    var x = value.FirstOrDefault().X;
                }
 
                private static Dictionary<int, List<(int X, int Y)>> _data =
                    new Dictionary<int, List<(int, int)>>();
            }
            """,
options: ImplicitTypeEverywhere());
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44507")]
    public async Task DoNotSuggestVarInAmbiguousSwitchExpression()
    {
        await TestMissingAsync(
            """
            using System;
 
            class C
            {
                void M()
                {
                    var i = 1;
                    [||]C x = i switch
                    {
                        0 => new A(),
                        1 => new B(),
                        _ => throw new ArgumentException(),
                    };
                }
            }
 
            class A : C
            {
            }
 
            class B : C
            {
            }
            """, parameters: new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44507")]
    public async Task DoNotSuggestVarInSwitchExpressionWithDelegateType()
    {
        await TestMissingAsync(
            """
            using System;
 
            class C
            {
                private void M(object sender, EventArgs e)
                {
                    var x = 1;
                    [||]Action<object, EventArgs> a = x switch
                    {
                        0 => (sender, e) => f1(sender, e),
                        1 => (sender, e) => f2(sender, e),
                        _ => throw new ArgumentException()
                    };
 
                    a(sender, e);
                }
 
                private readonly Action<object, EventArgs> f1;
                private readonly Action<object, EventArgs> f2;
            }
            """, parameters: new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public async Task DoNotSuggestVarForImplicitObjectCreation()
    {
        await TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class Program
            {
                void Method()
                {
                    [|string|] p = new('c', 1);
                }
 
            }
            """, new TestParameters(options: ImplicitTypeEverywhere()));
    }
 
    [Fact]
    public Task SuggestForNullable1()
        => TestInRegularAndScriptAsync(
            """
            #nullable enable
 
            class C
            {
                string? M()
                {
                    [|string?|] a = NullableString();
                    return a;
                }
 
                string? NullableString() => null;
            }
            """,
            """
            #nullable enable
 
            class C
            {
                string? M()
                {
                    var a = NullableString();
                    return a;
                }
 
                string? NullableString() => null;
            }
            """,
options: ImplicitTypeEverywhere());
 
    [Fact]
    public Task SuggestForNullable2()
        => TestInRegularAndScriptAsync(
            """
            #nullable enable
 
            class C
            {
                string? M()
                {
                    [|string?|] a = NonNullString();
                    return a;
                }
 
                string NonNullString() => string.Empty;
            }
            """,
            """
            #nullable enable
 
            class C
            {
                string? M()
                {
                    var a = NonNullString();
                    return a;
                }
 
                string NonNullString() => string.Empty;
            }
            """,
options: ImplicitTypeEverywhere());
 
    [Fact]
    public Task SuggestForNullable3()
        => TestInRegularAndScriptAsync(
            """
            #nullable enable
 
            class C
            {
                string? M()
                {
                    [|string|] a = NonNullString();
                    return a;
                }
 
                string NonNullString() => string.Empty;
            }
            """,
            """
            #nullable enable
 
            class C
            {
                string? M()
                {
                    var a = NonNullString();
                    return a;
                }
 
                string NonNullString() => string.Empty;
            }
            """,
options: ImplicitTypeEverywhere());
 
    [Fact]
    public Task SuggestForNullableOut1()
        => TestInRegularAndScriptAsync(
            """
            #nullable enable
 
            class C
            {
                string? M()
                {
                    if (GetNullString(out [|string?|] a))
                    {
                        return a;
                    }
 
                    return null;
                }
 
                bool GetNullString(out string? s)
                {
                    s = null;
                    return true;
                }
            }
            """,
            """
            #nullable enable
 
            class C
            {
                string? M()
                {
                    if (GetNullString(out var a))
                    {
                        return a;
                    }
 
                    return null;
                }
 
                bool GetNullString(out string? s)
                {
                    s = null;
                    return true;
                }
            }
            """,
options: ImplicitTypeEverywhere());
 
    [Fact]
    public Task SuggestForNullableOut2()
        => TestInRegularAndScriptAsync(
            """
            #nullable enable
 
            class C
            {
                string? M()
                {
                    if (GetNonNullString(out [|string?|] a))
                    {
                        return a;
                    }
 
                    return null;
                }
 
                bool GetNonNullString(out string s)
                {
                    s = string.Empty;
                    return true;
                }
            }
            """,
            """
            #nullable enable
 
            class C
            {
                string? M()
                {
                    if (GetNonNullString(out var a))
                    {
                        return a;
                    }
 
                    return null;
                }
 
                bool GetNonNullString(out string s)
                {
                    s = string.Empty;
                    return true;
                }
            }
            """,
options: ImplicitTypeEverywhere());
 
    [Fact]
    public Task SuggestForNullableOut3()
        => TestInRegularAndScriptAsync(
            """
            #nullable enable
 
            class C
            {
                string? M()
                {
                    if (GetNonNullString(out [|string|] a))
                    {
                        return a;
                    }
 
                    return null;
                }
 
                bool GetNonNullString(out string s)
                {
                    s = string.Empty;
                    return true;
                }
            }
            """,
            """
            #nullable enable
 
            class C
            {
                string? M()
                {
                    if (GetNonNullString(out var a))
                    {
                        return a;
                    }
 
                    return null;
                }
 
                bool GetNonNullString(out string s)
                {
                    s = string.Empty;
                    return true;
                }
            }
            """,
options: ImplicitTypeEverywhere());
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/41780")]
    public async Task SuggestOnRefType1()
    {
        await TestAsync(
            """
            class C
            {
                void Method(ref int x)
                {
                  ref [|int|] y = ref x;
                }
            }
            """,
            """
            class C
            {
                void Method(ref int x)
                {
                  ref var y = ref x;
                }
            }
            """, CSharpParseOptions.Default, options: ImplicitTypeEverywhere());
    }
}