Skip to content

Failing hover with macros and no invalidation #11995

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

Draft
wants to merge 2 commits into
base: development
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions tests/server/src/cases/issues/Issue11995.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cases.issues;

import haxe.display.Diagnostic;
import utest.Async;

class Issue11995 extends TestCase {
@:async
@:variant("WithInvalidation", true)
@:variant("WithoutInvalidation", false)
function test(async:Async, invalidate:Bool) {
var content = getTemplate("issues/Issue11995/Main.hx");
var transform = Markers.parse(content);
vfs.putContent("Main.hx", transform.source);
vfs.putContent("Macro.hx", getTemplate("issues/Issue11995/Macro.hx"));
var args = ["Main"];
runHaxe(args, () -> {
assertSuccess();

function doTest() {
runHaxeJsonCb(args, DisplayMethods.Hover, {file: new FsPath("Main.hx"), offset: transform.offset(1)}, (res) -> {
// No error during hover
Assert.pass();
}, () -> {
assertSuccess();
async.done();
});
}

if (invalidate) {
runHaxeJson(args, ServerMethods.Invalidate, {file: new FsPath("Main.hx")}, () -> {
doTest();
});
} else {
doTest();
}
});
}
}
101 changes: 50 additions & 51 deletions tests/server/src/utils/macro/TestBuilder.macro.hx
Original file line number Diff line number Diff line change
Expand Up @@ -16,68 +16,67 @@ class TestBuilder {
continue;
}
switch (field.kind) {
case FFun(f) if (field.meta.exists(m -> m.name == ":async")):
// Async is already manually handled, nothing to do

case FFun(f):
var isProcessed = field.meta.exists(m -> m.name == ":async");
var variants = field.meta.filter(m -> m.name == ":variant");
if (variants.length == 0) {
makeAsyncTest(f, field.pos);
} else {
// TODO: support functions that define their own async arg (not named `_` or `async`)
var args = f.args.copy();
f.args = [];
makeAsyncTest(f, field.pos);
if (!isProcessed) makeAsyncTest(f, field.pos);
continue;
}

// Ignore original field; generate variants instead
removedFields.push(field);
var args = f.args.copy();
f.args = [];
if (!isProcessed) makeAsyncTest(f, field.pos);

for (variant in variants) {
if (variant.params.length == 0) {
Context.error('Unexpected amount of variant parameters.', variant.pos);
}

var nameParam = variant.params.shift();
var name:String = try haxe.macro.ExprTools.getValue(nameParam) catch(e) {
Context.error('Variant first parameter should be a String (variant name)', nameParam.pos);
};
// Ignore original field; generate variants instead
removedFields.push(field);

var inits = [for (arg in args) {
var name = arg.name;
var ct = arg.type;
for (variant in variants) {
if (variant.params.length == 0) {
Context.error('Unexpected amount of variant parameters.', variant.pos);
}

if (variant.params.length == 0) {
Context.error('Unexpected amount of variant parameters.', variant.pos);
}
var nameParam = variant.params.shift();
var name:String = try haxe.macro.ExprTools.getValue(nameParam) catch(e) {
Context.error('Variant first parameter should be a String (variant name)', nameParam.pos);
};

var param = variant.params.shift();
macro @:pos(param.pos) var $name:$ct = (($name:$ct) -> $i{name})(${param});
}];
var inits = [for (arg in args) {
var name = arg.name;
if (isProcessed && name == "async") continue;
var ct = arg.type;

if (variant.params.length > 0) {
Context.error('Unexpected amount of variant parameters.', variant.params[0].pos);
if (variant.params.length == 0) {
Context.error('Unexpected amount of variant parameters.', variant.pos);
}

switch (f.expr.expr) {
case EBlock(b):
var ff = {
ret: f.ret,
params: f.params,
expr: {pos: variant.pos, expr: EBlock(inits.concat(b))},
args: [{name: "async", type: macro:utest.Async}]
};

newFields.push({
pos: variant.pos,
name: field.name + name,
meta: field.meta.filter(m -> m.name != ":variant"),
kind: FFun(ff),
doc: field.doc,
access : field.access
});

case _:
}
var param = variant.params.shift();
macro @:pos(param.pos) var $name:$ct = (($name:$ct) -> $i{name})(${param});
}];

if (variant.params.length > 0) {
Context.error('Unexpected amount of variant parameters.', variant.params[0].pos);
}

switch (f.expr.expr) {
case EBlock(b):
var ff = {
ret: f.ret,
params: f.params,
expr: {pos: variant.pos, expr: EBlock(inits.concat(b))},
args: [{name: "async", type: macro:utest.Async}]
};

newFields.push({
pos: variant.pos,
name: field.name + name,
meta: field.meta.filter(m -> m.name != ":variant"),
kind: FFun(ff),
doc: field.doc,
access : field.access
});

case _:
}
}
case _:
Expand Down
20 changes: 20 additions & 0 deletions tests/server/test/templates/issues/Issue11995/Macro.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import haxe.macro.Context;
using Lambda;

class Macro {
public static function bar() {
var fields = Context.getBuildFields();

switch fields.find(f -> f.name == "foo").kind {
case FFun(f):
f.expr = macro {
var baz:String = "hello";
${f.expr}
};

default: throw "assert";
}

return fields;
}
}
6 changes: 6 additions & 0 deletions tests/server/test/templates/issues/Issue11995/Main.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@:build(Macro.bar())
class Main {
static function foo() {
trace(ba{-1-}z);
}
}
Loading