}
for (JsniMethodRef ref : x.getJsniMethodRefs()) {
jsniMap.put(ref.getIdent(), ref.getTarget());
}
final JsFunction jsFunc = x.getFunc();
// replace all JSNI idents with a real JsName now that we know it
new JsModVisitor() {
/**
* Marks a ctor that is a direct child of an invocation. Instead of
* replacing the ctor with a tear-off, we replace the invocation with a
* new operation.
*/
private JsNameRef dontReplaceCtor;
@Override
public void endVisit(JsInvocation x, JsContext ctx) {
// Replace invocation to ctor with a new op.
if (x.getQualifier() instanceof JsNameRef) {
JsNameRef ref = (JsNameRef) x.getQualifier();
String ident = ref.getIdent();
if (isJsniIdent(ident)) {
JNode node = jsniMap.get(ident);
assert node instanceof JConstructor;
assert ref.getQualifier() == null;
JsName jsName = names.get(node);
assert (jsName != null);
ref.resolve(jsName);
JsNew jsNew = new JsNew(x.getSourceInfo(), ref);
jsNew.getArguments().addAll(x.getArguments());
ctx.replaceMe(jsNew);
}
}
}
@Override
public void endVisit(JsNameRef x, JsContext ctx) {
String ident = x.getIdent();
if (isJsniIdent(ident)) {
JNode node = jsniMap.get(ident);
assert (node != null);
if (node instanceof JField) {
JField field = (JField) node;
JsName jsName = names.get(field);
assert (jsName != null);
x.resolve(jsName);
// See if we need to add a clinit call to a static field ref
JsInvocation clinitCall = maybeCreateClinitCall(field);
if (clinitCall != null) {
JsExpression commaExpr = createCommaExpression(clinitCall, x);
ctx.replaceMe(commaExpr);
}
} else if (node instanceof JConstructor) {
if (x == dontReplaceCtor) {
// Do nothing, parent will handle.
} else {
// Replace with a local closure function.
// function(a,b,c){return new Obj(a,b,c);}
JConstructor ctor = (JConstructor) node;
JsName jsName = names.get(ctor);
assert (jsName != null);
x.resolve(jsName);
SourceInfo info = x.getSourceInfo();
JsFunction closureFunc = new JsFunction(info, jsFunc.getScope());
for (JParameter p : ctor.getParams()) {
JsName name = closureFunc.getScope().declareName(p.getName());
closureFunc.getParameters().add(new JsParameter(info, name));
}
JsNew jsNew = new JsNew(info, x);
for (JsParameter p : closureFunc.getParameters()) {
jsNew.getArguments().add(p.getName().makeRef(info));
}
JsBlock block = new JsBlock(info);
block.getStatements().add(new JsReturn(info, jsNew));
closureFunc.setBody(block);
ctx.replaceMe(closureFunc);
}
} else {
JMethod method = (JMethod) node;
if (x.getQualifier() == null) {