Skip to content

Instantly share code, notes, and snippets.

@tecteun
Last active January 31, 2019 23:17
Show Gist options
  • Save tecteun/51376c8572dad02879fb85ff512fce80 to your computer and use it in GitHub Desktop.
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!
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();
}
}
@tecteun
Copy link
Author

tecteun commented Jan 31, 2019

--macro Macro.buildJson("file.json", "ClassName")

object will be available in config.ClassName
Check the autocompletion 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment