File: Completion\CompletionProviders\DeclarationNameCompletionProviderTests.cs
Web Access
Project: src\src\EditorFeatures\CSharpTest\Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.EditorFeatures.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;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Completion.Providers;
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders;
using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.NamingStyles;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionSetSources;
 
using static SymbolSpecification;
 
[Trait(Traits.Feature, Traits.Features.Completion)]
public sealed class DeclarationNameCompletionProviderTests : AbstractCSharpCompletionProviderTests
{
    private const string Span = """
        namespace System
        {
            public readonly ref struct Span<T>
            {
                private readonly T[] arr;
                public ref T this[int i] => ref arr[i];
                public override int GetHashCode() => 1;
                public int Length { get; }
                unsafe public Span(void* pointer, int length)
                {
                    this.arr = Helpers.ToArray<T>(pointer, length);
                    this.Length = length;
                }
                public Span(T[] arr)
                {
                    this.arr = arr;
                    this.Length = arr.Length;
                }
                public void CopyTo(Span<T> other) { }
                /// <summary>Gets an enumerator for this span.</summary>
                public Enumerator GetEnumerator() => new Enumerator(this);
                /// <summary>Enumerates the elements of a <see cref="Span{T}"/>.</summary>
                public ref struct Enumerator
                {
                    /// <summary>The span being enumerated.</summary>
                    private readonly Span<T> _span;
                    /// <summary>The next index to yield.</summary>
                    private int _index;
                    /// <summary>Initialize the enumerator.</summary>
                    /// <param name="span">The span to enumerate.</param>
                    internal Enumerator(Span<T> span)
                    {
                        _span = span;
                        _index = -1;
                    }
                    /// <summary>Advances the enumerator to the next element of the span.</summary>
                    public bool MoveNext()
                    {
                        int index = _index + 1;
                        if (index < _span.Length)
                        {
                            _index = index;
                            return true;
                        }
                        return false;
                    }
                    /// <summary>Gets the element at the current position of the enumerator.</summary>
                    public ref T Current
                    {
                        get => ref _span[_index];
                    }
                }
                public static implicit operator Span<T>(T[] array) => new Span<T>(array);
                public Span<T> Slice(int offset, int length)
                {
                    var copy = new T[length];
                    Array.Copy(arr, offset, copy, 0, length);
                    return new Span<T>(copy);
                }
            }
            public readonly ref struct ReadOnlySpan<T>
            {
                private readonly T[] arr;
                public ref readonly T this[int i] => ref arr[i];
                public override int GetHashCode() => 2;
                public int Length { get; }
                unsafe public ReadOnlySpan(void* pointer, int length)
                {
                    this.arr = Helpers.ToArray<T>(pointer, length);
                    this.Length = length;
                }
                public ReadOnlySpan(T[] arr)
                {
                    this.arr = arr;
                    this.Length = arr.Length;
                }
                public void CopyTo(Span<T> other) { }
                /// <summary>Gets an enumerator for this span.</summary>
                public Enumerator GetEnumerator() => new Enumerator(this);
                /// <summary>Enumerates the elements of a <see cref="Span{T}"/>.</summary>
                public ref struct Enumerator
                {
                    /// <summary>The span being enumerated.</summary>
                    private readonly ReadOnlySpan<T> _span;
                    /// <summary>The next index to yield.</summary>
                    private int _index;
                    /// <summary>Initialize the enumerator.</summary>
                    /// <param name="span">The span to enumerate.</param>
                    internal Enumerator(ReadOnlySpan<T> span)
                    {
                        _span = span;
                        _index = -1;
                    }
                    /// <summary>Advances the enumerator to the next element of the span.</summary>
                    public bool MoveNext()
                    {
                        int index = _index + 1;
                        if (index < _span.Length)
                        {
                            _index = index;
                            return true;
                        }
                        return false;
                    }
                    /// <summary>Gets the element at the current position of the enumerator.</summary>
                    public ref readonly T Current
                    {
                        get => ref _span[_index];
                    }
                }
                public static implicit operator ReadOnlySpan<T>(T[] array) => array == null ? default : new ReadOnlySpan<T>(array);
                public static implicit operator ReadOnlySpan<T>(string stringValue) => string.IsNullOrEmpty(stringValue) ? default : new ReadOnlySpan<T>((T[])(object)stringValue.ToCharArray());
                public ReadOnlySpan<T> Slice(int offset, int length)
                {
                    var copy = new T[length];
                    Array.Copy(arr, offset, copy, 0, length);
                    return new ReadOnlySpan<T>(copy);
                }
            }
            public readonly ref struct SpanLike<T>
            {
                public readonly Span<T> field;
            }
            public enum Color: sbyte
            {
                Red,
                Green,
                Blue
            }
            public static unsafe class Helpers
            {
                public static T[] ToArray<T>(void* ptr, int count)
                {
                    if (ptr == null)
                    {
                        return null;
                    }
                    if (typeof(T) == typeof(int))
                    {
                        var arr = new int[count];
                        for(int i = 0; i < count; i++)
                        {
                            arr[i] = ((int*)ptr)[i];
                        }
                        return (T[])(object)arr;
                    }
                    if (typeof(T) == typeof(byte))
                    {
                        var arr = new byte[count];
                        for(int i = 0; i < count; i++)
                        {
                            arr[i] = ((byte*)ptr)[i];
                        }
                        return (T[])(object)arr;
                    }
                    if (typeof(T) == typeof(char))
                    {
                        var arr = new char[count];
                        for(int i = 0; i < count; i++)
                        {
                            arr[i] = ((char*)ptr)[i];
                        }
                        return (T[])(object)arr;
                    }
                    if (typeof(T) == typeof(Color))
                    {
                        var arr = new Color[count];
                        for(int i = 0; i < count; i++)
                        {
                            arr[i] = ((Color*)ptr)[i];
                        }
                        return (T[])(object)arr;
                    }
                    throw new Exception("add a case for: " + typeof(T));
                }
            }
        }
        """;
 
