Optimized task creation for local functions and variables
This commit is contained in:
+34
@@ -27,6 +27,9 @@ import org.jetbrains.kotlin.resolve.calls.tasks.createSynthesizedInvokes
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassObjectType
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.collectAllFromMeAndParent
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.getLocalVariable
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
@@ -34,6 +37,8 @@ import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
||||
|
||||
public interface CallableDescriptorCollector<D : CallableDescriptor> {
|
||||
|
||||
public fun getLocalNonExtensionsByName(lexicalScope: LexicalScope, name: Name, location: LookupLocation): Collection<D>
|
||||
|
||||
public fun getNonExtensionsByName(scope: JetScope, name: Name, location: LookupLocation): Collection<D>
|
||||
|
||||
public fun getMembersByName(receiver: JetType, name: Name, location: LookupLocation): Collection<D>
|
||||
@@ -71,6 +76,17 @@ public fun <D : CallableDescriptor> CallableDescriptorCollectors<D>.filtered(fil
|
||||
CallableDescriptorCollectors(this.collectors.map { it.filtered(filter) })
|
||||
|
||||
private object FunctionCollector : CallableDescriptorCollector<FunctionDescriptor> {
|
||||
override fun getLocalNonExtensionsByName(lexicalScope: LexicalScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
|
||||
return lexicalScope.collectAllFromMeAndParent {
|
||||
if (it.ownerDescriptor is FunctionDescriptor) {
|
||||
it.getDeclaredFunctions(name, location).filter { it.extensionReceiverParameter == null } +
|
||||
getConstructors(it.getDeclaredClassifier(name, location))
|
||||
}
|
||||
else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getNonExtensionsByName(scope: JetScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
|
||||
return scope.getFunctions(name, location).filter { it.extensionReceiverParameter == null } + getConstructors(scope, name, location)
|
||||
@@ -117,6 +133,13 @@ private object FunctionCollector : CallableDescriptorCollector<FunctionDescripto
|
||||
filterClassPredicate: (ClassDescriptor) -> Boolean = { true }
|
||||
): Collection<FunctionDescriptor> {
|
||||
val classifier = scope.getClassifier(name, location)
|
||||
return getConstructors(classifier, filterClassPredicate)
|
||||
}
|
||||
|
||||
private fun getConstructors(
|
||||
classifier: ClassifierDescriptor?,
|
||||
filterClassPredicate: (ClassDescriptor) -> Boolean = { true }
|
||||
): Collection<FunctionDescriptor> {
|
||||
if (classifier !is ClassDescriptor || ErrorUtils.isError(classifier) || !filterClassPredicate(classifier)
|
||||
// Constructors of singletons shouldn't be callable from the code
|
||||
|| classifier.kind.isSingleton) {
|
||||
@@ -129,6 +152,9 @@ private object FunctionCollector : CallableDescriptorCollector<FunctionDescripto
|
||||
}
|
||||
|
||||
private object VariableCollector : CallableDescriptorCollector<VariableDescriptor> {
|
||||
override fun getLocalNonExtensionsByName(lexicalScope: LexicalScope, name: Name, location: LookupLocation): Collection<VariableDescriptor> {
|
||||
return listOfNotNull(lexicalScope.getLocalVariable(name))
|
||||
}
|
||||
|
||||
private fun getFakeDescriptorForObject(scope: JetScope, name: Name, location: LookupLocation): VariableDescriptor? {
|
||||
val classifier = scope.getClassifier(name, location)
|
||||
@@ -172,6 +198,10 @@ private object PropertyCollector : CallableDescriptorCollector<VariableDescripto
|
||||
private fun filterProperties(variableDescriptors: Collection<VariableDescriptor>) =
|
||||
variableDescriptors.filter { it is PropertyDescriptor }
|
||||
|
||||
override fun getLocalNonExtensionsByName(lexicalScope: LexicalScope, name: Name, location: LookupLocation): Collection<VariableDescriptor> {
|
||||
return filterProperties(VARIABLES_COLLECTOR.getLocalNonExtensionsByName(lexicalScope, name, location))
|
||||
}
|
||||
|
||||
override fun getNonExtensionsByName(scope: JetScope, name: Name, location: LookupLocation): Collection<VariableDescriptor> {
|
||||
return filterProperties(VARIABLES_COLLECTOR.getNonExtensionsByName(scope, name, location))
|
||||
}
|
||||
@@ -194,6 +224,10 @@ private object PropertyCollector : CallableDescriptorCollector<VariableDescripto
|
||||
private fun <D : CallableDescriptor> CallableDescriptorCollector<D>.filtered(filter: (D) -> Boolean): CallableDescriptorCollector<D> {
|
||||
val delegate = this
|
||||
return object : CallableDescriptorCollector<D> {
|
||||
override fun getLocalNonExtensionsByName(lexicalScope: LexicalScope, name: Name, location: LookupLocation): Collection<D> {
|
||||
return delegate.getLocalNonExtensionsByName(lexicalScope, name, location).filter(filter)
|
||||
}
|
||||
|
||||
override fun getNonExtensionsByName(scope: JetScope, name: Name, location: LookupLocation): Collection<D> {
|
||||
return delegate.getNonExtensionsByName(scope, name, location).filter(filter)
|
||||
}
|
||||
|
||||
@@ -37,15 +37,6 @@ public class ResolutionTaskHolder<D : CallableDescriptor, F : D>(
|
||||
candidatesList.add(storageManager.createLazyValue { lazyCandidates().toReadOnlyList() })
|
||||
}
|
||||
|
||||
public fun addCandidates(candidatesList: List<Collection<ResolutionCandidate<D>>>) {
|
||||
assertNotFinished()
|
||||
for (candidates in candidatesList) {
|
||||
if (candidates.isNotEmpty()) {
|
||||
addCandidates { candidates }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun assertNotFinished() {
|
||||
assert(internalTasks == null, "Can't add candidates after the resulting tasks were computed.")
|
||||
}
|
||||
|
||||
@@ -56,22 +56,6 @@ public class TaskPrioritizer(
|
||||
private val smartCastManager: SmartCastManager
|
||||
) {
|
||||
|
||||
public fun <D : CallableDescriptor> splitLexicallyLocalDescriptors(
|
||||
allDescriptors: Collection<ResolutionCandidate<D>>,
|
||||
containerOfTheCurrentLocality: DeclarationDescriptor,
|
||||
local: MutableCollection<ResolutionCandidate<D>>,
|
||||
nonlocal: MutableCollection<ResolutionCandidate<D>>
|
||||
) {
|
||||
for (resolvedCall in allDescriptors) {
|
||||
if (ExpressionTypingUtils.isLocal(containerOfTheCurrentLocality, resolvedCall.getDescriptor())) {
|
||||
local.add(resolvedCall)
|
||||
}
|
||||
else {
|
||||
nonlocal.add(resolvedCall)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun <D : CallableDescriptor, F : D> computePrioritizedTasks(
|
||||
context: BasicCallResolutionContext,
|
||||
name: Name,
|
||||
@@ -264,28 +248,18 @@ public class TaskPrioritizer(
|
||||
implicitReceivers: Collection<ReceiverValue>,
|
||||
c: TaskPrioritizerContext<D, F>
|
||||
) {
|
||||
val localsList = Lists.newArrayList<Collection<ResolutionCandidate<D>>>()
|
||||
val nonlocalsList = Lists.newArrayList<Collection<ResolutionCandidate<D>>>()
|
||||
for (callableDescriptorCollector in c.callableDescriptorCollectors) {
|
||||
|
||||
val members = convertWithImpliedThisAndNoReceiver(
|
||||
c.scope,
|
||||
callableDescriptorCollector.getNonExtensionsByName(c.scope.asJetScope(), c.name, createLookupLocation(c)),
|
||||
c.context.call
|
||||
)
|
||||
|
||||
if (members.isNotEmpty()) {
|
||||
val nonlocals = Lists.newArrayList<ResolutionCandidate<D>>()
|
||||
val locals = Lists.newArrayList<ResolutionCandidate<D>>()
|
||||
splitLexicallyLocalDescriptors(members, c.scope.ownerDescriptor, locals, nonlocals)
|
||||
|
||||
localsList.add(locals)
|
||||
nonlocalsList.add(nonlocals)
|
||||
}
|
||||
}
|
||||
val lookupLocation = createLookupLocation(c)
|
||||
|
||||
//locals
|
||||
c.result.addCandidates(localsList)
|
||||
c.callableDescriptorCollectors.forEach {
|
||||
c.result.addCandidates {
|
||||
convertWithImpliedThisAndNoReceiver(
|
||||
c.scope,
|
||||
it.getLocalNonExtensionsByName(c.scope, c.name, lookupLocation),
|
||||
c.context.call
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val implicitReceiversWithTypes = implicitReceivers.map { ReceiverWithTypes(it, c.context) }
|
||||
|
||||
@@ -295,7 +269,13 @@ public class TaskPrioritizer(
|
||||
}
|
||||
|
||||
//nonlocals
|
||||
c.result.addCandidates(nonlocalsList)
|
||||
c.callableDescriptorCollectors.forEach {
|
||||
c.result.addCandidates {
|
||||
val descriptors = it.getNonExtensionsByName(c.scope.asJetScope(), c.name, lookupLocation)
|
||||
.filter { !ExpressionTypingUtils.isLocal(c.scope.ownerDescriptor, it) }
|
||||
convertWithImpliedThisAndNoReceiver(c.scope, descriptors, c.context.call)
|
||||
}
|
||||
}
|
||||
|
||||
//static (only for better error reporting)
|
||||
for (implicitReceiver in implicitReceiversWithTypes) {
|
||||
|
||||
@@ -266,7 +266,7 @@ private inline fun <T: Any> LexicalScope.collectFromMeAndParent(
|
||||
return result ?: emptyList()
|
||||
}
|
||||
|
||||
private inline fun <T: Any> LexicalScope.collectAllFromMeAndParent(
|
||||
internal inline fun <T: Any> LexicalScope.collectAllFromMeAndParent(
|
||||
collect: (LexicalScope) -> Collection<T>
|
||||
): Collection<T> {
|
||||
var result: Collection<T>? = null
|
||||
|
||||
@@ -7,20 +7,20 @@ import bar.*
|
||||
var b = ""
|
||||
|
||||
val c: /*c:foo.A c:foo.A.Companion p:foo*/String
|
||||
get() = /*p:foo p:bar c:foo.A c:foo.A.Companion*/b
|
||||
get() = /*c:foo.A*/b
|
||||
|
||||
var d: /*c:foo.A c:foo.A.Companion p:foo*/String = "ddd"
|
||||
get() = /*p:foo p:bar c:foo.A c:foo.A.Companion*/$d
|
||||
set(v) { /*p:foo p:bar c:foo.A c:foo.A.Companion*/$d = v }
|
||||
get() = /*c:foo.A*/$d
|
||||
set(v) { /*c:foo.A*/$d = v }
|
||||
|
||||
fun foo() {
|
||||
/*p:foo p:bar c:foo.A c:foo.A.Companion*/a
|
||||
/*p:foo p:bar c:foo.A c:foo.A.Companion*/foo()
|
||||
/*c:foo.A*/a
|
||||
/*c:foo.A*/foo()
|
||||
this./*c:foo.A*/a
|
||||
this./*c:foo.A*/foo()
|
||||
/*p:foo p:bar c:foo.A c:foo.A.Companion*/baz()
|
||||
/*p:foo p:bar c:foo.A c:foo.A.Companion*/Companion./*c:foo.A.Companion*/a
|
||||
/*p:foo p:bar c:foo.A c:foo.A.Companion*/O./*c:foo.A.O*/v = "OK"
|
||||
/*c:foo.A c:foo.A.Companion p:foo p:bar*/baz()
|
||||
/*c:foo.A c:foo.A.Companion p:foo p:bar*/Companion./*c:foo.A.Companion*/a
|
||||
/*c:foo.A c:foo.A.Companion p:foo p:bar*/O./*c:foo.A.O*/v = "OK"
|
||||
}
|
||||
|
||||
class B {
|
||||
@@ -59,10 +59,10 @@ import bar.*
|
||||
|
||||
val a = 1
|
||||
fun foo() {
|
||||
/*p:foo p:bar c:foo.E*/a
|
||||
/*p:foo p:bar c:foo.E*/Y./*c:foo.E*/a
|
||||
/*p:foo p:bar c:foo.E*/foo()
|
||||
/*p:foo p:bar c:foo.E*/X./*c:foo.E*/foo()
|
||||
/*c:foo.E*/a
|
||||
/*c:foo.E p:foo p:bar*/Y./*c:foo.E*/a
|
||||
/*c:foo.E*/foo()
|
||||
/*c:foo.E p:foo p:bar*/X./*c:foo.E*/foo()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import bar.*
|
||||
val a = 1
|
||||
val b = a
|
||||
fun localFun() = b
|
||||
fun /*p:local.declarations*/Int.localExtFun() = /*p:local.declarations p:bar*/localFun()
|
||||
fun /*p:local.declarations*/Int.localExtFun() = localFun()
|
||||
|
||||
interface LocalI {
|
||||
var a: /*p:local.declarations*/Int
|
||||
@@ -30,10 +30,10 @@ import bar.*
|
||||
fun foo(): LocalI = null as LocalI
|
||||
}
|
||||
|
||||
/*p:local.declarations p:bar*/localFun()
|
||||
localFun()
|
||||
1./*p:local.declarations p:bar*/localExtFun()
|
||||
|
||||
val c = /*p:local.declarations p:bar*/LocalC()
|
||||
val c = LocalC()
|
||||
c.a
|
||||
c.b
|
||||
c.foo()
|
||||
|
||||
@@ -12,6 +12,6 @@ import baz./*p:baz*/C
|
||||
}
|
||||
|
||||
/*p:foo*/fun /*p:foo*/MyClass.extFunc(p: /**p:foo p:bar*//*p:foo*/Array</*p:foo p:bar*/B>, e: /*p:foo*/MyEnum, c: /**???*/C): /*p:foo*/MyInterface {
|
||||
/*p:foo p:bar c:foo.MyClass*/b
|
||||
return /*p:foo p:bar c:foo.MyClass*/MyClass()
|
||||
/*c:foo.MyClass p:foo p:bar*/b
|
||||
return /*c:foo.MyClass p:foo p:bar*/MyClass()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user