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 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 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; } }