diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java index 2f230c791fb..e7a66617395 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java @@ -89,6 +89,12 @@ public abstract class AnnotationCodegen { } } + public void generateAnnotationDefaultValue(CompileTimeConstant value) { + AnnotationVisitor visitor = visitAnnotation(null, false); // Parameters are unimportant + genAnnotationArgument(null, value, visitor); + visitor.visitEnd(); + } + private void genAnnotation(AnnotationDescriptor annotationDescriptor) { ClassifierDescriptor classifierDescriptor = annotationDescriptor.getType().getConstructor().getDeclarationDescriptor(); RetentionPolicy rp = getRetentionPolicy(classifierDescriptor, typeMapper); @@ -270,4 +276,13 @@ public abstract class AnnotationCodegen { } }; } + + public static AnnotationCodegen forAnnotationDefaultValue(final MethodVisitor mv, JetTypeMapper mapper) { + return new AnnotationCodegen(mapper) { + @Override + AnnotationVisitor visitAnnotation(String descr, boolean visible) { + return mv.visitAnnotationDefault(); + } + }; + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index 806867b843b..f6454b79e9c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.name.Name; import java.util.Collections; @@ -135,7 +136,16 @@ public abstract class ClassBodyCodegen extends MemberCodegen { } else { Type type = state.getTypeMapper().mapType(propertyDescriptor); - v.newMethod(p, ACC_PUBLIC | ACC_ABSTRACT, p.getName(), "()" + type.getDescriptor(), null, null); + MethodVisitor visitor = + v.newMethod(p, ACC_PUBLIC | ACC_ABSTRACT, p.getName(), "()" + type.getDescriptor(), null, null); + JetExpression defaultValue = p.getDefaultValue(); + if (defaultValue != null) { + CompileTimeConstant constant = + state.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, defaultValue); + assert constant != null : "Default value for annotation parameter should be compile time value: " + defaultValue.getText(); + AnnotationCodegen annotationCodegen = AnnotationCodegen.forAnnotationDefaultValue(visitor, typeMapper); + annotationCodegen.generateAnnotationDefaultValue(constant); + } } } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java index 62a759df815..08060d35ad3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java @@ -223,7 +223,7 @@ public class AnnotationResolver { } @Nullable - private CompileTimeConstant resolveAnnotationArgument(@NotNull JetExpression expression, @NotNull final JetType expectedType, final BindingTrace trace) { + public CompileTimeConstant resolveAnnotationArgument(@NotNull JetExpression expression, @NotNull final JetType expectedType, final BindingTrace trace) { JetVisitor, Void> visitor = new JetVisitor, Void>() { @Override public CompileTimeConstant visitConstantExpression(JetConstantExpression expression, Void nothing) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index 10c83ece7b9..39a64e34cf7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; +import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.scopes.*; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.jet.lang.types.*; @@ -696,6 +697,13 @@ public class BodyResolver { JetExpression defaultValue = jetParameter.getDefaultValue(); if (defaultValue != null) { expressionTypingServices.getType(declaringScope, defaultValue, valueParameterDescriptor.getType(), DataFlowInfo.EMPTY, trace); + if (DescriptorUtils.isAnnotationClass(DescriptorUtils.getContainingClass(declaringScope))) { + CompileTimeConstant constant = + annotationResolver.resolveAnnotationArgument(defaultValue, valueParameterDescriptor.getType(), trace); + if (constant != null) { + trace.record(BindingContext.COMPILE_TIME_VALUE, defaultValue, constant); + } + } } } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index 733db8c6763..20baaa52eff 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -289,7 +289,7 @@ public class DescriptorUtils { return isKindOf(descriptor, ClassKind.ENUM_CLASS); } - public static boolean isAnnotationClass(@NotNull DeclarationDescriptor descriptor) { + public static boolean isAnnotationClass(@Nullable DeclarationDescriptor descriptor) { return isKindOf(descriptor, ClassKind.ANNOTATION_CLASS); } diff --git a/compiler/testData/codegen/boxWithStdlib/annotations/defaultParameterValues.kt b/compiler/testData/codegen/boxWithStdlib/annotations/defaultParameterValues.kt new file mode 100644 index 00000000000..b5979104e28 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/annotations/defaultParameterValues.kt @@ -0,0 +1,36 @@ +import java.lang.annotation.Retention +import java.lang.annotation.RetentionPolicy + +Retention(RetentionPolicy.RUNTIME) +annotation class Ann( + val i: Int = 1, + val s: String = "a", + val a: Ann2 = Ann2(), + val e: MyEnum = MyEnum.A, + val c: Class<*> = javaClass(), + val ia: IntArray = intArray(1, 2), + val sa: Array = array("a", "b") +) + +fun box(): String { + val ann = javaClass().getAnnotation(javaClass()) + if (ann == null) return "fail: cannot find Ann on MyClass}" + if (ann.i != 1) return "fail: annotation parameter i should be 1, but was ${ann.i}" + if (ann.s != "a") return "fail: annotation parameter s should be \"a\", but was ${ann.s}" + if (ann.a.toString() != "@Ann2()") return "fail: annotation parameter a should be of class Ann2, but was ${ann.a}" + if (ann.e != MyEnum.A) return "fail: annotation parameter e should be MyEnum.A, but was ${ann.e}" + if (ann.c != javaClass()) return "fail: annotation parameter c should be of class A, but was ${ann.c}" + if (ann.ia[0] != 1 || ann.ia[1] != 2) return "fail: annotation parameter ia should be [1, 2], but was ${ann.ia}" + if (ann.sa[0] != "a" || ann.sa[1] != "b") return "fail: annotation parameter ia should be [\"a\", \"b\"], but was ${ann.sa}" + return "OK" +} + +annotation class Ann2 + +enum class MyEnum { + A +} + +class A + +Ann class MyClass diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 5d2e99c1665..ee1a39307b0 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -36,12 +36,17 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode public void testAllFilesPresentInBoxWithStdlib() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/boxWithStdlib"), Pattern.compile("^(.+)\\.kt$"), true); } - + @TestMetadata("compiler/testData/codegen/boxWithStdlib/annotations") public static class Annotations extends AbstractBlackBoxCodegenTest { public void testAllFilesPresentInAnnotations() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/boxWithStdlib/annotations"), Pattern.compile("^(.+)\\.kt$"), true); } + + @TestMetadata("defaultParameterValues.kt") + public void testDefaultParameterValues() throws Exception { + doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/annotations/defaultParameterValues.kt"); + } @TestMetadata("varargInAnnotationParameter.kt") public void testVarargInAnnotationParameter() throws Exception {