diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaCompileTimeConstResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaCompileTimeConstResolver.java index 4e3a554cecb..4a00a225575 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaCompileTimeConstResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaCompileTimeConstResolver.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve.java.resolver; import com.google.common.collect.Lists; import com.intellij.psi.*; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; @@ -30,6 +31,7 @@ import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeProjection; +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import javax.inject.Inject; import java.util.ArrayList; @@ -164,6 +166,14 @@ public final class JavaCompileTimeConstResolver { @Nullable private static CompileTimeConstant getCompileTimeConstFromLiteralExpression(PsiLiteralExpression value) { + return getCompileTimeConstFromLiteralExpressionWithExpectedType(value, null); + } + + @Nullable + public static CompileTimeConstant getCompileTimeConstFromLiteralExpressionWithExpectedType( + @NotNull PsiLiteralExpression value, + @Nullable JetType expectedType + ) { Object literalValue = value.getValue(); if (literalValue instanceof String) { return new StringValue((String) literalValue); @@ -178,6 +188,16 @@ public final class JavaCompileTimeConstResolver { return new CharValue((Character) literalValue); } else if (literalValue instanceof Integer) { + KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); + if (builtIns.getShortType().equals(expectedType)) { + return new ShortValue(((Integer) literalValue).shortValue()); + } + else if (builtIns.getByteType().equals(expectedType)) { + return new ByteValue(((Integer) literalValue).byteValue()); + } + else if (builtIns.getCharType().equals(expectedType)) { + return new CharValue((char) ((Integer)literalValue).intValue()); + } return new IntValue((Integer) literalValue); } else if (literalValue instanceof Long) { diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaPropertyResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaPropertyResolver.java index 9c9cf23d4bb..5720faeda56 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaPropertyResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaPropertyResolver.java @@ -17,22 +17,20 @@ package org.jetbrains.jet.lang.resolve.java.resolver; import com.google.common.collect.Sets; -import com.intellij.psi.PsiEnumConstant; +import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.impl.*; -import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingTrace; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; -import org.jetbrains.jet.lang.resolve.OverrideResolver; +import org.jetbrains.jet.lang.resolve.*; +import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.java.*; import org.jetbrains.jet.lang.resolve.java.kotlinSignature.AlternativeFieldSignatureData; import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils; import org.jetbrains.jet.lang.resolve.java.kt.JetMethodAnnotation; -import org.jetbrains.jet.lang.resolve.java.provider.NamedMembers; import org.jetbrains.jet.lang.resolve.java.provider.PsiDeclarationProvider; +import org.jetbrains.jet.lang.resolve.java.provider.NamedMembers; import org.jetbrains.jet.lang.resolve.java.wrapper.*; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -243,6 +241,17 @@ public final class JavaPropertyResolver { if (scopeData.getDeclarationOrigin() == JAVA) { trace.record(JavaBindingContext.IS_DECLARED_IN_JAVA, propertyDescriptor); } + + if (AnnotationUtils.isPropertyAcceptableAsAnnotationParameter(propertyDescriptor) && psiData.getCharacteristicPsi() instanceof PsiField) { + PsiExpression initializer = ((PsiField) psiData.getCharacteristicPsi()).getInitializer(); + if (initializer instanceof PsiLiteralExpression) { + CompileTimeConstant constant = JavaCompileTimeConstResolver.getCompileTimeConstFromLiteralExpressionWithExpectedType( + (PsiLiteralExpression) initializer, propertyType); + if (constant != null) { + trace.record(BindingContext.COMPILE_TIME_INITIALIZER, propertyDescriptor, constant); + } + } + } return propertyDescriptor; } diff --git a/compiler/testData/codegen/boxWithJava/annotations/javaPropertyAsAnnotationParameter.java b/compiler/testData/codegen/boxWithJava/annotations/javaPropertyAsAnnotationParameter.java new file mode 100644 index 00000000000..9e0b81576c2 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/annotations/javaPropertyAsAnnotationParameter.java @@ -0,0 +1,11 @@ +class Foo { + public static final int i = 2; + public static final short s = 2; + public static final float f = 2f; + public static final double d = 2.0; + public static final long l = 2L; + public static final byte b = 2; + public static final boolean bool = true; + public static final char c = 'c'; + public static final String str = "str"; +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/annotations/javaPropertyAsAnnotationParameter.kt b/compiler/testData/codegen/boxWithJava/annotations/javaPropertyAsAnnotationParameter.kt new file mode 100644 index 00000000000..60170c36cba --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/annotations/javaPropertyAsAnnotationParameter.kt @@ -0,0 +1,32 @@ +import java.lang.annotation.Retention +import java.lang.annotation.RetentionPolicy + +Ann(Foo.i, Foo.s, Foo.f, Foo.d, Foo.l, Foo.b, Foo.bool, Foo.c, Foo.str) class MyClass + +fun box(): String { + val ann = javaClass().getAnnotation(javaClass()) + if (ann == null) return "fail: cannot find Ann on MyClass}" + if (ann.i != 2) return "fail: annotation parameter i should be 2, but was ${ann.i}" + if (ann.s != 2.toShort()) return "fail: annotation parameter i should be 2, but was ${ann.i}" + if (ann.f != 2.toFloat()) return "fail: annotation parameter i should be 2, but was ${ann.i}" + if (ann.d != 2.toDouble()) return "fail: annotation parameter i should be 2, but was ${ann.i}" + if (ann.l != 2.toLong()) return "fail: annotation parameter i should be 2, but was ${ann.i}" + if (ann.b != 2.toByte()) return "fail: annotation parameter i should be 2, but was ${ann.i}" + if (!ann.bool) return "fail: annotation parameter i should be true, but was ${ann.i}" + if (ann.c != 'c') return "fail: annotation parameter i should be c, but was ${ann.i}" + if (ann.str != "str") return "fail: annotation parameter i should be str, but was ${ann.i}" + return "OK" +} + +Retention(RetentionPolicy.RUNTIME) +annotation class Ann( + val i: Int, + val s: Short, + val f: Float, + val d: Double, + val l: Long, + val b: Byte, + val bool: Boolean, + val c: Char, + val str: String +) \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/annotations/javaPropertyWithIntInitializer.java b/compiler/testData/codegen/boxWithJava/annotations/javaPropertyWithIntInitializer.java new file mode 100644 index 00000000000..3a871981c18 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/annotations/javaPropertyWithIntInitializer.java @@ -0,0 +1,9 @@ +class Foo { + public static final int i = 2; + public static final short s = 2; + public static final float f = 2; + public static final double d = 2; + public static final long l = 2; + public static final byte b = 2; + public static final char c = 99; +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/annotations/javaPropertyWithIntInitializer.kt b/compiler/testData/codegen/boxWithJava/annotations/javaPropertyWithIntInitializer.kt new file mode 100644 index 00000000000..67875adf7f6 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/annotations/javaPropertyWithIntInitializer.kt @@ -0,0 +1,28 @@ +import java.lang.annotation.Retention +import java.lang.annotation.RetentionPolicy + +Ann(Foo.i, Foo.s, Foo.f, Foo.d, Foo.l, Foo.b, Foo.c) class MyClass + +fun box(): String { + val ann = javaClass().getAnnotation(javaClass()) + if (ann == null) return "fail: cannot find Ann on MyClass}" + if (ann.i != 2) return "fail: annotation parameter i should be 2, but was ${ann.i}" + if (ann.s != 2.toShort()) return "fail: annotation parameter i should be 2, but was ${ann.i}" + if (ann.f != 2.toFloat()) return "fail: annotation parameter i should be 2, but was ${ann.i}" + if (ann.d != 2.toDouble()) return "fail: annotation parameter i should be 2, but was ${ann.i}" + if (ann.l != 2.toLong()) return "fail: annotation parameter i should be 2, but was ${ann.i}" + if (ann.b != 2.toByte()) return "fail: annotation parameter i should be 2, but was ${ann.i}" + if (ann.c != 'c') return "fail: annotation parameter i should be c, but was ${ann.i}" + return "OK" +} + +Retention(RetentionPolicy.RUNTIME) +annotation class Ann( + val i: Int, + val s: Short, + val f: Float, + val d: Double, + val l: Long, + val b: Byte, + val c: Char +) \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java index 86502eaff94..b85b9016bc3 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java @@ -31,12 +31,30 @@ import org.jetbrains.jet.codegen.generated.AbstractBlackBoxCodegenTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @TestMetadata("compiler/testData/codegen/boxWithJava") -@InnerTestClasses({BlackBoxWithJavaCodegenTestGenerated.CallableReference.class, BlackBoxWithJavaCodegenTestGenerated.Enum.class, BlackBoxWithJavaCodegenTestGenerated.Functions.class, BlackBoxWithJavaCodegenTestGenerated.Property.class, BlackBoxWithJavaCodegenTestGenerated.Sam.class, BlackBoxWithJavaCodegenTestGenerated.StaticFun.class, BlackBoxWithJavaCodegenTestGenerated.Visibility.class}) +@InnerTestClasses({BlackBoxWithJavaCodegenTestGenerated.Annotations.class, BlackBoxWithJavaCodegenTestGenerated.CallableReference.class, BlackBoxWithJavaCodegenTestGenerated.Enum.class, BlackBoxWithJavaCodegenTestGenerated.Functions.class, BlackBoxWithJavaCodegenTestGenerated.Property.class, BlackBoxWithJavaCodegenTestGenerated.Sam.class, BlackBoxWithJavaCodegenTestGenerated.StaticFun.class, BlackBoxWithJavaCodegenTestGenerated.Visibility.class}) public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testAllFilesPresentInBoxWithJava() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/boxWithJava"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("compiler/testData/codegen/boxWithJava/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/boxWithJava/annotations"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("javaPropertyAsAnnotationParameter.kt") + public void testJavaPropertyAsAnnotationParameter() throws Exception { + doTestWithJava("compiler/testData/codegen/boxWithJava/annotations/javaPropertyAsAnnotationParameter.kt"); + } + + @TestMetadata("javaPropertyWithIntInitializer.kt") + public void testJavaPropertyWithIntInitializer() throws Exception { + doTestWithJava("compiler/testData/codegen/boxWithJava/annotations/javaPropertyWithIntInitializer.kt"); + } + + } + @TestMetadata("compiler/testData/codegen/boxWithJava/callableReference") public static class CallableReference extends AbstractBlackBoxCodegenTest { public void testAllFilesPresentInCallableReference() throws Exception { @@ -479,6 +497,7 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege public static Test suite() { TestSuite suite = new TestSuite("BlackBoxWithJavaCodegenTestGenerated"); suite.addTestSuite(BlackBoxWithJavaCodegenTestGenerated.class); + suite.addTestSuite(Annotations.class); suite.addTestSuite(CallableReference.class); suite.addTestSuite(Enum.class); suite.addTestSuite(Functions.class);