Files
Polonium.Generators/AssetProcessGenerator.cs
2025-02-06 01:33:12 +00:00

81 lines
2.7 KiB
C#

using System.Collections.Generic;
using System.IO;
using Microsoft.CodeAnalysis;
namespace Polonium.Generators;
public abstract class AssetProcessGenerator : ISourceGenerator
{
public void Initialize(GeneratorInitializationContext context)
{
context.RegisterForSyntaxNotifications(() => new ClassSyntaxReceiver());
}
public abstract void Execute(GeneratorExecutionContext context);
protected IEnumerable<AssetInfo> GetAssetsOfType(GeneratorExecutionContext context, INamedTypeSymbol? t)
{
if (!(context.SyntaxReceiver is ClassSyntaxReceiver receiver))
yield break;
Compilation compilation = context.Compilation;
foreach (var derivedClassDeclaration in receiver.Classes)
{
SemanticModel model = compilation.GetSemanticModel(derivedClassDeclaration.SyntaxTree);
INamedTypeSymbol? derivedClassSymbol = model.GetDeclaredSymbol(derivedClassDeclaration) as INamedTypeSymbol;
string filePath = derivedClassDeclaration.SyntaxTree.FilePath;
string className = Path.GetFileNameWithoutExtension(filePath);
if(derivedClassSymbol == null || !filePath.Contains("Assets"))
continue;
AssetInfo res = new AssetInfo
{
DeclarationSyntax = derivedClassDeclaration,
ClassName = className,
ClassFullName = derivedClassSymbol.ToDisplayString(),
Path = filePath,
Symbol = derivedClassSymbol
};
if (IsDerivedFrom(derivedClassSymbol, t))
{
yield return res;
continue;
}
foreach (INamedTypeSymbol interfaceSymbol in derivedClassSymbol.AllInterfaces)
{
if (SymbolEqualityComparer.Default.Equals(interfaceSymbol, t))
{
yield return res;
break;
}
}
}
}
protected IEnumerable<AssetInfo> GetAssetsOfType(GeneratorExecutionContext context, string t)
{
Compilation compilation = context.Compilation;
INamedTypeSymbol? specificType = compilation.GetTypeByMetadataName(t);
return GetAssetsOfType(context, specificType);
}
protected static bool IsDerivedFrom(INamedTypeSymbol? symbol, INamedTypeSymbol? baseType)
{
if (symbol == null)
return false;
if (baseType == null)
return true;
INamedTypeSymbol? current = symbol.BaseType;
while (current != null)
{
if (SymbolEqualityComparer.Default.Equals(current, baseType))
return true;
current = current.BaseType;
}
return false;
}
}