假設您有類型構建宏,接口調用@: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問題。
只有在haxe社區,一個答案,但具體解決我的問題。謝謝! – Misiur