File: Completion\CompletionProviders\NamedParameterCompletionProviderTests.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.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.CSharp.Completion.Providers;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionSetSources;
 
[Trait(Traits.Feature, Traits.Features.Completion)]
public class NamedParameterCompletionProviderTests : AbstractCSharpCompletionProviderTests
{
    internal override Type GetCompletionProviderType()
        => typeof(NamedParameterCompletionProvider);
 
    [Fact]
    public async Task SendEnterThroughToEditorTest()
    {
        const string markup = """
            class Goo
            {
                public Goo(int a = 42)
                { }
 
                void Bar()
                {
                    var b = new Goo($$
                }
            }
            """;
 
        await VerifySendEnterThroughToEnterAsync(markup, "a:", sendThroughEnterOption: EnterKeyRule.Never, expected: false);
        await VerifySendEnterThroughToEnterAsync(markup, "a:", sendThroughEnterOption: EnterKeyRule.AfterFullyTypedWord, expected: true);
        await VerifySendEnterThroughToEnterAsync(markup, "a:", sendThroughEnterOption: EnterKeyRule.Always, expected: true);
    }
 
    [Fact]
    public async Task CommitCharacterTest()
    {
        const string markup = """
            class Goo
            {
                public Goo(int a = 42)
                { }
 
                void Bar()
                {
                    var b = new Goo($$
                }
            }
            """;
 
        await VerifyCommonCommitCharactersAsync(markup, textTypedSoFar: "");
    }
 
    [Fact]
    public async Task InObjectCreation()
    {
        var markup = """
            class Goo
            {
                public Goo(int a = 42)
                { }
 
                void Bar()
                {
                    var b = new Goo($$
                }
            }
            """;
 
        await VerifyItemExistsAsync(markup, "a", displayTextSuffix: ":");
    }
 
    [Fact]
    public async Task InBaseConstructor()
    {
        var markup = """
            class Goo
            {
                public Goo(int a = 42)
                { }
            }
 
            class DogBed : Goo
            {
                public DogBed(int b) : base($$
            }
            """;
 
        await VerifyItemExistsAsync(markup, "a", displayTextSuffix: ":");
    }
 
    [Fact]
    public async Task InvocationExpression()
    {
        var markup = """
            class Goo
            {
                void Bar(int a)
                {
                    Bar($$
                }
            }
            """;
 
        await VerifyItemExistsAsync(markup, "a", displayTextSuffix: ":");
    }
 
    [Fact]
    public async Task InvocationExpressionAfterComma()
    {
        var markup = """
            class Goo
            {
                void Bar(int a, string b)
                {
                    Bar(b:"", $$
                }
            }
            """;
 
        await VerifyItemExistsAsync(markup, "a", displayTextSuffix: ":");
    }
 
    [Fact]
    public async Task ElementAccessExpression()
    {
        var markup = """
            class SampleCollection<T>
            {
                private T[] arr = new T[100];
                public T this[int i]
                {
                    get
                    {
                        return arr[i];
                    }
                    set
                    {
                        arr[i] = value;
                    }
                }
            }
 
            class Program
            {
                static void Main(string[] args)
                {
                    SampleCollection<string> stringCollection = new SampleCollection<string>();
                    stringCollection[$$
                }
            }
            """;
 
        await VerifyItemExistsAsync(markup, "i", displayTextSuffix: ":");
    }
 
    [Fact]
    public async Task PartialMethods()
    {
        var markup = """
            partial class PartialClass
            {
                static partial void Goo(int declaring);
                static partial void Goo(int implementing)
                {
                }
                static void Caller()
                {
                    Goo($$
                }
            }
            """;
 
        await VerifyItemExistsAsync(markup, "declaring", displayTextSuffix: ":");
        await VerifyItemIsAbsentAsync(markup, "implementing", displayTextSuffix: ":");
    }
 
    [Fact]
    public async Task ExtendedPartialMethods()
    {
        var markup = """
            partial class PartialClass
            {
                public static partial void Goo(int declaring);
                public static partial void Goo(int implementing)
                {
                }
                static void Caller()
                {
                    Goo($$
                }
            }
            """;
 
        await VerifyItemExistsAsync(markup, "declaring", displayTextSuffix: ":");
        await VerifyItemIsAbsentAsync(markup, "implementing", displayTextSuffix: ":");
    }
 
