Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing/Wrong code completion when using inline markup processed by macro #11804

Open
jeremyfa opened this issue Oct 25, 2024 · 2 comments
Open

Comments

@jeremyfa
Copy link

I have been playing with inline markup/xml feature of Haxe, but noticed a problem with code completion: no matter what the macro is returning as expr in place of the @:markup meta, code completion will not be affected by it. Instead it will always provide the same @:markup thing (which by the way only work on the first character <):

image

Code completion inside a ${} isn't working either, even if the macro returns a matching expression (see the macro below).
image

I would expect that the code completion would reflect what the macro actually returns as expression, so if it returns a string literal expression like in my macro, then the code completion would reflect that string.

As a comparison, this is what I have if, instead of the inline markup, I put directly the same string literal as the one my macro would return. In that situation, everything is working as expected:

image image image

Here is the example reproducing the case with a macro that converts any inline markup to the equivalent string literal (single quoted):

The class processed by the macro

class Main implements RenderMarkup {
    function new() {}

    var name = "John";

    public static function main() {
        var main = new Main();
        var result = main.render();
        trace(result);
    }

    function render() {
        return <div id="hello">Name: ${name}</div>;
    }
}

The macro

#if macro
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.ExprTools;

using StringTools;

class RenderMarkupMacro {

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

        var fields = Context.getBuildFields();

        for (field in fields) {

            switch field.kind {
                case FVar(t, e):
                    if (e != null)
                        field.kind = FVar(t, processInlineXml(e));

                case FProp(get, set, t, e):
                    if (e != null)
                        field.kind = FProp(get, set, t, processInlineXml(e));

                case FFun(f):
                    f.expr = processInlineXml(f.expr);
            }

        }

        return fields;

    }

    static function processInlineXml(e:Expr):Expr {

        switch e.expr {
            case EMeta(s, expr) if (s.name == ':markup'):
                switch expr.expr {
                    case EConst(CString(s, kind)):
                        return {
                            expr: EConst(CString(s, SingleQuotes)),
                            pos: expr.pos
                        };
                    case _:
                }
            case _:
        }

        return ExprTools.map(e, e -> {
            return processInlineXml(e);
        });

    }

}
#end

To confirm that my macro returns a valid single quoted string literal, I checked the js output, which is correct in referencing the ${name}. Only the code completion is missing.

// Generated by Haxe 4.3.6
(function ($global) { "use strict";
var Main = function() {
	this.name = "John";
};
Main.main = function() {
	var main = new Main();
	var result = main.render();
	console.log("src/Main.hx:14:",result);
};
Main.prototype = {
	render: function() {
		return "<div id=\"hello\">Name: " + this.name + "</div>";
	}
};
var haxe_iterators_ArrayIterator = function(array) {
	this.current = 0;
	this.array = array;
};
haxe_iterators_ArrayIterator.prototype = {
	hasNext: function() {
		return this.current < this.array.length;
	}
	,next: function() {
		return this.array[this.current++];
	}
};
Main.main();
})({});

It would be great if code completion was working in that situation, because that's so far the biggest obstacle against building well integrated react-style/jsx-like libraries for Haxe. Everything else in Haxe is there and well designed already for that, especially taking advantage of macros to process the inline markup 🙏

@jeremyfa
Copy link
Author

Looks like @kLabz managed to make this work in haxe-react with macro code, so I’ll have to check how he did it

@jeremyfa
Copy link
Author

So, it seems that some completion can be provided using the right EDisplay() for the right display queries, but this doesn't seem to work when using build macro and seems to only work when using an expression macro, that is, when wrapping the inline XML inside a method like jsx( <your markup />).

Aside from this, EDisplay usage is not documented as far as I know, and the implementation using it in haxe-react (react-next) is quite hard to understand and make sense of. At least I didn't manage to understand it enough so that I can provide satisfying code completion (only managed to provide some rudimentary Hover/Definition display completion). Anything wrapped in ${...} doesn`t provide any code completion like I would have when wrapping the xml in a single-quoted string.

All-in-all, I don't really know how to make it work right now with the elements I have. As a workaround I'll manage with inline markup inside a single-quoted string, but this issue remain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant