< Summary

Information
Class: NexusLabs.Needlr.SignalR.Analyzers.HubRegistrationPluginConstructorAnalyzer
Assembly: NexusLabs.Needlr.SignalR.Analyzers
File(s): /home/runner/work/needlr/needlr/src/NexusLabs.Needlr.SignalR.Analyzers/HubRegistrationPluginConstructorAnalyzer.cs
Line coverage
95%
Covered lines: 19
Uncovered lines: 1
Coverable lines: 20
Total lines: 61
Line coverage: 95%
Branch coverage
87%
Covered branches: 7
Total branches: 8
Branch coverage: 87.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_SupportedDiagnostics()100%11100%
Initialize(...)100%11100%
AnalyzeClass(...)87.5%8892.85%
ImplementsHubRegistrationPlugin(...)100%11100%

File(s)

/home/runner/work/needlr/needlr/src/NexusLabs.Needlr.SignalR.Analyzers/HubRegistrationPluginConstructorAnalyzer.cs

#LineLine coverage
 1using System.Collections.Immutable;
 2using System.Linq;
 3
 4using Microsoft.CodeAnalysis;
 5using Microsoft.CodeAnalysis.CSharp;
 6using Microsoft.CodeAnalysis.CSharp.Syntax;
 7using Microsoft.CodeAnalysis.Diagnostics;
 8
 9using NexusLabs.Needlr.Roslyn.Shared;
 10
 11namespace NexusLabs.Needlr.SignalR.Analyzers;
 12
 13/// <summary>
 14/// Analyzer that flags an <c>IHubRegistrationPlugin</c> implementation that is eligible
 15/// for Needlr's generated-constructor generation. The SignalR hub-registration generator
 16/// requires parameterless activation and deliberately excludes such a type from
 17/// registration, so a plugin shaped this way is silently never registered unless flagged
 18/// here.
 19/// </summary>
 20[DiagnosticAnalyzer(LanguageNames.CSharp)]
 21public sealed class HubRegistrationPluginConstructorAnalyzer : DiagnosticAnalyzer
 22{
 23    private const string HubRegistrationPluginInterfaceName = "NexusLabs.Needlr.SignalR.IHubRegistrationPlugin";
 24
 25    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
 68326        ImmutableArray.Create(DiagnosticDescriptors.HubRegistrationPluginRequiresParameterlessActivation);
 27
 28    public override void Initialize(AnalysisContext context)
 29    {
 7430        context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
 7431        context.EnableConcurrentExecution();
 32
 7433        context.RegisterSyntaxNodeAction(AnalyzeClass, SyntaxKind.ClassDeclaration);
 7434    }
 35
 36    private static void AnalyzeClass(SyntaxNodeAnalysisContext context)
 37    {
 23438        var classDeclaration = (ClassDeclarationSyntax)context.Node;
 23439        if (context.SemanticModel.GetDeclaredSymbol(classDeclaration) is not INamedTypeSymbol typeSymbol)
 040            return;
 41
 23442        if (!GeneratedConstructorEligibility.IsCanonicalDeclaration(typeSymbol, classDeclaration))
 443            return;
 44
 23045        if (!ImplementsHubRegistrationPlugin(typeSymbol))
 19146            return;
 47
 3948        if (!GeneratedConstructorEligibility.IsEligibleForGeneratedConstructor(typeSymbol))
 1549            return;
 50
 2451        context.ReportDiagnostic(Diagnostic.Create(
 2452            DiagnosticDescriptors.HubRegistrationPluginRequiresParameterlessActivation,
 2453            classDeclaration.Identifier.GetLocation(),
 2454            typeSymbol.Name));
 2455    }
 56
 57    private static bool ImplementsHubRegistrationPlugin(INamedTypeSymbol typeSymbol)
 58    {
 27259        return typeSymbol.AllInterfaces.Any(i => i.ToDisplayString() == HubRegistrationPluginInterfaceName);
 60    }
 61}