检查构建宏是否已处理祖先节点
Checking if build macro already processed ancestor node
假设您有类型构建宏,接口调用 @:autoBuild
使用上述宏,class 实现接口并 class 扩展它。如果 class 不包含特定方法,宏将失败。
像这样:
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 {}
如您所见,我们正在检查字段 "hello" 是否存在。但是,Context.getBuildFields
仅包含当前 class 的字段,并且 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 问题。
假设您有类型构建宏,接口调用 @:autoBuild
使用上述宏,class 实现接口并 class 扩展它。如果 class 不包含特定方法,宏将失败。
像这样:
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 {}
如您所见,我们正在检查字段 "hello" 是否存在。但是,Context.getBuildFields
仅包含当前 class 的字段,并且 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 问题。