Do not build enhanced descriptors if they are unchanged

This commit is contained in:
Denis Zharkov
2016-02-01 19:41:26 +03:00
parent 924d706e79
commit c1f57b743b
12 changed files with 60 additions and 34 deletions
@@ -2,5 +2,5 @@ package test
public open class MethodWithMappedClasses { public open class MethodWithMappedClasses {
public constructor MethodWithMappedClasses() public constructor MethodWithMappedClasses()
public open fun </*0*/ T : kotlin.Any!> copy(/*0*/ p0: (kotlin.collections.MutableList<in T!>..kotlin.collections.List<*>?), /*1*/ p1: kotlin.collections.(Mutable)List<T!>!): kotlin.Unit public open fun </*0*/ T : kotlin.Any!> copy(/*0*/ p0: kotlin.collections.(Mutable)List<in T!>!, /*1*/ p1: kotlin.collections.(Mutable)List<T!>!): kotlin.Unit
} }
@@ -2,5 +2,5 @@ package test
public open class MethodWithTypeParameters { public open class MethodWithTypeParameters {
public constructor MethodWithTypeParameters() public constructor MethodWithTypeParameters()
public open fun </*0*/ A : kotlin.Any!, /*1*/ B : java.lang.Runnable!> foo(/*0*/ p0: A!, /*1*/ p1: (kotlin.collections.MutableList<out B!>..kotlin.collections.List<B!>?), /*2*/ p2: (kotlin.collections.MutableList<in kotlin.String!>..kotlin.collections.List<*>?)): kotlin.Unit where B : kotlin.collections.(Mutable)List<kotlin.Cloneable!>! public open fun </*0*/ A : kotlin.Any!, /*1*/ B : java.lang.Runnable!> foo(/*0*/ p0: A!, /*1*/ p1: (kotlin.collections.MutableList<out B!>..kotlin.collections.List<B!>?), /*2*/ p2: kotlin.collections.(Mutable)List<in kotlin.String!>!): kotlin.Unit where B : kotlin.collections.(Mutable)List<kotlin.Cloneable!>!
} }
@@ -33,19 +33,24 @@ private fun <D : CallableMemberDescriptor> D.enhanceSignature(): D {
if (this !is JavaCallableMemberDescriptor) return this if (this !is JavaCallableMemberDescriptor) return this
val enhancedReceiverType = val receiverTypeEnhancement =
if (extensionReceiverParameter != null) if (extensionReceiverParameter != null)
parts(isCovariant = false) { it.extensionReceiverParameter!!.type }.enhance() parts(isCovariant = false) { it.extensionReceiverParameter!!.type }.enhance()
else null else null
val enhancedValueParametersTypes = valueParameters.map { val valueParameterEnhancements = valueParameters.map {
p -> parts(isCovariant = false) { it.valueParameters[p.index].type }.enhance() p -> parts(isCovariant = false) { it.valueParameters[p.index].type }.enhance()
} }
val enhancedReturnType = parts(isCovariant = true) { it.returnType!! }.enhance() val returnTypeEnhancement = parts(isCovariant = true) { it.returnType!! }.enhance()
@Suppress("UNCHECKED_CAST") if ((receiverTypeEnhancement?.wereChanges ?: false)
return this.enhance(enhancedReceiverType, enhancedValueParametersTypes, enhancedReturnType) as D || returnTypeEnhancement.wereChanges || valueParameterEnhancements.any { it.wereChanges }) {
@Suppress("UNCHECKED_CAST")
return this.enhance(receiverTypeEnhancement?.type, valueParameterEnhancements.map { it.type }, returnTypeEnhancement.type) as D
}
return this
} }
private class SignatureParts( private class SignatureParts(
@@ -53,12 +58,16 @@ private class SignatureParts(
val fromOverridden: Collection<KotlinType>, val fromOverridden: Collection<KotlinType>,
val isCovariant: Boolean val isCovariant: Boolean
) { ) {
fun enhance(): KotlinType { fun enhance(): PartEnhancementResult {
val qualifiers = fromOverride.computeIndexedQualifiersForOverride(this.fromOverridden, isCovariant) val qualifiers = fromOverride.computeIndexedQualifiersForOverride(this.fromOverridden, isCovariant)
return fromOverride.enhance(qualifiers) return fromOverride.enhance(qualifiers)?.let {
enhanced -> PartEnhancementResult(enhanced, wereChanges = true)
} ?: PartEnhancementResult(fromOverride, wereChanges = false)
} }
} }
private data class PartEnhancementResult(val type: KotlinType, val wereChanges: Boolean)
private fun <D : CallableMemberDescriptor> D.parts(isCovariant: Boolean, collector: (D) -> KotlinType): SignatureParts { private fun <D : CallableMemberDescriptor> D.parts(isCovariant: Boolean, collector: (D) -> KotlinType): SignatureParts {
return SignatureParts( return SignatureParts(
collector(this), collector(this),
@@ -33,13 +33,14 @@ import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.createProjection import org.jetbrains.kotlin.types.typeUtil.createProjection
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.utils.addToStdlib.check
import org.jetbrains.kotlin.utils.toReadOnlyList import org.jetbrains.kotlin.utils.toReadOnlyList
// The index in the lambda is the position of the type component: // The index in the lambda is the position of the type component:
// Example: for `A<B, C<D, E>>`, indices go as follows: `0 - A<...>, 1 - B, 2 - C<D, E>, 3 - D, 4 - E`, // Example: for `A<B, C<D, E>>`, indices go as follows: `0 - A<...>, 1 - B, 2 - C<D, E>, 3 - D, 4 - E`,
// which corresponds to the left-to-right breadth-first walk of the tree representation of the type. // which corresponds to the left-to-right breadth-first walk of the tree representation of the type.
// For flexible types, both bounds are indexed in the same way: `(A<B>..C<D>)` gives `0 - (A<B>..C<D>), 1 - B and D`. // For flexible types, both bounds are indexed in the same way: `(A<B>..C<D>)` gives `0 - (A<B>..C<D>), 1 - B and D`.
fun KotlinType.enhance(qualifiers: (Int) -> JavaTypeQualifiers) = this.enhancePossiblyFlexible(qualifiers, 0).type fun KotlinType.enhance(qualifiers: (Int) -> JavaTypeQualifiers) = this.enhancePossiblyFlexible(qualifiers, 0).typeIfChanged
private enum class TypeComponentPosition { private enum class TypeComponentPosition {
@@ -48,10 +49,12 @@ private enum class TypeComponentPosition {
INFLEXIBLE INFLEXIBLE
} }
private data class Result(val type: KotlinType, val subtreeSize: Int) private data class Result(val type: KotlinType, val subtreeSize: Int, val wereChanges: Boolean) {
val typeIfChanged: KotlinType? get() = type.check { wereChanges }
}
private fun KotlinType.enhancePossiblyFlexible(qualifiers: (Int) -> JavaTypeQualifiers, index: Int): Result { private fun KotlinType.enhancePossiblyFlexible(qualifiers: (Int) -> JavaTypeQualifiers, index: Int): Result {
if (this.isError()) return Result(this, 1) if (this.isError) return Result(this, 1, false)
return if (this.isFlexible()) { return if (this.isFlexible()) {
with(this.flexibility()) { with(this.flexibility()) {
val lowerResult = lowerBound.enhanceInflexible(qualifiers, index, TypeComponentPosition.FLEXIBLE_LOWER) val lowerResult = lowerBound.enhanceInflexible(qualifiers, index, TypeComponentPosition.FLEXIBLE_LOWER)
@@ -61,8 +64,15 @@ private fun KotlinType.enhancePossiblyFlexible(qualifiers: (Int) -> JavaTypeQual
"lower = ($lowerBound, ${lowerResult.subtreeSize}), " + "lower = ($lowerBound, ${lowerResult.subtreeSize}), " +
"upper = ($upperBound, ${upperResult.subtreeSize})" "upper = ($upperBound, ${upperResult.subtreeSize})"
} }
val wereChanges = lowerResult.wereChanges || upperResult.wereChanges
Result( Result(
DelegatingFlexibleType.create(lowerResult.type, upperResult.type, extraCapabilities), lowerResult.subtreeSize if (wereChanges)
DelegatingFlexibleType.create(lowerResult.type, upperResult.type, extraCapabilities)
else
this@enhancePossiblyFlexible,
lowerResult.subtreeSize,
wereChanges
) )
} }
} }
@@ -71,10 +81,10 @@ private fun KotlinType.enhancePossiblyFlexible(qualifiers: (Int) -> JavaTypeQual
private fun KotlinType.enhanceInflexible(qualifiers: (Int) -> JavaTypeQualifiers, index: Int, position: TypeComponentPosition): Result { private fun KotlinType.enhanceInflexible(qualifiers: (Int) -> JavaTypeQualifiers, index: Int, position: TypeComponentPosition): Result {
val shouldEnhance = position.shouldEnhance() val shouldEnhance = position.shouldEnhance()
if (!shouldEnhance && getArguments().isEmpty()) return Result(this, 1) if (!shouldEnhance && arguments.isEmpty()) return Result(this, 1, false)
val originalClass = getConstructor().declarationDescriptor val originalClass = constructor.declarationDescriptor
?: return Result(this, 1) ?: return Result(this, 1, false)
val effectiveQualifiers = qualifiers(index) val effectiveQualifiers = qualifiers(index)
val (enhancedClassifier, enhancedMutabilityAnnotations) = originalClass.enhanceMutability(effectiveQualifiers, position) val (enhancedClassifier, enhancedMutabilityAnnotations) = originalClass.enhanceMutability(effectiveQualifiers, position)
@@ -82,6 +92,7 @@ private fun KotlinType.enhanceInflexible(qualifiers: (Int) -> JavaTypeQualifiers
val typeConstructor = enhancedClassifier.typeConstructor val typeConstructor = enhancedClassifier.typeConstructor
var globalArgIndex = index + 1 var globalArgIndex = index + 1
var wereChanges = enhancedMutabilityAnnotations != null
val enhancedArguments = getArguments().mapIndexed { val enhancedArguments = getArguments().mapIndexed {
localArgIndex, arg -> localArgIndex, arg ->
if (arg.isStarProjection) { if (arg.isStarProjection) {
@@ -89,13 +100,19 @@ private fun KotlinType.enhanceInflexible(qualifiers: (Int) -> JavaTypeQualifiers
TypeUtils.makeStarProjection(enhancedClassifier.typeConstructor.parameters[localArgIndex]) TypeUtils.makeStarProjection(enhancedClassifier.typeConstructor.parameters[localArgIndex])
} }
else { else {
val (enhancedType, subtreeSize) = arg.type.enhancePossiblyFlexible(qualifiers, globalArgIndex) val (enhancedType, subtreeSize, wasChangeInArgument) = arg.type.enhancePossiblyFlexible(qualifiers, globalArgIndex)
wereChanges = wereChanges || wasChangeInArgument
globalArgIndex += subtreeSize globalArgIndex += subtreeSize
createProjection(enhancedType, arg.projectionKind, typeParameterDescriptor = typeConstructor.parameters[localArgIndex]) createProjection(enhancedType, arg.projectionKind, typeParameterDescriptor = typeConstructor.parameters[localArgIndex])
} }
} }
val (enhancedNullability, enhancedNullabilityAnnotations) = this.getEnhancedNullability(effectiveQualifiers, position) val (enhancedNullability, enhancedNullabilityAnnotations) = this.getEnhancedNullability(effectiveQualifiers, position)
wereChanges = wereChanges || enhancedNullabilityAnnotations != null
val subtreeSize = globalArgIndex - index
if (!wereChanges) return Result(this, subtreeSize, wereChanges = false)
val newAnnotations = listOf( val newAnnotations = listOf(
getAnnotations(), getAnnotations(),
enhancedMutabilityAnnotations, enhancedMutabilityAnnotations,
@@ -123,7 +140,7 @@ private fun KotlinType.enhanceInflexible(qualifiers: (Int) -> JavaTypeQualifiers
else enhancedClassifier.getDefaultType().getMemberScope(), else enhancedClassifier.getDefaultType().getMemberScope(),
newCapabilities newCapabilities
) )
return Result(enhancedType, globalArgIndex - index) return Result(enhancedType, subtreeSize, wereChanges = true)
} }
private fun List<Annotations>.compositeAnnotationsOrSingle() = when (size) { private fun List<Annotations>.compositeAnnotationsOrSingle() = when (size) {
@@ -1,7 +1,7 @@
// WITH_RUNTIME // WITH_RUNTIME
// SUGGESTED_RETURN_TYPES: kotlin.Boolean?, kotlin.Boolean // SUGGESTED_RETURN_TYPES: kotlin.Boolean?, kotlin.Boolean
// PARAM_DESCRIPTOR: value-parameter val it: kotlin.collections.Map.Entry<(kotlin.Boolean..kotlin.Boolean?), (kotlin.Boolean..kotlin.Boolean?)> defined in test.<anonymous> // PARAM_DESCRIPTOR: value-parameter val it: kotlin.collections.Map.Entry<(Boolean..Boolean?), (Boolean..Boolean?)> defined in test.<anonymous>
// PARAM_TYPES: kotlin.collections.Map.Entry<(kotlin.Boolean..kotlin.Boolean?), (kotlin.Boolean..kotlin.Boolean?)> // PARAM_TYPES: kotlin.collections.Map.Entry<(Boolean..Boolean?), (Boolean..Boolean?)>
fun test() { fun test() {
J.getMap().filter { <selection>it.key</selection> } J.getMap().filter { <selection>it.key</selection> }
} }
@@ -1,7 +1,7 @@
// WITH_RUNTIME // WITH_RUNTIME
// SUGGESTED_RETURN_TYPES: kotlin.Boolean?, kotlin.Boolean // SUGGESTED_RETURN_TYPES: kotlin.Boolean?, kotlin.Boolean
// PARAM_DESCRIPTOR: value-parameter val it: kotlin.collections.Map.Entry<(kotlin.Boolean..kotlin.Boolean?), (kotlin.Boolean..kotlin.Boolean?)> defined in test.<anonymous> // PARAM_DESCRIPTOR: value-parameter val it: kotlin.collections.Map.Entry<(Boolean..Boolean?), (Boolean..Boolean?)> defined in test.<anonymous>
// PARAM_TYPES: kotlin.collections.Map.Entry<(kotlin.Boolean..kotlin.Boolean?), (kotlin.Boolean..kotlin.Boolean?)> // PARAM_TYPES: kotlin.collections.Map.Entry<(Boolean..Boolean?), (Boolean..Boolean?)>
fun test() { fun test() {
J.getMap().filter { b(it) } J.getMap().filter { b(it) }
} }
@@ -1,7 +1,7 @@
// WITH_RUNTIME // WITH_RUNTIME
// SUGGESTED_NAMES: i, getN // SUGGESTED_NAMES: i, getN
// PARAM_TYPES: kotlin.String?, kotlin.String, kotlin.CharSequence?, CharSequence // PARAM_TYPES: String?, String, kotlin.CharSequence?, CharSequence
// PARAM_DESCRIPTOR: val property: (kotlin.String..kotlin.String?) defined in test // PARAM_DESCRIPTOR: val property: (String..String?) defined in test
fun test() { fun test() {
val property = System.getProperty("some") val property = System.getProperty("some")
val n = <selection>property?.length</selection> val n = <selection>property?.length</selection>
@@ -1,7 +1,7 @@
// WITH_RUNTIME // WITH_RUNTIME
// SUGGESTED_NAMES: i, getN // SUGGESTED_NAMES: i, getN
// PARAM_TYPES: kotlin.String?, kotlin.String, kotlin.CharSequence?, CharSequence // PARAM_TYPES: String?, String, kotlin.CharSequence?, CharSequence
// PARAM_DESCRIPTOR: val property: (kotlin.String..kotlin.String?) defined in test // PARAM_DESCRIPTOR: val property: (String..String?) defined in test
fun test() { fun test() {
val property = System.getProperty("some") val property = System.getProperty("some")
val n = i(property) val n = i(property)
@@ -1,7 +1,7 @@
// WITH_RUNTIME // WITH_RUNTIME
// SUGGESTED_NAMES: i, getN // SUGGESTED_NAMES: i, getN
// PARAM_TYPES: kotlin.String, CharSequence // PARAM_TYPES: String, CharSequence
// PARAM_DESCRIPTOR: val property: (kotlin.String..kotlin.String?) defined in test // PARAM_DESCRIPTOR: val property: (String..String?) defined in test
fun test() { fun test() {
val property = System.getProperty("some") val property = System.getProperty("some")
val n = <selection>property.length</selection> val n = <selection>property.length</selection>
@@ -1,7 +1,7 @@
// WITH_RUNTIME // WITH_RUNTIME
// SUGGESTED_NAMES: i, getN // SUGGESTED_NAMES: i, getN
// PARAM_TYPES: kotlin.String, CharSequence // PARAM_TYPES: String, CharSequence
// PARAM_DESCRIPTOR: val property: (kotlin.String..kotlin.String?) defined in test // PARAM_DESCRIPTOR: val property: (String..String?) defined in test
fun test() { fun test() {
val property = System.getProperty("some") val property = System.getProperty("some")
val n = i(property) val n = i(property)
@@ -1,6 +1,6 @@
// WITH_RUNTIME // WITH_RUNTIME
// PARAM_DESCRIPTOR: val data: (kotlin.collections.MutableList<(kotlin.String..kotlin.String?)>..kotlin.collections.List<(kotlin.String..kotlin.String?)>) defined in test // PARAM_DESCRIPTOR: val data: (kotlin.collections.MutableList<(String..String?)>..kotlin.collections.List<(String..String?)>) defined in test
// PARAM_TYPES: kotlin.collections.List<(kotlin.String..kotlin.String?)>, kotlin.collections.MutableList<(kotlin.String..kotlin.String?)>, kotlin.collections.MutableCollection<(kotlin.String..kotlin.String?)>, kotlin.collections.Collection<(kotlin.String..kotlin.String?)> // PARAM_TYPES: kotlin.collections.List<(String..String?)>, kotlin.collections.MutableList<(String..String?)>, kotlin.collections.MutableCollection<(String..String?)>, kotlin.collections.Collection<(String..String?)>
fun test(): Boolean { fun test(): Boolean {
val j: J? = null val j: J? = null
val data = j?.getData() ?: return false val data = j?.getData() ?: return false
@@ -1,6 +1,6 @@
// WITH_RUNTIME // WITH_RUNTIME
// PARAM_DESCRIPTOR: val data: (kotlin.collections.MutableList<(kotlin.String..kotlin.String?)>..kotlin.collections.List<(kotlin.String..kotlin.String?)>) defined in test // PARAM_DESCRIPTOR: val data: (kotlin.collections.MutableList<(String..String?)>..kotlin.collections.List<(String..String?)>) defined in test
// PARAM_TYPES: kotlin.collections.List<(kotlin.String..kotlin.String?)>, kotlin.collections.MutableList<(kotlin.String..kotlin.String?)>, kotlin.collections.MutableCollection<(kotlin.String..kotlin.String?)>, kotlin.collections.Collection<(kotlin.String..kotlin.String?)> // PARAM_TYPES: kotlin.collections.List<(String..String?)>, kotlin.collections.MutableList<(String..String?)>, kotlin.collections.MutableCollection<(String..String?)>, kotlin.collections.Collection<(String..String?)>
fun test(): Boolean { fun test(): Boolean {
val j: J? = null val j: J? = null
val data = j?.getData() ?: return false val data = j?.getData() ?: return false