Rewrite TowerLevels.

This commit is contained in:
Stanislav Erokhin
2015-12-04 21:28:11 +03:00
parent 11c86405bf
commit 75245b3046
5 changed files with 107 additions and 144 deletions
@@ -62,9 +62,8 @@ internal class ExplicitReceiverScopeTowerProcessor<C>(
}
private fun resolveAsMember(): Collection<C> {
val members = ReceiverScopeTowerLevel(context.scopeTower, explicitReceiver).collectCandidates(name).filter { candidate ->
candidate.dispatchReceiver != null && !candidate.requiresExtensionReceiver
}
val members = ReceiverScopeTowerLevel(context.scopeTower, explicitReceiver)
.collectCandidates(name).filter { !it.requiresExtensionReceiver }
return members.map { context.createCandidate(it, ExplicitReceiverKind.DISPATCH_RECEIVER, extensionReceiver = null) }
}
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isDynamic
import org.jetbrains.kotlin.types.typeUtil.getImmediateSuperclassNotAny
import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.*
@@ -64,95 +65,32 @@ internal abstract class AbstractScopeTowerLevel(
}
// todo create error for constructors call and for implicit receiver
// todo KT-9538 Unresolved inner class via subclass reference
// todo Future plan: move constructors and fake variables for objects to class member scope.
internal abstract class ConstructorsAndFakeVariableHackLevelScope(scopeTower: ScopeTower) : AbstractScopeTowerLevel(scopeTower) {
protected fun createConstructors(
classifier: ClassifierDescriptor?,
dispatchReceiver: ReceiverValue?,
dispatchReceiverSmartCastType: KotlinType? = null,
checkClass: (ClassDescriptor) -> ResolutionDiagnostic? = { null }
): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
val classDescriptor = getClassWithConstructors(classifier) ?: return emptyList()
val specialError = checkClass(classDescriptor)
return classDescriptor.constructors.map {
val dispatchReceiverHack = if (dispatchReceiver == null && it.dispatchReceiverParameter != null) {
it.dispatchReceiverParameter?.value // todo this is hack for Scope Level
}
else if (dispatchReceiver != null && it.dispatchReceiverParameter == null) { // should be reported error
null
}
else {
dispatchReceiver
}
createCandidateDescriptor(it, dispatchReceiverHack, specialError, dispatchReceiverSmartCastType)
}
}
protected fun createVariableDescriptor(
classifier: ClassifierDescriptor?,
dispatchReceiverSmartCastType: KotlinType? = null,
checkClass: (ClassDescriptor) -> ResolutionDiagnostic? = { null }
): CandidateWithBoundDispatchReceiver<VariableDescriptor>? {
val fakeVariable = getFakeDescriptorForObject(classifier) ?: return null
return createCandidateDescriptor(fakeVariable, null, checkClass(fakeVariable.classDescriptor), dispatchReceiverSmartCastType)
}
private fun getClassWithConstructors(classifier: ClassifierDescriptor?): ClassDescriptor? {
if (classifier !is ClassDescriptor || ErrorUtils.isError(classifier)
// Constructors of singletons shouldn't be callable from the code
|| classifier.kind.isSingleton) {
return null
}
else {
return classifier
}
}
private fun getFakeDescriptorForObject(classifier: ClassifierDescriptor?): FakeCallableDescriptorForObject? {
if (classifier !is ClassDescriptor || !classifier.hasClassValueDescriptor) return null // todo
return FakeCallableDescriptorForObject(classifier)
}
}
// todo add static methods & fields with error
internal class ReceiverScopeTowerLevel(
scopeTower: ScopeTower,
val dispatchReceiver: ReceiverValue
): ConstructorsAndFakeVariableHackLevelScope(scopeTower) {
private val memberScope = dispatchReceiver.type.memberScope
): AbstractScopeTowerLevel(scopeTower) {
private fun <D: CallableDescriptor> collectMembers(
members: ResolutionScope.() -> Collection<D>,
additionalDescriptors: ResolutionScope.(smartCastType: KotlinType?) -> Collection<CandidateWithBoundDispatchReceiver<D>> // todo
getMembers: ResolutionScope.(KotlinType?) -> Collection<D>
): Collection<CandidateWithBoundDispatchReceiver<D>> {
val result = ArrayList<CandidateWithBoundDispatchReceiver<D>>(0)
memberScope.members().mapTo(result) {
dispatchReceiver.type.memberScope.getMembers(dispatchReceiver.type).mapTo(result) {
createCandidateDescriptor(it, dispatchReceiver)
}
result.addAll(memberScope.additionalDescriptors(null))
val smartCastPossibleTypes = scopeTower.dataFlowInfo.getSmartCastTypes(dispatchReceiver)
val unstableError = if (scopeTower.dataFlowInfo.isStableReceiver(dispatchReceiver)) null else UnstableSmartCastDiagnostic
for (possibleType in smartCastPossibleTypes) {
possibleType.memberScope.members().mapTo(result) {
possibleType.memberScope.getMembers(possibleType).mapTo(result) {
createCandidateDescriptor(it, dispatchReceiver, unstableError, dispatchReceiverSmartCastType = possibleType)
}
possibleType.memberScope.additionalDescriptors(possibleType).mapTo(result) {
it.addDiagnostic(unstableError)
}
}
if (dispatchReceiver.type.isDynamic()) {
scopeTower.dynamicScope.members().mapTo(result) {
scopeTower.dynamicScope.getMembers(null).mapTo(result) {
createCandidateDescriptor(it, dispatchReceiver, DynamicDescriptorDiagnostic)
}
}
@@ -160,79 +98,46 @@ internal class ReceiverScopeTowerLevel(
return result
}
// todo add static methods & fields with error
override fun getVariables(name: Name): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
return collectMembers({ getContributedVariables(name, location) }) {
smartCastType ->
listOfNotNull(createVariableDescriptor(getContributedClassifier(name, location), smartCastType){ NestedClassViaInstanceReference(it) } )
}
return collectMembers { getContributedVariables(name, location) }
}
override fun getFunctions(name: Name): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
return collectMembers({ getContributedFunctions(name, location) }) {
smartCastType ->
createConstructors(getContributedClassifier(name, location), dispatchReceiver, smartCastType) {
if (it.isInner) null else NestedClassViaInstanceReference(it)
return collectMembers {
getContributedFunctions(name, location) + it.getInnerConstructors(name, location)
}
}
}
internal class QualifierScopeTowerLevel(scopeTower: ScopeTower, val qualifier: QualifierReceiver) : AbstractScopeTowerLevel(scopeTower) {
override fun getVariables(name: Name) = qualifier.getNestedClassesAndPackageMembersScope()
.getContributedVariablesAndObjects(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
override fun getFunctions(name: Name) = qualifier.getNestedClassesAndPackageMembersScope()
.getContributedFunctionsAndConstructors(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
}
}
}
internal class QualifierScopeTowerLevel(scopeTower: ScopeTower, qualifier: QualifierReceiver) : ConstructorsAndFakeVariableHackLevelScope(scopeTower) {
private val qualifierScope = qualifier.getNestedClassesAndPackageMembersScope()
override fun getVariables(name: Name): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
val result = ArrayList<CandidateWithBoundDispatchReceiver<VariableDescriptor>>(0)
qualifierScope.getContributedVariables(name, location).mapTo(result) {
createCandidateDescriptor(it, dispatchReceiver = null)
}
result.addIfNotNull(createVariableDescriptor(qualifierScope.getContributedClassifier(name, location)))
return result
}
override fun getFunctions(name: Name): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
val functions = qualifierScope.getContributedFunctions(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
val constructors = createConstructors(qualifierScope.getContributedClassifier(name, location), dispatchReceiver = null) {
if (it.isInner) InnerClassViaStaticReference(it) else null
}
return functions + constructors
}
}
// KT-3335 Creating imported super class' inner class fails in codegen
internal open class ScopeBasedTowerLevel protected constructor(
scopeTower: ScopeTower,
private val resolutionScope: ResolutionScope
) : ConstructorsAndFakeVariableHackLevelScope(scopeTower) {
) : AbstractScopeTowerLevel(scopeTower) {
internal constructor(scopeTower: ScopeTower, lexicalScope: LexicalScope): this(scopeTower, lexicalScope as ResolutionScope)
override fun getVariables(name: Name): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
val result = ArrayList<CandidateWithBoundDispatchReceiver<VariableDescriptor>>(0)
resolutionScope.getContributedVariables(name, location).mapTo(result) {
createCandidateDescriptor(it, dispatchReceiver = null)
}
result.addIfNotNull(createVariableDescriptor(resolutionScope.getContributedClassifier(name, location)))
return result
}
override fun getVariables(name: Name): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>>
= resolutionScope.getContributedVariablesAndObjects(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
override fun getFunctions(name: Name): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
val result = ArrayList<CandidateWithBoundDispatchReceiver<FunctionDescriptor>>(0)
resolutionScope.getContributedFunctions(name, location).mapTo(result) {
createCandidateDescriptor(it, dispatchReceiver = null)
}
// todo report errors for constructors if there is no match receiver
result.addAll(createConstructors(resolutionScope.getContributedClassifier(name, location), dispatchReceiver = null) {
if (!it.isInner) return@createConstructors null
// todo add constructors functions to member class member scope
// KT-3335 Creating imported super class' inner class fails in codegen
UnsupportedInnerClassCall("Constructor call for inner class from subclass unsupported")
})
return result
}
override fun getFunctions(name: Name): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>>
= resolutionScope.getContributedFunctionsAndConstructors(name, location).map {
createCandidateDescriptor(it, dispatchReceiver = null)
}
}
internal class ImportingScopeBasedTowerLevel(
@@ -254,4 +159,48 @@ internal class ImportingScopeBasedTowerLevel(
}
return super.getFunctions(name) + synthetic
}
}
private fun KotlinType.getClassifierFromMeAndSuperclasses(name: Name, location: LookupLocation): ClassifierDescriptor? {
var superclass: KotlinType? = this
while (superclass != null) {
superclass.memberScope.getContributedClassifier(name, location)?.let { return it }
superclass = superclass.getImmediateSuperclassNotAny()
}
return null
}
private fun KotlinType?.getInnerConstructors(name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
val classifierDescriptor = getClassWithConstructors(this?.getClassifierFromMeAndSuperclasses(name, location))
return classifierDescriptor?.constructors?.filter { it.dispatchReceiverParameter != null } ?: emptyList()
}
private fun ResolutionScope.getContributedFunctionsAndConstructors(name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
val classWithConstructors = getClassWithConstructors(getContributedClassifier(name, location))
return getContributedFunctions(name, location) +
(classWithConstructors?.constructors?.filter { it.dispatchReceiverParameter == null } ?: emptyList())
}
private fun ResolutionScope.getContributedVariablesAndObjects(name: Name, location: LookupLocation): Collection<VariableDescriptor> {
val objectDescriptor = getFakeDescriptorForObject(getContributedClassifier(name, location))
return getContributedVariables(name, location) + listOfNotNull(objectDescriptor)
}
private fun getFakeDescriptorForObject(classifier: ClassifierDescriptor?): FakeCallableDescriptorForObject? {
if (classifier !is ClassDescriptor || !classifier.hasClassValueDescriptor) return null // todo
return FakeCallableDescriptorForObject(classifier)
}
private fun getClassWithConstructors(classifier: ClassifierDescriptor?): ClassDescriptor? {
if (classifier !is ClassDescriptor || ErrorUtils.isError(classifier)
// Constructors of singletons shouldn't be callable from the code
|| classifier.kind.isSingleton) {
return null
}
else {
return classifier
}
}
@@ -23,12 +23,6 @@ import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
internal fun <D : CallableDescriptor> CandidateWithBoundDispatchReceiver<D>.addDiagnostic(error: ResolutionDiagnostic?): CandidateWithBoundDispatchReceiver<D> {
if (error == null) return this
return CandidateWithBoundDispatchReceiverImpl(dispatchReceiver, descriptor, diagnostics + error)
}
@Deprecated("Temporary error")
internal class PreviousResolutionError(candidateLevel: ResolutionCandidateApplicability): ResolutionDiagnostic(candidateLevel)
@@ -258,19 +258,31 @@ public class TypeUtils {
@NotNull
public static List<KotlinType> getImmediateSupertypes(@NotNull KotlinType type) {
boolean isNullable = type.isMarkedNullable();
TypeSubstitutor substitutor = TypeSubstitutor.create(type);
Collection<KotlinType> originalSupertypes = type.getConstructor().getSupertypes();
List<KotlinType> result = new ArrayList<KotlinType>(originalSupertypes.size());
for (KotlinType supertype : originalSupertypes) {
KotlinType substitutedType = substitutor.substitute(supertype, Variance.INVARIANT);
KotlinType substitutedType = createSubstitutedSupertype(type, supertype, substitutor);
if (substitutedType != null) {
result.add(makeNullableIfNeeded(substitutedType, isNullable));
result.add(substitutedType);
}
}
return result;
}
@Nullable
public static KotlinType createSubstitutedSupertype(
@NotNull KotlinType subType,
@NotNull KotlinType superType,
@NotNull TypeSubstitutor substitutor
) {
KotlinType substitutedType = substitutor.substitute(superType, Variance.INVARIANT);
if (substitutedType != null) {
return makeNullableIfNeeded(substitutedType, subType.isMarkedNullable());
}
return null;
}
private static void collectAllSupertypes(@NotNull KotlinType type, @NotNull Set<KotlinType> result) {
List<KotlinType> immediateSupertypes = getImmediateSupertypes(type);
result.addAll(immediateSupertypes);
@@ -17,11 +17,9 @@
package org.jetbrains.kotlin.types.typeUtil
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.utils.toReadOnlyList
@@ -162,3 +160,14 @@ private fun constituentTypes(result: MutableSet<KotlinType>, types: Collection<K
}
}
}
fun KotlinType.getImmediateSuperclassNotAny(): KotlinType? {
val superclasses = constructor.supertypes.filter {
val descriptor = it.constructor.declarationDescriptor
(DescriptorUtils.isClass(descriptor) || DescriptorUtils.isEnumClass(descriptor)) &&
!KotlinBuiltIns.isAnyOrNullableAny(it)
}
return superclasses.singleOrNull()?.let {
TypeUtils.createSubstitutedSupertype(this, it, TypeSubstitutor.create(this))
}
}