1.1 --- a/emul/mini/pom.xml Sun Feb 03 17:55:48 2013 +0100
1.2 +++ b/emul/mini/pom.xml Sun Feb 03 18:58:09 2013 +0100
1.3 @@ -22,6 +22,12 @@
1.4 <version>0.3-SNAPSHOT</version>
1.5 <type>jar</type>
1.6 </dependency>
1.7 + <dependency>
1.8 + <groupId>org.testng</groupId>
1.9 + <artifactId>testng</artifactId>
1.10 + <version>6.5.2</version>
1.11 + <scope>test</scope>
1.12 + </dependency>
1.13 </dependencies>
1.14 <build>
1.15 <plugins>
2.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/AnnotationImpl.java Sun Feb 03 17:55:48 2013 +0100
2.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/AnnotationImpl.java Sun Feb 03 18:58:09 2013 +0100
2.3 @@ -18,6 +18,8 @@
2.4 package org.apidesign.bck2brwsr.emul.reflect;
2.5
2.6 import java.lang.annotation.Annotation;
2.7 +import java.lang.reflect.Method;
2.8 +import java.lang.reflect.Modifier;
2.9 import org.apidesign.bck2brwsr.core.JavaScriptBody;
2.10
2.11 /**
2.12 @@ -29,7 +31,7 @@
2.13 return getClass();
2.14 }
2.15
2.16 - @JavaScriptBody(args = { "a", "n", "values" }, body = ""
2.17 + @JavaScriptBody(args = { "a", "n", "arr", "values" }, body = ""
2.18 + "function f(v, p) {\n"
2.19 + " var val = v;\n"
2.20 + " var prop = p;\n"
2.21 @@ -37,27 +39,42 @@
2.22 + " return val[prop];\n"
2.23 + " };\n"
2.24 + "}\n"
2.25 - + "var props = Object.getOwnPropertyNames(values);\n"
2.26 - + "for (var i = 0; i < props.length; i++) {\n"
2.27 - + " var p = props[i];\n"
2.28 - + " a[p] = new f(values, p);\n"
2.29 + + "for (var i = 0; i < arr.length; i += 2) {\n"
2.30 + + " var m = arr[i];\n"
2.31 + + " var p = arr[i + 1];\n"
2.32 + + " a[m] = new f(values, p);\n"
2.33 + "}\n"
2.34 + "a['$instOf_' + n] = true;\n"
2.35 + "return a;"
2.36 )
2.37 - private static <T extends Annotation> T create(AnnotationImpl a, String n, Object values) {
2.38 - return null;
2.39 - }
2.40 + private static native <T extends Annotation> T create(
2.41 + AnnotationImpl a, String n, String[] methodsAndProps, Object values
2.42 + );
2.43 +
2.44 public static <T extends Annotation> T create(Class<T> annoClass, Object values) {
2.45 - return create(new AnnotationImpl(), annoClass.getName().replace('.', '_'), values);
2.46 + return create(new AnnotationImpl(),
2.47 + annoClass.getName().replace('.', '_'),
2.48 + findProps(annoClass), values
2.49 + );
2.50 }
2.51
2.52 public static Annotation[] create(Object anno) {
2.53 String[] names = findNames(anno);
2.54 Annotation[] ret = new Annotation[names.length];
2.55 for (int i = 0; i < names.length; i++) {
2.56 - String n = names[i].substring(1, names[i].length() - 1).replace('/', '_');
2.57 - ret[i] = create(new AnnotationImpl(), n, findData(anno, names[i]));
2.58 + String annoNameSlash = names[i].substring(1, names[i].length() - 1);
2.59 + Class<?> annoClass;
2.60 + try {
2.61 + annoClass = Class.forName(annoNameSlash.replace('/', '.'));
2.62 + } catch (ClassNotFoundException ex) {
2.63 + throw new IllegalStateException("Can't find annotation class " + annoNameSlash);
2.64 + }
2.65 + ret[i] = create(
2.66 + new AnnotationImpl(),
2.67 + annoNameSlash.replace('/', '_'),
2.68 + findProps(annoClass),
2.69 + findData(anno, names[i])
2.70 + );
2.71 }
2.72 return ret;
2.73 }
2.74 @@ -70,12 +87,19 @@
2.75 + "}"
2.76 + "return arr;"
2.77 )
2.78 - private static String[] findNames(Object anno) {
2.79 - throw new UnsupportedOperationException();
2.80 - }
2.81 + private static native String[] findNames(Object anno);
2.82
2.83 @JavaScriptBody(args={ "anno", "p"}, body="return anno[p];")
2.84 - private static Object findData(Object anno, String p) {
2.85 - throw new UnsupportedOperationException();
2.86 + private static native Object findData(Object anno, String p);
2.87 +
2.88 + private static String[] findProps(Class<?> annoClass) {
2.89 + final Method[] marr = MethodImpl.findMethods(annoClass, Modifier.PUBLIC);
2.90 + String[] arr = new String[marr.length * 2];
2.91 + int pos = 0;
2.92 + for (Method m : marr) {
2.93 + arr[pos++] = MethodImpl.toSignature(m);
2.94 + arr[pos++] = m.getName();
2.95 + }
2.96 + return arr;
2.97 }
2.98 }
3.1 --- a/javap/src/main/java/org/apidesign/javap/AnnotationParser.java Sun Feb 03 17:55:48 2013 +0100
3.2 +++ b/javap/src/main/java/org/apidesign/javap/AnnotationParser.java Sun Feb 03 18:58:09 2013 +0100
3.3 @@ -35,9 +35,11 @@
3.4 */
3.5 public class AnnotationParser {
3.6 private final boolean textual;
3.7 + private final boolean iterateArray;
3.8
3.9 - protected AnnotationParser(boolean textual) {
3.10 + protected AnnotationParser(boolean textual, boolean iterateArray) {
3.11 this.textual = textual;
3.12 + this.iterateArray = iterateArray;
3.13 }
3.14
3.15 protected void visitAnnotationStart(String type) throws IOException {
3.16 @@ -45,6 +47,13 @@
3.17
3.18 protected void visitAnnotationEnd(String type) throws IOException {
3.19 }
3.20 +
3.21 + protected void visitValueStart(String attrName, char type) throws IOException {
3.22 + }
3.23 +
3.24 + protected void visitValueEnd(String attrName, char type) throws IOException {
3.25 + }
3.26 +
3.27
3.28 protected void visitAttr(
3.29 String annoType, String attr, String attrType, String value
3.30 @@ -89,9 +98,11 @@
3.31 }
3.32 }
3.33
3.34 - private void readValue(DataInputStream dis, ClassData cd, String typeName, String attrName)
3.35 - throws IOException {
3.36 + private void readValue(
3.37 + DataInputStream dis, ClassData cd, String typeName, String attrName
3.38 + ) throws IOException {
3.39 char type = (char)dis.readByte();
3.40 + visitValueStart(attrName, type);
3.41 if (type == '@') {
3.42 readAnno(dis, cd);
3.43 } else if ("CFJZsSIDB".indexOf(type) >= 0) { // NOI18N
3.44 @@ -112,13 +123,20 @@
3.45 } else if (type == '[') {
3.46 int cnt = dis.readUnsignedShort();
3.47 for (int i = 0; i < cnt; i++) {
3.48 - readValue(dis, cd, typeName, attrName);
3.49 + readValue(dis, cd, typeName, iterateArray ? attrName : null);
3.50 }
3.51 } else if (type == 'e') {
3.52 int enumT = dis.readUnsignedShort();
3.53 + String attrType = cd.stringValue(enumT, textual);
3.54 int enumN = dis.readUnsignedShort();
3.55 + String val = cd.stringValue(enumN, textual);
3.56 + if (textual) {
3.57 + val = '"' + val + '"';
3.58 + }
3.59 + visitAttr(typeName, attrName, attrType, val);
3.60 } else {
3.61 throw new IOException("Unknown type " + type);
3.62 }
3.63 + visitValueEnd(attrName, type);
3.64 }
3.65 }
4.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Sun Feb 03 17:55:48 2013 +0100
4.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Sun Feb 03 18:58:09 2013 +0100
4.3 @@ -1605,7 +1605,7 @@
4.4 final String jvmType = "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;";
4.5 class P extends AnnotationParser {
4.6 public P() {
4.7 - super(false);
4.8 + super(false, true);
4.9 }
4.10
4.11 int cnt;
4.12 @@ -1661,7 +1661,7 @@
4.13 final String[] values = new String[attrNames.length];
4.14 final boolean[] found = { false };
4.15 final String jvmType = "L" + className.replace('.', '/') + ";";
4.16 - AnnotationParser ap = new AnnotationParser(false) {
4.17 + AnnotationParser ap = new AnnotationParser(false, true) {
4.18 @Override
4.19 protected void visitAttr(String type, String attr, String at, String value) {
4.20 if (type.equals(jvmType)) {
4.21 @@ -1699,34 +1699,54 @@
4.22 }
4.23
4.24 private static void generateAnno(ClassData cd, final Appendable out, byte[] data) throws IOException {
4.25 - AnnotationParser ap = new AnnotationParser(true) {
4.26 - int anno;
4.27 - int cnt;
4.28 + AnnotationParser ap = new AnnotationParser(true, false) {
4.29 + int[] cnt = new int[32];
4.30 + int depth;
4.31
4.32 @Override
4.33 protected void visitAnnotationStart(String type) throws IOException {
4.34 - if (anno++ > 0) {
4.35 + if (cnt[depth]++ > 0) {
4.36 out.append(",");
4.37 }
4.38 out.append('"').append(type).append("\" : {\n");
4.39 - cnt = 0;
4.40 + cnt[++depth] = 0;
4.41 }
4.42
4.43 @Override
4.44 protected void visitAnnotationEnd(String type) throws IOException {
4.45 out.append("\n}\n");
4.46 + depth--;
4.47 + }
4.48 +
4.49 + @Override
4.50 + protected void visitValueStart(String attrName, char type) throws IOException {
4.51 + if (cnt[depth]++ > 0) {
4.52 + out.append(",\n");
4.53 + }
4.54 + cnt[++depth] = 0;
4.55 + if (attrName != null) {
4.56 + out.append(attrName).append(" : ");
4.57 + }
4.58 + if (type == '[') {
4.59 + out.append("[");
4.60 + }
4.61 + }
4.62 +
4.63 + @Override
4.64 + protected void visitValueEnd(String attrName, char type) throws IOException {
4.65 + if (type == '[') {
4.66 + out.append("]");
4.67 + }
4.68 + depth--;
4.69 }
4.70
4.71 @Override
4.72 protected void visitAttr(String type, String attr, String attrType, String value)
4.73 throws IOException {
4.74 - if (attr == null) {
4.75 + if (attr == null && value == null) {
4.76 return;
4.77 }
4.78 - if (cnt++ > 0) {
4.79 - out.append(",\n");
4.80 - }
4.81 - out.append(attr).append("__").append(attrType).append(" : ").append(value);
4.82 + out.append(value);
4.83 }
4.84 };
4.85 ap.parse(data, cd);
5.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Sun Feb 03 17:55:48 2013 +0100
5.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Sun Feb 03 18:58:09 2013 +0100
5.3 @@ -87,6 +87,9 @@
5.4 @Test public void jsAnnotation() throws Exception {
5.5 assertExec("Check class annotation", Classes.class, "getMarker__I", Double.valueOf(10));
5.6 }
5.7 + @Test public void jsArrayAnnotation() throws Exception {
5.8 + assertExec("Check array annotation", Classes.class, "getMarkerNicknames__Ljava_lang_String_2", Classes.getMarkerNicknames());
5.9 + }
5.10 @Test public void jsStringAnnotation() throws Exception {
5.11 assertExec("Check class annotation", Classes.class, "getNamer__Ljava_lang_String_2Z", "my text", true);
5.12 }
6.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Sun Feb 03 17:55:48 2013 +0100
6.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Sun Feb 03 18:58:09 2013 +0100
6.3 @@ -27,7 +27,7 @@
6.4 *
6.5 * @author Jaroslav Tulach <jtulach@netbeans.org>
6.6 */
6.7 -@ClassesMarker(number = 10)
6.8 +@ClassesMarker(number = 10, nicknames = { "Ten", "Deset" })
6.9 @ClassesNamer(name = "my text")
6.10 public class Classes {
6.11 public static String nameOfIO() {
6.12 @@ -39,6 +39,7 @@
6.13 }
6.14
6.15 private static final Class<?> PRELOAD = Runnable.class;
6.16 + private static final Class<?> PRELOAD2 = ClassesMarker.E.class;
6.17
6.18 public static boolean isInterface(String s) throws ClassNotFoundException {
6.19 return Class.forName(s).isInterface();
6.20 @@ -57,7 +58,7 @@
6.21 return new IOException().getClass().getName().toString();
6.22 }
6.23
6.24 - @ClassesMarker(number = 1)
6.25 + @ClassesMarker(number = 1, nicknames = { "One", "Jedna" } )
6.26 public static String name() {
6.27 return IOException.class.getName().toString();
6.28 }
6.29 @@ -89,6 +90,17 @@
6.30 ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
6.31 return cm == null ? -1 : cm.number();
6.32 }
6.33 + public static String getMarkerNicknames() {
6.34 + ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
6.35 + if (cm == null) {
6.36 + return null;
6.37 + }
6.38 + StringBuilder sb = new StringBuilder();
6.39 + for (String s : cm.nicknames()) {
6.40 + sb.append(s).append("\n");
6.41 + }
6.42 + return sb.toString().toString();
6.43 + }
6.44 public static String getNamer(boolean direct) {
6.45 if (direct) {
6.46 ClassesNamer cm = Classes.class.getAnnotation(ClassesNamer.class);
7.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassesMarker.java Sun Feb 03 17:55:48 2013 +0100
7.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassesMarker.java Sun Feb 03 18:58:09 2013 +0100
7.3 @@ -27,4 +27,10 @@
7.4 @Retention(RetentionPolicy.RUNTIME)
7.5 public @interface ClassesMarker {
7.6 int number();
7.7 + String[] nicknames();
7.8 + E count() default E.ONE;
7.9 +
7.10 + enum E {
7.11 + ONE, TWO;
7.12 + }
7.13 }