Gereksinimler ve Ön Hazırlık
Roslyn analizörü geliştirmek için sisteminizde belirli araçların yüklü olması gerekir. 2026 yılı standartlarına göre aşağıdaki kurulumları tamamlamış olmalısınız:
- Visual Studio 2022 veya üzeri (Community, Professional veya Enterprise).
- .NET 8.0 veya 9.0 SDK.
- "Visual Studio extension development" iş yükü (Workload).
- .NET Compiler Platform SDK (Visual Studio Installer üzerinden eklenebilir).
Kurulumları doğruladıktan sonra, "Analyzer with Code Fix" şablonunu kullanarak ilk projenizi oluşturabilirsiniz. Bu şablon, hem bir analiz kuralı hem de bu kuralın nasıl düzeltileceğine dair bir "Code Fix" (kod düzeltici) yapısını otomatik olarak sunar.
Roslyn Analizör Proje Yapısını Anlamak
Bir Roslyn analizörü projesi temel olarak iki ana bileşenden oluşur: DiagnosticAnalyzer (kuralı tanımlayan kısım) ve CodeFixProvider (hatayı otomatik düzelten kısım). Analizörler, kodun sözdizimi ağacı (Syntax Tree) üzerinde çalışır.
Aşağıdaki kod örneği, bir sınıfın isminin belirli bir standartta olup olmadığını kontrol eden temel bir analizör yapısını göstermektedir:
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class MyCustomAnalyzer : DiagnosticAnalyzer
{
public const string DiagnosticId = "MY001";
private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(
DiagnosticId, "Sınıf ismi hatası", "Sınıf ismi '{0}' standartlara uygun değil",
"Naming", DiagnosticSeverity.Warning, isEnabledByDefault: true);
public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeSymbol, SyntaxKind.ClassDeclaration);
}
}
Bu kodda, RegisterSyntaxNodeAction metodu ile sadece sınıf bildirimlerini (ClassDeclaration) dinliyoruz. Bu, analizörün performansını artırır çünkü tüm dosyayı değil, sadece ilgili düğümü inceler.
Adım Adım Özel Bir Kod Kuralı Yazma
Şimdi, kod içerisinde Console.WriteLine kullanımını yasaklayan ve yerine bir loglama kütüphanesi kullanılmasını zorunlu kılan bir kural yazalım. Bu, üretim ortamında (production) hata ayıklama kodlarının kalmasını engellemek için yaygın bir yöntemdir.
private static void AnalyzeSymbol(SyntaxNodeAnalysisContext context)
{
var invocation = (InvocationExpressionSyntax)context.Node;
var memberAccess = invocation.Expression as MemberAccessExpressionSyntax;
if (memberAccess?.Name.ToString() == "WriteLine" &&
memberAccess.Expression.ToString() == "Console")
{
var diagnostic = Diagnostic.Create(Rule, invocation.GetLocation());
context.ReportDiagnostic(diagnostic);
}
}
Bu kod, Console.WriteLine ifadesini yakaladığında bir uyarı oluşturur. context.ReportDiagnostic metodu, Visual Studio'nun "Error List" penceresinde bu hatayı göstermesini sağlar.
Dikkat: Analizörler derleme süresini doğrudan etkiler. Çok karmaşık ağaç taramaları (Syntax Tree traversal) yapmaktan kaçının ve her zaman
ConfigureGeneratedCodeAnalysisile oluşturulmuş kodları (otomatik üretilen dosyalar) kapsam dışı bırakın.
Kod Düzeltici (Code Fix) Entegrasyonu
Analizörünüz bir hata bulduğunda, geliştiriciye bu hatayı tek tuşla düzeltme imkanı sunmalısınız. CodeFixProvider sınıfı, RegisterCodeFixesAsync metodu ile bu işlemi gerçekleştirir.
public override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
var diagnostic = context.Diagnostics.First();
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
var node = root.FindNode(diagnostic.Location.SourceSpan);
context.RegisterCodeFix(
CodeAction.Create("Logger kullan", c => ReplaceWithLogger(context.Document, node, c), "FixId"),
diagnostic);
}
Burada ReplaceWithLogger metodu, hatalı kodu yeni kod yapısıyla (örneğin _logger.LogInformation(...)) değiştiren SyntaxRewriter mantığını tetikler.
Analizör Performansını Karşılaştırma
Kod standartlarını denetlemek için farklı yöntemler mevcuttur. Roslyn analizörleri, diğer yöntemlere göre daha derinlemesine analiz sağlar.
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| EditorConfig | Hızlı ve basit | Sadece stil odaklı |
| Roslyn Analizörü | Derinlemesine mantıksal analiz | Geliştirme süresi uzun |
| StyleCop | Hazır kurallar | Özelleştirme kısıtlı |
Test Odaklı Analizör Geliştirme
Analizörünüzün çalıştığından emin olmak için birim testleri (unit test) yazmak zorunludur. Roslyn SDK, Microsoft.CodeAnalysis.CSharp.Analyzer.Testing kütüphanesi ile kod parçacıklarını test etmenize olanak tanır.
[TestMethod]
public async Task TestConsoleWriteLineIsFlagged()
{
var code = @"using System; class Test { void M() { Console.WriteLine(); } }";
var expected = VerifyCS.Diagnostic("MY001").WithSpan(1, 38, 1, 55);
await VerifyCS.VerifyAnalyzerAsync(code, expected);
}
Bu test, kodunuzun analizör tarafından doğru bir şekilde yakalanıp yakalanmadığını doğrular. WithSpan metodu, hatanın kod içerisindeki tam konumunu belirtir.
Dağıtım ve Uygulama
Analizörünüzü tamamladıktan sonra bir NuGet paketi olarak paketleyebilirsiniz. Bu sayede, şirket içi projelerinizde veya açık kaynaklı projelerinizde .csproj dosyasına ekleyerek tüm ekibin aynı kod standartlarına uymasını sağlayabilirsiniz.
PrivateAssets="all" etiketi, bu analizörün projenin bağımlılıklarına dahil edilmemesini, sadece derleme zamanında çalışmasını sağlar.
Güvenlik Uyarısı: Analizör kodlarınızda dış kaynaklı (hardcoded) kimlik bilgileri veya hassas veriler bulundurmayın. Analizörler derleme sırasında çalışır ve projenin bir parçasıdır; bu nedenle güvenli kodlama pratiklerine (input validation, logging) burada da dikkat edilmelidir.
Sıkça Sorulan Sorular
Roslyn analizörleri çalışma zamanında (runtime) çalışır mı?
Hayır, Roslyn analizörleri sadece derleme zamanında (compile-time) çalışır. Çalışma zamanı hataları için birim testleri veya çalışma zamanı izleme araçları kullanılmalıdır.
Analizörüm çok yavaş çalışıyor, ne yapmalıyım?
Analizörünüzde Symbol aramaları yerine mümkün olduğunca Syntax düğümleri üzerinde işlem yapın. Ayrıca RegisterSyntaxNodeAction metodunda sadece ihtiyacınız olan SyntaxKind değerlerini filtreleyin.
Birden fazla kuralı tek bir pakette toplayabilir miyim?
Evet, bir NuGet paketi içerisinde onlarca farklı DiagnosticAnalyzer sınıfı tanımlayabilir ve bunları tek bir analizör kütüphanesi olarak dağıtabilirsiniz.
Analizörler CI/CD süreçlerinde nasıl kullanılır?
Analizörler derleme işleminin bir parçası olduğu için, Azure DevOps veya GitHub Actions üzerinde yapılan dotnet build komutu ile otomatik olarak tetiklenirler. Hatalar derlemeyi başarısız kılacak şekilde ayarlanabilir.
Kod düzeltici (Code Fix) yazmak zorunlu mu?
Zorunlu değildir, ancak geliştirici deneyimi (DX) açısından şiddetle önerilir. Sadece uyarı veren bir analizör, geliştiricinin hatayı düzeltmesini manuel bir süreç haline getirir.
İleri Seviye Analizör Teknikleri: SyntaxNode vs Symbol Analizi
Roslyn analizörleri geliştirirken, kodun sadece metinsel yapısına mı yoksa anlamsal (semantic) derinliğine mi odaklanacağınız, performans ve doğruluk açısından kritik bir karardır. Syntax tabanlı analizler hızlıdır ancak tip güvenliği veya kapsam (scope) hakkında bilgi sahibi değildir.
Semantic Model Kullanımı
Eğer bir değişkenin türünü kontrol etmeniz veya bir metodun hangi sınıfa ait olduğunu doğrulamanız gerekiyorsa, SemanticModel kullanmanız şarttır. Aşağıdaki örnek, bir değişkenin türünün tam adını kontrol eden bir analizör mantığını göstermektedir:
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeVariableDeclaration, SyntaxKind.VariableDeclaration);
}
private void AnalyzeVariableDeclaration(SyntaxNodeAnalysisContext context)
{
var variableDeclaration = (VariableDeclarationSyntax)context.Node;
var semanticModel = context.SemanticModel;
foreach (var variable in variableDeclaration.Variables)
{
var symbol = semanticModel.GetDeclaredSymbol(variable) as ILocalSymbol;
if (symbol != null && symbol.Type.Name == "var")
{
// Burada semantik analiz ile değişken türü doğrulanabilir
}
}
}
Analizörlerde Bellek Yönetimi ve Optimizasyon
Büyük kod tabanlarında çalışan analizörler, gereksiz nesne oluşturma nedeniyle IDE'nin yavaşlamasına neden olabilir. Roslyn analizörleri "stateless" (durumsuz) olmalıdır. Analizör sınıflarınızda sınıf seviyesinde değişken tutmaktan kaçınmalı ve her zaman AnalysisContext üzerinden sağlanan nesneleri kullanmalısınız.
Performans İpuçları
- Syntax Tree Walking: Gereksiz ağaç dolaşmalarından kaçının. Sadece ihtiyacınız olan düğüm türlerini (SyntaxKind) kaydedin.
- Caching: Eğer karmaşık hesaplamalar yapıyorsanız,
context.Optionsiçerisinde sağlanan önbellekleme mekanizmalarını kullanın. - Concurrent Execution:
context.EnableConcurrentExecution()metodunu kullanarak analizörün çok çekirdekli sistemlerden faydalanmasını sağlayın.
Aşağıdaki tablo, analizör geliştirme sürecinde sıkça karşılaşılan performans darboğazlarını ve çözüm yollarını özetlemektedir:
| Sorun | Çözüm |
|---|---|
| IDE Yavaşlaması | RegisterSyntaxNodeAction yerine daha spesifik filtreler kullanın. |
| Yüksek Bellek Kullanımı | Sınıf üyelerinde büyük koleksiyonlar tutmayın, yerel değişkenleri tercih edin. |
| Hatalı Teşhisler | Symbol karşılaştırmalarında SymbolEqualityComparer.Default kullanın. |
Analizör Hata Ayıklama (Debugging) Stratejileri
Analizörünüzü geliştirirken Visual Studio'nun "Experimental Instance" özelliğini kullanmak en etkili yöntemdir. Ancak bazen analizörün canlı kod üzerinde nasıl davrandığını görmek için Debugger.Launch() komutunu kullanabilirsiniz.
private void AnalyzeMethod(SyntaxNodeAnalysisContext context)
{
// Geliştirme aşamasında hata ayıklayıcıyı tetiklemek için:
// System.Diagnostics.Debugger.Launch();
var methodDeclaration = (MethodDeclarationSyntax)context.Node;
if (methodDeclaration.Identifier.ValueText.StartsWith("Test"))
{
// Analiz mantığı
}
}
Bu yöntemle, analizörünüzün hangi aşamada başarısız olduğunu veya hangi düğümde beklediğiniz veriyi alamadığınızı anlık olarak görebilirsiniz. Unutmayın, üretim (production) sürümüne geçmeden önce bu hata ayıklama satırlarını temizlemeyi ihmal etmeyin.
Sonuç
C# ile Roslyn analizörü geliştirmek, kod kalitesini standartlaştırmanın en profesyonel yoludur. Bu rehberde, bir analizörün nasıl tasarlanacağını, test edileceğini ve projelere entegre edileceğini öğrendiniz. Bir sonraki adım olarak, projenizdeki en sık yapılan hataları listeleyerek bunları engelleyen özel bir kural seti oluşturmayı deneyebilirsiniz. Temiz ve sürdürülebilir bir kod tabanı için Roslyn, .NET geliştiricisinin en güçlü silahıdır.


Yorumlar (0)
Yorum Yaz