HaxeFoundation / HaxeFoundation/haxe

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

Open
#11,804 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Haxe
Stars
6.9k
Forks
715
Avg merge
2d 2h
Merged PRs (30d)
11

Description

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**
```haxe
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

Name: ${name}
;
}
}
```

**The macro**
```haxe
#if macro
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.ExprTools;

using StringTools;

class RenderMarkupMacro {

macro static public function build():Array {

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.

```js
// 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 "

Name: " + this.name + "
";
}
};
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 🙏

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.