2016-07-15 76 views
1

假设您有类型构建宏,接口调用@: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 {} 

正如你所看到的,我们检查,如果场 “你好” 的存在。但是,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的宏类型的建筑?有没有更可行的方法来完成这项工作?我的代码在特定场景中是否失败?这个代码是否有任何有害的副作用?

库实现这样的想法:https://github.com/Misiur/MacroAncestry

我试图解决this问题。

回答

1

不,这是要走的路,使用元数据来存储您处理的类的信息。 https://groups.google.com/forum/#!searchin/haxelang/francis $ 20bourre/haxelang/WEZ6_47rgqo/7NQXfUzUFQAJ

另一种方式,如果你没有在运行时需要这些信息,是使用静态数组上的专用类。 https://github.com/DoclerLabs/hexAnnotation/blob/master/src/hex/annotation/AnnotationReader.hx

你甚至可以推后,在你的编译代码这样的信息: https://github.com/DoclerLabs/hexInject/blob/master/src/hex/di/annotation/AnnotationReader.hx

希望有所帮助。

+0

只有在haxe社区,一个答案,但具体解决我的问题。谢谢! – Misiur