File: Diagnostics\FixAllProvider\BatchFixerTests.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.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
using Xunit.Abstractions;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.SimplifyTypeNames;
 
public partial class BatchFixerTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
    public BatchFixerTests(ITestOutputHelper logger)
         : base(logger)
    {
    }
 
    internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
        => (new QualifyWithThisAnalyzer(), new QualifyWithThisFixer());
 
    [DiagnosticAnalyzer(LanguageNames.CSharp)]
    private class QualifyWithThisAnalyzer : DiagnosticAnalyzer
    {
        public static readonly DiagnosticDescriptor Descriptor = DescriptorFactory.CreateSimpleDescriptor("QualifyWithThis");
 
        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get
            {
                return ImmutableArray.Create(Descriptor);
            }
        }
 
        public override void Initialize(AnalysisContext context)
            => context.RegisterSyntaxNodeAction<SyntaxKind>(AnalyzeNode, SyntaxKind.IdentifierName);
 
        private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
        {
            if (context.Node is SimpleNameSyntax node)
            {
                var symbol = context.SemanticModel.GetSymbolInfo(node).Symbol;
                if (symbol != null && symbol.Kind == SymbolKind.Field)
                {
                    var diagnostic = Diagnostic.Create(Descriptor, node.GetLocation());
                    context.ReportDiagnostic(diagnostic);
                }
            }
        }
    }
 
    private class QualifyWithThisFixer : CodeFixProvider
    {
        public override ImmutableArray<string> FixableDiagnosticIds
        {
            get
            {
                return ImmutableArray.Create(QualifyWithThisAnalyzer.Descriptor.Id);
            }
        }
 
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
            if (root.FindNode(context.Span, getInnermostNodeForTie: true) is SimpleNameSyntax node)
            {
                var leadingTrivia = node.GetLeadingTrivia();
                var newNode = SyntaxFactory.MemberAccessExpression(
                    SyntaxKind.SimpleMemberAccessExpression,
                    SyntaxFactory.ThisExpression(),
                    node.WithoutLeadingTrivia())
                    .WithLeadingTrivia(leadingTrivia);
 
                var newRoot = root.ReplaceNode(node, newNode);
                var newDocument = context.Document.WithSyntaxRoot(newRoot);
 
                // Disable RS0005 as this is test code and we don't need telemetry for created code action.
#pragma warning disable RS0005 // Do not use generic CodeAction.Create to create CodeAction
                var fix = CodeAction.Create("QualifyWithThisFix", _ => Task.FromResult(newDocument));
#pragma warning restore RS0005 // Do not use generic CodeAction.Create to create CodeAction
 
                context.RegisterCodeFix(fix, context.Diagnostics);
            }
        }
 
        public override FixAllProvider GetFixAllProvider()
            => WellKnownFixAllProviders.BatchFixer;
    }
 
    #region "Fix all occurrences tests"
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/320")]
    [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
    public async Task TestFixAllInDocument_QualifyWithThis()
    {
        var input = """
            <Workspace>
                <Project Language="C#" AssemblyName="Assembly1" CommonReferences="true">
                    <Document>
            class C
            {
                int Sign;
                void F()
                {
                    string x = @"namespace Namespace
                {
                    class Type
                    {
                        void Goo()
                        {
                            int x = 1 " + {|FixAllInDocument:Sign|} + @" " + Sign + @"3;
                        }
                    }
                }
            ";
                }
            }
                    </Document>
                </Project>
            </Workspace>
            """;
 
        var expected = """
            <Workspace>
                <Project Language="C#" AssemblyName="Assembly1" CommonReferences="true">
                    <Document>
            class C
            {
                int Sign;
                void F()
                {
                    string x = @"namespace Namespace
                {
                    class Type
                    {
                        void Goo()
                        {
                            int x = 1 " + this.Sign + @" " + this.Sign + @"3;
                        }
                    }
                }
            ";
                }
            }
                    </Document>
                </Project>
            </Workspace>
            """;
 
        await TestInRegularAndScriptAsync(input, expected);
    }
 
    #endregion
}