Questions icon indicating copy to clipboard operation
Questions copied to clipboard

Need help in understanding Roslyn Analyzer

Open N-Vinodkumar opened this issue 2 years ago • 0 comments

Currently I am trying to implement some custom rules for goto statement using Roslyn, but I am not successfully achieving my goals and those rules are not getting activated.

Code in Analyzer.cs file using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading;

namespace GotoStatement { [DiagnosticAnalyzer(LanguageNames.CSharp)] public class GotoStatementAnalyzer : DiagnosticAnalyzer { public const string DiagnosticId = "AvoidGotoUsage";

    // You can change these strings in the Resources.resx file. If you do not want your analyzer to be localize-able, you can use regular strings for Title and MessageFormat.
    // See https://github.com/dotnet/roslyn/blob/main/docs/analyzers/Localizing%20Analyzers.md for more on localization
    private static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.AnalyzerTitle), Resources.ResourceManager, typeof(Resources));
    private static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(Resources.AnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources));
    private static readonly LocalizableString Description = new LocalizableResourceString(nameof(Resources.AnalyzerDescription), Resources.ResourceManager, typeof(Resources));
    private const string Category = "Naming";

    //private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: Description);
    private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(
    DiagnosticId,
    "Avoid using 'goto' keyword",
    "Avoid using 'goto' keyword in your code.",
    "CodeSmell",
    DiagnosticSeverity.Warning,
    isEnabledByDefault: true
);

    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }

    public override void Initialize(AnalysisContext context)
    {
        context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
        context.EnableConcurrentExecution();

        // TODO: Consider registering other actions that act on syntax instead of or in addition to symbols
        // See https://github.com/dotnet/roslyn/blob/main/docs/analyzers/Analyzer%20Actions%20Semantics.md for more information
        //context.RegisterSymbolAction(AnalyzeSymbol, SymbolKind.NamedType);
        context.RegisterSyntaxNodeAction(AnalyzeGotoKeyword, SyntaxKind.GotoKeyword);
    }

    private void AnalyzeGotoKeyword(SyntaxNodeAnalysisContext context)
    {
        var gotoStatement = (GotoStatementSyntax)context.Node;
        var gotoKeyword = gotoStatement.GotoKeyword;

        // Create a diagnostic for the 'goto' keyword
        var diagnostic = Diagnostic.Create(Rule, gotoKeyword.GetLocation());

        // Report the diagnostic
        context.ReportDiagnostic(diagnostic);
    }
}

}

code in CodeFixProvider.cs file using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Rename; using Microsoft.CodeAnalysis.Text; using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Composition; using System.Linq; using System.Threading; using System.Threading.Tasks;

namespace GotoStatement { [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(GotoKeywordCodeFixProvider)), Shared] public class GotoKeywordCodeFixProvider : CodeFixProvider { public sealed override ImmutableArray FixableDiagnosticIds { get { return ImmutableArray.Create(GotoStatementAnalyzer.DiagnosticId); } }

    public sealed override FixAllProvider GetFixAllProvider()
    {
        // See https://github.com/dotnet/roslyn/blob/main/docs/analyzers/FixAllProvider.md for more information on Fix All Providers
        return WellKnownFixAllProviders.BatchFixer;
    }

    public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
    {
        var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
        var diagnostic = context.Diagnostics.First();
        var diagnosticSpan = diagnostic.Location.SourceSpan;

        // Find the 'goto' keyword syntax node
        var gotoKeyword = root.FindToken(diagnosticSpan.Start);

        // Register a code fix to replace 'goto' with a different statement (e.g., 'return')
        context.RegisterCodeFix(
            CodeAction.Create(
                "Replace 'goto' with 'return'",
                cancellationToken => ReplaceGotoWithReturn(context.Document, gotoKeyword, cancellationToken),
                nameof(GotoKeywordCodeFixProvider)),
            diagnostic);
    }

    private async Task<Document> ReplaceGotoWithReturn(Document document, SyntaxToken gotoKeyword, CancellationToken cancellationToken)
    {
        // Replace 'goto' with 'return'
        var newRoot = (await document.GetSyntaxRootAsync(cancellationToken))
            .ReplaceToken(gotoKeyword, SyntaxFactory.Token(SyntaxKind.ReturnKeyword));

        return document.WithSyntaxRoot(newRoot);
    }
}

}

Can someone please guide me to identify the problem I am facing?

N-Vinodkumar avatar Oct 09 '23 06:10 N-Vinodkumar