47c7181f2a
The main reasoning for the module is to avoid running any compiler tests while executing run configuration that searches tests across module dependencies.
392 lines
17 KiB
Java
392 lines
17 KiB
Java
/*
|
|
* Copyright 2010-2016 JetBrains s.r.o.
|
|
*
|
|
* 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 org.jetbrains.kotlin.codegen;
|
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.jetbrains.kotlin.test.ConfigurationKind;
|
|
|
|
import java.lang.annotation.*;
|
|
import java.lang.reflect.*;
|
|
|
|
public class AnnotationGenTest extends CodegenTestCase {
|
|
@Override
|
|
protected void setUp() throws Exception {
|
|
super.setUp();
|
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL);
|
|
}
|
|
|
|
public void testVolatileProperty() throws Exception {
|
|
loadText("abstract class Foo { @Volatile public var x: String = \"\"; }");
|
|
Class<?> aClass = generateClass("Foo");
|
|
Field x = aClass.getDeclaredField("x");
|
|
assertTrue((x.getModifiers() & Modifier.VOLATILE) != 0);
|
|
}
|
|
|
|
public void testPropField() throws Exception {
|
|
loadText("@[java.lang.Deprecated] var x = 0");
|
|
Class<?> srcClass = generateFacadeClass();
|
|
assertNull(srcClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
|
|
assertNull(srcClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
|
|
assertNotNull(srcClass.getDeclaredField("x").getAnnotation(Deprecated.class));
|
|
}
|
|
|
|
public void testPropGetter() throws Exception {
|
|
loadText("var x = 0\n" +
|
|
"@[java.lang.Deprecated] get");
|
|
Class<?> srcClass = generateFacadeClass();
|
|
assertNotNull(srcClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
|
|
assertNull(srcClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
|
|
assertNull(srcClass.getDeclaredField("x").getAnnotation(Deprecated.class));
|
|
}
|
|
|
|
public void testPropSetter() throws Exception {
|
|
loadText("var x = 0\n" +
|
|
"@[java.lang.Deprecated] set");
|
|
Class<?> scrClass = generateFacadeClass();
|
|
assertNull(scrClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
|
|
assertNotNull(scrClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
|
|
assertNull(scrClass.getDeclaredField("x").getAnnotation(Deprecated.class));
|
|
}
|
|
|
|
public void testAnnotationForParamInTopLevelFunction() throws Exception {
|
|
loadText("fun x(@[java.lang.Deprecated] i: Int) {}");
|
|
Class<?> srcClass = generateFacadeClass();
|
|
Method srcClassMethod = srcClass.getMethod("x", int.class);
|
|
assertNotNull(srcClassMethod);
|
|
assertNotNull(getDeprecatedAnnotationFromList(srcClassMethod.getParameterAnnotations()[0]));
|
|
}
|
|
|
|
public void testAnnotationForParamInInstanceFunction() throws NoSuchFieldException, NoSuchMethodException {
|
|
loadText("class A() { fun x(@[java.lang.Deprecated] i: Int) {}}");
|
|
Class<?> aClass = generateClass("A");
|
|
Method x = aClass.getMethod("x", int.class);
|
|
assertNotNull(x);
|
|
// Get annotations for first parameter
|
|
Annotation[] annotations = x.getParameterAnnotations()[0];
|
|
assertNotNull(getDeprecatedAnnotationFromList(annotations));
|
|
}
|
|
|
|
public void testAnnotationForParamInInstanceExtensionFunction() throws NoSuchFieldException, NoSuchMethodException {
|
|
loadText("class A() { fun String.x(@[java.lang.Deprecated] i: Int) {}}");
|
|
Class<?> aClass = generateClass("A");
|
|
Method x = aClass.getMethod("x", String.class, int.class);
|
|
assertNotNull(x);
|
|
// Get annotations for first real parameter
|
|
Annotation[] annotations = x.getParameterAnnotations()[1];
|
|
assertNotNull(getDeprecatedAnnotationFromList(annotations));
|
|
}
|
|
|
|
public void testParamInConstructor() throws NoSuchFieldException, NoSuchMethodException {
|
|
loadText("class A (@[java.lang.Deprecated] x: Int) {}");
|
|
Class<?> aClass = generateClass("A");
|
|
Constructor constructor = aClass.getDeclaredConstructor(int.class);
|
|
assertNotNull(constructor);
|
|
// Get annotations for first parameter
|
|
Annotation[] annotations = constructor.getParameterAnnotations()[0];
|
|
assertNotNull(getDeprecatedAnnotationFromList(annotations));
|
|
}
|
|
|
|
public void testParamInEnumConstructor() throws NoSuchFieldException, NoSuchMethodException {
|
|
loadText("enum class E(@[java.lang.Deprecated] p: String)");
|
|
Class<?> klass = generateClass("E");
|
|
Constructor constructor = klass.getDeclaredConstructor(String.class, int.class, String.class);
|
|
assertNotNull(constructor);
|
|
// Get annotations for first parameter
|
|
Annotation[] annotations = constructor.getParameterAnnotations()[0];
|
|
assertNotNull(getDeprecatedAnnotationFromList(annotations));
|
|
}
|
|
|
|
public void testParamInInnerConstructor() throws NoSuchFieldException, NoSuchMethodException {
|
|
loadText("class Outer { inner class Inner(@[java.lang.Deprecated] x: Int) }");
|
|
Class<?> outer = generateClass("Outer");
|
|
Class<?> inner = outer.getDeclaredClasses()[0];
|
|
Constructor constructor = inner.getDeclaredConstructor(outer, int.class);
|
|
assertNotNull(constructor);
|
|
// Get annotations for first parameter
|
|
Annotation[] annotations = constructor.getParameterAnnotations()[0];
|
|
assertNotNull(getDeprecatedAnnotationFromList(annotations));
|
|
}
|
|
|
|
public void testPropFieldInConstructor() throws NoSuchFieldException, NoSuchMethodException {
|
|
loadText("class A (@field:java.lang.Deprecated @param:java.lang.Deprecated var x: Int) {}");
|
|
Class<?> aClass = generateClass("A");
|
|
Constructor constructor = aClass.getDeclaredConstructor(int.class);
|
|
assertNotNull(constructor);
|
|
// Get annotations for first parameter
|
|
Annotation[] annotations = constructor.getParameterAnnotations()[0];
|
|
assertNotNull(getDeprecatedAnnotationFromList(annotations));
|
|
assertNull(aClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
|
|
assertNull(aClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
|
|
assertNotNull(aClass.getDeclaredField("x").getAnnotation(Deprecated.class));
|
|
}
|
|
|
|
public void testAnnotationWithParamForParamInFunction() throws Exception {
|
|
loadText("import java.lang.annotation.*\n" +
|
|
"@java.lang.annotation.Retention(RetentionPolicy.RUNTIME) annotation class A(val a: String)\n" +
|
|
"fun x(@A(\"239\") i: Int) {}");
|
|
Class<?> packageClass = generateFacadeClass();
|
|
Method packageClassMethod = packageClass.getMethod("x", int.class);
|
|
assertNotNull(packageClassMethod);
|
|
assertNotNull(getAnnotationByName(packageClassMethod.getParameterAnnotations()[0], "A"));
|
|
}
|
|
|
|
@Nullable
|
|
private static Annotation getAnnotationByName(@NotNull Annotation[] annotations, @NotNull String name) {
|
|
for (Annotation annotation : annotations) {
|
|
if (annotation.annotationType().getCanonicalName().equals(name)) {
|
|
return annotation;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private static Deprecated getDeprecatedAnnotationFromList(Annotation[] annotations) {
|
|
for (Annotation annotation : annotations) {
|
|
if (annotation instanceof Deprecated) {
|
|
return (Deprecated) annotation;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public void testConstructor() throws NoSuchFieldException, NoSuchMethodException {
|
|
loadText("class A @[java.lang.Deprecated] constructor() {}");
|
|
Class<?> aClass = generateClass("A");
|
|
Constructor x = aClass.getDeclaredConstructor();
|
|
Deprecated annotation = (Deprecated) x.getAnnotation(Deprecated.class);
|
|
assertNotNull(annotation);
|
|
}
|
|
|
|
public void testMethod() throws Exception {
|
|
loadText("@[java.lang.Deprecated] fun x () {}");
|
|
Class<?> srcClass = generateFacadeClass();
|
|
Method srcClassMethod = srcClass.getDeclaredMethod("x");
|
|
assertNotNull(srcClassMethod.getAnnotation(Deprecated.class));
|
|
}
|
|
|
|
public void testClass() throws NoSuchFieldException, NoSuchMethodException {
|
|
loadText("@[java.lang.Deprecated] class A () {}");
|
|
Class aClass = generateClass("A");
|
|
Deprecated annotation = (Deprecated) aClass.getAnnotation(Deprecated.class);
|
|
assertNotNull(annotation);
|
|
}
|
|
|
|
public void testSimplestAnnotationClass() {
|
|
loadText("annotation class A");
|
|
Class<?> aClass = generateClass("A");
|
|
Class[] interfaces = aClass.getInterfaces();
|
|
assertEquals(0, aClass.getDeclaredMethods().length);
|
|
assertTrue(aClass.isAnnotation());
|
|
assertEquals(1, interfaces.length);
|
|
assertEquals("java.lang.annotation.Annotation", interfaces[0].getName());
|
|
}
|
|
|
|
public void testAnnotationClassWithStringProperty()
|
|
throws
|
|
NoSuchFieldException,
|
|
NoSuchMethodException,
|
|
ClassNotFoundException,
|
|
IllegalAccessException,
|
|
InstantiationException,
|
|
InvocationTargetException {
|
|
loadText("import java.lang.annotation.*\n" +
|
|
"" +
|
|
"@java.lang.annotation.Retention(RetentionPolicy.RUNTIME) annotation class A(val a: String)\n" +
|
|
"" +
|
|
"@A(\"239\") class B()");
|
|
Class aClass = generateClass("A");
|
|
|
|
Retention annotation = (Retention)aClass.getAnnotation(Retention.class);
|
|
RetentionPolicy value = annotation.value();
|
|
assertEquals(RetentionPolicy.RUNTIME, value);
|
|
|
|
Method[] methods = aClass.getDeclaredMethods();
|
|
assertEquals(1, methods.length);
|
|
assertEquals("a", methods[0].getName());
|
|
assertEquals(String.class, methods[0].getReturnType());
|
|
assertEquals(0, methods[0].getParameterTypes().length);
|
|
assertTrue(aClass.isAnnotation());
|
|
|
|
Class<?> bClass = aClass.getClassLoader().loadClass("B");
|
|
Annotation bClassAnnotation = bClass.getAnnotation(aClass);
|
|
assertNotNull(bClassAnnotation);
|
|
|
|
assertEquals("239", methods[0].invoke(bClassAnnotation));
|
|
}
|
|
|
|
public void testAnnotationClassWithAnnotationProperty()
|
|
throws
|
|
NoSuchFieldException,
|
|
NoSuchMethodException,
|
|
ClassNotFoundException,
|
|
IllegalAccessException,
|
|
InstantiationException,
|
|
InvocationTargetException {
|
|
loadText("import java.lang.annotation.*\n" +
|
|
"" +
|
|
"annotation class C(val c: String)\n" +
|
|
"@java.lang.annotation.Retention(RetentionPolicy.RUNTIME) annotation class A(val a: C)\n" +
|
|
"" +
|
|
"@A(C(\"239\")) class B()");
|
|
Class aClass = generateClass("A");
|
|
|
|
Retention annotation = (Retention)aClass.getAnnotation(Retention.class);
|
|
RetentionPolicy value = annotation.value();
|
|
assertEquals(RetentionPolicy.RUNTIME, value);
|
|
|
|
Method[] methods = aClass.getDeclaredMethods();
|
|
assertEquals(1, methods.length);
|
|
assertEquals("a", methods[0].getName());
|
|
assertEquals("C", methods[0].getReturnType().getName());
|
|
assertEquals(0, methods[0].getParameterTypes().length);
|
|
assertTrue(aClass.isAnnotation());
|
|
|
|
Class<?> bClass = aClass.getClassLoader().loadClass("B");
|
|
Annotation bClassAnnotation = bClass.getAnnotation(aClass);
|
|
assertNotNull(bClassAnnotation);
|
|
|
|
Object invoke = methods[0].invoke(bClassAnnotation);
|
|
// there is some Proxy here
|
|
Class<?> cClass = invoke.getClass().getInterfaces()[0];
|
|
assertEquals("C", cClass.getName());
|
|
assertEquals("239", cClass.getDeclaredMethod("c").invoke(invoke));
|
|
}
|
|
|
|
public void testAnnotationClassWithStringArrayProperty()
|
|
throws
|
|
NoSuchFieldException,
|
|
NoSuchMethodException,
|
|
ClassNotFoundException,
|
|
IllegalAccessException,
|
|
InstantiationException,
|
|
InvocationTargetException {
|
|
loadText("import java.lang.annotation.*\n" +
|
|
"" +
|
|
"@java.lang.annotation.Retention(RetentionPolicy.RUNTIME) annotation class A(val a: Array<String>)\n" +
|
|
"" +
|
|
"@A(arrayOf(\"239\",\"932\")) class B()");
|
|
Class aClass = generateClass("A");
|
|
|
|
Retention annotation = (Retention)aClass.getAnnotation(Retention.class);
|
|
RetentionPolicy value = annotation.value();
|
|
assertEquals(RetentionPolicy.RUNTIME, value);
|
|
|
|
Method[] methods = aClass.getDeclaredMethods();
|
|
assertEquals(1, methods.length);
|
|
assertEquals("a", methods[0].getName());
|
|
assertEquals(String[].class, methods[0].getReturnType());
|
|
assertEquals(0, methods[0].getParameterTypes().length);
|
|
assertTrue(aClass.isAnnotation());
|
|
|
|
Class<?> bClass = aClass.getClassLoader().loadClass("B");
|
|
Annotation bClassAnnotation = bClass.getAnnotation(aClass);
|
|
assertNotNull(bClassAnnotation);
|
|
|
|
Object invoke = methods[0].invoke(bClassAnnotation);
|
|
assertEquals("239", ((String[])invoke)[0]);
|
|
assertEquals("932", ((String[])invoke)[1]);
|
|
}
|
|
|
|
public void testAnnotationClassWithIntArrayProperty()
|
|
throws
|
|
NoSuchFieldException,
|
|
NoSuchMethodException,
|
|
ClassNotFoundException,
|
|
IllegalAccessException,
|
|
InstantiationException,
|
|
InvocationTargetException {
|
|
loadText("import java.lang.annotation.*\n" +
|
|
"" +
|
|
"@java.lang.annotation.Retention(RetentionPolicy.RUNTIME) annotation class A(val a: IntArray)\n" +
|
|
"" +
|
|
"@A(intArrayOf(239,932)) class B()");
|
|
Class aClass = generateClass("A");
|
|
|
|
Retention annotation = (Retention)aClass.getAnnotation(Retention.class);
|
|
RetentionPolicy value = annotation.value();
|
|
assertEquals(RetentionPolicy.RUNTIME, value);
|
|
|
|
Method[] methods = aClass.getDeclaredMethods();
|
|
assertEquals(1, methods.length);
|
|
assertEquals("a", methods[0].getName());
|
|
assertEquals(int[].class, methods[0].getReturnType());
|
|
assertEquals(0, methods[0].getParameterTypes().length);
|
|
assertTrue(aClass.isAnnotation());
|
|
|
|
Class<?> bClass = aClass.getClassLoader().loadClass("B");
|
|
Annotation bClassAnnotation = bClass.getAnnotation(aClass);
|
|
assertNotNull(bClassAnnotation);
|
|
|
|
Object invoke = methods[0].invoke(bClassAnnotation);
|
|
assertEquals(239, ((int[])invoke)[0]);
|
|
assertEquals(932, ((int[])invoke)[1]);
|
|
}
|
|
|
|
public void testAnnotationClassWithEnumArrayProperty()
|
|
throws
|
|
NoSuchFieldException,
|
|
NoSuchMethodException,
|
|
ClassNotFoundException,
|
|
IllegalAccessException,
|
|
InstantiationException,
|
|
InvocationTargetException {
|
|
loadText("import java.lang.annotation.*\n" +
|
|
"" +
|
|
"@java.lang.annotation.Target(ElementType.TYPE, ElementType.METHOD) annotation class A");
|
|
Class aClass = generateClass("A");
|
|
|
|
Target annotation = (Target)aClass.getAnnotation(Target.class);
|
|
ElementType[] value = annotation.value();
|
|
assertEquals(2, value.length);
|
|
|
|
assertEquals(ElementType.TYPE, value[0]);
|
|
assertEquals(ElementType.METHOD, value[1]);
|
|
}
|
|
|
|
public void testAnnotationClassWithAnnotationArrayProperty()
|
|
throws
|
|
NoSuchFieldException,
|
|
NoSuchMethodException,
|
|
ClassNotFoundException,
|
|
IllegalAccessException,
|
|
InstantiationException,
|
|
InvocationTargetException {
|
|
loadText("import java.lang.annotation.*\n" +
|
|
"import java.lang.annotation.Retention\n" +
|
|
"" +
|
|
"@Retention(RetentionPolicy.RUNTIME) annotation class A(val a: Array<Retention>)\n" +
|
|
"" +
|
|
"@A(arrayOf(Retention(RetentionPolicy.RUNTIME),Retention(RetentionPolicy.SOURCE))) class B()");
|
|
Class aClass = generateClass("A");
|
|
|
|
Method[] methods = aClass.getDeclaredMethods();
|
|
assertEquals(1, methods.length);
|
|
assertEquals("a", methods[0].getName());
|
|
|
|
Class<?> bClass = aClass.getClassLoader().loadClass("B");
|
|
Annotation bClassAnnotation = bClass.getAnnotation(aClass);
|
|
assertNotNull(bClassAnnotation);
|
|
|
|
Object invoke = methods[0].invoke(bClassAnnotation);
|
|
Retention[] invoke1 = (Retention[])invoke;
|
|
assertEquals(2, invoke1.length);
|
|
assertEquals(invoke1[0].value(), RetentionPolicy.RUNTIME);
|
|
assertEquals(invoke1[1].value(), RetentionPolicy.SOURCE);
|
|
}
|
|
}
|