Optimized task creation for local functions and variables

This commit is contained in:
Stanislav Erokhin
2015-09-02 16:23:06 +03:00
parent d3df04036e
commit 68389d34e4
7 changed files with 69 additions and 64 deletions
@@ -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()
}