FIR resolve: provide synthetic properties scope

At the moment get* and is* functions are supported
This commit is contained in:
Simon Ogorodnik
2019-04-10 21:28:00 +03:00
committed by Mikhail Glukhikh
parent 5763b82cdd
commit fe3afccfc2
2 changed files with 80 additions and 1 deletions
@@ -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<T>,
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 <T : ConeSymbol> processElementsByName(
@@ -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<ConeCallableSymbol, ConeVariableSymbol> = mutableMapOf()
private fun checkGetAndCreateSynthetic(
name: Name,
symbol: ConeFunctionSymbol,
processor: (ConeVariableSymbol) -> ProcessorAction
): ProcessorAction {
val fir = symbol.firSafeNullable<FirNamedFunction>() ?: 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)
}
}