* correctly on some browsers.
*/
@Override
public boolean visit(JsInvocation x, JsContext<JsExpression> ctx) {
if (x.getQualifier() instanceof JsNameRef) {
JsNameRef ref = (JsNameRef) x.getQualifier();
String ident = ref.getIdent();
if (ident.startsWith("@")) {
int dispId = dispatchInfo.getDispId(ident);
Member member;
if (dispId < 0) {
member = null;
} else {
member = dispatchInfo.getClassInfoByDispId(dispId).getMember(dispId);
}
/*
* Make sure the ident is a reference to a method or constructor and
* not a reference to a field whose contents (e.g. a Function) we
* intend to immediately invoke.
*
* p.C::method()(); versus p.C::field();
*
* Also, if the reference was to a non-existent field, we'll go ahead
* and rewrite the call site as though -1 is a valid dispid.
*/
if (member == null || member instanceof Method
|| member instanceof Constructor) {
// Use a clone instead of modifying the original JSNI
// __gwt_makeJavaInvoke(paramCount)(obj, dispId, args)
int paramCount = 0;
if (member instanceof Method) {
paramCount = ((Method) member).getParameterTypes().length;
} else if (member instanceof Constructor) {
paramCount = ((Constructor<?>) member).getParameterTypes().length;
}
SourceInfo newSourceInfo = x.getSourceInfo().makeChild(getClass(),
"Replace JSNI ref for hosted mode");
JsInvocation inner = new JsInvocation(newSourceInfo);
inner.setQualifier(new JsNameRef(newSourceInfo,
"__gwt_makeJavaInvoke"));
inner.getArguments().add(program.getNumberLiteral(paramCount));
JsInvocation outer = new JsInvocation(newSourceInfo);
outer.setQualifier(inner);
JsExpression q = ref.getQualifier();
if (q == null) {
q = program.getNullLiteral();
}
List<JsExpression> arguments = outer.getArguments();
arguments.add(q);