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"/>
|
||||
</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>
|
||||
|
||||
Reference in New Issue
Block a user