完成@:op(ab)

rom*_*mik 6 haxe

@:op(a.b)这里描述了这个功能:https://haxe.io/releases/3.3.0/ 我有May<T>一个用于null安全的摘要.这是它的简化版本:

package;
import haxe.macro.Expr;

abstract May<T>(Null<T>) from(Null<T>){

    // convert T, Null<T> or May<T> to May<T>
    // accepts Null<T because of 'from(Null<T>)' 
    // accepts T because Null<T> has 'from(T)'
    // we need to accept May<T> to avoid returning May<May<T>> from resolve() if field is already a May
    public static inline function from<T>(t:May<T>):May<T> return t; 

    public inline function exist():Bool return this != null;

    public inline function unwrap():T return exist() ? unsafeUnwrap() : throw 'unwrap null';

    public inline function unwrapOr(defaultValue:T):T return exist() ? unsafeUnwrap() : defaultValue;

    public inline function unsafeUnwrap():T return this;

    // return same field from underlying type but as May<FieldType>
    @:op(a.b) static macro function resolve<T>(ethis:ExprOf<May<T>>, name:String):Expr {
        return macro {
            var me = $ethis;
            var result = May.from(me.exist() ? me.unsafeUnwrap().$name : null);
            result;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

注意这个resolve()功能.这是我想要添加到我的实际May摘要中的新功能.它允许安全地从中获取字段Mayunwrap()仅调用一次.例如:

may.exist() ? may.unwrap().someField : defaultValue
Run Code Online (Sandbox Code Playgroud)

may.someField.unwrapOr(defaultValue)
Run Code Online (Sandbox Code Playgroud)

这非常方便,效果很好.但完成不起作用.它只是给出了场May:unwrap(),exist()等等,但没有从根本类字段.

我决定添加@:forward元数据以完成:

#if display @:forward #end
Run Code Online (Sandbox Code Playgroud)

这使编译器在完成期间查看所有字段.它总比没有好,但字段的类型不正确:T而不是May<T>,所以我没有完成May字段.

我理解为什么编译器在使用时无法知道所有可能的字段@:op(a.b),但也许有一些更聪明的技巧会有所帮助?