    private const string IAsyncEnumerable = """
        namespace System
        {
            public interface IAsyncDisposable
            {
                System.Threading.Tasks.ValueTask DisposeAsync();
            }
        }
 
        namespace System.Runtime.CompilerServices
        {
            using System.Threading.Tasks;
 
            public sealed class AsyncMethodBuilderAttribute : Attribute
            {
                public AsyncMethodBuilderAttribute(Type builderType) { }
                public Type BuilderType { get; }
            }
 
            public struct AsyncValueTaskMethodBuilder
            {
                public ValueTask Task => default;
 
                public static AsyncValueTaskMethodBuilder Create() => default;
                public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
                    where TAwaiter : INotifyCompletion
                    where TStateMachine : IAsyncStateMachine {}
 
                public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
                    where TAwaiter : ICriticalNotifyCompletion
                    where TStateMachine : IAsyncStateMachine {}
                public void SetException(Exception exception) {}
                public void SetResult() {}
                public void SetStateMachine(IAsyncStateMachine stateMachine) {}
                public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine {}
            }
 
            public readonly struct ValueTaskAwaiter : ICriticalNotifyCompletion, INotifyCompletion
            {
                public bool IsCompleted => default;
 
                public void GetResult() { }
                public void OnCompleted(Action continuation) { }
                public void UnsafeOnCompleted(Action continuation) { }
            }
 
            public readonly struct ValueTaskAwaiter<TResult> : ICriticalNotifyCompletion, INotifyCompletion
            {
                public bool IsCompleted => default;
                public TResult GetResult() => default;
                public void OnCompleted(Action continuation) { }
                public void UnsafeOnCompleted(Action continuation) { }
            }
        }
 
        namespace System.Threading.Tasks
        {
            using System.Runtime.CompilerServices;
 
            [AsyncMethodBuilder(typeof(AsyncValueTaskMethodBuilder))]
            public readonly struct ValueTask : IEquatable<ValueTask>
            {
                public ValueTask(Task task) {}
                public ValueTask(IValueTaskSource source, short token) {}
 
                public bool IsCompleted => default;
                public bool IsCompletedSuccessfully => default;
                public bool IsFaulted => default;
                public bool IsCanceled => default;
 
                public Task AsTask() => default;
                public ConfiguredValueTaskAwaitable ConfigureAwait(bool continueOnCapturedContext) => default;
                public override bool Equals(object obj) => default;
                public bool Equals(ValueTask other) => default;
                public ValueTaskAwaiter GetAwaiter() => default;
                public override int GetHashCode() => default;
                public ValueTask Preserve() => default;
 
                public static bool operator ==(ValueTask left, ValueTask right) => default;
                public static bool operator !=(ValueTask left, ValueTask right) => default;
            }
 
            [AsyncMethodBuilder(typeof(AsyncValueTaskMethodBuilder<>))]
            public readonly struct ValueTask<TResult> : IEquatable<ValueTask<TResult>>
            {
                public ValueTask(TResult result) {}
                public ValueTask(Task<TResult> task) {}
                public ValueTask(IValueTaskSource<TResult> source, short token) {}
 
                public bool IsFaulted => default;
                public bool IsCompletedSuccessfully => default;
                public bool IsCompleted => default;
                public bool IsCanceled => default;
                public TResult Result => default;
 
                public Task<TResult> AsTask() => default;
                public ConfiguredValueTaskAwaitable<TResult> ConfigureAwait(bool continueOnCapturedContext) => default;
 
                public bool Equals(ValueTask<TResult> other) => default;
                public override bool Equals(object obj) => default;
                public ValueTaskAwaiter<TResult> GetAwaiter() => default;
                public override int GetHashCode() => default;
                public ValueTask<TResult> Preserve() => default;
                public override string ToString() => default;
                public static bool operator ==(ValueTask<TResult> left, ValueTask<TResult> right) => default;
                public static bool operator !=(ValueTask<TResult> left, ValueTask<TResult> right) => default;
            }
        }
 
        namespace System.Collections.Generic
        {
            public interface IAsyncEnumerable<out T>
            {
                IAsyncEnumerator<T> GetAsyncEnumerator();
            }
 
            public interface IAsyncEnumerator<out T> : IAsyncDisposable
            {
                System.Threading.Tasks.ValueTask<bool> MoveNextAsync();
                T Current { get; }
            }
        }
        """;
 
    internal override Type GetCompletionProviderType()
        => typeof(DeclarationNameCompletionProvider);
 
    [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/48310")]
    [InlineData("record")]
    [InlineData("record class")]
    [InlineData("record struct")]
    public async Task TreatRecordPositionalParameterAsProperty(string record)
    {
        var markup = $$"""
            public class MyClass
            {
            }
 
            public {{record}} R(MyClass $$
            """;
        await VerifyItemExistsAsync(markup, "MyClass", glyph: (int)Glyph.PropertyPublic);
    }
 
    [Theory]
    [InlineData("class")]
    [InlineData("struct")]
    public async Task DoNotTreatPrimaryConstructorParameterAsProperty(string record)
    {
        var markup = $$"""
            public class MyClass
            {
            }
 
            public {{record}} R(MyClass $$
            """;
        await VerifyItemIsAbsentAsync(markup, "MyClass");
    }
 
    [Fact]
    public async Task NameWithOnlyType1()
    {
        var markup = """
            public class MyClass
            {
                MyClass $$
            }
            """;
        await VerifyItemExistsAsync(markup, "myClass", glyph: (int)Glyph.FieldPublic);
        await VerifyItemExistsAsync(markup, "MyClass", glyph: (int)Glyph.PropertyPublic);
        await VerifyItemExistsAsync(markup, "GetMyClass", glyph: (int)Glyph.MethodPublic);
    }
 
    [Fact]
    public async Task AsyncTaskOfT()
    {
        var markup = """
            using System.Threading.Tasks;
            public class C
            {
                async Task<C> $$
            }
            """;
        await VerifyItemExistsAsync(markup, "GetCAsync");
    }
 
    [Fact(Skip = "not yet implemented")]
    public async Task NonAsyncTaskOfT()
    {
        var markup = """
            public class C
            {
                Task<C> $$
            }
            """;
        await VerifyItemExistsAsync(markup, "GetCAsync");
    }
 
    [Fact]
    public async Task MethodDeclaration1()
    {
        var markup = """
            public class C
            {
                virtual C $$
            }
            """;
        await VerifyItemExistsAsync(markup, "GetC");
        await VerifyItemIsAbsentAsync(markup, "C");
        await VerifyItemIsAbsentAsync(markup, "c");
    }
 
    [Fact]
    public async Task WordBreaking1()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                CancellationToken $$
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken");
        await VerifyItemExistsAsync(markup, "cancellation");
        await VerifyItemExistsAsync(markup, "token");
    }
 
    [Fact]
    public async Task WordBreaking2()
    {
        var markup = """
            interface I {}
            public class C
            {
                I $$
            }
            """;
        await VerifyItemExistsAsync(markup, "GetI");
    }
 
    [Fact]
    public async Task WordBreaking3()
    {
        var markup = """
            interface II {}
            public class C
            {
                II $$
            }
            """;
        await VerifyItemExistsAsync(markup, "GetI");
    }
 
    [Fact]
    public async Task WordBreaking4()
    {
        var markup = """
            interface IGoo {}
            public class C
            {
                IGoo $$
            }
            """;
        await VerifyItemExistsAsync(markup, "Goo");
    }
 
    [Fact]
    public async Task WordBreaking5()
    {
        var markup = """
            class SomeWonderfullyLongClassName {}
            public class C
            {
                SomeWonderfullyLongClassName $$
            }
            """;
        await VerifyItemExistsAsync(markup, "Some");
        await VerifyItemExistsAsync(markup, "SomeWonderfully");
        await VerifyItemExistsAsync(markup, "SomeWonderfullyLong");
        await VerifyItemExistsAsync(markup, "SomeWonderfullyLongClass");
        await VerifyItemExistsAsync(markup, "Name");
        await VerifyItemExistsAsync(markup, "ClassName");
        await VerifyItemExistsAsync(markup, "LongClassName");
        await VerifyItemExistsAsync(markup, "WonderfullyLongClassName");
        await VerifyItemExistsAsync(markup, "SomeWonderfullyLongClassName");
    }
 
    [Fact]
    public async Task Parameter1()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                void Goo(CancellationToken $$
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken", glyph: (int)Glyph.Parameter);
    }
 
    [Fact]
    public async Task Parameter2()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                void Goo(int x, CancellationToken c$$
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken", glyph: (int)Glyph.Parameter);
    }
 
