diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallResolver.kt index 4961e433bdb..b770ed6e560 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallResolver.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.resolve.scope import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator +import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorWithJump import org.jetbrains.kotlin.fir.scopes.FirPosition import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction @@ -138,7 +139,10 @@ class MemberScopeTowerLevel( output: TowerScopeLevel.TowerScopeLevelProcessor, takeMembers: FirScope.(processor: (T) -> ProcessorAction) -> ProcessorAction ): ProcessorAction { - return dispatchReceiver.type.scope(session)?.takeMembers { output.consumeCandidate(it, dispatchReceiver) } ?: ProcessorAction.NEXT + val scope = dispatchReceiver.type.scope(session) ?: return ProcessorAction.NEXT + if (scope.takeMembers { output.consumeCandidate(it, dispatchReceiver) }.stop()) return ProcessorAction.STOP + val withSynthetic = FirSyntheticPropertiesScope(session, scope, ReturnTypeCalculatorWithJump(session)) + return withSynthetic.takeMembers { output.consumeCandidate(it, dispatchReceiver) } } override fun processElementsByName( 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 new file mode 100644 index 00000000000..b78a2ae219d --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt @@ -0,0 +1,75 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. 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.resolve.calls + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirNamedFunction +import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter +import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter +import org.jetbrains.kotlin.fir.declarations.impl.FirMemberPropertyImpl +import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator +import org.jetbrains.kotlin.fir.resolve.transformers.firSafeNullable +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.symbols.CallableId +import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol +import org.jetbrains.kotlin.fir.symbols.ConeFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.ConeVariableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.name.Name + +class FirSyntheticPropertiesScope(val session: FirSession, val baseScope: FirScope, val typeCalculator: ReturnTypeCalculator) : FirScope { + + val synthetic: MutableMap = mutableMapOf() + + + private fun checkGetAndCreateSynthetic( + name: Name, + symbol: ConeFunctionSymbol, + processor: (ConeVariableSymbol) -> ProcessorAction + ): ProcessorAction { + val fir = symbol.firSafeNullable() ?: return ProcessorAction.NEXT + + if (fir.typeParameters.isNotEmpty()) return ProcessorAction.NEXT + if (fir.valueParameters.isNotEmpty()) return ProcessorAction.NEXT + + val synthetic = FirPropertySymbol(CallableId(symbol.callableId.packageName, symbol.callableId.className, name)) + + val returnTypeRef = typeCalculator.tryCalculateReturnType(fir) + FirMemberPropertyImpl( + session, + null, + synthetic, + name, + fir.visibility, + fir.modality, + false, + false, + false, + false, + false, + null, + returnTypeRef, + true, + null, + FirDefaultPropertyGetter(session, null, returnTypeRef, fir.visibility), + FirDefaultPropertySetter(session, null, returnTypeRef, fir.visibility), + null + ) + return processor(synthetic) + } + + override fun processPropertiesByName(name: Name, processor: (ConeVariableSymbol) -> ProcessorAction): ProcessorAction { + if (baseScope.processFunctionsByName(Name.guessByFirstCharacter("get${name.identifier.capitalize()}")) { + checkGetAndCreateSynthetic(name, it, processor) + }.stop()) return ProcessorAction.STOP + + if (name.asString().startsWith("is") && baseScope.processFunctionsByName(name) { + checkGetAndCreateSynthetic(name, it, processor) + }.stop()) return ProcessorAction.STOP + return super.processPropertiesByName(name, processor) + } +} \ No newline at end of file