File: FixAnalyzers\FixerWithFixAllAnalyzerTests.cs
Web Access
Project: src\src\RoslynAnalyzers\Microsoft.CodeAnalysis.Analyzers\UnitTests\Microsoft.CodeAnalysis.Analyzers.UnitTests.csproj (Microsoft.CodeAnalysis.Analyzers.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.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Analyzers.FixAnalyzers;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Testing;
using Test.Utilities;
using Xunit;
using VerifyCS = Test.Utilities.CSharpCodeFixVerifier<
    Microsoft.CodeAnalysis.Analyzers.FixAnalyzers.FixerWithFixAllAnalyzer,
    Microsoft.CodeAnalysis.Analyzers.MetaAnalyzers.Fixers.FixerWithFixAllFix>;
using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier<
    Microsoft.CodeAnalysis.Analyzers.FixAnalyzers.FixerWithFixAllAnalyzer,
    Microsoft.CodeAnalysis.Analyzers.MetaAnalyzers.Fixers.FixerWithFixAllFix>;
 
namespace Microsoft.CodeAnalysis.Analyzers.UnitTests.FixAnalyzers
{
    public class FixerWithFixAllAnalyzerTests
    {
        #region CSharp tests
 
        private const string CSharpCustomCodeActions = @"
public class MyCodeActionNoEquivalenceKey : CodeAction
{
    public override string Title
    {
        get
        {
            throw new NotImplementedException();
        }
    }
}
 
public class MyCodeActionWithEquivalenceKey : CodeAction
{
    public override string Title
    {
        get
        {
            throw new NotImplementedException();
        }
    }
 
    public override string EquivalenceKey
    {
        get
        {
            return ""DummyEquivalenceKey"";
        }
    }
}
 
public abstract class MyAbstractCodeActionWithEquivalenceKey : CodeAction
{
    public override string Title
    {
        get
        {
            throw new NotImplementedException();
        }
    }
 
    public override string EquivalenceKey
    {
        get
        {
            return ""DummyEquivalenceKey"";
        }
    }
}
 
public class MyDerivedCodeActionWithEquivalenceKey : MyAbstractCodeActionWithEquivalenceKey
{
}
";
        private async Task TestCSharpCoreAsync(string source, DiagnosticResult missingGetFixAllProviderOverrideDiagnostic,
            bool withCustomCodeActions = false, params DiagnosticResult[] expected)
        {
            var fixAllProviderString = @"public override FixAllProvider GetFixAllProvider()
    {
        return WellKnownFixAllProviders.BatchFixer;
    }";
 
            var sourceSuffix = @"
}";
 
            if (withCustomCodeActions)
            {
                sourceSuffix += CSharpCustomCodeActions;
            }
 
            // Verify expected diagnostics for fixer that supports FixAllProvider.
            await VerifyCS.VerifyAnalyzerAsync(source + fixAllProviderString + sourceSuffix, expected);
 
            // Verify RS1016 (OverrideGetFixAllProviderRule) diagnostic for fixer that does not support FixAllProvider.
            expected = new[] { missingGetFixAllProviderOverrideDiagnostic };
            await VerifyCS.VerifyAnalyzerAsync(source + sourceSuffix, expected);
        }
 
        [Fact]
        public async Task CSharp_CodeActionCreate_VerifyDiagnosticsAsync()
        {
            var source = @"
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeActions;
 
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(C1))]
class C1 : CodeFixProvider
{
    public override ImmutableArray<string> FixableDiagnosticIds
    {
        get
        {
            throw new NotImplementedException();
        }
    }
 
    public override Task RegisterCodeFixesAsync(CodeFixContext context)
    {
        // Regular cases.
        var codeAction1_1 = CodeAction.Create(""Title1_1"", _ => Task.FromResult(context.Document));
        var codeAction1_2 = CodeAction.Create(""Title1_2"", createChangedDocument: _ => Task.FromResult(context.Document));
        var codeAction1_3 = CodeAction.Create(createChangedDocument: _ => Task.FromResult(context.Document), title: ""Title1_3"");
 
        // Null argument for equivalenceKey.
        var codeAction2_1 = CodeAction.Create(""Title2_1"", _ => Task.FromResult(context.Document), null);
        var codeAction2_2 = CodeAction.Create(createChangedDocument: _ => Task.FromResult(context.Document), equivalenceKey: null, title: ""Title2_2"");
        var codeAction2_3 = CodeAction.Create(""Title2_3"", _ => Task.FromResult(context.Document), equivalenceKey: null);
 
        return null;
    }
";
 
            var expected = new[]
            {
                // Test0.cs(23,29): warning RS1010: Provide an explicit argument for optional parameter 'equivalenceKey', which is non-null and unique across all code actions created by this fixer.
                GetCSharpCreateCodeActionWithEquivalenceKeyExpectedDiagnostic(23, 29),
                // Test0.cs(24,29): warning RS1010: Provide an explicit argument for optional parameter 'equivalenceKey', which is non-null and unique across all code actions created by this fixer.
                GetCSharpCreateCodeActionWithEquivalenceKeyExpectedDiagnostic(24, 29),
                // Test0.cs(25,29): warning RS1010: Provide an explicit argument for optional parameter 'equivalenceKey', which is non-null and unique across all code actions created by this fixer.
                GetCSharpCreateCodeActionWithEquivalenceKeyExpectedDiagnostic(25, 29),
                // Test0.cs(28,29): warning RS1010: Provide an explicit argument for optional parameter 'equivalenceKey', which is non-null and unique across all code actions created by this fixer.
                GetCSharpCreateCodeActionWithEquivalenceKeyExpectedDiagnostic(28, 29),
                // Test0.cs(29,29): warning RS1010: Provide an explicit argument for optional parameter 'equivalenceKey', which is non-null and unique across all code actions created by this fixer.
                GetCSharpCreateCodeActionWithEquivalenceKeyExpectedDiagnostic(29, 29),
                // Test0.cs(30,29): warning RS1010: Provide an explicit argument for optional parameter 'equivalenceKey', which is non-null and unique across all code actions created by this fixer.
                GetCSharpCreateCodeActionWithEquivalenceKeyExpectedDiagnostic(30, 29)
            };
 
            // Test0.cs(10,7): warning RS1016: 'C1' registers one or more code fixes, but does not override the method 'CodeFixProvider.GetFixAllProvider'. Override this method and provide a non-null FixAllProvider for FixAll support, potentially 'WellKnownFixAllProviders.BatchFixer', or 'null' to explicitly disable FixAll support.
            var missingGetFixAllProviderOverrideDiagnostic = GetCSharpOverrideGetFixAllProviderExpectedDiagnostic(10, 7, "C1");
            await TestCSharpCoreAsync(source, missingGetFixAllProviderOverrideDiagnostic, expected: expected);
        }
 
        [Fact]
        public async Task CSharp_CodeActionCreate_NoDiagnosticsAsync()
        {
            var source = @"
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeActions;
 
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(C1))]
class C1 : CodeFixProvider
{
    public override ImmutableArray<string> FixableDiagnosticIds
    {
        get
        {
            throw new NotImplementedException();
        }
    }
 
