检查构建宏是否已处理祖先节点

时间:2016-07-15 15:31:40

标签: macros haxe

假设您有类型构建宏,使用上述宏调用@:autoBuild接口,实现接口的类和扩展它的类。如果课程不包含特定方法,宏将失败。

像这样:

Macro.hx

package;

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

class Macro
{
    macro public function build():Array<Field>
    {
        var fields = Context.getBuildFields();

        for (field in fields) {
            if (field.name == "hello") {
                //Do some modifications

                return fields;       
            }
        }

        Context.error('${Context.getLocalClass().toString()} doesn\'t contain a method `hello`', Context.currentPos());

        return null;
    }
}

I.hx

package;

@:autoBuild(Macro.build())
interface I {}

Foobar.hx

package;

class Foobar implements I
{
    public function new() {}

    public function hello(person:String)
    {
        return 'Hello $person!';
    }
}

Foo.hx

package;

@:keep
class Foo extends Foobar {}

正如您所看到的,我们正在检查字段&#34;你好&#34;存在。但是,Context.getBuildFields仅包含当前类的字段,而Foo的构建将失败。

这就是我的想法所在:为什么不检查是否已经处理过任何祖先?我们将更改Macro.hx以反映:

Macro.hx

package;

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

class Macro
{
    macro public function build():Array<Field>
    {
        var c = Context.getLocalClass().get();
        if(isAncestorAlreadyProcessed(c)) {
            return null;
        }

        var fields = Context.getBuildFields();

        for (field in fields) {
            if (field.name == "hello") {
                //Do some modifications

                c.meta.add(":processed", [], c.pos);  

                return fields;       
            }
        }      

        Context.error('${Context.getLocalClass().toString()} doesn\'t contain a method `hello`', Context.currentPos());

        return null;
    }

    private static function isAncestorAlreadyProcessed(c:ClassType)
    {
        if (c.meta.has(":processed")) return true;
        if (c.superClass == null) return false;

        return isAncestorAlreadyProcessed(c.superClass.t.get());
    }
}

主要问题:我是否误解了haxe宏型建筑?有没有更可行的方法来完成这项工作?我的代码在特定情况下是否会失败?此代码是否会产生任何有害的副作用?

我试图解决this问题。

1 个答案:

答案 0 :(得分:1)

不,这是要走的路,使用元数据来存储您处理的类的信息(source)。

另一种方法是,如果您在运行时不需要此信息,则在here等专用类上使用静态数组。之后,您甚至可以在已编译的代码中推送此信息,请参阅here

希望有所帮助。