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:
+138
-127
@@ -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>,
|
||||||
|
|||||||
Reference in New Issue
Block a user