    public override Task RegisterCodeFixesAsync(CodeFixContext context)
    {
        // Overload resolution failure cases.
        var codeAction1_1 = CodeAction.{|CS1501:Create|}(""Title1_1"");
        var codeAction1_2 = CodeAction.{|CS7036:Create|}(createChangedDocument: _ => Task.FromResult(context.Document), equivalenceKey: null);
 
        // Correct non-null arguments
        var equivalenceKey = ""equivalenceKey"";
        var codeAction2_1 = CodeAction.Create(""Title2_1"", _ => Task.FromResult(context.Document), equivalenceKey);
        var codeAction2_2 = CodeAction.Create(title: ""Title2_2"", createChangedDocument: _ => Task.FromResult(context.Document), equivalenceKey: equivalenceKey);
        var codeAction2_3 = CodeAction.Create(equivalenceKey: equivalenceKey, title: ""Title2_3"", createChangedDocument: _ => Task.FromResult(context.Document));
 
        // Conservative no diagnostic cases.
        string nullKey = null;
        var codeAction3_1 = CodeAction.Create(""Title3_1"", _ => Task.FromResult(context.Document), nullKey);
        var codeAction3_2 = CodeAction.Create(""Title3_1"", _ => Task.FromResult(context.Document), GetKey());
 
        context.RegisterCodeFix(codeAction1_1, context.Diagnostics);
        context.RegisterCodeFix(codeAction1_2, context.Diagnostics);
 
        context.RegisterCodeFix(codeAction2_1, context.Diagnostics);
        context.RegisterCodeFix(codeAction2_2, context.Diagnostics);
        context.RegisterCodeFix(codeAction2_3, context.Diagnostics);
 
        context.RegisterCodeFix(codeAction3_1, context.Diagnostics);
        context.RegisterCodeFix(codeAction3_2, context.Diagnostics);
 
        return null;
    }
 
