Prohibit accessing nested classes/objects of class object using class literal
The fqname of class should be clear from code Example: can't shorten A.Default.B.Default.C to A.B.C Also fixes problem when nested class of enum class could be accessed via enum entry
This commit is contained in:
+12
-7
@@ -43,22 +43,27 @@ private val FUNCTIONS_COLLECTOR = FunctionCollector.withDefaultFilter()
|
||||
private val VARIABLES_COLLECTOR = VariableCollector.withDefaultFilter()
|
||||
private val PROPERTIES_COLLECTOR = PropertyCollector.withDefaultFilter()
|
||||
|
||||
public class CallableDescriptorCollectors<D : CallableDescriptor>(vararg collectors: CallableDescriptorCollector<D>) : Iterable<CallableDescriptorCollector<D>> {
|
||||
private val collectors = collectors.toList()
|
||||
public class CallableDescriptorCollectors<D : CallableDescriptor>(val collectors: List<CallableDescriptorCollector<D>>) :
|
||||
Iterable<CallableDescriptorCollector<D>> {
|
||||
override fun iterator(): Iterator<CallableDescriptorCollector<D>> = collectors.iterator()
|
||||
|
||||
[suppress("UNCHECKED_CAST")]
|
||||
class object {
|
||||
public val FUNCTIONS_AND_VARIABLES: CallableDescriptorCollectors<CallableDescriptor> =
|
||||
CallableDescriptorCollectors(FUNCTIONS_COLLECTOR as CallableDescriptorCollector<CallableDescriptor>,
|
||||
VARIABLES_COLLECTOR as CallableDescriptorCollector<CallableDescriptor>)
|
||||
CallableDescriptorCollectors(listOf(
|
||||
FUNCTIONS_COLLECTOR as CallableDescriptorCollector<CallableDescriptor>,
|
||||
VARIABLES_COLLECTOR as CallableDescriptorCollector<CallableDescriptor>
|
||||
))
|
||||
public val FUNCTIONS: CallableDescriptorCollectors<CallableDescriptor> =
|
||||
CallableDescriptorCollectors(FUNCTIONS_COLLECTOR as CallableDescriptorCollector<CallableDescriptor>)
|
||||
public val VARIABLES: CallableDescriptorCollectors<VariableDescriptor> = CallableDescriptorCollectors(VARIABLES_COLLECTOR)
|
||||
public val PROPERTIES: CallableDescriptorCollectors<VariableDescriptor> = CallableDescriptorCollectors(PROPERTIES_COLLECTOR)
|
||||
CallableDescriptorCollectors(listOf(FUNCTIONS_COLLECTOR as CallableDescriptorCollector<CallableDescriptor>))
|
||||
public val VARIABLES: CallableDescriptorCollectors<VariableDescriptor> = CallableDescriptorCollectors(listOf(VARIABLES_COLLECTOR))
|
||||
public val PROPERTIES: CallableDescriptorCollectors<VariableDescriptor> = CallableDescriptorCollectors(listOf(PROPERTIES_COLLECTOR))
|
||||
}
|
||||
}
|
||||
|
||||
public fun <D : CallableDescriptor> CallableDescriptorCollectors<D>.filtered(filter: (D) -> Boolean): CallableDescriptorCollectors<D> =
|
||||
CallableDescriptorCollectors(this.collectors.map { it.filtered(filter) })
|
||||
|
||||
private object FunctionCollector : CallableDescriptorCollector<FunctionDescriptor> {
|
||||
|
||||
override fun getNonExtensionsByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection<FunctionDescriptor> {
|
||||
|
||||
@@ -23,8 +23,6 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.psi.Call
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.collectors.CallableDescriptorCollector
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.collectors.CallableDescriptorCollectors
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScopeUtils
|
||||
@@ -39,6 +37,9 @@ import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.CallResolverUtil.isOrOverridesSynthesized
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.util.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.collectors.*
|
||||
|
||||
public class TaskPrioritizer(private val storageManager: StorageManager) {
|
||||
|
||||
@@ -71,10 +72,7 @@ public class TaskPrioritizer(private val storageManager: StorageManager) {
|
||||
if (explicitReceiver is QualifierReceiver) {
|
||||
val qualifierReceiver = explicitReceiver : QualifierReceiver
|
||||
doComputeTasks(NO_RECEIVER, taskPrioritizerContext.replaceScope(qualifierReceiver.getNestedClassesAndPackageMembersScope()))
|
||||
val classObjectReceiver = qualifierReceiver.getClassObjectReceiver()
|
||||
if (classObjectReceiver.exists()) {
|
||||
doComputeTasks(classObjectReceiver, taskPrioritizerContext)
|
||||
}
|
||||
computeTasksForClassObjectReceiver(qualifierReceiver, taskPrioritizerContext)
|
||||
}
|
||||
else {
|
||||
doComputeTasks(explicitReceiver, taskPrioritizerContext)
|
||||
@@ -83,6 +81,30 @@ public class TaskPrioritizer(private val storageManager: StorageManager) {
|
||||
return result.getTasks()
|
||||
}
|
||||
|
||||
private fun <D : CallableDescriptor, F : D> computeTasksForClassObjectReceiver(
|
||||
qualifierReceiver: QualifierReceiver,
|
||||
taskPrioritizerContext: TaskPrioritizerContext<D, F>
|
||||
) {
|
||||
val classObjectReceiver = qualifierReceiver.getClassObjectReceiver()
|
||||
if (!classObjectReceiver.exists()) {
|
||||
return
|
||||
}
|
||||
val classifierDescriptor = qualifierReceiver.classifier
|
||||
doComputeTasks(classObjectReceiver, taskPrioritizerContext.filterCollectors {
|
||||
when {
|
||||
classifierDescriptor is ClassDescriptor && classifierDescriptor.getDefaultObjectDescriptor() != null -> {
|
||||
// nested classes and objects should not be accessible via short reference to default object
|
||||
it !is ConstructorDescriptor && it !is FakeCallableDescriptorForObject
|
||||
}
|
||||
classifierDescriptor != null && DescriptorUtils.isEnumEntry(classifierDescriptor) -> {
|
||||
// objects nested in enum should not be accessible via enum entries reference
|
||||
it !is FakeCallableDescriptorForObject
|
||||
}
|
||||
else -> true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun <D : CallableDescriptor, F : D> doComputeTasks(receiver: ReceiverValue, c: TaskPrioritizerContext<D, F>) {
|
||||
ProgressIndicatorProvider.checkCanceled()
|
||||
|
||||
@@ -428,5 +450,9 @@ public class TaskPrioritizer(private val storageManager: StorageManager) {
|
||||
fun replaceCollectors(newCollectors: CallableDescriptorCollectors<D>): TaskPrioritizerContext<D, F> {
|
||||
return TaskPrioritizerContext(name, result, context, scope, newCollectors)
|
||||
}
|
||||
|
||||
fun filterCollectors(filter: (D) -> Boolean): TaskPrioritizerContext<D, F> {
|
||||
return TaskPrioritizerContext(name, result, context, scope, callableDescriptorCollectors.filtered(filter))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,6 +252,6 @@ class CollectorForDynamicReceivers<D: CallableDescriptor>(val delegate: Callable
|
||||
}
|
||||
}
|
||||
|
||||
fun <D: CallableDescriptor> CallableDescriptorCollectors<D>.onlyDynamicReceivers(): CallableDescriptorCollectors<D> {
|
||||
return CallableDescriptorCollectors(* this.map { CollectorForDynamicReceivers(it) }.copyToArray())
|
||||
fun <D : CallableDescriptor> CallableDescriptorCollectors<D>.onlyDynamicReceivers(): CallableDescriptorCollectors<D> {
|
||||
return CallableDescriptorCollectors(this.map { CollectorForDynamicReceivers(it) })
|
||||
}
|
||||
|
||||
@@ -18,12 +18,10 @@ package org.jetbrains.kotlin.resolve.scopes.receivers
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.getFqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.ChainedScope
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.*
|
||||
@@ -35,6 +33,7 @@ import org.jetbrains.kotlin.psi.JetExpression
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.recordScopeAndDataFlowInfo
|
||||
import kotlin.properties.Delegates
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classObjectDescriptor
|
||||
import org.jetbrains.kotlin.resolve.scopes.*
|
||||
|
||||
public trait Qualifier: ReceiverValue {
|
||||
|
||||
@@ -67,7 +66,10 @@ class QualifierReceiver (
|
||||
override var resultingDescriptor: DeclarationDescriptor by Delegates.notNull()
|
||||
|
||||
override val scope: JetScope get() {
|
||||
val scopes = listOf(classifier?.getClassObjectType()?.getMemberScope(), getNestedClassesAndPackageMembersScope()).filterNotNull().copyToArray()
|
||||
val classObjectTypeScope = classifier?.getClassObjectType()?.getMemberScope()?.let {
|
||||
FilteringScope(it) { it !is ClassDescriptor }
|
||||
}
|
||||
val scopes = listOf(classObjectTypeScope, getNestedClassesAndPackageMembersScope()).filterNotNull().copyToArray()
|
||||
return ChainedScope(descriptor, "Member scope for " + name + " as package or class or object", *scopes)
|
||||
}
|
||||
|
||||
@@ -82,12 +84,6 @@ class QualifierReceiver (
|
||||
if (classifier is ClassDescriptor) {
|
||||
scopes.add(classifier.getStaticScope())
|
||||
|
||||
val classObjectDescriptor = classifier.getDefaultObjectDescriptor()
|
||||
if (classObjectDescriptor != null) {
|
||||
// non-static members are resolved through class object receiver
|
||||
scopes.add(DescriptorUtils.getStaticNestedClassesScope(classObjectDescriptor))
|
||||
}
|
||||
|
||||
if (classifier.getKind() != ClassKind.ENUM_ENTRY) {
|
||||
scopes.add(DescriptorUtils.getStaticNestedClassesScope(classifier))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user