improve: move to src
This commit is contained in:
25
src/AssetInfo.cs
Normal file
25
src/AssetInfo.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
|
||||||
|
namespace Polonium.Generators;
|
||||||
|
|
||||||
|
public struct AssetInfo
|
||||||
|
{
|
||||||
|
public INamedTypeSymbol Symbol;
|
||||||
|
public string Path;
|
||||||
|
public ClassDeclarationSyntax DeclarationSyntax;
|
||||||
|
public string ClassName;
|
||||||
|
public string ClassFullName;
|
||||||
|
public string GodotPath {
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string rs = Path.Replace("\\", "/").Replace(" ", "%20");
|
||||||
|
rs = rs.Substring(rs.IndexOf("Assets", StringComparison.Ordinal));
|
||||||
|
return "res://" + rs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ScenePath => GodotPath.Replace(".cs", ".tscn");
|
||||||
|
|
||||||
|
}
|
||||||
80
src/AssetProcessGenerator.cs
Normal file
80
src/AssetProcessGenerator.cs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
52
src/AssetRegisterGenerator.cs
Normal file
52
src/AssetRegisterGenerator.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Polonium.Generators;
|
||||||
|
[Generator]
|
||||||
|
public class AssetRegisterGenerator : AssetProcessGenerator
|
||||||
|
{
|
||||||
|
public override void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
if (!(context.SyntaxReceiver is ClassSyntaxReceiver receiver))
|
||||||
|
return;
|
||||||
|
Compilation compilation = context.Compilation;
|
||||||
|
StringBuilder sb = new();
|
||||||
|
sb
|
||||||
|
.AppendLine("using System;")
|
||||||
|
.AppendLine("using Godot;")
|
||||||
|
.AppendLine("using Polonium.Attributes;")
|
||||||
|
.AppendLine("[AutoRegister]")
|
||||||
|
.AppendLine("public static class AssetRegister")
|
||||||
|
.AppendLine("{")
|
||||||
|
.AppendLine(" public static void Register()")
|
||||||
|
.AppendLine(" {");
|
||||||
|
foreach (var derivedClassDeclaration in receiver.Classes)
|
||||||
|
{
|
||||||
|
SemanticModel model = compilation.GetSemanticModel(derivedClassDeclaration.SyntaxTree);
|
||||||
|
INamedTypeSymbol? symbol = model.GetDeclaredSymbol(derivedClassDeclaration) as INamedTypeSymbol;
|
||||||
|
string filePath = derivedClassDeclaration.SyntaxTree.FilePath.Replace(".cs", ".tscn");
|
||||||
|
if(!filePath.Contains("Assets") || symbol == null)
|
||||||
|
continue;
|
||||||
|
ImmutableArray<AdditionalText> additionalFiles = context.AdditionalFiles;
|
||||||
|
if (additionalFiles.Select(y => y.Path).Contains(filePath))
|
||||||
|
{
|
||||||
|
string rs = filePath.Replace("\\", "/").Replace(" ", "%20");
|
||||||
|
rs = rs.Substring(rs.IndexOf("Assets", StringComparison.Ordinal));
|
||||||
|
string gdPath = "res://" + rs;
|
||||||
|
string className = Path.GetFileNameWithoutExtension(filePath);
|
||||||
|
sb
|
||||||
|
.AppendLine(
|
||||||
|
$" GlobalRegistry.Asset<{className}>.Scene = ResourceLoader.Load<PackedScene>(\"{gdPath}\");"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine("}");
|
||||||
|
context.AddSource("AssetRegistry.g.cs", sb.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/ClassSyntaxReceiver.cs
Normal file
18
src/ClassSyntaxReceiver.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
|
||||||
|
namespace Polonium.Generators;
|
||||||
|
|
||||||
|
public class ClassSyntaxReceiver : ISyntaxReceiver
|
||||||
|
{
|
||||||
|
public List<ClassDeclarationSyntax> Classes { get; set; } = new ();
|
||||||
|
|
||||||
|
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
|
||||||
|
{
|
||||||
|
if (syntaxNode is ClassDeclarationSyntax classDeclaration)
|
||||||
|
{
|
||||||
|
Classes.Add(classDeclaration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
56
src/GlobalRegistryGenerator.cs
Normal file
56
src/GlobalRegistryGenerator.cs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
using System.Text;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Polonium.Generators;
|
||||||
|
[Generator]
|
||||||
|
public class GlobalRegistryGenerator : ISourceGenerator
|
||||||
|
{
|
||||||
|
public void Initialize(GeneratorInitializationContext context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new();
|
||||||
|
sb
|
||||||
|
.AppendLine("using Godot;")
|
||||||
|
.AppendLine("using System;")
|
||||||
|
.AppendLine("using System.Collections.Generic;")
|
||||||
|
.AppendLine("using System.Linq;")
|
||||||
|
.AppendLine("using System.Reflection;")
|
||||||
|
.AppendLine("using Polonium.Attributes;")
|
||||||
|
.AppendLine("using Polonium;")
|
||||||
|
.AppendLine("public static partial class GlobalRegistry")
|
||||||
|
.AppendLine("{")
|
||||||
|
.AppendLine(" public static void Start()")
|
||||||
|
.AppendLine(" {")
|
||||||
|
.AppendLine(" PoloniumRegistry.Prepare();")
|
||||||
|
.AppendLine(" Assembly assembly = Assembly.GetExecutingAssembly();")
|
||||||
|
.AppendLine(" IEnumerable<Type> registerTypes = Utils.GetLoadableTypes(assembly);")
|
||||||
|
.AppendLine(" registerTypes = registerTypes.Where(t => t.IsClass && t.GetCustomAttributes(typeof(AutoRegister), false).Any());")
|
||||||
|
.AppendLine(" foreach(Type t in registerTypes)")
|
||||||
|
.AppendLine(" {")
|
||||||
|
.AppendLine(" MethodInfo registerMethod = t.GetMethod(\"Register\", BindingFlags.Static | BindingFlags.Public);")
|
||||||
|
.AppendLine(" if (registerMethod != null)")
|
||||||
|
.AppendLine(" registerMethod.Invoke(null, null);")
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine(" public static class Asset<T> where T : Node")
|
||||||
|
.AppendLine(" {")
|
||||||
|
.AppendLine(" private static readonly Queue<T> Pool = new();")
|
||||||
|
.AppendLine(" public static PackedScene Scene { get; set; }")
|
||||||
|
.AppendLine(" public static T Instance => Scene.Instantiate<T>();")
|
||||||
|
.AppendLine(" public static T Get() => Pool.Count > 0 ? Pool.Dequeue() : Instance;")
|
||||||
|
.AppendLine(" public static void Return(T obj)")
|
||||||
|
.AppendLine(" {")
|
||||||
|
.AppendLine(" if(Pool.Count < 10)")
|
||||||
|
.AppendLine(" Pool.Enqueue(obj);")
|
||||||
|
.AppendLine(" else")
|
||||||
|
.AppendLine(" obj.QueueFree();")
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine(" public static PoloniumRegistry PoloniumRegistry => PoloniumRegistry.Instance;")
|
||||||
|
.AppendLine("}");
|
||||||
|
context.AddSource("GlobalRegistry.g.cs", sb.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/RegistryEntityGenerator.cs
Normal file
33
src/RegistryEntityGenerator.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Polonium.Generators;
|
||||||
|
[Generator]
|
||||||
|
public class RegistryEntityGenerator : AssetProcessGenerator
|
||||||
|
{
|
||||||
|
public override void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
if (!(context.SyntaxReceiver is ClassSyntaxReceiver receiver))
|
||||||
|
return;
|
||||||
|
Compilation compilation = context.Compilation;
|
||||||
|
INamedTypeSymbol? regEntity = compilation.GetTypeByMetadataName("Polonium.Attributes.RegistryEntity");
|
||||||
|
foreach (var derivedClassDeclaration in receiver.Classes)
|
||||||
|
{
|
||||||
|
SemanticModel model = compilation.GetSemanticModel(derivedClassDeclaration.SyntaxTree);
|
||||||
|
if (
|
||||||
|
model.GetDeclaredSymbol(derivedClassDeclaration) is INamedTypeSymbol symbol &&
|
||||||
|
symbol.GetAttributes().Any(x => SymbolEqualityComparer.Default.Equals(x.AttributeClass, regEntity))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new();
|
||||||
|
sb
|
||||||
|
.AppendLine("public static partial class GlobalRegistry")
|
||||||
|
.AppendLine("{")
|
||||||
|
.AppendLine($" public static {symbol.ToDisplayString()} {symbol.Name} {{ get; set; }} ")
|
||||||
|
.AppendLine("}");
|
||||||
|
context.AddSource($"RegistryEntity_{symbol.Name}.g.cs", sb.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user