    [Fact]
    public async Task Parameter3()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                void Goo(CancellationToken c$$) {}
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken", glyph: (int)Glyph.Parameter);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/45492")]
    public async Task Parameter4()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                void Other(CancellationToken cancellationToken) {}
                void Goo(CancellationToken c$$) {}
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken", glyph: (int)Glyph.Parameter);
    }
 
    [Fact]
    public async Task Parameter5()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                void Goo(CancellationToken cancellationToken, CancellationToken c$$) {}
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken1", glyph: (int)Glyph.Parameter);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/45492")]
    public async Task Parameter6()
    {
        var markup = """
            using System.Threading;
 
            void Other(CancellationToken cancellationToken) {}
            void Goo(CancellationToken c$$) {}
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken", glyph: (int)Glyph.Parameter);
    }
 
    [Fact]
    public async Task Parameter7()
    {
        var markup = """
            using System.Threading;
 
            void Goo(CancellationToken cancellationToken, CancellationToken c$$) {}
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken1", glyph: (int)Glyph.Parameter);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/45492")]
    public async Task Parameter8()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                int this[CancellationToken cancellationToken] => throw null;
                int this[CancellationToken c$$] => throw null;
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken", glyph: (int)Glyph.Parameter);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/45492")]
    public async Task Parameter9()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                int this[CancellationToken cancellationToken] => throw null;
                int this[CancellationToken cancellationToken, CancellationToken c$$] => throw null;
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken1", glyph: (int)Glyph.Parameter);
    }
 
    [InlineData(LanguageVersion.CSharp7)]
    [InlineData(LanguageVersion.CSharp8)]
    [InlineData(LanguageVersion.Latest)]
    [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/42049")]
    [WorkItem("https://github.com/dotnet/roslyn/issues/45492")]
    public async Task Parameter10(LanguageVersion languageVersion)
    {
        var source = """
            public class DbContext { }
            public class C
            {
                void Goo(DbContext context) {
                    void InnerGoo(DbContext $$) { }
                }
            }
            """;
        var markup = GetMarkup(source, languageVersion);
        await VerifyItemExistsAsync(markup, "dbContext", glyph: (int)Glyph.Parameter);
        await VerifyItemExistsAsync(markup, "db", glyph: (int)Glyph.Parameter);
 
        if (languageVersion.MapSpecifiedToEffectiveVersion() >= LanguageVersion.CSharp8)
        {
            await VerifyItemExistsAsync(markup, "context", glyph: (int)Glyph.Parameter);
        }
        else
        {
            await VerifyItemExistsAsync(markup, "context1", glyph: (int)Glyph.Parameter);
        }
    }
 
    [InlineData(LanguageVersion.CSharp7)]
    [InlineData(LanguageVersion.CSharp8)]
    [InlineData(LanguageVersion.Latest)]
    [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/42049")]
    [WorkItem("https://github.com/dotnet/roslyn/issues/45492")]
    public async Task Parameter11(LanguageVersion languageVersion)
    {
        var source = """
            public class DbContext { }
            public class C
            {
                void Goo() {
                    DbContext context;
                    void InnerGoo(DbContext $$) { }
                }
            }
            """;
        var markup = GetMarkup(source, languageVersion);
        await VerifyItemExistsAsync(markup, "dbContext", glyph: (int)Glyph.Parameter);
        await VerifyItemExistsAsync(markup, "db", glyph: (int)Glyph.Parameter);
 
        if (languageVersion.MapSpecifiedToEffectiveVersion() >= LanguageVersion.CSharp8)
        {
            await VerifyItemExistsAsync(markup, "context", glyph: (int)Glyph.Parameter);
        }
        else
        {
            await VerifyItemExistsAsync(markup, "context1", glyph: (int)Glyph.Parameter);
        }
    }
 
    [InlineData(LanguageVersion.CSharp7)]
    [InlineData(LanguageVersion.CSharp8)]
    [InlineData(LanguageVersion.Latest)]
    [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/42049")]
    [WorkItem("https://github.com/dotnet/roslyn/issues/45492")]
    public async Task Parameter12(LanguageVersion languageVersion)
    {
        var source = """
            public class DbContext { }
            public class C
            {
                DbContext dbContext;
                void Goo(DbContext context) {
                    void InnerGoo(DbContext $$) { }
                }
            }
            """;
        var markup = GetMarkup(source, languageVersion);
        await VerifyItemExistsAsync(markup, "dbContext", glyph: (int)Glyph.Parameter);
        await VerifyItemExistsAsync(markup, "db", glyph: (int)Glyph.Parameter);
 
        if (languageVersion.MapSpecifiedToEffectiveVersion() >= LanguageVersion.CSharp8)
        {
            await VerifyItemExistsAsync(markup, "context", glyph: (int)Glyph.Parameter);
        }
        else
        {
            await VerifyItemExistsAsync(markup, "context1", glyph: (int)Glyph.Parameter);
        }
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36248")]
    public async Task Parameter13()
    {
        using var workspaceFixture = GetOrCreateWorkspaceFixture();
 
        var workspace = workspaceFixture.Target.GetWorkspace(GetComposition());
        workspace.SetAnalyzerFallbackOptions(new OptionsCollection(LanguageNames.CSharp)
        {
            { NamingStyleOptions.NamingPreferences, ParameterCamelCaseWithPascalCaseFallback() }
        });
 
        var markup = """
            using System.Threading;
            public class C
            {
                void Goo(CancellationToken $$
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken", glyph: (int)Glyph.Parameter);
        await VerifyItemIsAbsentAsync(markup, "CancellationToken");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/52534")]
    public async Task SuggestParameterNamesFromExistingOverloads()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                void M(CancellationToken myTok) { }
 
                void M(CancellationToken $$
            }
            """;
        await VerifyItemExistsAsync(markup, "myTok", glyph: (int)Glyph.Parameter);
        await VerifyItemExistsAsync(markup, "cancellationToken", glyph: (int)Glyph.Parameter);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/52534")]
    public async Task SuggestParameterNamesFromExistingOverloads_Constructor()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                public C(string firstName, string middleName, string lastName) { }
 
                public C(string firstName, string $$)
            }
            """;
        await VerifyItemExistsAsync(markup, "middleName", glyph: (int)Glyph.Parameter);
        await VerifyItemExistsAsync(markup, "lastName", glyph: (int)Glyph.Parameter);
        await VerifyItemIsAbsentAsync(markup, "firstName");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/52534")]
    public async Task DoNotSuggestParameterNamesFromTheSameOverload()
    {
        var markup = """
            public class C
            {
                void M(string name, string $$) { }
            }
            """;
        await VerifyItemIsAbsentAsync(markup, "name");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/52534")]
    public async Task DoNotSuggestParameterNamesFromNonOverloads()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                void M1(CancellationToken myTok) { }
 
                void M2(CancellationToken $$
            }
            """;
        await VerifyItemIsAbsentAsync(markup, "myTok");
        await VerifyItemExistsAsync(markup, "cancellationToken", glyph: (int)Glyph.Parameter);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/52534")]
    public async Task DoNotSuggestInGenericType()
    {
        var markup = """
            using System.Collections.Generic;
            public class C
            {
                void M(IEnumerable<int> numbers) { }
 
                void M(List<$$>) { }
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/52534")]
    public async Task DoNotSuggestInOptionalParameterDefaultValue()
    {
        var markup = """
            using System.Collections.Generic;
            public class C
            {
                private const int ZERO = 0;
                void M(int num = ZERO) { }
 
                void M(int x, int num = $$) { }
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/19260")]
    public async Task EscapeKeywords1()
    {
        var markup = """
            using System.Text;
            public class C
            {
                void Goo(StringBuilder $$) {}
            }
            """;
        await VerifyItemExistsAsync(markup, "stringBuilder", glyph: (int)Glyph.Parameter);
        await VerifyItemExistsAsync(markup, "@string", glyph: (int)Glyph.Parameter);
        await VerifyItemExistsAsync(markup, "builder", glyph: (int)Glyph.Parameter);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/19260")]
    public async Task EscapeKeywords2()
    {
        var markup = """
            class For { }
            public class C
            {
                void Goo(For $$) {}
            }
            """;
        await VerifyItemExistsAsync(markup, "@for", glyph: (int)Glyph.Parameter);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/19260")]
    public async Task EscapeKeywords3()
    {
        var markup = """
            class For { }
            public class C
            {
                void goo()
                {
                    For $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "@for");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/19260")]
    public async Task EscapeKeywords4()
    {
        var markup = """
            using System.Text;
            public class C
            {
                void goo()
                {
                    StringBuilder $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "stringBuilder");
        await VerifyItemExistsAsync(markup, "@string");
        await VerifyItemExistsAsync(markup, "builder");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25214")]
    public async Task TypeImplementsLazyOfType1()
    {
        var markup = """
            using System;
            using System.Collections.Generic;
 
            internal class Example
            {
                public Lazy<Item> $$
            }
 
            public class Item { }
            """;
        await VerifyItemExistsAsync(markup, "item");
        await VerifyItemExistsAsync(markup, "Item");
        await VerifyItemExistsAsync(markup, "GetItem");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25214")]
    public async Task TypeImplementsLazyOfType2()
    {
        var markup = """
            using System;
            using System.Collections.Generic;
 
            internal class Example
            {
                public List<Lazy<Item>> $$
            }
 
            public class Item { }
            """;
        await VerifyItemExistsAsync(markup, "items");
        await VerifyItemExistsAsync(markup, "Items");
        await VerifyItemExistsAsync(markup, "GetItems");
    }
 
    [Fact]
    public async Task NoSuggestionsForInt()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                int $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task NoSuggestionsForLong()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                long $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task NoSuggestionsForDouble()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                double $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task NoSuggestionsForFloat()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                float $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task NoSuggestionsForSbyte()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                sbyte $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task NoSuggestionsForShort()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                short $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task NoSuggestionsForUint()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                uint $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task NoSuggestionsForUlong()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                ulong $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task SuggestionsForUShort()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                ushort $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task NoSuggestionsForBool()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                bool $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task NoSuggestionsForByte()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                byte $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task NoSuggestionsForChar()
    {
        var markup = """
            using System.Threading;
            public class C
            {
                char $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task NoSuggestionsForString()
    {
        var markup = """
            public class C
            {
                string $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task NoSingleLetterClassNameSuggested()
    {
        var markup = """
            public class C
            {
                C $$
            }
            """;
        await VerifyItemIsAbsentAsync(markup, "C");
        await VerifyItemIsAbsentAsync(markup, "c");
    }
 
    [Fact]
    public async Task ArrayElementTypeSuggested()
    {
        var markup = """
            using System.Threading;
            public class MyClass
            {
                MyClass[] $$
            }
            """;
        await VerifyItemExistsAsync(markup, "MyClasses");
        await VerifyItemIsAbsentAsync(markup, "Array");
    }
 
    [Fact]
    public async Task NotTriggeredByVar()
    {
        var markup = """
            public class C
            {
                var $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task NotAfterVoid()
    {
        var markup = """
            public class C
            {
                void $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task AfterGeneric()
    {
        var markup = """
            public class C
            {
                System.Collections.Generic.IEnumerable<C> $$
            }
            """;
        await VerifyItemExistsAsync(markup, "GetCs");
    }
 
    [Fact]
    public async Task NothingAfterVar()
    {
        var markup = """
            public class C
            {
                void goo()
                {
                    var $$
                }
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task TestCorrectOrder()
    {
        var markup = """
            public class MyClass
            {
                MyClass $$
            }
            """;
        var items = await GetCompletionItemsAsync(markup, SourceCodeKind.Regular);
        Assert.Equal(
            ["myClass", "my", "@class", "MyClass", "My", "Class", "GetMyClass", "GetMy", "GetClass"],
            items.Select(item => item.DisplayText));
    }
 
    [Fact]
    public async Task TestDescriptionInsideClass()
    {
        var markup = """
            public class MyClass
            {
                MyClass $$
            }
            """;
        await VerifyItemExistsAsync(markup, "myClass", glyph: (int)Glyph.FieldPublic, expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
        await VerifyItemExistsAsync(markup, "MyClass", glyph: (int)Glyph.PropertyPublic, expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
        await VerifyItemExistsAsync(markup, "GetMyClass", glyph: (int)Glyph.MethodPublic, expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
    }
 
    [Fact]
    public async Task TestDescriptionInsideMethod()
    {
        var markup = """
            public class MyClass
            {
                void M()
                {
                    MyClass $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "myClass", glyph: (int)Glyph.Local, expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
        await VerifyItemIsAbsentAsync(markup, "MyClass");
        await VerifyItemIsAbsentAsync(markup, "GetMyClass");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/20273")]
    public async Task Alias1()
    {
        var markup = """
            using MyType = System.String;
            public class C
            {
                MyType $$
            }
            """;
        await VerifyItemExistsAsync(markup, "my");
        await VerifyItemExistsAsync(markup, "type");
        await VerifyItemExistsAsync(markup, "myType");
    }
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/20273")]
    public async Task AliasWithInterfacePattern()
    {
        var markup = """
            using IMyType = System.String;
            public class C
            {
                MyType $$
            }
            """;
        await VerifyItemExistsAsync(markup, "my");
        await VerifyItemExistsAsync(markup, "type");
        await VerifyItemExistsAsync(markup, "myType");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/20016")]
    public async Task NotAfterExistingName1()
    {
        var markup = """
            using IMyType = System.String;
            public class C
            {
                MyType myType $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/20016")]
    public async Task NotAfterExistingName2()
    {
        var markup = """
            using IMyType = System.String;
            public class C
            {
                MyType myType, MyType $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/19409")]
    public async Task OutVarArgument()
    {
        var markup = """
            class Test
            {
                void Do(out Test goo)
                {
                    Do(out var $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "test");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/19409")]
    public async Task OutArgument()
    {
        var markup = """
            class Test
            {
                void Do(out Test goo)
                {
                    Do(out Test $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "test");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/19409")]
    public async Task OutGenericArgument()
    {
        var markup = """
            class Test
            {
                void Do<T>(out T goo)
                {
                    Do(out Test $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "test");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22342")]
    public async Task TupleExpressionDeclaration1()
    {
        var markup = """
            class Test
            {
                void Do()
                {
                    (System.Array array, System.Action $$ 
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "action");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22342")]
    public async Task TupleExpressionDeclaration2()
    {
        var markup = """
            class Test
            {
                void Do()
                {
                    (array, action $$
                }
            }
            """;
        await VerifyItemIsAbsentAsync(markup, "action");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22342")]
    public async Task TupleExpressionDeclaration_NestedTuples()
    {
        var markup = """
            class Test
            {
                void Do()
                {
                    ((int i1, int i2), (System.Array array, System.Action $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "action");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22342")]
    public async Task TupleExpressionDeclaration_NestedTuples_CompletionInTheMiddle()
    {
        var markup = """
            class Test
            {
                void Do()
                {
                    ((System.Array array, System.Action $$), (int i1, int i2))
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "action");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22342")]
    public async Task TupleElementDefinition1()
    {
        var markup = """
            class Test
            {
                void Do()
                {
                    (System.Array $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "array");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22342")]
    public async Task TupleElementDefinition2()
    {
        var markup = """
            class Test
            {
                (System.Array $$) Test() => default;
            }
            """;
        await VerifyItemExistsAsync(markup, "array");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22342")]
    public async Task TupleElementDefinition3()
    {
        var markup = """
            class Test
            {
                (System.Array array, System.Action $$) Test() => default;
            }
            """;
        await VerifyItemExistsAsync(markup, "action");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22342")]
    public async Task TupleElementDefinition4()
    {
        var markup = """
            class Test
            {
                (System.Array $$
            }
            """;
        await VerifyItemExistsAsync(markup, "array");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22342")]
    public async Task TupleElementDefinition5()
    {
        var markup = """
            class Test
            {
                void M((System.Array $$
            }
            """;
        await VerifyItemExistsAsync(markup, "array");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22342")]
    public async Task TupleElementDefinition_NestedTuples()
    {
        var markup = """
            class Test
            {
                void M(((int, int), (int, System.Array $$
            }
            """;
        await VerifyItemExistsAsync(markup, "array");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22342")]
    public async Task TupleElementDefinition_InMiddleOfTuple()
    {
        var markup = """
            class Test
            {
                void M((int, System.Array $$),int)
            }
            """;
        await VerifyItemExistsAsync(markup, "array");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22342")]
    public async Task TupleElementTypeInference()
    {
        var markup = """
            class Test
            {
                void Do()
                {
                    (var accessViolationException, var $$) = (new AccessViolationException(), new Action(() => { }));
                }
            }
            """;
        // Currently not supported:
        await VerifyItemIsAbsentAsync(markup, "action");
        // see https://github.com/dotnet/roslyn/issues/27138
        // after the issue ist fixed we expect this to work:
        // await VerifyItemExistsAsync(markup, "action");
    }
 
    [Fact(Skip = "Not yet supported")]
    [WorkItem("https://github.com/dotnet/roslyn/issues/22342")]
    public async Task TupleElementInGenericTypeArgument()
    {
        var markup = """
            class Test
            {
                void Do()
                {
                    System.Func<(System.Action $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "action");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22342")]
    public async Task TupleElementInvocationInsideTuple()
    {
        var markup = """
            class Test
            {
                void Do()
                {
                        int M(int i1, int i2) => i1;
                        var t=(e1: 1, e2: M(1, $$));
                }
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17987")]
    public async Task Pluralize1()
    {
        var markup = """
            using System.Collections.Generic;
            class Index
            {
                IEnumerable<Index> $$
            }
            """;
        await VerifyItemExistsAsync(markup, "Indices");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17987")]
    public async Task Pluralize2()
    {
        var markup = """
            using System.Collections.Generic;
            class Test
            {
                IEnumerable<IEnumerable<Test>> $$
            }
            """;
        await VerifyItemExistsAsync(markup, "tests");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17987")]
    public async Task Pluralize3()
    {
        var markup = """
            using System.Collections.Generic;
            using System.Threading;
            class Test
            {
                IEnumerable<CancellationToken> $$
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationTokens");
        await VerifyItemExistsAsync(markup, "cancellations");
        await VerifyItemExistsAsync(markup, "tokens");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17987")]
    public async Task PluralizeList()
    {
        var markup = """
            using System.Collections.Generic;
            using System.Threading;
            class Test
            {
                List<CancellationToken> $$
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationTokens");
        await VerifyItemExistsAsync(markup, "cancellations");
        await VerifyItemExistsAsync(markup, "tokens");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17987")]
    public async Task PluralizeArray()
    {
        var markup = """
            using System.Collections.Generic;
            using System.Threading;
            class Test
            {
                CancellationToken[] $$
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationTokens");
        await VerifyItemExistsAsync(markup, "cancellations");
        await VerifyItemExistsAsync(markup, "tokens");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37366")]
    public async Task PluralizeSpan()
    {
        var markup = """
            using System;
 
            class Test
            {
                void M(Span<Test> $$) { }
            }
            """ + Span;
        await VerifyItemExistsAsync(markup, "tests");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37366")]
    public async Task PluralizeValidGetEnumerator()
    {
        var markup = """
            class MyClass
            {
                public void M(MyOwnCollection<MyClass> $$) { }
            }
 
 
            class MyOwnCollection<T>
            {
                public MyEnumerator GetEnumerator()
                {
                    return new MyEnumerator();
                }
 
                public class MyEnumerator
                {
                    public T Current { get; }
 
                    public bool MoveNext() { return false; }
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "myClasses");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37366")]
    public async Task PluralizeValidGetAsyncEnumerator()
    {
        var markup = """
            using System.Threading.Tasks;
 
            class MyClass
            {
                public void M(MyOwnCollection<MyClass> $$) { }
            }
 
 
            class MyOwnCollection<T>
            {
                public MyEnumerator GetAsyncEnumerator()
                {
                    return new MyEnumerator();
                }
 
                public class MyEnumerator
                {
                    public T Current { get; }
 
                    public Task<bool> MoveNextAsync() { return Task.FromResult(false); }
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "myClasses");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37366")]
    public async Task PluralizeForUnimplementedIEnumerable()
    {
        var markup = """
            using System.Collections.Generic;
 
            class MyClass
            {
                public void M(MyOwnCollection<MyClass> $$) { }
            }
 
 
            class MyOwnCollection<T> : IEnumerable<T>
            {
            }
            """;
        await VerifyItemExistsAsync(markup, "myClasses");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37366")]
    public async Task PluralizeForUnimplementedIAsyncEnumerable()
    {
        var markup = """
            using System.Collections.Generic;
 
            class MyClass
            {
                public void M(MyOwnCollection<MyClass> $$) { }
            }
 
 
            class MyOwnCollection<T> : IAsyncEnumerable<T>
            {
            }
            """ + IAsyncEnumerable;
        await VerifyItemExistsAsync(markup, "myClasses");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23497")]
    public async Task InPatternMatching1()
    {
        var markup = """
            using System.Threading;
 
            public class C
            {
                public static void Main()
                {
                    object obj = null;
                    if (obj is CancellationToken $$) { }
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken");
        await VerifyItemExistsAsync(markup, "cancellation");
        await VerifyItemExistsAsync(markup, "token");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23497")]
    public async Task InPatternMatching2()
    {
        var markup = """
            using System.Threading;
 
            public class C
            {
                public static bool Foo()
                {
                    object obj = null;
                    return obj is CancellationToken $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken");
        await VerifyItemExistsAsync(markup, "cancellation");
        await VerifyItemExistsAsync(markup, "token");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23497")]
    public async Task InPatternMatching3()
    {
        var markup = """
            using System.Threading;
 
            public class C
            {
                public static void Main()
                {
                    object obj = null;
                    switch(obj)
                    {
                        case CancellationToken $$
                    }
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken");
        await VerifyItemExistsAsync(markup, "cancellation");
        await VerifyItemExistsAsync(markup, "token");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23497")]
    public async Task InPatternMatching4()
    {
        var markup = """
            using System.Threading;
 
            public class C
            {
                public static void Main()
                {
                    object obj = null;
                    if (obj is CancellationToken ca$$) { }
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken");
        await VerifyItemExistsAsync(markup, "cancellation");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23497")]
    public async Task InPatternMatching5()
    {
        var markup = """
            using System.Threading;
 
            public class C
            {
                public static bool Foo()
                {
                    object obj = null;
                    return obj is CancellationToken to$$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken");
        await VerifyItemExistsAsync(markup, "token");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23497")]
    public async Task InPatternMatching6()
    {
        var markup = """
            using System.Threading;
 
            public class C
            {
                public static void Main()
                {
                    object obj = null;
                    switch(obj)
                    {
                        case CancellationToken to$$
                    }
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "cancellationToken");
        await VerifyItemExistsAsync(markup, "token");
    }
 
    [Fact]
    public async Task InUsingStatement1()
    {
        var markup = """
            using System.IO;
 
            class C
            {
                void M()
                {
                    using (StreamReader s$$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "streamReader");
    }
 
    [Fact]
    public async Task InUsingStatement2()
    {
        var markup = """
            using System.IO;
 
            class C
            {
                void M()
                {
                    using (StreamReader s1, $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "streamReader");
    }
 
    [Fact]
    public async Task InUsingStatement_Var()
    {
        var markup = """
            using System.IO;
 
            class C
            {
                void M()
                {
                    using (var m$$ = new MemoryStream())
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "memoryStream");
    }
 
    [Fact]
    public async Task InForStatement1()
    {
        var markup = """
            using System.IO;
 
            class C
            {
                void M()
                {
                    for (StreamReader s$$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "streamReader");
    }
 
    [Fact]
    public async Task InForStatement2()
    {
        var markup = """
            using System.IO;
 
            class C
            {
                void M()
                {
                    for (StreamReader s1, $$
                }
            }
            """;
        await VerifyItemIsAbsentAsync(markup, "streamReader");
    }
 
    [Fact]
    public async Task InForStatement_Var()
    {
        var markup = """
            using System.IO;
 
            class C
            {
                void M()
                {
                    for (var m$$ = new MemoryStream();
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "memoryStream");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26021")]
    public async Task InForEachStatement()
    {
        var markup = """
            using System.IO;
 
            class C
            {
                void M()
                {
                    foreach (StreamReader $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "streamReader");
    }
 
    [Fact]
    public async Task InForEachStatement_Var()
    {
        var markup = """
            using System.IO;
 
            class C
            {
                void M()
                {
                    foreach (var m$$ in new[] { new MemoryStream() })
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "memoryStream");
    }
 
    [Fact]
    public async Task DisabledByOption()
    {
        ShowNameSuggestions = false;
 
        var markup = """
            class Test
            {
                Test $$
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23590")]
    public async Task TypeImplementsIEnumerableOfType()
    {
        var markup = """
            using System.Collections.Generic;
 
            public class Class1
            {
              public void Method()
              {
                Container $$
              }
            }
 
            public class Container : ContainerBase { }
            public class ContainerBase : IEnumerable<ContainerBase> { }
            """;
        await VerifyItemExistsAsync(markup, "container");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23590")]
    public async Task TypeImplementsIEnumerableOfType2()
    {
        var markup = """
            using System.Collections.Generic;
 
            public class Class1
            {
              public void Method()
              {
                 Container $$
              }
            }
 
            public class ContainerBase : IEnumerable<Container> { }
            public class Container : ContainerBase { }
            """;
        await VerifyItemExistsAsync(markup, "container");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23590")]
    public async Task TypeImplementsIEnumerableOfType3()
    {
        var markup = """
            using System.Collections.Generic;
 
            public class Class1
            {
              public void Method()
              {
                 Container $$
              }
            }
 
            public class Container : IEnumerable<Container> { }
            """;
        await VerifyItemExistsAsync(markup, "container");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23590")]
    public async Task TypeImplementsIEnumerableOfType4()
    {
        var markup = """
            using System.Collections.Generic;
            using System.Threading.Tasks;
 
            public class Class1
            {
              public void Method()
              {
                 TaskType $$
              }
            }
 
            public class ContainerBase : IEnumerable<Container> { }
            public class Container : ContainerBase { }
            public class TaskType : Task<Container> { }
            """;
        await VerifyItemExistsAsync(markup, "taskType");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23590")]
    public async Task TypeImplementsTaskOfType()
    {
        var markup = """
            using System.Threading.Tasks;
 
            public class Class1
            {
              public void Method()
              {
                Container $$
              }
            }
 
            public class Container : ContainerBase { }
            public class ContainerBase : Task<ContainerBase> { }
            """;
        await VerifyItemExistsAsync(markup, "container");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23590")]
    public async Task TypeImplementsTaskOfType2()
    {
        var markup = """
            using System.Threading.Tasks;
 
            public class Class1
            {
              public void Method()
              {
                 Container $$
              }
            }
 
            public class Container : Task<ContainerBase> { }
            public class ContainerBase : Container { }
            """;
        await VerifyItemExistsAsync(markup, "container");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23590")]
    public async Task TypeImplementsTaskOfType3()
    {
        var markup = """
            using System.Collections.Generic;
            using System.Threading.Tasks;
 
            public class Class1
            {
              public void Method()
              {
                EnumerableType $$
              }
            }
 
            public class TaskType : TaskTypeBase { }
            public class TaskTypeBase : Task<TaskTypeBase> { }
            public class EnumerableType : IEnumerable<TaskType> { }
            """;
        await VerifyItemExistsAsync(markup, "taskTypes");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23590")]
    public async Task TypeIsNullableOfNullable()
    {
        var markup = """
            using System.Collections.Generic;
 
            public class Class1
            {
              public void Method()
              {
                  // This code isn't legal, but we want to ensure we don't crash in this broken code scenario
                  IEnumerable<Nullable<int?>> $$
              }
            }
            """;
        await VerifyItemExistsAsync(markup, "nullables");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36364")]
    [WorkItem("https://developercommunity2.visualstudio.com/t/Regression-from-1675-Suggested-varia/1220195")]
    public async Task TypeIsNullableStructInLocalWithNullableTypeName()
    {
        var markup = """
            using System;
 
            public struct ImmutableArray<T> : System.Collections.Generic.IEnumerable<T> { }
 
            public class Class1
            {
              public void Method()
              {
                  Nullable<ImmutableArray<int>> $$
              }
            }
            """;
        await VerifyItemExistsAsync(markup, "ints");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36364")]
    [WorkItem("https://developercommunity2.visualstudio.com/t/Regression-from-1675-Suggested-varia/1220195")]
    public async Task TypeIsNullableStructInLocalWithQuestionMark()
    {
        var markup = """
            using System.Collections.Immutable;
 
            public struct ImmutableArray<T> : System.Collections.Generic.IEnumerable<T> { }
 
            public class Class1
            {
              public void Method()
              {
                  ImmutableArray<int>? $$
              }
            }
            """;
        await VerifyItemExistsAsync(markup, "ints");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36364")]
    [WorkItem("https://developercommunity2.visualstudio.com/t/Regression-from-1675-Suggested-varia/1220195")]
    public async Task TypeIsNullableReferenceInLocal()
    {
        var markup = """
            #nullable enable
 
            using System.Collections.Generic;
 
            public class Class1
            {
              public void Method()
              {
                  IEnumerable<int>? $$
              }
            }
            """;
        await VerifyItemExistsAsync(markup, "ints");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36364")]
    [WorkItem("https://developercommunity2.visualstudio.com/t/Regression-from-1675-Suggested-varia/1220195")]
    public async Task TypeIsNullableStructInParameterWithNullableTypeName()
    {
        var markup = """
            using System;
 
            public struct ImmutableArray<T> : System.Collections.Generic.IEnumerable<T> { }
 
            public class Class1
            {
              public void Method(Nullable<ImmutableArray<int>> $$)
              {
              }
            }
            """;
        await VerifyItemExistsAsync(markup, "ints");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36364")]
    [WorkItem("https://developercommunity2.visualstudio.com/t/Regression-from-1675-Suggested-varia/1220195")]
    public async Task TypeIsNullableStructInParameterWithQuestionMark()
    {
        var markup = """
            public struct ImmutableArray<T> : System.Collections.Generic.IEnumerable<T> { }
 
            public class Class1
            {
              public void Method(ImmutableArray<int>? $$)
              {
              }
            }
            """;
        await VerifyItemExistsAsync(markup, "ints");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36364")]
    [WorkItem("https://developercommunity2.visualstudio.com/t/Regression-from-1675-Suggested-varia/1220195")]
    public async Task TypeIsNullableReferenceInParameter()
    {
        var markup = """
            #nullable enable
 
            using System.Collections.Generic;
 
            public class Class1
            {
              public void Method(IEnumerable<int>? $$)
              {
              }
            }
            """;
        await VerifyItemExistsAsync(markup, "ints");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36364")]
    public async Task EnumerableParameterOfUnmanagedType()
    {
        var markup = """
            using System.Collections.Generic;
 
            public class Class1
            {
              public void Method(IEnumerable<int> $$)
              {
              }
            }
            """;
        await VerifyItemExistsAsync(markup, "ints");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36364")]
    public async Task EnumerableParameterOfObject()
    {
        var markup = """
            using System.Collections.Generic;
 
            public class Class1
            {
              public void Method(IEnumerable<object> $$)
              {
              }
            }
            """;
        await VerifyItemExistsAsync(markup, "objects");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36364")]
    public async Task EnumerableParameterOfString()
    {
        var markup = """
            using System.Collections.Generic;
 
            public class Class1
            {
              public void Method(IEnumerable<string> $$)
              {
              }
            }
            """;
        await VerifyItemExistsAsync(markup, "strings");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36364")]
    public async Task EnumerableGenericTParameter()
    {
        var markup = """
            using System.Collections.Generic;
 
            public class Class1
            {
              public void Method<T>(IEnumerable<T> $$)
              {
              }
            }
            """;
        await VerifyItemExistsAsync(markup, "values");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36364")]
    public async Task EnumerableGenericTNameParameter()
    {
        var markup = """
            using System.Collections.Generic;
 
            public class Class1
            {
              public void Method<TResult>(IEnumerable<TResult> $$)
              {
              }
            }
            """;
        await VerifyItemExistsAsync(markup, "results");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36364")]
    public async Task EnumerableGenericUnexpectedlyNamedParameter()
    {
        var markup = """
            using System.Collections.Generic;
 
            public class Class1
            {
              public void Method<Arg>(IEnumerable<Arg> $$)
              {
              }
            }
            """;
        await VerifyItemExistsAsync(markup, "args");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36364")]
    public async Task EnumerableGenericUnexpectedlyNamedParameterBeginsWithT()
    {
        var markup = """
            using System.Collections.Generic;
 
            public class Class1
            {
              public void Method<Type>(IEnumerable<Type> $$)
              {
              }
            }
            """;
        await VerifyItemExistsAsync(markup, "types");
    }
 
    [Fact]
    public async Task CustomNamingStyleInsideClass()
    {
        using var workspaceFixture = GetOrCreateWorkspaceFixture();
 
        var workspace = workspaceFixture.Target.GetWorkspace(GetComposition());
 
        workspace.SetAnalyzerFallbackOptions(new OptionsCollection(LanguageNames.CSharp)
        {
            { NamingStyleOptions.NamingPreferences, NamesEndWithSuffixPreferences() }
        });
 
        var markup = """
            class Configuration
            {
                Configuration $$
            }
            """;
        await VerifyItemExistsAsync(markup, "ConfigurationField", glyph: (int)Glyph.FieldPublic,
            expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
        await VerifyItemExistsAsync(markup, "ConfigurationProperty", glyph: (int)Glyph.PropertyPublic,
            expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
        await VerifyItemExistsAsync(markup, "ConfigurationMethod", glyph: (int)Glyph.MethodPublic,
            expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
        await VerifyItemIsAbsentAsync(markup, "ConfigurationLocal");
        await VerifyItemIsAbsentAsync(markup, "ConfigurationLocalFunction");
    }
 
    [Fact]
    public async Task CustomNamingStyleInsideMethod()
    {
        using var workspaceFixture = GetOrCreateWorkspaceFixture();
 
        var workspace = workspaceFixture.Target.GetWorkspace(GetComposition());
 
        workspace.SetAnalyzerFallbackOptions(new OptionsCollection(LanguageNames.CSharp)
        {
            { NamingStyleOptions.NamingPreferences, NamesEndWithSuffixPreferences() }
        });
 
        var markup = """
            class Configuration
            {
                void M()
                {
                    Configuration $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "ConfigurationLocal", glyph: (int)Glyph.Local,
            expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
        await VerifyItemExistsAsync(markup, "ConfigurationLocalFunction", glyph: (int)Glyph.MethodPublic,
            expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
        await VerifyItemIsAbsentAsync(markup, "ConfigurationField");
        await VerifyItemIsAbsentAsync(markup, "ConfigurationMethod");
        await VerifyItemIsAbsentAsync(markup, "ConfigurationProperty");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31304")]
    public async Task TestCompletionDoesNotUseForeachVariableName()
    {
        var markup = """
            class ClassA
            {
                class ClassB {}
 
                readonly List<ClassB> classBList;
 
                void M()
                {
                    foreach (var classB in classBList)
                    {
                        ClassB $$
                    }
                }
            }
            """;
        await VerifyItemIsAbsentAsync(markup, "classB");
        await VerifyItemExistsAsync(markup, "classB1", glyph: (int)Glyph.Local,
                expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31304")]
    public async Task TestCompletionDoesNotUseParameterName()
    {
        var markup = """
            class ClassA
            {
                class ClassB { }
 
                void M(ClassB classB)
                {
                    ClassB $$
                }
            }
            """;
        await VerifyItemIsAbsentAsync(markup, "classB");
        await VerifyItemExistsAsync(markup, "classB1", glyph: (int)Glyph.Local,
                expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31304")]
    public async Task TestCompletionCanUsePropertyName()
    {
        var markup = """
            class ClassA
            {
                class ClassB { }
 
                ClassB classB { get; set; }
 
                void M()
                {
                    ClassB $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "classB", glyph: (int)Glyph.Local,
                expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31304")]
    public async Task TestCompletionCanUseFieldName()
    {
        var markup = """
            class ClassA
            {
                class ClassB { }
 
                ClassB classB;
 
                void M()
                {
                    ClassB $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "classB", glyph: (int)Glyph.Local,
                expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31304")]
    public async Task TestCompletionDoesNotUseLocalName()
    {
        var markup = """
            class ClassA
            {
                class ClassB { }
 
                void M()
                {
                    ClassB classB = new ClassB();
                    ClassB $$
                }
            }
            """;
        await VerifyItemIsAbsentAsync(markup, "classB");
        await VerifyItemExistsAsync(markup, "classB1", glyph: (int)Glyph.Local,
                expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31304")]
    public async Task TestCompletionDoesNotUseLocalNameMultiple()
    {
        var markup = """
            class ClassA
            {
                class ClassB { }
 
                void M()
                {
                    ClassB classB = new ClassB();
                    ClassB classB1 = new ClassB();
                    ClassB $$
                }
            }
            """;
        await VerifyItemIsAbsentAsync(markup, "classB");
        await VerifyItemIsAbsentAsync(markup, "classB1");
        await VerifyItemExistsAsync(markup, "classB2", glyph: (int)Glyph.Local,
                expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31304")]
    public async Task TestCompletionDoesNotUseLocalInsideIf()
    {
        var markup = """
            class ClassA
            {
                class ClassB { }
 
                void M(bool flag)
                {
                    ClassB $$
                    if (flag)
                    {
                        ClassB classB = new ClassB();
                    }
                }
            }
            """;
        await VerifyItemIsAbsentAsync(markup, "classB");
        await VerifyItemExistsAsync(markup, "classB1", glyph: (int)Glyph.Local,
                expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31304")]
    public async Task TestCompletionCanUseClassName()
    {
        var markup = """
            class classA
            {
                void M()
                {
                    classA $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "classA", glyph: (int)Glyph.Local,
                expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31304")]
    public async Task TestCompletionCanUseLocalInDifferentScope()
    {
        var markup = """
            class ClassA
            {
                class ClassB { }
 
                void M()
                {
                    ClassB classB = new ClassB(); 
                }
 
                void M2()
                {
                    ClassB $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "classB", glyph: (int)Glyph.Local,
                expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
    }
 
    [InlineData(LanguageVersion.CSharp7)]
    [InlineData(LanguageVersion.CSharp8)]
    [InlineData(LanguageVersion.Latest)]
    [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/35891")]
    [WorkItem("https://github.com/dotnet/roslyn/issues/42049")]
    public async Task TestUseLocalAsLocalFunctionParameter(LanguageVersion languageVersion)
    {
        var source = """
            class ClassA
            {
                class ClassB { }
                void M()
                {
                    ClassB classB = new ClassB();
                    void LocalM1(ClassB $$) { }
                }
            }
            """;
        var markup = GetMarkup(source, languageVersion);
 
        if (languageVersion.MapSpecifiedToEffectiveVersion() >= LanguageVersion.CSharp8)
        {
            await VerifyItemExistsAsync(markup, "classB", glyph: (int)Glyph.Parameter,
                    expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
        }
        else
        {
            await VerifyItemIsAbsentAsync(markup, "classB");
        }
    }
 
    [InlineData(LanguageVersion.CSharp7)]
    [InlineData(LanguageVersion.CSharp8)]
    [InlineData(LanguageVersion.Latest)]
    [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/35891")]
    [WorkItem("https://github.com/dotnet/roslyn/issues/42049")]
    public async Task TestCompletionDoesNotUseLocalAsLocalFunctionVariable(LanguageVersion languageVersion)
    {
        var source = """
            class ClassA
            {
                class ClassB { }
                void M()
                {
                    ClassB classB = new ClassB();
                    void LocalM1()
                    {
                        ClassB $$
                    }
                }
            }
            """;
        var markup = GetMarkup(source, languageVersion);
        await VerifyItemIsAbsentAsync(markup, "classB");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35891")]
    public async Task TestCompletionDoesNotUseLocalInNestedLocalFunction()
    {
        var markup = """
            class ClassA
            {
                class ClassB { }
                void M()
                {
                    ClassB classB = new ClassB();
                    void LocalM1()
                    {
                        void LocalM2()
                        {
                            ClassB $$
                        }
                    }
                }
            }
            """;
        await VerifyItemIsAbsentAsync(markup, "classB");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35891")]
    public async Task TestCompletionDoesNotUseLocalFunctionParameterInNestedLocalFunction()
    {
        var markup = """
            class ClassA
            {
                class ClassB { }
                void M()
                {
                    void LocalM1(ClassB classB)
                    {
                        void LocalM2()
                        {
                            ClassB $$
                        }
                    }
                }
            }
            """;
        await VerifyItemIsAbsentAsync(markup, "classB");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35891")]
    public async Task TestCompletionCanUseLocalFunctionParameterAsParameter()
    {
        var markup = """
            class ClassA
            {
                class ClassB { }
                void M()
                {
                    void LocalM1(ClassB classB) { }
                    void LocalM2(ClassB $$) { }
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "classB", glyph: (int)Glyph.Parameter,
                expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35891")]
    public async Task TestCompletionCanUseLocalFunctionVariableAsParameter()
    {
        var markup = """
            class ClassA
            {
                class ClassB { }
                void M()
                {
                    void LocalM1()
                    {
                        ClassB classB
                    }
                    void LocalM2(ClassB $$) { }
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "classB", glyph: (int)Glyph.Parameter,
                expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35891")]
    public async Task TestCompletionCanUseLocalFunctionParameterAsVariable()
    {
        var markup = """
            class ClassA
            {
                class ClassB { }
                void M()
                {
                    void LocalM1(ClassB classB) { }
                    void LocalM2()
                    {
                        ClassB $$
                    }
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "classB", glyph: (int)Glyph.Local,
                expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35891")]
    public async Task TestCompletionCanUseLocalFunctionVariableAsVariable()
    {
        var markup = """
            class ClassA
            {
                class ClassB { }
                void M()
                {
                    void LocalM1()
                    {
                        ClassB classB
                    }
                    void LocalM2()
                    {
                        ClassB $$
                    }
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "classB", glyph: (int)Glyph.Local,
                expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name);
    }
 
    [Fact]
    public async Task TestNotForUnboundAsync()
    {
        var markup = """
            class C
            {
                async $$
            }
            """;
        await VerifyItemIsAbsentAsync(markup, "async");
        await VerifyItemIsAbsentAsync(markup, "Async");
        await VerifyItemIsAbsentAsync(markup, "GetAsync");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/pull/43816")]
    public async Task ConflictingLocalVariable()
    {
        using var workspaceFixture = GetOrCreateWorkspaceFixture();
 
        var workspace = workspaceFixture.Target.GetWorkspace(GetComposition());
 
        workspace.SetAnalyzerFallbackOptions(new OptionsCollection(LanguageNames.CSharp)
        {
            { NamingStyleOptions.NamingPreferences, MultipleCamelCaseLocalRules() }
        });
 
        var markup = """
            public class MyClass
            {
                void M()
                {
                    MyClass myClass;
                    MyClass $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "myClass1", glyph: (int)Glyph.Local);
    }
 
    [Fact]
    public async Task TestNotForNonTypeSymbol()
    {
        var markup = """
            using System;
            class C
            {
                Console.BackgroundColor $$
            }
            """;
        await VerifyItemIsAbsentAsync(markup, "consoleColor");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/29487")]
    public async Task TestForOutParam1()
    {
        var markup = """
            using System.Threading;
 
            class C
            {
                void Main()
                {
                    Goo(out var $$)
                }
 
                void Goo(out CancellationToken interestingName)
                {
 
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "interestingName");
        await VerifyItemExistsAsync(markup, "cancellationToken");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/43602")]
    public async Task TestForOutParam2()
    {
        var markup = """
            class C
            {
                void Main()
                {
                    int.TryParse("", out var $$)
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "result");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/49791")]
    public async Task TestForErrorType1()
    {
        var markup = """
            class C
            {
                void Main(string _rootPath)
                {
                    _rootPath $$
                    _rootPath = null;
                }
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/49791")]
    public async Task TestForErrorType2()
    {
        var markup = """
            class C
            {
                void Main()
                {
                    Goo $$
                    Goo = null;
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "goo");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36352")]
    public async Task InferCollectionInErrorCase1()
    {
        var markup = """
            class Customer { }
 
            class V
            {
                void M(IEnumerable<Customer> $$)
                {
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "customers");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/63943")]
    public async Task InferOffOfGenericNameInPattern()
    {
        var markup = """
            using System.Collections.Generic;
 
            class Customer { }
 
            class V
            {
                void M(object o)
                {
                    if (o is List<Customer> $$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "customers");
    }
 
    private static NamingStylePreferences MultipleCamelCaseLocalRules()
    {
        var styles = new[]
        {
            SpecificationStyle(new SymbolKindOrTypeKind(SymbolKind.Local), name: "Local1"),
            SpecificationStyle(new SymbolKindOrTypeKind(SymbolKind.Local), name: "Local1"),
        };
 
        return new NamingStylePreferences(
            styles.Select(t => t.specification).ToImmutableArray(),
            styles.Select(t => t.style).ToImmutableArray(),
            styles.Select(t => CreateRule(t.specification, t.style)).ToImmutableArray());
 
        // Local functions
 
        static (SymbolSpecification specification, NamingStyle style) SpecificationStyle(SymbolKindOrTypeKind kind, string name)
        {
            var symbolSpecification = new SymbolSpecification(
                Guid.NewGuid(),
                name,
                ImmutableArray.Create(kind));
 
            var namingStyle = new NamingStyle(
                Guid.NewGuid(),
                name,
                capitalizationScheme: Capitalization.CamelCase);
 
            return (symbolSpecification, namingStyle);
        }
    }
 
    private static NamingStylePreferences NamesEndWithSuffixPreferences()
    {
        var specificationStyles = new[]
        {
            SpecificationStyle(new SymbolKindOrTypeKind(SymbolKind.Field), "Field"),
            SpecificationStyle(new SymbolKindOrTypeKind(SymbolKind.Property), "Property"),
            SpecificationStyle(new SymbolKindOrTypeKind(MethodKind.Ordinary), "Method"),
            SpecificationStyle(new SymbolKindOrTypeKind(SymbolKind.Local), "Local"),
            SpecificationStyle(new SymbolKindOrTypeKind(MethodKind.LocalFunction), "LocalFunction"),
        };
 
        return new NamingStylePreferences(
            specificationStyles.Select(t => t.specification).ToImmutableArray(),
            specificationStyles.Select(t => t.style).ToImmutableArray(),
            specificationStyles.Select(t => CreateRule(t.specification, t.style)).ToImmutableArray());
 
        // Local functions
 
        static (SymbolSpecification specification, NamingStyle style) SpecificationStyle(SymbolKindOrTypeKind kind, string suffix)
        {
            var symbolSpecification = new SymbolSpecification(
                Guid.NewGuid(),
                name: suffix,
                ImmutableArray.Create(kind),
                accessibilityList: default,
                modifiers: default);
 
            var namingStyle = new NamingStyle(
                Guid.NewGuid(),
                name: suffix,
                capitalizationScheme: Capitalization.PascalCase,
                prefix: "",
                suffix: suffix,
                wordSeparator: "");
 
            return (symbolSpecification, namingStyle);
        }
    }
 
    private static NamingStylePreferences ParameterCamelCaseWithPascalCaseFallback()
    {
        var symbolSpecifications = ImmutableArray.Create(
            new SymbolSpecification(
                id: Guid.NewGuid(),
                name: "parameters",
                ImmutableArray.Create(new SymbolKindOrTypeKind(SymbolKind.Parameter)),
                accessibilityList: default,
                modifiers: default),
            new SymbolSpecification(
                id: Guid.NewGuid(),
                name: "fallback",
                ImmutableArray.Create(new SymbolKindOrTypeKind(SymbolKind.Parameter), new SymbolKindOrTypeKind(SymbolKind.Local)),
                accessibilityList: default,
                modifiers: default));
        var namingStyles = ImmutableArray.Create(
            new NamingStyle(
                Guid.NewGuid(),
                name: "parameter",
                capitalizationScheme: Capitalization.CamelCase,
                prefix: "",
                suffix: "",
                wordSeparator: ""),
            new NamingStyle(
                Guid.NewGuid(),
                name: "any_symbol",
                capitalizationScheme: Capitalization.PascalCase,
                prefix: "",
                suffix: "",
                wordSeparator: ""));
        return new NamingStylePreferences(
            symbolSpecifications,
            namingStyles,
            namingRules: ImmutableArray.Create(
                CreateRule(symbolSpecifications[0], namingStyles[0]),
                CreateRule(symbolSpecifications[1], namingStyles[1])));
    }
 
    private static SerializableNamingRule CreateRule(SymbolSpecification specification, NamingStyle style)
        => new()
        {
            SymbolSpecificationID = specification.ID,
            NamingStyleID = style.ID,
            EnforcementLevel = ReportDiagnostic.Error
        };
}