public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
try {
MethodBinding b = methodDeclaration.binding;
SourceInfo info = makeSourceInfo(methodDeclaration);
JType returnType = (JType) typeMap.get(methodDeclaration.returnType.resolvedType);
JReferenceType enclosingType = (JReferenceType) typeMap.get(scope.enclosingSourceType());
JMethod newMethod = program.createMethod(info,
methodDeclaration.selector, enclosingType, returnType,
b.isAbstract(), b.isStatic(), b.isFinal(), b.isPrivate(),
b.isNative());
mapThrownExceptions(newMethod, methodDeclaration);
mapParameters(newMethod, methodDeclaration);
typeMap.put(b, newMethod);
if (newMethod.isNative()) {
// 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 true;
}
if (startPos < 0) {
GenerateJavaAST.reportJsniError(info, methodDeclaration,
"Unable to find start of native block; begin your JavaScript block with: /*-{");
return true;
}
if (endPos < 0) {
GenerateJavaAST.reportJsniError(
info,
methodDeclaration,
"Unable to find end of native block; terminate your JavaScript block with: }-*/");
return true;
}
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.params.size(); ++i) {
JParameter param = (JParameter) newMethod.params.get(i);
if (first) {
first = false;
} else {
syntheticFnHeader += ',';
}
syntheticFnHeader += param.getName();
}
syntheticFnHeader += ')';
StringReader sr = new StringReader(syntheticFnHeader + '\n'
+ jsniCode);
try {
// start at -1 to avoid counting our synthetic header
// TODO: get the character position start correct
JsStatements result = jsParser.parse(jsProgram.getScope(), sr, -1);
JsExprStmt jsExprStmt = (JsExprStmt) result.get(0);
JsFunction jsFunction = (JsFunction) jsExprStmt.getExpression();
((JsniMethod) newMethod).setFunc(jsFunction);
} catch (IOException e) {
throw new InternalCompilerException(
"Internal error parsing JSNI in method '" + newMethod
+ "' in type '" + enclosingType.getName() + "'", e);
} catch (JsParserException e) {
/*
* count the number of characters to the problem (from the start of
* the JSNI code)
*/