cincheo / jsweet

A Java to JavaScript transpiler.
http://www.jsweet.org
Other
1.46k stars 160 forks source link

Non deterministic behavior in Transpiler PrinterAdapter #545

Open iffyio opened 4 years ago

iffyio commented 4 years ago

Hi!

I have a usecase that involves accounting for untyped access in a source file. I figured extending the transpiler by overriding PrinterAdapter might work but it seems JSweetTranspiler has troubles reporting substitutions in some cases, at least the def.js.Object package.

As a repro, here is an adapter that wishes to substitute Class and MethodInvocation access.

...
public boolean substituteNewClass(NewClassElement newClass) {
    System.out.println("CLASS " + newClass);
    return super.substituteNewClass(newClass);
}
public boolean substituteMethodInvocation(MethodInvocationElement invocation) {
    System.out.println("METHOD " + invocation);
    return super.substituteMethodInvocation(invocation);
}

The following code works as expected, we get notified of a new class:

Object obj = new def.js.Object();
// CLASS new def.js.Object()

But nothing gets reported for the following:

Object obj = new def.js.Object(){{}};
// empty

Object obj = new def.js.Object(){{
    $set("x", 1);
}};
// also empty ( expected 'CLASS ...' and 'METHOD ...' )

The next is somewhat stranger, adding a $get throws an exception but combining $get with an arbitrary method invocation not only does not throw, it causes the transpiler to report the expected substitutions.

def.js.Object obj = new def.js.Object(){{
    $set("x", 1);
    $get("v");
}};

// ERROR output:55 - invalid initializer statement; only field assignments are allowed at ...

def.js.Object obj = new def.js.Object(){{
    $set("x", 1);
    $get("v");
    hasOwnProperty("b");
}};

// METHOD $set("x", 1)
// METHOD $get("v")
// METHOD hasOwnProperty("b")

Have I missed something here? e.g if it's some special behavior for instance initializers? The observed behavior doesn't seem deterministic.