Introduce TowerResolver.Task class

Its main purpose is code simplification: ImplicitScopeTower::run
contains a lot of local functions that are needed because of
lots of shared state

So, we're moving the state to the Task class instead

NB: This change doesn't change the code of `run`, it will be done
in further commits
This commit is contained in:
Denis Zharkov
2017-08-24 15:40:45 +03:00
parent b77cc54122
commit c7fda42ccc
@@ -93,167 +93,178 @@ class TowerResolver {
): Collection<C> ): Collection<C>
= scopeTower.run(processor, AllCandidatesCollector(), false, name) = scopeTower.run(processor, AllCandidatesCollector(), false, name)
fun <C : Candidate> ImplicitScopeTower.run(
processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>,
useOrder: Boolean,
name: Name
): Collection<C> = with(Task()) {
this@run.run(processor, resultCollector, useOrder, name)
}
private data class ScopeLevelsAndSkippedForLookups( private data class ScopeLevelsAndSkippedForLookups(
val levelsToProcess: Collection<ScopeTowerLevel>, val levelsToProcess: Collection<ScopeTowerLevel>,
val levelsToSkip: Collection<ScopeTowerLevel> val levelsToSkip: Collection<ScopeTowerLevel>
) )
private fun ImplicitScopeTower.createNonLocalLevels(name: Name): ScopeLevelsAndSkippedForLookups { private inner class Task {
val mainResult = mutableListOf<ScopeTowerLevel>() private fun ImplicitScopeTower.createNonLocalLevels(name: Name): ScopeLevelsAndSkippedForLookups {
val skippedLevels = mutableListOf<ScopeTowerLevel>() val mainResult = mutableListOf<ScopeTowerLevel>()
val skippedLevels = mutableListOf<ScopeTowerLevel>()
fun addLevel(scopeTowerLevel: ScopeTowerLevel, mayFitForName: Boolean) { fun addLevel(scopeTowerLevel: ScopeTowerLevel, mayFitForName: Boolean) {
if (mayFitForName) { if (mayFitForName) {
mainResult.add(scopeTowerLevel) mainResult.add(scopeTowerLevel)
}
else {
skippedLevels.add(scopeTowerLevel)
}
} }
else {
skippedLevels.add(scopeTowerLevel)
}
}
lexicalScope.parentsWithSelf.forEach { scope -> lexicalScope.parentsWithSelf.forEach { scope ->
if (scope is LexicalScope) { if (scope is LexicalScope) {
if (!scope.kind.withLocalDescriptors) { 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( addLevel(
ScopeBasedTowerLevel(this@createNonLocalLevels, scope), ImportingScopeBasedTowerLevel(this@createNonLocalLevels, scope as ImportingScope),
scope.mayFitForName(name) scope.mayFitForName(name)
) )
} }
}
getImplicitReceiver(scope)?.let { return ScopeLevelsAndSkippedForLookups(mainResult, skippedLevels)
addLevel( }
MemberScopeTowerLevel(this@createNonLocalLevels, it),
it.mayFitForName(name) fun <C : Candidate> ImplicitScopeTower.run(
) processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>,
useOrder: Boolean,
name: Name
): Collection<C> {
val skippedDataForLookup = mutableListOf<TowerData>()
fun recordLookups() {
processor.recordLookups(skippedDataForLookup, name)
}
fun TowerData.process() = processTowerData(processor, resultCollector, useOrder, this)?.also {
recordLookups()
}
fun TowerData.process(mayFitForName: Boolean): Collection<C>? {
if (!mayFitForName) {
skippedDataForLookup.add(this)
return null
} }
return process()
} }
else {
addLevel( // Lazy calculation
ImportingScopeBasedTowerLevel(this@createNonLocalLevels, scope as ImportingScope), var nonLocalLevels: Collection<ScopeTowerLevel>? = null
scope.mayFitForName(name) val hidesMembersLevel = HidesMembersTowerLevel(this)
) val syntheticLevel = SyntheticScopeBasedTowerLevel(this, syntheticScopes)
if (name in HIDES_MEMBERS_NAME_LIST) {
// hides members extensions for explicit receiver
TowerData.TowerLevel(hidesMembersLevel).process()?.let { return it }
} }
}
return ScopeLevelsAndSkippedForLookups(mainResult, skippedLevels) // possibly there is explicit member
} TowerData.Empty.process()?.let { return it }
// synthetic property for explicit receiver
TowerData.TowerLevel(syntheticLevel).process()?.let { return it }
private fun <C : Candidate> ImplicitScopeTower.run( val localLevels =
processor: ScopeTowerProcessor<C>, lexicalScope.parentsWithSelf.
resultCollector: ResultCollector<C>, filterIsInstance<LexicalScope>().filter { it.kind.withLocalDescriptors && it.mayFitForName(name) }.
useOrder: Boolean, map { ScopeBasedTowerLevel(this@run, it) }.toList()
name: Name
): Collection<C> {
val skippedDataForLookup = mutableListOf<TowerData>()
fun recordLookups() { // local non-extensions or extension for explicit receiver
processor.recordLookups(skippedDataForLookup, name) for (localLevel in localLevels) {
} TowerData.TowerLevel(localLevel).process()?.let { return it }
fun TowerData.process() = processTowerData(processor, resultCollector, useOrder, this)?.also {
recordLookups()
}
fun TowerData.process(mayFitForName: Boolean): Collection<C>? {
if (!mayFitForName) {
skippedDataForLookup.add(this)
return null
} }
return process()
}
// Lazy calculation for (scope in lexicalScope.parentsWithSelf) {
var nonLocalLevels: Collection<ScopeTowerLevel>? = null if (scope is LexicalScope) {
val hidesMembersLevel = HidesMembersTowerLevel(this) // statics
val syntheticLevel = SyntheticScopeBasedTowerLevel(this, syntheticScopes) if (!scope.kind.withLocalDescriptors) {
TowerData.TowerLevel(ScopeBasedTowerLevel(this, scope))
.process(scope.mayFitForName(name))?.let { return it }
}
if (name in HIDES_MEMBERS_NAME_LIST) { val implicitReceiver = getImplicitReceiver(scope)
// hides members extensions for explicit receiver if (implicitReceiver != null) {
TowerData.TowerLevel(hidesMembersLevel).process()?.let { return it } if (name in HIDES_MEMBERS_NAME_LIST) {
} // hides members extensions
TowerData.BothTowerLevelAndImplicitReceiver(hidesMembersLevel, implicitReceiver).process()?.let { return it }
}
// possibly there is explicit member // members of implicit receiver or member extension for explicit receiver
TowerData.Empty.process()?.let { return it } TowerData.TowerLevel(MemberScopeTowerLevel(this, implicitReceiver))
// synthetic property for explicit receiver .process(implicitReceiver.mayFitForName(name))?.let { return it }
TowerData.TowerLevel(syntheticLevel).process()?.let { return it }
val localLevels = // synthetic properties
lexicalScope.parentsWithSelf. TowerData.BothTowerLevelAndImplicitReceiver(syntheticLevel, implicitReceiver).process()?.let { return it }
filterIsInstance<LexicalScope>().filter { it.kind.withLocalDescriptors && it.mayFitForName(name) }.
map { ScopeBasedTowerLevel(this@run, it) }.toList()
// local non-extensions or extension for explicit receiver // invokeExtension on local variable
for (localLevel in localLevels) { TowerData.OnlyImplicitReceiver(implicitReceiver).process()?.let { return it }
TowerData.TowerLevel(localLevel).process()?.let { return it }
}
for (scope in lexicalScope.parentsWithSelf) { // local extensions for implicit receiver
if (scope is LexicalScope) { for (localLevel in localLevels) {
// statics TowerData.BothTowerLevelAndImplicitReceiver(localLevel, implicitReceiver).process()?.let { return it }
if (!scope.kind.withLocalDescriptors) { }
TowerData.TowerLevel(ScopeBasedTowerLevel(this, scope))
if (nonLocalLevels == null) {
val (toProcess, toSkip) = createNonLocalLevels(name)
nonLocalLevels = toProcess
toSkip.mapTo(skippedDataForLookup) { TowerData.BothTowerLevelAndImplicitReceiver(it, implicitReceiver) }
}
// extension for implicit receiver
for (nonLocalLevel in nonLocalLevels) {
TowerData.BothTowerLevelAndImplicitReceiver(nonLocalLevel, implicitReceiver).process()?.let { return it }
}
}
}
else {
TowerData.TowerLevel(ImportingScopeBasedTowerLevel(this, scope as ImportingScope))
.process(scope.mayFitForName(name))?.let { return it } .process(scope.mayFitForName(name))?.let { return it }
} }
val implicitReceiver = getImplicitReceiver(scope)
if (implicitReceiver != null) {
if (name in HIDES_MEMBERS_NAME_LIST) {
// hides members extensions
TowerData.BothTowerLevelAndImplicitReceiver(hidesMembersLevel, implicitReceiver).process()?.let { return it }
}
// members of implicit receiver or member extension for explicit receiver
TowerData.TowerLevel(MemberScopeTowerLevel(this, 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 }
}
if (nonLocalLevels == null) {
val (toProcess, toSkip) = createNonLocalLevels(name)
nonLocalLevels = toProcess
toSkip.mapTo(skippedDataForLookup) { TowerData.BothTowerLevelAndImplicitReceiver(it, implicitReceiver) }
}
// extension for implicit receiver
for (nonLocalLevel in nonLocalLevels) {
TowerData.BothTowerLevelAndImplicitReceiver(nonLocalLevel, implicitReceiver).process()?.let { return it }
}
}
}
else {
TowerData.TowerLevel(ImportingScopeBasedTowerLevel(this, scope as ImportingScope))
.process(scope.mayFitForName(name))?.let { return it }
} }
recordLookups()
return resultCollector.getFinalCandidates()
} }
recordLookups() 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) }
}
return resultCollector.getFinalCandidates() 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)
} }
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 <C : Candidate> runWithEmptyTowerData( fun <C : Candidate> runWithEmptyTowerData(
processor: ScopeTowerProcessor<C>, processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>, resultCollector: ResultCollector<C>,