Rewrite the CompiledClassList macro to use a resource

This commit is contained in:
EliteMasterEric
2026-08-08 02:46:40 +08:00
committed by Hundrec
parent 7a3422bda6
commit 86c6f95cae
2 changed files with 51 additions and 20 deletions
+14 -9
View File
@@ -13,6 +13,11 @@ import haxe.macro.Type.ClassType;
@:nullSafety
class ClassMacro
{
/**
* The name for the Haxe resource that stores Generation Metadata.
*/
static inline final METADATA_RESOURCE_NAME:String = 'Funkin_CompiledClassList';
/**
* Gets a list of `Class<T>` for all classes in a specified package.
*
@@ -42,7 +47,7 @@ class ClassMacro
*
* Example: `var list:Array<Class<FlxSprite>> = listSubclassesOf(FlxSprite);`
*
* @param targetClass The class to query for subclasses.
* @param targetClassExpr The class to query for subclasses.
* @return A list of classes matching the specified criteria.
*/
public static macro function listSubclassesOf<T>(targetClassExpr:ExprOf<Class<T>>):ExprOf<List<Class<T>>>
@@ -122,31 +127,31 @@ class ClassMacro
*/
static function compileClassLists()
{
var compiledClassList:ClassType = MacroUtil.getClassType("funkin.util.macro.CompiledClassList");
var compiledClassList:ClassType = MacroUtil.getClassType('funkin.util.macro.CompiledClassList');
if (compiledClassList == null) throw "Could not find CompiledClassList class.";
if (compiledClassList == null) throw 'Could not find CompiledClassList class.';
// Reset outdated metadata.
if (compiledClassList.meta.has('classLists')) compiledClassList.meta.remove('classLists');
var classLists:Array<Expr> = [];
var classLists:Array<Array<String>> = [];
// Generate classLists.
for (request in classListsToGenerate)
{
// Expression contains String, [Class<T>...]
var classListEntries:Array<Expr> = [macro $v{request}];
var classListEntries:Array<String> = [request];
for (i in classListsRaw.get(request))
{
// TODO: Boost performance by making this an Array<Class<T>> instead of an Array<String>
// How to perform perform macro reificiation to types given a name?
classListEntries.push(macro $v{i});
classListEntries.push(i);
}
classLists.push(macro $a{classListEntries});
classLists.push(classListEntries);
}
// Insert classLists into metadata.
compiledClassList.meta.add('classLists', classLists, Context.currentPos());
var classListsHXSF = haxe.Serializer.run(classLists);
Context.addResource(METADATA_RESOURCE_NAME, haxe.io.Bytes.ofString(classListsHXSF));
}
static function doesClassMatchRequest(classType:ClassType, request:String):Bool
+37 -11
View File
@@ -10,6 +10,11 @@ using funkin.util.AnsiUtil;
@:nullSafety
class CompiledClassList
{
/**
* The name for the Haxe resource that stores Generation Metadata.
*/
static inline final METADATA_RESOURCE_NAME:String = 'Funkin_CompiledClassList';
static var classLists:Map<String, List<Class<Dynamic>>> = [];
static var initialized:Bool = false;
@@ -21,25 +26,21 @@ class CompiledClassList
{
initialized = true;
// Meta.getType returns Dynamic<Array<Dynamic>>.
var metaData = Meta.getType(CompiledClassList);
var metadata:Array<Array<String>> = fetchMetadata();
if (metaData.classLists != null)
if (metadata != null)
{
for (list in metaData.classLists)
for (data in metadata)
{
var data:Array<Dynamic> = cast list;
// First element is the list ID.
var id:String = cast data[0];
var id:String = data[0];
// All other elements are class types.
var classes:List<Class<Dynamic>> = new List();
for (i in 1...data.length)
{
var className:String = cast data[i];
// var classType:Class<Dynamic> = cast data[i];
var classType:Class<Dynamic> = cast Type.resolveClass(className);
var className:String = data[i];
var classType:Class<Dynamic> = Type.resolveClass(className);
classes.push(classType);
}
@@ -48,10 +49,27 @@ class CompiledClassList
}
else
{
throw "Class lists not properly generated. Try cleaning out your export folder, restarting your IDE, and rebuilding your project.";
throw 'Class lists not properly generated. Try cleaning out your export folder, restarting your IDE, and rebuilding your project.';
}
}
static var _metadata:Dynamic = null;
static function fetchMetadata():Dynamic
{
if (_metadata != null) return _metadata;
var classListsHXSF:String = haxe.Resource.getString(METADATA_RESOURCE_NAME);
_metadata = haxe.Unserializer.run(classListsHXSF);
return _metadata;
}
/**
* Request a list of classes that match the specified criteria.
*
* @param request The request. See `ClassMacro` for more information.
* @return The list of matching classes.
*/
public static function get(request:String):List<Class<Dynamic>>
{
if (!initialized) init();
@@ -67,6 +85,14 @@ class CompiledClassList
return classLists.get(request);
}
/**
* Request a list of classes that match the specified criteria.
* Casts the list to match the specified type.
*
* @param request The request. See `ClassMacro` for more information.
* @param type The type of classes to cast the list to.
* @return The list of matching classes.
*/
public static inline function getTyped<T>(request:String, type:Class<T>):List<Class<T>>
{
return cast get(request);