Revision: 6833
Author: [email protected]
Date: Tue Nov 10 20:41:18 2009
Log: Refactors JSNI parsing/error reporting from GenerateJavaAST to  
JsniCollector.

This is to prepare for making JsniCollector the soure of truth for JSNI  
parsing.

Review by: bobv
http://code.google.com/p/google-web-toolkit/source/detail?r=6833

Modified:
  /trunk/dev/core/src/com/google/gwt/dev/javac/ArtificialRescueChecker.java
   
/trunk/dev/core/src/com/google/gwt/dev/javac/BinaryTypeReferenceRestrictionsChecker.java
  /trunk/dev/core/src/com/google/gwt/dev/javac/GWTProblem.java
  /trunk/dev/core/src/com/google/gwt/dev/javac/JSORestrictionsChecker.java
  /trunk/dev/core/src/com/google/gwt/dev/javac/JsniChecker.java
  /trunk/dev/core/src/com/google/gwt/dev/javac/JsniCollector.java
   
/trunk/dev/core/src/com/google/gwt/dev/jdt/FindDeferredBindingSitesVisitor.java
  /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
  /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
  /trunk/dev/core/test/com/google/gwt/dev/javac/GWTProblemTest.java

=======================================
---  
/trunk/dev/core/src/com/google/gwt/dev/javac/ArtificialRescueChecker.java       
 
Thu Nov  5 10:41:50 2009
+++  
/trunk/dev/core/src/com/google/gwt/dev/javac/ArtificialRescueChecker.java       
 
