Expand the amount of data exported by the symbol maps.
Patch by: bobv
Review by: jat
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5010 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/CompilationResult.java b/dev/core/src/com/google/gwt/core/ext/linker/CompilationResult.java
index e194f59..b62f20c 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/CompilationResult.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/CompilationResult.java
@@ -56,12 +56,12 @@
public abstract String getStrongName();
/**
- * Returns a map of obfuscated symbol names in the compilation to JSNI-style
- * identifiers. This data can allow for on-the-fly deobfuscation of stack
+ * Returns a map of obfuscated symbol names in the compilation to metadata
+ * about the symbol. This data can allow for on-the-fly deobfuscation of stack
* trace information or to allow server components to have in-depth knowledge
* of the runtime structure of compiled objects.
*/
- public abstract SortedMap<String, String> getSymbolMap();
+ public abstract SortedMap<SymbolData, String> getSymbolMap();
@Override
public final int hashCode() {
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/SymbolData.java b/dev/core/src/com/google/gwt/core/ext/linker/SymbolData.java
new file mode 100644
index 0000000..3b1b747
--- /dev/null
+++ b/dev/core/src/com/google/gwt/core/ext/linker/SymbolData.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2009 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.core.ext.linker;
+
+import java.io.Serializable;
+import java.net.URI;
+import java.util.Comparator;
+
+/**
+ * Provides basic information about symbols in the generated JavaScript.
+ *
+ * @see CompilationResult#getSymbolMap()
+ */
+public interface SymbolData extends Serializable {
+ /*
+ * NB: This class is intended to provide enough data to synthesize
+ * StackTraceElements, however we don't want to use STE in our API in the case
+ * that we want to provide additional data in the future.
+ *
+ * Note also that this class does not provide the name of the symbol it is
+ * describing, mainly because the JS compilation process results in multiple
+ * symbols that are mapped onto the same SymbolData (e.g. MakeCallsStatic).
+ */
+
+ /**
+ * A Comparator for use when presenting the data to humans. This Comparator
+ * orders SymbolData objects by their class names or JSNI idents.
+ */
+ class ClassIdentComparator implements Comparator<SymbolData>, Serializable {
+ public int compare(SymbolData o1, SymbolData o2) {
+ String s1 = o1.isClass() ? o1.getClassName() : o1.getJsniIdent();
+ String s2 = o2.isClass() ? o2.getClassName() : o2.getJsniIdent();
+ return s1.compareTo(s2);
+ }
+ }
+
+ /**
+ * Returns the name of the type or enclosing type if the symbol is a method or
+ * field.
+ */
+ String getClassName();
+
+ /**
+ * Returns a JSNI-like identifier for the symbol if it a method or field,
+ * otherwise <code>null</code>.
+ */
+ String getJsniIdent();
+
+ /**
+ * Returns the name of the member if the symbol is a method or field.
+ */
+ String getMemberName();
+
+ /**
+ * Returns the line number on which the symbol was originally declared or
+ * <code>-1</code> if the line number is unknown.
+ */
+ int getSourceLine();
+
+ /**
+ * Returns a URI representing the location of the source. This method will
+ * return <code>null</code> if the symbol was derived from a transient or
+ * unknown source.
+ */
+ URI getSourceUri();
+
+ /**
+ * Returns <code>true</code> if the symbol represents a class.
+ */
+ boolean isClass();
+
+ /**
+ * Returns <code>true</code> if the symbol represents a field.
+ */
+ boolean isField();
+
+ /**
+ * Returns <code>true</code> if the symbol represents a method.
+ */
+ boolean isMethod();
+}
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardCompilationResult.java b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardCompilationResult.java
index 62be9ce..670b312 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardCompilationResult.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardCompilationResult.java
@@ -19,6 +19,7 @@
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.CompilationResult;
import com.google.gwt.core.ext.linker.SelectionProperty;
+import com.google.gwt.core.ext.linker.SymbolData;
import com.google.gwt.dev.PermutationResult;
import com.google.gwt.dev.util.FileBackedObject;
@@ -74,7 +75,7 @@
private final FileBackedObject<PermutationResult> resultFile;
- private transient SoftReference<SortedMap<String, String>> symbolMap;
+ private transient SoftReference<SortedMap<SymbolData, String>> symbolMap;
private final SortedSet<SortedMap<SelectionProperty, String>> propertyValues = new TreeSet<SortedMap<SelectionProperty, String>>(
MAP_COMPARATOR);
@@ -126,8 +127,8 @@
}
@Override
- public SortedMap<String, String> getSymbolMap() {
- SortedMap<String, String> toReturn = null;
+ public SortedMap<SymbolData, String> getSymbolMap() {
+ SortedMap<SymbolData, String> toReturn = null;
if (symbolMap != null) {
toReturn = symbolMap.get();
}
@@ -135,7 +136,7 @@
if (toReturn == null) {
PermutationResult result = loadPermutationResult();
toReturn = result.getSymbolMap();
- symbolMap = new SoftReference<SortedMap<String, String>>(toReturn);
+ symbolMap = new SoftReference<SortedMap<SymbolData, String>>(toReturn);
}
return toReturn;
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSymbolData.java b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSymbolData.java
new file mode 100644
index 0000000..7ecc18d
--- /dev/null
+++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSymbolData.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2009 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.core.ext.linker.impl;
+
+import com.google.gwt.core.ext.linker.SymbolData;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * An immutable implementation of SymbolData.
+ */
+public class StandardSymbolData implements SymbolData {
+
+ public static SymbolData forClass(String className, String fileName,
+ int lineNumber) {
+ URI uri = inferUriFromFileName(fileName);
+ return new StandardSymbolData(className, null, null, uri, lineNumber);
+ }
+
+ public static SymbolData forMember(String className, String memberName,
+ String jsniIdent, String fileName, int lineNumber) {
+ URI uri = inferUriFromFileName(fileName);
+ return new StandardSymbolData(className, jsniIdent, memberName, uri,
+ lineNumber);
+ }
+
+ private static URI inferUriFromFileName(String fileName) {
+ File f = new File(fileName);
+ if (f.exists()) {
+ return f.toURI();
+ } else {
+ try {
+ return new URI(fileName);
+ } catch (URISyntaxException e) {
+ return null;
+ }
+ }
+ }
+
+ private final String className;
+ private final String jsniIdent;
+ private final String memberName;
+ private final int sourceLine;
+ private final URI sourceUri;
+
+ private StandardSymbolData(String className, String jsniIdent,
+ String memberName, URI sourceUri, int sourceLine) {
+ assert className != null && className.length() > 0 : "className";
+ assert !(jsniIdent == null ^ memberName == null) : "jsniIdent ^ memberName";
+ assert sourceLine >= -1 : "sourceLine: " + sourceLine;
+
+ this.className = className;
+ this.jsniIdent = jsniIdent;
+ this.memberName = memberName;
+ this.sourceUri = sourceUri;
+ this.sourceLine = sourceLine;
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public String getJsniIdent() {
+ return jsniIdent;
+ }
+
+ public String getMemberName() {
+ return memberName;
+ }
+
+ public int getSourceLine() {
+ return sourceLine;
+ }
+
+ public URI getSourceUri() {
+ return sourceUri;
+ }
+
+ public boolean isClass() {
+ return memberName == null;
+ }
+
+ public boolean isField() {
+ return jsniIdent != null && !jsniIdent.contains("(");
+ }
+
+ public boolean isMethod() {
+ return jsniIdent != null && jsniIdent.contains("(");
+ }
+
+ @Override
+ public String toString() {
+ return jsniIdent != null ? jsniIdent : className;
+ }
+}
diff --git a/dev/core/src/com/google/gwt/core/linker/SymbolMapsLinker.java b/dev/core/src/com/google/gwt/core/linker/SymbolMapsLinker.java
index 4f4afde..6124019 100644
--- a/dev/core/src/com/google/gwt/core/linker/SymbolMapsLinker.java
+++ b/dev/core/src/com/google/gwt/core/linker/SymbolMapsLinker.java
@@ -24,10 +24,12 @@
import com.google.gwt.core.ext.linker.EmittedArtifact;
import com.google.gwt.core.ext.linker.LinkerOrder;
import com.google.gwt.core.ext.linker.SelectionProperty;
+import com.google.gwt.core.ext.linker.SymbolData;
import com.google.gwt.core.ext.linker.LinkerOrder.Order;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
+import java.net.URI;
import java.util.Map;
import java.util.SortedMap;
@@ -44,7 +46,7 @@
* This value is appended to the strong name of the CompilationResult to form
* the symbol map's filename.
*/
- public static final String STRONG_NAME_SUFFIX = "_symbolMap.properties";
+ public static final String STRONG_NAME_SUFFIX = ".symbolMap";
@Override
public String getDescription() {
@@ -107,12 +109,32 @@
pw.println(" }");
}
- for (Map.Entry<String, String> entry : result.getSymbolMap().entrySet()) {
- // Don't use an actual Properties object because it emits a timestamp
- pw.print(entry.getKey());
- pw.print(" = ");
+ pw.println("# jsName, jsniIdent, className, memberName, sourceUri, sourceLine");
+ for (Map.Entry<SymbolData, String> entry : result.getSymbolMap().entrySet()) {
+ SymbolData symbol = entry.getKey();
+
pw.print(entry.getValue());
+
+ print(pw, symbol.getJsniIdent());
+ print(pw, symbol.getClassName());
+ print(pw, symbol.getMemberName());
+ print(pw, symbol.getSourceUri());
+ print(pw, String.valueOf(symbol.getSourceLine()));
pw.println();
}
}
+
+ private void print(PrintWriter pw, String value) {
+ pw.print(",");
+ if (value != null) {
+ pw.print(value);
+ }
+ }
+
+ private void print(PrintWriter pw, URI uri) {
+ pw.print(",");
+ if (uri != null) {
+ pw.print(uri.toASCIIString());
+ }
+ }
}
diff --git a/dev/core/src/com/google/gwt/dev/PermutationResult.java b/dev/core/src/com/google/gwt/dev/PermutationResult.java
index 67e7da8..4f9aa6f 100644
--- a/dev/core/src/com/google/gwt/dev/PermutationResult.java
+++ b/dev/core/src/com/google/gwt/dev/PermutationResult.java
@@ -16,6 +16,7 @@
package com.google.gwt.dev;
import com.google.gwt.core.ext.linker.ArtifactSet;
+import com.google.gwt.core.ext.linker.SymbolData;
import java.io.Serializable;
import java.util.SortedMap;
@@ -38,5 +39,5 @@
/**
* The symbol map for the permutation.
*/
- SortedMap<String, String> getSymbolMap();
+ SortedMap<SymbolData, String> getSymbolMap();
}
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 edadbb8..345c8b5 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -18,6 +18,7 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.ArtifactSet;
+import com.google.gwt.core.ext.linker.SymbolData;
import com.google.gwt.core.ext.linker.impl.StandardCompilationAnalysis;
import com.google.gwt.core.ext.soyc.Range;
import com.google.gwt.core.ext.soyc.SplitPointRecorder;
@@ -120,10 +121,10 @@
private static class PermutationResultImpl implements PermutationResult {
private final ArtifactSet artifacts = new ArtifactSet();
private final String[] js;
- private final SortedMap<String, String> symbolMap;
+ private final SortedMap<SymbolData, String> symbolMap;
public PermutationResultImpl(String[] js,
- SortedMap<String, String> symbolMap) {
+ SortedMap<SymbolData, String> symbolMap) {
this.js = js;
this.symbolMap = symbolMap;
}
@@ -136,7 +137,7 @@
return js;
}
- public SortedMap<String, String> getSymbolMap() {
+ public SortedMap<SymbolData, String> getSymbolMap() {
return symbolMap;
}
}
@@ -167,7 +168,8 @@
JProgram jprogram = ast.getJProgram();
JsProgram jsProgram = ast.getJsProgram();
JJSOptions options = unifiedAst.getOptions();
- Map<String, JsName> symbolTable = new HashMap<String, JsName>();
+ Map<SymbolData, JsName> symbolTable = new TreeMap<SymbolData, JsName>(
+ new SymbolData.ClassIdentComparator());
ResolveRebinds.exec(jprogram, rebindAnswers);
@@ -278,7 +280,7 @@
}
}
- SortedMap<String, String> symbolMap = makeSymbolMap(symbolTable);
+ SortedMap<SymbolData, String> symbolMap = makeSymbolMap(symbolTable);
PermutationResult toReturn = new PermutationResultImpl(js, symbolMap);
if (sourceInfoMaps != null) {
@@ -788,12 +790,15 @@
return amp.makeStatement();
}
- private static SortedMap<String, String> makeSymbolMap(
- Map<String, JsName> symbolTable) {
+ private static SortedMap<SymbolData, String> makeSymbolMap(
+ Map<SymbolData, JsName> symbolTable) {
- SortedMap<String, String> toReturn = new TreeMap<String, String>();
+ SortedMap<SymbolData, String> toReturn = new TreeMap<SymbolData, String>(
+ new SymbolData.ClassIdentComparator());
- for (Map.Entry<String, JsName> entry : symbolTable.entrySet()) {
+ for (Map.Entry<SymbolData, JsName> entry : symbolTable.entrySet()) {
+ assert !toReturn.containsKey(entry.getKey()) : "Duplicate key for "
+ + entry.getKey().toString();
toReturn.put(entry.getKey(), entry.getValue().getShortIdent());
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index b9c5310..5ee7364 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -15,7 +15,10 @@
*/
package com.google.gwt.dev.jjs.impl;
+import com.google.gwt.core.ext.linker.SymbolData;
+import com.google.gwt.core.ext.linker.impl.StandardSymbolData;
import com.google.gwt.dev.jjs.Correlation;
+import com.google.gwt.dev.jjs.HasSourceInfo;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.JsOutputOption;
import com.google.gwt.dev.jjs.SourceInfo;
@@ -373,12 +376,14 @@
}
private void recordSymbol(JReferenceType x, JsName jsName) {
- assert !symbolTable.containsKey(x.getName());
- symbolTable.put(x.getName(), jsName);
+ SymbolData symbolData = StandardSymbolData.forClass(x.getName(),
+ x.getSourceInfo().getFileName(), x.getSourceInfo().getStartLine());
+ assert !symbolTable.containsKey(symbolData);
+ symbolTable.put(symbolData, jsName);
}
- private <T extends HasEnclosingType & HasName> void recordSymbol(T x,
- JsName jsName) {
+ private <T extends HasEnclosingType & HasName & HasSourceInfo> void recordSymbol(
+ T x, JsName jsName) {
StringBuilder sb = new StringBuilder();
sb.append(x.getEnclosingType().getName());
sb.append("::");
@@ -405,10 +410,13 @@
sb.append(')');
}
- assert !symbolTable.containsKey(sb.toString()) : "Duplicate symbol "
+ SymbolData symbolData = StandardSymbolData.forMember(
+ x.getEnclosingType().getName(), x.getName(), sb.toString(),
+ x.getSourceInfo().getFileName(), x.getSourceInfo().getStartLine());
+ assert !symbolTable.containsKey(symbolData) : "Duplicate symbol "
+ "recorded " + jsName.getIdent() + " for " + x.getName()
+ " and key " + sb.toString();
- symbolTable.put(sb.toString(), jsName);
+ symbolTable.put(symbolData, jsName);
}
}
@@ -1796,7 +1804,7 @@
}
public static JavaToJavaScriptMap exec(JProgram program, JsProgram jsProgram,
- JsOutputOption output, Map<String, JsName> symbolTable) {
+ JsOutputOption output, Map<SymbolData, JsName> symbolTable) {
GenerateJavaScriptAST generateJavaScriptAST = new GenerateJavaScriptAST(
program, jsProgram, output, symbolTable);
return generateJavaScriptAST.execImpl();
@@ -1870,10 +1878,10 @@
/**
* Maps JsNames to machine-usable identifiers.
*/
- private final Map<String, JsName> symbolTable;
+ private final Map<SymbolData, JsName> symbolTable;
private GenerateJavaScriptAST(JProgram program, JsProgram jsProgram,
- JsOutputOption output, Map<String, JsName> symbolTable) {
+ JsOutputOption output, Map<SymbolData, JsName> symbolTable) {
this.program = program;
typeOracle = program.typeOracle;
this.jsProgram = jsProgram;