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.
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
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 {
// this operation should be very fast
val isSuccessful: Boolean
val resultingApplicability: ResolutionCandidateApplicability
}
interface CandidateFactory {
fun createCandidate(
towerCandidate: CandidateWithBoundDispatchReceiver,
explicitReceiverKind: ExplicitReceiverKind,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): C
}
interface CandidateFactoryProviderForInvoke {
// variable here is resolved, invoke -- only chosen
fun transformCandidate(variable: C, invoke: C): C
fun factoryForVariable(stripExplicitReceiver: Boolean): CandidateFactory
// foo() -> ReceiverValue(foo), context for invoke
// null means that there is no invoke on variable
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()
// Has the same meaning as BothTowerLevelAndImplicitReceiver, but it's only used for names lookup, so it doesn't need implicit receiver
class ForLookupForNoExplicitReceiver(val level: ScopeTowerLevel) : TowerData()
}
interface ScopeTowerProcessor {
// Candidates with matched receivers (dispatch receiver was already matched in ScopeTowerLevel)
// Candidates in one groups have same priority, first group has highest priority.
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
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))
}
}
lexicalScope.parentsWithSelf.forEach { scope ->
if (scope is LexicalScope) {
if (!scope.kind.withLocalDescriptors) {
addLevel(
ScopeBasedTowerLevel(this@createNonLocalLevels, scope),
scope.mayFitForName(name)
)
}
getImplicitReceiver(scope)?.let {
addLevel(
MemberScopeTowerLevel(this@createNonLocalLevels, it),
it.mayFitForName(name)
)
}
} else {
addLevel(
ImportingScopeBasedTowerLevel(this@createNonLocalLevels, scope as ImportingScope),
scope.mayFitForName(name)
)
}
}
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) {
// hides members extensions for explicit receiver
TowerData.TowerLevel(hidesMembersLevel).process()?.let { return it }
}
// possibly there is explicit member
TowerData.Empty.process()?.let { return it }
// synthetic property for explicit receiver
TowerData.TowerLevel(syntheticLevel).process()?.let { return it }
// local non-extensions or extension for explicit receiver
for (localLevel in localLevels) {
TowerData.TowerLevel(localLevel).process()?.let { return it }
}
for (scope in implicitScopeTower.lexicalScope.parentsWithSelf) {
if (scope is LexicalScope) {
// statics
if (!scope.kind.withLocalDescriptors) {
TowerData.TowerLevel(ScopeBasedTowerLevel(implicitScopeTower, scope))
.process(scope.mayFitForName(name))?.let { return it }
}
implicitScopeTower.getImplicitReceiver(scope)
?.let(this::processImplicitReceiver)
?.let { return it }
} else {
TowerData.TowerLevel(ImportingScopeBasedTowerLevel(implicitScopeTower, scope as ImportingScope))
.process(scope.mayFitForName(name))?.let { return it }
}
}
recordLookups()
return resultCollector.getFinalCandidates()
}
private fun processImplicitReceiver(implicitReceiver: ReceiverValueWithSmartCastInfo): Collection? {
if (isNameForHidesMember) {
// hides members extensions
TowerData.BothTowerLevelAndImplicitReceiver(hidesMembersLevel, implicitReceiver).process()?.let { return it }
}
// members of implicit receiver or member extension for explicit receiver
TowerData.TowerLevel(MemberScopeTowerLevel(implicitScopeTower, implicitReceiver))
.process(implicitReceiver.mayFitForName(name))?.let { return it }
// synthetic properties
TowerData.BothTowerLevelAndImplicitReceiver(syntheticLevel, implicitReceiver).process()?.let { return it }
// invokeExtension on local variable
TowerData.OnlyImplicitReceiver(implicitReceiver).process()?.let { return it }
// local extensions for implicit receiver
for (localLevel in localLevels) {
TowerData.BothTowerLevelAndImplicitReceiver(localLevel, implicitReceiver).process()?.let { return it }
}
// extension for implicit receiver
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 (possibleTypes.isEmpty()) return false
return possibleTypes.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 == ResolutionCandidateApplicability.HIDDEN
}
}
}
class SuccessfulResultCollector : ResultCollector() {
private var candidateGroups = arrayListOf>()
private var isSuccessful = false
override fun getSuccessfulCandidates(): Collection? {
if (!isSuccessful) return null
val firstGroupWithResolved = candidateGroups.firstOrNull {
it.any { it.resultingApplicability == ResolutionCandidateApplicability.RESOLVED }
} ?: return null
return firstGroupWithResolved.filter { it.resultingApplicability == ResolutionCandidateApplicability.RESOLVED }
}
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.minBy { it.groupApplicability } ?: return emptyList()
val groupApplicability = moreSuitableGroup.groupApplicability
if (groupApplicability == ResolutionCandidateApplicability.HIDDEN) return emptyList()
return moreSuitableGroup.filter { it.resultingApplicability == groupApplicability }
}
private val Collection.groupApplicability
get() =
minBy { it.resultingApplicability }?.resultingApplicability ?: ResolutionCandidateApplicability.HIDDEN
}
}