Reputation: 595
Is it possible to apply my type building macro to all classes in a project without modifying their code?
I'm trying to implement a debugger based on Haxe macros: basically I inject calls to my function between every expression in every function of the class. Currently I have an interface IDebuggable
and only code in classes that implement that interface can be stopped at breakpoints.
Upvotes: 3
Views: 523
Reputation: 3225
I've been pondering the specific "Add @:build to all classes, but only my classes" subject for some time, and I think the following is a slightly cleaner solution:
import haxe.io.Path;
import haxe.macro.Compiler;
import haxe.macro.Context;
import haxe.macro.Expr;
import sys.FileSystem;
class BuildTest {
public static macro function addMeta(meta:String) {
var here = Context.resolvePath("BuildTest.hx");
var dir = Path.directory(here);
for (rel in FileSystem.readDirectory(dir)) {
var full = Path.join([dir, rel]);
if (FileSystem.isDirectory(full)) {
Compiler.addGlobalMetadata(rel, meta);
} else if (Path.extension(rel).toLowerCase() == "hx") {
var name = Path.withoutExtension(rel);
Compiler.addGlobalMetadata(name, meta);
}
}
return null;
}
// test @:build
public static macro function build():Array<Field> {
trace(Context.getLocalType());
return null;
}
}
So the macro class sits in the root of the project class path, we use it as a point of reference for where the project files are, and then look over everything in the directory and call addGlobalMetadata
for top-level directories and Haxe files.
Doing addGlobalMetadata
on a directory/file that is not referenced in the project doesn't include it and doesn't throw an error either, so it all works out.
And then you call this macro in your HXML:
--macro BuildTest.addMeta("@:build(BuildTest.build())")
The singular caveat here is that if you have library code that uses the same packages as your code, it'll get added to those types too. For that purpose, doing a path/module check inside your @:build
macro is still the way.
Upvotes: 0
Reputation: 34188
You can use haxe.macro.Compiler.addGlobalMetadata()
for this. This can either be done from an initialization macro or on the command line:
--macro addGlobalMetadata('', '@:build(Build.build())')
Upvotes: 8