Last active
January 31, 2019 23:17
-
-
Save tecteun/51376c8572dad02879fb85ff512fce80 to your computer and use it in GitHub Desktop.
buildJson macro, dynamically builds type from json in package config.*, autocomplete your json son!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import haxe.macro.Context; | |
import haxe.macro.Expr; | |
class Macro { | |
macro public static function buildJson(config_path:String, ?name:String = "JsonConfig"):Array<Field>{ | |
var config_field_name = "data"; | |
var config = null; | |
var traverse:Dynamic->?Null<Array<haxe.macro.Field>>->ComplexType = null; | |
try{ | |
config = haxe.Json.parse(sys.io.File.getContent(config_path)); | |
}catch(e:Dynamic){ | |
trace('unable to parse config.json: $e'); | |
} | |
var td = macro class $name { | |
public function new(json_string:String) { | |
$i{config_field_name} = haxe.Json.parse(json_string); | |
}; | |
} | |
td.pack = [ "config" ]; | |
//this is typing only, generating a complextype | |
traverse = function(object, ?fields:Null<Array<haxe.macro.Field>> = null){ | |
fields = fields == null ? [] : fields; | |
for(f in Reflect.fields(object)){ | |
var field = Reflect.field(object, f); | |
var ct = haxe.macro.Context.toComplexType(haxe.macro.Context.typeof(macro $v{field})); | |
switch(ct){ | |
case TAnonymous(t): | |
//recurse anon sub objects | |
var ct:ComplexType = traverse(Reflect.field(object, f), []); | |
fields.push( { name: f, doc:null, access:[ APublic ], kind:FVar(macro:$ct), pos: haxe.macro.PositionTools.here(), meta: [] } ); | |
default: | |
fields.push( { name: f, doc:null, access:[ APublic ], kind:FVar(ct), pos: haxe.macro.PositionTools.here(), meta: [] } ); | |
} | |
} | |
return ComplexType.TAnonymous(fields); | |
} | |
var test:ComplexType = traverse(config); | |
//define the created type as a public var in the generated class (td) optionally set value. | |
td.fields.push({ | |
name : config_field_name, | |
access : [ APublic ], | |
kind : FVar(test), //kind : FVar(test, macro $v{ config }), //do not load initially | |
pos : haxe.macro.PositionTools.here(), | |
}); | |
/* | |
td.fields.push({ | |
name : "iterator", | |
access : [ APublic ], | |
kind : FFun({ret: macro:Iterator<String>, expr: macro return Reflect.fields(this).iterator(), args:[] }), | |
pos : Context.currentPos() | |
}); | |
*/ | |
Context.defineType(td); | |
return Context.getBuildFields(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
--macro Macro.buildJson("file.json", "ClassName")
object will be available in config.ClassName
Check the autocompletion 👍