mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2025-04-28 08:19:47 +00:00
Added an empty string analyzer & code fix
This commit is contained in:
parent
5a8b5154c9
commit
4121755c4c
@ -9,4 +9,5 @@
|
||||
MWAIS0003 | Naming | Error | UnderscorePrefixAnalyzer
|
||||
MWAIS0004 | Usage | Error | RandomInstantiationAnalyzer
|
||||
MWAIS0005 | Usage | Error | ThisUsageAnalyzer
|
||||
MWAIS0006 | Style | Error | SwitchExpressionMethodAnalyzer
|
||||
MWAIS0006 | Style | Error | SwitchExpressionMethodAnalyzer
|
||||
MWAIS0007 | Usage | Error | EmptyStringAnalyzer
|
@ -8,4 +8,5 @@ public static class Identifier
|
||||
public const string RANDOM_INSTANTIATION_ANALYZER = $"{Tools.ID_PREFIX}0004";
|
||||
public const string THIS_USAGE_ANALYZER = $"{Tools.ID_PREFIX}0005";
|
||||
public const string SWITCH_EXPRESSION_METHOD_ANALYZER = $"{Tools.ID_PREFIX}0006";
|
||||
public const string EMPTY_STRING_ANALYZER = $"{Tools.ID_PREFIX}0007";
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
using System.Collections.Immutable;
|
||||
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
|
||||
namespace SourceCodeRules.UsageAnalyzers;
|
||||
|
||||
#pragma warning disable RS1038
|
||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||
#pragma warning restore RS1038
|
||||
public sealed class EmptyStringAnalyzer : DiagnosticAnalyzer
|
||||
{
|
||||
private const string DIAGNOSTIC_ID = Identifier.EMPTY_STRING_ANALYZER;
|
||||
|
||||
private static readonly string TITLE = """
|
||||
Use string.Empty instead of ""
|
||||
""";
|
||||
|
||||
private static readonly string MESSAGE_FORMAT = """
|
||||
Use string.Empty instead of ""
|
||||
""";
|
||||
|
||||
private static readonly string DESCRIPTION = """Empty string literals ("") should be replaced with string.Empty for better code consistency and readability except in const contexts.""";
|
||||
|
||||
private const string CATEGORY = "Usage";
|
||||
|
||||
private static readonly DiagnosticDescriptor RULE = new(DIAGNOSTIC_ID, TITLE, MESSAGE_FORMAT, CATEGORY, DiagnosticSeverity.Error, isEnabledByDefault: true, description: DESCRIPTION);
|
||||
|
||||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [RULE];
|
||||
|
||||
public override void Initialize(AnalysisContext context)
|
||||
{
|
||||
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
|
||||
context.EnableConcurrentExecution();
|
||||
context.RegisterSyntaxNodeAction(AnalyzeEmptyStringLiteral, SyntaxKind.StringLiteralExpression);
|
||||
}
|
||||
|
||||
private static void AnalyzeEmptyStringLiteral(SyntaxNodeAnalysisContext context)
|
||||
{
|
||||
var stringLiteral = (LiteralExpressionSyntax)context.Node;
|
||||
if (stringLiteral.Token.ValueText != string.Empty)
|
||||
return;
|
||||
|
||||
if (IsInConstContext(stringLiteral))
|
||||
return;
|
||||
|
||||
var diagnostic = Diagnostic.Create(RULE, stringLiteral.GetLocation());
|
||||
context.ReportDiagnostic(diagnostic);
|
||||
}
|
||||
|
||||
private static bool IsInConstContext(LiteralExpressionSyntax stringLiteral)
|
||||
{
|
||||
var variableDeclarator = stringLiteral.FirstAncestorOrSelf<VariableDeclaratorSyntax>();
|
||||
if (variableDeclarator is null)
|
||||
return false;
|
||||
|
||||
var declaration = variableDeclarator.Parent?.Parent;
|
||||
return declaration switch
|
||||
{
|
||||
FieldDeclarationSyntax fieldDeclaration => fieldDeclaration.Modifiers.Any(SyntaxKind.ConstKeyword),
|
||||
LocalDeclarationStatementSyntax localDeclaration => localDeclaration.Modifiers.Any(SyntaxKind.ConstKeyword),
|
||||
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Composition;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CodeActions;
|
||||
using Microsoft.CodeAnalysis.CodeFixes;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Formatting;
|
||||
|
||||
namespace SourceCodeRules.UsageCodeFixes;
|
||||
|
||||
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(EmptyStringCodeFixProvider)), Shared]
|
||||
public class EmptyStringCodeFixProvider : CodeFixProvider
|
||||
{
|
||||
private const string TITLE = """Replace "" with string.Empty""";
|
||||
|
||||
public sealed override ImmutableArray<string> FixableDiagnosticIds => [Identifier.EMPTY_STRING_ANALYZER];
|
||||
|
||||
public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;
|
||||
|
||||
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
|
||||
{
|
||||
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
|
||||
if(root is null)
|
||||
return;
|
||||
|
||||
var diagnostic = context.Diagnostics.First();
|
||||
var diagnosticSpan = diagnostic.Location.SourceSpan;
|
||||
|
||||
if (root.FindToken(diagnosticSpan.Start).Parent is not LiteralExpressionSyntax emptyStringLiteral)
|
||||
return;
|
||||
|
||||
context.RegisterCodeFix(
|
||||
CodeAction.Create(
|
||||
title: TITLE,
|
||||
createChangedDocument: c => ReplaceWithStringEmpty(context.Document, emptyStringLiteral, c),
|
||||
equivalenceKey: TITLE),
|
||||
diagnostic);
|
||||
}
|
||||
private static async Task<Document> ReplaceWithStringEmpty(Document document, LiteralExpressionSyntax emptyStringLiteral, CancellationToken cancellationToken)
|
||||
{
|
||||
var stringEmptyExpression = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("string"), SyntaxFactory.IdentifierName("Empty")).WithAdditionalAnnotations(Formatter.Annotation);
|
||||
var root = await document.GetSyntaxRootAsync(cancellationToken);
|
||||
if (root is null)
|
||||
return document;
|
||||
|
||||
var newRoot = root.ReplaceNode(emptyStringLiteral, stringEmptyExpression);
|
||||
return document.WithSyntaxRoot(newRoot);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user