FIR Java: support Java setters more properly in use-site scope

This commit is contained in:
Mikhail Glukhikh
2020-09-24 16:55:48 +03:00
parent 873ea560a9
commit 368de43623
4 changed files with 56 additions and 39 deletions
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.scopes.getContainingClassifierNamesIfPresent
import org.jetbrains.kotlin.fir.scopes.impl.AbstractFirUseSiteMemberScope
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.isUnit
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
import org.jetbrains.kotlin.name.Name
@@ -58,33 +59,19 @@ class JavaClassUseSiteMemberScope(
}
private fun generateAccessorSymbol(
functionSymbol: FirFunctionSymbol<*>,
getterSymbol: FirNamedFunctionSymbol,
setterSymbol: FirNamedFunctionSymbol?,
syntheticPropertyName: Name,
isGetter: Boolean
): FirAccessorSymbol? {
if (functionSymbol !is FirNamedFunctionSymbol) {
return null
}
val fir = functionSymbol.fir
if (fir.isStatic) {
return null
}
when (isGetter) {
true -> if (fir.valueParameters.isNotEmpty()) {
return null
}
false -> if (fir.valueParameters.size != 1) {
return null
}
}
return buildSyntheticProperty {
session = this@JavaClassUseSiteMemberScope.session
name = syntheticPropertyName
symbol = FirAccessorSymbol(
accessorId = functionSymbol.callableId,
callableId = CallableId(functionSymbol.callableId.packageName, functionSymbol.callableId.className, syntheticPropertyName)
accessorId = getterSymbol.callableId,
callableId = CallableId(getterSymbol.callableId.packageName, getterSymbol.callableId.className, syntheticPropertyName)
)
delegateGetter = fir
delegateGetter = getterSymbol.fir
delegateSetter = setterSymbol?.fir
}.symbol
}
@@ -103,9 +90,28 @@ class JavaClassUseSiteMemberScope(
if (klass is FirJavaClass) {
for (getterName in getterNames) {
var getterSymbol: FirNamedFunctionSymbol? = null
var setterSymbol: FirNamedFunctionSymbol? = null
declaredMemberScope.processFunctionsByName(getterName) { functionSymbol ->
if (getterSymbol == null && functionSymbol is FirNamedFunctionSymbol) {
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 && functionSymbol is FirNamedFunctionSymbol) {
val function = functionSymbol.fir
if (!function.isStatic && function.returnTypeRef.isUnit && function.valueParameters.size == 1) {
setterSymbol = functionSymbol
}
}
}
val accessorSymbol = generateAccessorSymbol(
functionSymbol, propertyName, isGetter = true
getterSymbol!!, setterSymbol, propertyName
)
if (accessorSymbol != null) {
// NB: accessor should not be processed directly unless we find matching property symbol in supertype
@@ -158,7 +164,6 @@ class JavaClassUseSiteMemberScope(
return processAccessorFunctionsAndPropertiesByName(name, emptyList(), processor)
}
val getterNames = FirJavaSyntheticNamesProvider.possibleGetterNamesByPropertyName(name)
val setterName = Name.identifier(SETTER_PREFIX + name.identifier.capitalize())
return processAccessorFunctionsAndPropertiesByName(name, getterNames, processor)
}
@@ -169,7 +174,8 @@ class JavaClassUseSiteMemberScope(
val potentialPropertyName = session.syntheticNamesProvider.propertyNameByAccessorName(name)
?: return super.processFunctionsByName(name, processor)
val accessors = mutableListOf<FirAccessorSymbol>()
processAccessorFunctionsAndPropertiesByName(potentialPropertyName, listOf(name)) {
val getterName = session.syntheticNamesProvider.getterNameBySetterName(name) ?: name
processAccessorFunctionsAndPropertiesByName(potentialPropertyName, listOf(getterName)) {
if (it is FirAccessorSymbol) {
accessors += it
}
@@ -188,8 +194,4 @@ class JavaClassUseSiteMemberScope(
}
}
}
companion object {
private const val SETTER_PREFIX = "set"
}
}