FIR: Do not load hashCode/toString/equals methods from Java interface
As it's done in FE 1.0, and there are subtle semantics in the language that depends on it
This commit is contained in:
@@ -205,6 +205,7 @@ class JavaSymbolProvider(
|
|||||||
val classIsAnnotation = classKind == ClassKind.ANNOTATION_CLASS
|
val classIsAnnotation = classKind == ClassKind.ANNOTATION_CLASS
|
||||||
|
|
||||||
for (javaMethod in javaClass.methods) {
|
for (javaMethod in javaClass.methods) {
|
||||||
|
if (javaMethod.isObjectMethodInInterface()) continue
|
||||||
declarations += convertJavaMethodToFir(
|
declarations += convertJavaMethodToFir(
|
||||||
javaMethod,
|
javaMethod,
|
||||||
classId,
|
classId,
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
public abstract interface Comparator<T : R|ft<kotlin/Any, kotlin/Any?>!|> : R|kotlin/Any| {
|
public abstract interface Comparator<T : R|ft<kotlin/Any, kotlin/Any?>!|> : R|kotlin/Any| {
|
||||||
public abstract fun compare(o1: R|ft<T, T?>!|, o2: R|ft<T, T?>!|): R|kotlin/Int|
|
public abstract fun compare(o1: R|ft<T, T?>!|, o2: R|ft<T, T?>!|): R|kotlin/Int|
|
||||||
|
|
||||||
public abstract operator fun equals(obj: R|kotlin/Any?|): R|kotlin/Boolean|
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,2 @@
|
|||||||
public abstract interface InterfaceWithObjectMethod : R|kotlin/Any| {
|
public abstract interface InterfaceWithObjectMethod : R|kotlin/Any| {
|
||||||
public abstract fun toString(): R|kotlin/String|
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.load.java.structure
|
||||||
|
|
||||||
|
|
||||||
|
fun JavaMember.isObjectMethodInInterface(): Boolean {
|
||||||
|
return containingClass.isInterface && this is JavaMethod && isObjectMethod(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isObjectMethod(method: JavaMethod): Boolean {
|
||||||
|
return when (method.name.asString()) {
|
||||||
|
"toString", "hashCode" -> {
|
||||||
|
method.valueParameters.isEmpty()
|
||||||
|
}
|
||||||
|
"equals" -> {
|
||||||
|
isMethodWithOneObjectParameter(method)
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isMethodWithOneObjectParameter(method: JavaMethod): Boolean {
|
||||||
|
val parameters = method.valueParameters
|
||||||
|
val type = parameters.singleOrNull()?.type as? JavaClassifierType ?: return false
|
||||||
|
val classifier = type.classifier
|
||||||
|
if (classifier is JavaClass) {
|
||||||
|
val classFqName = classifier.fqName
|
||||||
|
return classFqName != null && classFqName.asString() == "java.lang.Object"
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
-32
@@ -24,8 +24,6 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor;
|
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||||
import org.jetbrains.kotlin.load.java.structure.*;
|
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.resolve.NonReportingOverrideStrategy;
|
import org.jetbrains.kotlin.resolve.NonReportingOverrideStrategy;
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil;
|
import org.jetbrains.kotlin.resolve.OverridingUtil;
|
||||||
@@ -33,7 +31,6 @@ import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public final class DescriptorResolverUtils {
|
public final class DescriptorResolverUtils {
|
||||||
@@ -121,33 +118,4 @@ public final class DescriptorResolverUtils {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isObjectMethodInInterface(@NotNull JavaMember member) {
|
|
||||||
return member.getContainingClass().isInterface() && member instanceof JavaMethod && isObjectMethod((JavaMethod) member);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isObjectMethod(@NotNull JavaMethod method) {
|
|
||||||
String name = method.getName().asString();
|
|
||||||
if (name.equals("toString") || name.equals("hashCode")) {
|
|
||||||
return method.getValueParameters().isEmpty();
|
|
||||||
}
|
|
||||||
else if (name.equals("equals")) {
|
|
||||||
return isMethodWithOneObjectParameter(method);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isMethodWithOneObjectParameter(@NotNull JavaMethod method) {
|
|
||||||
List<JavaValueParameter> parameters = method.getValueParameters();
|
|
||||||
if (parameters.size() == 1) {
|
|
||||||
JavaType type = parameters.get(0).getType();
|
|
||||||
if (type instanceof JavaClassifierType) {
|
|
||||||
JavaClassifier classifier = ((JavaClassifierType) type).getClassifier();
|
|
||||||
if (classifier instanceof JavaClass) {
|
|
||||||
FqName classFqName = ((JavaClass) classifier).getFqName();
|
|
||||||
return classFqName != null && classFqName.asString().equals("java.lang.Object");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-6
@@ -16,11 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.load.java.lazy.descriptors
|
package org.jetbrains.kotlin.load.java.lazy.descriptors
|
||||||
|
|
||||||
import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils
|
import org.jetbrains.kotlin.load.java.structure.*
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaField
|
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaMember
|
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaMethod
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
interface DeclaredMemberIndex {
|
interface DeclaredMemberIndex {
|
||||||
@@ -44,7 +40,7 @@ open class ClassDeclaredMemberIndex(
|
|||||||
private val memberFilter: (JavaMember) -> Boolean
|
private val memberFilter: (JavaMember) -> Boolean
|
||||||
) : DeclaredMemberIndex {
|
) : DeclaredMemberIndex {
|
||||||
private val methodFilter = { m: JavaMethod ->
|
private val methodFilter = { m: JavaMethod ->
|
||||||
memberFilter(m) && !DescriptorResolverUtils.isObjectMethodInInterface(m)
|
memberFilter(m) && !m.isObjectMethodInInterface()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val methods = jClass.methods.asSequence().filter(methodFilter).groupBy { m -> m.name }
|
private val methods = jClass.methods.asSequence().filter(methodFilter).groupBy { m -> m.name }
|
||||||
|
|||||||
Reference in New Issue
Block a user