    private string GetKey()
    {
        return null;
    }
";
 
            // Test0.cs(10,7): warning RS1016: 'C1' registers one or more code fixes, but does not override the method 'CodeFixProvider.GetFixAllProvider'. Override this method and provide a non-null FixAllProvider for FixAll support, potentially 'WellKnownFixAllProviders.BatchFixer', or 'null' to explicitly disable FixAll support.
            var missingGetFixAllProviderOverrideDiagnostic = GetCSharpOverrideGetFixAllProviderExpectedDiagnostic(10, 7, "C1");
 
            await TestCSharpCoreAsync(source, missingGetFixAllProviderOverrideDiagnostic);
        }
 
        [Fact]
        public async Task CSharp_CodeActionCreate_DiagnosticsOnExportedCodeFixProviderTypeAsync()
        {
            var source = @"
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeActions;
 
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(C2))]
class C2 : C1
{
}
 
abstract class C1 : CodeFixProvider
{
    public override ImmutableArray<string> FixableDiagnosticIds
    {
        get
        {
            throw new NotImplementedException();
        }
    }
 
    public override Task RegisterCodeFixesAsync(CodeFixContext context)
    {
        var codeAction1_1 = CodeAction.Create(""Title1_1"", _ => Task.FromResult(context.Document));
        return null;
    }
";
            var expected = new[]
            {
                // Test0.cs(26,29): warning RS1010: Provide an explicit argument for optional parameter 'equivalenceKey', which is non-null and unique across all code actions created by this fixer.
                GetCSharpCreateCodeActionWithEquivalenceKeyExpectedDiagnostic(26, 29)
            };
 
            // Test0.cs(10,16): warning RS1016: 'C1' registers one or more code fixes, but does not override the method 'CodeFixProvider.GetFixAllProvider'. Override this method and provide a non-null FixAllProvider for FixAll support, potentially 'WellKnownFixAllProviders.BatchFixer', or 'null' to explicitly disable FixAll support.
            var missingGetFixAllProviderOverrideDiagnostic = GetCSharpOverrideGetFixAllProviderExpectedDiagnostic(10, 7, "C2");
 
            await TestCSharpCoreAsync(source, missingGetFixAllProviderOverrideDiagnostic, expected: expected);
        }
 
        [Fact]
        public async Task CSharp_CustomCodeAction_VerifyDiagnosticsAsync()
        {
            var source = @"
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeActions;
 
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(C1))]
class C1 : CodeFixProvider
{
    public override ImmutableArray<string> FixableDiagnosticIds
    {
        get
        {
            throw new NotImplementedException();
        }
    }
 
    public override Task RegisterCodeFixesAsync(CodeFixContext context)
    {
        var codeAction = new MyCodeActionNoEquivalenceKey();
        return null;
    }
";
 
            var expected = new[]
            {
                // Test0.cs(22,26): warning RS1011: 'MyCodeActionNoEquivalenceKey' has the default value of 'null' for property 'EquivalenceKey'. Either override this property on 'MyCodeActionNoEquivalenceKey' to return a non-null and unique value across all code actions per-fixer or use such an existing code action.
                GetCSharpOverrideCodeActionEquivalenceKeyExpectedDiagnostic(22, 26, "MyCodeActionNoEquivalenceKey")
            };
 
            // Test0.cs(10,7): warning RS1016: 'C1' registers one or more code fixes, but does not override the method 'CodeFixProvider.GetFixAllProvider'. Override this method and provide a non-null FixAllProvider for FixAll support, potentially 'WellKnownFixAllProviders.BatchFixer', or 'null' to explicitly disable FixAll support.
            var missingGetFixAllProviderOverrideDiagnostic = GetCSharpOverrideGetFixAllProviderExpectedDiagnostic(10, 7, "C1");
 
