diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt index 949459ef0f5..07b453ca7a8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt @@ -23,16 +23,16 @@ import org.jetbrains.kotlin.incremental.KotlinLookupLocation import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.descriptorUtil.classObjectType +import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassObjectType import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.scopes.ImportingScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope -import org.jetbrains.kotlin.resolve.scopes.receivers.ClassifierQualifier -import org.jetbrains.kotlin.resolve.scopes.receivers.PackageQualifier -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue -import org.jetbrains.kotlin.resolve.scopes.receivers.createClassifierQualifier +import org.jetbrains.kotlin.resolve.scopes.receivers.* import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator +import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addToStdlib.check @@ -464,6 +464,94 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa } return Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, descriptor, shouldBeVisibleFrom) } + + public fun resolveAsReceiverInQualifiedExpression( + qualifier: QualifierReceiver, + context: ExpressionTypingContext, + selector: DeclarationDescriptor? + ) { + resolveAndRecordReferenceTarget(qualifier, context, selector) + + if (qualifier is ClassifierQualifier) { + val classifier = qualifier.classifier + if (classifier is TypeParameterDescriptor) { + context.trace.report(Errors.TYPE_PARAMETER_ON_LHS_OF_DOT.on(qualifier.referenceExpression, classifier)) + } + else if (classifier is ClassDescriptor && classifier.hasClassObjectType) { + context.trace.recordType(qualifier.expression, classifier.classObjectType) + } + } + } + + public fun resolveAsStandaloneExpression(qualifier: QualifierReceiver, context: ExpressionTypingContext) { + resolveAndRecordReferenceTarget(qualifier, context, selector = null) + + if (qualifier is ClassifierQualifier) { + val classifier = qualifier.classifier + if (classifier is TypeParameterDescriptor) { + context.trace.report(Errors.TYPE_PARAMETER_IS_NOT_AN_EXPRESSION.on(qualifier.referenceExpression, classifier)) + } + else if (classifier is ClassDescriptor && !classifier.hasClassObjectType) { + context.trace.report(Errors.NO_COMPANION_OBJECT.on(qualifier.referenceExpression, classifier)) + } + } + else if (qualifier is PackageQualifier) { + context.trace.report(Errors.EXPRESSION_EXPECTED_PACKAGE_FOUND.on(qualifier.referenceExpression)) + } + } + + // TODO refactor + private fun resolveAndRecordReferenceTarget( + qualifier: QualifierReceiver, + context: ExpressionTypingContext, + selector: DeclarationDescriptor? + ) { + qualifier.resultingDescriptor = resolveReferenceTarget(qualifier, context, selector) + context.trace.record(BindingContext.REFERENCE_TARGET, qualifier.referenceExpression, qualifier.resultingDescriptor) + } + + // TODO refactor + private fun resolveReferenceTarget( + qualifier: QualifierReceiver, + context: ExpressionTypingContext, + selector: DeclarationDescriptor? + ): DeclarationDescriptor { + if (qualifier is ClassQualifier && qualifier.classifier is TypeParameterDescriptor) { + return qualifier.classifier + } + + val selectorContainer = when (selector) { + is ConstructorDescriptor -> selector.containingDeclaration.containingDeclaration + else -> selector?.containingDeclaration + } + + if (qualifier is PackageQualifier && + (selectorContainer is PackageFragmentDescriptor || selectorContainer is PackageViewDescriptor) && + DescriptorUtils.getFqName(qualifier.packageView) == DescriptorUtils.getFqName(selectorContainer) + ) { + return qualifier.packageView + } + + if (qualifier is ClassQualifier) { + symbolUsageValidator.validateTypeUsage(qualifier.classifier, context.trace, qualifier.referenceExpression) + + if (selector is CallableDescriptor && + (selector.dispatchReceiverParameter != null || selector.extensionReceiverParameter != null) && + qualifier.classifier is ClassDescriptor && + qualifier.classifier.hasClassObjectType + ) { + val companionObjectDescriptor = qualifier.classifier.companionObjectDescriptor + if (companionObjectDescriptor != null) { + context.trace.record(BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, qualifier.referenceExpression, qualifier.classifier) + symbolUsageValidator.validateTypeUsage(companionObjectDescriptor, context.trace, qualifier.referenceExpression) + return companionObjectDescriptor + } + } + } + + return qualifier.descriptor + } + } /* diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.java index 3f9c5f829dd..40ab7639a1f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.java @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.DescriptorUtils; +import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver; import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt; import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt; import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext; @@ -45,7 +46,6 @@ import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject; import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant; import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator; import org.jetbrains.kotlin.resolve.scopes.receivers.*; -import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator; import org.jetbrains.kotlin.types.ErrorUtils; import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.TypeUtils; @@ -66,24 +66,24 @@ import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE; public class CallExpressionResolver { - private final CallResolver callResolver; - private final ConstantExpressionEvaluator constantExpressionEvaluator; - private final SymbolUsageValidator symbolUsageValidator; - private final DataFlowAnalyzer dataFlowAnalyzer; + @NotNull private final CallResolver callResolver; + @NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator; + @NotNull private final DataFlowAnalyzer dataFlowAnalyzer; @NotNull private final KotlinBuiltIns builtIns; + @NotNull private final QualifiedExpressionResolver qualifiedExpressionResolver; public CallExpressionResolver( @NotNull CallResolver callResolver, @NotNull ConstantExpressionEvaluator constantExpressionEvaluator, - @NotNull SymbolUsageValidator symbolUsageValidator, @NotNull DataFlowAnalyzer dataFlowAnalyzer, - @NotNull KotlinBuiltIns builtIns + @NotNull KotlinBuiltIns builtIns, + @NotNull QualifiedExpressionResolver qualifiedExpressionResolver ) { this.callResolver = callResolver; this.constantExpressionEvaluator = constantExpressionEvaluator; - this.symbolUsageValidator = symbolUsageValidator; this.dataFlowAnalyzer = dataFlowAnalyzer; this.builtIns = builtIns; + this.qualifiedExpressionResolver = qualifiedExpressionResolver; } private ExpressionTypingServices expressionTypingServices; @@ -139,7 +139,7 @@ public class CallExpressionResolver { if (qualifier != null) { result[0] = true; if (!isLHSOfDot) { - QualifierKt.resolveAsStandaloneExpression(qualifier, context, symbolUsageValidator); + qualifiedExpressionResolver.resolveAsStandaloneExpression(qualifier, context); } return null; } @@ -211,7 +211,7 @@ public class CallExpressionResolver { * Determines the result type and data flow information after the call. */ @NotNull - public KotlinTypeInfo getCallExpressionTypeInfoWithoutFinalTypeCheck( + private KotlinTypeInfo getCallExpressionTypeInfoWithoutFinalTypeCheck( @NotNull KtCallExpression callExpression, @NotNull Receiver receiver, @Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context ) { @@ -275,7 +275,7 @@ public class CallExpressionResolver { KotlinType type = getVariableType((KtSimpleNameExpression) calleeExpression, receiver, callOperationNode, context.replaceTraceAndCache(temporaryForVariable), result); Qualifier qualifier = temporaryForVariable.trace.get(BindingContext.QUALIFIER, calleeExpression); - if (result[0] && (qualifier == null || qualifier.getPackageView() == null)) { + if (result[0] && (qualifier == null || !(qualifier instanceof PackageQualifier))) { temporaryForVariable.commit(); context.trace.report(FUNCTION_EXPECTED.on(calleeExpression, calleeExpression, type != null ? type : ErrorUtils.createErrorType(""))); @@ -423,7 +423,8 @@ public class CallExpressionResolver { DeclarationDescriptor selectorDescriptor = calleeExpression instanceof KtReferenceExpression ? context.trace.get(BindingContext.REFERENCE_TARGET, (KtReferenceExpression) calleeExpression) : null; - QualifierKt.resolveAsReceiverInQualifiedExpression(qualifierReceiver, context, symbolUsageValidator, selectorDescriptor); + + qualifiedExpressionResolver.resolveAsReceiverInQualifiedExpression(qualifierReceiver, context, selectorDescriptor); } private static void checkNestedClassAccess( @@ -440,10 +441,11 @@ public class CallExpressionResolver { Qualifier receiverQualifier = context.trace.get(BindingContext.QUALIFIER, expression.getReceiverExpression()); if (receiverQualifier == null && expressionQualifier != null) { - assert expressionQualifier.getClassifier() instanceof ClassDescriptor : + assert expressionQualifier instanceof ClassQualifier : "Only class can (package cannot) be accessed by instance reference: " + expressionQualifier; - context.trace.report(NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE - .on(selectorExpression, (ClassDescriptor) expressionQualifier.getClassifier())); + context.trace.report(NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE.on( + selectorExpression, + ((ClassQualifier) expressionQualifier).getClassifier())); } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/TaskPrioritizer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/TaskPrioritizer.kt index 4b00bd2ab21..d0098c012b6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/TaskPrioritizer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/TaskPrioritizer.kt @@ -37,11 +37,7 @@ import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution import org.jetbrains.kotlin.resolve.scopes.ImportingScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope -import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver -import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver -import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver -import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.kotlin.resolve.scopes.receivers.* import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope @@ -70,23 +66,23 @@ public class TaskPrioritizer( val result = ResolutionTaskHolder(storageManager, context, PriorityProviderImpl(context), tracing) val taskPrioritizerContext = TaskPrioritizerContext(name, result, context, context.scope, callableDescriptorCollectors) - if (explicitReceiver is QualifierReceiver) { - val qualifierReceiver: QualifierReceiver = explicitReceiver - val receiverScope = LexicalScope.empty(qualifierReceiver.getNestedClassesAndPackageMembersScope().memberScopeAsImportingScope(), - qualifierReceiver.descriptor) - doComputeTasks(NO_RECEIVER, taskPrioritizerContext.replaceScope(receiverScope)) - computeTasksForClassObjectReceiver(qualifierReceiver, taskPrioritizerContext) - } - else { - doComputeTasks(explicitReceiver, taskPrioritizerContext) + when (explicitReceiver) { + is QualifierReceiver -> { + val qualifierReceiver: QualifierReceiver = explicitReceiver + val receiverScope = qualifierReceiver.getNestedClassesAndPackageMembersScope().memberScopeAsImportingScope() + doComputeTasks(NO_RECEIVER, taskPrioritizerContext.replaceScope(receiverScope)) + computeTasksForClassObjectReceiver(qualifierReceiver, taskPrioritizerContext) + } + is ReceiverValue -> { + doComputeTasks(explicitReceiver, taskPrioritizerContext) - // Temporary fix for code migration (unaryPlus()/unaryMinus()) - val unaryConventionName = getUnaryPlusOrMinusOperatorFunctionName(context.call) - if (unaryConventionName != null) { - val deprecatedName = if (name == OperatorNameConventions.UNARY_PLUS) - OperatorNameConventions.PLUS - else - OperatorNameConventions.MINUS + // Temporary fix for code migration (unaryPlus()/unaryMinus()) + val unaryConventionName = getUnaryPlusOrMinusOperatorFunctionName(context.call) + if (unaryConventionName != null) { + val deprecatedName = if (name == OperatorNameConventions.UNARY_PLUS) + OperatorNameConventions.PLUS + else + OperatorNameConventions.MINUS val additionalContext = TaskPrioritizerContext(deprecatedName, result, context, context.scope, callableDescriptorCollectors) doComputeTasks(explicitReceiver, additionalContext) @@ -98,24 +94,26 @@ public class TaskPrioritizer( } private fun computeTasksForClassObjectReceiver( - qualifierReceiver: QualifierReceiver, + qualifier: Qualifier, taskPrioritizerContext: TaskPrioritizerContext ) { - val companionObject = qualifierReceiver.companionObjectReceiver ?: return - val classifierDescriptor = qualifierReceiver.classifier - doComputeTasks(companionObject, taskPrioritizerContext.filterCollectors { - when { - classifierDescriptor is ClassDescriptor && classifierDescriptor.getCompanionObjectDescriptor() != null -> { - // nested classes and objects should not be accessible via short reference to companion object - it !is ConstructorDescriptor && it !is FakeCallableDescriptorForObject + if (qualifier is ClassQualifier) { + val companionObject = qualifierReceiver.companionObjectReceiver ?: return + val classifierDescriptor = qualifierReceiver.classifier + doComputeTasks(companionObject, taskPrioritizerContext.filterCollectors { + when { + classifierDescriptor is ClassDescriptor && classifierDescriptor.getCompanionObjectDescriptor() != null -> { + // nested classes and objects should not be accessible via short reference to companion 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 } - classifierDescriptor != null && DescriptorUtils.isEnumEntry(classifierDescriptor) -> { - // objects nested in enum should not be accessible via enum entries reference - it !is FakeCallableDescriptorForObject - } - else -> true - } - }) + }) + } } private fun doComputeTasks(receiver: ReceiverValue, c: TaskPrioritizerContext) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/receivers/Qualifier.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/receivers/Qualifier.kt index 93ff2097cd7..e81435358e9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/receivers/Qualifier.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/receivers/Qualifier.kt @@ -47,12 +47,10 @@ public interface Qualifier: Receiver { public val expression: KtExpression - public val packageView: PackageViewDescriptor? - - public val classifier: ClassifierDescriptor? - public val name: Name - get() = classifier?.getName() ?: packageView!!.getName() + get() = descriptor.name + + public val descriptor: DeclarationDescriptor // package, classifier or companion object descriptor public val resultingDescriptor: DeclarationDescriptor @@ -64,15 +62,11 @@ abstract class QualifierReceiver( val referenceExpression: KtSimpleNameExpression ) : Qualifier { - override val expression: KtExpression = referenceExpression.getTopmostParentQualifiedExpressionForSelector() ?: referenceExpression - - val descriptor: DeclarationDescriptor - get() = classifier ?: packageView ?: throw AssertionError("PackageView and classifier both are null") + override val expression: KtExpression + get() = referenceExpression.getTopmostParentQualifiedExpressionForSelector() ?: referenceExpression override var resultingDescriptor: DeclarationDescriptor by Delegates.notNull() - abstract val companionObjectReceiver: ReceiverValue? - abstract fun getNestedClassesAndPackageMembersScope(): MemberScope override fun exists() = true @@ -80,10 +74,11 @@ abstract class QualifierReceiver( class PackageQualifier( referenceExpression: KtSimpleNameExpression, - override val packageView: PackageViewDescriptor + public val packageView: PackageViewDescriptor ) : QualifierReceiver(referenceExpression) { - override val classifier: ClassifierDescriptor? get() = null + override val descriptor: DeclarationDescriptor + get() = packageView override val scope: MemberScope get() = packageView.memberScope @@ -95,13 +90,28 @@ class PackageQualifier( get() = null } -class ClassifierQualifier( - referenceExpression: KtSimpleNameExpression, - override val classifier: ClassifierDescriptor, - override val companionObjectReceiver: ReceiverValue? -) : QualifierReceiver(referenceExpression) { +abstract class ClassifierQualifier(referenceExpression: KtSimpleNameExpression) : QualifierReceiver(referenceExpression) { + abstract val classifier: ClassifierDescriptor - override val packageView: PackageViewDescriptor? get() = null + override val descriptor: DeclarationDescriptor + get() = classifier +} + +class ClassifierQualifierWithEmptyScope( + referenceExpression: KtSimpleNameExpression, + override val classifier: ClassifierDescriptor +) : ClassifierQualifier(referenceExpression) { + + override fun getNestedClassesAndPackageMembersScope(): MemberScope = scope + + override val scope: MemberScope = MemberScope.empty(classifier) +} + +class ClassQualifier( + referenceExpression: KtSimpleNameExpression, + override val classifier: ClassDescriptor, + val companionObjectReceiver: ReceiverValue? +) : ClassifierQualifier(referenceExpression) { override val scope: MemberScope get() { if (classifier !is ClassDescriptor) { @@ -140,21 +150,12 @@ class ClassifierQualifier( return ChainedScope("Static scope for $name as class or object", *scopes.toTypedArray()) } - override fun toString() = "Classifier{$classifier}" -} + fun getClassObjectReceiver(): ReceiverValue = + classifier.classObjectType?.let { ExpressionReceiver(referenceExpression, it) } ?: ReceiverValue.NO_RECEIVER -fun createClassifierQualifier( - referenceExpression: KtSimpleNameExpression, - classifier: ClassifierDescriptor, - bindingContext: BindingContext -): ClassifierQualifier { - val companionObjectReceiver = (classifier as? ClassDescriptor)?.companionObjectType?.let { - ExpressionReceiver.create(referenceExpression, it, bindingContext) - } - return ClassifierQualifier(referenceExpression, classifier, companionObjectReceiver) + override fun toString() = "Class{$classifier}" } - fun createQualifier( expression: KtSimpleNameExpression, receiver: Receiver, @@ -163,7 +164,8 @@ fun createQualifier( val receiverScope = when { !receiver.exists() -> context.scope receiver is QualifierReceiver -> receiver.scope.memberScopeAsImportingScope() - else -> receiver.getType().getMemberScope().memberScopeAsImportingScope() + receiver is ReceiverValue -> receiver.type.memberScope.memberScopeAsImportingScope() + else -> throw IllegalArgumentException("Unexpected receiver kind: $receiver") } val name = expression.getReferencedNameAsName() @@ -175,7 +177,7 @@ fun createQualifier( context.trace.recordScope(context.scope, expression) val qualifier = - if (receiver is PackageQualifier) + if (receiver is PackageQualifier) { if (packageViewDescriptor != null) PackageQualifier(expression, packageViewDescriptor) else @@ -185,92 +187,19 @@ fun createQualifier( createClassifierQualifier(expression, classifierDescriptor, context.trace.bindingContext) else PackageQualifier(expression, packageViewDescriptor!!) + } context.trace.record(QUALIFIER, qualifier.expression, qualifier) return qualifier } -fun QualifierReceiver.resolveAsStandaloneExpression( - context: ExpressionTypingContext, - symbolUsageValidator: SymbolUsageValidator -): KotlinType? { - val classifier = this.classifier - - resolveAndRecordReferenceTarget(context, symbolUsageValidator, selector = null) - if (classifier is TypeParameterDescriptor) { - context.trace.report(TYPE_PARAMETER_IS_NOT_AN_EXPRESSION.on(referenceExpression, classifier)) +fun createClassifierQualifier( + referenceExpression: KtSimpleNameExpression, + classifier: ClassifierDescriptor, + bindingContext: BindingContext +): ClassifierQualifier { + val companionObjectReceiver = (classifier as? ClassDescriptor)?.companionObjectType?.let { + ExpressionReceiver.create(referenceExpression, it, bindingContext) } - else if (classifier is ClassDescriptor && !classifier.hasCompanionObject) { - context.trace.report(NO_COMPANION_OBJECT.on(referenceExpression, classifier)) - } - else if (packageView != null) { - context.trace.report(EXPRESSION_EXPECTED_PACKAGE_FOUND.on(referenceExpression)) - } - return null -} - -fun QualifierReceiver.resolveAsReceiverInQualifiedExpression( - context: ExpressionTypingContext, - symbolUsageValidator: SymbolUsageValidator, - selector: DeclarationDescriptor? -) { - val classifier = this.classifier - - resolveAndRecordReferenceTarget(context, symbolUsageValidator, selector) - if (classifier is TypeParameterDescriptor) { - context.trace.report(TYPE_PARAMETER_ON_LHS_OF_DOT.on(referenceExpression, classifier)) - } - else if (classifier is ClassDescriptor && classifier.hasCompanionObject) { - context.trace.recordType(expression, classifier.companionObjectType) - } -} - -private fun QualifierReceiver.resolveAndRecordReferenceTarget( - context: ExpressionTypingContext, - symbolUsageValidator: SymbolUsageValidator, - selector: DeclarationDescriptor? -) { - resultingDescriptor = resolveReferenceTarget(context, symbolUsageValidator, selector) - context.trace.record(REFERENCE_TARGET, referenceExpression, resultingDescriptor) -} - -private fun QualifierReceiver.resolveReferenceTarget( - context: ExpressionTypingContext, - symbolUsageValidator: SymbolUsageValidator, - selector: DeclarationDescriptor? -): DeclarationDescriptor { - val classifier = this.classifier - val packageView = this.packageView - - if (classifier is TypeParameterDescriptor) { - return classifier - } - - val selectorContainer = when { - selector is ConstructorDescriptor -> selector.getContainingDeclaration().getContainingDeclaration() - else -> selector?.getContainingDeclaration() - } - - if (packageView != null && (selectorContainer is PackageFragmentDescriptor || selectorContainer is PackageViewDescriptor) - && getFqName(packageView) == getFqName(selectorContainer)) { - return packageView - } - - val isCallableWithReceiver = selector is CallableDescriptor && - (selector.getDispatchReceiverParameter() != null || selector.getExtensionReceiverParameter() != null) - - val declarationDescriptor = descriptor - if (declarationDescriptor is ClassifierDescriptor) - symbolUsageValidator.validateTypeUsage(declarationDescriptor, context.trace, referenceExpression) - - if (isCallableWithReceiver && classifier is ClassDescriptor && classifier.hasCompanionObject) { - val companionObjectDescriptor = classifier.getCompanionObjectDescriptor() - if (companionObjectDescriptor != null) { - context.trace.record(SHORT_REFERENCE_TO_COMPANION_OBJECT, referenceExpression, classifier) - symbolUsageValidator.validateTypeUsage(companionObjectDescriptor, context.trace, referenceExpression) - return companionObjectDescriptor - } - } - - return declarationDescriptor -} + return ClassQualifier(referenceExpression, classifier, companionObjectReceiver) +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInsight/CodeInsightUtils.java b/idea/src/org/jetbrains/kotlin/idea/codeInsight/CodeInsightUtils.java index 8458b5fb3cd..1914598a96b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInsight/CodeInsightUtils.java +++ b/idea/src/org/jetbrains/kotlin/idea/codeInsight/CodeInsightUtils.java @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils; import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingContext; +import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier; import org.jetbrains.kotlin.resolve.scopes.receivers.Qualifier; import org.jetbrains.kotlin.types.KotlinType; @@ -78,8 +79,11 @@ public class CodeInsightUtils { Qualifier qualifier = context.get(BindingContext.QUALIFIER, expression); if (qualifier != null) { - ClassifierDescriptor classifier = qualifier.getClassifier(); - if (!(classifier instanceof ClassDescriptor) || ((ClassDescriptor) classifier).getKind() != ClassKind.OBJECT) return null; + if (!(qualifier instanceof ClassQualifier)) return null; + ClassifierDescriptor classifier = ((ClassQualifier) qualifier).getClassifier(); + if (!(classifier instanceof ClassDescriptor) || ((ClassDescriptor) classifier).getKind() != ClassKind.OBJECT) { + return null; + } } return expression; diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateCallableFromCallActionFactory.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateCallableFromCallActionFactory.kt index 1cd5b275442..4202de9a037 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateCallableFromCallActionFactory.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateCallableFromCallActionFactory.kt @@ -38,6 +38,7 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.callUtil.getCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier import org.jetbrains.kotlin.resolve.scopes.receivers.Qualifier import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue @@ -110,7 +111,7 @@ sealed class CreateCallableFromCallActionFactory( receiver is Qualifier -> { val qualifierType = context.getType(receiver.expression) if (qualifierType != null) return TypeInfo(qualifierType, Variance.IN_VARIANCE) - + if (receiver !is ClassQualifier) return null val classifier = receiver.classifier as? JavaClassDescriptor ?: return null val javaClass = DescriptorToSourceUtilsIde.getAnyDeclaration(project, classifier) as? PsiClass if (javaClass == null || !javaClass.canRefactor()) return null diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/pushDown/pushDownConflictsUtils.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/pushDown/pushDownConflictsUtils.kt index e30d4c9c54d..8d9499c0d4c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/pushDown/pushDownConflictsUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/pushDown/pushDownConflictsUtils.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForReceiver import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.resolve.scopes.receivers.Qualifier import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.source.getPsi @@ -180,7 +181,7 @@ private fun checkExternalUsages( val resolvedCall = calleeExpr.getResolvedCall(context.resolutionFacade.analyze(calleeExpr)) ?: continue val callElement = resolvedCall.call.callElement val dispatchReceiver = resolvedCall.dispatchReceiver - if (!dispatchReceiver.exists() || dispatchReceiver is QualifierReceiver) continue + if (!dispatchReceiver.exists() || dispatchReceiver is Qualifier) continue val receiverClassDescriptor = dispatchReceiver.type.constructor.declarationDescriptor as? ClassDescriptor ?: continue if (!DescriptorUtils.isSubclass(receiverClassDescriptor, targetClassDescriptor)) { conflicts.putValue(callElement, "Pushed member won't be available in '${callElement.text}'")