using System.Collections.Generic; using System.Collections.Immutable; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; namespace Ariadne.Generator { /// /// Silences CS0164 ("label not referenced") on step labels in passages, and nowhere else. /// [DiagnosticAnalyzer(LanguageNames.CSharp)] public class StepLabelSuppressor : DiagnosticSuppressor { public static readonly SuppressionDescriptor UnreferencedStepLabel = new SuppressionDescriptor( "ARIS0001", "CS0164", "In a passage, a label names a step for saves; nothing jumps to it."); public override ImmutableArray SupportedSuppressions { get { return ImmutableArray.Create(UnreferencedStepLabel); } } public override void ReportSuppressions(SuppressionAnalysisContext context) { var scripts = new Dictionary(SymbolEqualityComparer.Default); foreach (Diagnostic diagnostic in context.ReportedDiagnostics) { SyntaxTree tree = diagnostic.Location.SourceTree; if (tree == null) { continue; } SyntaxNode node = tree.GetRoot(context.CancellationToken).FindNode(diagnostic.Location.SourceSpan); MethodDeclarationSyntax methodSyntax = node.FirstAncestorOrSelf(); if (methodSyntax == null) { continue; } var method = context.GetSemanticModel(tree).GetDeclaredSymbol(methodSyntax) as IMethodSymbol; if (method == null) { continue; } ScriptClass script; if (!scripts.TryGetValue(method.ContainingType, out script)) { script = ScriptClass.Create(method.ContainingType, context.Compilation); scripts[method.ContainingType] = script; } if (script != null && script.Passages.Contains(method)) { context.ReportSuppression(Suppression.Create(UnreferencedStepLabel, diagnostic)); } } } } }