mirror of
				https://github.com/MindWorkAI/AI-Studio.git
				synced 2025-11-04 03:40:21 +00:00 
			
		
		
		
	Added an analyzer for static and const field naming
This commit is contained in:
		
							parent
							
								
									4aba041c40
								
							
						
					
					
						commit
						a33347ddb7
					
				@ -4,4 +4,5 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 Rule ID   | Category | Severity | Notes                  
 | 
					 Rule ID   | Category | Severity | Notes                  
 | 
				
			||||||
-----------|----------|----------|------------------------
 | 
					-----------|----------|----------|------------------------
 | 
				
			||||||
 MWAIS0001 | Usage    | Error    | ProviderAccessAnalyzer 
 | 
					 MWAIS0001 | Usage    | Error    | ProviderAccessAnalyzer
 | 
				
			||||||
 | 
					 MWAIS0002 | Naming | Error | ConstStaticAnalyzer
 | 
				
			||||||
@ -0,0 +1,67 @@
 | 
				
			|||||||
 | 
					using System.Collections.Immutable;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis;
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis.CSharp;
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis.CSharp.Syntax;
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis.Diagnostics;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace SourceCodeRules.NamingAnalyzers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma warning disable RS1038
 | 
				
			||||||
 | 
					[DiagnosticAnalyzer(LanguageNames.CSharp)]
 | 
				
			||||||
 | 
					#pragma warning restore RS1038
 | 
				
			||||||
 | 
					public sealed class ConstStaticAnalyzer : DiagnosticAnalyzer
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private const string DIAGNOSTIC_ID = $"{Tools.ID_PREFIX}0002";
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static readonly string TITLE = "Constant and static fields must be in UPPER_CASE";
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static readonly string MESSAGE_FORMAT = "Field '{0}' must be in UPPER_CASE";
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static readonly string DESCRIPTION = "All constant and static fields should be named using UPPER_CASE.";
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private const string CATEGORY = "Naming";
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    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(this.AnalyzeField, SyntaxKind.FieldDeclaration);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private void AnalyzeField(SyntaxNodeAnalysisContext context)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var fieldDeclaration = (FieldDeclarationSyntax)context.Node;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Prüfen ob das Feld static oder const ist
 | 
				
			||||||
 | 
					        if (!fieldDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword) || m.IsKind(SyntaxKind.ConstKeyword)))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        foreach (var variable in fieldDeclaration.Declaration.Variables)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var fieldName = variable.Identifier.Text;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // Prüfen ob der Name bereits in UPPER_CASE ist
 | 
				
			||||||
 | 
					            if (!IsUpperCase(fieldName))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var diagnostic = Diagnostic.Create(
 | 
				
			||||||
 | 
					                    RULE,
 | 
				
			||||||
 | 
					                    variable.Identifier.GetLocation(),
 | 
				
			||||||
 | 
					                    fieldName);
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                context.ReportDiagnostic(diagnostic);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static bool IsUpperCase(string name)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Erlaubt: Nur Großbuchstaben, Zahlen und Unterstriche
 | 
				
			||||||
 | 
					        return name.All(c => char.IsUpper(c) || char.IsDigit(c) || c == '_');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,67 @@
 | 
				
			|||||||
 | 
					using System.Collections.Immutable;
 | 
				
			||||||
 | 
					using System.Composition;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis;
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis.CodeActions;
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis.CodeFixes;
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis.CSharp.Syntax;
 | 
				
			||||||
 | 
					using Microsoft.CodeAnalysis.Rename;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace SourceCodeRules.NamingCodeFixes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(ConstStaticCodeFixProvider)), Shared]
 | 
				
			||||||
 | 
					public sealed class ConstStaticCodeFixProvider : CodeFixProvider
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public override ImmutableArray<string> FixableDiagnosticIds => [$"{Tools.ID_PREFIX}0002"];
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public override async Task RegisterCodeFixesAsync(CodeFixContext context)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
 | 
				
			||||||
 | 
					        var diagnostic = context.Diagnostics.First();
 | 
				
			||||||
 | 
					        var diagnosticSpan = diagnostic.Location.SourceSpan;
 | 
				
			||||||
 | 
					        var declaration = root?.FindToken(diagnosticSpan.Start).Parent?.AncestorsAndSelf().OfType<VariableDeclaratorSyntax>().First();
 | 
				
			||||||
 | 
					        if (declaration is null)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        context.RegisterCodeFix(CodeAction.Create(title: "Convert to UPPER_CASE", createChangedDocument: c => this.ConvertToUpperCaseAsync(context.Document, declaration, c), equivalenceKey: nameof(ConstStaticCodeFixProvider)), diagnostic);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private async Task<Document> ConvertToUpperCaseAsync(Document document, VariableDeclaratorSyntax declarator, CancellationToken cancellationToken)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var oldName = declarator.Identifier.Text;
 | 
				
			||||||
 | 
					        var newName = ConvertToUpperCase(oldName);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        var semanticModel = await document.GetSemanticModelAsync(cancellationToken);
 | 
				
			||||||
 | 
					        var symbol = semanticModel?.GetDeclaredSymbol(declarator, cancellationToken);
 | 
				
			||||||
 | 
					        if (symbol is null)
 | 
				
			||||||
 | 
					            return document;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var solution = document.Project.Solution;
 | 
				
			||||||
 | 
					        var newSolution = await Renamer.RenameSymbolAsync(solution, symbol, new SymbolRenameOptions(), newName, cancellationToken);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return newSolution.GetDocument(document.Id) ?? document;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static string ConvertToUpperCase(string name)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var result = new StringBuilder();
 | 
				
			||||||
 | 
					        for (var i = 0; i < name.Length; i++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var current = name[i];
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // Insert an underscore before each uppercase letter, except the first one:
 | 
				
			||||||
 | 
					            if (i > 0 && char.IsUpper(current) && !char.IsUpper(name[i - 1]))
 | 
				
			||||||
 | 
					                result.Append('_');
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            result.Append(char.ToUpper(current));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return result.ToString();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user