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:
Pavel V. Talanov
2015-02-18 19:22:25 +03:00
parent 86bbb117ef
commit ffabe19229
25 changed files with 480 additions and 44 deletions
@@ -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))
}