Haxe:在构建宏中访问Context.getLocalClass()的Class <T>

rom*_*mik 5 macros haxe

我想创建一个宏,为我的类添加一个字段,并且字段值应该是Class<T>它们所在的类.这是我的最小示例,它不会使用此错误进行编译:

src/Base.hx:3:字符2-11:未知标识符:foo.Foo

但是如果我Foo从包foo转移到root包,那么它就会编译并运行.

Main.hx

import foo.Foo;
class Main 
{
    static function main() 
    {
        trace(Foo.data);
    }
}
Run Code Online (Sandbox Code Playgroud)

Build.hx

import haxe.macro.Context;
import haxe.macro.Type;
import haxe.macro.Expr;

class Build
{
    macro static public function build(DataClass):Array<Field> 
    {
        var cls = Context.getLocalClass().get();
        var pack = cls.pack.concat([cls.name]);
        var name = pack.join(".");
        trace(name);

        var expr = {
            expr: ExprDef.EConst(Constant.CIdent(name)),
            pos: Context.currentPos()
        }

        var newFieldCls = macro class {

            public static var data:Class<Dynamic> = $expr; 

        }

        var fields = Context.getBuildFields();
        return fields.concat(newFieldCls.fields);


    }
}
Run Code Online (Sandbox Code Playgroud)

Base.hx

package;

@:autoBuild(Build.build(Main.Data))
class Base
{
    public function new()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

富/ Foo.hx

package foo;

class Foo extends Base
{
}
Run Code Online (Sandbox Code Playgroud)

Yel*_*ife 5

EConst(CIdent("foo.Bar"))不会起作用,因为这就像你可以指定一个带有.句号的名字一样.相反,您需要这样做EField({ expr: EConst(CIdent("foo")) }, "Bar"),因为这是foo.Bar编译器本身解析的内容(尝试trace从宏中获取表达式).

所以正确的代码就是

import haxe.macro.Context;
import haxe.macro.Expr;
class Build {
    public static macro function build():Array<Field> {
        var self = Context.getLocalClass().get();
        var cpos = Context.currentPos();
        var out:Expr = null;
        inline function add(name:String) {
            if (out == null) {
                out = { expr: EConst(CIdent(name)), pos: cpos };
            } else out = { expr: EField(out, name), pos: cpos };
        }
        for (name in self.pack) add(name);
        add(self.name);
        return Context.getBuildFields().concat((macro class {
            public static var data:Class<Dynamic> = $out;
        }).fields);
    }
}
Run Code Online (Sandbox Code Playgroud)

处理EConst(CIdent)表达式的创建并随后将其包装在EField用于尾随包的层中,最后是类名.