Support declarations returning object literals in ultra-light classes

This commit is contained in:
Denis Zharkov
2018-11-20 12:24:26 +03:00
parent 28f20a97f8
commit 7de8b4de4e
8 changed files with 250 additions and 46 deletions
@@ -21,13 +21,18 @@ import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.ValueDescriptor
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
import org.jetbrains.kotlin.resolve.BindingContext
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.supertypes
import java.text.StringCharacterIterator
internal fun buildTypeParameterList(
@@ -105,5 +110,38 @@ internal fun typeMapper(support: UltraLightSupport): KotlinTypeMapper = KotlinTy
IncompatibleClassTracker.DoNothing, support.moduleName,
JvmTarget.JVM_1_8,
KotlinTypeMapper.LANGUAGE_VERSION_SETTINGS_DEFAULT, // TODO use proper LanguageVersionSettings
false
false,
KotlinType::cleanFromAnonymousTypes
)
// Returns null when type is unchanged
fun KotlinType.cleanFromAnonymousTypes(): KotlinType? {
val returnTypeClass = constructor.declarationDescriptor as? ClassDescriptor ?: return null
if (DescriptorUtils.isAnonymousObject(returnTypeClass)) {
// We choose just the first supertype because:
// - In public declarations, object literals should always have a single supertype (otherwise it's an error)
// - For private declarations, they might have more than one supertype
// but it looks like it's not important how we choose a representative for them
val representative = returnTypeClass.defaultType.supertypes().firstOrNull() ?: return null
return representative.cleanFromAnonymousTypes() ?: representative
}
if (arguments.isEmpty()) return null
var wasUpdates = false
val newArguments = arguments.map { typeProjection ->
val updatedType =
typeProjection.takeUnless { it.isStarProjection }
?.type?.cleanFromAnonymousTypes()
?: return@map typeProjection
wasUpdates = true
TypeProjectionImpl(typeProjection.projectionKind, updatedType)
}
if (!wasUpdates) return null
return replace(newArguments = newArguments)
}