【问题标题】:Access Class<T> of Context.getLocalClass() in build macro在构建宏中访问 Context.getLocalClass() 的 Class<T>
【发布时间】:2016-04-18 11:26:27
【问题描述】:

我想创建一个宏,为我的类添加一个字段,字段值应该是他们所在类的Class&lt;T&gt;。这是我的最小示例,它不会因为这个错误而编译:

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

但是如果我将 Foo 从包 foo 移动到根包,那么它可以编译并工作。

Main.hx

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

构建.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

package;

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

foo/Foo.hx

package foo;

class Foo extends Base
{
}

【问题讨论】:

    标签: macros haxe


    【解决方案1】:

    EConst(CIdent("foo.Bar")) 不起作用,因为这就像您可以指定一个带有. 句点的名称一样。相反,您需要执行EField({ expr: EConst(CIdent("foo")) }, "Bar"),因为这是foo.Bar 被编译器本身解析的内容(尝试使用宏中的traceing 表达式)。

    所以正确的代码应该是

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-04
      • 2018-07-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多