Tue Nov 10 20:41:18 2009
@@ -79,7 +79,7 @@
      private void processArtificialRescue(Annotation rescue) {
        if (!allowArtificialRescue) {
          // Goal (1)
-        GWTProblem.recordInCud(rescue, cud, onlyGeneratedCode(), null);
+        GWTProblem.recordError(rescue, cud, onlyGeneratedCode(), null);
          return;
        }

@@ -155,25 +155,25 @@
        TypeBinding typeBinding = cud.scope.getType(compoundName,
            compoundName.length);
        if (typeBinding == null) {
-        GWTProblem.recordInCud(rescue, cud, notFound(className), null);
+        GWTProblem.recordError(rescue, cud, notFound(className), null);
        } else if (typeBinding instanceof ProblemReferenceBinding) {
          ProblemReferenceBinding problem = (ProblemReferenceBinding)  
typeBinding;
          if (problem.problemId() == ProblemReasons.NotVisible) {
            // Ignore
          } else if (problem.problemId() == ProblemReasons.NotFound) {
-          GWTProblem.recordInCud(rescue, cud, notFound(className), null);
+          GWTProblem.recordError(rescue, cud, notFound(className), null);
          } else {
-          GWTProblem.recordInCud(rescue, cud,
+          GWTProblem.recordError(rescue, cud,
                unknownProblem(className, problem), null);
          }
        } else if (typeBinding instanceof BaseTypeBinding) {
          // No methods or fields on primitive types (3)
          if (methods.length > 0) {
-          GWTProblem.recordInCud(rescue, cud, noMethodsAllowed(), null);
+          GWTProblem.recordError(rescue, cud, noMethodsAllowed(), null);
          }

          if (fields.length > 0) {
-          GWTProblem.recordInCud(rescue, cud, noFieldsAllowed(), null);
+          GWTProblem.recordError(rescue, cud, noFieldsAllowed(), null);
          }
        } else if (typeBinding instanceof ReferenceBinding) {
          ReferenceBinding ref = (ReferenceBinding) typeBinding;
@@ -181,22 +181,22 @@
          if (isArray) {
            // No methods or fields on array types (3)
            if (methods.length > 0) {
-            GWTProblem.recordInCud(rescue, cud, noMethodsAllowed(), null);
+            GWTProblem.recordError(rescue, cud, noMethodsAllowed(), null);
            }

            if (fields.length > 0) {
-            GWTProblem.recordInCud(rescue, cud, noFieldsAllowed(), null);
+            GWTProblem.recordError(rescue, cud, noFieldsAllowed(), null);
            }
          } else {
            // Check methods on reference types (3)
            for (String method : methods) {
              if (method.contains("@")) {
-              GWTProblem.recordInCud(rescue, cud, nameAndTypesOnly(),  
null);
+              GWTProblem.recordError(rescue, cud, nameAndTypesOnly(),  
null);
                continue;
              }
              JsniRef jsni = JsniRef.parse("@foo::" + method);
              if (jsni == null) {
-              GWTProblem.recordInCud(rescue, cud,  
badMethodSignature(method),
+              GWTProblem.recordError(rescue, cud,  
badMethodSignature(method),
                    null);
                continue;
              }
@@ -207,7 +207,7 @@
              } else {
                MethodBinding[] methodBindings =  
ref.getMethods(jsni.memberName().toCharArray());
                if (methodBindings == null || methodBindings.length == 0) {
-                GWTProblem.recordInCud(rescue, cud, noMethod(className,
+                GWTProblem.recordError(rescue, cud, noMethod(className,
                      jsni.memberName()), null);
                  continue;
                }
@@ -217,7 +217,7 @@
            // Check fields on reference types (3)
            for (String field : fields) {
              if (ref.getField(field.toCharArray(), false) == null) {
-              GWTProblem.recordInCud(rescue, cud, unknownField(field),  
null);
+              GWTProblem.recordError(rescue, cud, unknownField(field),  
null);
              }
            }
          }
=======================================
---  
/trunk/dev/core/src/com/google/gwt/dev/javac/BinaryTypeReferenceRestrictionsChecker.java
         
Thu Nov  5 10:41:38 2009
+++  
/trunk/dev/core/src/com/google/gwt/dev/javac/BinaryTypeReferenceRestrictionsChecker.java
         
Tue Nov 10 20:41:18 2009
@@ -131,7 +131,7 @@
        String error = formatBinaryTypeRefErrorMessage(qualifiedTypeName);

        // TODO(mmendez): provide extra help info?
-      GWTProblem.recordInCud(binaryTypeReferenceSite.getExpression(), cud,
+      GWTProblem.recordError(binaryTypeReferenceSite.getExpression(), cud,
            error, null);
      }
    }
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/javac/GWTProblem.java        Wed Mar 
 4  
10:40:25 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/javac/GWTProblem.java        Tue Nov 
10  
20:41:18 2009
@@ -16,6 +16,7 @@
  package com.google.gwt.dev.javac;

  import com.google.gwt.core.ext.TreeLogger.HelpInfo;
+import com.google.gwt.dev.jjs.SourceInfo;

  import org.eclipse.jdt.core.compiler.IProblem;
  import org.eclipse.jdt.internal.compiler.CompilationResult;
@@ -30,30 +31,49 @@
   */
  public class GWTProblem extends DefaultProblem {

-  public static void recordInCud(ASTNode node, CompilationUnitDeclaration  
cud,
+  public static void recordError(ASTNode node, CompilationUnitDeclaration  
cud,
        String message, HelpInfo helpInfo) {
-    recordInCud(ProblemSeverities.Error, node, cud, message, helpInfo);
+    recordProblem(node, cud.compilationResult(), message, helpInfo,
+        ProblemSeverities.Error);
    }

-  public static void recordInCud(int problemSeverity, ASTNode node,
-      CompilationUnitDeclaration cud, String message, HelpInfo helpInfo) {
-    CompilationResult compResult = cud.compilationResult();
+  public static void recordError(SourceInfo info, int startColumn,
+      CompilationResult compResult, String message, HelpInfo helpInfo) {
+    recordProblem(info, startColumn, compResult, message, helpInfo,
+        ProblemSeverities.Error);
+  }
+
+  public static void recordProblem(ASTNode node, CompilationResult  
compResult,
+      String message, HelpInfo helpInfo, int problemSeverity) {
      int[] lineEnds = compResult.getLineSeparatorPositions();
      int startLine = Util.getLineNumber(node.sourceStart(), lineEnds, 0,
          lineEnds.length - 1);
      int startColumn = Util.searchColumnNumber(lineEnds, startLine,
          node.sourceStart());
-    DefaultProblem problem = new GWTProblem(problemSeverity,
-        compResult.fileName, message, node.sourceStart(), node.sourceEnd(),
-        startLine, startColumn, helpInfo);
-    compResult.record(problem, cud);
+    recordProblem(node.sourceStart(), node.sourceEnd(), startLine,  
startColumn,
+        compResult, message, helpInfo, problemSeverity);
+  }
+
+  public static void recordProblem(SourceInfo info, int startColumn,
+      CompilationResult compResult, String message, HelpInfo helpInfo,
+      int problemSeverity) {
+    recordProblem(info.getStartPos(), info.getEndPos(),  
info.getStartLine(),
+        startColumn, compResult, message, helpInfo, problemSeverity);
+  }
+
+  private static void recordProblem(int startPos, int endPos, int  
startLine,
+      int startColumn, CompilationResult compResult, String message,
+      HelpInfo helpInfo, int problemSeverity) {
+    DefaultProblem problem = new GWTProblem(compResult.fileName, startPos,
+        endPos, startLine, startColumn, message, helpInfo,  
problemSeverity);
+    compResult.record(problem, null);
    }

    private HelpInfo helpInfo;

-  GWTProblem(int problemSeverity, char[] originatingFileName, String  
message,
-      int startPosition, int endPosition, int line, int column,
-      HelpInfo helpInfo) {
+  private GWTProblem(char[] originatingFileName, int startPosition,
+      int endPosition, int line, int column, String message, HelpInfo  
helpInfo,
+      int problemSeverity) {
      super(originatingFileName, message, IProblem.ExternalProblemNotFixable,
          null, problemSeverity, startPosition, endPosition, line, column);
      this.helpInfo = helpInfo;
@@ -62,5 +82,4 @@
    public HelpInfo getHelpInfo() {
      return helpInfo;
    }
-
-}
+}
=======================================
---  
/trunk/dev/core/src/com/google/gwt/dev/javac/JSORestrictionsChecker.java        
 
Tue Feb 24 14:28:39 2009
+++  
/trunk/dev/core/src/com/google/gwt/dev/javac/JSORestrictionsChecker.java        
 
Tue Nov 10 20:41:18 2009
@@ -341,7 +341,7 @@

    private static void errorOn(ASTNode node, CompilationUnitDeclaration cud,
        String error) {
-    GWTProblem.recordInCud(node, cud, error, new InstalledHelpInfo(
+    GWTProblem.recordError(node, cud, error, new InstalledHelpInfo(
          "jsoRestrictions.html"));
    }

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/javac/JsniChecker.java       Wed Mar 
 
11 16:11:41 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/javac/JsniChecker.java       Tue Nov 
 
10 20:41:18 2009
@@ -195,8 +195,8 @@
          filterWarnings(meth, warnings);
          for (Set<String> set : warnings.values()) {
            for (String warning : set) {
-            GWTProblem.recordInCud(ProblemSeverities.Warning, meth, cud,
-                warning, null);
+            GWTProblem.recordProblem(meth, cud.compilationResult(),  
warning,
+                null, ProblemSeverities.Warning);
            }
          }
        }
@@ -373,7 +373,7 @@
      }

      private void longAccessError(ASTNode node, String message) {
-      GWTProblem.recordInCud(node, cud, message, new InstalledHelpInfo(
+      GWTProblem.recordError(node, cud, message, new InstalledHelpInfo(
            "longJsniRestriction.html"));
      }

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/javac/JsniCollector.java     Wed  
Nov  4 11:56:48 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/javac/JsniCollector.java     Tue Nov 
 
10 20:41:18 2009
@@ -16,7 +16,11 @@
  package com.google.gwt.dev.javac;

  import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.TreeLogger.HelpInfo;
  import com.google.gwt.dev.javac.CompilationUnit.State;
+import com.google.gwt.dev.jjs.InternalCompilerException;
+import com.google.gwt.dev.jjs.SourceInfo;
+import com.google.gwt.dev.jjs.SourceOrigin;
  import com.google.gwt.dev.js.JsParser;
  import com.google.gwt.dev.js.JsParserException;
  import com.google.gwt.dev.js.JsParserException.SourceDetail;
@@ -27,9 +31,12 @@
  import com.google.gwt.dev.util.Empty;
  import com.google.gwt.dev.util.Name.InternalName;

+import org.eclipse.jdt.internal.compiler.CompilationResult;
  import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
  import org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
  import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
  import org.eclipse.jdt.internal.compiler.util.Util;

  import java.io.IOException;
@@ -176,6 +183,107 @@
        }
      }
    }
+
+  public static JsFunction parseJsniFunction(AbstractMethodDeclaration  
method,
+      String unitSource, String enclosingType, String fileName,
+      JsProgram jsProgram) {
+    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);
+
+    // Handle JSNI block
+    String jsniCode = unitSource.substring(method.bodyStart,  
method.bodyEnd + 1);
+    int startPos = jsniCode.indexOf("/*-{");
+    int endPos = jsniCode.lastIndexOf("}-*/");
+    if (startPos < 0 && endPos < 0) {
+      reportJsniError(
+          info,
+          method,
+          "Native methods require a JavaScript implementation enclosed  
with /*-{ and }-*/");
+      return null;
+    }
+    if (startPos < 0) {
+      reportJsniError(info, method,
+          "Unable to find start of native block; begin your JavaScript  
block with: /*-{");
+      return null;
+    }
+    if (endPos < 0) {
+      reportJsniError(
+          info,
+          method,
+          "Unable to find end of native block; terminate your JavaScript  
block with: }-*/");
+      return null;
+    }
+
+    startPos += 3; // move up to open brace
+    endPos += 1; // move past close brace
+
+    jsniCode = jsniCode.substring(startPos, endPos);
+
+    // Here we parse it as an anonymous function, but we will give it a
+    // name later when we generate the JavaScript during code generation.
+    //
+    StringBuilder functionSource = new StringBuilder("function (");
+    boolean first = true;
+    if (method.arguments != null) {
+      for (Argument arg : method.arguments) {
+        if (first) {
+          first = false;
+        } else {
+          functionSource.append(',');
+        }
+        functionSource.append(arg.binding.name);
+      }
+    }
+    functionSource.append(") ");
+    int functionHeaderLength = functionSource.length();
+    functionSource.append(jsniCode);
+    StringReader sr = new StringReader(functionSource.toString());
+
+    // Absolute start and end position of braces in original source.
+    int absoluteJsStartPos = method.bodyStart + startPos;
+    int absoluteJsEndPos = absoluteJsStartPos + jsniCode.length();
+
+    // Adjust the points the JS parser sees to account for the synth  
header.
+    int jsStartPos = absoluteJsStartPos - functionHeaderLength;
+    int jsEndPos = absoluteJsEndPos - functionHeaderLength;
+
+    // To compute the start line, count lines from point to point.
+    int jsLine = info.getStartLine()
+        + countLines(indexes, info.getStartPos(), absoluteJsStartPos);
+
+    SourceInfo jsInfo = SourceOrigin.create(jsStartPos, jsEndPos, jsLine,
+        info.getFileName());
+    try {
+      List<JsStatement> result = JsParser.parse(jsInfo,  
jsProgram.getScope(),
+          sr);
+      JsExprStmt jsExprStmt = (JsExprStmt) result.get(0);
+      return (JsFunction) jsExprStmt.getExpression();
+    } catch (IOException e) {
+      throw new InternalCompilerException("Internal error parsing JSNI  
in '"
+          + enclosingType + '.' + method.toString() + '\'', e);
+    } catch (JsParserException e) {
+      int problemCharPos = computeAbsoluteProblemPosition(indexes,
+          e.getSourceDetail());
+      SourceInfo errorInfo = SourceOrigin.create(problemCharPos,
+          problemCharPos, e.getSourceDetail().getLine(),  
info.getFileName());
+      reportJsniError(errorInfo, method, e.getMessage());
+      return null;
+    }
+  }
+
+  public static void reportJsniError(SourceInfo info,
+      AbstractMethodDeclaration method, String msg) {
+    reportJsniProblem(info, method, msg, ProblemSeverities.Error);
+  }
+
+  public static void reportJsniWarning(SourceInfo info,
+      MethodDeclaration method, String msg) {
+    reportJsniProblem(info, method, msg, ProblemSeverities.Warning);
+  }

    /**
     * TODO: log real errors, replacing GenerateJavaScriptAST?
@@ -214,6 +322,39 @@
      }
      return jsniMethods;
    }
+
+  /**
+   * JS reports the error as a line number, to find the absolute position  
in the
+   * real source stream, we have to walk from the absolute JS start  
position
+   * until we have counted down enough lines. Then we use the column  
position to
+   * find the exact spot.
+   */
+  private static int computeAbsoluteProblemPosition(int[] indexes,
+      SourceDetail detail) {
+    // Convert 1-based to -1 - based.
+    int line = detail.getLine() - 1;
+    if (line == 0) {
+      return detail.getLineOffset() - 1;
+    }
+
+    int result = indexes[line - 1] + detail.getLineOffset();
+    /*
+     * In other words, make sure our result is actually on this line (less  
than
+     * the start position of the next line), but make sure we don't  
overflow if
+     * this is the last line in the file.
+     */
+    assert line >= indexes.length || result < indexes[line];
+    return result;
+  }
+
+  private static int countLines(int[] indexes, int p1, int p2) {
+    assert p1 >= 0;
+    assert p2 >= 0;
+    assert p1 <= p2;
+    int p1line = findLine(p1, indexes, 0, indexes.length);
+    int p2line = findLine(p2, indexes, 0, indexes.length);
+    return p2line - p1line;
+  }

    private static Interval findJsniSource(String source,
        AbstractMethodDeclaration method) {
@@ -238,6 +379,20 @@
      int srcEnd = bodyStart + jsniEnd;
      return new Interval(srcStart, srcEnd);
    }
+
+  private static int findLine(int pos, int[] indexes, int lo, int tooHi) {
+    assert (lo < tooHi);
+    if (lo == tooHi - 1) {
+      return lo;
+    }
+    int mid = lo + (tooHi - lo) / 2;
+    assert (lo < mid);
+    if (pos < indexes[mid]) {
+      return findLine(pos, indexes, lo, mid);
+    } else {
+      return findLine(pos, indexes, mid, tooHi);
+    }
+  }

    /**
     * Gets a unique name for this method and its signature (this is used to
@@ -332,6 +487,20 @@
        }
      }
    }
+
+  private static void reportJsniProblem(SourceInfo info,
+      AbstractMethodDeclaration methodDeclaration, String message,
+      int problemSeverity) {
+    // TODO: provide helpInfo for how to write JSNI methods?
+    HelpInfo jsniHelpInfo = null;
+    CompilationResult compResult = methodDeclaration.compilationResult();
+    // recalculate startColumn, because SourceInfo does not hold it
+    int startColumn = Util.searchColumnNumber(
+        compResult.getLineSeparatorPositions(), info.getStartLine(),
+        info.getStartPos());
+    GWTProblem.recordProblem(info, startColumn, compResult, message,
+        jsniHelpInfo, problemSeverity);
+  }

    private JsniCollector() {
    }
=======================================
---  
/trunk/dev/core/src/com/google/gwt/dev/jdt/FindDeferredBindingSitesVisitor.java 
 
Tue Sep  8 11:07:39 2009
+++  
/trunk/dev/core/src/com/google/gwt/dev/jdt/FindDeferredBindingSitesVisitor.java 
 
Tue Nov 10 20:41:18 2009
@@ -64,7 +64,7 @@
      Scope scope = site.scope;
      // Safe since CUS.referenceContext is set in its constructor.
      CompilationUnitDeclaration cud =  
scope.compilationUnitScope().referenceContext;
-    GWTProblem.recordInCud(messageSend, cud, message, null);
+    GWTProblem.recordError(messageSend, cud, message, null);
    }

    private final Map<String, MessageSendSite> results = new HashMap<String,  
MessageSendSite>();
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java   Mon  
Apr 20 15:21:46 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java   Tue  
Nov 10 20:41:18 2009
@@ -15,6 +15,7 @@
   */
  package com.google.gwt.dev.jjs.impl;

+import com.google.gwt.dev.javac.JsniCollector;
  import com.google.gwt.dev.jjs.HasSourceInfo;
  import com.google.gwt.dev.jjs.InternalCompilerException;
  import com.google.gwt.dev.jjs.SourceInfo;
@@ -38,15 +39,10 @@
  import com.google.gwt.dev.jjs.ast.JField.Disposition;
  import com.google.gwt.dev.jjs.ast.js.JsniMethodBody;
  import com.google.gwt.dev.js.JsAbstractSymbolResolver;
-import com.google.gwt.dev.js.JsParser;
-import com.google.gwt.dev.js.JsParserException;
-import com.google.gwt.dev.js.JsParserException.SourceDetail;
-import com.google.gwt.dev.js.ast.JsExprStmt;
  import com.google.gwt.dev.js.ast.JsFunction;
  import com.google.gwt.dev.js.ast.JsName;
  import com.google.gwt.dev.js.ast.JsNameRef;
  import com.google.gwt.dev.js.ast.JsProgram;
-import com.google.gwt.dev.js.ast.JsStatement;

  import org.eclipse.jdt.internal.compiler.ASTVisitor;
  import org.eclipse.jdt.internal.compiler.CompilationResult;
@@ -79,8 +75,6 @@
  import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
  import org.eclipse.jdt.internal.compiler.util.Util;

-import java.io.IOException;
-import java.io.StringReader;
  import java.util.ArrayList;
  import java.util.HashSet;
  import java.util.Iterator;
@@ -314,61 +308,6 @@
          CompilationUnitScope scope) {
        return process(typeDeclaration);
      }
-
-    /**
-     * JS reports the error as a line number, to find the absolute  
position in
-     * the real source stream, we have to walk from the absolute JS start
-     * position until we have counted down enough lines. Then we use the  
column
-     * position to find the exact spot.
-     */
-    private int computeAbsoluteProblemPosition(char[] source, int start,
-        int end, int jsStartLine, SourceDetail detail) {
-      int linesToCount = detail.getLine() - jsStartLine;
-      int i = start;
-      while (linesToCount > 0 && i < end) {
-        switch (source[i]) {
-          case '\r':
-            // if skip an extra character if this is a CR/LF
-            if (i + 1 < end && source[i + 1] == '\n') {
-              ++i;
-            }
-            // intentional fall through
-          case '\n':
-            --linesToCount;
-            // intentional fall through
-          default:
-            ++i;
-        }
-      }
-
-      // Jump to the correct (1-based) column.
-      i += detail.getLineOffset() - 1;
-      return i;
-    }
-
-    private int countLines(char[] source, int p1, int p2) {
-      assert p1 >= 0 && p1 < source.length;
-      assert p2 >= 0 && p2 <= source.length;
-      assert p1 <= p2;
-
-      int lines = 0;
-      while (p1 < p2) {
-        switch (source[p1]) {
-          case '\r':
-            // if skip an extra character if this is a CR/LF
-            if (p1 + 1 < p2 && source[p1 + 1] == '\n') {
-              ++p1;
-            }
-            // intentional fall through
-          case '\n':
-            ++lines;
-            // intentional fall through
-          default:
-            ++p1;
-        }
-      }
-      return lines;
-    }

      private JField createEnumField(SourceInfo info, FieldBinding binding,
          JReferenceType enclosingType) {
@@ -719,94 +658,20 @@

      private void processNativeMethod(MethodDeclaration methodDeclaration,
          SourceInfo info, JDeclaredType enclosingType, JMethod newMethod) {
+      // TODO: use existing parsed JSNI functions from CompilationState.
        // Handle JSNI block
        char[] source =  
methodDeclaration.compilationResult().getCompilationUnit().getContents();
-      String jsniCode = String.valueOf(source, methodDeclaration.bodyStart,
-          methodDeclaration.bodyEnd - methodDeclaration.bodyStart + 1);
-      int startPos = jsniCode.indexOf("/*-{");
-      int endPos = jsniCode.lastIndexOf("}-*/");
-      if (startPos < 0 && endPos < 0) {
-        GenerateJavaAST.reportJsniError(
-            info,
-            methodDeclaration,
-            "Native methods require a JavaScript implementation enclosed  
with /*-{ and }-*/");
-        return;
-      }
-      if (startPos < 0) {
-        GenerateJavaAST.reportJsniError(info, methodDeclaration,
-            "Unable to find start of native block; begin your JavaScript  
block with: /*-{");
-        return;
-      }
-      if (endPos < 0) {
-        GenerateJavaAST.reportJsniError(
-            info,
-            methodDeclaration,
-            "Unable to find end of native block; terminate your JavaScript  
block with: }-*/");
-        return;
-      }
-
-      startPos += 3; // move up to open brace
-      endPos += 1; // move past close brace
-
-      jsniCode = jsniCode.substring(startPos, endPos);
-
-      // Here we parse it as an anonymous function, but we will give it a
-      // name later when we generate the JavaScript during code generation.
-      //
-      String syntheticFnHeader = "function (";
-      boolean first = true;
-      for (int i = 0; i < newMethod.getParams().size(); ++i) {
-        JParameter param = newMethod.getParams().get(i);
-        if (first) {
-          first = false;
-        } else {
-          syntheticFnHeader += ',';
-        }
-        syntheticFnHeader += param.getName();
-      }
-      syntheticFnHeader += ") ";
-      StringReader sr = new StringReader(syntheticFnHeader + jsniCode);
-
-      // Absolute start and end position of braces in original source.
-      int absoluteJsStartPos = methodDeclaration.bodyStart + startPos;
-      int absoluteJsEndPos = absoluteJsStartPos + jsniCode.length();
-
-      // Adjust the points the JS parser sees to account for the synth  
header.
-      int jsStartPos = absoluteJsStartPos - syntheticFnHeader.length();
-      int jsEndPos = absoluteJsEndPos - syntheticFnHeader.length();
-
-      // To compute the start line, count lines from point to point.
-      int jsLine = info.getStartLine()
-          + countLines(source, info.getStartPos(), absoluteJsStartPos);
-
-      SourceInfo jsInfo = program.createSourceInfo(jsStartPos, jsEndPos,
-          jsLine, info.getFileName());
-      jsInfo.copyMissingCorrelationsFrom(info);
-
-      try {
-        List<JsStatement> result = JsParser.parse(jsInfo,  
jsProgram.getScope(),
-            sr);
-        JsExprStmt jsExprStmt = (JsExprStmt) result.get(0);
-        JsFunction jsFunction = (JsFunction) jsExprStmt.getExpression();
+      String unitSource = String.valueOf(source);
+      JsFunction jsFunction = JsniCollector.parseJsniFunction(
+          methodDeclaration, unitSource, enclosingType.getName(),
+          info.getFileName(), jsProgram);
+      if (jsFunction != null) {
          jsFunction.setFromJava(true);
          ((JsniMethodBody) newMethod.getBody()).setFunc(jsFunction);
-
          // Ensure that we've resolved the parameter and local references  
within
          // the JSNI method for later pruning.
          JsParameterResolver localResolver = new  
JsParameterResolver(jsFunction);
          localResolver.accept(jsFunction);
-      } catch (IOException e) {
-        throw new InternalCompilerException(
-            "Internal error parsing JSNI in method '" + newMethod
-                + "' in type '" + enclosingType.getName() + "'", e);
-      } catch (JsParserException e) {
-        int problemCharPos = computeAbsoluteProblemPosition(source,
-            absoluteJsStartPos, absoluteJsEndPos, jsInfo.getStartLine(),
-            e.getSourceDetail());
-        SourceInfo errorInfo = program.createSourceInfo(problemCharPos,
-            problemCharPos, e.getSourceDetail().getLine(),  
info.getFileName());
-        GenerateJavaAST.reportJsniError(errorInfo, methodDeclaration,
-            e.getMessage());
        }
      }

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java        
 
Tue Nov 10 20:40:54 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java        
 
Tue Nov 10 20:41:18 2009
@@ -16,6 +16,7 @@
  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;
  import com.google.gwt.dev.jjs.JJSOptions;
@@ -98,8 +99,6 @@
  import com.google.gwt.dev.util.JsniRef;

  import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.compiler.IProblem;
-import org.eclipse.jdt.internal.compiler.CompilationResult;
  import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression;
  import org.eclipse.jdt.internal.compiler.ast.ASTNode;
  import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
@@ -184,8 +183,6 @@
  import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
  import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
  import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
-import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
-import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
  import org.eclipse.jdt.internal.compiler.util.Util;

  import java.lang.reflect.Field;
@@ -2823,7 +2820,7 @@
            String ident) {
          JsniRef parsed = JsniRef.parse(ident);
          if (parsed == null) {
-          reportJsniError(info, methodDecl,
+          JsniCollector.reportJsniError(info, methodDecl,
                "Badly formatted native reference '" + ident + "'");
            return null;
          }
@@ -2833,7 +2830,7 @@
          return JsniRefLookup.findJsniRefTarget(parsed, prog,
              new JsniRefLookup.ErrorReporter() {
                public void reportError(String error) {
-                reportJsniError(info, methodDecl, error);
+                JsniCollector.reportJsniError(info, methodDecl, error);
                }
              });
        }
@@ -2842,11 +2839,11 @@
            JField field, JsContext<JsExpression> ctx) {
          if (field.getEnclosingType() != null) {
            if (field.isStatic() && nameRef.getQualifier() != null) {
-            reportJsniError(info, methodDecl,
+            JsniCollector.reportJsniError(info, methodDecl,
                  "Cannot make a qualified reference to the static field "
                      + field.getName());
            } else if (!field.isStatic() && nameRef.getQualifier() == null) {
-            reportJsniError(info, methodDecl,
+            JsniCollector.reportJsniError(info, methodDecl,
                  "Cannot make an unqualified reference to the instance  
field "
                      + field.getName());
            }
@@ -2858,7 +2855,7 @@
           */
          if (field.isCompileTimeConstant()) {
            if (ctx.isLvalue()) {
-            reportJsniError(info, methodDecl,
+            JsniCollector.reportJsniError(info, methodDecl,
                  "Cannot change the value of compile-time constant "
                      + field.getName());
            }
@@ -2890,22 +2887,24 @@
            JClassType jsoImplType =  
program.typeOracle.getSingleJsoImpls().get(
                enclosingType);
            if (jsoImplType != null) {
-            reportJsniError(info, methodDecl, "Illegal reference to  
method '"
-                + method.getName() + "' in type '" +  
enclosingType.getName()
-                + "', which is implemented by an overlay type '"
-                + jsoImplType.getName() + "'. Use a stronger type in the  
JSNI "
-                + "identifier or a Java trampoline method.");
+            JsniCollector.reportJsniError(info, methodDecl,
+                "Illegal reference to method '" + method.getName()
+                    + "' in type '" + enclosingType.getName()
+                    + "', which is implemented by an overlay type '"
+                    + jsoImplType.getName()
+                    + "'. Use a stronger type in the JSNI "
+                    + "identifier or a Java trampoline method.");
            } else if (method.isStatic() && nameRef.getQualifier() != null) {
-            reportJsniError(info, methodDecl,
+            JsniCollector.reportJsniError(info, methodDecl,
                  "Cannot make a qualified reference to the static method "
                      + method.getName());
            } else if (!method.isStatic() && nameRef.getQualifier() == null)  
{
-            reportJsniError(info, methodDecl,
+            JsniCollector.reportJsniError(info, methodDecl,
                  "Cannot make an unqualified reference to the instance  
method "
                      + method.getName());
            } else if (!method.isStatic()
                && program.isJavaScriptObject(enclosingType)) {
-            reportJsniError(
+            JsniCollector.reportJsniError(
                  info,
                  methodDecl,
                  "Illegal reference to instance method '"
@@ -2916,8 +2915,8 @@
            }
          }
          if (ctx.isLvalue()) {
-          reportJsniError(info, methodDecl, "Cannot reassign the Java  
method "
-              + method.getName());
+          JsniCollector.reportJsniError(info, methodDecl,
+              "Cannot reassign the Java method " + method.getName());
          }

          JsniMethodRef methodRef = new JsniMethodRef(info,  
nameRef.getIdent(),
@@ -3003,20 +3002,6 @@
      Map<JsniMethodBody, AbstractMethodDeclaration> jsniMethodMap =  
v.getJsniMethodMap();
      new JsniRefGenerationVisitor(jprogram, jsProgram,  
jsniMethodMap).accept(jprogram);
    }
-
-  public static void reportJsniError(SourceInfo info,
-      AbstractMethodDeclaration methodDeclaration, String message) {
-    CompilationResult compResult = methodDeclaration.compilationResult();
-    // recalculate startColumn, because SourceInfo does not hold it
-    int startColumn = Util.searchColumnNumber(
-        compResult.getLineSeparatorPositions(), info.getStartLine(),
-        info.getStartPos());
-    DefaultProblem problem = new DefaultProblem(
-        info.getFileName().toCharArray(), message,
-        IProblem.ExternalProblemNotFixable, null, ProblemSeverities.Error,
-        info.getStartPos(), info.getEndPos(), info.getStartLine(),  
startColumn);
-    compResult.record(problem, methodDeclaration);
-  }

    /**
     * Returns <code>true</code> if JDT optimized the condition to
=======================================
--- /trunk/dev/core/test/com/google/gwt/dev/javac/GWTProblemTest.java   Fri  
May  9 14:33:56 2008
+++ /trunk/dev/core/test/com/google/gwt/dev/javac/GWTProblemTest.java   Tue  
Nov 10 20:41:18 2009
@@ -40,7 +40,7 @@
      };

      // Pick an Expression subtype to pass in
-    GWTProblem.recordInCud(new Wildcard(Wildcard.EXTENDS), cud,  
errorMessage,
+    GWTProblem.recordError(new Wildcard(Wildcard.EXTENDS), cud,  
errorMessage,
          info);

      CategorizedProblem[] errors = compilationResult.getErrors();

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to