            await TestCSharpCoreAsync(source, missingGetFixAllProviderOverrideDiagnostic, withCustomCodeActions: true, expected: expected);
        }
 
        [Fact]
        public async Task CSharp_CustomCodeAction_NoDiagnosticsAsync()
        {
            var source = @"
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeActions;
 
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(C1))]
class C1 : CodeFixProvider
{
    public override ImmutableArray<string> FixableDiagnosticIds
    {
        get
        {
            throw new NotImplementedException();
        }
    }
 
    public override Task RegisterCodeFixesAsync(CodeFixContext context)
    {
        CodeAction codeAction = new MyCodeActionWithEquivalenceKey();        
        context.RegisterCodeFix(codeAction, context.Diagnostics);
        
        codeAction = new MyDerivedCodeActionWithEquivalenceKey();        
        context.RegisterCodeFix(codeAction, context.Diagnostics);
        return null;
    }
 
    private string GetKey()
    {
        return null;
    }
";
            // Test0.cs(10,7): warning RS1016: 'C1' registers one or more code fixes, but does not override the method 'CodeFixProvider.GetFixAllProvider'. Override this method and provide a non-null FixAllProvider for FixAll support, potentially 'WellKnownFixAllProviders.BatchFixer', or 'null' to explicitly disable FixAll support.
            var missingGetFixAllProviderOverrideDiagnostic = GetCSharpOverrideGetFixAllProviderExpectedDiagnostic(10, 7, "C1");
 
            await TestCSharpCoreAsync(source, missingGetFixAllProviderOverrideDiagnostic, withCustomCodeActions: true);
        }
 
        [Fact, WorkItem(3475, "https://github.com/dotnet/roslyn-analyzers/issues/3475")]
        public async Task CSharp_CodeActionCreateNestedActions_NoDiagnosticsAsync()
        {
            await new VerifyCS.Test
            {
                ReferenceAssemblies = ReferenceAssemblies.Default.AddPackages(ImmutableArray.Create(new PackageIdentity("Microsoft.CodeAnalysis", "3.3.0"))),
                TestCode = @"
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeActions;
 
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(C1))]
class C1 : CodeFixProvider
{
    public override ImmutableArray<string> FixableDiagnosticIds
    {
        get
        {
            throw new NotImplementedException();
        }
    }
 
    public override FixAllProvider GetFixAllProvider()
    {
        throw new NotImplementedException();
    }
 
    public override Task RegisterCodeFixesAsync(CodeFixContext context)
    {
        var c1 = CodeAction.Create(
            ""Title1"",
            ImmutableArray.Create(
                CodeAction.Create(""Title1_1"", _ => Task.FromResult(context.Document), equivalenceKey: ""Title1_1""),
                {|#0:CodeAction.Create(""Title1_2"", _ => Task.FromResult(context.Document))|}
            ),
            false);
 
        var c2 = CodeAction.Create(
            ""Title2"",
            ImmutableArray.Create(
                CodeAction.Create(""Title2_1"", _ => Task.FromResult(context.Document), equivalenceKey: ""Title2_1""),
                {|#1:CodeAction.Create(""Title2_2"", _ => Task.FromResult(context.Document))|}
            ),
            true);
 
        return null;
    }
}",
                ExpectedDiagnostics =
                {
                    VerifyCS.Diagnostic(FixerWithFixAllAnalyzer.CreateCodeActionEquivalenceKeyRule).WithLocation(0).WithArguments("equivalenceKey"),
                    VerifyCS.Diagnostic(FixerWithFixAllAnalyzer.CreateCodeActionEquivalenceKeyRule).WithLocation(1).WithArguments("equivalenceKey"),
                }
            }.RunAsync();
        }
 
        #endregion
 
        #region VisualBasic tests
 
        private const string VisualBasicCustomCodeActions = @"
 
Public Class MyCodeActionNoEquivalenceKey
	Inherits CodeAction
	Public Overrides ReadOnly Property Title() As String
		Get
			Throw New NotImplementedException()
		End Get
	End Property
End Class
 
Public Class MyCodeActionWithEquivalenceKey
	Inherits CodeAction
	Public Overrides ReadOnly Property Title() As String
		Get
			Throw New NotImplementedException()
		End Get
	End Property
 
	Public Overrides ReadOnly Property EquivalenceKey() As String
		Get
			Return ""DummyEquivalenceKey""
		End Get
	End Property
End Class
 
