Kapt: Fix anonymous type transformer, do not use ClassDescriptor.defaultType as a replacement (KT-27119)

This commit is contained in:
Yan Zhulanow
2018-09-28 22:18:03 +03:00
parent 39863edd0e
commit ac1dd59472
8 changed files with 181 additions and 24 deletions
@@ -9,19 +9,15 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
import org.jetbrains.kotlin.resolve.DeclarationSignatureAnonymousTypeTransformer
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils.isAnonymousObject
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.resolve.DescriptorUtils.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.replace
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
class KaptAnonymousTypeTransformer : DeclarationSignatureAnonymousTypeTransformer {
override fun transformAnonymousType(descriptor: DeclarationDescriptorWithVisibility, type: KotlinType): KotlinType? {
if (DescriptorUtils.isLocal(descriptor))
if (isLocal(descriptor))
return type
return convertPossiblyAnonymousType(type)
@@ -41,7 +37,17 @@ class KaptAnonymousTypeTransformer : DeclarationSignatureAnonymousTypeTransforme
}
val actualType = when {
isAnonymousObject(declaration) -> findMostSuitableParentForAnonymousType(declaration)
isAnonymousObject(declaration) -> {
if (type.constructor.supertypes.size == 1) {
type.constructor.supertypes.iterator().next()
} else {
/*
Frontend reports an error on public properties in this case,
but we ignore errors when making stubs, so there should be a reasonable fallback.
*/
type.builtIns.anyType
}
}
else -> type
}
@@ -56,18 +62,4 @@ class KaptAnonymousTypeTransformer : DeclarationSignatureAnonymousTypeTransforme
return actualType.replace(newArguments = arguments)
}
private fun findMostSuitableParentForAnonymousType(descriptor: ClassDescriptor): KotlinType {
descriptor.getSuperClassNotAny()?.let { return it.defaultType }
val sortedSuperTypes = descriptor.typeConstructor.supertypes
.sortedBy { it.constructor.declarationDescriptor?.name?.asString() ?: "" }
for (candidate in sortedSuperTypes) {
if (!candidate.isAnyOrNullableAny())
return candidate
}
return descriptor.builtIns.anyType
}
}
@@ -129,6 +129,11 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi
runTest("plugins/kapt3/kapt3-compiler/testData/converter/ignoredMembers.kt");
}
@TestMetadata("implicitReturnTypes.kt")
public void testImplicitReturnTypes() throws Exception {
runTest("plugins/kapt3/kapt3-compiler/testData/converter/implicitReturnTypes.kt");
}
@TestMetadata("importsForErrorTypes.kt")
public void testImportsForErrorTypes() throws Exception {
runTest("plugins/kapt3/kapt3-compiler/testData/converter/importsForErrorTypes.kt");
@@ -154,6 +159,11 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi
runTest("plugins/kapt3/kapt3-compiler/testData/converter/innerClassesWithTypeParameters.kt");
}
@TestMetadata("interfaceImplementation.kt")
public void testInterfaceImplementation() throws Exception {
runTest("plugins/kapt3/kapt3-compiler/testData/converter/interfaceImplementation.kt");
}
@TestMetadata("invalidFieldName.kt")
public void testInvalidFieldName() throws Exception {
runTest("plugins/kapt3/kapt3-compiler/testData/converter/invalidFieldName.kt");
@@ -0,0 +1,37 @@
// WITH_RUNTIME
// FILE: lib/Prop.java
package lib;
public abstract class Prop<T> {
public abstract int get(T key);
public abstract void set(T key, int value);
}
// FILE: test.kt
package test
import lib.Prop
class Cl(var name: String)
val TEST = object : Prop<Cl>() {
override fun get(key: Cl) = key.name.length
override fun set(key: Cl, value: Int) {
key.name = " ".repeat(value)
}
}
val TESTS_ARRAY = arrayOf(object : Prop<Cl>() {
override fun get(key: Cl) = key.name.length
override fun set(key: Cl, value: Int) {
key.name = " ".repeat(value)
}
})
val TESTS_LIST = listOf(object : Prop<Cl>() {
override fun get(key: Cl) = key.name.length
override fun set(key: Cl, value: Int) {
key.name = " ".repeat(value)
}
})
@@ -0,0 +1,73 @@
package lib;
public abstract class Prop<T> {
public Prop() {
super();
}
public abstract int get(T key);
public abstract void set(T key, int value);
}
////////////////////
package test;
import java.lang.System;
@kotlin.Metadata()
public final class Cl {
@org.jetbrains.annotations.NotNull()
private java.lang.String name;
@org.jetbrains.annotations.NotNull()
public final java.lang.String getName() {
return null;
}
public final void setName(@org.jetbrains.annotations.NotNull()
java.lang.String p0) {
}
public Cl(@org.jetbrains.annotations.NotNull()
java.lang.String name) {
super();
}
}
////////////////////
package test;
import java.lang.System;
@kotlin.Metadata()
public final class TestKt {
public TestKt() {
super();
}
@org.jetbrains.annotations.NotNull()
private static final lib.Prop<test.Cl> TEST = null;
@org.jetbrains.annotations.NotNull()
private static final lib.Prop<test.Cl>[] TESTS_ARRAY = null;
@org.jetbrains.annotations.NotNull()
private static final java.util.List<lib.Prop<test.Cl>> TESTS_LIST = null;
@org.jetbrains.annotations.NotNull()
public static final lib.Prop<test.Cl> getTEST() {
return null;
}
@org.jetbrains.annotations.NotNull()
public static final lib.Prop<test.Cl>[] getTESTS_ARRAY() {
return null;
}
@org.jetbrains.annotations.NotNull()
public static final java.util.List<lib.Prop<test.Cl>> getTESTS_LIST() {
return null;
}
}
@@ -0,0 +1,11 @@
interface Named {
val name: String?
}
class Product2 : Named {
override var name: String? = null
constructor(otherName: String) {
this.name = otherName
}
}
@@ -0,0 +1,34 @@
import java.lang.System;
@kotlin.Metadata()
public abstract interface Named {
@org.jetbrains.annotations.Nullable()
public abstract java.lang.String getName();
}
////////////////////
import java.lang.System;
@kotlin.Metadata()
public final class Product2 implements Named {
@org.jetbrains.annotations.Nullable()
private java.lang.String name;
@org.jetbrains.annotations.Nullable()
@java.lang.Override()
public java.lang.String getName() {
return null;
}
public void setName(@org.jetbrains.annotations.Nullable()
java.lang.String p0) {
}
public Product2(@org.jetbrains.annotations.NotNull()
java.lang.String otherName) {
super();
}
}
@@ -28,12 +28,12 @@ public final class Kt14997Kt {
}
@org.jetbrains.annotations.NotNull()
public static final java.lang.Runnable b() {
public static final java.lang.Object b() {
return null;
}
@org.jetbrains.annotations.NotNull()
public static final CrashMe c() {
public static final java.lang.Object c() {
return null;
}
@@ -36,7 +36,7 @@ public final class Kt18682Kt {
}
@org.jetbrains.annotations.NotNull()
public static final java.util.List<Foo> test4() {
public static final java.util.List<java.lang.Object> test4() {
return null;
}
}