File: Completion\CompletionProviders\PartialMethodCompletionProviderTests.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.
 
#nullable disable
 
using System;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Completion.Providers;
using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders;
 
[Trait(Traits.Feature, Traits.Features.Completion)]
public class PartialMethodCompletionProviderTests : AbstractCSharpCompletionProviderTests
{
    internal override Type GetCompletionProviderType()
        => typeof(PartialMethodCompletionProvider);
 
    [Fact]
    public async Task NoPartialMethods1()
    {
        var text = """
            class c
            {
                $$
            }
            """;
        await VerifyNoItemsExistAsync(text);
    }
 
    [Fact]
    public async Task NoPartialMethods2()
    {
        var text = """
            class c
            {
                private void goo() { };
 
                partial void $$
            }
            """;
        await VerifyNoItemsExistAsync(text);
    }
 
    [Fact]
    public async Task NoExtendedPartialMethods2()
    {
        var text = """
            class c
            {
                public void goo() { };
 
                public void $$
            }
            """;
        await VerifyNoItemsExistAsync(text);
    }
 
    [Fact]
    public async Task PartialMethodInPartialClass()
    {
        var text = """
            partial class c
            {
                partial void goo();
 
                partial void $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task ExtendedPartialMethodInPartialClass()
    {
        var text = """
            partial class c
            {
                public partial void goo();
 
                public partial void $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task PartialMethodInPartialGenericClass()
    {
        var text = """
            partial class c<T>
            {
                partial void goo(T bar);
 
                partial void $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo(T bar)");
    }
 
    [Fact]
    public async Task ExtendedPartialMethodInPartialGenericClass()
    {
        var text = """
            partial class c<T>
            {
                public partial void goo(T bar);
 
                public partial void $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo(T bar)");
    }
 
    [Fact]
    public async Task PartialMethodInPartialStruct()
    {
        var text = """
            partial struct c
            {
                partial void goo();
 
                partial void $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task ExtendedPartialMethodInPartialStruct()
    {
        var text = """
            partial struct c
            {
                public partial void goo();
 
                public partial void $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task CompletionOnPartial1()
    {
        var text = """
            partial class c
            {
                partial void goo();
 
                partial $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task CompletionOnExtendedPartial1()
    {
        var text = """
            partial class c
            {
                public partial void goo();
 
                partial $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task CompletionOnPartial2()
    {
        var text = """
            partial class c
            {
                partial void goo();
 
                void partial $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task CompletionOnExtendedPartial2()
    {
        var text = """
            partial class c
            {
                public partial void goo();
 
                void partial $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task StaticUnsafePartial()
    {
        var text = """
            partial class c
            {
                partial static unsafe void goo();
 
                void static unsafe partial $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task StaticUnsafeExtendedPartial()
    {
        var text = """
            partial class c
            {
                public partial static unsafe void goo();
 
                void static unsafe partial $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task PartialCompletionWithPrivate()
    {
        var text = """
            partial class c
            {
                partial static unsafe void goo();
 
                private partial $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task PartialCompletionWithPublic()
    {
        var text = """
            partial class c
            {
                public partial static unsafe void goo();
 
                public partial $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task NotCompletionDespiteValidModifier()
    {
        var text = """
            partial class c
            {
                partial void goo();
 
                void partial unsafe $$
            }
            """;
        await VerifyNoItemsExistAsync(text);
    }
 
    [Fact]
    public async Task NoExtendedCompletionDespiteValidModifier()
    {
        var text = """
            partial class c
            {
                public partial void goo();
 
                void partial unsafe $$
            }
            """;
        await VerifyNoItemsExistAsync(text);
    }
 
    [Fact]
    public async Task YesIfPublic()
    {
        var text = """
            partial class c
            {
                public partial void goo();
 
                void partial $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task YesIfInternal()
    {
        var text = """
            partial class c
            {
                internal partial void goo();
 
                void partial $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task YesIfProtected()
    {
        var text = """
            partial class c
            {
                protected partial void goo();
 
                void partial $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task YesIfProtectedInternal()
    {
        var text = """
            partial class c
            {
                protected internal partial void goo();
 
                void partial $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task YesIfExtern()
    {
        var text = """
            partial class c
            {
                partial void goo();
 
                extern void partial $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task YesIfVirtual()
    {
        var text = """
            partial class c
            {
                virtual partial void goo();
 
                void partial $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task YesIfNonVoidReturnType()
    {
        var text = """
            partial class c
            {
                partial int goo();
 
                partial $$
            }
            """;
        await VerifyItemExistsAsync(text, "goo()");
    }
 
    [Fact]
    public async Task NotInsideInterface()
    {
        var text = """
            partial interface i
            {
                partial void goo();
 
                partial $$
            }
            """;
        await VerifyNoItemsExistAsync(text);
    }
 
    [WpfFact]
    public async Task CommitInPartialClass()
    {
        var markupBeforeCommit = """
            partial class c
            {
                partial void goo();
 
                partial $$
            }
            """;
 
        var expectedCodeAfterCommit = """
            partial class c
            {
                partial void goo();
 
                partial void goo()
                {
                    throw new System.NotImplementedException();$$
                }
            }
            """;
 
        await VerifyCustomCommitProviderAsync(markupBeforeCommit, "goo()", expectedCodeAfterCommit);
    }
 
    [WpfFact]
    public async Task CommitInExtendedPartialClass()
    {
        var markupBeforeCommit = """
            partial class c
            {
                public partial void goo();
 
                partial $$
            }
            """;
 
        var expectedCodeAfterCommit = """
            partial class c
            {
                public partial void goo();
 
                public partial void goo()
                {
                    throw new System.NotImplementedException();$$
                }
            }
            """;
 
        await VerifyCustomCommitProviderAsync(markupBeforeCommit, "goo()", expectedCodeAfterCommit);
    }
 
    [WpfFact]
    public async Task CommitGenericPartialMethod()
    {
        var markupBeforeCommit = """
            partial class c<T>
            {
                partial void goo(T bar);
 
                partial $$
            }
            """;
 
        var expectedCodeAfterCommit = """
            partial class c<T>
            {
                partial void goo(T bar);
 
                partial void goo(T bar)
                {
                    throw new System.NotImplementedException();$$
                }
            }
            """;
 
        await VerifyCustomCommitProviderAsync(markupBeforeCommit, "goo(T bar)", expectedCodeAfterCommit);
    }
 
    [WpfFact]
    public async Task CommitGenericExtendedPartialMethod()
    {
        var markupBeforeCommit = """
            partial class c<T>
            {
                public partial void goo(T bar);
 
                partial $$
            }
            """;
 
        var expectedCodeAfterCommit = """
            partial class c<T>
            {
                public partial void goo(T bar);
 
                public partial void goo(T bar)
                {
                    throw new System.NotImplementedException();$$
                }
            }
            """;
 
        await VerifyCustomCommitProviderAsync(markupBeforeCommit, "goo(T bar)", expectedCodeAfterCommit);
    }
 
    [WpfFact]
    public async Task CommitMethodErasesPrivate()
    {
        var markupBeforeCommit = """
            partial class c
            {
                partial void goo();
 
                private partial $$
            }
            """;
 
        var expectedCodeAfterCommit = """
            partial class c
            {
                partial void goo();
 
                partial void goo()
                {
                    throw new System.NotImplementedException();$$
                }
            }
            """;
 
        await VerifyCustomCommitProviderAsync(markupBeforeCommit, "goo()", expectedCodeAfterCommit);
    }
 
    [WpfFact]
    public async Task CommitMethodKeepsExtendedPrivate()
    {
        var markupBeforeCommit = """
            partial class c
            {
                private partial void goo();
 
                private partial $$
            }
            """;
 
        var expectedCodeAfterCommit = """
            partial class c
            {
                private partial void goo();
 
                private partial void goo()
                {
                    throw new System.NotImplementedException();$$
                }
            }
            """;
 
        await VerifyCustomCommitProviderAsync(markupBeforeCommit, "goo()", expectedCodeAfterCommit);
    }
 
    [WpfFact]
    public async Task CommitInPartialClassPart()
    {
        var markupBeforeCommit = """
            partial class c
            {
                partial void goo();
            }
 
            partial class c
            {
                partial $$
            }
            """;
 
        var expectedCodeAfterCommit = """
            partial class c
            {
                partial void goo();
            }
 
            partial class c
            {
                partial void goo()
                {
                    throw new System.NotImplementedException();$$
                }
            }
            """;
 
        await VerifyCustomCommitProviderAsync(markupBeforeCommit, "goo()", expectedCodeAfterCommit);
    }
 
    [WpfFact]
    public async Task CommitInExtendedPartialClassPart()
    {
        var markupBeforeCommit = """
            partial class c
            {
                public partial void goo();
            }
 
            partial class c
            {
                partial $$
            }
            """;
 
        var expectedCodeAfterCommit = """
            partial class c
            {
                public partial void goo();
            }
 
            partial class c
            {
                public partial void goo()
                {
                    throw new System.NotImplementedException();$$
                }
            }
            """;
 
        await VerifyCustomCommitProviderAsync(markupBeforeCommit, "goo()", expectedCodeAfterCommit);
    }
 
    [WpfFact]
    public async Task CommitInPartialStruct()
    {
        var markupBeforeCommit = """
            partial struct c
            {
                partial void goo();
 
                partial $$
            }
            """;
 
        var expectedCodeAfterCommit = """
            partial struct c
            {
                partial void goo();
 
                partial void goo()
                {
                    throw new System.NotImplementedException();$$
                }
            }
            """;
 
        await VerifyCustomCommitProviderAsync(markupBeforeCommit, "goo()", expectedCodeAfterCommit);
    }
 
    [Fact]
    public async Task NotIfNoPartialKeyword()
    {
        var text = """
            partial class C
                {
                    partial void Goo();
                }
 
                partial class C
                {
                    void $$
                }
            """;
        await VerifyNoItemsExistAsync(text);
    }
 
    [Fact]
    public async Task NotIfNoExtendedPartialKeyword()
    {
        var text = """
            partial class C
                {
                    public partial void Goo();
                }
 
                partial class C
                {
                    void $$
                }
            """;
        await VerifyNoItemsExistAsync(text);
    }
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/578757")]
    public async Task DoNotConsiderFollowingDeclarationPartial()
    {
        var text = """
            class Program
            {
                partial $$
 
                void Goo()
                {
 
                }
            }
            """;
        await VerifyNoItemsExistAsync(text);
    }
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/578757")]
    public async Task DoNotConsiderFollowingDeclarationExtendedPartial()
    {
        var text = """
            class Program
            {
                public partial $$
 
                void Goo()
                {
 
                }
            }
            """;
        await VerifyNoItemsExistAsync(text);
    }
 
    [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/578078")]
    public async Task CommitAsync()
    {
        var markupBeforeCommit = """
            using System;
 
            partial class Bar
            {
                partial void Goo();
 
                async partial $$
            }
            """;
 
        var expectedCodeAfterCommit = """
            using System;
 
            partial class Bar
            {
                partial void Goo();
 
                async partial void Goo()
                {
                    throw new NotImplementedException();$$
                }
            }
            """;
 
        await VerifyCustomCommitProviderAsync(markupBeforeCommit, "Goo()", expectedCodeAfterCommit);
    }
 
    [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/578078")]
    public async Task CommitAsyncExtended()
    {
        var markupBeforeCommit = """
            using System;
 
            partial class Bar
            {
                public partial void Goo();
 
                async partial $$
            }
            """;
 
        var expectedCodeAfterCommit = """
            using System;
 
            partial class Bar
            {
                public partial void Goo();
 
                public async partial void Goo()
                {
                    throw new NotImplementedException();$$
                }
            }
            """;
 
        await VerifyCustomCommitProviderAsync(markupBeforeCommit, "Goo()", expectedCodeAfterCommit);
    }
 
    [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/578078")]
    public async Task AmbiguityCommittingWithParen()
    {
        var markupBeforeCommit = """
            using System;
 
            partial class Bar
            {
                partial void Goo();
 
                partial Goo$$
            }
            """;
 
        var expectedCodeAfterCommit = """
            using System;
 
            partial class Bar
            {
                partial void Goo();
 
                partial void Goo()
                {
                    throw new NotImplementedException();$$
                }
            }
            """;
 
        await VerifyCustomCommitProviderAsync(markupBeforeCommit, "Goo()", expectedCodeAfterCommit, commitChar: '(');
    }
 
    [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/965677")]
    public async Task NoDefaultParameterValues()
    {
        var text = """
            namespace PartialClass
            {
                partial class PClass
                {
                    partial void PMethod(int i = 0);
 
                    partial $$
                }
            }
            """;
 
        var expected = """
            namespace PartialClass
            {
                partial class PClass
                {
                    partial void PMethod(int i = 0);
 
                    partial void PMethod(int i)
                    {
                        throw new System.NotImplementedException();$$
                    }
                }
            }
            """;
        await VerifyCustomCommitProviderAsync(text, "PMethod(int i)", expected);
    }
 
    [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/965677")]
    public async Task NoDefaultParameterValuesExtended()
    {
        var text = """
            namespace PartialClass
            {
                partial class PClass
                {
                    public partial void PMethod(int i = 0);
 
                    partial $$
                }
            }
            """;
 
        var expected = """
            namespace PartialClass
            {
                partial class PClass
                {
                    public partial void PMethod(int i = 0);
 
                    public partial void PMethod(int i)
                    {
                        throw new System.NotImplementedException();$$
                    }
                }
            }
            """;
        await VerifyCustomCommitProviderAsync(text, "PMethod(int i)", expected);
    }
 
    [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/26388")]
    public async Task ExpressionBodyMethod()
    {
        using var workspaceFixture = GetOrCreateWorkspaceFixture();
 
        var workspace = workspaceFixture.Target.GetWorkspace(GetComposition());
        workspace.SetAnalyzerFallbackOptions(new OptionsCollection(LanguageNames.CSharp)
        {
            { CSharpCodeStyleOptions.PreferExpressionBodiedMethods, new CodeStyleOption2<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption2.Silent) }
        });
 
        var text = """
            using System;
            partial class Bar
            {
                partial void Foo();
                partial $$
            }
            """;
 
        var expected = """
            using System;
            partial class Bar
            {
                partial void Foo();
                partial void Foo() => throw new NotImplementedException();$$
            }
            """;
 
        await VerifyCustomCommitProviderAsync(text, "Foo()", expected);
    }
 
    [WpfFact]
    public async Task ExpressionBodyMethodExtended()
    {
        using var workspaceFixture = GetOrCreateWorkspaceFixture();
 
        var workspace = workspaceFixture.Target.GetWorkspace(GetComposition());
        workspace.SetAnalyzerFallbackOptions(new OptionsCollection(LanguageNames.CSharp)
        {
            { CSharpCodeStyleOptions.PreferExpressionBodiedMethods, new CodeStyleOption2<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption2.Silent) }
        });
 
        var text = """
            using System;
            partial class Bar
            {
                public partial void Foo();
                partial $$
            }
            """
;
 
        var expected = """
            using System;
            partial class Bar
            {
                public partial void Foo();
                public partial void Foo() => throw new NotImplementedException();$$
            }
            """
;
 
        await VerifyCustomCommitProviderAsync(text, "Foo()", expected);
    }
 
    private Task VerifyItemExistsAsync(string markup, string expectedItem)
    {
        return VerifyItemExistsAsync(markup, expectedItem, isComplexTextEdit: true);
    }
}