Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.fir.java.scopes
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.isVisibleInClass
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunctionCopy
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod
import org.jetbrains.kotlin.fir.java.declarations.buildJavaMethodCopy
import org.jetbrains.kotlin.fir.java.declarations.buildJavaValueParameterCopy
import org.jetbrains.kotlin.fir.java.resolveIfJavaType
import org.jetbrains.kotlin.fir.java.symbols.FirJavaOverriddenSyntheticPropertySymbol
import org.jetbrains.kotlin.fir.java.syntheticPropertiesStorage
import org.jetbrains.kotlin.fir.java.toConeKotlinTypeProbablyFlexible
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.impl.AbstractFirUseSiteMemberScope
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScopeContext.ResultOfIntersection
import org.jetbrains.kotlin.fir.scopes.impl.MembersByScope
import org.jetbrains.kotlin.fir.scopes.impl.similarFunctionsOrBothProperties
import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptor
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
import org.jetbrains.kotlin.load.java.*
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.SpecialGenericSignatures.Companion.sameAsRenamedInJvmBuiltin
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.runIf
class JavaClassUseSiteMemberScope(
private val klass: FirJavaClass,
session: FirSession,
superTypeScopes: List,
declaredMemberScope: FirContainingNamesAwareScope
) : AbstractFirUseSiteMemberScope(
klass.symbol.toLookupTag(),
session,
JavaOverrideChecker(session, klass.javaTypeParameterStack, superTypeScopes, considerReturnTypeKinds = true),
superTypeScopes,
klass.defaultType(),
declaredMemberScope
) {
private val typeParameterStack = klass.javaTypeParameterStack
private val canUseSpecialGetters: Boolean by lazy { !klass.hasKotlinSuper(session) }
private val javaOverrideChecker: JavaOverrideChecker get() = overrideChecker as JavaOverrideChecker
private val syntheticPropertyCache = session.syntheticPropertiesStorage.cacheByOwner.getValue(klass, null)
private fun generateSyntheticPropertySymbol(
getterSymbol: FirNamedFunctionSymbol,
setterSymbol: FirNamedFunctionSymbol?,
property: FirProperty,
takeModalityFromGetter: Boolean,
): FirSyntheticPropertySymbol {
return buildSyntheticProperty {
moduleData = session.moduleData
name = property.name
symbol = FirJavaOverriddenSyntheticPropertySymbol(
getterId = getterSymbol.callableId,
propertyId = CallableId(getterSymbol.callableId.packageName, getterSymbol.callableId.className, property.name)
)
delegateGetter = getterSymbol.fir
delegateSetter = setterSymbol?.fir
status = getterSymbol.fir.status.copy(
modality = if (takeModalityFromGetter) {
delegateGetter.modality ?: property.modality
} else {
chooseModalityForAccessor(property, delegateGetter)
}
)
deprecationsProvider = getDeprecationsProviderFromAccessors(session, delegateGetter, delegateSetter)
}.symbol
}
private fun chooseModalityForAccessor(property: FirProperty, getter: FirSimpleFunction): Modality? {
val a = property.modality
val b = getter.modality
if (a == null) return b
if (b == null) return a
return minOf(a, b)
}
override fun collectProperties(name: Name): Collection> {
val fields = mutableSetOf>()
val fieldNames = mutableSetOf()
val result = mutableSetOf>()
// fields
declaredMemberScope.processPropertiesByName(name) processor@{ variableSymbol ->
if (variableSymbol.isStatic) return@processor
fields += variableSymbol
fieldNames += variableSymbol.fir.name
result += variableSymbol
}
/*
* From supertype we can get at most two results:
* 1. Set of properties with same name
* 2. Field from some java superclass (only one, if class have more than one superclass then we can choose
* just one field because this is incorrect code anyway)
*/
val fromSupertypes = supertypeScopeContext.collectIntersectionResultsForCallables(name, FirScope::processPropertiesByName)
val (fieldsFromSupertype, propertiesFromSupertypes) = fromSupertypes.partition {
it is ResultOfIntersection.SingleMember && it.chosenSymbol is FirFieldSymbol
}
assert(fieldsFromSupertype.size in 0..1)
assert(propertiesFromSupertypes.size in 0..1)
fieldsFromSupertype.firstOrNull()?.chosenSymbol?.let { fieldSymbol ->
require(fieldSymbol is FirFieldSymbol)
if (fieldSymbol.name !in fieldNames) {
result.addIfNotNull(fieldSymbol)
}
}
@Suppress("UNCHECKED_CAST")
val overriddenProperty = propertiesFromSupertypes.firstOrNull() as ResultOfIntersection? ?: return result
val overrideInClass = syntheticPropertyCache.getValue(name, this to overriddenProperty)
val chosenSymbol = overrideInClass ?: overriddenProperty.chosenSymbol
directOverriddenProperties[chosenSymbol] = listOf(overriddenProperty)
overriddenProperty.overriddenMembers.forEach { overrideByBase[it.member] = overrideInClass }
result += chosenSymbol
return result
}
internal fun syntheticPropertyFromOverride(overriddenProperty: ResultOfIntersection): FirSyntheticPropertySymbol? {
val overrideInClass = overriddenProperty.overriddenMembers.firstNotNullOfOrNull { (symbol, _) ->
// We may call this function at the STATUS phase, which means that using resolved status may lead to cycle
// So we need to use raw status here
if (!symbol.isVisibleInClass(klass.symbol, symbol.rawStatus)) return@firstNotNullOfOrNull null
symbol.createOverridePropertyIfExists(declaredMemberScope, takeModalityFromGetter = true)
?: superTypeScopes.firstNotNullOfOrNull { scope ->
symbol.createOverridePropertyIfExists(scope, takeModalityFromGetter = false)
}
}
return overrideInClass
}
private fun FirPropertySymbol.createOverridePropertyIfExists(
scope: FirScope,
takeModalityFromGetter: Boolean
): FirSyntheticPropertySymbol? {
val getterSymbol = this.findGetterOverride(scope) ?: return null
val setterSymbol =
if (this.fir.isVar)
this.findSetterOverride(scope) ?: return null
else
null
if (setterSymbol != null && setterSymbol.fir.modality != getterSymbol.fir.modality) return null
return generateSyntheticPropertySymbol(getterSymbol, setterSymbol, fir, takeModalityFromGetter)
}
private fun FirPropertySymbol.findGetterOverride(
scope: FirScope,
): FirNamedFunctionSymbol? {
val specialGetterName = if (canUseSpecialGetters) getBuiltinSpecialPropertyGetterName() else null
val name = specialGetterName?.asString() ?: JvmAbi.getterName(fir.name.asString())
return findGetterByName(name, scope)
}
private fun FirPropertySymbol.findGetterByName(
getterName: String,
scope: FirScope,
): FirNamedFunctionSymbol? {
val propertyFromSupertype = fir
val expectedReturnType = propertyFromSupertype.returnTypeRef.coneTypeSafe()
return scope.getFunctions(Name.identifier(getterName)).firstNotNullOfOrNull factory@{ candidateSymbol ->
val candidate = candidateSymbol.fir
if (candidate.valueParameters.isNotEmpty()) return@factory null
val candidateReturnType = candidate.returnTypeRef.toConeKotlinTypeProbablyFlexible(session, typeParameterStack)
candidateSymbol.takeIf {
when {
candidate.isAcceptableAsAccessorOverride() ->
// TODO: Decide something for the case when property type is not computed yet
expectedReturnType == null ||
AbstractTypeChecker.isSubtypeOf(session.typeContext, candidateReturnType, expectedReturnType)
else -> false
}
}
}
}
private fun FirPropertySymbol.findSetterOverride(
scope: FirScope,
): FirNamedFunctionSymbol? {
val propertyType = fir.returnTypeRef.coneTypeSafe() ?: return null
return scope.getFunctions(Name.identifier(JvmAbi.setterName(fir.name.asString()))).firstNotNullOfOrNull 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 {
candidate.isAcceptableAsAccessorOverride() && AbstractTypeChecker.equalTypes(
session.typeContext, parameterType, propertyType
)
}
}
}
private fun FirSimpleFunction.isAcceptableAsAccessorOverride(): Boolean {
// We don't accept here accessors with type parameters from Kotlin to avoid strange cases like KT-59038
// However, we (temporarily, see below) accept accessors from Kotlin in general to keep K1 compatibility in cases like KT-59550
// KT-59601: we are going to forbid accessors from Kotlin in general after some investigation and/or deprecation period
return isJavaOrEnhancement || typeParameters.isEmpty()
}
private fun FirPropertySymbol.getBuiltinSpecialPropertyGetterName(): Name? {
var result: Name? = null
superTypeScopes.processOverriddenPropertiesAndSelf(this) { overridden ->
val fqName = overridden.fir.containingClassLookupTag()?.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 FirNamedFunctionSymbol.isVisibleInCurrentClass(): Boolean {
val potentialPropertyNames = getPropertyNamesCandidatesByAccessorName(name)
val hasCorrespondingProperty = potentialPropertyNames.any { propertyName ->
getProperties(propertyName).any l@{ propertySymbol ->
// TODO: add magic overrides from LazyJavaClassMemberScope.isVisibleAsFunctionInCurrentClass
if (propertySymbol !is FirPropertySymbol) return@l false
// We may call this function at the STATUS phase, which means that using resolved status may lead to cycle
// so we need to use raw status here
propertySymbol.isVisibleInClass([email protected], propertySymbol.rawStatus) &&
propertySymbol.isOverriddenInClassBy(this)
}
}
if (hasCorrespondingProperty) return false
return !doesOverrideRenamedBuiltins() &&
!shouldBeVisibleAsOverrideOfBuiltInWithErasedValueParameters()
}
private fun FirNamedFunctionSymbol.doesOverrideRenamedBuiltins(): Boolean {
// e.g. 'removeAt' or 'toInt'
val builtinName = SpecialGenericSignatures.getBuiltinFunctionNamesByJvmName(name) ?: return false
val builtinSpecialFromSuperTypes = supertypeScopeContext.collectMembersGroupedByScope(builtinName, FirScope::processFunctionsByName)
.flatMap { (scope, symbols) ->
symbols.filter { it.doesOverrideBuiltinWithDifferentJvmName(scope, session) }
}
if (builtinSpecialFromSuperTypes.isEmpty()) return false
return builtinSpecialFromSuperTypes.any {
// Here `this` and `it` have different names but it's ok because override checker does not consider
// names of declarations at all
overrideChecker.isOverriddenFunction(this.fir, it.fir)
}
}
/**
* Checks if function is a valid override of JDK analogue of built-in method with erased value parameters (e.g. Map.containsKey(k: K))
*
* Examples:
* - boolean containsKey(Object key) -> true
* - boolean containsKey(K key) -> false // Wrong JDK method override, while it's a valid Kotlin built-in override
*
* There is a case when we shouldn't hide a function even if it overrides builtin member with value parameter erasure:
* if substituted kotlin overridden has the same parameters as current java override. Such situation may happen only in
* case when `Any`/`Object` is used as parameterization of supertype:
*
* // java
* class MySuperMap extends java.util.Map