add: Registry
This commit is contained in:
26
AssetInfo.cs
Normal file
26
AssetInfo.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
namespace Hangman.SDK.Generators;
|
||||||
|
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
|
||||||
|
|
||||||
|
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
AssetProcessGenerator.cs
Normal file
80
AssetProcessGenerator.cs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Hangman.SDK.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
18
ClassSyntaxReceiver.cs
Normal file
18
ClassSyntaxReceiver.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
|
||||||
|
namespace Hangman.SDK.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
GlobalRegistryGenerator.cs
Normal file
37
GlobalRegistryGenerator.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System.Text;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Hangman.SDK.Generators;
|
||||||
|
[Generator]
|
||||||
|
public class GlobalRegistryGenerator : ISourceGenerator
|
||||||
|
{
|
||||||
|
public void Initialize(GeneratorInitializationContext context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new();
|
||||||
|
sb.AppendLine("using System;");
|
||||||
|
sb.AppendLine("using System.Collections.Generic;");
|
||||||
|
sb.AppendLine("using System.Linq;");
|
||||||
|
sb.AppendLine("using System.Reflection;");
|
||||||
|
sb.AppendLine("using Hangman.SDK.Attributes;");
|
||||||
|
sb.AppendLine("public static partial class GlobalRegistry");
|
||||||
|
sb.AppendLine("{");
|
||||||
|
sb.AppendLine(" public static void Register()");
|
||||||
|
sb.AppendLine(" {");
|
||||||
|
sb.AppendLine(" Assembly assembly = Assembly.GetEntryAssembly();");
|
||||||
|
sb.AppendLine(" IEnumerable<Type> registerTypes = assembly.GetTypes()");
|
||||||
|
sb.AppendLine(" .Where(t => t.IsClass && t.GetCustomAttributes(typeof(AutoRegister), false).Any());");
|
||||||
|
sb.AppendLine(" foreach(Type t in registerTypes)");
|
||||||
|
sb.AppendLine(" {");
|
||||||
|
sb.AppendLine(" MethodInfo registerMethod = t.GetMethod(\"Register\", BindingFlags.Static | BindingFlags.Public);");
|
||||||
|
sb.AppendLine(" if (registerMethod != null)");
|
||||||
|
sb.AppendLine(" registerMethod.Invoke(null, null);");
|
||||||
|
sb.AppendLine(" }");
|
||||||
|
sb.AppendLine(" }");
|
||||||
|
sb.AppendLine("}");
|
||||||
|
context.AddSource("GlobalRegistry.g.cs", sb.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,23 +22,4 @@
|
|||||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.3.0"/>
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.3.0"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Update="Resources.resx">
|
|
||||||
<Generator>ResXFileCodeGenerator</Generator>
|
|
||||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
|
||||||
</EmbeddedResource>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Update="Resources.Designer.cs">
|
|
||||||
<DesignTime>True</DesignTime>
|
|
||||||
<AutoGen>True</AutoGen>
|
|
||||||
<DependentUpon>Resources.resx</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Properties\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
Reference in New Issue
Block a user