Search code examples
macroshaxecode-completion

Haxe: Creating a code completion macro for JSON files


I am trying to implement a code completion macro for JSON files by generating field definitions

    var classOfChild = Type.getClass(child); // `child` may look like this array: [[1,2,3],[0.1,0.2,0.3]]
    fields.push({
        "name": childName,
        "pos" : _pos,
        "kind": childType,
    });

I already watched some videos and read some tutorials on this, but there is no information how to get ComplexType from a Type.typeof(object) result.

I have tried code that doesn't work like:

                    //"kind": childType,
                    //"kind": childType.toString(),
                    //"kind": FVar(macro {childType.toString(); }),
                    //"kind": FVar(macro Array<$v{arrType}>)

but none of them worked (all of them raise some Error or )

Edit 1: here is my json data:

{"floatVar1":0.1, "str":"some string", "nullValueObject":null, "arrayOfInts":[11,20,9], "matrixLikeArray":[[14, 12, 13, 11, 18]], "floatMatrix":[[14.4, 12.3, 13.7, 11.9, 18.0]], "symbolPayouts":[0.05], "objectInObject":{"prop1":"some str", "prop2": "some str2", "prop3":10.17, "prop4":[[1,2,3],[19.3,20.4]]}}

I would like to create Definitions for prop4, ("prop4":[[1,2,3],[19.3,20.4]])

Edit 2: I have already figured out how to create the "kind" for the simple types ("kind": FVar(macro:Dynamic)) and the object (kind : FVar(TAnonymous( jsonFields ))). But how to do that for arrays, arrays of arrays, etc.

Edit 3: code in gist.github.com


Solution

  • When generating code with macros it is easy to attempt to generate something which isn't efficient and you did get side tracked by trying to define explicit types.

    Based on your gist, you just need to define a json field and give it the content of your JSON file as the field's value as if you were defining the value as a Haxe literal object.

    Your goal is then to generate something you could have written as:

    private var json = { prop1:'hello', prop2:42, prop3:[1,2,3] };
    

    The haxe compiler will strongly type this json field.

    To achieve that, your macro just need to add one field with an initial value obtained from the JSON file; and likewise, the Haxe compiler will strictly type it.

    Creating a variable with a type to be inferred by the compiler is simply FVar(null, valueExpr), which means your entire macro can be reduced to:

        var fields = Context.getBuildFields();
        var json = Json.parse(src); 
    
        fields.push({
            name : "json",
            pos : Context.currentPos(),
            kind : FVar(null, macro $v{json}),
            access: [APrivate],
        });
        return fields;
    

    For a more elaborated version I can point you on the following gist: ResourceGenerator.hx which will generate recursively "inlinable" and dce-friendly objects.

    PS: sadly your "prop4":[[1,2,3],[19.3,20.4]] is impossible because it will be seen by the compiler as an Array of incompatible types ([Array<Int>, Array<Float>]).