    [Fact]
    public async Task NotAfterColon()
    {
        var markup = """
            class Goo
            {
                void Bar(int a, string b)
                {
                    Bar(a:$$ 
                }
            }
            """;
 
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544292")]
    public async Task NotInCollectionInitializers()
    {
        var markup = """
            using System.Collections.Generic;
            class Goo
            {
                void Bar(List<int> integers)
                {
                    Bar(integers: new List<int> { 10, 11,$$ 12 });
                }
            }
            """;
 
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544191")]
    public async Task FilteringOverloadsByCallSite()
    {
        var markup = """
            class Class1
            {
                void Test()
                {
                    Goo(boolean:true, $$)
                }
 
                void Goo(string str = "hello", char character = 'a')
                { }
 
                void Goo(string str = "hello", bool boolean = false)
                { }
            }
            """;
 
        await VerifyItemExistsAsync(markup, "str", displayTextSuffix: ":");
        await VerifyItemIsAbsentAsync(markup, "character", displayTextSuffix: ":");
    }
 
    [Fact]
    public async Task DoNotFilterYet()
    {
        var markup = """
            class Class1
            {
                void Test()
                {
                    Goo(str:"", $$)
                }
 
                void Goo(string str = "hello", char character = 'a')
                { }
 
                void Goo(string str = "hello", bool boolean = false)
                { }
            }
            """;
 
        await VerifyItemExistsAsync(markup, "boolean", displayTextSuffix: ":");
        await VerifyItemExistsAsync(markup, "character", displayTextSuffix: ":");
    }
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544191")]
    public async Task FilteringOverloadsByCallSiteComplex()
    {
        var markup = """
            class Goo
            {
                void Test()
                {
                    Bar m = new Bar();
                    Method(obj:m, $$
                }
 
                void Method(Bar obj, int num = 23, string str = "")
                {
                }
                void Method(double dbl = double.MinValue, string str = "")
                {
                }
                void Method(int num = 1, bool b = false, string str = "")
                {
                }
                void Method(Bar obj, bool b = false, string str = "")
                {
                }
            }
            class Bar { }
            """;
        await VerifyItemExistsAsync(markup, "str", displayTextSuffix: ":");
        await VerifyItemExistsAsync(markup, "num", displayTextSuffix: ":");
        await VerifyItemExistsAsync(markup, "b", displayTextSuffix: ":");
        await VerifyItemIsAbsentAsync(markup, "dbl", displayTextSuffix: ":");
    }
 
    [Fact]
    public async Task MethodOverloads()
    {
        var markup = """
            class Goo
            {
                void Test()
                {
                    object m = null;
                    Method(m, $$
                }
 
                void Method(object obj, int num = 23, string str = "")
                {
                }
                void Method(int num = 1, bool b = false, string str = "")
                {
                }
                void Method(object obj, bool b = false, string str = "")
                {
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "str", displayTextSuffix: ":");
        await VerifyItemExistsAsync(markup, "num", displayTextSuffix: ":");
        await VerifyItemExistsAsync(markup, "b", displayTextSuffix: ":");
    }
 
    [Fact]
    public async Task ExistingNamedParamsAreFilteredOut()
    {
        var markup = """
            class Goo
            {
                void Test()
                {
                    object m = null;
                    Method(obj: m, str: "", $$);
                }
 
                void Method(object obj, int num = 23, string str = "")
                {
                }
                void Method(double dbl = double.MinValue, string str = "")
                {
                }
                void Method(int num = 1, bool b = false, string str = "")
                {
                }
                void Method(object obj, bool b = false, string str = "")
                {
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "num", displayTextSuffix: ":");
        await VerifyItemExistsAsync(markup, "b", displayTextSuffix: ":");
        await VerifyItemIsAbsentAsync(markup, "obj", displayTextSuffix: ":");
        await VerifyItemIsAbsentAsync(markup, "str", displayTextSuffix: ":");
    }
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529369")]
    public async Task VerbatimIdentifierNotAKeyword()
    {
        var markup = """
            class Program
            {
                void Goo(int @integer)
                {
                    Goo(@i$$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "integer", displayTextSuffix: ":");
    }
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544209")]
    public async Task DescriptionStringInMethodOverloads()
    {
        var markup = """
            class Class1
            {
                void Test()
                {
                    Goo(boolean: true, $$)
                }
 
                void Goo(string obj = "hello")
                { }
 
                void Goo(bool boolean = false, Class1 obj = default(Class1))
                { }
            }
            """;
        await VerifyItemExistsAsync(markup, "obj", displayTextSuffix: ":",
            expectedDescriptionOrNull: $"({FeaturesResources.parameter}) Class1 obj = default(Class1)");
    }
 
    [Fact]
    public async Task InDelegates()
    {
        var markup = """
            public delegate void Del(string message);
 
            class Program
            {
                public static void DelegateMethod(string message)
                {
                    System.Console.WriteLine(message);
                }
 
                static void Main(string[] args)
                {
                    Del handler = DelegateMethod;
                    handler($$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "message", displayTextSuffix: ":");
    }
 
    [Fact]
    public async Task InDelegateInvokeSyntax()
    {
        var markup = """
            public delegate void Del(string message);
 
            class Program
            {
                public static void DelegateMethod(string message)
                {
                    System.Console.WriteLine(message);
                }
 
                static void Main(string[] args)
                {
                    Del handler = DelegateMethod;
                    handler.Invoke($$
                }
            }
            """;
        await VerifyItemExistsAsync(markup, "message", displayTextSuffix: ":");
    }
 
    [Fact]
    public async Task NotInComment()
    {
        var markup = """
            public class Test
            {
            static void Main()
            {
            M(x: 0, //Hit ctrl-space at the end of this comment $$
            y: 1);
            }
            static void M(int x, int y) { }
            }
            """;
        await VerifyNoItemsExistAsync(markup);
    }
 
    [Fact]
    public async Task CommitWithColonWordFullyTyped()
    {
        var markup = """
            class Program
            {
                static void Main(string[] args)
                {
                    Main(args$$)
                }
            }
            """;
 
        var expected = """
            class Program
            {
                static void Main(string[] args)
                {
                    Main(args:)
                }
            }
            """;
        await VerifyProviderCommitAsync(markup, "args:", expected, ':');
    }
 
    [Fact]
    public async Task CommitWithColonWordPartiallyTyped()
    {
        var markup = """
            class Program
            {
                static void Main(string[] args)
                {
                    Main(arg$$)
                }
            }
            """;
 
        var expected = """
            class Program
            {
                static void Main(string[] args)
                {
                    Main(args:)
                }
            }
            """;
        await VerifyProviderCommitAsync(markup, "args:", expected, ':');
    }
}