OnLocation methods can have additional arguments
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 29 Jul 2013 16:06:51 +0200
changeset 212b6c17baf1615
parent 207 89aefa5591e4
child 213 5b6e96aa697f
OnLocation methods can have additional arguments
geo/src/main/java/org/apidesign/html/geo/impl/GeoProcessor.java
geo/src/test/java/net/java/html/geo/OnLocationTest.java
geo/src/test/java/org/apidesign/html/geo/impl/GeoProcessorTest.java
     1.1 --- a/geo/src/main/java/org/apidesign/html/geo/impl/GeoProcessor.java	Thu Jul 25 16:54:49 2013 +0200
     1.2 +++ b/geo/src/main/java/org/apidesign/html/geo/impl/GeoProcessor.java	Mon Jul 29 16:06:51 2013 +0200
     1.3 @@ -22,6 +22,7 @@
     1.4  
     1.5  import java.io.IOException;
     1.6  import java.io.Writer;
     1.7 +import java.util.List;
     1.8  import java.util.Locale;
     1.9  import java.util.Set;
    1.10  import java.util.logging.Level;
    1.11 @@ -38,6 +39,7 @@
    1.12  import javax.lang.model.element.Modifier;
    1.13  import javax.lang.model.element.PackageElement;
    1.14  import javax.lang.model.element.TypeElement;
    1.15 +import javax.lang.model.element.VariableElement;
    1.16  import javax.lang.model.type.TypeMirror;
    1.17  import javax.tools.Diagnostic;
    1.18  import javax.tools.JavaFileObject;
    1.19 @@ -85,8 +87,9 @@
    1.20              return false;
    1.21          }
    1.22          TypeMirror positionClass = processingEnv.getElementUtils().getTypeElement(Position.class.getName()).asType();
    1.23 -        if (me.getParameters().size() != 1 || !me.getParameters().get(0).asType().equals(positionClass)) {
    1.24 -            error("Method annotated by @OnLocation needs to have one net.java.html.geo.Position argument!", e);
    1.25 +        final List<? extends VariableElement> params = me.getParameters();
    1.26 +        if (params.size() < 1 || !params.get(0).asType().equals(positionClass)) {
    1.27 +            error("Method annotated by @OnLocation first argument must be net.java.html.geo.Position!", e);
    1.28              return false;
    1.29          }
    1.30          String className = ol.className();
    1.31 @@ -104,17 +107,32 @@
    1.32          final String pkg = pe.getQualifiedName().toString();
    1.33          final String fqn = pkg + "." + className;
    1.34          final boolean isStatic = me.getModifiers().contains(Modifier.STATIC);
    1.35 +        String sep;
    1.36          try {
    1.37              JavaFileObject fo = processingEnv.getFiler().createSourceFile(fqn, e);
    1.38              Writer w = fo.openWriter();
    1.39              w.append("package ").append(pkg).append(";\n");
    1.40              w.append("class ").append(className).append(" extends net.java.html.geo.Position.Handle {\n");
    1.41 -            w.append("  private ").append(te.getSimpleName()).append(" i;\n");
    1.42 +            if (!isStatic) {
    1.43 +                w.append("  private final ").append(te.getSimpleName()).append(" $i;\n");
    1.44 +            }
    1.45 +            for (int i = 1; i < params.size(); i++) {
    1.46 +                final VariableElement p = params.get(i);
    1.47 +                w.append("  private final ").append(p.asType().toString()).append(" ").append(p.getSimpleName()).append(";\n");
    1.48 +            }
    1.49              w.append("  private ").append(className).append("(boolean oneTime");
    1.50              w.append(", ").append(te.getSimpleName()).append(" i");
    1.51 +            for (int i = 1; i < params.size(); i++) {
    1.52 +                final VariableElement p = params.get(i);
    1.53 +                w.append(", ").append(p.asType().toString()).append(" ").append(p.getSimpleName());
    1.54 +            }
    1.55              w.append(") {\n    super(oneTime);\n");
    1.56              if (!isStatic) {
    1.57 -                w.append("    this.i = i;\n");
    1.58 +                w.append("    this.$i = i;\n");
    1.59 +            }
    1.60 +            for (int i = 1; i < params.size(); i++) {
    1.61 +                final VariableElement p = params.get(i);
    1.62 +                w.append("  this.").append(p.getSimpleName()).append(" = ").append(p.getSimpleName()).append(";\n");
    1.63              }
    1.64              w.append("}\n");
    1.65              w.append("  static net.java.html.geo.Position.Handle createQuery(");
    1.66 @@ -122,15 +140,39 @@
    1.67              if (!isStatic) {
    1.68                  w.append(te.getSimpleName()).append(" instance");
    1.69                  inst = "instance";
    1.70 +                sep = ", ";
    1.71              } else {
    1.72                  inst = "null";
    1.73 +                sep = "";
    1.74              }
    1.75 -            w.append(") { return new ").append(className).append("(true, ").append(inst).append("); }\n");
    1.76 +            for (int i = 1; i < params.size(); i++) {
    1.77 +                final VariableElement p = params.get(i);
    1.78 +                w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
    1.79 +                sep = ", ";
    1.80 +            }
    1.81 +            w.append(") { return new ").append(className).append("(true, ").append(inst);
    1.82 +            for (int i = 1; i < params.size(); i++) {
    1.83 +                final VariableElement p = params.get(i);
    1.84 +                w.append(", ").append(p.getSimpleName());
    1.85 +            }
    1.86 +            w.append("); }\n");
    1.87              w.append("  static net.java.html.geo.Position.Handle createWatch(");
    1.88              if (!isStatic) {
    1.89                  w.append(te.getSimpleName()).append(" instance");
    1.90 +                sep = ", ";
    1.91 +            } else {
    1.92 +                sep = "";
    1.93              }
    1.94 -            w.append(") { return new ").append(className).append("(false, ").append(inst).append("); }\n");
    1.95 +            for (int i = 1; i < params.size(); i++) {
    1.96 +                final VariableElement p = params.get(i);
    1.97 +                w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
    1.98 +            }
    1.99 +            w.append(") { return new ").append(className).append("(false, ").append(inst);
   1.100 +            for (int i = 1; i < params.size(); i++) {
   1.101 +                final VariableElement p = params.get(i);
   1.102 +                w.append(", ").append(p.getSimpleName());
   1.103 +            }
   1.104 +            w.append("); }\n");
   1.105              w.append("  @Override protected void onError(Exception t) throws Throwable {\n");
   1.106              if (ol.onError().isEmpty()) {
   1.107                  w.append("    t.printStackTrace();");
   1.108 @@ -141,18 +183,28 @@
   1.109                  if (isStatic) {
   1.110                      w.append("    ").append(te.getSimpleName()).append(".");
   1.111                  } else {
   1.112 -                    w.append("    i.");
   1.113 +                    w.append("    $i.");
   1.114                  }
   1.115 -                w.append(ol.onError()).append("(t);\n");
   1.116 +                w.append(ol.onError()).append("(t");
   1.117 +                for (int i = 1; i < params.size(); i++) {
   1.118 +                    final VariableElement p = params.get(i);
   1.119 +                    w.append(", ").append(p.getSimpleName());
   1.120 +                }
   1.121 +                w.append(");\n");
   1.122              }
   1.123              w.append("  }\n");
   1.124              w.append("  @Override protected void onLocation(net.java.html.geo.Position p) throws Throwable {\n");
   1.125              if (isStatic) {
   1.126                  w.append("    ").append(te.getSimpleName()).append(".");
   1.127              } else {
   1.128 -                w.append("    i.");
   1.129 +                w.append("    $i.");
   1.130              }
   1.131 -            w.append(me.getSimpleName()).append("(p);\n");
   1.132 +            w.append(me.getSimpleName()).append("(p");
   1.133 +            for (int i = 1; i < params.size(); i++) {
   1.134 +                final VariableElement p = params.get(i);
   1.135 +                w.append(", ").append(p.getSimpleName());
   1.136 +            }
   1.137 +            w.append(");\n");
   1.138              w.append("  }\n");
   1.139              w.append("}\n");
   1.140              w.close();
   1.141 @@ -165,9 +217,9 @@
   1.142          return true;
   1.143      }
   1.144  
   1.145 -    private boolean findOnError(Element errElem, TypeElement te, String name, boolean onlyStatic) {
   1.146 +    private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, boolean onlyStatic) {
   1.147          String err = null;
   1.148 -        for (Element e : te.getEnclosedElements()) {
   1.149 +        METHODS: for (Element e : te.getEnclosedElements()) {
   1.150              if (e.getKind() != ElementKind.METHOD) {
   1.151                  continue;
   1.152              }
   1.153 @@ -175,19 +227,35 @@
   1.154                  continue;
   1.155              }
   1.156              if (onlyStatic && !e.getModifiers().contains(Modifier.STATIC)) {
   1.157 -                errElem = e;
   1.158 +                errElem = (ExecutableElement) e;
   1.159                  err = "Would have to be static";
   1.160                  continue;
   1.161              }
   1.162              ExecutableElement ee = (ExecutableElement) e;
   1.163              TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
   1.164 -            if (ee.getParameters().size() != 1 || 
   1.165 +            final List<? extends VariableElement> params = ee.getParameters(); 
   1.166 +            if (params.size() < 1 || 
   1.167                  !processingEnv.getTypeUtils().isAssignable(excType, ee.getParameters().get(0).asType())
   1.168              ) {
   1.169 -                errElem = e;
   1.170 -                err = "Error method needs to take one Exception argument";
   1.171 +                errElem = (ExecutableElement) e;
   1.172 +                err = "Error method first argument needs to be Exception";
   1.173                  continue;
   1.174              }
   1.175 +            final List<? extends Element> origParams = errElem.getParameters();
   1.176 +            if (params.size() != origParams.size()) {
   1.177 +                errElem = (ExecutableElement) e;
   1.178 +                err = "Error method must have the same parameters as @OnLocation one";
   1.179 +                continue;
   1.180 +            }
   1.181 +            for (int i = 1; i < origParams.size(); i++) {
   1.182 +                final TypeMirror t1 = params.get(i).asType();
   1.183 +                final TypeMirror t2 = origParams.get(i).asType();
   1.184 +                if (!processingEnv.getTypeUtils().isSameType(t1, t2)) {
   1.185 +                    errElem = (ExecutableElement) e;
   1.186 +                    err = "Error method must have the same parameters as @OnLocation one";
   1.187 +                    continue METHODS;
   1.188 +                }
   1.189 +            }
   1.190              return true;
   1.191          }
   1.192          if (err == null) {
     2.1 --- a/geo/src/test/java/net/java/html/geo/OnLocationTest.java	Thu Jul 25 16:54:49 2013 +0200
     2.2 +++ b/geo/src/test/java/net/java/html/geo/OnLocationTest.java	Mon Jul 29 16:06:51 2013 +0200
     2.3 @@ -104,4 +104,12 @@
     2.4          if (h.isSupported()) h.start();
     2.5          h.stop();
     2.6      }
     2.7 +    
     2.8 +    @OnLocation(onError = "errParam") void withParam(Position pos, int param) {
     2.9 +        instCnt = param;
    2.10 +    }
    2.11 +    
    2.12 +    void errParam(Exception ex, int param) {
    2.13 +        instCnt = param;
    2.14 +    }
    2.15  }
     3.1 --- a/geo/src/test/java/org/apidesign/html/geo/impl/GeoProcessorTest.java	Thu Jul 25 16:54:49 2013 +0200
     3.2 +++ b/geo/src/test/java/org/apidesign/html/geo/impl/GeoProcessorTest.java	Mon Jul 29 16:06:51 2013 +0200
     3.3 @@ -40,7 +40,7 @@
     3.4              + "}\n"
     3.5          );
     3.6          res.assertErrors();
     3.7 -        res.assertError("one net.java.html.geo.Position argument");
     3.8 +        res.assertError("first argument must be net.java.html.geo.Position");
     3.9      }
    3.10      
    3.11      @Test public void onLocationMethodCannotBePrivate() throws IOException {
    3.12 @@ -86,7 +86,7 @@
    3.13              + "}\n"
    3.14          );
    3.15          res.assertErrors();
    3.16 -        res.assertError("take one Exception arg");
    3.17 +        res.assertError("Error method first argument needs to be Exception");
    3.18      }
    3.19      
    3.20  }