1.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JavaScriptProcesor.java Thu Jul 11 14:04:37 2013 +0200
1.2 +++ b/boot/src/main/java/org/apidesign/html/boot/impl/JavaScriptProcesor.java Thu Jul 11 14:47:58 2013 +0200
1.3 @@ -37,6 +37,10 @@
1.4 import javax.lang.model.element.ExecutableElement;
1.5 import javax.lang.model.element.TypeElement;
1.6 import javax.lang.model.element.VariableElement;
1.7 +import javax.lang.model.type.ArrayType;
1.8 +import javax.lang.model.type.ExecutableType;
1.9 +import javax.lang.model.type.TypeKind;
1.10 +import javax.lang.model.type.TypeMirror;
1.11 import javax.tools.Diagnostic;
1.12 import net.java.html.js.JavaScriptBody;
1.13 import net.java.html.js.JavaScriptResource;
1.14 @@ -114,13 +118,74 @@
1.15
1.16 @Override
1.17 protected CharSequence callMethod(String ident, String fqn, String method, String params) {
1.18 - if (processingEnv.getElementUtils().getTypeElement(fqn) == null) {
1.19 + final TypeElement type = processingEnv.getElementUtils().getTypeElement(fqn);
1.20 + if (type == null) {
1.21 processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
1.22 "Callback to non-existing class " + fqn, e
1.23 );
1.24 + return "";
1.25 + }
1.26 + Element found = null;
1.27 + StringBuilder foundParams = new StringBuilder();
1.28 + for (Element m : type.getEnclosedElements()) {
1.29 + if (m.getKind() != ElementKind.METHOD) {
1.30 + continue;
1.31 + }
1.32 + if (m.getSimpleName().contentEquals(method)) {
1.33 + String paramTypes = findParamTypes((ExecutableElement)m);
1.34 + if (paramTypes.equals(params)) {
1.35 + found = m;
1.36 + break;
1.37 + }
1.38 + foundParams.append(paramTypes).append("\n");
1.39 + }
1.40 + }
1.41 + if (found == null) {
1.42 + if (foundParams.length() == 0) {
1.43 + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
1.44 + "Callback to class " + fqn + " with unknown method " + method, e
1.45 + );
1.46 + } else {
1.47 + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
1.48 + "Callback to " + fqn + "." + method + " with wrong parameters: " +
1.49 + params + ". Only known parameters are " + foundParams, e
1.50 + );
1.51 + }
1.52 }
1.53 return "";
1.54 }
1.55 +
1.56 + private String findParamTypes(ExecutableElement method) {
1.57 + ExecutableType t = (ExecutableType) method.asType();
1.58 + StringBuilder sb = new StringBuilder();
1.59 + sb.append('(');
1.60 + for (TypeMirror tm : t.getParameterTypes()) {
1.61 + if (tm.getKind().isPrimitive()) {
1.62 + switch (tm.getKind()) {
1.63 + case INT: sb.append('I'); break;
1.64 + case BOOLEAN: sb.append('Z'); break;
1.65 + case BYTE: sb.append('B'); break;
1.66 + case CHAR: sb.append('C'); break;
1.67 + case SHORT: sb.append('S'); break;
1.68 + case DOUBLE: sb.append('D'); break;
1.69 + case FLOAT: sb.append('F'); break;
1.70 + case LONG: sb.append('J'); break;
1.71 + default:
1.72 + throw new IllegalStateException("Uknown " + tm.getKind());
1.73 + }
1.74 + } else {
1.75 + while (tm.getKind() == TypeKind.ARRAY) {
1.76 + sb.append('[');
1.77 + tm = ((ArrayType)tm).getComponentType();
1.78 + }
1.79 + sb.append('L');
1.80 + sb.append(tm.toString().replace('.', '/'));
1.81 + sb.append(';');
1.82 + }
1.83 + }
1.84 + sb.append(')');
1.85 + return sb.toString();
1.86 + }
1.87
1.88 }
1.89 }
2.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JsCallback.java Thu Jul 11 14:04:37 2013 +0200
2.2 +++ b/boot/src/main/java/org/apidesign/html/boot/impl/JsCallback.java Thu Jul 11 14:47:58 2013 +0200
2.3 @@ -20,7 +20,6 @@
2.4 */
2.5 package org.apidesign.html.boot.impl;
2.6
2.7 -import org.objectweb.asm.Type;
2.8
2.9 /**
2.10 *
3.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/Compile.java Thu Jul 11 14:04:37 2013 +0200
3.2 +++ b/boot/src/test/java/org/apidesign/html/boot/impl/Compile.java Thu Jul 11 14:47:58 2013 +0200
3.3 @@ -46,6 +46,7 @@
3.4 import javax.tools.StandardJavaFileManager;
3.5 import javax.tools.StandardLocation;
3.6 import javax.tools.ToolProvider;
3.7 +import static org.testng.Assert.assertTrue;
3.8 import static org.testng.Assert.assertFalse;
3.9 import static org.testng.Assert.fail;
3.10
3.11 @@ -261,4 +262,8 @@
3.12 }
3.13 fail(sb.toString());
3.14 }
3.15 +
3.16 + void assertNoErrors() {
3.17 + assertTrue(getErrors().isEmpty(), "No errors expected: " + getErrors());
3.18 + }
3.19 }
4.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JavaScriptProcesorTest.java Thu Jul 11 14:04:37 2013 +0200
4.2 +++ b/boot/src/test/java/org/apidesign/html/boot/impl/JavaScriptProcesorTest.java Thu Jul 11 14:47:58 2013 +0200
4.3 @@ -43,5 +43,49 @@
4.4 c.assertErrors();
4.5 c.assertError("java.lang.Runable"); // typo
4.6 }
4.7 +
4.8 + @Test public void detectCallbackToNonExistingMethod() throws IOException {
4.9 + String code = "package x.y.z;\n"
4.10 + + "import net.java.html.js.JavaScriptBody;\n"
4.11 + + "class X {\n"
4.12 + + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
4.13 + + " \"r.@java.lang.Runnable::cancel()();\"\n"
4.14 + + " )\n"
4.15 + + " private static native void callback(Runnable r);\n"
4.16 + + "}\n";
4.17 +
4.18 + Compile c = Compile.create("", code);
4.19 + c.assertErrors();
4.20 + c.assertError("method cancel");
4.21 + }
4.22 +
4.23 + @Test public void detectCallbackToNonExistingParams() throws IOException {
4.24 + String code = "package x.y.z;\n"
4.25 + + "import net.java.html.js.JavaScriptBody;\n"
4.26 + + "class X {\n"
4.27 + + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
4.28 + + " \"r.@java.lang.Runnable::run(I)(10);\"\n"
4.29 + + " )\n"
4.30 + + " private static native void callback(Runnable r);\n"
4.31 + + "}\n";
4.32 +
4.33 + Compile c = Compile.create("", code);
4.34 + c.assertErrors();
4.35 + c.assertError("wrong parameters: (I)");
4.36 + }
4.37 +
4.38 + @Test public void objectTypeParamsAreOK() throws IOException {
4.39 + String code = "package x.y.z;\n"
4.40 + + "import net.java.html.js.JavaScriptBody;\n"
4.41 + + "class X {\n"
4.42 + + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
4.43 + + " \"r.@java.lang.Object::equals(Ljava/lang/Object;)(null);\"\n"
4.44 + + " )\n"
4.45 + + " private static native void testEqual(Object r);\n"
4.46 + + "}\n";
4.47 +
4.48 + Compile c = Compile.create("", code);
4.49 + c.assertNoErrors();
4.50 + }
4.51
4.52 }