Please wait. This can take some minutes ...
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.
org.jetbrains.kotlin.resolve.calls.tower.TowerResolver.kt Maven / Gradle / Ivy
package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.inference.model.LowerPriorityToPreserveCompatibility
import org.jetbrains.kotlin.resolve.calls.model.constraintSystemError
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
import org.jetbrains.kotlin.resolve.scopes.HierarchicalScope
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.ResolutionScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isDynamic
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.*
interface Candidate {
val isSuccessful: Boolean
val resultingApplicability: CandidateApplicability
fun addCompatibilityWarning(other: Candidate )
}
interface CandidateFactory {
fun createCandidate(
towerCandidate: CandidateWithBoundDispatchReceiver ,
explicitReceiverKind: ExplicitReceiverKind ,
extensionReceiver: ReceiverValueWithSmartCastInfo ?
): C
fun createErrorCandidate(): C
fun createCandidate(
towerCandidate: CandidateWithBoundDispatchReceiver ,
explicitReceiverKind: ExplicitReceiverKind ,
extensionReceiverCandidates: List
): C
}
interface CandidateFactoryProviderForInvoke {
fun transformCandidate(variable: C , invoke: C ): C
fun factoryForVariable(stripExplicitReceiver: Boolean ): CandidateFactory
fun factoryForInvoke(variable: C , useExplicitReceiver: Boolean ): Pair >?
}
sealed class TowerData {
object Empty : TowerData ()
class OnlyImplicitReceiver (val implicitReceiver: ReceiverValueWithSmartCastInfo ) : TowerData ()
class TowerLevel (val level: ScopeTowerLevel ) : TowerData ()
class BothTowerLevelAndImplicitReceiver (val level: ScopeTowerLevel , val implicitReceiver: ReceiverValueWithSmartCastInfo ) : TowerData ()
class BothTowerLevelAndContextReceiversGroup (
val level: ScopeTowerLevel ,
val contextReceiversGroup: List
) : TowerData ()
class ForLookupForNoExplicitReceiver (val level: ScopeTowerLevel ) : TowerData ()
}
interface ScopeTowerProcessor {
fun process(data: TowerData ): List >
fun recordLookups(skippedData: Collection , name: Name )
}
class TowerResolver {
fun runResolve(
scopeTower: ImplicitScopeTower ,
processor: ScopeTowerProcessor ,
useOrder: Boolean ,
name: Name
): Collection = scopeTower.run(processor, SuccessfulResultCollector (), useOrder, name)
fun collectAllCandidates(
scopeTower: ImplicitScopeTower ,
processor: ScopeTowerProcessor ,
name: Name
): Collection = scopeTower.run(processor, AllCandidatesCollector (), false , name)
private fun ImplicitScopeTower .run(
processor: ScopeTowerProcessor ,
resultCollector: ResultCollector ,
useOrder: Boolean ,
name: Name
): Collection = Task (this , processor, resultCollector, useOrder, name).run()
private inner class Task (
private val implicitScopeTower: ImplicitScopeTower ,
private val processor: ScopeTowerProcessor ,
private val resultCollector: ResultCollector ,
private val useOrder: Boolean ,
private val name: Name
) {
private val isNameForHidesMember =
name in HIDES_MEMBERS_NAME_LIST || implicitScopeTower.getNameForGivenImportAlias(name) in HIDES_MEMBERS_NAME_LIST
private val skippedDataForLookup = mutableListOf()
private val localLevels: Collection by lazy (LazyThreadSafetyMode .NONE ) {
implicitScopeTower.lexicalScope.parentsWithSelf.filterIsInstance()
.filter { it.kind.withLocalDescriptors && it.mayFitForName(name) }.map { ScopeBasedTowerLevel (implicitScopeTower, it) }
.toList()
}
private val nonLocalLevels: Collection by lazy (LazyThreadSafetyMode .NONE ) {
implicitScopeTower.createNonLocalLevels()
}
val hidesMembersLevel = HidesMembersTowerLevel (implicitScopeTower)
val syntheticLevel = SyntheticScopeBasedTowerLevel (implicitScopeTower, implicitScopeTower.syntheticScopes)
private fun ImplicitScopeTower .createNonLocalLevels(): Collection {
val mainResult = mutableListOf()
fun addLevel(scopeTowerLevel: ScopeTowerLevel , mayFitForName: Boolean ) {
if (mayFitForName) {
mainResult.add(scopeTowerLevel)
} else {
skippedDataForLookup.add(TowerData .ForLookupForNoExplicitReceiver (scopeTowerLevel))
}
}
fun addLevelForLexicalScope(scope: LexicalScope ) {
if (!scope.kind.withLocalDescriptors) {
addLevel(
ScopeBasedTowerLevel (this @createNonLocalLevels , scope),
scope.mayFitForName(name)
)
}
getImplicitReceiver(scope)?.let {
addLevel(
MemberScopeTowerLevel (this @createNonLocalLevels , it),
it.mayFitForName(name)
)
}
}
fun addLevelForContextReceiverGroup(contextReceiversGroup: List ) =
addLevel(
ContextReceiversGroupScopeTowerLevel (this @createNonLocalLevels , contextReceiversGroup),
contextReceiversGroup.any { it.mayFitForName(name) }
)
fun addLevelForImportingScope(scope: HierarchicalScope ) =
addLevel(
ImportingScopeBasedTowerLevel (this @createNonLocalLevels , scope as ImportingScope ),
scope.mayFitForName(name)
)
if (!areContextReceiversEnabled) {
lexicalScope.parentsWithSelf.forEach { scope ->
if (scope is LexicalScope ) addLevelForLexicalScope(scope) else addLevelForImportingScope(scope)
}
return mainResult
}
val parentScopes = lexicalScope.parentsWithSelf.toList()
val contextReceiversGroups = mutableListOf>()
var firstImportingScopeIndex = 0
for ((i, scope) in parentScopes.withIndex()) {
if (scope !is LexicalScope ) {
firstImportingScopeIndex = i
break
}
addLevelForLexicalScope(scope)
val contextReceiversGroup = getContextReceivers(scope)
if (contextReceiversGroup.isNotEmpty()) {
contextReceiversGroups.add(contextReceiversGroup)
}
}
contextReceiversGroups.forEach(::addLevelForContextReceiverGroup)
parentScopes.subList(firstImportingScopeIndex, parentScopes.size).forEach(::addLevelForImportingScope)
return mainResult
}
private fun TowerData .process() = processTowerData(processor, resultCollector, useOrder, this )?.also {
recordLookups()
}
private fun TowerData .process(mayFitForName: Boolean ): Collection ? {
if (!mayFitForName) {
skippedDataForLookup.add(this )
return null
}
return process()
}
fun run(): Collection {
if (isNameForHidesMember) {
TowerData .TowerLevel (hidesMembersLevel).process()?.let { return it }
}
TowerData .Empty .process()?.let { return it }
TowerData .TowerLevel (syntheticLevel).process()?.let { return it }
for (localLevel in localLevels) {
TowerData .TowerLevel (localLevel).process()?.let { return it }
}
val contextReceiversGroups = mutableListOf>()
fun processLexicalScope(scope: LexicalScope , resolveExtensionsForImplicitReceiver: Boolean ): Collection ? {
if (implicitScopeTower.areContextReceiversEnabled) {
val contextReceiversGroup = implicitScopeTower.getContextReceivers(scope)
if (contextReceiversGroup.isNotEmpty()) {
contextReceiversGroups.add(contextReceiversGroup)
}
}
if (!scope.kind.withLocalDescriptors) {
TowerData .TowerLevel (ScopeBasedTowerLevel (implicitScopeTower, scope))
.process(scope.mayFitForName(name))?.let { return it }
}
implicitScopeTower.getImplicitReceiver(scope)
?.let { processImplicitReceiver(it, resolveExtensionsForImplicitReceiver) }
?.let { return it }
return null
}
fun processContextReceiverGroup(contextReceiversGroup: List ): Collection ? {
TowerData .TowerLevel (ContextReceiversGroupScopeTowerLevel (implicitScopeTower, contextReceiversGroup))
.process()?.let { return it }
TowerData .BothTowerLevelAndContextReceiversGroup (syntheticLevel, contextReceiversGroup).process()
?.let { return it }
for (nonLocalLevel in nonLocalLevels) {
TowerData .BothTowerLevelAndContextReceiversGroup (nonLocalLevel, contextReceiversGroup).process()
?.let { return it }
}
return null
}
fun processImportingScope(scope: ImportingScope ): Collection ? {
TowerData .TowerLevel (ImportingScopeBasedTowerLevel (implicitScopeTower, scope))
.process(scope.mayFitForName(name))?.let { return it }
return null
}
fun processScopes(
scopes: Sequence ,
resolveExtensionsForImplicitReceiver: (HierarchicalScope ) -> Boolean
): Collection ? {
if (!implicitScopeTower.areContextReceiversEnabled) {
scopes.forEach { scope ->
if (scope is LexicalScope ) {
processLexicalScope(scope, resolveExtensionsForImplicitReceiver(scope))?.let { return it }
} else {
processImportingScope(scope as ImportingScope )?.let { return it }
}
}
return null
}
var firstImportingScopePassed = false
for (scope in scopes) {
if (scope is LexicalScope ) {
processLexicalScope(scope, resolveExtensionsForImplicitReceiver(scope))?.let { return it }
} else {
if (!firstImportingScopePassed) {
firstImportingScopePassed = true
contextReceiversGroups.forEach { contextReceiversGroup ->
processContextReceiverGroup(contextReceiversGroup)?.let { return it }
}
}
processImportingScope(scope as ImportingScope )?.let { return it }
}
}
return null
}
if (implicitScopeTower.implicitsResolutionFilter === ImplicitsExtensionsResolutionFilter .Default ) {
processScopes(implicitScopeTower.lexicalScope.parentsWithSelf) { true }
} else {
val scopeInfos = implicitScopeTower.allScopesWithImplicitsResolutionInfo()
val scopeToResolveExtensionsForImplicitReceiverMap =
scopeInfos.map { it.scope to it.resolveExtensionsForImplicitReceiver }.toMap()
processScopes(scopeInfos.map { it.scope }) { scopeToResolveExtensionsForImplicitReceiverMap[it] ?: false }
}
recordLookups()
return resultCollector.getFinalCandidates()
}
private fun processImplicitReceiver(implicitReceiver: ReceiverValueWithSmartCastInfo , resolveExtensions: Boolean ): Collection ? {
if (isNameForHidesMember) {
TowerData .BothTowerLevelAndImplicitReceiver (hidesMembersLevel, implicitReceiver).process()?.let { return it }
}
TowerData .TowerLevel (MemberScopeTowerLevel (implicitScopeTower, implicitReceiver))
.process(implicitReceiver.mayFitForName(name))?.let { return it }
TowerData .BothTowerLevelAndImplicitReceiver (syntheticLevel, implicitReceiver).process()?.let { return it }
if (resolveExtensions) {
TowerData .OnlyImplicitReceiver (implicitReceiver).process()?.let { return it }
for (localLevel in localLevels) {
TowerData .BothTowerLevelAndImplicitReceiver (localLevel, implicitReceiver).process()?.let { return it }
}
for (nonLocalLevel in nonLocalLevels) {
TowerData .BothTowerLevelAndImplicitReceiver (nonLocalLevel, implicitReceiver).process()?.let { return it }
}
}
return null
}
private fun recordLookups() {
processor.recordLookups(skippedDataForLookup, name)
}
private fun ReceiverValueWithSmartCastInfo .mayFitForName(name: Name ): Boolean {
if (receiverValue.type .mayFitForName(name)) return true
if (!hasTypesFromSmartCasts()) return false
return typesFromSmartCasts.any { it.mayFitForName(name) }
}
private fun KotlinType .mayFitForName(name: Name ) =
isDynamic() ||
!memberScope.definitelyDoesNotContainName(name) ||
!memberScope.definitelyDoesNotContainName(OperatorNameConventions .INVOKE )
private fun ResolutionScope .mayFitForName(name: Name ) =
!definitelyDoesNotContainName(name) || !definitelyDoesNotContainName(OperatorNameConventions .INVOKE )
}
fun runWithEmptyTowerData(
processor: ScopeTowerProcessor ,
resultCollector: ResultCollector ,
useOrder: Boolean
): Collection = processTowerData(processor, resultCollector, useOrder, TowerData .Empty ) ?: resultCollector.getFinalCandidates()
private fun processTowerData(
processor: ScopeTowerProcessor ,
resultCollector: ResultCollector ,
useOrder: Boolean ,
towerData: TowerData
): Collection ? {
ProgressIndicatorAndCompilationCanceledStatus .checkCanceled()
val candidatesGroups = if (useOrder) {
processor.process(towerData)
} else {
listOf(processor.process(towerData).flatten())
}
for (candidatesGroup in candidatesGroups) {
resultCollector.pushCandidates(candidatesGroup)
resultCollector.getSuccessfulCandidates()?.let { return it }
}
return null
}
abstract class ResultCollector {
abstract fun getSuccessfulCandidates(): Collection ?
abstract fun getFinalCandidates(): Collection
abstract fun pushCandidates(candidates: Collection )
}
class AllCandidatesCollector : ResultCollector () {
private val allCandidates = ArrayList ()
override fun getSuccessfulCandidates(): Collection ? = null
override fun getFinalCandidates(): Collection = allCandidates
override fun pushCandidates(candidates: Collection ) {
candidates.filterNotTo(allCandidates) {
it.resultingApplicability == CandidateApplicability .HIDDEN
}
}
}
class SuccessfulResultCollector : ResultCollector () {
private var candidateGroups = arrayListOf>()
private var isSuccessful = false
override fun getSuccessfulCandidates(): Collection ? {
if (!isSuccessful) return null
var compatibilityCandidate: C ? = null
var compatibilityGroup: Collection ? = null
var shouldStopGroup: Collection ? = null
outer@ for (group in candidateGroups) {
for (candidate in group) {
if (shouldStopResolveOnCandidate(candidate)) {
shouldStopGroup = group
break @outer
}
if (compatibilityCandidate == null && isPreserveCompatibilityCandidate(candidate)) {
compatibilityGroup = group
compatibilityCandidate = candidate
}
}
}
if (shouldStopGroup == null ) return null
if (compatibilityCandidate != null
&& compatibilityGroup !== shouldStopGroup
&& needToReportCompatibilityWarning(compatibilityCandidate)
) {
shouldStopGroup.forEach { it.addCompatibilityWarning(compatibilityCandidate) }
}
return shouldStopGroup.filter(::shouldStopResolveOnCandidate)
}
private fun needToReportCompatibilityWarning(candidate: C ) = candidate is ResolutionCandidate &&
candidate.diagnostics.any {
(it.constraintSystemError as? LowerPriorityToPreserveCompatibility )?.needToReportWarning == true
}
private fun shouldStopResolveOnCandidate(candidate: C ): Boolean {
return candidate.resultingApplicability.shouldStopResolve
}
private fun isPreserveCompatibilityCandidate(candidate: C ): Boolean =
candidate.resultingApplicability == CandidateApplicability .RESOLVED_NEED_PRESERVE_COMPATIBILITY
override fun pushCandidates(candidates: Collection ) {
val thereIsSuccessful = candidates.any { it.isSuccessful }
if (!isSuccessful && !thereIsSuccessful) {
candidateGroups.add(candidates)
return
}
if (!isSuccessful) {
candidateGroups.clear()
isSuccessful = true
}
if (thereIsSuccessful) {
candidateGroups.add(candidates.filter { it.isSuccessful })
}
}
override fun getFinalCandidates(): Collection {
val moreSuitableGroup = candidateGroups.maxByOrNull { it.groupApplicability } ?: return emptyList()
val groupApplicability = moreSuitableGroup.groupApplicability
if (groupApplicability == CandidateApplicability .HIDDEN ) return emptyList()
return moreSuitableGroup.filter { it.resultingApplicability == groupApplicability }
}
private val Collection .groupApplicability: CandidateApplicability
get() = maxOfOrNull { it.resultingApplicability } ?: CandidateApplicability .HIDDEN
}
}