File: CodeActions\ImplementInterface\ImplementImplicitlyTests.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.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.ImplementInterface;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ImplementInterface;
 
[Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)]
public class ImplementImplicitlyTests : AbstractCSharpCodeActionTest
{
    private const int SingleMember = 0;
    private const int SameInterface = 1;
    private const int AllInterfaces = 2;
 
    protected override CodeRefactoringProvider CreateCodeRefactoringProvider(EditorTestWorkspace workspace, TestParameters parameters)
        => new CSharpImplementImplicitlyCodeRefactoringProvider();
 
    protected override ImmutableArray<CodeAction> MassageActions(ImmutableArray<CodeAction> actions)
        => FlattenActions(actions);
 
    [Fact]
    public async Task TestSingleMember()
    {
        await TestInRegularAndScriptAsync(
            """
            interface IGoo { void Goo1(); void Goo2(); }
            interface IBar { void Bar(); }
 
            class C : IGoo, IBar
            {
                void IGoo.[||]Goo1() { }
 
                void IGoo.Goo2() { }
 
                void IBar.Bar() { }
            }
            """,
            """
            interface IGoo { void Goo1(); void Goo2(); }
            interface IBar { void Bar(); }
 
            class C : IGoo, IBar
            {
                public void Goo1() { }
 
                void IGoo.Goo2() { }
 
                void IBar.Bar() { }
            }
            """, index: SingleMember);
    }
 
    [Fact]
    public async Task TestSameInterface()
    {
        await TestInRegularAndScriptAsync(
            """
            interface IGoo { void Goo1(); void Goo2(); }
            interface IBar { void Bar(); }
 
            class C : IGoo, IBar
            {
                void IGoo.[||]Goo1() { }
 
                void IGoo.Goo2() { }
 
                void IBar.Bar() { }
            }
            """,
            """
            interface IGoo { void Goo1(); void Goo2(); }
            interface IBar { void Bar(); }
 
            class C : IGoo, IBar
            {
                public void Goo1() { }
 
                public void Goo2() { }
 
                void IBar.Bar() { }
            }
            """, index: SameInterface);
    }
 
    [Fact]
    public async Task TestAllInterfaces()
    {
        await TestInRegularAndScriptAsync(
            """
            interface IGoo { void Goo1(); void Goo2(); }
            interface IBar { void Bar(); }
 
            class C : IGoo, IBar
            {
                void IGoo.[||]Goo1() { }
 
                void IGoo.Goo2() { }
 
                void IBar.Bar() { }
            }
            """,
            """
            interface IGoo { void Goo1(); void Goo2(); }
            interface IBar { void Bar(); }
 
            class C : IGoo, IBar
            {
                public void Goo1() { }
 
                public void Goo2() { }
 
                public void Bar() { }
            }
            """, index: AllInterfaces);
    }
 
    [Fact]
    public async Task TestProperty()
    {
        await TestInRegularAndScriptAsync(
            """
            interface IGoo { int Goo1 { get; } }
 
            class C : IGoo
            {
                int IGoo.[||]Goo1 { get { } }
            }
            """,
            """
            interface IGoo { int Goo1 { get; } }
 
            class C : IGoo
            {
                public int Goo1 { get { } }
            }
            """, index: SingleMember);
    }
 
    [Fact]
    public async Task TestEvent()
    {
        await TestInRegularAndScriptAsync(
            """
            interface IGoo { event Action E; }
 
            class C : IGoo
            {
                event Action IGoo.[||]E { add { } remove { } }
            }
            """,
            """
            interface IGoo { event Action E; }
 
            class C : IGoo
            {
                public event Action E { add { } remove { } }
            }
            """, index: SingleMember);
    }
 
    [Fact]
    public async Task TestNotOnImplicitMember()
    {
        await TestMissingAsync(
            """
            interface IGoo { void Goo1(); }
 
            class C : IGoo
            {
                public void [||]Goo1() { }
            }
            """);
    }
 
    [Fact]
    public async Task TestNotOnUnboundExplicitImpl()
    {
        await TestMissingAsync(
            """
            class C : IGoo
            {
                void IGoo.[||]Goo1() { }
            }
            """);
    }
 
    [Fact]
    public async Task TestCollision()
    {
        // Currently we don't do anything special here.  But we just test here to make sure we
        // don't blow up here.
        await TestInRegularAndScriptAsync(
            """
            interface IGoo { void Goo1(); }
 
            class C : IGoo
            {
                void IGoo.[||]Goo1() { }
 
                private void Goo1() { }
            }
            """,
            """
            interface IGoo { void Goo1(); }
 
            class C : IGoo
            {
                public void Goo1() { }
 
                private void Goo1() { }
            }
            """, index: SingleMember);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/48027")]
    public async Task TestSingleMemberAndContainingTypeHasNoInterface()
    {
        await TestMissingAsync(
            """
            using System;
            using System.Collections;
 
            class C
            {
                IEnumerator IEnumerable.[||]GetEnumerator()
                {
                    throw new NotImplementedException();
                }
            }
            """);
    }
 
    [Fact]
    public async Task TestPreserveReadOnly()
    {
        await TestInRegularAndScriptAsync(
            """
            interface IGoo { void Goo1(); }
 
            class C : IGoo
            {
                readonly void IGoo.[||]Goo1() { }
            }
            """,
            """
            interface IGoo { void Goo1(); }
 
            class C : IGoo
            {
                public readonly void Goo1() { }
            }
            """);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/70232")]
    public async Task TestMissingWhenAlreadyContainingImpl()
    {
        await TestMissingAsync(
            """
            interface I
            {
                event System.EventHandler Click;
            }
 
            class C : I
            {
                event System.EventHandler I.Click { add { } remove { } }
 
                event System.EventHandler [||]I.Click
 
            }
            """);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72024")]
    public async Task TestPropertyEvent()
    {
        await TestInRegularAndScriptAsync(
            """
            using System;
            
            interface IGoo { event Action E; }
            
            class C : IGoo
            {
                public event Action IGoo.[||]E { add { } remove { } };
            }
            """,
            """
            using System;
 
            interface IGoo { event Action E; }
 
            class C : IGoo
            {
                public event Action E { add { } remove { } };
            }
            """, index: SingleMember);
    }
}