Do not load special builtin overrides from Java as synthesized

It has been done just to avoid clashes with real declarations that look
like our builtins: e.g. 'String removeAt(int index) {}' and 'String remove(int index) {}'in Java.

But synthesized members are even weaker than extensions.

Solution is just to ignore the latter declaration and treat first as effective override
of out builltin.
This commit is contained in:
Denis Zharkov
2015-10-13 17:48:41 +03:00
committed by Mikhail Glukhikh
parent cd589b7e6a
commit e062e32f95
18 changed files with 375 additions and 37 deletions
@@ -106,7 +106,7 @@ public class JavaConstructorDescriptor extends ConstructorDescriptorImpl impleme
enhancedReceiverType,
getDispatchReceiverParameter(),
getTypeParameters(),
DescriptorsPackage.createEnhancedValueParameters(enhancedValueParametersTypes, getValueParameters(), enhanced),
DescriptorsPackage.copyValueParameters(enhancedValueParametersTypes, getValueParameters(), enhanced),
enhancedReturnType,
getModality(),
getVisibility()
@@ -135,7 +135,7 @@ public class JavaMethodDescriptor extends SimpleFunctionDescriptorImpl implement
@NotNull JetType enhancedReturnType
) {
List<ValueParameterDescriptor> enhancedValueParameters =
DescriptorsPackage.createEnhancedValueParameters(enhancedValueParametersTypes, getValueParameters(), this);
UtilKt.copyValueParameters(enhancedValueParametersTypes, getValueParameters(), this);
// We use `doSubstitute` here because it does exactly what we need:
// 1. creates full copy of descriptor
@@ -22,16 +22,16 @@ import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.types.JetType
fun createEnhancedValueParameters(
enhancedTypes: Collection<JetType>,
fun copyValueParameters(
newValueParametersTypes: Collection<JetType>,
oldValueParameters: Collection<ValueParameterDescriptor>,
newOwner: CallableDescriptor
): List<ValueParameterDescriptor> {
assert(enhancedTypes.size() == oldValueParameters.size()) {
"Different value parameters sizes: Enhanced = ${enhancedTypes.size()}, Old = ${oldValueParameters.size()}"
assert(newValueParametersTypes.size() == oldValueParameters.size()) {
"Different value parameters sizes: Enhanced = ${newValueParametersTypes.size}, Old = ${oldValueParameters.size}"
}
return enhancedTypes.zip(oldValueParameters).map {
return newValueParametersTypes.zip(oldValueParameters).map {
pair ->
val (newType, oldParameter) = pair
ValueParameterDescriptorImpl(
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.load.java.components.TypeUsage
import org.jetbrains.kotlin.load.java.descriptors.JavaConstructorDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor
import org.jetbrains.kotlin.load.java.descriptors.copyValueParameters
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
import org.jetbrains.kotlin.load.java.lazy.child
import org.jetbrains.kotlin.load.java.lazy.resolveAnnotations
@@ -98,9 +99,25 @@ public class LazyJavaClassMemberScope(
return false
}
if (name.sameAsBuiltinMethodWithErasedValueParameters && javaMethod != null) {
val originalMethodDescriptor = super.resolveMethodToFunctionDescriptor(javaMethod)
val overridden = firstOverriddenBuiltinFunctionWithErasedValueParameters(originalMethodDescriptor)
if (overridden != null) {
if (doesClassOverrideBuiltinWithoutMagic(overridden)) return false
}
}
return true
}
// E.g. it have explicit removeAt declaration in Java
private fun doesClassOverrideBuiltinWithoutMagic(callableMemberDescriptor: CallableMemberDescriptor): Boolean {
return memberIndex().findMethodsByName(callableMemberDescriptor.name).any {
otherJavaMethod ->
super.resolveMethodToFunctionDescriptor(otherJavaMethod).doesOverride(callableMemberDescriptor)
}
}
private fun JavaMethod.doesOverrideRenamedBuiltins(): Boolean {
return BuiltinSpecialMethods.getSpecialBuiltinFunctionsByJvmName(name).any {
builtinName ->
@@ -118,13 +135,24 @@ public class LazyJavaClassMemberScope(
// if we check 'removeAt', get original sub-descriptor to distinct `remove(int)` and `remove(E)` in Java
val subDescriptorToCheck = if (superDescriptor.isRemoveAtByIndex) subDescriptor.original else subDescriptor
return subDescriptorToCheck.doesOverride(superDescriptor)
}
private fun CallableDescriptor.doesOverride(superDescriptor: CallableDescriptor): Boolean {
return OverridingUtil.DEFAULT.isOverridableByIncludingReturnType(
superDescriptor, subDescriptorToCheck
superDescriptor, this
).result == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE
}
private fun PropertyDescriptor.findGetterOverride(): JavaMethodDescriptor? {
val getterName = getter?.getBuiltinSpecialOverridden()?.getBuiltinSpecialPropertyGetterName() ?: JvmAbi.getterName(name.asString())
val commonProperty = findGetterByName(JvmAbi.getterName(name.asString()))
if (commonProperty != null) return commonProperty
val specialGetterName = getter?.getBuiltinSpecialOverridden()?.getBuiltinSpecialPropertyGetterName() ?: return null
return findGetterByName(specialGetterName)
}
private fun PropertyDescriptor.findGetterByName(getterName: String): JavaMethodDescriptor? {
return memberIndex().findMethodsByName(Name.identifier(getterName)).firstNotNullResult factory@{
javaMethod ->
val descriptor = resolveMethodToFunctionDescriptor(javaMethod)
@@ -177,6 +205,9 @@ public class LazyJavaClassMemberScope(
for (descriptor in mergedFunctionFromSuperTypes) {
val overriddenBuiltin = descriptor.getBuiltinSpecialOverridden() ?: continue
if (result.any { it.doesOverride(overriddenBuiltin) }) continue
val nameInJava = getJvmMethodNameIfSpecial(overriddenBuiltin)!!
for (method in memberIndex().findMethodsByName(Name.identifier(nameInJava))) {
val renamedCopy = resolveMethodToFunctionDescriptorWithName(method, name)
@@ -316,30 +347,38 @@ public class LazyJavaClassMemberScope(
methodDescriptor: JavaMethodDescriptor
): JavaMethodDescriptor? {
val overriddenCandidates =
getFunctionsFromSupertypes(methodDescriptor.name).map {
BuiltinMethodsWithSpecialJvmSignature.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(it)
}.filterNotNull()
val overridden = firstOverriddenBuiltinFunctionWithErasedValueParameters(methodDescriptor) ?: return null
if (overriddenCandidates.isEmpty()) return null
val newMethod = JavaMethodDescriptor.createJavaMethod(
methodDescriptor.containingDeclaration, methodDescriptor.annotations, methodDescriptor.name, methodDescriptor.source)
val overridden = firstOverriddenBuiltinFunctionWithErasedValueParameters(methodDescriptor, overriddenCandidates) ?: return null
return methodDescriptor
.enhance(
methodDescriptor.extensionReceiverParameter?.type,
overridden.valueParameters.map { it.type },
methodDescriptor.returnType!!)
.copy(
methodDescriptor.containingDeclaration,
methodDescriptor.modality, methodDescriptor.visibility,
CallableMemberDescriptor.Kind.SYNTHESIZED, false) as? JavaMethodDescriptor
assert(methodDescriptor.typeParameters.isEmpty()) { "There should be methods with no type parameters, but $methodDescriptor found" }
newMethod.initialize(
methodDescriptor.extensionReceiverParameter?.type,
methodDescriptor.dispatchReceiverParameter,
emptyList(),
copyValueParameters(overridden.valueParameters.map { it.type }, methodDescriptor.valueParameters, newMethod),
methodDescriptor.returnType,
methodDescriptor.modality,
methodDescriptor.visibility
)
newMethod.setParameterNamesStatus(methodDescriptor.hasStableParameterNames(), methodDescriptor.hasSynthesizedParameterNames())
return newMethod
}
private fun firstOverriddenBuiltinFunctionWithErasedValueParameters(
javaMethodDescriptor: JavaMethodDescriptor,
candidatesToOverride: Collection<FunctionDescriptor>
javaMethodDescriptor: JavaMethodDescriptor
): FunctionDescriptor? {
val candidatesToOverride =
getFunctionsFromSupertypes(javaMethodDescriptor.name).map {
BuiltinMethodsWithSpecialJvmSignature.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(it)
}.filterNotNull()
if (candidatesToOverride.isEmpty()) return null
return candidatesToOverride.firstNotNullResult overrides@{
candidate ->
candidate.check { javaMethodDescriptor.doesOverrideBuiltinFunctionWithErasedValueParameters(candidate) }