我想使用宏来检查函数是否返回特定的泛型类型,例如Array
,如果函数正在返回Array<Dynamic>
,Array<String>
甚至泛型也很好Array<T>
。
所以我尝试Context.unify
了Array<Dynamic>
。对于type参数为“ generic”的情况,它是否可行Array<String>
还是Array<Dynamic>
失败,因为ComplexTypeArray<T>
不会使用转换为Type Type not found: T
(请参见下面的代码)。有什么方法可以实现我的目标?
package;
#if macro
import haxe.macro.Context;
using haxe.macro.ComplexTypeTools;
#end
#if !macro @:build(Macros.build()) #end
class Main
{
public function test<T>():Array<T>
{
return [];
}
}
class Macros
{
public static function build()
{
#if macro
var fields = Context.getBuildFields();
for(field in fields)
{
switch(field.kind)
{
case FFun(f):
// try to unify Array<String> with Array<Dynamic>
trace(Context.unify((macro:Array<String>).toType(), (macro:Array<Dynamic>).toType()));
// true
// try to unify Array<T> with Array<Dynamic>
trace(Context.unify(f.ret.toType(), (macro:Array<Dynamic>).toType()));
// Type not found: T
default:
}
}
return null;
#end
}
}
因此,检查TPath并不是最好的主意。基于先前关于Dynamic可分配给任何类型的假设,我们可以使用Dynamic(例如Array<T>
= Array<Dynamic>
)替换不可转换的类型参数,并在尝试统一它时进行替换。
static function toTypeExt(c:ComplexType):Null<haxe.macro.Type>
{
try {
return c.toType();
} catch (error:Error)
{
switch (c)
{
case TPath(p):
//deep copy of the TPath with all type parameters as Dynamic
var paramsCopy = [for (i in 0...p.params.length) TPType(macro:Dynamic)];
var pCopy:TypePath = {
name: p.name,
pack: p.pack,
sub: p.sub,
params: paramsCopy
}
var cCopy = TPath(pCopy);
//convert after
return cCopy.toType();
default:
}
}
return null;
}
在构建宏中使用toTypeExt()而不是toType。
trace(Context.unify(toTypeExt(f.ret), (macro:Array<Dynamic>).toType()));
在我看来,这更像是一种解决方法,但是ComplexTypeTools.toType有一个奇怪的事情-它会在使用类类型参数的情况下成功,而在方法类型参数的情况下失败。
统一将无法正常工作,因为无法将带有type参数的ComplexType转换为Type(在这种情况下)。但是,由于您要与Array统一,因此可以安全地假定任何Array都可以与其统一(因为任何类型都可以分配给Dynamic http://haxe.org/manual/types-dynamic.html)。
可能不是最简单的解决方案,但是简单的TPath检查是解决问题的方法:
case FFun(f):
switch (f.ret) {
case TPath({ name: "Array", pack: [], params: _ }):
trace("Yay!");
default:
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句