Untangle JSNI methods produced in CompilationStateBuilder to facilitate serialization.

With this change, JSNI methods parsed during CompilationState's build do not share a jsProgram or common scope.  This allows CompilationUnits to be individually serialized.

http://gwt-code-reviews.appspot.com/1350801/show

Review by: zundel@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9707 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java b/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java
index d3e4f26..bcf9938 100644
--- a/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java
@@ -20,7 +20,8 @@
 import com.google.gwt.dev.javac.CompilationUnitBuilder.ResourceCompilationUnitBuilder;
 import com.google.gwt.dev.javac.JdtCompiler.AdditionalTypeProviderDelegate;
 import com.google.gwt.dev.javac.JdtCompiler.UnitProcessor;
-import com.google.gwt.dev.js.ast.JsProgram;
+import com.google.gwt.dev.jjs.CorrelationFactory.DummyCorrelationFactory;
+import com.google.gwt.dev.js.ast.JsRootScope;
 import com.google.gwt.dev.resource.Resource;
 import com.google.gwt.dev.util.StringInterner;
 import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
@@ -65,7 +66,8 @@
         Event compilationStateBuilderProcess = SpeedTracerLogger.start(DevModeEventType.COMPILATION_STATE_BUILDER_PROCESS);
         try {
           Map<MethodDeclaration, JsniMethod> jsniMethods = JsniCollector.collectJsniMethods(
-              cud, builder.getSource(), jsProgram);
+              cud, builder.getSource(), JsRootScope.INSTANCE,
+              DummyCorrelationFactory.INSTANCE);
 
           JSORestrictionsChecker.check(jsoState, cud);
 
@@ -297,11 +299,6 @@
   }
 
   /**
-   * JsProgram for collecting JSNI methods.
-   */
-  private final JsProgram jsProgram = new JsProgram();
-
-  /**
    * This map of weak keys to hard values exists solely to keep the most recent
    * version of any unit from being eagerly garbage collected.
    * 
diff --git a/dev/core/src/com/google/gwt/dev/javac/JsniCollector.java b/dev/core/src/com/google/gwt/dev/javac/JsniCollector.java
index 3888f9d..d78da8c 100644
--- a/dev/core/src/com/google/gwt/dev/javac/JsniCollector.java
+++ b/dev/core/src/com/google/gwt/dev/javac/JsniCollector.java
@@ -17,6 +17,7 @@
 
 import com.google.gwt.core.client.GwtScriptOnly;
 import com.google.gwt.core.ext.TreeLogger.HelpInfo;
+import com.google.gwt.dev.jjs.CorrelationFactory;
 import com.google.gwt.dev.jjs.InternalCompilerException;
 import com.google.gwt.dev.jjs.SourceInfo;
 import com.google.gwt.dev.jjs.SourceOrigin;
@@ -26,7 +27,7 @@
 import com.google.gwt.dev.js.ast.JsExprStmt;
 import com.google.gwt.dev.js.ast.JsFunction;
 import com.google.gwt.dev.js.ast.JsParameter;
-import com.google.gwt.dev.js.ast.JsProgram;
+import com.google.gwt.dev.js.ast.JsScope;
 import com.google.gwt.dev.js.ast.JsStatement;
 import com.google.gwt.dev.util.collect.IdentityHashMap;
 import com.google.gwt.dev.util.collect.IdentityMaps;
@@ -69,8 +70,8 @@
 
   private static final class JsniMethodImpl extends JsniMethod {
     private final JsFunction func;
-    private final String name;
     private boolean isScriptOnly;
+    private final String name;
 
     public JsniMethodImpl(String name, JsFunction func, boolean isScriptOnly) {
       this.name = name;
@@ -134,15 +135,25 @@
       return false;
     }
 
+    private final CorrelationFactory correlator;
     private final Map<MethodDeclaration, JsniMethod> jsniMethods;
-    private final JsProgram jsProgram;
+    private final JsScope scope;
     private final String source;
+    private SourceInfo cudInfo;
 
-    public Visitor(String source, JsProgram program,
+    public Visitor(String source, JsScope scope, CorrelationFactory correlator,
         Map<MethodDeclaration, JsniMethod> jsniMethods) {
-      this.jsProgram = program;
       this.jsniMethods = jsniMethods;
       this.source = source;
+      this.scope = scope;
+      this.correlator = correlator;
+    }
+
+    @Override
+    public void collect(CompilationUnitDeclaration cud) {
+      cudInfo = correlator.makeSourceInfo(SourceOrigin.create(0,
+          String.valueOf(cud.getFileName())));
+      super.collect(cud);
     }
 
     @Override
@@ -152,9 +163,9 @@
 
     @Override
     protected void processMethod(TypeDeclaration typeDecl,
-        AbstractMethodDeclaration method, String enclosingType, String loc) {
+        AbstractMethodDeclaration method, String enclosingType) {
       JsFunction jsFunction = parseJsniFunction(method, source, enclosingType,
-          loc, jsProgram);
+          cudInfo, scope);
       if (jsFunction != null) {
         String jsniSignature = getJsniSignature(enclosingType, method);
         jsniMethods.put((MethodDeclaration) method, new JsniMethodImpl(
@@ -168,22 +179,22 @@
   public static final String JSNI_BLOCK_START = "/*-{";
 
   public static Map<MethodDeclaration, JsniMethod> collectJsniMethods(
-      final CompilationUnitDeclaration cud, final String source,
-      final JsProgram program) {
+      CompilationUnitDeclaration cud, String source, JsScope scope,
+      CorrelationFactory correlator) {
     Map<MethodDeclaration, JsniMethod> jsniMethods = new IdentityHashMap<MethodDeclaration, JsniMethod>();
-    new Visitor(source, program, jsniMethods).collect(cud);
+    new Visitor(source, scope, correlator, jsniMethods).collect(cud);
     return IdentityMaps.normalizeUnmodifiable(jsniMethods);
   }
 
   public static JsFunction parseJsniFunction(AbstractMethodDeclaration method,
-      String unitSource, String enclosingType, String fileName,
-      JsProgram jsProgram) {
+      String unitSource, String enclosingType, SourceInfo baseInfo,
+      JsScope scope) {
     CompilationResult compResult = method.compilationResult;
     int[] indexes = compResult.lineSeparatorPositions;
     int startLine = Util.getLineNumber(method.sourceStart, indexes, 0,
         indexes.length - 1);
-    SourceInfo info = SourceOrigin.create(method.sourceStart, method.bodyEnd,
-        startLine, fileName);
+    SourceInfo info = baseInfo.makeChild(SourceOrigin.create(
+        method.sourceStart, method.bodyEnd, startLine, baseInfo.getFileName()));
 
     // Handle JSNI block
     String jsniCode = unitSource.substring(method.bodyStart, method.bodyEnd + 1);
@@ -246,11 +257,10 @@
     int jsLine = info.getStartLine()
         + countLines(indexes, info.getStartPos(), absoluteJsStartPos);
 
-    SourceInfo jsInfo = jsProgram.createSourceInfo(jsStartPos, jsEndPos,
-        jsLine, info.getFileName());
+    SourceInfo jsInfo = baseInfo.makeChild(SourceOrigin.create(jsStartPos,
+        jsEndPos, jsLine, baseInfo.getFileName()));
     try {
-      List<JsStatement> result = JsParser.parse(jsInfo, jsProgram.getScope(),
-          sr);
+      List<JsStatement> result = JsParser.parse(jsInfo, scope, sr);
       JsExprStmt jsExprStmt = (JsExprStmt) result.get(0);
       return (JsFunction) jsExprStmt.getExpression();
     } catch (IOException e) {
diff --git a/dev/core/src/com/google/gwt/dev/javac/MethodParamCollector.java b/dev/core/src/com/google/gwt/dev/javac/MethodParamCollector.java
index 8b36de4..4c4b589 100644
--- a/dev/core/src/com/google/gwt/dev/javac/MethodParamCollector.java
+++ b/dev/core/src/com/google/gwt/dev/javac/MethodParamCollector.java
@@ -40,7 +40,7 @@
 
     @Override
     protected void processMethod(TypeDeclaration typeDecl,
-        AbstractMethodDeclaration method, String enclosingType, String loc) {
+        AbstractMethodDeclaration method, String enclosingType) {
       methodArgs.store(enclosingType, method);
     }
   }
diff --git a/dev/core/src/com/google/gwt/dev/javac/MethodVisitor.java b/dev/core/src/com/google/gwt/dev/javac/MethodVisitor.java
index a726da6..03334a4 100644
--- a/dev/core/src/com/google/gwt/dev/javac/MethodVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/javac/MethodVisitor.java
@@ -54,21 +54,21 @@
    * 
    * @param cud
    */
