almost full support for annotations
This commit is contained in:
Generated
+35
@@ -158,6 +158,41 @@
|
||||
<option name="TAB_SIZE" value="8" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="jet">
|
||||
<option name="LINE_COMMENT_AT_FIRST_COLUMN" value="false" />
|
||||
<option name="BLOCK_COMMENT_AT_FIRST_COLUMN" value="false" />
|
||||
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
|
||||
<option name="ELSE_ON_NEW_LINE" value="true" />
|
||||
<option name="WHILE_ON_NEW_LINE" value="true" />
|
||||
<option name="CATCH_ON_NEW_LINE" value="true" />
|
||||
<option name="FINALLY_ON_NEW_LINE" value="true" />
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
|
||||
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
|
||||
<option name="ALIGN_MULTILINE_ASSIGNMENT" value="true" />
|
||||
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
|
||||
<option name="ALIGN_MULTILINE_THROWS_LIST" value="true" />
|
||||
<option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
|
||||
<option name="ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION" value="true" />
|
||||
<option name="CALL_PARAMETERS_WRAP" value="1" />
|
||||
<option name="METHOD_PARAMETERS_WRAP" value="5" />
|
||||
<option name="EXTENDS_LIST_WRAP" value="1" />
|
||||
<option name="THROWS_LIST_WRAP" value="5" />
|
||||
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
|
||||
<option name="THROWS_KEYWORD_WRAP" value="1" />
|
||||
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
|
||||
<option name="BINARY_OPERATION_WRAP" value="5" />
|
||||
<option name="TERNARY_OPERATION_WRAP" value="5" />
|
||||
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
|
||||
<option name="FOR_STATEMENT_WRAP" value="5" />
|
||||
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
|
||||
<option name="ASSIGNMENT_WRAP" value="1" />
|
||||
<option name="IF_BRACE_FORCE" value="1" />
|
||||
<option name="DOWHILE_BRACE_FORCE" value="1" />
|
||||
<option name="WHILE_BRACE_FORCE" value="1" />
|
||||
<option name="FOR_BRACE_FORCE" value="1" />
|
||||
<option name="FIELD_ANNOTATION_WRAP" value="0" />
|
||||
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
|
||||
</codeStyleSettings>
|
||||
</value>
|
||||
</option>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod;
|
||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
|
||||
@@ -37,15 +36,22 @@ import java.util.Map;
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public abstract class AnnotationCodegen {
|
||||
public void genAnnotations(Annotated annotated, JetTypeMapper typeMapper) {
|
||||
final JetTypeMapper typeMapper;
|
||||
final BindingContext bindingContext;
|
||||
|
||||
protected AnnotationCodegen(JetTypeMapper mapper) {
|
||||
typeMapper = mapper;
|
||||
bindingContext = typeMapper.bindingContext;
|
||||
}
|
||||
|
||||
public void genAnnotations(Annotated annotated) {
|
||||
if(annotated == null)
|
||||
return;
|
||||
|
||||
if(!(annotated instanceof DeclarationDescriptor))
|
||||
return;
|
||||
|
||||
BindingContext bindingContext = typeMapper.bindingContext;
|
||||
PsiElement psiElement = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, (DeclarationDescriptor) annotated);
|
||||
PsiElement psiElement = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, (DeclarationDescriptor)annotated);
|
||||
|
||||
JetModifierList modifierList = null;
|
||||
if(annotated instanceof ConstructorDescriptor && psiElement instanceof JetClass) {
|
||||
@@ -67,83 +73,118 @@ public abstract class AnnotationCodegen {
|
||||
assert annotationDescriptor != null;
|
||||
|
||||
JetType type = annotationDescriptor.getType();
|
||||
ClassifierDescriptor classifierDescriptor = type.getConstructor().getDeclarationDescriptor();
|
||||
RetentionPolicy rp = getRetentionPolicy(classifierDescriptor, typeMapper);
|
||||
if(rp != RetentionPolicy.SOURCE) {
|
||||
String internalName = typeMapper.mapType(type).getDescriptor();
|
||||
AnnotationVisitor annotationVisitor = visitAnnotation(internalName, rp == RetentionPolicy.RUNTIME);
|
||||
genAnnotation(resolvedCall, type);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
|
||||
ResolvedValueArgument valueArgument = entry.getValue();
|
||||
if (!(valueArgument instanceof DefaultValueArgument)) {
|
||||
List<ValueArgument> valueArguments = valueArgument.getArguments();
|
||||
assert valueArguments.size() == 1 : "Number of arguments on " + resolvedCall.getResultingDescriptor() + " = " + valueArguments.size(); // todo
|
||||
CompileTimeConstant<?> compileTimeConstant =
|
||||
bindingContext.get(BindingContext.COMPILE_TIME_VALUE, valueArguments.get(0).getArgumentExpression());
|
||||
private void genAnnotation(ResolvedCall<? extends CallableDescriptor> resolvedCall,
|
||||
JetType type) {
|
||||
ClassifierDescriptor classifierDescriptor = type.getConstructor().getDeclarationDescriptor();
|
||||
RetentionPolicy rp = getRetentionPolicy(classifierDescriptor, typeMapper);
|
||||
if (rp == RetentionPolicy.SOURCE) {
|
||||
return;
|
||||
}
|
||||
|
||||
String keyName = entry.getKey().getName();
|
||||
if(compileTimeConstant != null) {
|
||||
Object value = compileTimeConstant.getValue();
|
||||
annotationVisitor.visit(keyName, value);
|
||||
continue;
|
||||
}
|
||||
String internalName = typeMapper.mapType(type).getDescriptor();
|
||||
AnnotationVisitor annotationVisitor = visitAnnotation(internalName, rp == RetentionPolicy.RUNTIME);
|
||||
|
||||
ExpressionValueArgument expressionValueArgument = (ExpressionValueArgument)valueArgument;
|
||||
JetExpression expression = expressionValueArgument.getArguments().get(0).getArgumentExpression();
|
||||
if(expression instanceof JetDotQualifiedExpression) {
|
||||
JetDotQualifiedExpression qualifiedExpression = (JetDotQualifiedExpression)expression;
|
||||
ResolvedCall<? extends CallableDescriptor> call =
|
||||
bindingContext.get(BindingContext.RESOLVED_CALL, qualifiedExpression.getSelectorExpression());
|
||||
if(call != null) {
|
||||
if(call.getResultingDescriptor() instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor descriptor = (PropertyDescriptor)call.getResultingDescriptor();
|
||||
annotationVisitor.visitEnum(keyName, typeMapper.mapType(descriptor.getReturnType()).getDescriptor(),descriptor.getName());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(expression instanceof JetCallExpression) {
|
||||
JetCallExpression callExpression = (JetCallExpression)expression;
|
||||
ResolvedCall<? extends CallableDescriptor> call =
|
||||
bindingContext.get(BindingContext.RESOLVED_CALL, callExpression.getCalleeExpression());
|
||||
if(call != null) {
|
||||
List<AnnotationDescriptor> annotations = call.getResultingDescriptor().getOriginal().getAnnotations();
|
||||
String value = null;
|
||||
if (annotations != null) {
|
||||
for (AnnotationDescriptor annotation : annotations) {
|
||||
if("Intrinsic".equals(annotation.getType().getConstructor().getDeclarationDescriptor().getName())) {
|
||||
value = (String) annotation.getValueArguments().get(0).getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(IntrinsicMethods.KOTLIN_JAVA_CLASS_FUNCTION.equals(value)) {
|
||||
annotationVisitor.visit(keyName, typeMapper.mapType(call.getResultingDescriptor().getReturnType().getArguments().get(0).getType()));
|
||||
continue;
|
||||
}
|
||||
if(IntrinsicMethods.KOTLIN_ARRAYS_ARRAY.equals(value)) {
|
||||
AnnotationVisitor visitor = annotationVisitor.visitArray(keyName);
|
||||
VarargValueArgument next = (VarargValueArgument)call.getValueArguments().values().iterator().next();
|
||||
for (ValueArgument argument : next.getArguments()) {
|
||||
CompileTimeConstant<?> constant =
|
||||
bindingContext.get(BindingContext.COMPILE_TIME_VALUE, argument.getArgumentExpression());
|
||||
visitor.visit(null, constant.getValue());
|
||||
}
|
||||
visitor.visitEnd();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
getAnnotation(resolvedCall, annotationVisitor);
|
||||
|
||||
throw new IllegalStateException("Don't know how to compile annotation value");
|
||||
}
|
||||
annotationVisitor.visitEnd();
|
||||
}
|
||||
|
||||
private void getAnnotation(ResolvedCall<? extends CallableDescriptor> resolvedCall, AnnotationVisitor annotationVisitor) {
|
||||
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
|
||||
ResolvedValueArgument valueArgument = entry.getValue();
|
||||
if (valueArgument instanceof DefaultValueArgument) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String keyName = entry.getKey().getName();
|
||||
genAnnotationValueArgument(annotationVisitor, valueArgument, keyName);
|
||||
}
|
||||
}
|
||||
|
||||
private void genAnnotationValueArgument(AnnotationVisitor annotationVisitor, ResolvedValueArgument valueArgument, String keyName) {
|
||||
List<ValueArgument> valueArguments = valueArgument.getArguments();
|
||||
if(valueArgument instanceof VarargValueArgument) {
|
||||
AnnotationVisitor visitor = annotationVisitor.visitArray(keyName);
|
||||
for (ValueArgument argument : valueArguments) {
|
||||
genAnnotationExpressionValue(visitor, null, argument.getArgumentExpression());
|
||||
}
|
||||
visitor.visitEnd();
|
||||
}
|
||||
else {
|
||||
assert valueArguments.size() == 1 : "Number of arguments on " + keyName + " = " + valueArguments.size(); // todo
|
||||
JetExpression expression = valueArguments.get(0).getArgumentExpression();
|
||||
genAnnotationExpressionValue(annotationVisitor, keyName, expression);
|
||||
}
|
||||
}
|
||||
|
||||
private void genAnnotationExpressionValue(AnnotationVisitor annotationVisitor, String keyName, JetExpression expression) {
|
||||
CompileTimeConstant<?> compileTimeConstant =
|
||||
bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expression);
|
||||
|
||||
if(compileTimeConstant != null) {
|
||||
Object value = compileTimeConstant.getValue();
|
||||
annotationVisitor.visit(keyName, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if(expression instanceof JetDotQualifiedExpression) {
|
||||
JetDotQualifiedExpression qualifiedExpression = (JetDotQualifiedExpression)expression;
|
||||
ResolvedCall<? extends CallableDescriptor> call =
|
||||
bindingContext.get(BindingContext.RESOLVED_CALL, qualifiedExpression.getSelectorExpression());
|
||||
if(call != null) {
|
||||
if(call.getResultingDescriptor() instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor descriptor = (PropertyDescriptor)call.getResultingDescriptor();
|
||||
annotationVisitor.visitEnum(keyName, typeMapper.mapType(descriptor.getReturnType()).getDescriptor(),descriptor.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
annotationVisitor.visitEnd();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(expression instanceof JetCallExpression) {
|
||||
JetCallExpression callExpression = (JetCallExpression)expression;
|
||||
ResolvedCall<? extends CallableDescriptor> call =
|
||||
bindingContext.get(BindingContext.RESOLVED_CALL, callExpression.getCalleeExpression());
|
||||
if(call != null) {
|
||||
List<AnnotationDescriptor> annotations = call.getResultingDescriptor().getOriginal().getAnnotations();
|
||||
String value = null;
|
||||
if (annotations != null) {
|
||||
for (AnnotationDescriptor annotation : annotations) {
|
||||
if("Intrinsic".equals(annotation.getType().getConstructor().getDeclarationDescriptor().getName())) {
|
||||
value = (String) annotation.getValueArguments().get(0).getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(IntrinsicMethods.KOTLIN_JAVA_CLASS_FUNCTION.equals(value)) {
|
||||
annotationVisitor.visit(keyName, typeMapper.mapType(call.getResultingDescriptor().getReturnType().getArguments().get(0).getType()));
|
||||
return;
|
||||
}
|
||||
else if(IntrinsicMethods.KOTLIN_ARRAYS_ARRAY.equals(value)) {
|
||||
AnnotationVisitor visitor = annotationVisitor.visitArray(keyName);
|
||||
VarargValueArgument next = (VarargValueArgument)call.getValueArguments().values().iterator().next();
|
||||
for (ValueArgument argument : next.getArguments()) {
|
||||
genAnnotationExpressionValue(visitor, null, argument.getArgumentExpression());
|
||||
}
|
||||
visitor.visitEnd();
|
||||
return;
|
||||
}
|
||||
else if(call.getResultingDescriptor() instanceof ConstructorDescriptor) {
|
||||
ConstructorDescriptor descriptor = (ConstructorDescriptor)call.getResultingDescriptor();
|
||||
AnnotationVisitor visitor = annotationVisitor.visitAnnotation(keyName, typeMapper
|
||||
.mapType(descriptor.getContainingDeclaration().getDefaultType()).getDescriptor());
|
||||
getAnnotation(call, visitor);
|
||||
visitor.visitEnd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Don't know how to compile annotation value");
|
||||
}
|
||||
|
||||
private static RetentionPolicy getRetentionPolicy(ClassifierDescriptor descriptor, JetTypeMapper typeMapper) {
|
||||
@@ -164,8 +205,8 @@ public abstract class AnnotationCodegen {
|
||||
|
||||
abstract AnnotationVisitor visitAnnotation(String descr, boolean visible);
|
||||
|
||||
public static AnnotationCodegen forClass(final ClassVisitor cv) {
|
||||
return new AnnotationCodegen() {
|
||||
public static AnnotationCodegen forClass(final ClassVisitor cv, JetTypeMapper mapper) {
|
||||
return new AnnotationCodegen(mapper) {
|
||||
@Override
|
||||
AnnotationVisitor visitAnnotation(String descr, boolean visible) {
|
||||
return cv.visitAnnotation(descr, visible);
|
||||
@@ -173,8 +214,8 @@ public abstract class AnnotationCodegen {
|
||||
};
|
||||
}
|
||||
|
||||
public static AnnotationCodegen forMethod(final MethodVisitor mv) {
|
||||
return new AnnotationCodegen() {
|
||||
public static AnnotationCodegen forMethod(final MethodVisitor mv, JetTypeMapper mapper) {
|
||||
return new AnnotationCodegen(mapper) {
|
||||
@Override
|
||||
AnnotationVisitor visitAnnotation(String descr, boolean visible) {
|
||||
return mv.visitAnnotation(descr, visible);
|
||||
@@ -182,8 +223,8 @@ public abstract class AnnotationCodegen {
|
||||
};
|
||||
}
|
||||
|
||||
public static AnnotationCodegen forField(final FieldVisitor fv) {
|
||||
return new AnnotationCodegen() {
|
||||
public static AnnotationCodegen forField(final FieldVisitor fv, JetTypeMapper mapper) {
|
||||
return new AnnotationCodegen(mapper) {
|
||||
@Override
|
||||
AnnotationVisitor visitAnnotation(String descr, boolean visible) {
|
||||
return fv.visitAnnotation(descr, visible);
|
||||
|
||||
@@ -118,7 +118,7 @@ public class FunctionCodegen {
|
||||
if (isAbstract) flags |= ACC_ABSTRACT;
|
||||
|
||||
final MethodVisitor mv = v.newMethod(fun, flags, jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor(), jvmSignature.getGenericsSignature(), null);
|
||||
AnnotationCodegen.forMethod(mv).genAnnotations(functionDescriptor, state.getInjector().getJetTypeMapper());
|
||||
AnnotationCodegen.forMethod(mv, state.getInjector().getJetTypeMapper()).genAnnotations(functionDescriptor);
|
||||
if(v.generateCode() != ClassBuilder.Mode.SIGNATURES) {
|
||||
int start = 0;
|
||||
if (needJetAnnotations) {
|
||||
|
||||
@@ -154,7 +154,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
v.visitInnerClass(outerClassInernalName + JvmAbi.CLASS_OBJECT_SUFFIX, outerClassInernalName, JvmAbi.CLASS_OBJECT_CLASS_NAME, innerClassAccess);
|
||||
}
|
||||
|
||||
AnnotationCodegen.forClass(v.getVisitor()).genAnnotations(descriptor, typeMapper);
|
||||
AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor);
|
||||
|
||||
if (signature.getKotlinGenericSignature() != null) {
|
||||
AnnotationVisitor annotationVisitor = v.newAnnotation(myClass, JvmStdlibNames.JET_CLASS.getDescriptor(), true);
|
||||
@@ -519,7 +519,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
jetConstructorVisitor.visitEnd();
|
||||
|
||||
AnnotationCodegen.forMethod(mv).genAnnotations(constructorDescriptor, typeMapper);
|
||||
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(constructorDescriptor);
|
||||
|
||||
if (constructorDescriptor != null) {
|
||||
int i = 0;
|
||||
|
||||
@@ -98,7 +98,7 @@ public class PropertyCodegen {
|
||||
modifiers |= Opcodes.ACC_VOLATILE;
|
||||
}
|
||||
FieldVisitor fieldVisitor = v.newField(p, modifiers, p.getName(), state.getInjector().getJetTypeMapper().mapType(propertyDescriptor.getType()).getDescriptor(), null, value);
|
||||
AnnotationCodegen.forField(fieldVisitor).genAnnotations(propertyDescriptor, state.getInjector().getJetTypeMapper());
|
||||
AnnotationCodegen.forField(fieldVisitor, state.getInjector().getJetTypeMapper()).genAnnotations(propertyDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ public class PropertyCodegen {
|
||||
|
||||
if(propertyDescriptor.getGetter() != null) {
|
||||
assert !propertyDescriptor.getGetter().hasBody();
|
||||
AnnotationCodegen.forMethod(mv).genAnnotations(propertyDescriptor.getGetter(), state.getInjector().getJetTypeMapper());
|
||||
AnnotationCodegen.forMethod(mv, state.getInjector().getJetTypeMapper()).genAnnotations(propertyDescriptor.getGetter());
|
||||
}
|
||||
|
||||
if (v.generateCode() != ClassBuilder.Mode.SIGNATURES && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
|
||||
@@ -246,7 +246,7 @@ public class PropertyCodegen {
|
||||
|
||||
if(propertyDescriptor.getSetter() != null) {
|
||||
assert !propertyDescriptor.getSetter().hasBody();
|
||||
AnnotationCodegen.forMethod(mv).genAnnotations(propertyDescriptor.getSetter(), state.getInjector().getJetTypeMapper());
|
||||
AnnotationCodegen.forMethod(mv, state.getInjector().getJetTypeMapper()).genAnnotations(propertyDescriptor.getSetter());
|
||||
}
|
||||
|
||||
if (v.generateCode() != ClassBuilder.Mode.SIGNATURES && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
|
||||
|
||||
@@ -18,9 +18,7 @@ package org.jetbrains.jet.codegen;
|
||||
|
||||
import jet.JetObject;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -120,4 +118,42 @@ public class AnnotationGenTest extends CodegenTestCase {
|
||||
|
||||
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" +
|
||||
"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));
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,7 @@ import org.jetbrains.jet.compiler.CompileEnvironment;
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
@@ -269,4 +267,55 @@ public class StdlibTest extends CodegenTestCase {
|
||||
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" +
|
||||
"" +
|
||||
"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" +
|
||||
"" +
|
||||
"Retention(RetentionPolicy.RUNTIME) annotation class A(val a: Array<Retention>)\n" +
|
||||
"" +
|
||||
"A(array(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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user