简体   繁体   English

访问等级 <T> 宏中的Context.getLocalClass()的说明

[英]Access Class<T> of Context.getLocalClass() in build macro

I want to make a macro that adds a field to my classes, and the field value should be Class<T> of class they are sitting in. Here is my minimal example, and it does not compile with this error: 我想创建一个宏,将一个字段添加到我的类中,并且该字段的值应为它们所在Class<T> 。这是我的最小示例,并且不会编译此错误:

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

But if I move Foo from package foo to root package, then it compiles and works. 但是,如果我将Foo从软件包foo移到根软件包,那么它将编译并起作用。

Main.hx Main.hx

import foo.Foo;
class Main 
{
    static function main() 
    {
        trace(Foo.data);
    }
}

Build.hx 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);


    }
}

Base.hx Base.hx

package;

@:autoBuild(Build.build(Main.Data))
class Base
{
    public function new()
    {
    }
}

foo/Foo.hx foo / Foo.hx

package foo;

class Foo extends Base
{
}

EConst(CIdent("foo.Bar")) won't work, because that's very much as if you could specify a name with . EConst(CIdent("foo.Bar"))无效,因为这就像您可以使用指定名称一样. periods in it. 期间。 Instead, you need to do EField({ expr: EConst(CIdent("foo")) }, "Bar") , since that is what foo.Bar gets parsed to by a compiler itself (try trace ing expressions from a macro). 相反,您需要执行EField({ expr: EConst(CIdent("foo")) }, "Bar") ,因为这是编译器本身解析foo.Bar (尝试从宏中trace表达式) 。

So the correct code would be 所以正确的代码是

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);
    }
}

handling creation of a EConst(CIdent) expression and subsequent wrapping it in EField layers for trailing packages, and, finally, the class name. 处理EConst(CIdent)表达式的创建,然后将其包装在EField层中以用于尾随程序包,最后是类名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM