feat: aetherbind, first source generator

This commit is contained in:
redglow
2026-07-18 17:05:03 +02:00
parent 4ce99d9486
commit aae9c083d9
69 changed files with 210 additions and 156 deletions
+93
View File
@@ -0,0 +1,93 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using Godot;
using OwofGames.GodotLume;
namespace GodotHostTest.AetherBind;
public static class ScopeTypesAndNames
{
private static readonly ConcurrentDictionary<Type, string> TypeToQualifiedName = new();
private static readonly ConcurrentDictionary<string, Type> QualifiedNameToType = new();
private static readonly ConcurrentDictionary<string, string> QualifiedNameToSimpleName = new();
private static readonly Type RootScopeType = typeof(RootScope);
private static AssemblyLoadEventHandler? _assemblyLoadEventHandler;
private static void InitializeIfNeeded()
{
if (_assemblyLoadEventHandler != null) return;
Initialize();
AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly())!.Unloading += OnUnloading;
}
private static void OnUnloading(AssemblyLoadContext _)
{
Deinitialize();
}
private static void Initialize()
{
GD.Print($"Initializing {nameof(ScopeTypesAndNames)}");
TypeToQualifiedName.Clear();
QualifiedNameToType.Clear();
QualifiedNameToSimpleName.Clear();
_assemblyLoadEventHandler = (sender, args) => CacheScriptsInAssembly(args.LoadedAssembly);
AppDomain.CurrentDomain.AssemblyLoad += _assemblyLoadEventHandler;
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
CacheScriptsInAssembly(assembly);
return;
void CacheScriptsInAssembly(Assembly assembly)
{
foreach (var type in assembly.GetTypes()
.Where(t => t.IsClass)
.Where(t => t == RootScopeType || t.IsSubclassOf(RootScopeType)))
{
if (type.AssemblyQualifiedName == null)
{
GD.PrintErr("Assembly qualified name of {type} is null");
continue;
}
TypeToQualifiedName[type] = type.AssemblyQualifiedName;
QualifiedNameToType[type.AssemblyQualifiedName] = type;
QualifiedNameToSimpleName[type.AssemblyQualifiedName] = type.Name;
}
}
}
private static void Deinitialize()
{
GD.Print($"Deinitializing {nameof(ScopeTypesAndNames)}");
AppDomain.CurrentDomain.AssemblyLoad -= _assemblyLoadEventHandler;
_assemblyLoadEventHandler = null;
TypeToQualifiedName.Clear();
QualifiedNameToType.Clear();
QualifiedNameToSimpleName.Clear();
}
public static IEnumerable<string> GetQualifiedNames()
{
InitializeIfNeeded();
return from p in TypeToQualifiedName
orderby p.Key == RootScopeType ? 0 : 1
select p.Value;
}
public static Type GetType(string qualifiedName)
{
InitializeIfNeeded();
return QualifiedNameToType[qualifiedName];
}
public static string GetSimpleNameFromQualifiedName(string qualifiedName)
{
InitializeIfNeeded();
return QualifiedNameToSimpleName[qualifiedName];
}
}