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 -~----------~----~----~----~------~----~------~--~---
