Use JAnnotation API for ArtificialRescue Patch by: bobv Review by: scottb git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7549 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ArtificialRescueRecorder.java b/dev/core/src/com/google/gwt/dev/jjs/ArtificialRescueRecorder.java new file mode 100644 index 0000000..5d3e9bd --- /dev/null +++ b/dev/core/src/com/google/gwt/dev/jjs/ArtificialRescueRecorder.java
@@ -0,0 +1,138 @@ +/* + * Copyright 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.dev.jjs; + +import com.google.gwt.core.client.impl.ArtificialRescue; +import com.google.gwt.core.client.impl.ArtificialRescue.Rescue; +import com.google.gwt.dev.jjs.ast.Context; +import com.google.gwt.dev.jjs.ast.HasEnclosingType; +import com.google.gwt.dev.jjs.ast.JAnnotation; +import com.google.gwt.dev.jjs.ast.JDeclaredType; +import com.google.gwt.dev.jjs.ast.JField; +import com.google.gwt.dev.jjs.ast.JNode; +import com.google.gwt.dev.jjs.ast.JProgram; +import com.google.gwt.dev.jjs.ast.JReferenceType; +import com.google.gwt.dev.jjs.ast.JVisitor; +import com.google.gwt.dev.jjs.impl.JsniRefLookup; +import com.google.gwt.dev.util.JsniRef; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Process ArtificialRescue annotations. + */ +public class ArtificialRescueRecorder { + private class Recorder extends JVisitor { + private JDeclaredType currentClass; + + @Override + public void endVisit(JAnnotation x, Context ctx) { + if (x.getType() == artificialRescueType) { + ArtificialRescue annotation = JAnnotation.createAnnotation( + ArtificialRescue.class, x); + for (Rescue rescue : annotation.value()) { + process(rescue); + } + } + } + + @Override + public void endVisit(JDeclaredType x, Context ctx) { + assert currentClass == x; + } + + @Override + public boolean visit(JDeclaredType x, Context ctx) { + currentClass = x; + + /* + * We only care about annotations declared on the type itself, so we can + * skip the traversal of fields and methods. + */ + accept(x.getAnnotations()); + return false; + } + + private void process(Rescue rescue) { + assert rescue != null : "rescue"; + + String typeName = rescue.className(); + JReferenceType classType = (JReferenceType) program.getTypeFromJsniRef(typeName); + String[] fields = rescue.fields(); + boolean instantiable = rescue.instantiable(); + String[] methods = rescue.methods(); + + assert classType != null : "classType " + typeName; + assert fields != null : "fields"; + assert methods != null : "methods"; + + if (instantiable) { + currentClass.addArtificialRescue(classType); + + // Make sure that a class literal for the type has been allocated + program.getLiteralClass(classType); + } + + if (classType instanceof JDeclaredType) { + List<String> toRescue = new ArrayList<String>(); + Collections.addAll(toRescue, fields); + Collections.addAll(toRescue, methods); + + for (String name : toRescue) { + JsniRef ref = JsniRef.parse("@" + classType.getName() + "::" + name); + final String[] errors = {null}; + HasEnclosingType node = JsniRefLookup.findJsniRefTarget(ref, program, + new JsniRefLookup.ErrorReporter() { + public void reportError(String error) { + errors[0] = error; + } + }); + if (errors[0] != null) { + // Should have been caught by ArtificialRescueChecker + throw new InternalCompilerException( + "Unable to artificially rescue " + name + ": " + errors[0]); + } + + currentClass.addArtificialRescue((JNode) node); + if (node instanceof JField) { + JField field = (JField) node; + if (!field.isFinal()) { + field.setVolatile(); + } + } + } + } + } + } + + public static void exec(JProgram program) { + new ArtificialRescueRecorder(program).execImpl(); + } + + private final JDeclaredType artificialRescueType; + private final JProgram program; + + private ArtificialRescueRecorder(JProgram program) { + this.program = program; + artificialRescueType = program.getFromTypeMap(ArtificialRescue.class.getName()); + } + + private void execImpl() { + new Recorder().accept(program); + } +}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java index b725548..bcdf051 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java +++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -486,7 +486,7 @@ maybeDumpAST(jprogram); // (3) Perform Java AST normalizations. - + ArtificialRescueRecorder.exec(jprogram); FixAssignmentToUnbox.exec(jprogram); /*
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JAnnotation.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JAnnotation.java index f4a3413..1d2876b 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/JAnnotation.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JAnnotation.java
@@ -220,9 +220,7 @@ new Class<?>[] {clazz}, new AnnotationInvocationHandler<T>(clazz, annotation)); - @SuppressWarnings("unchecked") - T toReturn = (T) o; - return toReturn; + return clazz.cast(o); } /**
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java index 907c789..45424e0 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
@@ -87,7 +87,8 @@ * Only annotations defined in the following packages or sub-packages thereof * will be recorded in the Java AST. */ - public static final Set<String> RECORDED_ANNOTATION_PACKAGES = new LinkedHashSet<String>(); + public static final Set<String> RECORDED_ANNOTATION_PACKAGES = new LinkedHashSet<String>( + Arrays.asList("com.google.gwt.core.client.impl")); static final Map<String, Set<String>> traceMethods = new HashMap<String, Set<String>>();
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java index e2fd879..d1820bc 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
@@ -15,7 +15,6 @@ */ package com.google.gwt.dev.jjs.impl; -import com.google.gwt.core.client.impl.ArtificialRescue; import com.google.gwt.dev.javac.JsniCollector; import com.google.gwt.dev.jjs.HasSourceInfo; import com.google.gwt.dev.jjs.InternalCompilerException; @@ -101,7 +100,6 @@ import com.google.gwt.dev.js.ast.JsModVisitor; import com.google.gwt.dev.js.ast.JsNameRef; import com.google.gwt.dev.js.ast.JsProgram; -import com.google.gwt.dev.util.Empty; import com.google.gwt.dev.util.JsniRef; import com.google.gwt.dev.util.collect.Lists; @@ -141,7 +139,6 @@ import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression; import org.eclipse.jdt.internal.compiler.ast.LabeledStatement; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; -import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.MessageSend; import org.eclipse.jdt.internal.compiler.ast.NullLiteral; import org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression; @@ -152,10 +149,8 @@ import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference; import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; -import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.Statement; -import org.eclipse.jdt.internal.compiler.ast.StringLiteral; import org.eclipse.jdt.internal.compiler.ast.SuperReference; import org.eclipse.jdt.internal.compiler.ast.SwitchStatement; import org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement; @@ -491,8 +486,6 @@ processEnumType((JEnumType) currentClass); } - processArtificialRescues(x); - currentClassScope = null; currentClass = null; currentSeparatorPositions = null; @@ -2560,128 +2553,6 @@ + value.getClass().getName()); } - private void processArtificialRescue(Annotation rescue) { - assert rescue != null; - - JReferenceType classType = null; - String[] fields = Empty.STRINGS; - boolean instantiable = false; - String[] methods = Empty.STRINGS; - String typeName = null; - - for (MemberValuePair pair : rescue.memberValuePairs()) { - String name = String.valueOf(pair.name); - Expression value = pair.value; - - if ("className".equals(name)) { - typeName = value.constant.stringValue(); - - // Invalid references should be caught in ArtificialRescueChecker - classType = (JReferenceType) program.getTypeFromJsniRef(typeName); - - } else if ("fields".equals(name)) { - if (value instanceof StringLiteral) { - fields = new String[] {value.constant.stringValue()}; - } else if (value instanceof ArrayInitializer) { - ArrayInitializer init = (ArrayInitializer) value; - fields = new String[init.expressions == null ? 0 - : init.expressions.length]; - for (int i = 0, j = fields.length; i < j; i++) { - fields[i] = init.expressions[i].constant.stringValue(); - } - } - - } else if ("instantiable".equals(name)) { - instantiable = value.constant.booleanValue(); - - } else if ("methods".equals(name)) { - if (value instanceof StringLiteral) { - methods = new String[] {value.constant.stringValue()}; - } else if (value instanceof ArrayInitializer) { - ArrayInitializer init = (ArrayInitializer) value; - methods = new String[init.expressions == null ? 0 - : init.expressions.length]; - for (int i = 0, j = methods.length; i < j; i++) { - methods[i] = init.expressions[i].constant.stringValue(); - } - } - } else { - throw new InternalCompilerException( - "Unknown Rescue annotation member " + name); - } - } - - assert classType != null : "classType " + typeName; - assert fields != null : "fields"; - assert methods != null : "methods"; - - if (instantiable) { - currentClass.addArtificialRescue(classType); - - // Make sure that a class literal for the type has been allocated - program.getLiteralClass(classType); - } - - if (classType instanceof JDeclaredType) { - List<String> toRescue = new ArrayList<String>(); - Collections.addAll(toRescue, fields); - Collections.addAll(toRescue, methods); - - for (String name : toRescue) { - JsniRef ref = JsniRef.parse("@" + classType.getName() + "::" + name); - final String[] errors = {null}; - HasEnclosingType node = JsniRefLookup.findJsniRefTarget(ref, program, - new JsniRefLookup.ErrorReporter() { - public void reportError(String error) { - errors[0] = error; - } - }); - if (errors[0] != null) { - // Should have been caught by ArtificialRescueChecker - throw new InternalCompilerException( - "Unable to artificially rescue " + name + ": " + errors[0]); - } - - currentClass.addArtificialRescue((JNode) node); - if (node instanceof JField) { - JField field = (JField) node; - if (!field.isFinal()) { - field.setVolatile(); - } - } - } - } - } - - private void processArtificialRescues(TypeDeclaration x) { - if (x.annotations == null) { - return; - } - - for (Annotation a : x.annotations) { - if (!ArtificialRescue.class.getName().equals( - CharOperation.toString(((ReferenceBinding) a.resolvedType).compoundName))) { - continue; - } - - Expression value = ((SingleMemberAnnotation) a).memberValue; - assert value != null; - if (value instanceof ArrayInitializer) { - for (Expression e : ((ArrayInitializer) value).expressions) { - processArtificialRescue((Annotation) e); - } - } else if (value instanceof Annotation) { - processArtificialRescue((Annotation) value); - } else { - throw new InternalCompilerException( - "Unable to process annotation with value of type " - + value.getClass().getName()); - } - - return; - } - } - /** * Helper for creating all JBinaryOperation. Several different JDT nodes can * result in binary operations: AND_AND_Expression, Assignment,