-  public final void collect(final CompilationUnitDeclaration cud) {
+  public void collect(final CompilationUnitDeclaration cud) {
     cud.traverse(new SafeASTVisitor() {
       @Override
       public void endVisit(TypeDeclaration type, ClassScope scope) {
-        collectMethods(cud, type);
+        collectMethods(type);
       }
 
       @Override
       public void endVisit(TypeDeclaration type, CompilationUnitScope scope) {
-        collectMethods(cud, type);
+        collectMethods(type);
       }
 
       @Override
       public void endVisitValid(TypeDeclaration type, BlockScope scope) {
-        collectMethods(cud, type);
+        collectMethods(type);
       }
     }, cud.scope);
   }
@@ -94,7 +94,7 @@
    * @param loc
    */
   protected abstract void processMethod(TypeDeclaration typeDecl,
-      AbstractMethodDeclaration method, String enclosingType, String loc);
+      AbstractMethodDeclaration method, String enclosingType);
 
   /**
    * Collect data about interesting methods on a particular type in a
@@ -103,8 +103,7 @@
    * @param cud
    * @param typeDecl
    */
-  private void collectMethods(CompilationUnitDeclaration cud,
-      TypeDeclaration typeDecl) {
+  private void collectMethods(TypeDeclaration typeDecl) {
     AbstractMethodDeclaration[] methods = typeDecl.methods;
     if (methods == null) {
       return;
@@ -112,7 +111,6 @@
 
     // Lazy initialize these when an interesting method is actually hit.
     String enclosingType = null;
-    String loc = null;
     boolean lazyInitialized = false;
 
     for (AbstractMethodDeclaration method : methods) {
@@ -122,10 +120,9 @@
 
       if (!lazyInitialized) {
         enclosingType = InternalName.toBinaryName(String.valueOf(typeDecl.binding.constantPoolName()));
-        loc = String.valueOf(cud.getFileName());
         lazyInitialized = true;
       }
-      processMethod(typeDecl, method, enclosingType, loc);
+      processMethod(typeDecl, method, enclosingType);
     }
   }
 }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
index e2221ba..6e56652 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
@@ -351,8 +351,8 @@
       char[] source = methodDeclaration.compilationResult().getCompilationUnit().getContents();
       String unitSource = String.valueOf(source);
       JsFunction jsFunction = JsniCollector.parseJsniFunction(
-          methodDeclaration, unitSource, enclosingType.getName(),
-          info.getFileName(), jsProgram);
+          methodDeclaration, unitSource, enclosingType.getName(), info,
+          jsProgram.getScope());
       if (jsFunction != null) {
         jsFunction.setFromJava(true);
         ((JsniMethodBody) newMethod.getBody()).setFunc(jsFunction);