Kapt: Don't convert field initializers for enum fields inside companion objects (KT-37732)
For classes with companion objects, Kotlin compiler generates a 'Companion' static accessor field. Java prioritizes fields over inner types (apparently, Scala does this as well, KT-29864), so the generated initializer doesn't compile. As a workaround, initializer generatation is disabled for enum fields inside companion objects. Certainly, it's not a proper fix, however it does fix the regression.
This commit is contained in:
+23
@@ -60,10 +60,12 @@ import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluat
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.isError
|
||||
import org.jetbrains.kotlin.types.typeUtil.isEnum
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
@@ -668,6 +670,18 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati
|
||||
}
|
||||
|
||||
val propertyType = (origin?.descriptor as? PropertyDescriptor)?.returnType
|
||||
|
||||
/*
|
||||
Work-around for enum classes in companions.
|
||||
In expressions "Foo.Companion.EnumClass", Java prefers static field over a type name, making the reference invalid.
|
||||
*/
|
||||
if (propertyType != null && propertyType.isEnum()) {
|
||||
val enumClass = propertyType.constructor.declarationDescriptor
|
||||
if (enumClass is ClassDescriptor && enumClass.isInsideCompanionObject()) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
if (propertyInitializer != null && propertyType != null) {
|
||||
val constValue = getConstantValue(propertyInitializer, propertyType)
|
||||
if (constValue != null) {
|
||||
@@ -686,6 +700,15 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati
|
||||
return null
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.isInsideCompanionObject(): Boolean {
|
||||
val parent = containingDeclaration ?: return false
|
||||
if (parent.isCompanionObject()) {
|
||||
return true
|
||||
}
|
||||
|
||||
return parent.isInsideCompanionObject()
|
||||
}
|
||||
|
||||
private object UnknownConstantValue
|
||||
|
||||
private fun getConstantValue(expression: KtExpression, expectedType: KotlinType): ConstantValue<*>? {
|
||||
|
||||
+5
@@ -108,6 +108,11 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi
|
||||
runTest("plugins/kapt3/kapt3-compiler/testData/converter/enumImports.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumInCompanion.kt")
|
||||
public void testEnumInCompanion() throws Exception {
|
||||
runTest("plugins/kapt3/kapt3-compiler/testData/converter/enumInCompanion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enums.kt")
|
||||
public void testEnums() throws Exception {
|
||||
runTest("plugins/kapt3/kapt3-compiler/testData/converter/enums.kt");
|
||||
|
||||
+5
@@ -109,6 +109,11 @@ public class IrClassFileToSourceStubConverterTestGenerated extends AbstractIrCla
|
||||
runTest("plugins/kapt3/kapt3-compiler/testData/converter/enumImports.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumInCompanion.kt")
|
||||
public void testEnumInCompanion() throws Exception {
|
||||
runTest("plugins/kapt3/kapt3-compiler/testData/converter/enumInCompanion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enums.kt")
|
||||
public void testEnums() throws Exception {
|
||||
runTest("plugins/kapt3/kapt3-compiler/testData/converter/enums.kt");
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
class Test {
|
||||
private val foo = Example.FOO
|
||||
|
||||
companion object {
|
||||
enum class Example { FOO }
|
||||
}
|
||||
}
|
||||
|
||||
class Test2 {
|
||||
private val foo = Example.FOO
|
||||
|
||||
companion object Amigo {
|
||||
enum class Example { FOO }
|
||||
}
|
||||
}
|
||||
|
||||
class Test3 {
|
||||
private val foo = Amigo.Example.FOO
|
||||
|
||||
object Amigo {
|
||||
enum class Example { FOO }
|
||||
}
|
||||
}
|
||||
|
||||
class Test4 {
|
||||
private val foo = Foo.constProperty
|
||||
|
||||
companion object {
|
||||
object Foo {
|
||||
const val constProperty = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Test5 {
|
||||
private val foo = Amigos.Companion.Goo.Example.FOO
|
||||
|
||||
class Amigos {
|
||||
companion object {
|
||||
class Goo {
|
||||
enum class Example { FOO }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
import java.lang.System;
|
||||
|
||||
@kotlin.Metadata()
|
||||
public final class Test {
|
||||
private final Test.Companion.Example foo;
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
public static final Test.Companion Companion = null;
|
||||
|
||||
public Test() {
|
||||
super();
|
||||
}
|
||||
|
||||
@kotlin.Metadata()
|
||||
public static final class Companion {
|
||||
|
||||
private Companion() {
|
||||
super();
|
||||
}
|
||||
|
||||
@kotlin.Metadata()
|
||||
public static enum Example {
|
||||
/*public static final*/ FOO /* = new Example() */;
|
||||
|
||||
Example() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////
|
||||
|
||||
|
||||
import java.lang.System;
|
||||
|
||||
@kotlin.Metadata()
|
||||
public final class Test2 {
|
||||
private final Test2.Amigo.Example foo;
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
public static final Test2.Amigo Amigo = null;
|
||||
|
||||
public Test2() {
|
||||
super();
|
||||
}
|
||||
|
||||
@kotlin.Metadata()
|
||||
public static final class Amigo {
|
||||
|
||||
private Amigo() {
|
||||
super();
|
||||
}
|
||||
|
||||
@kotlin.Metadata()
|
||||
public static enum Example {
|
||||
/*public static final*/ FOO /* = new Example() */;
|
||||
|
||||
Example() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////
|
||||
|
||||
|
||||
import java.lang.System;
|
||||
|
||||
@kotlin.Metadata()
|
||||
public final class Test3 {
|
||||
private final Test3.Amigo.Example foo = Test3.Amigo.Example.FOO;
|
||||
|
||||
public Test3() {
|
||||
super();
|
||||
}
|
||||
|
||||
@kotlin.Metadata()
|
||||
public static final class Amigo {
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
public static final Test3.Amigo INSTANCE = null;
|
||||
|
||||
private Amigo() {
|
||||
super();
|
||||
}
|
||||
|
||||
@kotlin.Metadata()
|
||||
public static enum Example {
|
||||
/*public static final*/ FOO /* = new Example() */;
|
||||
|
||||
Example() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////
|
||||
|
||||
|
||||
import java.lang.System;
|
||||
|
||||
@kotlin.Metadata()
|
||||
public final class Test4 {
|
||||
private final int foo = 1;
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
public static final Test4.Companion Companion = null;
|
||||
|
||||
public Test4() {
|
||||
super();
|
||||
}
|
||||
|
||||
@kotlin.Metadata()
|
||||
public static final class Companion {
|
||||
|
||||
private Companion() {
|
||||
super();
|
||||
}
|
||||
|
||||
@kotlin.Metadata()
|
||||
public static final class Foo {
|
||||
public static final int constProperty = 1;
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
public static final Test4.Companion.Foo INSTANCE = null;
|
||||
|
||||
private Foo() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////
|
||||
|
||||
|
||||
import java.lang.System;
|
||||
|
||||
@kotlin.Metadata()
|
||||
public final class Test5 {
|
||||
private final Test5.Amigos.Companion.Goo.Example foo;
|
||||
|
||||
public Test5() {
|
||||
super();
|
||||
}
|
||||
|
||||
@kotlin.Metadata()
|
||||
public static final class Amigos {
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
public static final Test5.Amigos.Companion Companion = null;
|
||||
|
||||
public Amigos() {
|
||||
super();
|
||||
}
|
||||
|
||||
@kotlin.Metadata()
|
||||
public static final class Companion {
|
||||
|
||||
private Companion() {
|
||||
super();
|
||||
}
|
||||
|
||||
@kotlin.Metadata()
|
||||
public static final class Goo {
|
||||
|
||||
public Goo() {
|
||||
super();
|
||||
}
|
||||
|
||||
@kotlin.Metadata()
|
||||
public static enum Example {
|
||||
/*public static final*/ FOO /* = new Example() */;
|
||||
|
||||
Example() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user