* The order of emulation is: - assign all synthetic fields from synthetic
* args - call our super constructor emulation method - call our instance
* initializer emulation method - run user code
*/
void processConstructor(ConstructorDeclaration x) {
JConstructor ctor = (JConstructor) typeMap.get(x.binding);
try {
processHasAnnotations(ctor, x.annotations);
SourceInfo info = ctor.getSourceInfo();
currentMethod = ctor;
currentMethodBody = ctor.getBody();
currentMethodScope = x.scope;
/*
* Determine if we have an explicit this call. The presence of an
* explicit this call indicates we can skip certain initialization steps
* (as the callee will perform those steps for us). These skippable
* steps are 1) assigning synthetic args to fields and 2) running
* initializers.
*/
boolean hasExplicitThis = (x.constructorCall != null)
&& !x.constructorCall.isSuperAccess();
JClassType enclosingType = ctor.getEnclosingType();
JBlock block = currentMethodBody.getBlock();
currentOuterThisRefParams = Maps.create();
/*
* All synthetic fields must be assigned, unless we have an explicit
* this constructor call, in which case the callee will assign them for
* us.
*/
ReferenceBinding declaringClass = x.binding.declaringClass;
if (declaringClass instanceof NestedTypeBinding) {
Iterator<JParameter> paramIt = currentMethod.getParams().iterator();
NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
if (nestedBinding.enclosingInstances != null) {
for (SyntheticArgumentBinding arg : nestedBinding.enclosingInstances) {
JParameter param = paramIt.next();
JField field = (JField) typeMap.get(arg);
if (!hasExplicitThis) {
block.addStmt(JProgram.createAssignmentStmt(info,
createVariableRef(info, field),
createVariableRef(info, param)));
}
currentOuterThisRefParams = Maps.put(currentOuterThisRefParams,
field, param);
}
}
if (!hasExplicitThis) {
paramIt = getSyntheticLocalsIterator();
if (nestedBinding.outerLocalVariables != null) {
for (SyntheticArgumentBinding arg : nestedBinding.outerLocalVariables) {
JParameter param = paramIt.next();
JField field = (JField) typeMap.get(arg);
block.addStmt(JProgram.createAssignmentStmt(info,
createVariableRef(info, field),
createVariableRef(info, param)));
}
}
}
}
// optional this or super constructor call
if (x.constructorCall != null) {
JMethodCall superOrThisCall = (JMethodCall) dispatch(
"processExpression", x.constructorCall);
// Enums: wire up synthetic name/ordinal params to the super method.
if (enclosingType.isEnumOrSubclass() != null) {
JVariableRef enumNameRef = createVariableRef(
superOrThisCall.getSourceInfo(), ctor.getParams().get(0));
superOrThisCall.addArg(0, enumNameRef);
JVariableRef enumOrdinalRef = createVariableRef(
superOrThisCall.getSourceInfo(), ctor.getParams().get(1));
superOrThisCall.addArg(1, enumOrdinalRef);
}
superOrThisCall.setStaticDispatchOnly();
block.addStmt(superOrThisCall.makeStatement());