Public MustInherit Class MyAbstractCodeActionWithEquivalenceKey
	Inherits CodeAction
	Public Overrides ReadOnly Property Title() As String
		Get
			Throw New NotImplementedException()
		End Get
	End Property
 
	Public Overrides ReadOnly Property EquivalenceKey() As String
		Get
			Return ""DummyEquivalenceKey""
		End Get
	End Property
End Class
 
Public Class MyDerivedCodeActionWithEquivalenceKey
	Inherits MyAbstractCodeActionWithEquivalenceKey
End Class
";
        private async Task TestBasicCoreAsync(string source, DiagnosticResult missingGetFixAllProviderOverrideDiagnostic,
            bool withCustomCodeActions = false, params DiagnosticResult[] expected)
        {
            var fixAllProviderString = @"Public Overrides Function GetFixAllProvider() As FixAllProvider
	Return WellKnownFixAllProviders.BatchFixer
End Function
";
 
            var sourceSuffix = @"
End Class
";
 
            if (withCustomCodeActions)
            {
                sourceSuffix += VisualBasicCustomCodeActions;
            }
 
            // Verify expected diagnostics for fixer that supports FixAllProvider.
            await VerifyVB.VerifyAnalyzerAsync(source + fixAllProviderString + sourceSuffix, expected);
 
            // Verify RS1016 (OverrideGetFixAllProviderRule) diagnostic for fixer that does not support FixAllProvider.
            expected = new[] { missingGetFixAllProviderOverrideDiagnostic };
            await VerifyVB.VerifyAnalyzerAsync(source + sourceSuffix, expected);
        }
 
        [Fact]
        public async Task VisualBasic_CodeActionCreate_VerifyDiagnosticsAsync()
        {
            var source = @"
Imports System
Imports System.Collections.Immutable
Imports System.Threading.Tasks
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.CodeActions
 
<ExportCodeFixProvider(LanguageNames.VisualBasic, Name:=NameOf(C1))>
Class C1
	Inherits CodeFixProvider
	Public Overrides ReadOnly Property FixableDiagnosticIds() As ImmutableArray(Of String)
		Get
			Throw New NotImplementedException()
		End Get
	End Property
 
	Public Overrides Function RegisterCodeFixesAsync(context As CodeFixContext) As Task
		' Regular cases.
		Dim codeAction1_1 = CodeAction.Create(""Title1_1"", Function(x) Task.FromResult(context.Document))
		Dim codeAction1_2 = CodeAction.Create(""Title1_2"", createChangedDocument := Function(x) Task.FromResult(context.Document))
		Dim codeAction1_3 = CodeAction.Create(createChangedDocument := Function(x) Task.FromResult(context.Document), title := ""Title1_3"")
 
		' Null argument for equivalenceKey.
		Dim codeAction2_1 = CodeAction.Create(""Title2_1"", Function(x) Task.FromResult(context.Document), Nothing)
		Dim codeAction2_2 = CodeAction.Create(createChangedDocument := Function(x) Task.FromResult(context.Document), equivalenceKey := Nothing, title := ""Title2_2"")
		Dim codeAction2_3 = CodeAction.Create(""Title2_3"", Function(x) Task.FromResult(context.Document), equivalenceKey := Nothing)
 
		Return Nothing
	End Function
";
 
            var expected = new[]
            {
                // Test0.vb(20,23): warning RS1010: Provide an explicit argument for optional parameter 'equivalenceKey', which is non-null and unique across all code actions created by this fixer.
                GetBasicCreateCodeActionWithEquivalenceKeyExpectedDiagnostic(20, 23),
                // Test0.vb(21,23): warning RS1010: Provide an explicit argument for optional parameter 'equivalenceKey', which is non-null and unique across all code actions created by this fixer.
                GetBasicCreateCodeActionWithEquivalenceKeyExpectedDiagnostic(21, 23),
                // Test0.vb(22,23): warning RS1010: Provide an explicit argument for optional parameter 'equivalenceKey', which is non-null and unique across all code actions created by this fixer.
                GetBasicCreateCodeActionWithEquivalenceKeyExpectedDiagnostic(22, 23),
                // Test0.vb(25,23): warning RS1010: Provide an explicit argument for optional parameter 'equivalenceKey', which is non-null and unique across all code actions created by this fixer.
                GetBasicCreateCodeActionWithEquivalenceKeyExpectedDiagnostic(25, 23),
                // Test0.vb(26,23): warning RS1010: Provide an explicit argument for optional parameter 'equivalenceKey', which is non-null and unique across all code actions created by this fixer.
                GetBasicCreateCodeActionWithEquivalenceKeyExpectedDiagnostic(26, 23),
                // Test0.vb(27,23): warning RS1010: Provide an explicit argument for optional parameter 'equivalenceKey', which is non-null and unique across all code actions created by this fixer.
                GetBasicCreateCodeActionWithEquivalenceKeyExpectedDiagnostic(27, 23)
            };
 
            // Test0.vb(10,7): warning RS1016: 'C1' registers one or more code fixes, but does not override the method 'CodeFixProvider.GetFixAllProvider'. Override this method and provide a non-null FixAllProvider for FixAll support, potentially 'WellKnownFixAllProviders.BatchFixer', or 'null' to explicitly disable FixAll support.
            var missingGetFixAllProviderOverrideDiagnostic = GetBasicOverrideGetFixAllProviderExpectedDiagnostic(10, 7, "C1");
 
            await TestBasicCoreAsync(source, missingGetFixAllProviderOverrideDiagnostic, expected: expected);
        }
 
        [Fact]
        public async Task VisualBasic_CodeActionCreate_NoDiagnosticsAsync()
        {
            var source = @"
Imports System
Imports System.Collections.Immutable
Imports System.Threading.Tasks
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.CodeActions
 
<ExportCodeFixProvider(LanguageNames.VisualBasic, Name:=NameOf(C1))>
Class C1
	Inherits CodeFixProvider
	Public Overrides ReadOnly Property FixableDiagnosticIds() As ImmutableArray(Of String)
		Get
			Throw New NotImplementedException()
		End Get
	End Property
 
	Public Overrides Function RegisterCodeFixesAsync(context As CodeFixContext) As Task
		' Overload resolution failure cases.
		Dim codeAction1_1 = CodeAction.{|BC30516:Create|}(""Title1_1"")
		Dim codeAction1_2 = CodeAction.{|BC30518:Create|}(createChangedDocument := Function(x) Task.FromResult(context.Document), equivalenceKey := Nothing)
 
		' Correct non-null arguments
		Dim equivalenceKey = ""equivalenceKey""
		Dim codeAction2_1 = CodeAction.Create(""Title2_1"", Function(x) Task.FromResult(context.Document), equivalenceKey)
		Dim codeAction2_2 = CodeAction.Create(title := ""Title2_2"", createChangedDocument := Function(x) Task.FromResult(context.Document), equivalenceKey := equivalenceKey)
		Dim codeAction2_3 = CodeAction.Create(equivalenceKey := equivalenceKey, title := ""Title2_3"", createChangedDocument := Function(x) Task.FromResult(context.Document))
 
		' Conservative no diagnostic cases.
		Dim nullKey As String = Nothing
		Dim codeAction3_1 = CodeAction.Create(""Title3_1"", Function(x) Task.FromResult(context.Document), nullKey)
		Dim codeAction3_2 = CodeAction.Create(""Title3_1"", Function(x) Task.FromResult(context.Document), GetKey())
 
		context.RegisterCodeFix(codeAction1_1, context.Diagnostics)
		context.RegisterCodeFix(codeAction1_2, context.Diagnostics)
 
		context.RegisterCodeFix(codeAction2_1, context.Diagnostics)
		context.RegisterCodeFix(codeAction2_2, context.Diagnostics)
		context.RegisterCodeFix(codeAction2_3, context.Diagnostics)
 
		context.RegisterCodeFix(codeAction3_1, context.Diagnostics)
		context.RegisterCodeFix(codeAction3_2, context.Diagnostics)
 
		Return Nothing
	End Function
 
	Private Function GetKey() As String
		Return Nothing
	End Function
";
            // Test0.vb(10,7): warning RS1016: 'C1' registers one or more code fixes, but does not override the method 'CodeFixProvider.GetFixAllProvider'. Override this method and provide a non-null FixAllProvider for FixAll support, potentially 'WellKnownFixAllProviders.BatchFixer', or 'null' to explicitly disable FixAll support.
            var missingGetFixAllProviderOverrideDiagnostic = GetBasicOverrideGetFixAllProviderExpectedDiagnostic(10, 7, "C1");
 
            await TestBasicCoreAsync(source, missingGetFixAllProviderOverrideDiagnostic);
        }
 
        [Fact]
        public async Task VisualBasic_CodeActionCreate_DiagnosticsOnExportedCodeFixProviderTypeAsync()
        {
            var source = @"
Imports System
Imports System.Collections.Immutable
Imports System.Threading.Tasks
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.CodeActions
 
<ExportCodeFixProvider(LanguageNames.VisualBasic, Name:=NameOf(C2))>
Class C2
    Inherits C1
End Class
 
MustInherit Class C1
	Inherits CodeFixProvider
	Public Overrides ReadOnly Property FixableDiagnosticIds() As ImmutableArray(Of String)
		Get
			Throw New NotImplementedException()
		End Get
	End Property
 
	Public Overrides Function RegisterCodeFixesAsync(context As CodeFixContext) As Task
		Dim codeAction1_1 = CodeAction.Create(""Title1_1"", Function(x) Task.FromResult(context.Document))
		Return Nothing
	End Function
 
	Private Function GetKey() As String
		Return Nothing
	End Function
";
            var expected = new[]
            {
                // Test0.vb(23,23): warning RS1010: Provide an explicit argument for optional parameter 'equivalenceKey', which is non-null and unique across all code actions created by this fixer.
                GetBasicCreateCodeActionWithEquivalenceKeyExpectedDiagnostic(23, 23)
            };
 
            // Test0.vb(10,7): warning RS1016: 'C1' registers one or more code fixes, but does not override the method 'CodeFixProvider.GetFixAllProvider'. Override this method and provide a non-null FixAllProvider for FixAll support, potentially 'WellKnownFixAllProviders.BatchFixer', or 'null' to explicitly disable FixAll support.
            var missingGetFixAllProviderOverrideDiagnostic = GetBasicOverrideGetFixAllProviderExpectedDiagnostic(10, 7, "C2");
 
            await TestBasicCoreAsync(source, missingGetFixAllProviderOverrideDiagnostic, expected: expected);
        }
 
        [Fact]
        public async Task VisualBasic_CustomCodeAction_VerifyDiagnosticsAsync()
        {
            var source = @"
Imports System
Imports System.Collections.Immutable
Imports System.Threading.Tasks
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.CodeActions
 
<ExportCodeFixProvider(LanguageNames.VisualBasic, Name:=NameOf(C1))>
Class C1
	Inherits CodeFixProvider
	Public Overrides ReadOnly Property FixableDiagnosticIds() As ImmutableArray(Of String)
		Get
			Throw New NotImplementedException()
		End Get
	End Property
 
	Public Overrides Function RegisterCodeFixesAsync(context As CodeFixContext) As Task
		Dim codeAction = New MyCodeActionNoEquivalenceKey()
		Return Nothing
	End Function
";
 
            var expected = new[]
            {
                // Test0.vb(19,20): warning RS1011: 'MyCodeActionNoEquivalenceKey' has the default value of 'null' for property 'EquivalenceKey'. Either override this property on 'MyCodeActionNoEquivalenceKey' to return a non-null and unique value across all code actions per-fixer or use such an existing code action.
                GetBasicOverrideCodeActionEquivalenceKeyExpectedDiagnostic(19, 20, "MyCodeActionNoEquivalenceKey")
            };
 
            // Test0.vb(10,7): warning RS1016: 'C1' registers one or more code fixes, but does not override the method 'CodeFixProvider.GetFixAllProvider'. Override this method and provide a non-null FixAllProvider for FixAll support, potentially 'WellKnownFixAllProviders.BatchFixer', or 'null' to explicitly disable FixAll support.
            var missingGetFixAllProviderOverrideDiagnostic = GetBasicOverrideGetFixAllProviderExpectedDiagnostic(10, 7, "C1");
 
            await TestBasicCoreAsync(source, missingGetFixAllProviderOverrideDiagnostic, withCustomCodeActions: true, expected: expected);
        }
 
        [Fact]
        public async Task VisualBasic_CustomCodeAction_NoDiagnosticsAsync()
        {
            var source = @"
Imports System
Imports System.Collections.Immutable
Imports System.Threading.Tasks
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.CodeActions
 
<ExportCodeFixProvider(LanguageNames.VisualBasic, Name:=NameOf(C1))>
Class C1
	Inherits CodeFixProvider
	Public Overrides ReadOnly Property FixableDiagnosticIds() As ImmutableArray(Of String)
		Get
			Throw New NotImplementedException()
		End Get
	End Property
 
	Public Overrides Function RegisterCodeFixesAsync(context As CodeFixContext) As Task
		Dim codeAction As CodeAction = New MyCodeActionWithEquivalenceKey()
		context.RegisterCodeFix(codeAction, context.Diagnostics)
 
        codeAction = New MyDerivedCodeActionWithEquivalenceKey()
		context.RegisterCodeFix(codeAction, context.Diagnostics)
 
		Return Nothing
	End Function
 
	Private Function GetKey() As String
		Return Nothing
	End Function
";
            // Test0.vb(10,7): warning RS1016: 'C1' registers one or more code fixes, but does not override the method 'CodeFixProvider.GetFixAllProvider'. Override this method and provide a non-null FixAllProvider for FixAll support, potentially 'WellKnownFixAllProviders.BatchFixer', or 'null' to explicitly disable FixAll support.
            var missingGetFixAllProviderOverrideDiagnostic = GetBasicOverrideGetFixAllProviderExpectedDiagnostic(10, 7, "C1");
 
            await TestBasicCoreAsync(source, missingGetFixAllProviderOverrideDiagnostic, withCustomCodeActions: true);
        }
 
        #endregion
 
        private static DiagnosticResult GetCSharpOverrideCodeActionEquivalenceKeyExpectedDiagnostic(int line, int column, string customCodeActionName)
        {
#pragma warning disable RS0030 // Do not use banned APIs
            return VerifyCS.Diagnostic(FixerWithFixAllAnalyzer.OverrideCodeActionEquivalenceKeyRule).WithLocation(line, column).WithArguments(customCodeActionName, nameof(CodeAction.EquivalenceKey));
#pragma warning restore RS0030 // Do not use banned APIs
        }
 
        private static DiagnosticResult GetBasicOverrideCodeActionEquivalenceKeyExpectedDiagnostic(int line, int column, string customCodeActionName)
        {
#pragma warning disable RS0030 // Do not use banned APIs
            return VerifyVB.Diagnostic(FixerWithFixAllAnalyzer.OverrideCodeActionEquivalenceKeyRule).WithLocation(line, column).WithArguments(customCodeActionName, nameof(CodeAction.EquivalenceKey));
#pragma warning restore RS0030 // Do not use banned APIs
        }
 
        private static DiagnosticResult GetCSharpCreateCodeActionWithEquivalenceKeyExpectedDiagnostic(int line, int column)
        {
#pragma warning disable RS0030 // Do not use banned APIs
            return VerifyCS.Diagnostic(FixerWithFixAllAnalyzer.CreateCodeActionEquivalenceKeyRule).WithLocation(line, column).WithArguments("equivalenceKey");
#pragma warning restore RS0030 // Do not use banned APIs
        }
 
        private static DiagnosticResult GetBasicCreateCodeActionWithEquivalenceKeyExpectedDiagnostic(int line, int column)
        {
#pragma warning disable RS0030 // Do not use banned APIs
            return VerifyVB.Diagnostic(FixerWithFixAllAnalyzer.CreateCodeActionEquivalenceKeyRule).WithLocation(line, column).WithArguments("equivalenceKey");
#pragma warning restore RS0030 // Do not use banned APIs
        }
 
        private static DiagnosticResult GetCSharpOverrideGetFixAllProviderExpectedDiagnostic(int line, int column, string codeFixProviderTypeName)
        {
#pragma warning disable RS0030 // Do not use banned APIs
            return VerifyCS.Diagnostic(FixerWithFixAllAnalyzer.OverrideGetFixAllProviderRule).WithLocation(line, column).WithArguments(codeFixProviderTypeName);
#pragma warning restore RS0030 // Do not use banned APIs
        }
 
        private static DiagnosticResult GetBasicOverrideGetFixAllProviderExpectedDiagnostic(int line, int column, string codeFixProviderTypeName)
        {
#pragma warning disable RS0030 // Do not use banned APIs
            return VerifyVB.Diagnostic(FixerWithFixAllAnalyzer.OverrideGetFixAllProviderRule).WithLocation(line, column).WithArguments(codeFixProviderTypeName);
#pragma warning restore RS0030 // Do not use banned APIs
        }
    }
}