File: Completion\CompletionProviders\NamedParameterCompletionProviderTests.cs
Web Access
Project: ..\..\..\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 DontFilterYet()
        {
            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, ':');
        }
    }
}