From 368de4362326a45bd55fa503c8438a214a5321d7 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 24 Sep 2020 16:55:48 +0300 Subject: [PATCH] FIR Java: support Java setters more properly in use-site scope --- .../scopes/JavaClassUseSiteMemberScope.kt | 56 ++++++++++--------- .../resolve/FirJavaSyntheticNamesProvider.kt | 13 ++++- .../calls/FirSyntheticNamesProvider.kt | 3 +- .../kotlin/fir/resolve/calls/Synthetics.kt | 23 +++++--- 4 files changed, 56 insertions(+), 39 deletions(-) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt index 957dd1f4558..85cbb3543fb 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt @@ -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() - 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" - } } diff --git a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/FirJavaSyntheticNamesProvider.kt b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/FirJavaSyntheticNamesProvider.kt index 2c91d712372..04e41b09c7b 100644 --- a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/FirJavaSyntheticNamesProvider.kt +++ b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/FirJavaSyntheticNamesProvider.kt @@ -32,16 +32,25 @@ object FirJavaSyntheticNamesProvider : FirSyntheticNamesProvider() { } } - override fun setterNameByGetterName(name: Name): Name { + override fun setterNameByGetterName(name: Name): Name? { val identifier = name.identifier val prefix = when { identifier.startsWith(GETTER_PREFIX) -> GETTER_PREFIX identifier.startsWith(IS_PREFIX) -> IS_PREFIX - else -> throw IllegalArgumentException() + else -> return null } return Name.identifier(SETTER_PREFIX + identifier.removePrefix(prefix)) } + override fun getterNameBySetterName(name: Name): Name? { + val identifier = name.identifier + val prefix = when { + identifier.startsWith(SETTER_PREFIX) -> SETTER_PREFIX + else -> return null + } + return Name.identifier(GETTER_PREFIX + identifier.removePrefix(prefix)) + } + override fun propertyNameByAccessorName(name: Name): Name? { if (name.isSpecial) return null val identifier = name.identifier diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirSyntheticNamesProvider.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirSyntheticNamesProvider.kt index acd14225c52..e5467ace73b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirSyntheticNamesProvider.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirSyntheticNamesProvider.kt @@ -11,7 +11,8 @@ import org.jetbrains.kotlin.name.Name abstract class FirSyntheticNamesProvider : FirSessionComponent { abstract fun possibleGetterNamesByPropertyName(name: Name): List - abstract fun setterNameByGetterName(name: Name): Name + abstract fun setterNameByGetterName(name: Name): Name? + abstract fun getterNameBySetterName(name: Name): Name? abstract fun propertyNameByAccessorName(name: Name): Name? } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt index 25664b45177..e75eb8e4ac8 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.SyntheticSymbol import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.ConeNullability.NOT_NULL import org.jetbrains.kotlin.name.Name class SyntheticPropertySymbol( @@ -64,15 +65,19 @@ class FirSyntheticPropertiesScope( var matchingSetter: FirSimpleFunction? = null if (getterReturnType != null) { val setterName = syntheticNamesProvider.setterNameByGetterName(getterName) - baseScope.processFunctionsByName(setterName, fun(setterSymbol: FirFunctionSymbol<*>) { - if (matchingSetter != null) return - val setter = setterSymbol.fir as? FirSimpleFunction ?: return - val parameter = setter.valueParameters.singleOrNull() ?: return - if (setter.typeParameters.isNotEmpty() || setter.isStatic) return - val parameterType = (parameter.returnTypeRef as? FirResolvedTypeRef)?.type ?: return - if (getterReturnType.withNullability(ConeNullability.NOT_NULL) != parameterType.withNullability(ConeNullability.NOT_NULL)) return - matchingSetter = setter - }) + if (setterName != null) { + baseScope.processFunctionsByName(setterName, fun(setterSymbol: FirFunctionSymbol<*>) { + if (matchingSetter != null) return + val setter = setterSymbol.fir as? FirSimpleFunction ?: return + val parameter = setter.valueParameters.singleOrNull() ?: return + if (setter.typeParameters.isNotEmpty() || setter.isStatic) return + val parameterType = (parameter.returnTypeRef as? FirResolvedTypeRef)?.type ?: return + if (getterReturnType.withNullability(NOT_NULL) != parameterType.withNullability(NOT_NULL)) { + return + } + matchingSetter = setter + }) + } } val property = buildSyntheticProperty {