Add Impl.getNameOf() to expose JNameOf nodes to Java code.
http://gwt-code-reviews.appspot.com/46802/show
Patch by: bobv
Review by: scottb
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5640 8db76d5a-ed1c-0410-87a9-c151d255dfc7
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 f093396..c601e7a 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
@@ -77,6 +77,7 @@
"com.google.gwt.lang.ClassLiteralHolder",
"com.google.gwt.core.client.RunAsyncCallback",
"com.google.gwt.core.client.impl.AsyncFragmentLoader",
+ "com.google.gwt.core.client.impl.Impl",
"com.google.gwt.lang.EntryMethodHolder",}));
static final Map<String, Set<String>> traceMethods = new HashMap<String, Set<String>>();
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java
index eccd7e5..ef8eb03 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java
@@ -20,15 +20,21 @@
import com.google.gwt.dev.jdt.RebindPermutationOracle;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.ast.Context;
+import com.google.gwt.dev.jjs.ast.HasEnclosingType;
+import com.google.gwt.dev.jjs.ast.HasName;
import com.google.gwt.dev.jjs.ast.JClassLiteral;
import com.google.gwt.dev.jjs.ast.JClassType;
+import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JGwtCreate;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JModVisitor;
+import com.google.gwt.dev.jjs.ast.JNameOf;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
+import com.google.gwt.dev.jjs.ast.JStringLiteral;
+import com.google.gwt.dev.util.JsniRef;
import java.util.ArrayList;
import java.util.List;
@@ -40,30 +46,85 @@
private class RebindVisitor extends JModVisitor {
+ private final JMethod nameOfMethod;
private final JMethod rebindCreateMethod;
- public RebindVisitor(JMethod rebindCreateMethod) {
+ public RebindVisitor(JMethod nameOfMethod, JMethod rebindCreateMethod) {
+ this.nameOfMethod = nameOfMethod;
this.rebindCreateMethod = rebindCreateMethod;
}
@Override
public void endVisit(JMethodCall x, Context ctx) {
JMethod method = x.getTarget();
- if (method == rebindCreateMethod) {
- assert (x.getArgs().size() == 1);
- JExpression arg = x.getArgs().get(0);
- assert (arg instanceof JClassLiteral);
- JClassLiteral classLiteral = (JClassLiteral) arg;
- JReferenceType sourceType = (JReferenceType) classLiteral.getRefType();
- List<JClassType> allRebindResults = getAllPossibleRebindResults(sourceType);
- JGwtCreate gwtCreate = new JGwtCreate(x.getSourceInfo(), sourceType,
- allRebindResults, program.getTypeJavaLangObject());
- if (allRebindResults.size() == 1) {
- // Just replace with the instantiation expression.
- ctx.replaceMe(gwtCreate.getInstantiationExpressions().get(0));
- } else {
- ctx.replaceMe(gwtCreate);
+ if (method == nameOfMethod) {
+ replaceImplNameOf(x, ctx);
+
+ } else if (method == rebindCreateMethod) {
+ replaceGwtCreate(x, ctx);
+ }
+ }
+
+ private void replaceGwtCreate(JMethodCall x, Context ctx) {
+ assert (x.getArgs().size() == 1);
+ JExpression arg = x.getArgs().get(0);
+ assert (arg instanceof JClassLiteral);
+ JClassLiteral classLiteral = (JClassLiteral) arg;
+ JReferenceType sourceType = (JReferenceType) classLiteral.getRefType();
+ List<JClassType> allRebindResults = getAllPossibleRebindResults(sourceType);
+ JGwtCreate gwtCreate = new JGwtCreate(x.getSourceInfo(), sourceType,
+ allRebindResults, program.getTypeJavaLangObject());
+ if (allRebindResults.size() == 1) {
+ // Just replace with the instantiation expression.
+ ctx.replaceMe(gwtCreate.getInstantiationExpressions().get(0));
+ } else {
+ ctx.replaceMe(gwtCreate);
+ }
+ }
+
+ private void replaceImplNameOf(JMethodCall x, Context ctx) {
+ JExpression arg0 = x.getArgs().get(0);
+ assert arg0 instanceof JStringLiteral;
+ String stringLiteral = ((JStringLiteral) arg0).getValue();
+
+ HasName named = null;
+
+ JDeclaredType refType;
+ JsniRef ref = JsniRef.parse(stringLiteral);
+
+ if (ref != null) {
+ final List<String> errors = new ArrayList<String>();
+ HasEnclosingType node = JsniRefLookup.findJsniRefTarget(ref, program,
+ new JsniRefLookup.ErrorReporter() {
+ public void reportError(String error) {
+ errors.add(error);
+ }
+ });
+
+ if (!errors.isEmpty()) {
+ for (String error : errors) {
+ logger.log(TreeLogger.ERROR, error);
+ }
}
+
+ if (node instanceof HasName) {
+ named = (HasName) node;
+ }
+
+ } else {
+ // See if it's just @foo.Bar, which would result in the class seed
+ refType = program.getFromTypeMap(stringLiteral.charAt(0) == '@'
+ ? stringLiteral.substring(1) : stringLiteral);
+ if (refType != null) {
+ named = refType;
+ }
+ }
+
+ if (named == null) {
+ // Not found, must be null
+ ctx.replaceMe(program.getLiteralNull());
+ } else {
+ ctx.replaceMe(new JNameOf(x.getSourceInfo(), program, named));
}
}
}
@@ -108,6 +169,7 @@
private boolean execImpl() {
RebindVisitor rebinder = new RebindVisitor(
+ program.getIndexedMethod("Impl.getNameOf"),
program.getIndexedMethod("GWT.create"));
rebinder.accept(program);
return rebinder.didChange();
diff --git a/user/src/com/google/gwt/core/client/impl/Impl.java b/user/src/com/google/gwt/core/client/impl/Impl.java
index 2bbeb48..149dd40 100644
--- a/user/src/com/google/gwt/core/client/impl/Impl.java
+++ b/user/src/com/google/gwt/core/client/impl/Impl.java
@@ -15,6 +15,8 @@
*/
package com.google.gwt.core.client.impl;
+import com.google.gwt.core.client.GWT;
+
/**
* Private implementation class for GWT core. This API is should not be
* considered public or stable.
@@ -66,6 +68,29 @@
return $moduleName;
}-*/;
+ /**
+ * Returns the obfuscated name of members in the compiled output. This is a
+ * thin wrapper around JNameOf AST nodes and is therefore meaningless to
+ * implement in hosted mode.
+ *
+ * @param jsniIdent a string literal specifying a type, field, or method. Raw
+ * type names may also be used to obtain the name of the type's seed
+ * function.
+ * @return the name by which the named member can be accessed at runtime, or
+ * <code>null</code> if the requested member has been pruned from the
+ * output.
+ * @see com.google.gwt.core.client.ArtificialRescue
+ */
+ public static String getNameOf(String jsniIdent) {
+ /*
+ * In web mode, the compiler directly replaces calls to this method with a
+ * string literal expression.
+ */
+ assert !GWT.isScript() : "ReplaceRebinds failed to replace this method";
+ throw new UnsupportedOperationException(
+ "Impl.getNameOf() is unimplemented in hosted mode");
+ }
+
public static native String getPermutationStrongName() /*-{
return $strongName;
}-*/;