SourceInfo info = makeSourceInfo(x);
MethodBinding b = x.binding;
assert b.isConstructor();
JConstructor ctor = (JConstructor) typeMap.get(b);
JMethodCall call = new JNewInstance(info, ctor, curClass.type);
JExpression qualExpr = pop(qualifier);
// Enums: hidden arguments for the name and id.
if (x.enumConstant != null) {
call.addArgs(getStringLiteral(info, x.enumConstant.name), JIntLiteral
.get(x.enumConstant.binding.original().id));
}
// Synthetic args for inner classes
ReferenceBinding targetBinding = (ReferenceBinding) b.declaringClass.erasure();
NestedTypeBinding nestedBinding = null;
if (targetBinding.isNestedType() && !targetBinding.isStatic()) {
nestedBinding = (NestedTypeBinding) targetBinding;
}
if (nestedBinding != null) {
// Synthetic this args for inner classes
if (nestedBinding.enclosingInstances != null) {
ReferenceBinding checkedTargetType =
targetBinding.isAnonymousType() ? (ReferenceBinding) targetBinding.superclass()
.erasure() : targetBinding;
ReferenceBinding targetEnclosingType = checkedTargetType.enclosingType();
for (SyntheticArgumentBinding arg : nestedBinding.enclosingInstances) {
TypeBinding argType = arg.type.erasure();
if (qualifier != null && argType == targetEnclosingType) {
call.addArg(qualExpr);
} else {
JExpression thisRef =
makeThisReference(info, (ReferenceBinding) argType, false, scope);
call.addArg(thisRef);
}
}
}
}
// Plain old regular user arguments
call.addArgs(arguments);
// Synthetic args for inner classes
if (nestedBinding != null) {
// Synthetic locals for local classes
if (nestedBinding.outerLocalVariables != null) {
for (SyntheticArgumentBinding arg : nestedBinding.outerLocalVariables) {
LocalVariableBinding targetVariable = arg.actualOuterLocalVariable;
VariableBinding[] path = scope.getEmulationPath(targetVariable);
assert path.length == 1;
if (curMethod.scope.isInsideInitializer()
&& path[0] instanceof SyntheticArgumentBinding) {
SyntheticArgumentBinding sb = (SyntheticArgumentBinding) path[0];
JField field = curClass.syntheticFields.get(sb);
assert field != null;
call.addArg(makeInstanceFieldRef(info, field));
} else if (path[0] instanceof LocalVariableBinding) {
JExpression localRef = makeLocalRef(info, (LocalVariableBinding) path[0]);
call.addArg(localRef);
} else if (path[0] instanceof FieldBinding) {
JField field = typeMap.get((FieldBinding) path[0]);
assert field != null;
call.addArg(makeInstanceFieldRef(info, field));
} else {
throw new InternalCompilerException("Unknown emulation path.");
}
}
}
}
if (ctor.getEnclosingType() == javaLangString) {
/*
* MAGIC: java.lang.String is implemented as a JavaScript String
* primitive with a modified prototype. This requires funky handling of
* constructor calls. We find a method named _String() whose signature
* matches the requested constructor
*
* TODO(scottb): consider moving this to a later pass.
*/
MethodBinding staticBinding =
targetBinding.getExactMethod(_STRING, b.parameters, curCud.scope);
assert staticBinding.isStatic();
JMethod staticMethod = typeMap.get(staticBinding);
JMethodCall newCall = new JMethodCall(info, null, staticMethod);
newCall.addArgs(call.getArgs());
call = newCall;
}
push(call);
}