FIR: Rework loading overrides of special built-in methods from Java
Some of the changed data is correct, but some diagnostics are incorrect Corner cases like having both contains(Object) and contains(String) within implementation of Collection<String> is not supported
This commit is contained in:
@@ -43,6 +43,9 @@ import org.jetbrains.kotlin.util.OperatorNameConventions.ITERATOR
|
|||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.NEXT
|
import org.jetbrains.kotlin.util.OperatorNameConventions.NEXT
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.SET
|
import org.jetbrains.kotlin.util.OperatorNameConventions.SET
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.UNARY_OPERATION_NAMES
|
import org.jetbrains.kotlin.util.OperatorNameConventions.UNARY_OPERATION_NAMES
|
||||||
|
import kotlin.contracts.ExperimentalContracts
|
||||||
|
import kotlin.contracts.InvocationKind
|
||||||
|
import kotlin.contracts.contract
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
@OptIn(FirImplementationDetail::class)
|
@OptIn(FirImplementationDetail::class)
|
||||||
@@ -227,3 +230,29 @@ class FirJavaMethodBuilder : FirFunctionBuilder, FirTypeParametersOwnerBuilder,
|
|||||||
inline fun buildJavaMethod(init: FirJavaMethodBuilder.() -> Unit): FirJavaMethod {
|
inline fun buildJavaMethod(init: FirJavaMethodBuilder.() -> Unit): FirJavaMethod {
|
||||||
return FirJavaMethodBuilder().apply(init).build()
|
return FirJavaMethodBuilder().apply(init).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalContracts::class)
|
||||||
|
inline fun buildJavaMethodCopy(original: FirSimpleFunction, init: FirJavaMethodBuilder.() -> Unit): FirJavaMethod {
|
||||||
|
contract {
|
||||||
|
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||||
|
}
|
||||||
|
val copyBuilder = FirJavaMethodBuilder()
|
||||||
|
copyBuilder.source = original.source
|
||||||
|
copyBuilder.session = original.session
|
||||||
|
copyBuilder.resolvePhase = original.resolvePhase
|
||||||
|
copyBuilder.attributes = original.attributes.copy()
|
||||||
|
copyBuilder.returnTypeRef = original.returnTypeRef
|
||||||
|
copyBuilder.valueParameters.addAll(original.valueParameters)
|
||||||
|
copyBuilder.body = original.body
|
||||||
|
copyBuilder.status = original.status
|
||||||
|
copyBuilder.dispatchReceiverType = original.dispatchReceiverType
|
||||||
|
copyBuilder.name = original.name
|
||||||
|
copyBuilder.symbol = original.symbol
|
||||||
|
copyBuilder.annotations.addAll(original.annotations)
|
||||||
|
copyBuilder.typeParameters.addAll(original.typeParameters)
|
||||||
|
val annotations = original.annotations
|
||||||
|
copyBuilder.annotationBuilder = { annotations }
|
||||||
|
return copyBuilder
|
||||||
|
.apply(init)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|||||||
+21
@@ -20,6 +20,9 @@ import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
|||||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import kotlin.contracts.ExperimentalContracts
|
||||||
|
import kotlin.contracts.InvocationKind
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
@OptIn(FirImplementationDetail::class)
|
@OptIn(FirImplementationDetail::class)
|
||||||
class FirJavaValueParameter @FirImplementationDetail constructor(
|
class FirJavaValueParameter @FirImplementationDetail constructor(
|
||||||
@@ -174,3 +177,21 @@ class FirJavaValueParameterBuilder {
|
|||||||
inline fun buildJavaValueParameter(init: FirJavaValueParameterBuilder.() -> Unit): FirJavaValueParameter {
|
inline fun buildJavaValueParameter(init: FirJavaValueParameterBuilder.() -> Unit): FirJavaValueParameter {
|
||||||
return FirJavaValueParameterBuilder().apply(init).build()
|
return FirJavaValueParameterBuilder().apply(init).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalContracts::class)
|
||||||
|
inline fun buildJavaValueParameterCopy(original: FirValueParameter, init: FirJavaValueParameterBuilder.() -> Unit): FirValueParameter {
|
||||||
|
contract {
|
||||||
|
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||||
|
}
|
||||||
|
val copyBuilder = FirJavaValueParameterBuilder()
|
||||||
|
copyBuilder.source = original.source
|
||||||
|
copyBuilder.session = original.session
|
||||||
|
copyBuilder.attributes = original.attributes.copy()
|
||||||
|
copyBuilder.returnTypeRef = original.returnTypeRef
|
||||||
|
copyBuilder.name = original.name
|
||||||
|
val annotations = original.annotations
|
||||||
|
copyBuilder.annotationBuilder = { annotations }
|
||||||
|
copyBuilder.defaultValue = original.defaultValue
|
||||||
|
copyBuilder.isVararg = original.isVararg
|
||||||
|
return copyBuilder.apply(init).build()
|
||||||
|
}
|
||||||
|
|||||||
+8
-1
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty
|
|||||||
import org.jetbrains.kotlin.fir.initialSignatureAttr
|
import org.jetbrains.kotlin.fir.initialSignatureAttr
|
||||||
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
|
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
|
||||||
import org.jetbrains.kotlin.fir.java.declarations.*
|
import org.jetbrains.kotlin.fir.java.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.java.toConeKotlinTypeProbablyFlexible
|
||||||
import org.jetbrains.kotlin.fir.render
|
import org.jetbrains.kotlin.fir.render
|
||||||
import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptor
|
import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptor
|
||||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||||
@@ -165,7 +166,10 @@ class FirSignatureEnhancement(
|
|||||||
val memberContext = context.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, jsr305State, firMethod.annotations)
|
val memberContext = context.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, jsr305State, firMethod.annotations)
|
||||||
|
|
||||||
val predefinedEnhancementInfo =
|
val predefinedEnhancementInfo =
|
||||||
SignatureBuildingComponents.signature(owner.symbol.classId, firMethod.computeJvmDescriptor()).let { signature ->
|
SignatureBuildingComponents.signature(
|
||||||
|
owner.symbol.classId,
|
||||||
|
firMethod.computeJvmDescriptor { it.toConeKotlinTypeProbablyFlexible(session, javaTypeParameterStack) }
|
||||||
|
).let { signature ->
|
||||||
PREDEFINED_FUNCTION_ENHANCEMENT_INFO_BY_SIGNATURE[signature]
|
PREDEFINED_FUNCTION_ENHANCEMENT_INFO_BY_SIGNATURE[signature]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,6 +312,9 @@ class FirSignatureEnhancement(
|
|||||||
ownerParameter: FirJavaValueParameter,
|
ownerParameter: FirJavaValueParameter,
|
||||||
index: Int
|
index: Int
|
||||||
): FirResolvedTypeRef {
|
): FirResolvedTypeRef {
|
||||||
|
if (ownerParameter.returnTypeRef is FirResolvedTypeRef) {
|
||||||
|
return ownerParameter.returnTypeRef as FirResolvedTypeRef
|
||||||
|
}
|
||||||
val signatureParts = ownerFunction.partsForValueParameter(
|
val signatureParts = ownerFunction.partsForValueParameter(
|
||||||
typeQualifierResolver,
|
typeQualifierResolver,
|
||||||
overriddenMembers,
|
overriddenMembers,
|
||||||
|
|||||||
+1
-97
@@ -5,31 +5,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.java.scopes
|
package org.jetbrains.kotlin.fir.java.scopes
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames
|
|
||||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
import org.jetbrains.kotlin.fir.java.enhancement.FirSignatureEnhancement
|
import org.jetbrains.kotlin.fir.java.enhancement.FirSignatureEnhancement
|
||||||
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptorReplacingKotlinToJava
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures
|
|
||||||
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.ERASED_COLLECTION_PARAMETER_SIGNATURES
|
|
||||||
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.ERASED_VALUE_PARAMETERS_SHORT_NAMES
|
|
||||||
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.ERASED_VALUE_PARAMETERS_SIGNATURES
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
|
||||||
|
|
||||||
class JavaClassMembersEnhancementScope(
|
class JavaClassMembersEnhancementScope(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
@@ -62,91 +48,10 @@ class JavaClassMembersEnhancementScope(
|
|||||||
return super.processPropertiesByName(name, processor)
|
return super.processPropertiesByName(name, processor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirSimpleFunction.changeSignatureIfErasedValueParameter(): FirSimpleFunction {
|
|
||||||
val typeParameters = owner.fir.typeParameters
|
|
||||||
if (typeParameters.isEmpty() || name !in ERASED_VALUE_PARAMETERS_SHORT_NAMES) {
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
val jvmDescriptor = this.computeJvmDescriptorReplacingKotlinToJava().replace(
|
|
||||||
"kotlin/collections/Collection",
|
|
||||||
"java/util/Collection"
|
|
||||||
)
|
|
||||||
if (ERASED_VALUE_PARAMETERS_SIGNATURES.none { it.endsWith(jvmDescriptor) }) {
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
val superClassIds = listOfNotNull(symbol.callableId.classId) +
|
|
||||||
lookupSuperTypes(owner, lookupInterfaces = true, deep = true, useSiteSession = session).map { it.lookupTag.classId }
|
|
||||||
for (superClassId in superClassIds) {
|
|
||||||
val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(superClassId.asSingleFqName().toUnsafe()) ?: superClassId
|
|
||||||
val newParameterTypes: List<ConeKotlinType?> = when (val fqJvmDescriptor = "${javaClassId.asString()}.$jvmDescriptor") {
|
|
||||||
in ERASED_COLLECTION_PARAMETER_SIGNATURES -> {
|
|
||||||
valueParameters.map {
|
|
||||||
val typeParameter = typeParameters.first()
|
|
||||||
ConeClassLikeLookupTagImpl(ClassId.topLevel(StandardNames.FqNames.collection)).constructClassType(
|
|
||||||
arrayOf(
|
|
||||||
ConeTypeParameterLookupTag(typeParameter.symbol).constructType(emptyArray(), isNullable = false)
|
|
||||||
), isNullable = false
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
in ERASED_VALUE_PARAMETERS_SIGNATURES -> {
|
|
||||||
val specialSignatureInfo = SpecialGenericSignatures.getSpecialSignatureInfo(fqJvmDescriptor)
|
|
||||||
if (!specialSignatureInfo.isObjectReplacedWithTypeParameter) {
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
valueParameters.mapIndexed { i, valueParameter ->
|
|
||||||
val classLikeType =
|
|
||||||
valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()?.lowerBoundIfFlexible().safeAs<ConeClassLikeType>()
|
|
||||||
if (classLikeType?.lookupTag?.classId == StandardClassIds.Any) {
|
|
||||||
val typeParameterIndex = if (name.asString() == "containsValue") 1 else i
|
|
||||||
val typeParameter = typeParameters.getOrNull(typeParameterIndex) ?: typeParameters.first()
|
|
||||||
val type = ConeTypeParameterLookupTag(typeParameter.symbol).constructType(
|
|
||||||
emptyArray(), valueParameter.returnTypeRef.isMarkedNullable == true
|
|
||||||
)
|
|
||||||
if (valueParameter.returnTypeRef.coneType is ConeFlexibleType) {
|
|
||||||
ConeFlexibleType(
|
|
||||||
type.withAttributes(
|
|
||||||
type.attributes.withFlexibleUnless {
|
|
||||||
it.hasEnhancedNullability
|
|
||||||
}
|
|
||||||
),
|
|
||||||
type.withNullability(ConeNullability.NULLABLE)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
type
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newParameterTypes.none { it != null }) {
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
return FirFakeOverrideGenerator.createCopyForFirFunction(
|
|
||||||
FirNamedFunctionSymbol(symbol.callableId),
|
|
||||||
this,
|
|
||||||
session,
|
|
||||||
FirDeclarationOrigin.Enhancement,
|
|
||||||
newParameterTypes = valueParameters.zip(newParameterTypes).map { (valueParameter, newType) ->
|
|
||||||
newType ?: valueParameter.returnTypeRef.coneType
|
|
||||||
},
|
|
||||||
newDispatchReceiverType = dispatchReceiverType,
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
||||||
useSiteMemberScope.processFunctionsByName(name) process@{ original ->
|
useSiteMemberScope.processFunctionsByName(name) process@{ original ->
|
||||||
val symbol = signatureEnhancement.enhancedFunction(original, name)
|
val symbol = signatureEnhancement.enhancedFunction(original, name)
|
||||||
val enhancedFunction = (symbol.fir as? FirSimpleFunction)?.changeSignatureIfErasedValueParameter()
|
val enhancedFunction = (symbol.fir as? FirSimpleFunction)
|
||||||
val enhancedFunctionSymbol = enhancedFunction?.symbol ?: symbol
|
val enhancedFunctionSymbol = enhancedFunction?.symbol ?: symbol
|
||||||
|
|
||||||
if (enhancedFunctionSymbol is FirNamedFunctionSymbol) {
|
if (enhancedFunctionSymbol is FirNamedFunctionSymbol) {
|
||||||
@@ -162,7 +67,6 @@ class JavaClassMembersEnhancementScope(
|
|||||||
|
|
||||||
private fun FirCallableMemberDeclaration<*>.overriddenMembers(name: Name): List<FirCallableMemberDeclaration<*>> {
|
private fun FirCallableMemberDeclaration<*>.overriddenMembers(name: Name): List<FirCallableMemberDeclaration<*>> {
|
||||||
val backMap = overrideBindCache.getOrPut(name) {
|
val backMap = overrideBindCache.getOrPut(name) {
|
||||||
useSiteMemberScope.bindOverrides(name)
|
|
||||||
useSiteMemberScope
|
useSiteMemberScope
|
||||||
.overrideByBase
|
.overrideByBase
|
||||||
.toList()
|
.toList()
|
||||||
|
|||||||
+374
-98
@@ -5,26 +5,30 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.java.scopes
|
package org.jetbrains.kotlin.fir.java.scopes
|
||||||
|
|
||||||
import com.intellij.lang.jvm.types.JvmPrimitiveTypeKind
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
|
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
|
||||||
import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty
|
import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty
|
||||||
import org.jetbrains.kotlin.fir.java.declarations.*
|
import org.jetbrains.kotlin.fir.java.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.FirJavaSyntheticNamesProvider
|
import org.jetbrains.kotlin.fir.java.toConeKotlinTypeProbablyFlexible
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.syntheticNamesProvider
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.*
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.getContainingCallableNamesIfPresent
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.getContainingClassifierNamesIfPresent
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.AbstractFirUseSiteMemberScope
|
import org.jetbrains.kotlin.fir.scopes.impl.AbstractFirUseSiteMemberScope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptor
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmSignature
|
||||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.types.isUnit
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
|
import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaPrimitiveType
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaPrimitiveTypeImpl
|
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures
|
||||||
|
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.ERASED_COLLECTION_PARAMETER_NAMES
|
||||||
|
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.sameAsBuiltinMethodWithErasedValueParameters
|
||||||
|
import org.jetbrains.kotlin.load.java.getPropertyNamesCandidatesByAccessorName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||||
|
|
||||||
class JavaClassUseSiteMemberScope(
|
class JavaClassUseSiteMemberScope(
|
||||||
klass: FirJavaClass,
|
klass: FirJavaClass,
|
||||||
@@ -37,15 +41,8 @@ class JavaClassUseSiteMemberScope(
|
|||||||
superTypesScope,
|
superTypesScope,
|
||||||
declaredMemberScope
|
declaredMemberScope
|
||||||
) {
|
) {
|
||||||
internal fun bindOverrides(name: Name) {
|
private val typeParameterStack = klass.javaTypeParameterStack
|
||||||
val overrideCandidates = mutableSetOf<FirNamedFunctionSymbol>()
|
private val specialFunctions = hashMapOf<Name, Collection<FirNamedFunctionSymbol>>()
|
||||||
declaredMemberScope.processFunctionsByName(name) {
|
|
||||||
overrideCandidates += it
|
|
||||||
}
|
|
||||||
superTypesScope.processFunctionsByName(name) {
|
|
||||||
it.getOverridden(overrideCandidates)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getCallableNames(): Set<Name> {
|
override fun getCallableNames(): Set<Name> {
|
||||||
return declaredMemberScope.getContainingCallableNamesIfPresent() + superTypesScope.getCallableNames()
|
return declaredMemberScope.getContainingCallableNamesIfPresent() + superTypesScope.getCallableNames()
|
||||||
@@ -72,99 +69,378 @@ class JavaClassUseSiteMemberScope(
|
|||||||
}.symbol
|
}.symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processAccessorFunctionsAndPropertiesByName(
|
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
|
||||||
propertyName: Name,
|
val fields = mutableSetOf<FirCallableSymbol<*>>()
|
||||||
getterNames: List<Name>,
|
val fieldNames = mutableSetOf<Name>()
|
||||||
processor: (FirVariableSymbol<*>) -> Unit
|
|
||||||
) {
|
// fields
|
||||||
val overrideCandidates = mutableSetOf<FirCallableSymbol<*>>()
|
declaredMemberScope.processPropertiesByName(name) processor@{ variableSymbol ->
|
||||||
declaredMemberScope.processPropertiesByName(propertyName) { variableSymbol ->
|
if (variableSymbol.isStatic) return@processor
|
||||||
if (variableSymbol.isStatic) return@processPropertiesByName
|
fields += variableSymbol
|
||||||
overrideCandidates += variableSymbol
|
fieldNames += variableSymbol.fir.name
|
||||||
processor(variableSymbol)
|
processor(variableSymbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (getterName in getterNames) {
|
val fromSupertypes = superTypesScope.getProperties(name)
|
||||||
var getterSymbol: FirNamedFunctionSymbol? = null
|
|
||||||
var setterSymbol: FirNamedFunctionSymbol? = null
|
|
||||||
declaredMemberScope.processFunctionsByName(getterName) { functionSymbol ->
|
|
||||||
if (getterSymbol == null) {
|
|
||||||
val function = functionSymbol.fir
|
|
||||||
if (!function.isStatic && function.valueParameters.isEmpty()) {
|
|
||||||
getterSymbol = functionSymbol
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val setterName = session.syntheticNamesProvider.setterNameByGetterName(getterName)
|
|
||||||
if (getterSymbol != null && setterName != null) {
|
|
||||||
declaredMemberScope.processFunctionsByName(setterName) { functionSymbol ->
|
|
||||||
if (setterSymbol == null) {
|
|
||||||
val function = functionSymbol.fir
|
|
||||||
if (!function.isStatic && function.valueParameters.size == 1) {
|
|
||||||
val returnTypeRef = function.returnTypeRef
|
|
||||||
if (returnTypeRef.isUnit) {
|
|
||||||
// Unit return type
|
|
||||||
setterSymbol = functionSymbol
|
|
||||||
} else if (returnTypeRef is FirJavaTypeRef) {
|
|
||||||
// Void/void return type
|
|
||||||
when (val returnType = returnTypeRef.type) {
|
|
||||||
is JavaPrimitiveTypeImpl ->
|
|
||||||
if (returnType.psi.kind == JvmPrimitiveTypeKind.VOID) {
|
|
||||||
setterSymbol = functionSymbol
|
|
||||||
}
|
|
||||||
is JavaPrimitiveType ->
|
|
||||||
if (returnType.type == null) {
|
|
||||||
setterSymbol = functionSymbol
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val accessorSymbol = generateAccessorSymbol(getterSymbol!!, setterSymbol, propertyName)
|
|
||||||
overrideCandidates += accessorSymbol
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
superTypesScope.processPropertiesByName(propertyName) {
|
for (propertyFromSupertype in fromSupertypes) {
|
||||||
when (val overriddenBy = it.getOverridden(overrideCandidates)) {
|
if (propertyFromSupertype is FirFieldSymbol) {
|
||||||
null -> processor(it)
|
if (propertyFromSupertype.fir.name !in fieldNames) {
|
||||||
is FirAccessorSymbol -> processor(overriddenBy)
|
processor(propertyFromSupertype)
|
||||||
is FirPropertySymbol -> if (it is FirPropertySymbol) {
|
|
||||||
directOverriddenProperties.getOrPut(overriddenBy) { mutableListOf() }.add(it)
|
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (propertyFromSupertype !is FirPropertySymbol) continue
|
||||||
|
val overrideInClass = propertyFromSupertype.createOverridePropertyIfExists(declaredMemberScope)
|
||||||
|
when {
|
||||||
|
overrideInClass != null -> {
|
||||||
|
directOverriddenProperties.getOrPut(overrideInClass) { mutableListOf() }.add(propertyFromSupertype)
|
||||||
|
overrideByBase[propertyFromSupertype] = overrideInClass
|
||||||
|
processor(overrideInClass)
|
||||||
|
}
|
||||||
|
else -> processor(propertyFromSupertype)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
|
private fun FirVariableSymbol<*>.createOverridePropertyIfExists(scope: FirScope): FirPropertySymbol? {
|
||||||
val getterNames = FirJavaSyntheticNamesProvider.possibleGetterNamesByPropertyName(name)
|
if (this !is FirPropertySymbol || !doesClassOverridesProperty(this, scope)) return null
|
||||||
return processAccessorFunctionsAndPropertiesByName(name, getterNames, processor)
|
|
||||||
|
val getterSymbol = this.findGetterOverride(scope)!!
|
||||||
|
val setterSymbol =
|
||||||
|
if (this.fir.isVar)
|
||||||
|
this.findSetterOverride(scope)!!
|
||||||
|
else
|
||||||
|
null
|
||||||
|
|
||||||
|
return generateAccessorSymbol(getterSymbol, setterSymbol, fir.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doesClassOverridesProperty(
|
||||||
|
propertySymbolFromSupertype: FirPropertySymbol,
|
||||||
|
scope: FirScope,
|
||||||
|
): Boolean {
|
||||||
|
val getter = propertySymbolFromSupertype.findGetterOverride(scope)
|
||||||
|
val setter = propertySymbolFromSupertype.findSetterOverride(scope)
|
||||||
|
|
||||||
|
if (getter == null) return false
|
||||||
|
if (!propertySymbolFromSupertype.fir.isVar) return true
|
||||||
|
|
||||||
|
return setter != null && setter.fir.modality == getter.fir.modality
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirPropertySymbol.findGetterOverride(
|
||||||
|
scope: FirScope,
|
||||||
|
): FirNamedFunctionSymbol? {
|
||||||
|
val specialGetterName = getBuiltinSpecialPropertyGetterName()
|
||||||
|
if (specialGetterName != null) {
|
||||||
|
return findGetterByName(specialGetterName.asString(), scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
return findGetterByName(JvmAbi.getterName(fir.name.asString()), scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirPropertySymbol.findGetterByName(
|
||||||
|
getterName: String,
|
||||||
|
scope: FirScope,
|
||||||
|
): FirNamedFunctionSymbol? {
|
||||||
|
val propertyFromSupertype = fir
|
||||||
|
val expectedReturnType = propertyFromSupertype.returnTypeRef.coneTypeSafe<ConeKotlinType>()
|
||||||
|
return scope.getFunctions(Name.identifier(getterName)).firstNotNullResult factory@{ candidateSymbol ->
|
||||||
|
val candidate = candidateSymbol.fir
|
||||||
|
if (candidate.valueParameters.isNotEmpty()) return@factory null
|
||||||
|
|
||||||
|
val candidateReturnType = candidate.returnTypeRef.toConeKotlinTypeProbablyFlexible(session, typeParameterStack)
|
||||||
|
|
||||||
|
candidateSymbol.takeIf {
|
||||||
|
// TODO: Decide something for the case when property type is not computed yet
|
||||||
|
expectedReturnType == null || AbstractTypeChecker.isSubtypeOf(session.typeContext, candidateReturnType, expectedReturnType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirPropertySymbol.findSetterOverride(
|
||||||
|
scope: FirScope,
|
||||||
|
): FirNamedFunctionSymbol? {
|
||||||
|
val propertyType = fir.returnTypeRef.coneTypeSafe<ConeKotlinType>() ?: return null
|
||||||
|
return scope.getFunctions(Name.identifier(JvmAbi.setterName(fir.name.asString()))).firstNotNullResult factory@{ candidateSymbol ->
|
||||||
|
val candidate = candidateSymbol.fir
|
||||||
|
if (candidate.valueParameters.size != 1) return@factory null
|
||||||
|
|
||||||
|
if (!candidate.returnTypeRef.toConeKotlinTypeProbablyFlexible(session, typeParameterStack).isUnit) return@factory null
|
||||||
|
|
||||||
|
val parameterType =
|
||||||
|
candidate.valueParameters.single().returnTypeRef.toConeKotlinTypeProbablyFlexible(session, typeParameterStack)
|
||||||
|
|
||||||
|
candidateSymbol.takeIf {
|
||||||
|
AbstractTypeChecker.equalTypes(session.typeContext, parameterType, propertyType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirPropertySymbol.getBuiltinSpecialPropertyGetterName(): Name? {
|
||||||
|
var result: Name? = null
|
||||||
|
|
||||||
|
superTypesScope.processOverriddenPropertiesAndSelf(this) { overridden ->
|
||||||
|
val fqName = overridden.fir.containingClass()?.classId?.asSingleFqName()?.child(overridden.fir.name)
|
||||||
|
|
||||||
|
BuiltinSpecialProperties.PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP[fqName]?.let { name ->
|
||||||
|
result = name
|
||||||
|
return@processOverriddenPropertiesAndSelf ProcessorAction.STOP
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessorAction.NEXT
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
||||||
val potentialPropertyNames = session.syntheticNamesProvider.possiblePropertyNamesByAccessorName(name)
|
val potentialPropertyNames = getPropertyNamesCandidatesByAccessorName(name)
|
||||||
val accessors = mutableListOf<FirAccessorSymbol>()
|
|
||||||
val getterName by lazy { session.syntheticNamesProvider.getterNameBySetterName(name) ?: name }
|
val renamedSpecialBuiltInNames = SpecialGenericSignatures.getBuiltinFunctionNamesByJvmName(name)
|
||||||
for (potentialPropertyName in potentialPropertyNames) {
|
|
||||||
processAccessorFunctionsAndPropertiesByName(potentialPropertyName, listOf(getterName)) {
|
if (potentialPropertyNames.isEmpty() && renamedSpecialBuiltInNames.isEmpty() &&
|
||||||
if (it is FirAccessorSymbol) {
|
!name.sameAsBuiltinMethodWithErasedValueParameters
|
||||||
accessors += it
|
) {
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (accessors.isEmpty()) {
|
|
||||||
return super.processFunctionsByName(name, processor)
|
return super.processFunctionsByName(name, processor)
|
||||||
}
|
}
|
||||||
super.processFunctionsByName(name) { functionSymbol ->
|
|
||||||
if (accessors.none { accessorSymbol ->
|
val overriddenProperties = potentialPropertyNames.flatMap(this::getProperties).filterIsInstance<FirPropertySymbol>()
|
||||||
val syntheticProperty = accessorSymbol.fir as FirSyntheticProperty
|
|
||||||
syntheticProperty.getter.delegate === functionSymbol.fir ||
|
specialFunctions.getOrPut(name) {
|
||||||
syntheticProperty.setter?.delegate === functionSymbol.fir
|
doProcessSpecialFunctions(name, overriddenProperties, renamedSpecialBuiltInNames)
|
||||||
}
|
}.forEach {
|
||||||
|
processor(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doProcessSpecialFunctions(
|
||||||
|
name: Name,
|
||||||
|
overriddenProperties: List<FirPropertySymbol>,
|
||||||
|
renamedSpecialBuiltInNames: List<Name>
|
||||||
|
): List<FirNamedFunctionSymbol> {
|
||||||
|
val result = mutableListOf<FirNamedFunctionSymbol>()
|
||||||
|
|
||||||
|
declaredMemberScope.processFunctionsByName(name) { functionSymbol ->
|
||||||
|
if (functionSymbol.isStatic) return@processFunctionsByName
|
||||||
|
if (overriddenProperties.none { it.isOverriddenInClassBy(functionSymbol) } &&
|
||||||
|
!functionSymbol.doesOverrideRenamedBuiltins(renamedSpecialBuiltInNames) &&
|
||||||
|
!functionSymbol.shouldBeVisibleAsOverrideOfBuiltInWithErasedValueParameters()
|
||||||
) {
|
) {
|
||||||
processor(functionSymbol)
|
result += functionSymbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addOverriddenSpecialMethods(name, result, declaredMemberScope)
|
||||||
|
|
||||||
|
val overrideCandidates = result.toMutableSet()
|
||||||
|
|
||||||
|
superTypesScope.processFunctionsByName(name) {
|
||||||
|
val overriddenBy = it.getOverridden(overrideCandidates)
|
||||||
|
if (overriddenBy == null) {
|
||||||
|
result += it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirPropertySymbol.isOverriddenInClassBy(functionSymbol: FirNamedFunctionSymbol): Boolean {
|
||||||
|
val fir = fir as? FirSyntheticProperty ?: return false
|
||||||
|
|
||||||
|
return fir.getter.delegate.symbol == functionSymbol || fir.setter?.delegate?.symbol == functionSymbol
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addOverriddenSpecialMethods(
|
||||||
|
name: Name,
|
||||||
|
result: MutableList<FirNamedFunctionSymbol>,
|
||||||
|
scope: FirScope,
|
||||||
|
) {
|
||||||
|
superTypesScope.processFunctionsByName(name) { fromSupertype ->
|
||||||
|
obtainOverrideForBuiltinWithDifferentJvmName(fromSupertype, scope, name)?.let {
|
||||||
|
directOverriddenFunctions[it] = listOf(fromSupertype)
|
||||||
|
overrideByBase[fromSupertype] = it
|
||||||
|
result += it
|
||||||
|
}
|
||||||
|
|
||||||
|
obtainOverrideForBuiltInWithErasedValueParametersInJava(fromSupertype, scope)?.let {
|
||||||
|
directOverriddenFunctions[it] = listOf(fromSupertype)
|
||||||
|
overrideByBase[fromSupertype] = it
|
||||||
|
result += it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun obtainOverrideForBuiltinWithDifferentJvmName(
|
||||||
|
symbol: FirNamedFunctionSymbol,
|
||||||
|
scope: FirScope,
|
||||||
|
name: Name,
|
||||||
|
): FirNamedFunctionSymbol? {
|
||||||
|
val overriddenBuiltin = symbol.getOverriddenBuiltinWithDifferentJvmName() ?: return null
|
||||||
|
|
||||||
|
val nameInJava =
|
||||||
|
SpecialGenericSignatures.SIGNATURE_TO_JVM_REPRESENTATION_NAME[overriddenBuiltin.fir.computeJvmSignature() ?: return null]
|
||||||
|
?: return null
|
||||||
|
|
||||||
|
for (candidateSymbol in scope.getFunctions(nameInJava)) {
|
||||||
|
val candidateFir = candidateSymbol.fir
|
||||||
|
val renamedCopy = buildJavaMethodCopy(candidateFir) {
|
||||||
|
this.name = name
|
||||||
|
this.symbol = FirNamedFunctionSymbol(CallableId(candidateFir.symbol.callableId.classId!!, name))
|
||||||
|
}.apply {
|
||||||
|
initialSignatureAttr = candidateFir
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overrideChecker.isOverriddenFunction(renamedCopy, overriddenBuiltin.fir)) {
|
||||||
|
return renamedCopy.symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun obtainOverrideForBuiltInWithErasedValueParametersInJava(
|
||||||
|
symbol: FirNamedFunctionSymbol,
|
||||||
|
scope: FirScope,
|
||||||
|
): FirNamedFunctionSymbol? {
|
||||||
|
val overriddenBuiltin =
|
||||||
|
symbol.getOverriddenBuiltinFunctionWithErasedValueParametersInJava()
|
||||||
|
?: return null
|
||||||
|
|
||||||
|
return createOverrideForBuiltinFunctionWithErasedParameterIfNeeded(symbol, overriddenBuiltin, scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createOverrideForBuiltinFunctionWithErasedParameterIfNeeded(
|
||||||
|
fromSupertype: FirNamedFunctionSymbol,
|
||||||
|
overriddenBuiltin: FirNamedFunctionSymbol,
|
||||||
|
scope: FirScope,
|
||||||
|
): FirNamedFunctionSymbol? {
|
||||||
|
return scope.getFunctions(overriddenBuiltin.fir.name).firstOrNull { candidateOverride ->
|
||||||
|
candidateOverride.fir.computeJvmDescriptor() == overriddenBuiltin.fir.computeJvmDescriptor() &&
|
||||||
|
candidateOverride.hasErasedParameters()
|
||||||
|
}?.let { override ->
|
||||||
|
buildJavaMethodCopy(override.fir) {
|
||||||
|
this.valueParameters.clear()
|
||||||
|
override.fir.valueParameters.zip(fromSupertype.fir.valueParameters)
|
||||||
|
.mapTo(this.valueParameters) { (overrideParameter, parameterFromSupertype) ->
|
||||||
|
buildJavaValueParameterCopy(overrideParameter) {
|
||||||
|
this@buildJavaValueParameterCopy.returnTypeRef = parameterFromSupertype.returnTypeRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
symbol = FirNamedFunctionSymbol(override.callableId)
|
||||||
|
}.apply {
|
||||||
|
initialSignatureAttr = override.fir
|
||||||
|
}.symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's either overrides Collection.contains(Object) or Collection.containsAll(Collection<?>) or similar methods
|
||||||
|
private fun FirNamedFunctionSymbol.hasErasedParameters(): Boolean {
|
||||||
|
val valueParameter = fir.valueParameters.first()
|
||||||
|
val parameterType = valueParameter.returnTypeRef.toConeKotlinTypeProbablyFlexible(session, typeParameterStack)
|
||||||
|
val upperBound = parameterType.upperBoundIfFlexible()
|
||||||
|
if (upperBound !is ConeClassLikeType) return false
|
||||||
|
|
||||||
|
if (fir.name.asString() in ERASED_COLLECTION_PARAMETER_NAMES) {
|
||||||
|
require(upperBound.lookupTag.classId == StandardClassIds.Collection) {
|
||||||
|
"Unexpected type: ${upperBound.lookupTag.classId}"
|
||||||
|
}
|
||||||
|
|
||||||
|
return upperBound.typeArguments.singleOrNull() is ConeStarProjection
|
||||||
|
}
|
||||||
|
|
||||||
|
return upperBound.classId == StandardClassIds.Any
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirNamedFunctionSymbol.doesOverrideRenamedBuiltins(renamedSpecialBuiltInNames: List<Name>): Boolean {
|
||||||
|
return renamedSpecialBuiltInNames.any {
|
||||||
|
// e.g. 'removeAt' or 'toInt'
|
||||||
|
builtinName ->
|
||||||
|
val builtinSpecialFromSuperTypes =
|
||||||
|
getFunctionsFromSupertypes(builtinName).filter { it.getOverriddenBuiltinWithDifferentJvmName() != null }
|
||||||
|
if (builtinSpecialFromSuperTypes.isEmpty()) return@any false
|
||||||
|
|
||||||
|
val currentJvmDescriptor = fir.computeJvmDescriptor(customName = builtinName.asString())
|
||||||
|
|
||||||
|
builtinSpecialFromSuperTypes.any { builtinSpecial ->
|
||||||
|
builtinSpecial.fir.computeJvmDescriptor() == currentJvmDescriptor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirFunction<*>.computeJvmSignature(): String? {
|
||||||
|
return computeJvmSignature { it.toConeKotlinTypeProbablyFlexible(session, typeParameterStack) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirFunction<*>.computeJvmDescriptor(customName: String? = null, includeReturnType: Boolean = false): String {
|
||||||
|
return computeJvmDescriptor(customName, includeReturnType) {
|
||||||
|
it.toConeKotlinTypeProbablyFlexible(
|
||||||
|
session,
|
||||||
|
typeParameterStack
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getFunctionsFromSupertypes(name: Name): List<FirNamedFunctionSymbol> {
|
||||||
|
val result = mutableListOf<FirNamedFunctionSymbol>()
|
||||||
|
superTypesScope.processFunctionsByName(name) {
|
||||||
|
result += it
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirNamedFunctionSymbol.getOverriddenBuiltinWithDifferentJvmName(): FirNamedFunctionSymbol? {
|
||||||
|
var result: FirNamedFunctionSymbol? = null
|
||||||
|
|
||||||
|
superTypesScope.processOverriddenFunctions(this) {
|
||||||
|
if (!it.isFromBuiltInClass(session)) return@processOverriddenFunctions ProcessorAction.NEXT
|
||||||
|
if (SpecialGenericSignatures.SIGNATURE_TO_JVM_REPRESENTATION_NAME.containsKey(
|
||||||
|
it.fir.computeJvmSignature()
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
result = it
|
||||||
|
return@processOverriddenFunctions ProcessorAction.STOP
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessorAction.NEXT
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirNamedFunctionSymbol.shouldBeVisibleAsOverrideOfBuiltInWithErasedValueParameters(): Boolean {
|
||||||
|
val name = fir.name
|
||||||
|
if (!name.sameAsBuiltinMethodWithErasedValueParameters) return false
|
||||||
|
val candidatesToOverride =
|
||||||
|
getFunctionsFromSupertypes(name).mapNotNull {
|
||||||
|
it.getOverriddenBuiltinFunctionWithErasedValueParametersInJava()
|
||||||
|
}
|
||||||
|
|
||||||
|
val jvmDescriptor = fir.computeJvmDescriptor()
|
||||||
|
|
||||||
|
return candidatesToOverride.any { candidate ->
|
||||||
|
candidate.fir.computeJvmDescriptor() == jvmDescriptor && this.hasErasedParameters()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirNamedFunctionSymbol.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(): FirNamedFunctionSymbol? {
|
||||||
|
var result: FirNamedFunctionSymbol? = null
|
||||||
|
|
||||||
|
superTypesScope.processOverriddenFunctionsAndSelf(this) {
|
||||||
|
if (it.fir.computeJvmSignature() in SpecialGenericSignatures.ERASED_VALUE_PARAMETERS_SIGNATURES) {
|
||||||
|
result = it
|
||||||
|
return@processOverriddenFunctionsAndSelf ProcessorAction.STOP
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessorAction.NEXT
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirCallableSymbol<*>.isFromBuiltInClass(session: FirSession) =
|
||||||
|
dispatchReceiverClassOrNull()?.toSymbol(session)?.fir?.origin == FirDeclarationOrigin.BuiltIns
|
||||||
|
|||||||
@@ -15,11 +15,9 @@ import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
|||||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractOverrideChecker
|
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractOverrideChecker
|
||||||
import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptor
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||||
import org.jetbrains.kotlin.fir.typeContext
|
import org.jetbrains.kotlin.fir.typeContext
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures
|
|
||||||
|
|
||||||
class JavaOverrideChecker internal constructor(
|
class JavaOverrideChecker internal constructor(
|
||||||
private val session: FirSession,
|
private val session: FirSession,
|
||||||
@@ -30,11 +28,10 @@ class JavaOverrideChecker internal constructor(
|
|||||||
private fun isEqualTypes(
|
private fun isEqualTypes(
|
||||||
candidateType: ConeKotlinType,
|
candidateType: ConeKotlinType,
|
||||||
baseType: ConeKotlinType,
|
baseType: ConeKotlinType,
|
||||||
substitutor: ConeSubstitutor,
|
substitutor: ConeSubstitutor
|
||||||
mayBeSpecialBuiltIn: Boolean
|
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (candidateType is ConeFlexibleType) return isEqualTypes(candidateType.lowerBound, baseType, substitutor, mayBeSpecialBuiltIn)
|
if (candidateType is ConeFlexibleType) return isEqualTypes(candidateType.lowerBound, baseType, substitutor)
|
||||||
if (baseType is ConeFlexibleType) return isEqualTypes(candidateType, baseType.lowerBound, substitutor, mayBeSpecialBuiltIn)
|
if (baseType is ConeFlexibleType) return isEqualTypes(candidateType, baseType.lowerBound, substitutor)
|
||||||
if (candidateType is ConeClassLikeType && baseType is ConeClassLikeType) {
|
if (candidateType is ConeClassLikeType && baseType is ConeClassLikeType) {
|
||||||
val candidateTypeClassId = candidateType.fullyExpandedType(session).lookupTag.classId.let { it.readOnlyToMutable() ?: it }
|
val candidateTypeClassId = candidateType.fullyExpandedType(session).lookupTag.classId.let { it.readOnlyToMutable() ?: it }
|
||||||
val baseTypeClassId = baseType.fullyExpandedType(session).lookupTag.classId.let { it.readOnlyToMutable() ?: it }
|
val baseTypeClassId = baseType.fullyExpandedType(session).lookupTag.classId.let { it.readOnlyToMutable() ?: it }
|
||||||
@@ -49,22 +46,11 @@ class JavaOverrideChecker internal constructor(
|
|||||||
return isEqualArrayElementTypeProjections(
|
return isEqualArrayElementTypeProjections(
|
||||||
candidateType.typeArguments.single(),
|
candidateType.typeArguments.single(),
|
||||||
baseType.typeArguments.single(),
|
baseType.typeArguments.single(),
|
||||||
substitutor,
|
substitutor
|
||||||
mayBeSpecialBuiltIn
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// TODO: handle the situation in more proper way
|
|
||||||
// Typical case: class EnumMap<K extends Enum, V> implements Map<K, V>
|
|
||||||
// We have containsKey(Object) in Map which is enhanced to containsKey(K) in supertype scope
|
|
||||||
// In EnumMap we have overridden containsKey(Object) which is not yet enhanced
|
|
||||||
// K may be substituted but after that we will get containsKey(Enum) from supertype, which still does not match...
|
|
||||||
if (mayBeSpecialBuiltIn && baseType is ConeTypeParameterType &&
|
|
||||||
candidateType is ConeClassLikeType && candidateType.classId == StandardClassIds.Any
|
|
||||||
) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return with(context) {
|
return with(context) {
|
||||||
areEqualTypeConstructors(
|
areEqualTypeConstructors(
|
||||||
substitutor.substituteOrSelf(candidateType).typeConstructor(),
|
substitutor.substituteOrSelf(candidateType).typeConstructor(),
|
||||||
@@ -76,25 +62,22 @@ class JavaOverrideChecker internal constructor(
|
|||||||
private fun isEqualTypes(
|
private fun isEqualTypes(
|
||||||
candidateTypeRef: FirTypeRef,
|
candidateTypeRef: FirTypeRef,
|
||||||
baseTypeRef: FirTypeRef,
|
baseTypeRef: FirTypeRef,
|
||||||
substitutor: ConeSubstitutor,
|
substitutor: ConeSubstitutor
|
||||||
mayBeSpecialBuiltIn: Boolean = false
|
|
||||||
) = isEqualTypes(
|
) = isEqualTypes(
|
||||||
candidateTypeRef.toConeKotlinTypeProbablyFlexible(session, javaTypeParameterStack),
|
candidateTypeRef.toConeKotlinTypeProbablyFlexible(session, javaTypeParameterStack),
|
||||||
baseTypeRef.toConeKotlinTypeProbablyFlexible(session, javaTypeParameterStack),
|
baseTypeRef.toConeKotlinTypeProbablyFlexible(session, javaTypeParameterStack),
|
||||||
substitutor,
|
substitutor
|
||||||
mayBeSpecialBuiltIn
|
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun isEqualArrayElementTypeProjections(
|
private fun isEqualArrayElementTypeProjections(
|
||||||
candidateTypeProjection: ConeTypeProjection,
|
candidateTypeProjection: ConeTypeProjection,
|
||||||
baseTypeProjection: ConeTypeProjection,
|
baseTypeProjection: ConeTypeProjection,
|
||||||
substitutor: ConeSubstitutor,
|
substitutor: ConeSubstitutor
|
||||||
mayBeSpecialBuiltIn: Boolean
|
|
||||||
): Boolean =
|
): Boolean =
|
||||||
when {
|
when {
|
||||||
candidateTypeProjection is ConeKotlinTypeProjection && baseTypeProjection is ConeKotlinTypeProjection ->
|
candidateTypeProjection is ConeKotlinTypeProjection && baseTypeProjection is ConeKotlinTypeProjection ->
|
||||||
candidateTypeProjection.kind == baseTypeProjection.kind &&
|
candidateTypeProjection.kind == baseTypeProjection.kind &&
|
||||||
isEqualTypes(candidateTypeProjection.type, baseTypeProjection.type, substitutor, mayBeSpecialBuiltIn)
|
isEqualTypes(candidateTypeProjection.type, baseTypeProjection.type, substitutor)
|
||||||
candidateTypeProjection is ConeStarProjection && baseTypeProjection is ConeStarProjection -> true
|
candidateTypeProjection is ConeStarProjection && baseTypeProjection is ConeStarProjection -> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
@@ -169,13 +152,8 @@ class JavaOverrideChecker internal constructor(
|
|||||||
|
|
||||||
if (overrideCandidate.valueParameters.size != baseParameterTypes.size) return false
|
if (overrideCandidate.valueParameters.size != baseParameterTypes.size) return false
|
||||||
val substitutor = buildTypeParametersSubstitutorIfCompatible(overrideCandidate, baseDeclaration) ?: return false
|
val substitutor = buildTypeParametersSubstitutorIfCompatible(overrideCandidate, baseDeclaration) ?: return false
|
||||||
|
|
||||||
val jvmDescriptor by lazy { baseDeclaration.computeJvmDescriptor() }
|
|
||||||
val mayBeSpecialBuiltIn =
|
|
||||||
baseDeclaration.name in SpecialGenericSignatures.ERASED_VALUE_PARAMETERS_SHORT_NAMES &&
|
|
||||||
SpecialGenericSignatures.ERASED_VALUE_PARAMETERS_SIGNATURES.any { it.endsWith(jvmDescriptor) }
|
|
||||||
return overrideCandidate.valueParameters.zip(baseParameterTypes).all { (paramFromJava, baseType) ->
|
return overrideCandidate.valueParameters.zip(baseParameterTypes).all { (paramFromJava, baseType) ->
|
||||||
isEqualTypes(paramFromJava.returnTypeRef, baseType, substitutor, mayBeSpecialBuiltIn)
|
isEqualTypes(paramFromJava.returnTypeRef, baseType, substitutor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.scopes.jvm
|
package org.jetbrains.kotlin.fir.scopes.jvm
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||||
|
import org.jetbrains.kotlin.fir.containingClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||||
@@ -12,68 +15,44 @@ import org.jetbrains.kotlin.fir.types.*
|
|||||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitAnyTypeRef
|
import org.jetbrains.kotlin.fir.types.impl.FirImplicitAnyTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitNullableAnyTypeRef
|
import org.jetbrains.kotlin.fir.types.impl.FirImplicitNullableAnyTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
|
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaClassifierType
|
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaPrimitiveType
|
import org.jetbrains.kotlin.load.java.structure.JavaPrimitiveType
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
|
import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
fun FirFunction<*>.computeJvmDescriptorReplacingKotlinToJava(): String =
|
fun FirFunction<*>.computeJvmSignature(typeConversion: (FirTypeRef) -> ConeKotlinType? = FirTypeRef::coneTypeSafe): String? {
|
||||||
computeJvmDescriptor()
|
if (this !is FirCallableMemberDeclaration<*>) return null
|
||||||
.replace("kotlin/Any", "java/lang/Object")
|
val containingClass = containingClass() ?: return null
|
||||||
.replace("kotlin/String", "java/lang/String")
|
|
||||||
.replace("kotlin/Throwable", "java/lang/Throwable")
|
|
||||||
|
|
||||||
fun FirFunction<*>.computeJvmDescriptor(): String = buildString {
|
return SignatureBuildingComponents.signature(containingClass.classId, computeJvmDescriptor(typeConversion = typeConversion))
|
||||||
if (this@computeJvmDescriptor is FirSimpleFunction) {
|
}
|
||||||
append(name.asString())
|
|
||||||
|
fun FirFunction<*>.computeJvmDescriptor(
|
||||||
|
customName: String? = null,
|
||||||
|
includeReturnType: Boolean = true,
|
||||||
|
typeConversion: (FirTypeRef) -> ConeKotlinType? = FirTypeRef::coneTypeSafe
|
||||||
|
): String = buildString {
|
||||||
|
if (customName != null) {
|
||||||
|
append(customName)
|
||||||
} else {
|
} else {
|
||||||
append("<init>")
|
if (this@computeJvmDescriptor is FirSimpleFunction) {
|
||||||
|
append(name.asString())
|
||||||
|
} else {
|
||||||
|
append("<init>")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
append("(")
|
append("(")
|
||||||
for (parameter in valueParameters) {
|
for (parameter in valueParameters) {
|
||||||
appendErasedType(parameter.returnTypeRef)
|
typeConversion(parameter.returnTypeRef)?.let(this::appendConeType)
|
||||||
}
|
}
|
||||||
append(")")
|
append(")")
|
||||||
|
|
||||||
if (this@computeJvmDescriptor !is FirSimpleFunction || returnTypeRef.isVoid()) {
|
if (includeReturnType) {
|
||||||
append("V")
|
if (this@computeJvmDescriptor !is FirSimpleFunction || returnTypeRef.isVoid()) {
|
||||||
} else {
|
append("V")
|
||||||
appendErasedType(returnTypeRef)
|
} else {
|
||||||
}
|
typeConversion(returnTypeRef)?.let(this::appendConeType)
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: primitive types, arrays, etc.
|
|
||||||
private fun StringBuilder.appendErasedType(typeRef: FirTypeRef) {
|
|
||||||
fun appendClass(klass: JavaClass) {
|
|
||||||
klass.fqName?.let {
|
|
||||||
append("L")
|
|
||||||
append(it.asString().replace(".", "/"))
|
|
||||||
append(";")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
when (typeRef) {
|
|
||||||
is FirResolvedTypeRef -> appendConeType(typeRef.type)
|
|
||||||
is FirJavaTypeRef -> {
|
|
||||||
when (val javaType = typeRef.type) {
|
|
||||||
is JavaClassifierType -> {
|
|
||||||
when (val classifier = javaType.classifier) {
|
|
||||||
is JavaClass -> appendClass(classifier)
|
|
||||||
is JavaTypeParameter -> {
|
|
||||||
val representative = classifier.upperBounds.firstOrNull { it.classifier is JavaClass }
|
|
||||||
if (representative == null) {
|
|
||||||
append("Ljava/lang/Object;")
|
|
||||||
} else {
|
|
||||||
appendClass(representative.classifier as JavaClass)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,7 +80,8 @@ private fun StringBuilder.appendConeType(coneType: ConeKotlinType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun appendClassLikeType(type: ConeClassLikeType) {
|
fun appendClassLikeType(type: ConeClassLikeType) {
|
||||||
val classId = type.lookupTag.classId
|
val baseClassId = type.lookupTag.classId
|
||||||
|
val classId = JavaToKotlinClassMap.mapKotlinToJava(baseClassId.asSingleFqName().toUnsafe()) ?: baseClassId
|
||||||
if (classId == StandardClassIds.Array) {
|
if (classId == StandardClassIds.Array) {
|
||||||
append("[")
|
append("[")
|
||||||
type.typeArguments.forEach { typeArg ->
|
type.typeArguments.forEach { typeArg ->
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ class JvmMappedScope(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val declaredSignatures by lazy {
|
val declaredSignatures by lazy {
|
||||||
declared.mapTo(mutableSetOf()) { it.fir.computeJvmDescriptorReplacingKotlinToJava() }
|
declared.mapTo(mutableSetOf()) { it.fir.computeJvmDescriptor() }
|
||||||
}
|
}
|
||||||
|
|
||||||
javaMappedClassUseSiteScope.processFunctionsByName(name) { symbol ->
|
javaMappedClassUseSiteScope.processFunctionsByName(name) { symbol ->
|
||||||
val jvmSignature = symbol.fir.computeJvmDescriptorReplacingKotlinToJava()
|
val jvmSignature = symbol.fir.computeJvmDescriptor()
|
||||||
if (jvmSignature in visibleMethods && jvmSignature !in declaredSignatures) {
|
if (jvmSignature in visibleMethods && jvmSignature !in declaredSignatures) {
|
||||||
processor(symbol)
|
processor(symbol)
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,7 @@ class JvmMappedScope(
|
|||||||
val hiddenConstructors = signatures.hiddenConstructors
|
val hiddenConstructors = signatures.hiddenConstructors
|
||||||
if (hiddenConstructors.isNotEmpty()) {
|
if (hiddenConstructors.isNotEmpty()) {
|
||||||
javaMappedClassUseSiteScope.processDeclaredConstructors { symbol ->
|
javaMappedClassUseSiteScope.processDeclaredConstructors { symbol ->
|
||||||
val jvmSignature = symbol.fir.computeJvmDescriptorReplacingKotlinToJava()
|
val jvmSignature = symbol.fir.computeJvmDescriptor()
|
||||||
if (jvmSignature !in hiddenConstructors) {
|
if (jvmSignature !in hiddenConstructors) {
|
||||||
processor(symbol)
|
processor(symbol)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ abstract class AbstractFirUseSiteMemberScope(
|
|||||||
) : AbstractFirOverrideScope(session, overrideChecker) {
|
) : AbstractFirOverrideScope(session, overrideChecker) {
|
||||||
|
|
||||||
private val functions = hashMapOf<Name, Collection<FirNamedFunctionSymbol>>()
|
private val functions = hashMapOf<Name, Collection<FirNamedFunctionSymbol>>()
|
||||||
private val directOverriddenFunctions = hashMapOf<FirNamedFunctionSymbol, Collection<FirNamedFunctionSymbol>>()
|
protected val directOverriddenFunctions = hashMapOf<FirNamedFunctionSymbol, Collection<FirNamedFunctionSymbol>>()
|
||||||
protected val directOverriddenProperties = hashMapOf<FirPropertySymbol, MutableList<FirPropertySymbol>>()
|
protected val directOverriddenProperties = hashMapOf<FirPropertySymbol, MutableList<FirPropertySymbol>>()
|
||||||
|
|
||||||
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
||||||
|
|||||||
@@ -61,6 +61,15 @@ fun FirTypeScope.processOverriddenFunctionsAndSelf(
|
|||||||
return processOverriddenFunctions(functionSymbol, processor)
|
return processOverriddenFunctions(functionSymbol, processor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun FirTypeScope.processOverriddenPropertiesAndSelf(
|
||||||
|
propertySymbol: FirPropertySymbol,
|
||||||
|
processor: (FirPropertySymbol) -> ProcessorAction
|
||||||
|
): ProcessorAction {
|
||||||
|
if (!processor(propertySymbol)) return ProcessorAction.STOP
|
||||||
|
|
||||||
|
return processOverriddenProperties(propertySymbol, processor)
|
||||||
|
}
|
||||||
|
|
||||||
enum class ProcessorAction {
|
enum class ProcessorAction {
|
||||||
STOP,
|
STOP,
|
||||||
NEXT,
|
NEXT,
|
||||||
|
|||||||
+85
@@ -0,0 +1,85 @@
|
|||||||
|
// FILE: CollectionStringImpl.java
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
public class CollectionStringImpl implements Collection<String> {
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<String> iterator() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] toArray() {
|
||||||
|
return new Object[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T[] toArray(T[] a) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(String s) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsAll(Collection<?> c) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(Collection<? extends String> c) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeAll(Collection<?> c) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean retainAll(Collection<?> c) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(String o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
fun test(x: CollectionStringImpl) {
|
||||||
|
x.<!AMBIGUITY!>contains<!>("")
|
||||||
|
(x as Collection<String>).contains("")
|
||||||
|
}
|
||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// FILE: CollectionStringImpl.java
|
// FILE: CollectionStringImpl.java
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|||||||
+6
-6
@@ -40,14 +40,14 @@ fun foo(
|
|||||||
1 <!INAPPLICABLE_CANDIDATE!>in<!> a
|
1 <!INAPPLICABLE_CANDIDATE!>in<!> a
|
||||||
|
|
||||||
b.contains("")
|
b.contains("")
|
||||||
b.contains(1)
|
b.<!INAPPLICABLE_CANDIDATE!>contains<!>(1)
|
||||||
"" in b
|
"" in b
|
||||||
1 in b
|
1 <!INAPPLICABLE_CANDIDATE!>in<!> b
|
||||||
|
|
||||||
ic.contains("")
|
ic.contains("")
|
||||||
ic.contains(1)
|
ic.<!INAPPLICABLE_CANDIDATE!>contains<!>(1)
|
||||||
"" in ic
|
"" in ic
|
||||||
1 in ic
|
1 <!INAPPLICABLE_CANDIDATE!>in<!> ic
|
||||||
|
|
||||||
ka.contains("")
|
ka.contains("")
|
||||||
ka.<!INAPPLICABLE_CANDIDATE!>contains<!>(1)
|
ka.<!INAPPLICABLE_CANDIDATE!>contains<!>(1)
|
||||||
@@ -55,9 +55,9 @@ fun foo(
|
|||||||
1 <!INAPPLICABLE_CANDIDATE!>in<!> ka
|
1 <!INAPPLICABLE_CANDIDATE!>in<!> ka
|
||||||
|
|
||||||
kb.contains("")
|
kb.contains("")
|
||||||
kb.contains(1)
|
kb.<!INAPPLICABLE_CANDIDATE!>contains<!>(1)
|
||||||
"" in kb
|
"" in kb
|
||||||
1 in kb
|
1 <!INAPPLICABLE_CANDIDATE!>in<!> kb
|
||||||
|
|
||||||
al.contains("")
|
al.contains("")
|
||||||
al.<!INAPPLICABLE_CANDIDATE!>contains<!>(1)
|
al.<!INAPPLICABLE_CANDIDATE!>contains<!>(1)
|
||||||
|
|||||||
+3
-3
@@ -40,16 +40,16 @@ fun foo(
|
|||||||
a.<!INAPPLICABLE_CANDIDATE!>containsAll<!>(ca)
|
a.<!INAPPLICABLE_CANDIDATE!>containsAll<!>(ca)
|
||||||
|
|
||||||
b.containsAll(cs)
|
b.containsAll(cs)
|
||||||
b.containsAll(ca)
|
b.<!INAPPLICABLE_CANDIDATE!>containsAll<!>(ca)
|
||||||
|
|
||||||
ic.containsAll(cs)
|
ic.containsAll(cs)
|
||||||
ic.containsAll(ca)
|
ic.<!INAPPLICABLE_CANDIDATE!>containsAll<!>(ca)
|
||||||
|
|
||||||
ka.containsAll(cs)
|
ka.containsAll(cs)
|
||||||
ka.<!INAPPLICABLE_CANDIDATE!>containsAll<!>(ca)
|
ka.<!INAPPLICABLE_CANDIDATE!>containsAll<!>(ca)
|
||||||
|
|
||||||
kb.containsAll(cs)
|
kb.containsAll(cs)
|
||||||
kb.containsAll(ca)
|
kb.<!INAPPLICABLE_CANDIDATE!>containsAll<!>(ca)
|
||||||
|
|
||||||
al.containsAll(cs)
|
al.containsAll(cs)
|
||||||
al.<!INAPPLICABLE_CANDIDATE!>containsAll<!>(ca)
|
al.<!INAPPLICABLE_CANDIDATE!>containsAll<!>(ca)
|
||||||
|
|||||||
+6
-6
@@ -12,13 +12,13 @@ abstract class KA : A() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun foo(a: A, ka: KA) {
|
fun foo(a: A, ka: KA) {
|
||||||
a.contains("")
|
a.<!AMBIGUITY!>contains<!>("")
|
||||||
a.contains(1)
|
a.<!NONE_APPLICABLE!>contains<!>(1)
|
||||||
"" in a
|
"" <!AMBIGUITY!>in<!> a
|
||||||
1 in a
|
1 <!NONE_APPLICABLE!>in<!> a
|
||||||
|
|
||||||
ka.contains("")
|
ka.contains("")
|
||||||
ka.contains(1)
|
ka.<!INAPPLICABLE_CANDIDATE!>contains<!>(1)
|
||||||
"" in ka
|
"" in ka
|
||||||
1 in ka
|
1 <!INAPPLICABLE_CANDIDATE!>in<!> ka
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+19
@@ -0,0 +1,19 @@
|
|||||||
|
// FILE: Dict.java
|
||||||
|
|
||||||
|
public abstract class Dict<K, V> {
|
||||||
|
abstract public V get(Object key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: MHashtable.java
|
||||||
|
|
||||||
|
abstract public class MHashtable<X, Y> extends Dict<X, Y> implements java.util.Map<X, Y> {
|
||||||
|
public V get(Object key) { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
abstract class C1 : MHashtable<String, Int>()
|
||||||
|
|
||||||
|
abstract class C2 : MHashtable<String, Int>() {
|
||||||
|
override fun <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>get<!>(key: String) = 1
|
||||||
|
}
|
||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// FILE: Dict.java
|
// FILE: Dict.java
|
||||||
|
|
||||||
public abstract class Dict<K, V> {
|
public abstract class Dict<K, V> {
|
||||||
|
|||||||
-32
@@ -1,32 +0,0 @@
|
|||||||
// JAVAC_EXPECTED_FILE
|
|
||||||
// FILE: A.java
|
|
||||||
abstract public class A extends B {
|
|
||||||
public Integer removeAt(int x) { }
|
|
||||||
public boolean remove(Integer x) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: main.kt
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
abstract class B : MutableList<Int>, AbstractList<Int>() {
|
|
||||||
override fun removeAt(index: Int): Int = null!!
|
|
||||||
override fun remove(element: Int): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Boolean<!> = null!!
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class D : AbstractList<Int>() {
|
|
||||||
// removeAt() doesn't exist in java/util/AbstractList, it's a
|
|
||||||
// fake override of the method from kotlin/collections/MutableList
|
|
||||||
override fun removeAt(index: Int): Int = null!!
|
|
||||||
// AbstractList::remove() should return Int here. No fake overrides created.
|
|
||||||
// This may be a bug because the old compiler doesn't report a diagnostic here.
|
|
||||||
override fun remove(element: Int): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Boolean<!> = null!!
|
|
||||||
}
|
|
||||||
|
|
||||||
fun main(a: A, b: B, c: ArrayList<Int>) {
|
|
||||||
a.remove(1)
|
|
||||||
a.removeAt(0)
|
|
||||||
b.remove(1)
|
|
||||||
b.removeAt(0)
|
|
||||||
c.remove(1)
|
|
||||||
c.removeAt(0)
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// JAVAC_EXPECTED_FILE
|
// JAVAC_EXPECTED_FILE
|
||||||
// FILE: A.java
|
// FILE: A.java
|
||||||
abstract public class A extends B {
|
abstract public class A extends B {
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
// JAVAC_EXPECTED_FILE
|
|
||||||
// FILE: A.java
|
|
||||||
|
|
||||||
abstract public class A extends java.util.ArrayList<String> {
|
|
||||||
public final int size() { return 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: main.kt
|
|
||||||
|
|
||||||
class B : A() {
|
|
||||||
override val size: Int = 1
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// JAVAC_EXPECTED_FILE
|
// JAVAC_EXPECTED_FILE
|
||||||
// FILE: A.java
|
// FILE: A.java
|
||||||
|
|
||||||
|
|||||||
+113
@@ -0,0 +1,113 @@
|
|||||||
|
// FILE: AbstractSpecializedMap.java
|
||||||
|
public abstract class AbstractSpecializedMap implements java.util.Map<Integer, Double> {
|
||||||
|
public abstract double put(int x, double y);
|
||||||
|
public abstract double remove(int k);
|
||||||
|
public abstract double get(int k);
|
||||||
|
|
||||||
|
public abstract boolean containsKey(int k);
|
||||||
|
public boolean containsKey(Object x) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract boolean containsValue(double v);
|
||||||
|
public boolean containsValue(Object x) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: SpecializedMap.java
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class SpecializedMap extends AbstractSpecializedMap {
|
||||||
|
public double put(int x, double y) {
|
||||||
|
return 123.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double get(Object key) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double put(Integer key, Double value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double remove(int k) {
|
||||||
|
return 456.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Double remove(Object ok) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public double get(int k) {
|
||||||
|
return 789.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsKey(int k) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsValue(double v) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putAll(Map<? extends Integer, ? extends Double> m) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Set<Integer> keySet() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Collection<Double> values() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Set<Entry<Integer, Double>> entrySet() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
fun foo(x: SpecializedMap) {
|
||||||
|
x.containsKey(1)
|
||||||
|
x.<!INAPPLICABLE_CANDIDATE!>containsKey<!>(null)
|
||||||
|
|
||||||
|
x.<!AMBIGUITY!>get<!>(2)
|
||||||
|
x.<!NONE_APPLICABLE!>get<!>(null)
|
||||||
|
|
||||||
|
x.<!AMBIGUITY!>remove<!>(3)
|
||||||
|
x.<!NONE_APPLICABLE!>remove<!>(null)
|
||||||
|
|
||||||
|
x.put(4, 5.0)
|
||||||
|
x.put(4, null)
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// FILE: AbstractSpecializedMap.java
|
// FILE: AbstractSpecializedMap.java
|
||||||
public abstract class AbstractSpecializedMap implements java.util.Map<Integer, Double> {
|
public abstract class AbstractSpecializedMap implements java.util.Map<Integer, Double> {
|
||||||
public abstract double put(int x, double y);
|
public abstract double put(int x, double y);
|
||||||
|
|||||||
-2
@@ -1,8 +1,6 @@
|
|||||||
public open class ModalityOfFakeOverrides : R|java/util/AbstractList<ft<@FlexibleNullability kotlin/String, kotlin/String?>!>| {
|
public open class ModalityOfFakeOverrides : R|java/util/AbstractList<ft<@FlexibleNullability kotlin/String, kotlin/String?>!>| {
|
||||||
@R|java/lang/Override|() @R|org/jetbrains/annotations/NotNull|() public open operator fun get(index: R|kotlin/Int|): R|@EnhancedNullability kotlin/String|
|
@R|java/lang/Override|() @R|org/jetbrains/annotations/NotNull|() public open operator fun get(index: R|kotlin/Int|): R|@EnhancedNullability kotlin/String|
|
||||||
|
|
||||||
@R|java/lang/Override|() public open fun size(): R|kotlin/Int|
|
|
||||||
|
|
||||||
public constructor(): R|test/ModalityOfFakeOverrides|
|
public constructor(): R|test/ModalityOfFakeOverrides|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,46 +52,25 @@ KtFirJavaFieldSymbol:
|
|||||||
symbolKind: MEMBER
|
symbolKind: MEMBER
|
||||||
visibility: PRIVATE
|
visibility: PRIVATE
|
||||||
|
|
||||||
KtFirFunctionSymbol:
|
KtFirSyntheticJavaPropertySymbol:
|
||||||
annotatedType: [] kotlin/Int
|
annotatedType: [] kotlin/Int
|
||||||
annotationClassIds: []
|
annotationClassIds: []
|
||||||
annotations: []
|
annotations: []
|
||||||
callableIdIfNonLocal: java.lang.String.length
|
callableIdIfNonLocal: java.lang.String.length
|
||||||
dispatchType: java/lang/String
|
dispatchType: java/lang/String
|
||||||
isExtension: false
|
|
||||||
isExternal: false
|
|
||||||
isInline: false
|
|
||||||
isOperator: false
|
|
||||||
isOverride: false
|
|
||||||
isSuspend: false
|
|
||||||
modality: OPEN
|
|
||||||
name: length
|
|
||||||
origin: JAVA
|
|
||||||
receiverType: null
|
|
||||||
symbolKind: MEMBER
|
|
||||||
typeParameters: []
|
|
||||||
valueParameters: []
|
|
||||||
visibility: PUBLIC
|
|
||||||
|
|
||||||
KtFirKotlinPropertySymbol:
|
|
||||||
annotatedType: [] kotlin/Int
|
|
||||||
annotationClassIds: []
|
|
||||||
annotations: []
|
|
||||||
callableIdIfNonLocal: kotlin.CharSequence.length
|
|
||||||
dispatchType: kotlin/CharSequence
|
|
||||||
getter: KtFirPropertyGetterSymbol(<getter>)
|
getter: KtFirPropertyGetterSymbol(<getter>)
|
||||||
hasBackingField: false
|
hasBackingField: true
|
||||||
hasGetter: true
|
hasGetter: true
|
||||||
hasSetter: false
|
hasSetter: false
|
||||||
initializer: null
|
initializer: null
|
||||||
isConst: false
|
|
||||||
isExtension: false
|
isExtension: false
|
||||||
isLateInit: false
|
|
||||||
isOverride: false
|
isOverride: false
|
||||||
isVal: true
|
isVal: true
|
||||||
modality: ABSTRACT
|
javaGetterName: length
|
||||||
|
javaSetterName: null
|
||||||
|
modality: OPEN
|
||||||
name: length
|
name: length
|
||||||
origin: LIBRARY
|
origin: JAVA_SYNTHETIC_PROPERTY
|
||||||
receiverType: null
|
receiverType: null
|
||||||
setter: null
|
setter: null
|
||||||
symbolKind: MEMBER
|
symbolKind: MEMBER
|
||||||
|
|||||||
Reference in New Issue
Block a user