簡體   English   中英

Haxe自定義元數據到宏調用

[英]Haxe Custom Metadata to Macro Call

假設我已經創建了一個可以像這樣使用的構建宏

@:build(macros.SampleMacro.build("arg"))
class Main {}

是否可以將其轉換為自定義的速記元數據?

@:samplemacro("arg")
class Main {}

關於這個的任何文件?

我不確定這是否可行,但您可以利用@:autoBuild()元數據在接口上工作的事實。 這通常用於“標記接口”,如下所示:

class Main implements ISampleMacro {}

@:autoBuild(macros.SampleMacro.build("arg"))
interface ISampleMacro {}

但是,大概你想要每次使用不同的"arg" ,而不是硬編碼。 您可以使用@:const類型參數來實現此目的:

class Main implements ISampleMacro<"foo"> {}

@:autoBuild(macros.SampleMacro.build())
interface ISampleMacro<@:const T> {}

在構建宏中提取類型參數的值需要比簡單地向其傳遞參數更多的努力:

switch (Context.getLocalClass().get().interfaces[0].params[0]) {
    case TInst(_.get() => t, params):
        switch (t.kind) {
            case KExpr({expr: EConst(CString(arg)), pos: _}):
                trace(arg); // "foo"
            case _:
        }
    case _:
}

經過多次磕磕絆絆之后,我發現有可能做到這一點。

部分解決方案是使用

--macro addGlobalMetadata('$path', '@:build(Build.build())')

這允許您將@:build函數分配給$ path中的所有類。 這可以用作編譯器選項或haxeflag。

但這本身並不足以采用采用動態參數的元數據標簽。 但是因為我們現在有一個為所有類執行的Build.build(), 所以 Build.build()函數可以處理檢查哪些類具有我們的自定義元數據標記,以及為這些類構建任何類我們可能需要。

要檢查我們的自定義元數據標簽,我們設置檢查宏,如下所示:

class Build {

    static var META_STR:String = ":samplemacro";

    macro static public function build():Array<Field> {

        // We check only those Contexts for where a class type exists
        var localClass:Null<Ref<ClassType>> = Context.getLocalClass();
        if(localClass == null) return null; // no class type

        // We check if the metadata for the class contains our 
        // custom metadata string at all
        if(!localClass.get().meta.has(META_STR)) return null;

        // This class does have our custom metadata!
        // Because there may be more than one of the same type
        // of metadata, we extract a list of all the custom metadata tags

        var customTags = localClass.get().meta.extract(META_STR);

        // For each tag we can get at the arguments passed in 
        // by accessing the params field
        for(customTag in customTags){
            var params = customTag.params;

            // Here we can handle each of our @:samplemacro(params) tags,
            // save the params for use later, or 
            // pass the arguments over to another class to deal with
        }

        var fields = Context.getBuildFields();

        // Modify the class fields the way you want

        // Optionally destroy the metadata tags afterwards
        // with localClass.get().meta.remove(META_STR);

        return fields;
    }
}

有關addGlobalMetadata的更多詳細信息,請訪問: https ://stackoverflow.com/a/38075492/1502818

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM