< Summary

Information
Class: Hertzole.ScriptableValues.Generator.TypeNotSupportedForCallbackAttributeAnalyzer
Assembly: Hertzole.ScriptableValues.Generator
File(s): Generator/Hertzole.ScriptableValues.Generator/Analyzers/TypeNotSupportedForCallbackAttributeAnalyzer.cs
Tag: 52_28197466029
Line coverage
0%
Covered lines: 0
Uncovered lines: 45
Coverable lines: 45
Total lines: 119
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 29
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.cctor()100%110%
Initialize(...)100%110%
Action(...)0%22220%
GetCorrectAttributeName(...)0%770%

File(s)

Generator/Hertzole.ScriptableValues.Generator/Analyzers/TypeNotSupportedForCallbackAttributeAnalyzer.cs

#LineLine coverage
 1using System.Collections.Immutable;
 2using Microsoft.CodeAnalysis;
 3using Microsoft.CodeAnalysis.CSharp;
 4using Microsoft.CodeAnalysis.CSharp.Syntax;
 5using Microsoft.CodeAnalysis.Diagnostics;
 6
 7namespace Hertzole.ScriptableValues.Generator;
 8
 9[DiagnosticAnalyzer(LanguageNames.CSharp)]
 10public sealed class TypeNotSupportedForCallbackAttributeAnalyzer : DiagnosticAnalyzer
 11{
 012    private static readonly ImmutableArray<DiagnosticDescriptor> supportedDiagnostics =
 013        ImmutableArray.Create(DiagnosticRules.TypeNotSupportedForCallbackAttribute);
 14
 015    private static readonly SyntaxKind[] supportedSyntaxKinds = [SyntaxKind.Attribute];
 16
 17    /// <inheritdoc />
 18    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
 19    {
 020        get { return supportedDiagnostics; }
 21    }
 22
 23    /// <inheritdoc />
 24    public override void Initialize(AnalysisContext context)
 25    {
 026        context.EnableConcurrentExecution();
 027        context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
 28
 029        context.RegisterSyntaxNodeAction(Action, supportedSyntaxKinds);
 030    }
 31
 32    private static void Action(SyntaxNodeAnalysisContext context)
 33    {
 034        if (context.Node is not AttributeSyntax attributeSyntax)
 35        {
 036            return;
 37        }
 38
 039        context.CancellationToken.ThrowIfCancellationRequested();
 40
 041        INamedTypeSymbol? attributeSymbol = attributeSyntax.GetAttributeSymbol(context.SemanticModel, context.Cancellati
 042        if (attributeSymbol == null)
 43        {
 044            return;
 45        }
 46
 047        if (!attributeSymbol.TryGetCallbackAttribute(out CallbackType callbackType))
 48        {
 49            // This is not a callback attribute, so we don't need to do anything.
 050            return;
 51        }
 52
 53        // Get member declaration
 054        MemberDeclarationSyntax? memberDeclaration = attributeSyntax.FirstAncestorOrSelf<MemberDeclarationSyntax>();
 055        if (memberDeclaration == null)
 56        {
 057            return;
 58        }
 59
 60        // Get wrapper
 061        if (!memberDeclaration.TryGetFieldOrPropertyWrapper(context.SemanticModel, out ImmutableArray<FieldOrPropertyWra
 062            wrappers.IsDefaultOrEmpty)
 63        {
 064            return;
 65        }
 66
 067        TypeDeclarationSyntax? containingTypeDeclaration = memberDeclaration.FirstAncestorOrSelf<TypeDeclarationSyntax>(
 068        if (containingTypeDeclaration == null)
 69        {
 070            return;
 71        }
 72
 73        // Make sure the containing type has the marker attribute
 074        if (context.SemanticModel.GetDeclaredSymbol(containingTypeDeclaration) is not INamedTypeSymbol containingTypeSym
 075            !containingTypeSymbol.HasAttribute(Types.GLOBAL_MARKER_ATTRIBUTE))
 76        {
 077            return;
 78        }
 79
 080        FieldOrPropertyWrapper wrapper = wrappers.ItemRef(0);
 081        if (!ScriptableValueHelper.TryGetScriptableType(context.SemanticModel, (INamedTypeSymbol) wrapper.Type, out Scri
 82        {
 083            return;
 84        }
 85
 86        // The correct callback attribute was used.
 087        if (ScriptableValueHelper.IsSupportedType(in callbackType, in wrapperType))
 88        {
 089            return;
 90        }
 91
 092        string correctAttributeName = GetCorrectAttributeName(wrapperType);
 93
 094        ImmutableDictionary<string, string?>.Builder propertiesBuilder = ImmutableDictionary.CreateBuilder<string, strin
 095        propertiesBuilder.Add("correctAttributeName", correctAttributeName);
 96
 097        context.ReportDiagnostic(Diagnostic.Create(DiagnosticRules.TypeNotSupportedForCallbackAttribute, attributeSyntax
 098            propertiesBuilder.ToImmutable(), attributeSymbol.Name, correctAttributeName));
 099    }
 100
 101    private static string GetCorrectAttributeName(in ScriptableType scriptableType)
 102    {
 0103        switch (scriptableType)
 104        {
 105            case ScriptableType.Event:
 106            case ScriptableType.GenericEvent:
 0107                return "GenerateEventCallbackAttribute";
 108            case ScriptableType.Value:
 0109                return "GenerateValueCallbackAttribute";
 110            case ScriptableType.Pool:
 0111                return "GeneratePoolCallbackAttribute";
 112            case ScriptableType.List:
 113            case ScriptableType.Dictionary:
 0114                return "GenerateCollectionCallbackAttribute";
 115            default:
 0116                return "UNKNOWN";
 117        }
 118    }
 119}