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.calls.util.FakeCallableDescriptorForObject
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassObjectType
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassObjectType
|
||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
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.ErrorUtils
|
||||||
import org.jetbrains.kotlin.types.JetType
|
import org.jetbrains.kotlin.types.JetType
|
||||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||||
@@ -34,6 +37,8 @@ import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
|||||||
|
|
||||||
public interface CallableDescriptorCollector<D : CallableDescriptor> {
|
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 getNonExtensionsByName(scope: JetScope, name: Name, location: LookupLocation): Collection<D>
|
||||||
|
|
||||||
public fun getMembersByName(receiver: JetType, 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) })
|
CallableDescriptorCollectors(this.collectors.map { it.filtered(filter) })
|
||||||
|
|
||||||
private object FunctionCollector : CallableDescriptorCollector<FunctionDescriptor> {
|
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> {
|
override fun getNonExtensionsByName(scope: JetScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
|
||||||
return scope.getFunctions(name, location).filter { it.extensionReceiverParameter == null } + getConstructors(scope, name, location)
|
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 }
|
filterClassPredicate: (ClassDescriptor) -> Boolean = { true }
|
||||||
): Collection<FunctionDescriptor> {
|
): Collection<FunctionDescriptor> {
|
||||||
val classifier = scope.getClassifier(name, location)
|
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)
|
if (classifier !is ClassDescriptor || ErrorUtils.isError(classifier) || !filterClassPredicate(classifier)
|
||||||
// Constructors of singletons shouldn't be callable from the code
|
// Constructors of singletons shouldn't be callable from the code
|
||||||
|| classifier.kind.isSingleton) {
|
|| classifier.kind.isSingleton) {
|
||||||
@@ -129,6 +152,9 @@ private object FunctionCollector : CallableDescriptorCollector<FunctionDescripto
|
|||||||
}
|
}
|
||||||
|
|
||||||
private object VariableCollector : CallableDescriptorCollector<VariableDescriptor> {
|
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? {
|
private fun getFakeDescriptorForObject(scope: JetScope, name: Name, location: LookupLocation): VariableDescriptor? {
|
||||||
val classifier = scope.getClassifier(name, location)
|
val classifier = scope.getClassifier(name, location)
|
||||||
@@ -172,6 +198,10 @@ private object PropertyCollector : CallableDescriptorCollector<VariableDescripto
|
|||||||
private fun filterProperties(variableDescriptors: Collection<VariableDescriptor>) =
|
private fun filterProperties(variableDescriptors: Collection<VariableDescriptor>) =
|
||||||
variableDescriptors.filter { it is PropertyDescriptor }
|
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> {
|
override fun getNonExtensionsByName(scope: JetScope, name: Name, location: LookupLocation): Collection<VariableDescriptor> {
|
||||||
return filterProperties(VARIABLES_COLLECTOR.getNonExtensionsByName(scope, name, location))
|
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> {
|
private fun <D : CallableDescriptor> CallableDescriptorCollector<D>.filtered(filter: (D) -> Boolean): CallableDescriptorCollector<D> {
|
||||||
val delegate = this
|
val delegate = this
|
||||||
return object : CallableDescriptorCollector<D> {
|
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> {
|
override fun getNonExtensionsByName(scope: JetScope, name: Name, location: LookupLocation): Collection<D> {
|
||||||
return delegate.getNonExtensionsByName(scope, name, location).filter(filter)
|
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() })
|
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() {
|
private fun assertNotFinished() {
|
||||||
assert(internalTasks == null, "Can't add candidates after the resulting tasks were computed.")
|
assert(internalTasks == null, "Can't add candidates after the resulting tasks were computed.")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,22 +56,6 @@ public class TaskPrioritizer(
|
|||||||
private val smartCastManager: SmartCastManager
|
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(
|
public fun <D : CallableDescriptor, F : D> computePrioritizedTasks(
|
||||||
context: BasicCallResolutionContext,
|
context: BasicCallResolutionContext,
|
||||||
name: Name,
|
name: Name,
|
||||||
@@ -264,28 +248,18 @@ public class TaskPrioritizer(
|
|||||||
implicitReceivers: Collection<ReceiverValue>,
|
implicitReceivers: Collection<ReceiverValue>,
|
||||||
c: TaskPrioritizerContext<D, F>
|
c: TaskPrioritizerContext<D, F>
|
||||||
) {
|
) {
|
||||||
val localsList = Lists.newArrayList<Collection<ResolutionCandidate<D>>>()
|
val lookupLocation = createLookupLocation(c)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//locals
|
//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) }
|
val implicitReceiversWithTypes = implicitReceivers.map { ReceiverWithTypes(it, c.context) }
|
||||||
|
|
||||||
@@ -295,7 +269,13 @@ public class TaskPrioritizer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
//nonlocals
|
//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)
|
//static (only for better error reporting)
|
||||||
for (implicitReceiver in implicitReceiversWithTypes) {
|
for (implicitReceiver in implicitReceiversWithTypes) {
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ private inline fun <T: Any> LexicalScope.collectFromMeAndParent(
|
|||||||
return result ?: emptyList()
|
return result ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <T: Any> LexicalScope.collectAllFromMeAndParent(
|
internal inline fun <T: Any> LexicalScope.collectAllFromMeAndParent(
|
||||||
collect: (LexicalScope) -> Collection<T>
|
collect: (LexicalScope) -> Collection<T>
|
||||||
): Collection<T> {
|
): Collection<T> {
|
||||||
var result: Collection<T>? = null
|
var result: Collection<T>? = null
|
||||||
|
|||||||
@@ -7,20 +7,20 @@ import bar.*
|
|||||||
var b = ""
|
var b = ""
|
||||||
|
|
||||||
val c: /*c:foo.A c:foo.A.Companion p:foo*/String
|
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"
|
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
|
get() = /*c:foo.A*/$d
|
||||||
set(v) { /*p:foo p:bar c:foo.A c:foo.A.Companion*/$d = v }
|
set(v) { /*c:foo.A*/$d = v }
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
/*p:foo p:bar c:foo.A c:foo.A.Companion*/a
|
/*c:foo.A*/a
|
||||||
/*p:foo p:bar c:foo.A c:foo.A.Companion*/foo()
|
/*c:foo.A*/foo()
|
||||||
this./*c:foo.A*/a
|
this./*c:foo.A*/a
|
||||||
this./*c:foo.A*/foo()
|
this./*c:foo.A*/foo()
|
||||||
/*p:foo p:bar c:foo.A c:foo.A.Companion*/baz()
|
/*c:foo.A c:foo.A.Companion p:foo p:bar*/baz()
|
||||||
/*p:foo p:bar c:foo.A c:foo.A.Companion*/Companion./*c:foo.A.Companion*/a
|
/*c:foo.A c:foo.A.Companion p:foo p:bar*/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*/O./*c:foo.A.O*/v = "OK"
|
||||||
}
|
}
|
||||||
|
|
||||||
class B {
|
class B {
|
||||||
@@ -59,10 +59,10 @@ import bar.*
|
|||||||
|
|
||||||
val a = 1
|
val a = 1
|
||||||
fun foo() {
|
fun foo() {
|
||||||
/*p:foo p:bar c:foo.E*/a
|
/*c:foo.E*/a
|
||||||
/*p:foo p:bar c:foo.E*/Y./*c:foo.E*/a
|
/*c:foo.E p:foo p:bar*/Y./*c:foo.E*/a
|
||||||
/*p:foo p:bar c:foo.E*/foo()
|
/*c:foo.E*/foo()
|
||||||
/*p:foo p:bar c:foo.E*/X./*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 a = 1
|
||||||
val b = a
|
val b = a
|
||||||
fun localFun() = b
|
fun localFun() = b
|
||||||
fun /*p:local.declarations*/Int.localExtFun() = /*p:local.declarations p:bar*/localFun()
|
fun /*p:local.declarations*/Int.localExtFun() = localFun()
|
||||||
|
|
||||||
interface LocalI {
|
interface LocalI {
|
||||||
var a: /*p:local.declarations*/Int
|
var a: /*p:local.declarations*/Int
|
||||||
@@ -30,10 +30,10 @@ import bar.*
|
|||||||
fun foo(): LocalI = null as LocalI
|
fun foo(): LocalI = null as LocalI
|
||||||
}
|
}
|
||||||
|
|
||||||
/*p:local.declarations p:bar*/localFun()
|
localFun()
|
||||||
1./*p:local.declarations p:bar*/localExtFun()
|
1./*p:local.declarations p:bar*/localExtFun()
|
||||||
|
|
||||||
val c = /*p:local.declarations p:bar*/LocalC()
|
val c = LocalC()
|
||||||
c.a
|
c.a
|
||||||
c.b
|
c.b
|
||||||
c.foo()
|
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*/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
|
/*c:foo.MyClass p:foo p:bar*/b
|
||||||
return /*p:foo p:bar c:foo.MyClass*/MyClass()
|
return /*c:foo.MyClass p:foo p:bar*/MyClass()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user