diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt index a8dc19944bb..1d8c6b65395 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.base.kapt3.KaptFlag import org.jetbrains.kotlin.codegen.coroutines.CONTINUATION_PARAMETER_NAME import org.jetbrains.kotlin.codegen.needsExperimentalCoroutinesWrapper import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations @@ -49,11 +50,13 @@ import org.jetbrains.kotlin.load.java.sources.JavaSourceElement import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.DelegatingBindingTrace import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument import org.jetbrains.kotlin.resolve.constants.* +import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny @@ -644,8 +647,10 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati private fun convertPropertyInitializer(field: FieldNode): JCExpression? { val value = field.value + val origin = kaptContext.origins[field] + val propertyInitializer = (origin?.element as? KtProperty)?.initializer + if (value != null) { - val propertyInitializer = (kaptContext.origins[field]?.element as? KtProperty)?.initializer if (propertyInitializer != null) { return convertConstantValueArguments(value, listOf(propertyInitializer)) } @@ -653,6 +658,17 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati return convertValueOfPrimitiveTypeOrString(value) } + val propertyType = (origin?.descriptor as? PropertyDescriptor)?.returnType + if (propertyInitializer != null && propertyType != null) { + val moduleDescriptor = kaptContext.generationState.module + val evaluator = ConstantExpressionEvaluator(moduleDescriptor, LanguageVersionSettingsImpl.DEFAULT, kaptContext.project) + val trace = DelegatingBindingTrace(kaptContext.bindingContext, "Kapt") + val const = evaluator.evaluateExpression(propertyInitializer, trace, propertyType) + if (const != null && !const.isError && const.canBeUsedInAnnotations && !const.usesNonConstValAsConstant) { + return convertConstantValueArguments(const.getValue(propertyType), listOf(propertyInitializer)) + } + } + if (isFinal(field.access)) { val type = Type.getType(field.desc) return convertLiteralExpression(getDefaultValue(type)) diff --git a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java index c4d4cc1b3b6..ad62204c293 100644 --- a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java +++ b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java @@ -408,4 +408,9 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi public void testTopLevel() throws Exception { runTest("plugins/kapt3/kapt3-compiler/testData/converter/topLevel.kt"); } + + @TestMetadata("unsafePropertyInitializers.kt") + public void testUnsafePropertyInitializers() throws Exception { + runTest("plugins/kapt3/kapt3-compiler/testData/converter/unsafePropertyInitializers.kt"); + } } diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/annotations.txt b/plugins/kapt3/kapt3-compiler/testData/converter/annotations.txt index a0daffbe80e..eb6f7768673 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/annotations.txt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/annotations.txt @@ -101,7 +101,7 @@ import java.lang.System; public final class TestAnno2 { @org.jetbrains.annotations.NotNull() @Anno3(value = "field") - private java.lang.String b; + private java.lang.String b = "property initializer"; @Anno1() public final void a(@org.jetbrains.annotations.NotNull() diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/kt18791.txt b/plugins/kapt3/kapt3-compiler/testData/converter/kt18791.txt index a0b74f61b25..a46e5cfc39f 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/kt18791.txt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/kt18791.txt @@ -130,9 +130,9 @@ public final class MyActivity { private final int f = 0; public final int propA = app.B.id.textView; private final int propB = app.B.id.textView; - private int propC; + private int propC = app.B.id.textView; public final int propD = app.B.id.textView; - public int propE; + public int propE = app.B.id.textView; private final int propF = 0; @Bind(id = lib.R.id.textView) diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/modifiers.txt b/plugins/kapt3/kapt3-compiler/testData/converter/modifiers.txt index 3ba828dc35e..f54ffd3f1da 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/modifiers.txt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/modifiers.txt @@ -31,7 +31,7 @@ public final class Modifiers { @org.jetbrains.annotations.NotNull() private final transient java.lang.String transientField = ""; @org.jetbrains.annotations.NotNull() - private volatile java.lang.String volatileField; + private volatile java.lang.String volatileField = ""; @org.jetbrains.annotations.NotNull() public final java.lang.String getTransientField() { diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/unsafePropertyInitializers.kt b/plugins/kapt3/kapt3-compiler/testData/converter/unsafePropertyInitializers.kt new file mode 100644 index 00000000000..0a802b38a4d --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/testData/converter/unsafePropertyInitializers.kt @@ -0,0 +1,24 @@ +object Foo { + const val aString: String = "foo" + const val aInt: Int = 3 + + val bString: String = "bar" + val bInt: Int = 5 + + var cString: String = "baz" + var cInt: Int = 7 + + val d = Boo.z + val e = Boo.z.length + val f = 5 + 3 + val g = "a" + "b" + val h = -4 + val i = Int.MAX_VALUE + val j = "$e$g" + val k = g + j +} + +object Boo { + val z = foo() + fun foo() = "abc" +} \ No newline at end of file diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/unsafePropertyInitializers.txt b/plugins/kapt3/kapt3-compiler/testData/converter/unsafePropertyInitializers.txt new file mode 100644 index 00000000000..cc80a16adc4 --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/testData/converter/unsafePropertyInitializers.txt @@ -0,0 +1,118 @@ +import java.lang.System; + +@kotlin.Metadata() +public final class Boo { + @org.jetbrains.annotations.NotNull() + private static final java.lang.String z = null; + public static final Boo INSTANCE = null; + + @org.jetbrains.annotations.NotNull() + public final java.lang.String getZ() { + return null; + } + + @org.jetbrains.annotations.NotNull() + public final java.lang.String foo() { + return null; + } + + private Boo() { + super(); + } +} + +//////////////////// + + +import java.lang.System; + +@kotlin.Metadata() +public final class Foo { + @org.jetbrains.annotations.NotNull() + public static final java.lang.String aString = "foo"; + public static final int aInt = 3; + @org.jetbrains.annotations.NotNull() + private static final java.lang.String bString = "bar"; + private static final int bInt = 5; + @org.jetbrains.annotations.NotNull() + private static java.lang.String cString = "baz"; + private static int cInt = 7; + @org.jetbrains.annotations.NotNull() + private static final java.lang.String d = null; + private static final int e = 0; + private static final int f = 8; + @org.jetbrains.annotations.NotNull() + private static final java.lang.String g = "ab"; + private static final int h = -4; + private static final int i = 2147483647; + @org.jetbrains.annotations.NotNull() + private static final java.lang.String j = null; + @org.jetbrains.annotations.NotNull() + private static final java.lang.String k = null; + public static final Foo INSTANCE = null; + + @org.jetbrains.annotations.NotNull() + public final java.lang.String getBString() { + return null; + } + + public final int getBInt() { + return 0; + } + + @org.jetbrains.annotations.NotNull() + public final java.lang.String getCString() { + return null; + } + + public final void setCString(@org.jetbrains.annotations.NotNull() + java.lang.String p0) { + } + + public final int getCInt() { + return 0; + } + + public final void setCInt(int p0) { + } + + @org.jetbrains.annotations.NotNull() + public final java.lang.String getD() { + return null; + } + + public final int getE() { + return 0; + } + + public final int getF() { + return 0; + } + + @org.jetbrains.annotations.NotNull() + public final java.lang.String getG() { + return null; + } + + public final int getH() { + return 0; + } + + public final int getI() { + return 0; + } + + @org.jetbrains.annotations.NotNull() + public final java.lang.String getJ() { + return null; + } + + @org.jetbrains.annotations.NotNull() + public final java.lang.String getK() { + return null; + } + + private Foo() { + super(); + } +}