Move resolve* methods from Qualifier.kt to QualifiedExpressionResolver.
Further differentiate various qualifiers.
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+17
-15
@@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<D, F>(storageManager, context, PriorityProviderImpl<D>(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 <D : CallableDescriptor, F : D> computeTasksForClassObjectReceiver(
|
||||
qualifierReceiver: QualifierReceiver,
|
||||
qualifier: Qualifier,
|
||||
taskPrioritizerContext: TaskPrioritizerContext<D, F>
|
||||
) {
|
||||
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 <D : CallableDescriptor, F : D> doComputeTasks(receiver: ReceiverValue, c: TaskPrioritizerContext<D, F>) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
+2
-1
@@ -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<E : KtExpression>(
|
||||
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
|
||||
|
||||
@@ -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}'")
|
||||
|
||||
Reference in New Issue
Block a user