Need help in understanding Roslyn Analyzer
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
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?