blob: ba096e91c9069d4154b407b284b3b3210ce2b9b1 [file] [log] [blame]
/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.dev.javac.asm;
import com.google.gwt.dev.javac.typemodel.test.PrimitiveValuesAnnotation;
import com.google.gwt.dev.javac.typemodel.test.TestAnnotation;
import com.google.gwt.dev.asm.AnnotationVisitor;
import com.google.gwt.dev.asm.ClassReader;
import com.google.gwt.dev.asm.Opcodes;
import com.google.gwt.dev.asm.Type;
import com.google.gwt.dev.asm.commons.EmptyVisitor;
import com.google.gwt.dev.javac.asm.CollectAnnotationData.AnnotationData;
import com.google.gwt.dev.javac.asm.CollectClassData.ClassType;
import java.util.List;
/**
* Tests for {@link CollectClassData}.
*/
public class CollectClassDataTest extends AsmTestCase {
public static class One extends EmptyVisitor {
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
new EmptyVisitor() {
@Override
public void visit(int version, int access, String name,
String signature, String superName, String[] interfaces) {
}
};
return new CollectAnnotationData(desc, visible);
}
}
@PrimitiveValuesAnnotation(b = 42, i = 42)
protected static class Two {
public class TwoInner {
}
private final String field;
@TestAnnotation("field")
private final String annotatedField;
public Two(int a) {
this(a, null);
}
@TestAnnotation("foo")
public String foo(int a) throws IllegalStateException {
return annotatedField;
}
public Two(int a, String b) {
new TwoInner();
field = b;
annotatedField = field;
}
}
/**
* Test local classes.
*/
public static class Three {
public int foo;
/**
* Static method that has a local class in it.
*/
public static void methodWithLocalStatic() {
class Foo {
}
Foo x = new Foo();
}
/**
* Method that has a local class in it.
*/
public void methodWithLocal() {
class Foo {
Foo() {
foo = 1;
}
}
Foo x = new Foo();
}
}
public void testAnonymous() {
CollectClassData cd = collect(One.class.getName() + "$1");
// Don't access on anonymous classes, it varies among compilers
// assertEquals(0, cd.getAccess() & ~Opcodes.ACC_SUPER);
assertEquals(ClassType.Anonymous, cd.getClassType());
assertEquals(0, cd.getFields().size());
List<CollectMethodData> methods = cd.getMethods();
assertEquals(2, methods.size());
}
public void testOne() {
CollectClassData cd = collect(One.class);
// Don't check for super bit, as it will depend on the JDK used to compile.
assertEquals(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, cd.getAccess()
& ~Opcodes.ACC_SUPER);
assertEquals(ClassType.Nested, cd.getClassType());
assertEquals(0, cd.getFields().size());
assertEquals(0, cd.getInterfaces().length);
assertEquals(0, cd.getAnnotations().size());
assertEquals("com/google/gwt/dev/asm/commons/EmptyVisitor",
cd.getSuperName());
List<CollectMethodData> methods = cd.getMethods();
assertEquals(2, methods.size());
// TODO(jat): Is it safe to assume the implicit constructor is always first?
CollectMethodData method = methods.get(0);
Type[] argTypes = method.getArgTypes();
String[] argNames = method.getArgNames();
assertEquals("<init>", method.getName());
assertEquals(0, argTypes.length);
assertEquals(0, argNames.length);
assertEquals(0, method.getArgAnnotations().length);
assertEquals(0, method.getAnnotations().size());
assertEquals(0, method.getExceptions().length);
method = methods.get(1);
argTypes = method.getArgTypes();
argNames = method.getArgNames();
assertEquals("visitAnnotation", method.getName());
assertEquals(2, argTypes.length);
assertEquals("java.lang.String", argTypes[0].getClassName());
assertEquals("boolean", argTypes[1].getClassName());
assertEquals(2, argNames.length);
assertEquals("desc", argNames[0]);
assertEquals("visible", argNames[1]);
assertEquals(2, method.getArgAnnotations().length);
assertEquals(0, method.getArgAnnotations()[0].size());
assertEquals(0, method.getArgAnnotations()[1].size());
// Note that @Override is a source-only annotation
assertEquals(0, method.getAnnotations().size());
assertEquals(0, method.getExceptions().length);
}
public void testTopLevel() {
CollectClassData cd = collect(CollectClassDataTest.class);
// Don't check for super bit, as it will depend on the JDK used to compile.
assertEquals(Opcodes.ACC_PUBLIC, cd.getAccess() & ~Opcodes.ACC_SUPER);
assertEquals(ClassType.TopLevel, cd.getClassType());
}
public void testTwo() {
CollectClassData cd = collect(Two.class);
// Don't check for super bit, as it will depend on the JDK used to compile.
assertEquals(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, cd.getAccess()
& ~Opcodes.ACC_SUPER);
assertEquals(ClassType.Nested, cd.getClassType());
List<CollectFieldData> fields = cd.getFields();
assertEquals(2, fields.size());
CollectFieldData field = fields.get(0);
assertEquals("field", field.getName());
assertEquals("Ljava/lang/String;", field.getDesc());
List<CollectAnnotationData> annotations = field.getAnnotations();
assertEquals(0, annotations.size());
field = fields.get(1);
assertEquals("annotatedField", field.getName());
assertEquals("Ljava/lang/String;", field.getDesc());
annotations = field.getAnnotations();
assertEquals(1, annotations.size());
AnnotationData annotation = annotations.get(0).getAnnotation();
assertEquals("Lcom/google/gwt/dev/javac/typemodel/test/TestAnnotation;",
annotation.getDesc());
assertEquals("field", annotation.getValues().get("value"));
assertEquals(0, cd.getInterfaces().length);
annotations = cd.getAnnotations();
assertEquals(1, annotations.size());
annotation = annotations.get(0).getAnnotation();
assertEquals(
"Lcom/google/gwt/dev/javac/typemodel/test/PrimitiveValuesAnnotation;",
annotation.getDesc());
assertEquals(Byte.valueOf((byte) 42), annotation.getValues().get("b"));
assertEquals(42, annotation.getValues().get("i"));
assertEquals("java/lang/Object", cd.getSuperName());
List<CollectMethodData> methods = cd.getMethods();
assertEquals(3, methods.size());
// TODO(jat): Is it safe to assume the order?
CollectMethodData method = methods.get(0);
Type[] argTypes = method.getArgTypes();
String[] argNames = method.getArgNames();
assertEquals("<init>", method.getName());
assertEquals(1, argTypes.length);
assertEquals(1, argNames.length);
assertEquals(1, method.getArgAnnotations().length);
assertEquals(0, method.getAnnotations().size());
assertEquals(0, method.getExceptions().length);
method = methods.get(1);
argTypes = method.getArgTypes();
argNames = method.getArgNames();
assertEquals("foo", method.getName());
assertEquals(1, argTypes.length);
assertEquals("int", argTypes[0].getClassName());
assertEquals(1, argNames.length);
assertEquals("a", argNames[0]);
assertEquals(1, method.getArgAnnotations().length);
assertEquals(0, method.getArgAnnotations()[0].size());
assertEquals(1, method.getAnnotations().size());
assertEquals(1, method.getExceptions().length);
method = methods.get(2);
argTypes = method.getArgTypes();
argNames = method.getArgNames();
assertEquals("<init>", method.getName());
assertEquals(2, argTypes.length);
assertEquals("int", argTypes[0].getClassName());
assertEquals("java.lang.String", argTypes[1].getClassName());
assertEquals(2, argNames.length);
assertEquals("a", argNames[0]);
assertEquals("b", argNames[1]);
assertEquals(2, method.getArgAnnotations().length);
assertEquals(0, method.getArgAnnotations()[0].size());
assertEquals(0, method.getArgAnnotations()[1].size());
assertEquals(0, method.getAnnotations().size());
assertEquals(0, method.getExceptions().length);
}
public void testTwoInner() {
CollectClassData cd = collect(Two.TwoInner.class);
// Don't check for super bit, as it will depend on the JDK used to compile.
assertEquals(Opcodes.ACC_PUBLIC, cd.getAccess() & ~Opcodes.ACC_SUPER);
assertEquals(ClassType.Inner, cd.getClassType());
}
public void testLocal() {
CollectClassData cd = collect(Three.class.getName() + "$2Foo");
// Don't check for super bit, as it will depend on the JDK used to compile.
assertEquals(0, cd.getAccess() & ~Opcodes.ACC_SUPER);
assertEquals(ClassType.Local, cd.getClassType());
assertEquals("methodWithLocal", cd.getOuterMethodName());
}
public void testLocalStatic() {
CollectClassData cd = collect(Three.class.getName() + "$1Foo");
// Don't check for super bit, as it will depend on the JDK used to compile.
assertEquals(0, cd.getAccess() & ~Opcodes.ACC_SUPER);
assertEquals(ClassType.Local, cd.getClassType());
assertEquals("methodWithLocalStatic", cd.getOuterMethodName());
}
private CollectClassData collect(Class<?> clazz) {
return collect(clazz.getName());
}
private CollectClassData collect(String className) {
byte[] bytes = getClassBytes(className);
assertNotNull("Couldn't load bytes for " + className, bytes);
CollectClassData cv = new CollectClassData();
ClassReader reader = new ClassReader(bytes);
reader.accept(cv, 0);
return cv;
}
}