blob: cacf00ccb6d8006a2dc9bddcafb38ffdb35235f6 [file] [log] [blame]
/*
* Copyright 2008 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.typemodel;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.HasAnnotations;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.dev.javac.typemodel.test.AnnotatedClass;
import com.google.gwt.dev.javac.typemodel.test.ClassAnnotatedWithBinaryOnlyAnnotation;
import com.google.gwt.dev.javac.typemodel.test.ClassLiteralReferenceAnnotation;
import com.google.gwt.dev.javac.typemodel.test.PrimitiveValuesAnnotation;
import com.google.gwt.dev.javac.typemodel.test.PrimitivesAnnotatedClass;
import com.google.gwt.dev.javac.typemodel.test.SourceRetentionAnnotation;
import com.google.gwt.dev.javac.typemodel.test.TestAnnotation;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
import junit.framework.TestCase;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* Test cases for the {@link TypeOracle}'s {@link Annotation} support.
*
* Array annotations Enum annotations String from field annotations
*/
public class TypeOracleAnnotationSupportTest extends TestCase {
private static void validateAnnotation(HasAnnotations annotatedElement,
String testAnnotationValue, String nestedAnnotationValue,
TestAnnotation realAnnotation) {
assertNotNull(annotatedElement);
assertNull(annotatedElement.getAnnotation(SourceRetentionAnnotation.class));
TestAnnotation testAnnotation = annotatedElement.getAnnotation(TestAnnotation.class);
assertNotNull(testAnnotation);
// Check our proxy objects against the real thing.
assertEquals(realAnnotation, testAnnotation);
assertEquals(realAnnotation.hashCode(), testAnnotation.hashCode());
// tobyr doesn't like this.
// assertEquals(realAnnotation.toString(), testAnnotation.toString());
// checks default value
assertEquals(testAnnotationValue, testAnnotation.value());
assertEquals(nestedAnnotationValue,
testAnnotation.nestedAnnotation().value());
// Tests default values using conditional statements.
assertEquals(realAnnotation.longValue(), testAnnotation.longValue());
// Tests default value of array type.
assertEquals(realAnnotation.intArrayValue().length,
testAnnotation.intArrayValue().length);
// Tests default value which is a field reference.
assertEquals(realAnnotation.stringValue(), testAnnotation.stringValue());
// Tests default value that is a class literal.
assertEquals(realAnnotation.classLiteral(), testAnnotation.classLiteral());
// Tests implicit array initializers
Class<?>[] expectedArrayValue = realAnnotation.arrayWithImplicitArrayInitializer();
Class<?>[] actualArrayValue = testAnnotation.arrayWithImplicitArrayInitializer();
assertTrue(expectedArrayValue.length > 0);
assertEquals(expectedArrayValue.length, actualArrayValue.length);
assertEquals(expectedArrayValue[0], actualArrayValue[0]);
// Tests that empty array initializers are also handled correctly.
assertEquals(realAnnotation.emptyArray().length,
testAnnotation.emptyArray().length);
}
private final boolean logToConsole = false;
private final ModuleContext moduleContext = new ModuleContext(logToConsole
? new PrintWriterTreeLogger() : TreeLogger.NULL,
"com.google.gwt.dev.javac.typemodel.TypeOracleTest");
private final TypeOracle typeOracle = moduleContext.getOracle();
public TypeOracleAnnotationSupportTest() throws UnableToCompleteException {
}
/**
* Test that a class can be annotated.
*/
public void testAnnotatedClass() throws NotFoundException {
JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName());
TestAnnotation realAnnotation = AnnotatedClass.class.getAnnotation(TestAnnotation.class);
validateAnnotation(annotatedClass, "Class", "Foo", realAnnotation);
ClassLiteralReferenceAnnotation classReferenceAnnotation = annotatedClass.getAnnotation(ClassLiteralReferenceAnnotation.class);
assertEquals(ClassLiteralReferenceAnnotation.Foo.class,
classReferenceAnnotation.value());
assertEquals(2, annotatedClass.getAnnotations().length);
}
/**
* Test that a constructor can be annotated.
*/
public void testAnnotatedConstructor() throws NotFoundException,
SecurityException, NoSuchMethodException {
JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName());
JConstructor ctor = annotatedClass.getConstructor(TypeOracle.NO_JTYPES);
Constructor<AnnotatedClass> constructor = AnnotatedClass.class.getConstructor();
TestAnnotation realAnnotation = constructor.getAnnotation(TestAnnotation.class);
validateAnnotation(ctor, "Constructor", "Not assigned", realAnnotation);
}
/**
* Test that a field can be annotated.
*/
public void testAnnotatedField() throws NotFoundException, SecurityException,
NoSuchFieldException {
JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName());
JField annotatedField = annotatedClass.getField("annotatedField");
Field field = AnnotatedClass.class.getDeclaredField("annotatedField");
TestAnnotation realAnnotation = field.getAnnotation(TestAnnotation.class);
validateAnnotation(annotatedField, "Field", "Not assigned", realAnnotation);
}
/**
* Tests that methods can be annotated.
*/
public void testAnnotatedMethod() throws NotFoundException,
SecurityException, NoSuchMethodException {
JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName());
JMethod annotatedMethod = annotatedClass.getMethod("annotatedMethod",
TypeOracle.NO_JTYPES);
Method method = AnnotatedClass.class.getDeclaredMethod("annotatedMethod");
TestAnnotation realAnnotation = method.getAnnotation(TestAnnotation.class);
validateAnnotation(annotatedMethod, "Method", "Not assigned",
realAnnotation);
}
/**
* Tests that packages can be annotated. This necessitates the existence of a
* package-info.java file in the package that you wish to annotate.
*/
public void testAnnotatedPackage() throws NotFoundException,
ClassNotFoundException {
JPackage annotatedPackage = typeOracle.getPackage("com.google.gwt.dev.javac.typemodel.test");
assertNotNull(annotatedPackage);
TestAnnotation realAnnotation = Class.forName(
"com.google.gwt.dev.javac.typemodel.test.package-info", false,
TypeOracleAnnotationSupportTest.class.getClassLoader()).getAnnotation(
TestAnnotation.class);
validateAnnotation(annotatedPackage, "Package", "Not assigned",
realAnnotation);
}
/**
* Tests that parameters can be annotated.
*/
public void testAnnotatedParameter() throws NotFoundException,
SecurityException, NoSuchMethodException {
JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName());
JMethod jmethod = annotatedClass.getMethod("methodWithAnnotatedParameter",
new JType[]{JPrimitiveType.INT});
JParameter parameter = jmethod.getParameters()[0];
Method method = AnnotatedClass.class.getDeclaredMethod(
"methodWithAnnotatedParameter", int.class);
Annotation[][] paramAnnotations = method.getParameterAnnotations();
TestAnnotation realAnnotation = (TestAnnotation) paramAnnotations[0][0];
validateAnnotation(parameter, "Parameter", "Not assigned", realAnnotation);
}
public void testAnnotatedWithArrayOfClasses() throws NotFoundException,
SecurityException, NoSuchMethodException {
JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName());
JMethod annotatedMethod = annotatedClass.getMethod(
"annotatedWithArrayOfClasses", TypeOracle.NO_JTYPES);
Method method = AnnotatedClass.class.getDeclaredMethod("annotatedWithArrayOfClasses");
TestAnnotation realAnnotation = method.getAnnotation(TestAnnotation.class);
validateAnnotation(annotatedMethod, "Method", "Not assigned",
realAnnotation);
}
/**
* Tests translatable classes that are annotated with annotations for which we
* have no source.
*/
public void testBinaryOnlyAnnotation() throws NotFoundException {
// It is an error if we fail to get the type.
JClassType classType = typeOracle.getType(ClassAnnotatedWithBinaryOnlyAnnotation.class.getCanonicalName());
BinaryOnlyAnnotation annotation = classType.getAnnotation(BinaryOnlyAnnotation.class);
assertNotNull(annotation);
assertEquals(File.class, annotation.jreClassLiteralReference());
}
/**
* Ensures that we properly handle primitive value attributes on annotations.
* (Special-cased, because of how JDT handles char/numeric literals)
*/
public void testPrimitiveValuesAnnotations() throws NotFoundException {
JClassType primitivesAnnotatedClass = typeOracle.getType(PrimitivesAnnotatedClass.class.getName());
PrimitiveValuesAnnotation annotation = primitivesAnnotatedClass.getAnnotation(PrimitiveValuesAnnotation.class);
boolean bool = annotation.bool();
assertTrue(bool);
byte b = annotation.b();
assertTrue(b > 0);
char c = annotation.c();
assertTrue(c > 0);
double d = annotation.d();
assertTrue(d > 0);
float f = annotation.f();
assertTrue(f > 0);
int i = annotation.i();
assertTrue(i > 0);
long l = annotation.l();
assertTrue(l > 0);
short s = annotation.s();
assertTrue(s > 0);
int[] ia = annotation.ia();
assertEquals(3, ia.length);
for (int it = 0; it < 3; ++it) {
assertEquals(it, ia[it]);
}
}
}