Merge pull request #21 from AnnulusGames/add-diagnostic-descriptors

Add: diagnostic descriptors
This commit is contained in:
Annulus Games 2024-02-16 23:47:53 +09:00 committed by GitHub
commit e6eca44fc8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 74 additions and 6 deletions

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Alchemy.SourceGenerator
@ -25,6 +26,21 @@ namespace Alchemy.SourceGenerator
{
foreach (var typeSyntax in receiver.TargetTypes)
{
var typeSymbol = context.Compilation.GetSemanticModel(typeSyntax.SyntaxTree)
.GetDeclaredSymbol(typeSyntax);
if (!IsPartial(typeSyntax))
{
context.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.MustBePartial, typeSyntax.Identifier.GetLocation(), typeSymbol.Name));
continue;
}
if (IsNested(typeSyntax))
{
context.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.NestedNotAllow, typeSyntax.Identifier.GetLocation(), typeSymbol.Name));
continue;
}
var fieldSymbols = new List<IFieldSymbol>();
var fields = typeSyntax.Members
.Where(x => x is FieldDeclarationSyntax)
@ -35,22 +51,32 @@ namespace Alchemy.SourceGenerator
foreach (var variable in field.Declaration.Variables)
{
var fieldSymbol = model.GetDeclaredSymbol(variable) as IFieldSymbol;
var attribute = fieldSymbol.GetAttributes()
var alchemySerializeAttribute = fieldSymbol.GetAttributes()
.FirstOrDefault(x =>
x.AttributeClass.Name is "AlchemySerializeField"
or "AlchemySerializeFieldAttribute"
or "Alchemy.Serialization.AlchemySerializeField"
or "Alchemy.Serialization.AlchemySerializeFieldAttribute");
if (attribute != null)
var nonSerializedAttribute = fieldSymbol.GetAttributes()
.FirstOrDefault(x =>
x.AttributeClass.Name is "NonSerialized"
or "NonSerializedAttribute"
or "System.NonSerialized"
or "System.NonSerializedAttribute");
if (alchemySerializeAttribute != null)
{
if (nonSerializedAttribute == null)
{
context.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.ShouldBeNonSerialized, variable.Identifier.GetLocation(), fieldSymbol.Name));
}
fieldSymbols.Add(fieldSymbol);
}
}
}
var typeSymbol = context.Compilation.GetSemanticModel(typeSyntax.SyntaxTree)
.GetDeclaredSymbol(typeSyntax);
var sourceText = ProcessClass((INamedTypeSymbol)typeSymbol, fieldSymbols);
var fullType = typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)
.Replace("global::", "")
@ -159,6 +185,16 @@ catch (global::System.Exception ex)
";
}
static bool IsPartial(TypeDeclarationSyntax typeDeclaration)
{
return typeDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword));
}
static bool IsNested(TypeDeclarationSyntax typeDeclaration)
{
return typeDeclaration.Parent is TypeDeclarationSyntax;
}
sealed class SyntaxReceiver : ISyntaxReceiver
{
internal static ISyntaxReceiver Create()

View File

@ -1,4 +1,36 @@
using Microsoft.CodeAnalysis;
namespace Alchemy.SourceGenerator
{
public static class DiagnosticDescriptors
{
const string Category = "GenerateAlchemySerializationData";
public static readonly DiagnosticDescriptor MustBePartial = new(
id: "ALCHEMY001",
title: "AlchemySerialize class must be partial.",
messageFormat: "AlchemySerialize class '{0}' must be partial.",
category: Category,
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true
);
public static readonly DiagnosticDescriptor NestedNotAllow = new(
id: "ALCHEMY002",
title: "AlchemySerialize class must not be nested type.",
messageFormat: "The AlchemySerialize class '{0}' must be not nested type.",
category: Category,
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true
);
public static readonly DiagnosticDescriptor ShouldBeNonSerialized = new(
id: "ALCHEMY003",
title: "AlchemySerializeField should be NonSerialized to avoid duplicate serialization.",
messageFormat: "AlchemySerializeField '{0}' should be NonSerialized to avoid duplicate serialization.",
category: Category,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true
);
}
}