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.fqNameOrNull
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
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.resolve.source.PsiSourceElement
|
||||||
import org.jetbrains.kotlin.types.ErrorUtils
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.isError
|
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.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.tree.*
|
import org.jetbrains.org.objectweb.asm.tree.*
|
||||||
@@ -668,6 +670,18 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati
|
|||||||
}
|
}
|
||||||
|
|
||||||
val propertyType = (origin?.descriptor as? PropertyDescriptor)?.returnType
|
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) {
|
if (propertyInitializer != null && propertyType != null) {
|
||||||
val constValue = getConstantValue(propertyInitializer, propertyType)
|
val constValue = getConstantValue(propertyInitializer, propertyType)
|
||||||
if (constValue != null) {
|
if (constValue != null) {
|
||||||
@@ -686,6 +700,15 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun DeclarationDescriptor.isInsideCompanionObject(): Boolean {
|
||||||
|
val parent = containingDeclaration ?: return false
|
||||||
|
if (parent.isCompanionObject()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent.isInsideCompanionObject()
|
||||||
|
}
|
||||||
|
|
||||||
private object UnknownConstantValue
|
private object UnknownConstantValue
|
||||||
|
|
||||||
private fun getConstantValue(expression: KtExpression, expectedType: KotlinType): ConstantValue<*>? {
|
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");
|
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")
|
@TestMetadata("enums.kt")
|
||||||
public void testEnums() throws Exception {
|
public void testEnums() throws Exception {
|
||||||
runTest("plugins/kapt3/kapt3-compiler/testData/converter/enums.kt");
|
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");
|
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")
|
@TestMetadata("enums.kt")
|
||||||
public void testEnums() throws Exception {
|
public void testEnums() throws Exception {
|
||||||
runTest("plugins/kapt3/kapt3-compiler/testData/converter/enums.kt");
|
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