romamik
romamik

Reputation: 595

Haxe: add @:build metadata to all classes in project

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

Answers (2)

YellowAfterlife
YellowAfterlife

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

Gama11
Gama11

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

Related Questions