more annotations
This commit is contained in:
@@ -17,20 +17,17 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
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.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
|
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.DefaultValueArgument;
|
import org.jetbrains.jet.lang.resolve.calls.*;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
|
||||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedValueArgument;
|
|
||||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.objectweb.asm.AnnotationVisitor;
|
import org.objectweb.asm.*;
|
||||||
import org.objectweb.asm.ClassVisitor;
|
|
||||||
import org.objectweb.asm.FieldVisitor;
|
|
||||||
import org.objectweb.asm.MethodVisitor;
|
|
||||||
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -80,12 +77,67 @@ public abstract class AnnotationCodegen {
|
|||||||
ResolvedValueArgument valueArgument = entry.getValue();
|
ResolvedValueArgument valueArgument = entry.getValue();
|
||||||
if (!(valueArgument instanceof DefaultValueArgument)) {
|
if (!(valueArgument instanceof DefaultValueArgument)) {
|
||||||
List<ValueArgument> valueArguments = valueArgument.getArguments();
|
List<ValueArgument> valueArguments = valueArgument.getArguments();
|
||||||
assert valueArguments.size() == 1 : "Number of assertions on " + resolvedCall.getResultingDescriptor() + " = " + valueArguments.size(); // todo
|
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());
|
CompileTimeConstant<?> compileTimeConstant =
|
||||||
assert compileTimeConstant != null;
|
bindingContext.get(BindingContext.COMPILE_TIME_VALUE, valueArguments.get(0).getArgumentExpression());
|
||||||
|
|
||||||
Object value = compileTimeConstant.getValue();
|
String keyName = entry.getKey().getName();
|
||||||
annotationVisitor.visit(entry.getKey().getName(), value);
|
if(compileTimeConstant != null) {
|
||||||
|
Object value = compileTimeConstant.getValue();
|
||||||
|
annotationVisitor.visit(keyName, value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Don't know how to compile annotation value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
|
||||||
|
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author max
|
* @author max
|
||||||
* @author yole
|
* @author yole
|
||||||
@@ -99,27 +102,33 @@ public abstract class ClassBodyCodegen {
|
|||||||
functionCodegen.gen(declaration);
|
functionCodegen.gen(declaration);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen, PsiElement origin) {
|
private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen, JetClassOrObject origin) {
|
||||||
|
boolean isAnnotation = origin instanceof JetClass && ((JetClass)origin).isAnnotation();
|
||||||
OwnerKind kind = context.getContextKind();
|
OwnerKind kind = context.getContextKind();
|
||||||
for (JetParameter p : getPrimaryConstructorParameters()) {
|
for (JetParameter p : getPrimaryConstructorParameters()) {
|
||||||
if (p.getValOrVarNode() != null) {
|
if (p.getValOrVarNode() != null) {
|
||||||
PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
|
PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
|
||||||
if (propertyDescriptor != null) {
|
if (propertyDescriptor != null) {
|
||||||
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p);
|
if(!isAnnotation) {
|
||||||
if (propertyDescriptor.isVar()) {
|
propertyCodegen.generateDefaultGetter(propertyDescriptor, ACC_PUBLIC, p);
|
||||||
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, origin);
|
if (propertyDescriptor.isVar()) {
|
||||||
}
|
propertyCodegen.generateDefaultSetter(propertyDescriptor, ACC_PUBLIC, origin);
|
||||||
|
}
|
||||||
|
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
if (!(kind instanceof OwnerKind.DelegateKind) && state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
|
if (!(kind instanceof OwnerKind.DelegateKind) && state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
|
||||||
int modifiers = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0);
|
int modifiers = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0);
|
||||||
if (!propertyDescriptor.isVar()) {
|
if (!propertyDescriptor.isVar()) {
|
||||||
modifiers |= Opcodes.ACC_FINAL;
|
modifiers |= Opcodes.ACC_FINAL;
|
||||||
|
}
|
||||||
|
if(state.getInjector().getJetStandardLibrary().isVolatile(propertyDescriptor)) {
|
||||||
|
modifiers |= Opcodes.ACC_VOLATILE;
|
||||||
|
}
|
||||||
|
v.newField(p, modifiers, p.getName(), state.getInjector().getJetTypeMapper().mapType(propertyDescriptor.getType()).getDescriptor(), null, null);
|
||||||
}
|
}
|
||||||
if(state.getInjector().getJetStandardLibrary().isVolatile(propertyDescriptor)) {
|
}
|
||||||
modifiers |= Opcodes.ACC_VOLATILE;
|
else {
|
||||||
}
|
v.newMethod(p, ACC_PUBLIC|ACC_ABSTRACT, p.getName(), "()" + state.getInjector().getJetTypeMapper().mapType(propertyDescriptor.getType()).getDescriptor(), null, null);
|
||||||
v.newField(p, modifiers, p.getName(), state.getInjector().getJetTypeMapper().mapType(propertyDescriptor.getType()).getDescriptor(), null, null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,7 +144,7 @@ public abstract class ClassBodyCodegen {
|
|||||||
|
|
||||||
private void generateStaticInitializer() {
|
private void generateStaticInitializer() {
|
||||||
if (staticInitializerChunks.size() > 0) {
|
if (staticInitializerChunks.size() > 0) {
|
||||||
final MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,"<clinit>", "()V", null, null);
|
final MethodVisitor mv = v.newMethod(null, ACC_PUBLIC | Opcodes.ACC_STATIC,"<clinit>", "()V", null, null);
|
||||||
if (v.generateCode() == ClassBuilder.Mode.FULL) {
|
if (v.generateCode() == ClassBuilder.Mode.FULL) {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
boolean isInterface = false;
|
boolean isInterface = false;
|
||||||
boolean isFinal = false;
|
boolean isFinal = false;
|
||||||
boolean isStatic = false;
|
boolean isStatic = false;
|
||||||
|
boolean isAnnotation = false;
|
||||||
|
|
||||||
if(myClass instanceof JetClass) {
|
if(myClass instanceof JetClass) {
|
||||||
JetClass jetClass = (JetClass) myClass;
|
JetClass jetClass = (JetClass) myClass;
|
||||||
if (jetClass.hasModifier(JetTokens.ABSTRACT_KEYWORD))
|
if (jetClass.hasModifier(JetTokens.ABSTRACT_KEYWORD))
|
||||||
@@ -81,6 +82,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
isAbstract = true;
|
isAbstract = true;
|
||||||
isInterface = true;
|
isInterface = true;
|
||||||
}
|
}
|
||||||
|
if (jetClass.isAnnotation()) {
|
||||||
|
isAbstract = true;
|
||||||
|
isInterface = true;
|
||||||
|
isAnnotation = true;
|
||||||
|
signature.getInterfaces().add("java/lang/annotation/Annotation");
|
||||||
|
}
|
||||||
if (!jetClass.hasModifier(JetTokens.OPEN_KEYWORD) && !isAbstract) {
|
if (!jetClass.hasModifier(JetTokens.OPEN_KEYWORD) && !isAbstract) {
|
||||||
isFinal = true;
|
isFinal = true;
|
||||||
}
|
}
|
||||||
@@ -103,6 +110,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
if (isStatic) {
|
if (isStatic) {
|
||||||
access |= ACC_STATIC;
|
access |= ACC_STATIC;
|
||||||
}
|
}
|
||||||
|
if (isAnnotation) {
|
||||||
|
access |= ACC_ANNOTATION;
|
||||||
|
}
|
||||||
v.defineClass(myClass, V1_6,
|
v.defineClass(myClass, V1_6,
|
||||||
access,
|
access,
|
||||||
signature.getName(),
|
signature.getName(),
|
||||||
@@ -407,8 +417,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void generatePrimaryConstructor() {
|
protected void generatePrimaryConstructor() {
|
||||||
if(myClass instanceof JetClass && ((JetClass) myClass).isTrait())
|
if(myClass instanceof JetClass) {
|
||||||
return;
|
JetClass aClass = (JetClass)myClass;
|
||||||
|
if(aClass.isTrait())
|
||||||
|
return;
|
||||||
|
if(aClass.isAnnotation()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass);
|
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass);
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ public class IntrinsicMethods {
|
|||||||
public static final ArraySet ARRAY_SET = new ArraySet();
|
public static final ArraySet ARRAY_SET = new ArraySet();
|
||||||
public static final ArrayGet ARRAY_GET = new ArrayGet();
|
public static final ArrayGet ARRAY_GET = new ArrayGet();
|
||||||
public static final StringPlus STRING_PLUS = new StringPlus();
|
public static final StringPlus STRING_PLUS = new StringPlus();
|
||||||
|
public static final String KOTLIN_JAVA_CLASS_FUNCTION = "kotlin.javaClass.function";
|
||||||
|
public static final String KOTLIN_ARRAYS_ARRAY = "kotlin.arrays.array";
|
||||||
|
public static final String KOTLIN_JAVA_CLASS_PROPERTY = "kotlin.javaClass.property";
|
||||||
|
|
||||||
private Project myProject;
|
private Project myProject;
|
||||||
private JetStandardLibrary myStdLib;
|
private JetStandardLibrary myStdLib;
|
||||||
@@ -83,9 +86,9 @@ public class IntrinsicMethods {
|
|||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
namedMethods.put("kotlin.javaClass.function", new JavaClassFunction());
|
namedMethods.put(KOTLIN_JAVA_CLASS_FUNCTION, new JavaClassFunction());
|
||||||
namedMethods.put("kotlin.javaClass.property", new JavaClassProperty());
|
namedMethods.put(KOTLIN_JAVA_CLASS_PROPERTY, new JavaClassProperty());
|
||||||
namedMethods.put("kotlin.arrays.array", new JavaClassArray());
|
namedMethods.put(KOTLIN_ARRAYS_ARRAY, new JavaClassArray());
|
||||||
|
|
||||||
List<String> primitiveCastMethods = OperatorConventions.NUMBER_CONVERSIONS.asList();
|
List<String> primitiveCastMethods = OperatorConventions.NUMBER_CONVERSIONS.asList();
|
||||||
for (String method : primitiveCastMethods) {
|
for (String method : primitiveCastMethods) {
|
||||||
@@ -249,6 +252,21 @@ public class IntrinsicMethods {
|
|||||||
return descriptor.getMemberScope(typeParameters);
|
return descriptor.getMemberScope(typeParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IntrinsicMethod isIntrinsicMethod(DeclarationDescriptor descriptor) {
|
||||||
|
List<AnnotationDescriptor> annotations = descriptor.getAnnotations();
|
||||||
|
if (annotations != null) {
|
||||||
|
for (AnnotationDescriptor annotation : annotations) {
|
||||||
|
if("Intrinsic".equals(annotation.getType().getConstructor().getDeclarationDescriptor().getName())) {
|
||||||
|
String value = (String) annotation.getValueArguments().get(0).getValue();
|
||||||
|
IntrinsicMethod intrinsicMethod = namedMethods.get(value);
|
||||||
|
if(intrinsicMethod != null)
|
||||||
|
return intrinsicMethod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public IntrinsicMethod getIntrinsic(DeclarationDescriptor descriptor) {
|
public IntrinsicMethod getIntrinsic(DeclarationDescriptor descriptor) {
|
||||||
IntrinsicMethod intrinsicMethod = myMethods.get(descriptor.getOriginal());
|
IntrinsicMethod intrinsicMethod = myMethods.get(descriptor.getOriginal());
|
||||||
if(intrinsicMethod == null) {
|
if(intrinsicMethod == null) {
|
||||||
|
|||||||
@@ -143,6 +143,10 @@ public class JetClass extends JetTypeParameterListOwner
|
|||||||
return findChildByType(JetTokens.TRAIT_KEYWORD) != null;
|
return findChildByType(JetTokens.TRAIT_KEYWORD) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAnnotation() {
|
||||||
|
return hasModifier(JetTokens.ANNOTATION_KEYWORD);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IStubElementType getElementType() {
|
public IStubElementType getElementType() {
|
||||||
// TODO (stubs)
|
// TODO (stubs)
|
||||||
|
|||||||
@@ -16,7 +16,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.codegen;
|
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.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
public class AnnotationGenTest extends CodegenTestCase {
|
public class AnnotationGenTest extends CodegenTestCase {
|
||||||
@@ -70,4 +76,48 @@ public class AnnotationGenTest extends CodegenTestCase {
|
|||||||
Deprecated annotation = (Deprecated) aClass.getAnnotation(Deprecated.class);
|
Deprecated annotation = (Deprecated) aClass.getAnnotation(Deprecated.class);
|
||||||
assertNotNull(annotation);
|
assertNotNull(annotation);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public void testSimplestAnnotationClass() throws NoSuchFieldException, NoSuchMethodException {
|
||||||
|
loadText("annotation class A");
|
||||||
|
Class aClass = generateClass("A");
|
||||||
|
Class[] interfaces = aClass.getInterfaces();
|
||||||
|
assertEquals(2, interfaces.length);
|
||||||
|
assertEquals(0, aClass.getDeclaredMethods().length);
|
||||||
|
assertTrue(Annotation.class == interfaces[0] || Annotation.class == interfaces[1]);
|
||||||
|
assertTrue(JetObject.class == interfaces[0] || JetObject.class == interfaces[1]);
|
||||||
|
assertTrue(aClass.isAnnotation());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAnnotationClassWithStringProperty()
|
||||||
|
throws
|
||||||
|
NoSuchFieldException,
|
||||||
|
NoSuchMethodException,
|
||||||
|
ClassNotFoundException,
|
||||||
|
IllegalAccessException,
|
||||||
|
InstantiationException,
|
||||||
|
InvocationTargetException {
|
||||||
|
loadText("import java.lang.annotation.*\n" +
|
||||||
|
"" +
|
||||||
|
"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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,8 @@ import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
@@ -164,4 +166,107 @@ public class StdlibTest extends CodegenTestCase {
|
|||||||
loader.dispose();
|
loader.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testAnnotationClassWithClassProperty()
|
||||||
|
throws
|
||||||
|
NoSuchFieldException,
|
||||||
|
NoSuchMethodException,
|
||||||
|
ClassNotFoundException,
|
||||||
|
IllegalAccessException,
|
||||||
|
InstantiationException,
|
||||||
|
InvocationTargetException {
|
||||||
|
loadText("import java.lang.annotation.*\n" +
|
||||||
|
"" +
|
||||||
|
"Retention(RetentionPolicy.RUNTIME) annotation class A(val a: java.lang.Class<*>)\n" +
|
||||||
|
"" +
|
||||||
|
"A(javaClass<String>()) 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(Class.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(String.class, methods[0].invoke(bClassAnnotation));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAnnotationClassWithStringArrayProperty()
|
||||||
|
throws
|
||||||
|
NoSuchFieldException,
|
||||||
|
NoSuchMethodException,
|
||||||
|
ClassNotFoundException,
|
||||||
|
IllegalAccessException,
|
||||||
|
InstantiationException,
|
||||||
|
InvocationTargetException {
|
||||||
|
loadText("import java.lang.annotation.*\n" +
|
||||||
|
"" +
|
||||||
|
"Retention(RetentionPolicy.RUNTIME) annotation class A(val a: Array<String>)\n" +
|
||||||
|
"" +
|
||||||
|
"A(array(\"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" +
|
||||||
|
"" +
|
||||||
|
"Retention(RetentionPolicy.RUNTIME) annotation class A(val a: IntArray)\n" +
|
||||||
|
"" +
|
||||||
|
"A(intArray(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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user