diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
index 6cf609c4f1..1c5db34bcf 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
@@ -293,33 +293,37 @@ private JsniReferenceCollector(JsniMethodBody nativeMethodBody) {
@Override
public void endVisit(JsNameRef x, JsContext ctx) {
- if (!x.isJsniReference()) {
- return;
- }
- String ident = x.getIdent();
- Binding binding = jsniRefs.get(ident);
- SourceInfo info = x.getSourceInfo();
- assert binding != null;
- if (binding instanceof TypeBinding) {
- JType type = typeMap.get((TypeBinding) binding);
- processClassLiteral(x, info, type, ctx);
- } else if (binding instanceof FieldBinding) {
- FieldBinding fieldBinding = (FieldBinding) binding;
- if (isOptimizableCompileTimeConstant(fieldBinding)) {
- // Replace any compile-time constants with the constant value of the field.
- assert !ctx.isLvalue();
- JExpression constant = getConstant(info, fieldBinding.constant());
- JsExpression result = JjsUtils.translateLiteral((JLiteral) constant);
- assert (result != null);
- ctx.replaceMe(result);
+ try {
+ if (!x.isJsniReference()) {
+ return;
+ }
+ String ident = x.getIdent();
+ Binding binding = jsniRefs.get(ident);
+ SourceInfo info = x.getSourceInfo();
+ assert binding != null;
+ if (binding instanceof TypeBinding) {
+ JType type = typeMap.get((TypeBinding) binding);
+ processClassLiteral(x, info, type, ctx);
+ } else if (binding instanceof FieldBinding) {
+ FieldBinding fieldBinding = (FieldBinding) binding;
+ if (isOptimizableCompileTimeConstant(fieldBinding)) {
+ // Replace any compile-time constants with the constant value of the field.
+ assert !ctx.isLvalue();
+ JExpression constant = getConstant(info, fieldBinding.constant());
+ JsExpression result = JjsUtils.translateLiteral((JLiteral) constant);
+ assert (result != null);
+ ctx.replaceMe(result);
+ } else {
+ // Normal: create a jsniRef.
+ JField field = typeMap.get(fieldBinding);
+ processField(x, info, field, ctx);
+ }
} else {
- // Normal: create a jsniRef.
- JField field = typeMap.get(fieldBinding);
- processField(x, info, field, ctx);
+ JMethod method = typeMap.get((MethodBinding) binding);
+ processMethod(x, info, method);
}
- } else {
- JMethod method = typeMap.get((MethodBinding) binding);
- processMethod(x, info, method);
+ } catch (Throwable e) {
+ throw translateException(x, e);
}
}
@@ -946,113 +950,117 @@ public void endVisit(FloatLiteral x, BlockScope scope) {
@Override
public void endVisit(ForeachStatement x, BlockScope scope) {
- SourceInfo info = makeSourceInfo(x);
-
- JBlock body = popBlock(info, x.action);
- JExpression collection = pop(x.collection);
- JDeclarationStatement elementDecl = pop(x.elementVariable);
- assert (elementDecl.initializer == null);
+ try {
+ SourceInfo info = makeSourceInfo(x);
- JLocal elementVar = (JLocal) curMethod.locals.get(x.elementVariable.binding);
- String elementVarName = elementVar.getName();
+ JBlock body = popBlock(info, x.action);
+ JExpression collection = pop(x.collection);
+ JDeclarationStatement elementDecl = pop(x.elementVariable);
+ assert (elementDecl.initializer == null);
+
+ JLocal elementVar = (JLocal) curMethod.locals.get(x.elementVariable.binding);
+ String elementVarName = elementVar.getName();
+
+ JForStatement result;
+ if (x.collectionVariable != null) {
+ /**
+ *
+ * for (final T[] i$array = collection,
+ * int i$index = 0,
+ * final int i$max = i$array.length;
+ * i$index < i$max; ++i$index) {
+ * T elementVar = i$array[i$index];
+ * // user action
+ * }
+ *
+ */
+ JLocal arrayVar = JProgram.createLocal(info, elementVarName + "$array",
+ typeMap.get(x.collection.resolvedType), true, curMethod.body);
+ JLocal indexVar =
+ JProgram.createLocal(info, elementVarName + "$index", JPrimitiveType.INT, false,
+ curMethod.body);
+ JLocal maxVar =
+ JProgram.createLocal(info, elementVarName + "$max", JPrimitiveType.INT, true,
+ curMethod.body);
+
+ List initializers = Lists.newArrayListWithCapacity(3);
+ // T[] i$array = arr
+ initializers.add(makeDeclaration(info, arrayVar, collection));
+ // int i$index = 0
+ initializers.add(makeDeclaration(info, indexVar, JIntLiteral.get(0)));
+ // int i$max = i$array.length
+ initializers.add(makeDeclaration(info, maxVar,
+ new JArrayLength(info, arrayVar.makeRef(info))));
+
+ // i$index < i$max
+ JExpression condition =
+ new JBinaryOperation(info, JPrimitiveType.BOOLEAN, JBinaryOperator.LT,
+ indexVar.makeRef(info), maxVar.makeRef(info));
+
+ // ++i$index
+ JExpression increments = new JPrefixOperation(info, JUnaryOperator.INC,
+ indexVar.makeRef(info));
+
+ // T elementVar = i$array[i$index];
+ elementDecl.initializer =
+ new JArrayRef(info, arrayVar.makeRef(info), indexVar.makeRef(info));
+ body.addStmt(0, elementDecl);
+
+ result = new JForStatement(info, initializers, condition, increments, body);
+ } else {
+ /**
+ *
+ * for (Iterator<T> i$iterator = collection.iterator(); i$iterator.hasNext();) {
+ * T elementVar = i$iterator.next();
+ * // user action
+ * }
+ *
+ */
+ CompilationUnitScope cudScope = scope.compilationUnitScope();
+ ReferenceBinding javaUtilIterator = scope.getJavaUtilIterator();
+ ReferenceBinding javaLangIterable = scope.getJavaLangIterable();
+ MethodBinding iterator = javaLangIterable.getExactMethod(ITERATOR_, NO_TYPES, cudScope);
+ MethodBinding hasNext = javaUtilIterator.getExactMethod(HAS_NEXT_, NO_TYPES, cudScope);
+ MethodBinding next = javaUtilIterator.getExactMethod(NEXT_, NO_TYPES, cudScope);
+ JLocal iteratorVar =
+ JProgram.createLocal(info, (elementVarName + "$iterator"), typeMap
+ .get(javaUtilIterator), false, curMethod.body);
+
+ List initializers = Lists.newArrayListWithCapacity(1);
+ // Iterator i$iterator = collection.iterator()
+ initializers.add(makeDeclaration(info, iteratorVar, new JMethodCall(info, collection,
+ typeMap.get(iterator))));
+
+ // i$iterator.hasNext()
+ JExpression condition =
+ new JMethodCall(info, iteratorVar.makeRef(info), typeMap.get(hasNext));
+
+ // T elementVar = (T) i$iterator.next();
+ elementDecl.initializer =
+ new JMethodCall(info, iteratorVar.makeRef(info), typeMap.get(next));
+
+ // Perform any implicit reference type casts (due to generics).
+ // Note this occurs before potential unboxing.
+ if (elementVar.getType() != javaLangObject) {
+ TypeBinding collectionElementType = getCollectionElementTypeBinding(x);
+ JType toType = typeMap.get(collectionElementType);
+ assert (toType instanceof JReferenceType);
+ elementDecl.initializer = maybeCast(toType, elementDecl.initializer);
+ }
- JForStatement result;
- if (x.collectionVariable != null) {
- /**
- *
- * for (final T[] i$array = collection,
- * int i$index = 0,
- * final int i$max = i$array.length;
- * i$index < i$max; ++i$index) {
- * T elementVar = i$array[i$index];
- * // user action
- * }
- *
- */
- JLocal arrayVar = JProgram.createLocal(info, elementVarName + "$array",
- typeMap.get(x.collection.resolvedType), true, curMethod.body);
- JLocal indexVar =
- JProgram.createLocal(info, elementVarName + "$index", JPrimitiveType.INT, false,
- curMethod.body);
- JLocal maxVar =
- JProgram.createLocal(info, elementVarName + "$max", JPrimitiveType.INT, true,
- curMethod.body);
-
- List initializers = Lists.newArrayListWithCapacity(3);
- // T[] i$array = arr
- initializers.add(makeDeclaration(info, arrayVar, collection));
- // int i$index = 0
- initializers.add(makeDeclaration(info, indexVar, JIntLiteral.get(0)));
- // int i$max = i$array.length
- initializers.add(makeDeclaration(info, maxVar,
- new JArrayLength(info, arrayVar.makeRef(info))));
-
- // i$index < i$max
- JExpression condition =
- new JBinaryOperation(info, JPrimitiveType.BOOLEAN, JBinaryOperator.LT,
- indexVar.makeRef(info), maxVar.makeRef(info));
-
- // ++i$index
- JExpression increments = new JPrefixOperation(info, JUnaryOperator.INC,
- indexVar.makeRef(info));
-
- // T elementVar = i$array[i$index];
- elementDecl.initializer =
- new JArrayRef(info, arrayVar.makeRef(info), indexVar.makeRef(info));
- body.addStmt(0, elementDecl);
+ body.addStmt(0, elementDecl);
- result = new JForStatement(info, initializers, condition, increments, body);
- } else {
- /**
- *
- * for (Iterator<T> i$iterator = collection.iterator(); i$iterator.hasNext();) {
- * T elementVar = i$iterator.next();
- * // user action
- * }
- *
- */
- CompilationUnitScope cudScope = scope.compilationUnitScope();
- ReferenceBinding javaUtilIterator = scope.getJavaUtilIterator();
- ReferenceBinding javaLangIterable = scope.getJavaLangIterable();
- MethodBinding iterator = javaLangIterable.getExactMethod(ITERATOR_, NO_TYPES, cudScope);
- MethodBinding hasNext = javaUtilIterator.getExactMethod(HAS_NEXT_, NO_TYPES, cudScope);
- MethodBinding next = javaUtilIterator.getExactMethod(NEXT_, NO_TYPES, cudScope);
- JLocal iteratorVar =
- JProgram.createLocal(info, (elementVarName + "$iterator"), typeMap
- .get(javaUtilIterator), false, curMethod.body);
-
- List initializers = Lists.newArrayListWithCapacity(1);
- // Iterator i$iterator = collection.iterator()
- initializers.add(makeDeclaration(info, iteratorVar, new JMethodCall(info, collection,
- typeMap.get(iterator))));
-
- // i$iterator.hasNext()
- JExpression condition =
- new JMethodCall(info, iteratorVar.makeRef(info), typeMap.get(hasNext));
-
- // T elementVar = (T) i$iterator.next();
- elementDecl.initializer =
- new JMethodCall(info, iteratorVar.makeRef(info), typeMap.get(next));
-
- // Perform any implicit reference type casts (due to generics).
- // Note this occurs before potential unboxing.
- if (elementVar.getType() != javaLangObject) {
- TypeBinding collectionElementType = getCollectionElementTypeBinding(x);
- JType toType = typeMap.get(collectionElementType);
- assert (toType instanceof JReferenceType);
- elementDecl.initializer = maybeCast(toType, elementDecl.initializer);
+ result = new JForStatement(info, initializers, condition,
+ null, body);
}
- body.addStmt(0, elementDecl);
-
- result = new JForStatement(info, initializers, condition,
- null, body);
+ // May need to box or unbox the element assignment.
+ elementDecl.initializer =
+ maybeBoxOrUnbox(elementDecl.initializer, x.elementVariableImplicitWidening);
+ push(result);
+ } catch (Throwable e) {
+ throw translateException(x, e);
}
-
- // May need to box or unbox the element assignment.
- elementDecl.initializer =
- maybeBoxOrUnbox(elementDecl.initializer, x.elementVariableImplicitWidening);
- push(result);
}
@Override
@@ -1211,54 +1219,62 @@ public void endVisit(LabeledStatement x, BlockScope scope) {
@Override
public boolean visit(ReferenceExpression x, BlockScope blockScope) {
- // T[][][]::new => lambda$n(int x) { return new T[int x][][]; }
- if (x.isArrayConstructorReference()) {
- // ensure array[]::new synthetic method (created by JDT) has an associated JMethod
- JMethod synthMethod = typeMap.get(x.binding);
- if (synthMethod.getBody() == null) {
- JMethodBody body = new JMethodBody(synthMethod.getSourceInfo());
- List dims = new ArrayList();
- JArrayType arrayType = (JArrayType) synthMethod.getType();
- JParameter dimParam = synthMethod.getParams().get(0);
- JExpression dimArgExpr = dimParam.makeRef(dimParam.getSourceInfo());
- dims.add(dimArgExpr);
- JNewArray newArray = JNewArray.createArrayWithDimensionExpressions(
- synthMethod.getSourceInfo(), arrayType, dims);
- body.getBlock().addStmt(newArray.makeReturnStatement());
- synthMethod.setBody(body);
+ try {
+ // T[][][]::new => lambda$n(int x) { return new T[int x][][]; }
+ if (x.isArrayConstructorReference()) {
+ // ensure array[]::new synthetic method (created by JDT) has an associated JMethod
+ JMethod synthMethod = typeMap.get(x.binding);
+ if (synthMethod.getBody() == null) {
+ JMethodBody body = new JMethodBody(synthMethod.getSourceInfo());
+ List dims = new ArrayList();
+ JArrayType arrayType = (JArrayType) synthMethod.getType();
+ JParameter dimParam = synthMethod.getParams().get(0);
+ JExpression dimArgExpr = dimParam.makeRef(dimParam.getSourceInfo());
+ dims.add(dimArgExpr);
+ JNewArray newArray = JNewArray.createArrayWithDimensionExpressions(
+ synthMethod.getSourceInfo(), arrayType, dims);
+ body.getBlock().addStmt(newArray.makeReturnStatement());
+ synthMethod.setBody(body);
+ }
}
- }
- if (hasQualifier(x)) {
- x.lhs.traverse(this, blockScope);
+ if (hasQualifier(x)) {
+ x.lhs.traverse(this, blockScope);
+ }
+ return false;
+ } catch (Throwable e) {
+ throw translateException(x, e);
}
- return false;
}
@Override
public boolean visit(LambdaExpression x, BlockScope blockScope) {
- // Fetch the variables 'captured' by this lambda
- SyntheticArgumentBinding[] synthArgs = x.outerLocalVariables;
- // Get the parameter names, captured locals + lambda arguments
- String paramNames[] = computeCombinedParamNames(x, synthArgs);
- SourceInfo info = makeSourceInfo(x);
- // JDT synthesizes a method lambda$n(capture1, capture2, ..., lambda_arg1, lambda_arg2, ...)
- // Here we create a JMethod from this
- JMethod lambdaMethod = createMethodFromBinding(info, x.binding, paramNames);
- // Because the lambda implementations is synthesized as a static method in the
- // enclosing class, it needs to be adjusted if that class happens to be a JsType.
- lambdaMethod.setJsMemberInfo(HasJsInfo.JsMemberType.NONE, null, null, false);
- if (curClass.type.isJsNative()) {
- lambdaMethod.setJsOverlay();
- }
- JMethodBody methodBody = new JMethodBody(info);
- lambdaMethod.setBody(methodBody);
- // We need to push this method on the stack as it introduces a scope, and
- // expressions in the body need to lookup variable refs like parameters from it
- pushMethodInfo(new MethodInfo(lambdaMethod, methodBody, x.scope));
- pushLambdaExpressionLocalsIntoMethodScope(x, synthArgs, lambdaMethod);
- // now the body of the lambda is processed
- return true;
+ try {
+ // Fetch the variables 'captured' by this lambda
+ SyntheticArgumentBinding[] synthArgs = x.outerLocalVariables;
+ // Get the parameter names, captured locals + lambda arguments
+ String paramNames[] = computeCombinedParamNames(x, synthArgs);
+ SourceInfo info = makeSourceInfo(x);
+ // JDT synthesizes a method lambda$n(capture1, capture2, ..., lambda_arg1, lambda_arg2, ...)
+ // Here we create a JMethod from this
+ JMethod lambdaMethod = createMethodFromBinding(info, x.binding, paramNames);
+ // Because the lambda implementations is synthesized as a static method in the
+ // enclosing class, it needs to be adjusted if that class happens to be a JsType.
+ lambdaMethod.setJsMemberInfo(HasJsInfo.JsMemberType.NONE, null, null, false);
+ if (curClass.type.isJsNative()) {
+ lambdaMethod.setJsOverlay();
+ }
+ JMethodBody methodBody = new JMethodBody(info);
+ lambdaMethod.setBody(methodBody);
+ // We need to push this method on the stack as it introduces a scope, and
+ // expressions in the body need to lookup variable refs like parameters from it
+ pushMethodInfo(new MethodInfo(lambdaMethod, methodBody, x.scope));
+ pushLambdaExpressionLocalsIntoMethodScope(x, synthArgs, lambdaMethod);
+ // now the body of the lambda is processed
+ return true;
+ } catch (Throwable e) {
+ throw translateException(x, e);
+ }
}
private void pushLambdaExpressionLocalsIntoMethodScope(LambdaExpression x,
@@ -1310,80 +1326,84 @@ private String nameForSyntheticArgument(SyntheticArgumentBinding synthArg) {
@Override
public void endVisit(LambdaExpression x, BlockScope blockScope) {
- /**
- * Our output of a (args) -> expression_using_locals(locals) looks like this.
- *
- * class Enclosing {
- *
- * T lambda$0(locals, args) {...lambda expr }
- *
- * class lambda$0$type implements I {
- * ctor([outer], locals) { ... }
- * R (args) { return [outer].lambda$0(locals, args); }
- * }
- * }
- *
- * And replaces the lambda with new lambda$0$Type([outer this], captured locals...).
- */
+ try {
+ /**
+ * Our output of a (args) -> expression_using_locals(locals) looks like this.
+ *
+ * class Enclosing {
+ *
+ * T lambda$0(locals, args) {...lambda expr }
+ *
+ * class lambda$0$type implements I {
+ * ctor([outer], locals) { ... }
+ * R (args) { return [outer].lambda$0(locals, args); }
+ * }
+ * }
+ *
+ * And replaces the lambda with new lambda$0$Type([outer this], captured locals...).
+ */
- // The target accepting this lambda is looking for which type? (e.g. ClickHandler, Runnable)
- TypeBinding binding = x.expectedType();
- // Find the single abstract method of this interface
- MethodBinding samBinding = binding.getSingleAbstractMethod(blockScope, false);
- assert (samBinding != null && samBinding.isValidBinding());
-
- // Lookup the JMethod version
- JMethod interfaceMethod = typeMap.get(samBinding);
- // And its JInterface container we must implement
- // There may be more than more JInterface containers to be implemented
- // if the lambda expression is cast to a IntersectionCastType.
- JInterfaceType[] lambdaInterfaces = getInterfacesToImplement(binding);
- SourceInfo info = makeSourceInfo(x);
+ // The target accepting this lambda is looking for which type? (e.g. ClickHandler, Runnable)
+ TypeBinding binding = x.expectedType();
+ // Find the single abstract method of this interface
+ MethodBinding samBinding = binding.getSingleAbstractMethod(blockScope, false);
+ assert (samBinding != null && samBinding.isValidBinding());
+
+ // Lookup the JMethod version
+ JMethod interfaceMethod = typeMap.get(samBinding);
+ // And its JInterface container we must implement
+ // There may be more than more JInterface containers to be implemented
+ // if the lambda expression is cast to a IntersectionCastType.
+ JInterfaceType[] lambdaInterfaces = getInterfacesToImplement(binding);
+ SourceInfo info = makeSourceInfo(x);
- // Create an inner class to implement the interface and SAM method.
- // class lambda$0$Type implements T {}
+ // Create an inner class to implement the interface and SAM method.
+ // class lambda$0$Type implements T {}
- String innerLambdaImplementationClassShortName = String.valueOf(x.binding.selector);
- JClassType innerLambdaClass = createInnerClass(curClass.getClassOrInterface(),
- innerLambdaImplementationClassShortName, info, lambdaInterfaces);
- JConstructor ctor = new JConstructor(info, innerLambdaClass, AccessModifier.PRIVATE);
+ String innerLambdaImplementationClassShortName = String.valueOf(x.binding.selector);
+ JClassType innerLambdaClass = createInnerClass(curClass.getClassOrInterface(),
+ innerLambdaImplementationClassShortName, info, lambdaInterfaces);
+ JConstructor ctor = new JConstructor(info, innerLambdaClass, AccessModifier.PRIVATE);
- // locals captured by the lambda and saved as fields on the anonymous inner class
- List locals = new ArrayList();
- SyntheticArgumentBinding[] synthArgs = x.outerLocalVariables;
+ // locals captured by the lambda and saved as fields on the anonymous inner class
+ List locals = new ArrayList();
+ SyntheticArgumentBinding[] synthArgs = x.outerLocalVariables;
- // create the constructor for the anonymous inner and return the field used to store the
- // enclosing 'this' which is needed by the SAM method implementation later
- JField outerField =
- createLambdaConstructor(x, info, innerLambdaClass, ctor, locals, synthArgs);
+ // create the constructor for the anonymous inner and return the field used to store the
+ // enclosing 'this' which is needed by the SAM method implementation later
+ JField outerField =
+ createLambdaConstructor(x, info, innerLambdaClass, ctor, locals, synthArgs);
- // the method containing the lambda expression that the anonymous inner class delegates to,
- // it corresponds directly to the lambda expression itself, produced by JDT as a helper method
- JMethod lambdaMethod = createLambdaMethod(x);
+ // the method containing the lambda expression that the anonymous inner class delegates to,
+ // it corresponds directly to the lambda expression itself, produced by JDT as a helper method
+ JMethod lambdaMethod = createLambdaMethod(x);
- // Now that we've added an implementation method for the lambda, we must create the inner
- // class method that implements the target interface type that delegates to the target lambda
- // method
- JMethod samMethod = new JMethod(info, interfaceMethod.getName(), innerLambdaClass,
- interfaceMethod.getType(), false, false, true, interfaceMethod.getAccess());
- samMethod.setSynthetic();
+ // Now that we've added an implementation method for the lambda, we must create the inner
+ // class method that implements the target interface type that delegates to the target lambda
+ // method
+ JMethod samMethod = new JMethod(info, interfaceMethod.getName(), innerLambdaClass,
+ interfaceMethod.getType(), false, false, true, interfaceMethod.getAccess());
+ samMethod.setSynthetic();
- // implements the SAM, e.g. Callback.onCallback(), Runnable.run(), etc
- createLambdaSamMethod(x, interfaceMethod, info, innerLambdaClass, locals, outerField,
- lambdaMethod,
- samMethod);
+ // implements the SAM, e.g. Callback.onCallback(), Runnable.run(), etc
+ createLambdaSamMethod(x, interfaceMethod, info, innerLambdaClass, locals, outerField,
+ lambdaMethod,
+ samMethod);
- ctor.freezeParamTypes();
- samMethod.freezeParamTypes();
+ ctor.freezeParamTypes();
+ samMethod.freezeParamTypes();
- // Create necessary bridges.
- createFunctionalExpressionBridges(innerLambdaClass, x, samMethod);
+ // Create necessary bridges.
+ createFunctionalExpressionBridges(innerLambdaClass, x, samMethod);
- // replace (x,y,z) -> expr with 'new Lambda(args)'
- replaceLambdaWithInnerClassAllocation(x, info, innerLambdaClass, ctor, synthArgs);
- popMethodInfo();
- // Add the newly generated type
- newTypes.add(innerLambdaClass);
+ // replace (x,y,z) -> expr with 'new Lambda(args)'
+ replaceLambdaWithInnerClassAllocation(x, info, innerLambdaClass, ctor, synthArgs);
+ popMethodInfo();
+ // Add the newly generated type
+ newTypes.add(innerLambdaClass);
+ } catch (Throwable e) {
+ throw translateException(x, e);
+ }
}
private JInterfaceType[] getInterfacesToImplement(TypeBinding binding) {
@@ -1867,263 +1887,267 @@ public void endVisit(QualifiedThisReference x, BlockScope scope) {
@Override
public void endVisit(ReferenceExpression x, BlockScope blockScope) {
- /**
- * Converts an expression like foo(qualifier::someMethod) into
- *
- * class Enclosing {
- *
- * [static] T someMethod(locals, args) {...lambda expr }
- *
- * class lambda$someMethodType implements I {
- * ctor([qualifier]) { ... }
- * R (args) { return [outer]someMethod(args); }
- * }
- * }
- *
- * and replaces qualifier::someMethod with new lambda$someMethodType([outer this])
- *
- * [x] denotes optional, depending on context of whether outer this scope is needed.
- */
+ try {
+ /**
+ * Converts an expression like foo(qualifier::someMethod) into
+ *
+ * class Enclosing {
+ *
+ * [static] T someMethod(locals, args) {...lambda expr }
+ *
+ * class lambda$someMethodType implements I {
+ * ctor([qualifier]) { ... }
+ * R (args) { return [outer]someMethod(args); }
+ * }
+ * }
+ *
+ * and replaces qualifier::someMethod with new lambda$someMethodType([outer this])
+ *
+ * [x] denotes optional, depending on context of whether outer this scope is needed.
+ */
- // Resolve the reference expression to make sure the declaring class of the method is resolved
- // to the right type.
- x.resolve(blockScope);
- // Calculate what type this reference is going to bind to, and what single abstract method
- TypeBinding binding = x.expectedType();
- MethodBinding samBinding = binding.getSingleAbstractMethod(blockScope, false);
- MethodBinding declarationSamBinding =
- binding.getSingleAbstractMethod(blockScope, false).original();
- // Get the interface method is binds to
- JMethod interfaceMethod = typeMap.get(declarationSamBinding);
-
- JInterfaceType[] funcType = getInterfacesToImplement(binding);
- SourceInfo info = makeSourceInfo(x);
+ // Resolve the reference expression to make sure the declaring class of the method is resolved
+ // to the right type.
+ x.resolve(blockScope);
+ // Calculate what type this reference is going to bind to, and what single abstract method
+ TypeBinding binding = x.expectedType();
+ MethodBinding samBinding = binding.getSingleAbstractMethod(blockScope, false);
+ MethodBinding declarationSamBinding =
+ binding.getSingleAbstractMethod(blockScope, false).original();
+ // Get the interface method is binds to
+ JMethod interfaceMethod = typeMap.get(declarationSamBinding);
+
+ JInterfaceType[] funcType = getInterfacesToImplement(binding);
+ SourceInfo info = makeSourceInfo(x);
- // Get the method that the Type::method is actually referring to
- MethodBinding referredMethodBinding = x.binding;
- if (referredMethodBinding instanceof SyntheticMethodBinding) {
- SyntheticMethodBinding synthRefMethodBinding =
- (SyntheticMethodBinding) referredMethodBinding;
- if (synthRefMethodBinding.targetMethod != null) {
- // generated in cases were a private method in an outer class needed to be called
- // e.g. outer.access$0 calls some outer.private_method
- referredMethodBinding = synthRefMethodBinding.targetMethod;
- // privateCtor::new generates overloaded references with fake args that delegate
- // to the real ctor (JDT WTF!). Will we ever need to go deeper?
- if (synthRefMethodBinding.fakePaddedParameters != 0
- && synthRefMethodBinding.targetMethod instanceof SyntheticMethodBinding) {
- referredMethodBinding = ((SyntheticMethodBinding) referredMethodBinding).targetMethod;
+ // Get the method that the Type::method is actually referring to
+ MethodBinding referredMethodBinding = x.binding;
+ if (referredMethodBinding instanceof SyntheticMethodBinding) {
+ SyntheticMethodBinding synthRefMethodBinding =
+ (SyntheticMethodBinding) referredMethodBinding;
+ if (synthRefMethodBinding.targetMethod != null) {
+ // generated in cases were a private method in an outer class needed to be called
+ // e.g. outer.access$0 calls some outer.private_method
+ referredMethodBinding = synthRefMethodBinding.targetMethod;
+ // privateCtor::new generates overloaded references with fake args that delegate
+ // to the real ctor (JDT WTF!). Will we ever need to go deeper?
+ if (synthRefMethodBinding.fakePaddedParameters != 0
+ && synthRefMethodBinding.targetMethod instanceof SyntheticMethodBinding) {
+ referredMethodBinding = ((SyntheticMethodBinding) referredMethodBinding).targetMethod;
+ }
}
}
- }
- JMethod referredMethod = typeMap.get(referredMethodBinding);
- boolean hasQualifier = hasQualifier(x);
-
- // Constructors, overloading and generics means that the safest approach is to consider
- // each different member reference as a different lambda implementation.
- String lambdaImplementationClassShortName =
- String.valueOf(nextReferenceExpressionId++) + "methodref$"
- + (x.binding.isConstructor() ? "ctor" : String.valueOf(x.binding.selector));
- List enclosingThisRefs = Lists.newArrayList();
-
- // Create an inner class to hold the implementation of the interface
- JClassType innerLambdaClass = createInnerClass(
- curClass.getClassOrInterface(), lambdaImplementationClassShortName, info, funcType);
- newTypes.add(innerLambdaClass);
-
- JConstructor ctor = new JConstructor(info, innerLambdaClass, AccessModifier.PRIVATE);
-
- JMethodBody ctorBody = new JMethodBody(info);
- JThisRef thisRef = new JThisRef(info, innerLambdaClass);
- JExpression instance = null;
-
- List enclosingInstanceFields = new ArrayList();
- // If we have a qualifier instance, we have to stash it in the constructor
- if (hasQualifier) {
- // this.$$outer = $$outer
- JField outerField = createAndBindCapturedLambdaParameter(info, OUTER_LAMBDA_PARAM_NAME,
- referredMethod.getEnclosingType(), ctor, ctorBody);
- instance = new JFieldRef(info,
- new JThisRef(info, innerLambdaClass), outerField, innerLambdaClass);
- } else if (referredMethod instanceof JConstructor) {
- // the method we are invoking is a constructor and may need enclosing instances passed to
- // it.
- // For example, an class Foo { class Inner { Inner(int x) { } } } needs
- // it's constructor invoked with an enclosing instance, Inner::new
- // Java8 doesn't allow the qualifified case, e.g. x.new Foo() -> x.Foo::new
- ReferenceBinding targetBinding = referredMethodBinding.declaringClass;
- if (targetBinding.syntheticEnclosingInstanceTypes() != null) {
- for (ReferenceBinding argType : targetBinding.syntheticEnclosingInstanceTypes()) {
- argType = (ReferenceBinding) argType.erasure();
- JExpression enclosingThisRef = resolveThisReference(info, argType, false, blockScope);
- JField enclosingInstance = createAndBindCapturedLambdaParameter(info,
- String.valueOf(argType.readableName()).replace('.', '_'),
- enclosingThisRef.getType(), ctor, ctorBody);
- enclosingInstanceFields.add(enclosingInstance);
- enclosingThisRefs.add(enclosingThisRef);
+ JMethod referredMethod = typeMap.get(referredMethodBinding);
+ boolean hasQualifier = hasQualifier(x);
+
+ // Constructors, overloading and generics means that the safest approach is to consider
+ // each different member reference as a different lambda implementation.
+ String lambdaImplementationClassShortName =
+ String.valueOf(nextReferenceExpressionId++) + "methodref$"
+ + (x.binding.isConstructor() ? "ctor" : String.valueOf(x.binding.selector));
+ List enclosingThisRefs = Lists.newArrayList();
+
+ // Create an inner class to hold the implementation of the interface
+ JClassType innerLambdaClass = createInnerClass(
+ curClass.getClassOrInterface(), lambdaImplementationClassShortName, info, funcType);
+ newTypes.add(innerLambdaClass);
+
+ JConstructor ctor = new JConstructor(info, innerLambdaClass, AccessModifier.PRIVATE);
+
+ JMethodBody ctorBody = new JMethodBody(info);
+ JThisRef thisRef = new JThisRef(info, innerLambdaClass);
+ JExpression instance = null;
+
+ List enclosingInstanceFields = new ArrayList();
+ // If we have a qualifier instance, we have to stash it in the constructor
+ if (hasQualifier) {
+ // this.$$outer = $$outer
+ JField outerField = createAndBindCapturedLambdaParameter(info, OUTER_LAMBDA_PARAM_NAME,
+ referredMethod.getEnclosingType(), ctor, ctorBody);
+ instance = new JFieldRef(info,
+ new JThisRef(info, innerLambdaClass), outerField, innerLambdaClass);
+ } else if (referredMethod instanceof JConstructor) {
+ // the method we are invoking is a constructor and may need enclosing instances passed to
+ // it.
+ // For example, an class Foo { class Inner { Inner(int x) { } } } needs
+ // it's constructor invoked with an enclosing instance, Inner::new
+ // Java8 doesn't allow the qualifified case, e.g. x.new Foo() -> x.Foo::new
+ ReferenceBinding targetBinding = referredMethodBinding.declaringClass;
+ if (targetBinding.syntheticEnclosingInstanceTypes() != null) {
+ for (ReferenceBinding argType : targetBinding.syntheticEnclosingInstanceTypes()) {
+ argType = (ReferenceBinding) argType.erasure();
+ JExpression enclosingThisRef = resolveThisReference(info, argType, false, blockScope);
+ JField enclosingInstance = createAndBindCapturedLambdaParameter(info,
+ String.valueOf(argType.readableName()).replace('.', '_'),
+ enclosingThisRef.getType(), ctor, ctorBody);
+ enclosingInstanceFields.add(enclosingInstance);
+ enclosingThisRefs.add(enclosingThisRef);
+ }
}
}
- }
- ctor.setBody(ctorBody);
- innerLambdaClass.addMethod(ctor);
-
- // Create an implementation of the target interface that invokes the method referred to
- // void onClick(ClickEvent e) { outer.referredMethod(e); }
- JMethod samMethod = new JMethod(info, interfaceMethod.getName(),
- innerLambdaClass, interfaceMethod.getType(),
- false, false, true, interfaceMethod.getAccess());
- samMethod.setSynthetic();
-
- for (JParameter origParam : interfaceMethod.getParams()) {
- samMethod.cloneParameter(origParam);
- }
- JMethodBody samMethodBody = new JMethodBody(info);
-
- Iterator paramIt = samMethod.getParams().iterator();
- // here's where it gets tricky. A method can have an implicit qualifier, e.g.
- // String::compareToIgnoreCase, it's non-static, it only has one argument, but it binds to
- // Comparator.
- // The first argument serves as the qualifier, so for example, the method dispatch looks
- // like this: int compare(T a, T b) { a.compareTo(b); }
- if (!hasQualifier
- && !referredMethod.isStatic()
- && !referredMethod.isConstructor()
- && instance == null) {
- // the instance qualifier is the first parameter in this case.
- // Needs to be cast the actual type due to generics.
- instance = new JCastOperation(info, typeMap.get(referredMethodBinding.declaringClass),
- paramIt.next().makeRef(info));
- }
- JMethodCall samCall = null;
-
- if (referredMethod.isConstructor()) {
- // Constructors must be invoked with JNewInstance
- samCall = new JNewInstance(info, (JConstructor) referredMethod);
- for (JField enclosingInstance : enclosingInstanceFields) {
- samCall.addArg(new JFieldRef(enclosingInstance.getSourceInfo(), thisRef,
- enclosingInstance, innerLambdaClass));
+ ctor.setBody(ctorBody);
+ innerLambdaClass.addMethod(ctor);
+
+ // Create an implementation of the target interface that invokes the method referred to
+ // void onClick(ClickEvent e) { outer.referredMethod(e); }
+ JMethod samMethod = new JMethod(info, interfaceMethod.getName(),
+ innerLambdaClass, interfaceMethod.getType(),
+ false, false, true, interfaceMethod.getAccess());
+ samMethod.setSynthetic();
+
+ for (JParameter origParam : interfaceMethod.getParams()) {
+ samMethod.cloneParameter(origParam);
}
- } else {
- // For static methods, instance will be null
- samCall = new JMethodCall(info, instance, referredMethod);
- // if super::method, we need static dispatch
- if (isSuperReference(x.lhs)) {
- samCall.setStaticDispatchOnly();
+ JMethodBody samMethodBody = new JMethodBody(info);
+
+ Iterator paramIt = samMethod.getParams().iterator();
+ // here's where it gets tricky. A method can have an implicit qualifier, e.g.
+ // String::compareToIgnoreCase, it's non-static, it only has one argument, but it binds to
+ // Comparator.
+ // The first argument serves as the qualifier, so for example, the method dispatch looks
+ // like this: int compare(T a, T b) { a.compareTo(b); }
+ if (!hasQualifier
+ && !referredMethod.isStatic()
+ && !referredMethod.isConstructor()
+ && instance == null) {
+ // the instance qualifier is the first parameter in this case.
+ // Needs to be cast the actual type due to generics.
+ instance = new JCastOperation(info, typeMap.get(referredMethodBinding.declaringClass),
+ paramIt.next().makeRef(info));
+ }
+ JMethodCall samCall = null;
+
+ if (referredMethod.isConstructor()) {
+ // Constructors must be invoked with JNewInstance
+ samCall = new JNewInstance(info, (JConstructor) referredMethod);
+ for (JField enclosingInstance : enclosingInstanceFields) {
+ samCall.addArg(new JFieldRef(enclosingInstance.getSourceInfo(), thisRef,
+ enclosingInstance, innerLambdaClass));
+ }
+ } else {
+ // For static methods, instance will be null
+ samCall = new JMethodCall(info, instance, referredMethod);
+ // if super::method, we need static dispatch
+ if (isSuperReference(x.lhs)) {
+ samCall.setStaticDispatchOnly();
+ }
}
- }
- // Add the rest of the parameters from the interface method to methodcall
- // boxing or unboxing and dealing with varargs
- int paramNumber = 0;
-
- // need to build up an array of passed parameters if we have varargs
- List varArgInitializers = null;
- int varArg = referredMethodBinding.parameters.length - 1;
-
- // interface Foo { m(int x, int y); } bound to reference foo(int... args)
- // if varargs and incoming param is not already a var-arg, we'll need to convert
- // trailing args of the target interface into an array
- boolean isVarargArgumentSuppliedDirectlyAsAnArray =
- referredMethodBinding.isVarargs()
- && samBinding.parameters.length == referredMethodBinding.parameters.length
- && samBinding.parameters[varArg]
- .isCompatibleWith(referredMethodBinding.parameters[varArg]);
-
- if (referredMethodBinding.isVarargs()
- && !isVarargArgumentSuppliedDirectlyAsAnArray) {
- varArgInitializers = Lists.newArrayList();
- }
-
- while (paramIt.hasNext()) {
- JParameter param = paramIt.next();
- JExpression paramExpr = param.makeRef(info);
- // params may need to be boxed or unboxed
- TypeBinding destParam = null;
-
- int declarationParameterOffset =
- declarationSamBinding.parameters.length
- - referredMethodBinding.parameters.length;
- // The method declared in the functional interface might have more or less parameters than
- // the method referred by the method reference. In the case of an instance method without
- // an explicit qualifier (A::m vs instance::m) the method in the functional interface will
- // have an additional parameter for the instance preceding all the method parameters.
- // So truncate the value of the index to refer to the right parameter.
- int declarationParameterIndex = Math.max(0,
- Math.min(
- paramNumber
- + declarationParameterOffset,
- declarationSamBinding.parameters.length - 1)
- );
- TypeBinding samParameterBinding =
- declarationSamBinding.parameters[declarationParameterIndex];
- // if it is not the trailing param or varargs, or interface method is already varargs
- if (varArgInitializers == null
- || !referredMethodBinding.isVarargs()
- || (paramNumber < varArg)) {
- destParam = referredMethodBinding.parameters[paramNumber];
- paramExpr = maybeInsertCasts(paramExpr, samParameterBinding, destParam);
- samCall.addArg(paramExpr);
- } else if (!samParameterBinding.isArrayType()) {
- // else add trailing parameters to var-args initializer list for an array
- destParam = referredMethodBinding.parameters[varArg].leafComponentType();
- paramExpr = maybeInsertCasts(paramExpr, samParameterBinding, destParam);
- varArgInitializers.add(paramExpr);
+ // Add the rest of the parameters from the interface method to methodcall
+ // boxing or unboxing and dealing with varargs
+ int paramNumber = 0;
+
+ // need to build up an array of passed parameters if we have varargs
+ List varArgInitializers = null;
+ int varArg = referredMethodBinding.parameters.length - 1;
+
+ // interface Foo { m(int x, int y); } bound to reference foo(int... args)
+ // if varargs and incoming param is not already a var-arg, we'll need to convert
+ // trailing args of the target interface into an array
+ boolean isVarargArgumentSuppliedDirectlyAsAnArray =
+ referredMethodBinding.isVarargs()
+ && samBinding.parameters.length == referredMethodBinding.parameters.length
+ && samBinding.parameters[varArg]
+ .isCompatibleWith(referredMethodBinding.parameters[varArg]);
+
+ if (referredMethodBinding.isVarargs()
+ && !isVarargArgumentSuppliedDirectlyAsAnArray) {
+ varArgInitializers = Lists.newArrayList();
}
- paramNumber++;
- }
- // add trailing new T[] { initializers } var-arg array
- if (varArgInitializers != null) {
- JArrayType lastParamType =
- (JArrayType) typeMap.get(
- referredMethodBinding.parameters[referredMethodBinding.parameters.length - 1]);
- JNewArray newArray =
- JNewArray.createArrayWithInitializers(info, lastParamType, varArgInitializers);
- samCall.addArg(newArray);
- }
+ while (paramIt.hasNext()) {
+ JParameter param = paramIt.next();
+ JExpression paramExpr = param.makeRef(info);
+ // params may need to be boxed or unboxed
+ TypeBinding destParam = null;
+
+ int declarationParameterOffset =
+ declarationSamBinding.parameters.length
+ - referredMethodBinding.parameters.length;
+ // The method declared in the functional interface might have more or less parameters than
+ // the method referred by the method reference. In the case of an instance method without
+ // an explicit qualifier (A::m vs instance::m) the method in the functional interface will
+ // have an additional parameter for the instance preceding all the method parameters.
+ // So truncate the value of the index to refer to the right parameter.
+ int declarationParameterIndex = Math.max(0,
+ Math.min(
+ paramNumber
+ + declarationParameterOffset,
+ declarationSamBinding.parameters.length - 1)
+ );
+ TypeBinding samParameterBinding =
+ declarationSamBinding.parameters[declarationParameterIndex];
+ // if it is not the trailing param or varargs, or interface method is already varargs
+ if (varArgInitializers == null
+ || !referredMethodBinding.isVarargs()
+ || (paramNumber < varArg)) {
+ destParam = referredMethodBinding.parameters[paramNumber];
+ paramExpr = maybeInsertCasts(paramExpr, samParameterBinding, destParam);
+ samCall.addArg(paramExpr);
+ } else if (!samParameterBinding.isArrayType()) {
+ // else add trailing parameters to var-args initializer list for an array
+ destParam = referredMethodBinding.parameters[varArg].leafComponentType();
+ paramExpr = maybeInsertCasts(paramExpr, samParameterBinding, destParam);
+ varArgInitializers.add(paramExpr);
+ }
+ paramNumber++;
+ }
- // TODO(rluble): Make this a call to JjsUtils.makeMethodEndStatement once boxing/unboxing
- // is handled there.
- if (samMethod.getType() != JPrimitiveType.VOID) {
- JExpression samExpression = maybeInsertCasts(samCall, referredMethodBinding.returnType,
- declarationSamBinding.returnType);
- samMethodBody.getBlock().addStmt(maybeBoxOrUnbox(samExpression, x).makeReturnStatement());
- } else {
- samMethodBody.getBlock().addStmt(samCall.makeStatement());
- }
- samMethod.setBody(samMethodBody);
- innerLambdaClass.addMethod(samMethod);
- ctor.freezeParamTypes();
- samMethod.freezeParamTypes();
+ // add trailing new T[] { initializers } var-arg array
+ if (varArgInitializers != null) {
+ JArrayType lastParamType =
+ (JArrayType) typeMap.get(
+ referredMethodBinding.parameters[referredMethodBinding.parameters.length - 1]);
+ JNewArray newArray =
+ JNewArray.createArrayWithInitializers(info, lastParamType, varArgInitializers);
+ samCall.addArg(newArray);
+ }
- createFunctionalExpressionBridges(innerLambdaClass, x, samMethod);
+ // TODO(rluble): Make this a call to JjsUtils.makeMethodEndStatement once boxing/unboxing
+ // is handled there.
+ if (samMethod.getType() != JPrimitiveType.VOID) {
+ JExpression samExpression = maybeInsertCasts(samCall, referredMethodBinding.returnType,
+ declarationSamBinding.returnType);
+ samMethodBody.getBlock().addStmt(maybeBoxOrUnbox(samExpression, x).makeReturnStatement());
+ } else {
+ samMethodBody.getBlock().addStmt(samCall.makeStatement());
+ }
+ samMethod.setBody(samMethodBody);
+ innerLambdaClass.addMethod(samMethod);
+ ctor.freezeParamTypes();
+ samMethod.freezeParamTypes();
- JConstructor lambdaCtor = null;
- for (JMethod method : innerLambdaClass.getMethods()) {
- if (method instanceof JConstructor) {
- lambdaCtor = (JConstructor) method;
- break;
+ createFunctionalExpressionBridges(innerLambdaClass, x, samMethod);
+
+ JConstructor lambdaCtor = null;
+ for (JMethod method : innerLambdaClass.getMethods()) {
+ if (method instanceof JConstructor) {
+ lambdaCtor = (JConstructor) method;
+ break;
+ }
}
- }
- assert lambdaCtor != null;
+ assert lambdaCtor != null;
- // Replace the ReferenceExpression qualifier::method with new lambdaType(qualifier)
- assert lambdaCtor.getEnclosingType() == innerLambdaClass;
- JNewInstance allocLambda = new JNewInstance(info, lambdaCtor);
+ // Replace the ReferenceExpression qualifier::method with new lambdaType(qualifier)
+ assert lambdaCtor.getEnclosingType() == innerLambdaClass;
+ JNewInstance allocLambda = new JNewInstance(info, lambdaCtor);
- if (hasQualifier) {
- JExpression qualifier = (JExpression) pop();
- // pop qualifier from stack
- allocLambda.addArg(qualifier);
- } else {
- // you can't simultaneously have a qualifier, and have enclosing inner class refs
- // because Java8 won't allow a qualified constructor method reference, e.g. x.Foo::new
- for (JExpression enclosingRef : enclosingThisRefs) {
- allocLambda.addArg(enclosingRef);
+ if (hasQualifier) {
+ JExpression qualifier = (JExpression) pop();
+ // pop qualifier from stack
+ allocLambda.addArg(qualifier);
+ } else {
+ // you can't simultaneously have a qualifier, and have enclosing inner class refs
+ // because Java8 won't allow a qualified constructor method reference, e.g. x.Foo::new
+ for (JExpression enclosingRef : enclosingThisRefs) {
+ allocLambda.addArg(enclosingRef);
+ }
}
+ push(allocLambda);
+ } catch (Throwable e) {
+ throw translateException(x, e);
}
- push(allocLambda);
}
/**
@@ -2559,8 +2583,12 @@ public boolean visit(Argument x, BlockScope scope) {
@Override
public boolean visit(Block x, BlockScope scope) {
- x.statements = reduceToReachable(x.statements);
- return true;
+ try {
+ x.statements = reduceToReachable(x.statements);
+ return true;
+ } catch (Throwable e) {
+ throw translateException(x, e);
+ }
}
@Override
@@ -2700,14 +2728,22 @@ public boolean visit(SingleMemberAnnotation annotation, BlockScope scope) {
@Override
public boolean visit(SwitchStatement x, BlockScope scope) {
- x.statements = reduceToReachable(x.statements);
- return true;
+ try {
+ x.statements = reduceToReachable(x.statements);
+ return true;
+ } catch (Throwable e) {
+ throw translateException(x, e);
+ }
}
@Override
public boolean visit(SwitchExpression x, BlockScope blockScope) {
- x.statements = reduceToReachable(x.statements);
- return true;
+ try {
+ x.statements = reduceToReachable(x.statements);
+ return true;
+ } catch (Throwable e) {
+ throw translateException(x, e);
+ }
}
@Override
@@ -2744,37 +2780,41 @@ public boolean visitValid(TypeDeclaration x, BlockScope scope) {
}
protected void endVisit(TypeDeclaration x) {
- JDeclaredType type = curClass.type;
+ try {
+ JDeclaredType type = curClass.type;
+
+ // Synthesize super clinit calls.
+ if (type instanceof JClassType) {
+ Iterable interfacesToInitialize =
+ Iterables.transform(
+ JdtUtil.getSuperInterfacesRequiringInitialization(x.binding),
+ new Function() {
+ @Override
+ public JInterfaceType apply(ReferenceBinding referenceBinding) {
+ return (JInterfaceType) typeMap.get(referenceBinding);
+ }
+ });
+ JjsUtils.synthesizeStaticInitializerChain(type, interfacesToInitialize);
+ }
- // Synthesize super clinit calls.
- if (type instanceof JClassType) {
- Iterable interfacesToInitialize =
- Iterables.transform(
- JdtUtil.getSuperInterfacesRequiringInitialization(x.binding),
- new Function() {
- @Override
- public JInterfaceType apply(ReferenceBinding referenceBinding) {
- return (JInterfaceType) typeMap.get(referenceBinding);
- }
- });
- JjsUtils.synthesizeStaticInitializerChain(type, interfacesToInitialize);
- }
+ // Implement getClass() implementation for all non-Object classes.
+ if (isSyntheticGetClassNeeded(x, type) && !type.isAbstract()) {
+ implementGetClass(type);
+ }
- // Implement getClass() implementation for all non-Object classes.
- if (isSyntheticGetClassNeeded(x, type) && !type.isAbstract()) {
- implementGetClass(type);
- }
+ if (type instanceof JEnumType) {
+ processEnumType((JEnumType) type);
+ }
- if (type instanceof JEnumType) {
- processEnumType((JEnumType) type);
- }
+ if (type instanceof JClassType && type.isJsNative()) {
+ maybeImplementJavaLangObjectMethodsOnNativeClass(type);
+ }
+ addBridgeMethods(x.binding);
- if (type instanceof JClassType && type.isJsNative()) {
- maybeImplementJavaLangObjectMethodsOnNativeClass(type);
+ curClass = classStack.pop();
+ } catch (Throwable e) {
+ throw translateException(x, e);
}
- addBridgeMethods(x.binding);
-
- curClass = classStack.pop();
}
protected JBlock pop(Block x) {
@@ -2876,46 +2916,50 @@ protected void pushBinaryOp(BinaryExpression x, JBinaryOperator op) {
}
protected boolean visit(TypeDeclaration x) {
- JDeclaredType type = (JDeclaredType) typeMap.get(x.binding);
- assert !type.isExternal();
- classStack.push(curClass);
- curClass = new ClassInfo(type, x);
+ try {
+ JDeclaredType type = (JDeclaredType) typeMap.get(x.binding);
+ assert !type.isExternal();
+ classStack.push(curClass);
+ curClass = new ClassInfo(type, x);
- /*
- * It's okay to defer creation of synthetic fields, they can't be
- * referenced until we analyze the code.
- */
- SourceTypeBinding binding = x.binding;
- if (JdtUtil.isInnerClass(binding)) {
- // add synthetic fields for outer this and locals
- assert (type instanceof JClassType);
- NestedTypeBinding nestedBinding = (NestedTypeBinding) binding;
- if (nestedBinding.enclosingInstances != null) {
- for (SyntheticArgumentBinding argument : nestedBinding.enclosingInstances) {
- createSyntheticField(argument, type, Disposition.THIS_REF);
+ /*
+ * It's okay to defer creation of synthetic fields, they can't be
+ * referenced until we analyze the code.
+ */
+ SourceTypeBinding binding = x.binding;
+ if (JdtUtil.isInnerClass(binding)) {
+ // add synthetic fields for outer this and locals
+ assert (type instanceof JClassType);
+ NestedTypeBinding nestedBinding = (NestedTypeBinding) binding;
+ if (nestedBinding.enclosingInstances != null) {
+ for (SyntheticArgumentBinding argument : nestedBinding.enclosingInstances) {
+ createSyntheticField(argument, type, Disposition.THIS_REF);
+ }
}
- }
- if (nestedBinding.outerLocalVariables != null) {
- for (SyntheticArgumentBinding argument : nestedBinding.outerLocalVariables) {
- // See InnerClassTest.testOuterThisFromSuperCall().
- boolean isReallyThisRef = false;
- if (argument.actualOuterLocalVariable instanceof SyntheticArgumentBinding) {
- SyntheticArgumentBinding outer =
- (SyntheticArgumentBinding) argument.actualOuterLocalVariable;
- if (outer.matchingField != null) {
- JField field = typeMap.get(outer.matchingField);
- if (field.isThisRef()) {
- isReallyThisRef = true;
+ if (nestedBinding.outerLocalVariables != null) {
+ for (SyntheticArgumentBinding argument : nestedBinding.outerLocalVariables) {
+ // See InnerClassTest.testOuterThisFromSuperCall().
+ boolean isReallyThisRef = false;
+ if (argument.actualOuterLocalVariable instanceof SyntheticArgumentBinding) {
+ SyntheticArgumentBinding outer =
+ (SyntheticArgumentBinding) argument.actualOuterLocalVariable;
+ if (outer.matchingField != null) {
+ JField field = typeMap.get(outer.matchingField);
+ if (field.isThisRef()) {
+ isReallyThisRef = true;
+ }
}
}
+ createSyntheticField(argument, type, isReallyThisRef ? Disposition.THIS_REF
+ : Disposition.FINAL);
}
- createSyntheticField(argument, type, isReallyThisRef ? Disposition.THIS_REF
- : Disposition.FINAL);
}
}
+ return true;
+ } catch (Throwable e) {
+ throw translateException(x, e);
}
- return true;
}
/**