add: Item Manager

This commit is contained in:
h z
2025-02-28 08:49:32 +00:00
parent 03468ad89c
commit ed9ae2113d
5 changed files with 161 additions and 1 deletions

View File

@@ -86,5 +86,75 @@ public abstract class AssetProcessGenerator : ISourceGenerator
}
protected IEnumerable<ClassInfo> GetClassesWithAttribute(GeneratorExecutionContext context,
INamedTypeSymbol? attribute)
{
if(context.SyntaxReceiver is not ClassSyntaxReceiver receiver)
yield break;
Compilation compilation = context.Compilation;
foreach (ClassDeclarationSyntax? declaration in receiver.Classes)
{
SemanticModel model = compilation.GetSemanticModel(declaration.SyntaxTree);
INamedTypeSymbol? sClassSymbol = model.GetDeclaredSymbol(declaration) as INamedTypeSymbol;
string filePath = declaration.SyntaxTree.FilePath;
string className = Path.GetFileNameWithoutExtension(filePath);
if (sClassSymbol is null)
continue;
if (HasAttribute(sClassSymbol, attribute))
yield return new ClassInfo
{
DeclarationSyntax = declaration,
ClassName = className,
ClassFullName = sClassSymbol.ToDisplayString(),
Path = filePath,
Symbol = sClassSymbol,
Namespace = sClassSymbol.ContainingNamespace.ToDisplayString()
};
}
}
protected static bool HasAttribute(INamedTypeSymbol? type, INamedTypeSymbol? attr)
{
if (type is null)
return false;
return type.GetAttributes().Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, attr));
}
protected IEnumerable<ClassInfo> GetClassesOfType(GeneratorExecutionContext context, INamedTypeSymbol? type)
{
if(context.SyntaxReceiver is not ClassSyntaxReceiver receiver)
yield break;
Compilation compilation = context.Compilation;
foreach (ClassDeclarationSyntax? declaration in receiver.Classes)
{
SemanticModel model = compilation.GetSemanticModel(declaration.SyntaxTree);
INamedTypeSymbol? sClassSymbol = model.GetDeclaredSymbol(declaration) as INamedTypeSymbol;
string filePath = declaration.SyntaxTree.FilePath;
string className = Path.GetFileNameWithoutExtension(filePath);
if (sClassSymbol is null)
continue;
ClassInfo res = new ClassInfo
{
DeclarationSyntax = declaration,
ClassName = className,
ClassFullName = sClassSymbol.ToDisplayString(),
Path = filePath,
Symbol = sClassSymbol,
Namespace = sClassSymbol.ContainingNamespace.ToDisplayString()
};
if (IsDerivedFrom(sClassSymbol, type))
{
yield return res;
continue;
}
foreach (INamedTypeSymbol interfaceSymbol in sClassSymbol.AllInterfaces)
{
if (SymbolEqualityComparer.Default.Equals(interfaceSymbol, type))
{
yield return res;
break;
}
}
}
}
}

15
src/ClassInfo.cs Normal file
View File

@@ -0,0 +1,15 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Polonium.Generators;
public class ClassInfo
{
public INamedTypeSymbol Symbol { get; set; }
public ClassDeclarationSyntax DeclarationSyntax { get; set; }
public string ClassName { get; set; }
public string ClassFullName { get; set; }
public string Namespace { get; set; }
public string Path { get; set; }
}

View File

@@ -0,0 +1,42 @@
using Microsoft.CodeAnalysis;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis.CSharp;
namespace Polonium.Generators.Generators;
public class AbstractSkinItemTemplateGenerator : AssetProcessGenerator
{
public override void Execute(GeneratorExecutionContext context)
{
if (context.SyntaxReceiver is not ClassSyntaxReceiver receiver)
return;
Compilation compilation = context.Compilation;
INamedTypeSymbol? skinItem = compilation.GetTypeByMetadataName("Polonium.ItemManagers.SkinItem");
foreach (ClassInfo c in GetClassesOfType(context, skinItem))
{
if (!c.DeclarationSyntax.Modifiers.Any(m => m.IsKind(SyntaxKind.AbstractKeyword)))
continue;
StringBuilder sb = new();
sb
.AppendLine("using System;")
.AppendLine("using Skin=Polonium.SkinManagers.Skin;")
.AppendLine($"namespace {c.Namespace}")
.AppendLine($"public abstract partial class {c.ClassName}")
.AppendLine("{")
.AppendLine($" public new abstract partial class Generic<T{c.ClassName}, TSkin>")
.AppendLine($" where T{c.ClassName} : Generic<T{c.ClassName}, TSkin>")
.AppendLine($" where TSkin : Skin")
.AppendLine(" {")
.AppendLine($" public new abstract class Template : {c.ClassName}.Template")
.AppendLine(" {")
.AppendLine($" public override T{c.ClassName} Get => GenericGet<T{c.ClassName}, TSkin>();")
.AppendLine($" public override void Return(T{c.ClassName} item) => GenericReturn<T{c.ClassName}, TSkin>(item);")
.AppendLine(" }")
.AppendLine(" }")
.AppendLine(" }")
.AppendLine("}");
context.AddSource($"{c.ClassName}_AbstractSkinItemTemplate.g.cs", sb.ToString());
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.Text;
using Microsoft.CodeAnalysis;
namespace Polonium.Generators.Generators;
[Generator]
public class ActionNameRegisterGenerator : AssetProcessGenerator
{
public override void Execute(GeneratorExecutionContext context)
{
if (!(context.SyntaxReceiver is ClassSyntaxReceiver receiver))
return;
Compilation compilation = context.Compilation;
INamedTypeSymbol? actionSyntax = compilation.GetTypeByMetadataName("Polonium.Agents.AgentAction");
StringBuilder sb = new();
sb
.AppendLine("using System;")
.AppendLine("using Polonium;")
.AppendLine("using Polonium.Attributes;")
.AppendLine("[AutoRegister]")
.AppendLine("public static class ActionNameRegister")
.AppendLine("{")
.AppendLine(" public static void Register()")
.AppendLine(" {");
foreach (AssetInfo a in GetAssetsOfType(context, actionSyntax))
sb.AppendLine($" PoloniumRegistry.Action<{a.ClassName}>.Name = \"{a.ClassName}\";");
sb
.AppendLine(" }")
.AppendLine("}");
context.AddSource("ActionNameRegister.g.cs", sb.ToString());
}
}

View File

@@ -18,6 +18,7 @@ public class AssetRegisterGenerator : AssetProcessGenerator
sb
.AppendLine("using System;")
.AppendLine("using Godot;")
.AppendLine("using Polonium;")
.AppendLine("using Polonium.Attributes;")
.AppendLine("[AutoRegister]")
.AppendLine("public static class AssetRegister")
@@ -40,7 +41,7 @@ public class AssetRegisterGenerator : AssetProcessGenerator
string className = Path.GetFileNameWithoutExtension(filePath);
sb
.AppendLine(
$" GlobalRegistry.Asset<{className}>.Scene = ResourceLoader.Load<PackedScene>(\"{gdPath}\");"
$" PoloniumRegistry.Asset<{className}>.Scene = ResourceLoader.Load<PackedScene>(\"{gdPath}\");"
);
}
}