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.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
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.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
|
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassifierQualifier
|
import org.jetbrains.kotlin.resolve.scopes.receivers.*
|
||||||
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.utils.findClassifier
|
import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
|
||||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||||
import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator
|
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.addIfNotNull
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
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)
|
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.BindingContext;
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
|
import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver;
|
||||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext;
|
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.CompileTimeConstant;
|
||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*;
|
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.ErrorUtils;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.kotlin.types.TypeUtils;
|
import org.jetbrains.kotlin.types.TypeUtils;
|
||||||
@@ -66,24 +66,24 @@ import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
|
|||||||
|
|
||||||
public class CallExpressionResolver {
|
public class CallExpressionResolver {
|
||||||
|
|
||||||
private final CallResolver callResolver;
|
@NotNull private final CallResolver callResolver;
|
||||||
private final ConstantExpressionEvaluator constantExpressionEvaluator;
|
@NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator;
|
||||||
private final SymbolUsageValidator symbolUsageValidator;
|
@NotNull private final DataFlowAnalyzer dataFlowAnalyzer;
|
||||||
private final DataFlowAnalyzer dataFlowAnalyzer;
|
|
||||||
@NotNull private final KotlinBuiltIns builtIns;
|
@NotNull private final KotlinBuiltIns builtIns;
|
||||||
|
@NotNull private final QualifiedExpressionResolver qualifiedExpressionResolver;
|
||||||
|
|
||||||
public CallExpressionResolver(
|
public CallExpressionResolver(
|
||||||
@NotNull CallResolver callResolver,
|
@NotNull CallResolver callResolver,
|
||||||
@NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
|
@NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
|
||||||
@NotNull SymbolUsageValidator symbolUsageValidator,
|
|
||||||
@NotNull DataFlowAnalyzer dataFlowAnalyzer,
|
@NotNull DataFlowAnalyzer dataFlowAnalyzer,
|
||||||
@NotNull KotlinBuiltIns builtIns
|
@NotNull KotlinBuiltIns builtIns,
|
||||||
|
@NotNull QualifiedExpressionResolver qualifiedExpressionResolver
|
||||||
) {
|
) {
|
||||||
this.callResolver = callResolver;
|
this.callResolver = callResolver;
|
||||||
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
||||||
this.symbolUsageValidator = symbolUsageValidator;
|
|
||||||
this.dataFlowAnalyzer = dataFlowAnalyzer;
|
this.dataFlowAnalyzer = dataFlowAnalyzer;
|
||||||
this.builtIns = builtIns;
|
this.builtIns = builtIns;
|
||||||
|
this.qualifiedExpressionResolver = qualifiedExpressionResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExpressionTypingServices expressionTypingServices;
|
private ExpressionTypingServices expressionTypingServices;
|
||||||
@@ -139,7 +139,7 @@ public class CallExpressionResolver {
|
|||||||
if (qualifier != null) {
|
if (qualifier != null) {
|
||||||
result[0] = true;
|
result[0] = true;
|
||||||
if (!isLHSOfDot) {
|
if (!isLHSOfDot) {
|
||||||
QualifierKt.resolveAsStandaloneExpression(qualifier, context, symbolUsageValidator);
|
qualifiedExpressionResolver.resolveAsStandaloneExpression(qualifier, context);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -211,7 +211,7 @@ public class CallExpressionResolver {
|
|||||||
* Determines the result type and data flow information after the call.
|
* Determines the result type and data flow information after the call.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public KotlinTypeInfo getCallExpressionTypeInfoWithoutFinalTypeCheck(
|
private KotlinTypeInfo getCallExpressionTypeInfoWithoutFinalTypeCheck(
|
||||||
@NotNull KtCallExpression callExpression, @NotNull Receiver receiver,
|
@NotNull KtCallExpression callExpression, @NotNull Receiver receiver,
|
||||||
@Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context
|
@Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context
|
||||||
) {
|
) {
|
||||||
@@ -275,7 +275,7 @@ public class CallExpressionResolver {
|
|||||||
KotlinType type = getVariableType((KtSimpleNameExpression) calleeExpression, receiver, callOperationNode,
|
KotlinType type = getVariableType((KtSimpleNameExpression) calleeExpression, receiver, callOperationNode,
|
||||||
context.replaceTraceAndCache(temporaryForVariable), result);
|
context.replaceTraceAndCache(temporaryForVariable), result);
|
||||||
Qualifier qualifier = temporaryForVariable.trace.get(BindingContext.QUALIFIER, calleeExpression);
|
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();
|
temporaryForVariable.commit();
|
||||||
context.trace.report(FUNCTION_EXPECTED.on(calleeExpression, calleeExpression,
|
context.trace.report(FUNCTION_EXPECTED.on(calleeExpression, calleeExpression,
|
||||||
type != null ? type : ErrorUtils.createErrorType("")));
|
type != null ? type : ErrorUtils.createErrorType("")));
|
||||||
@@ -423,7 +423,8 @@ public class CallExpressionResolver {
|
|||||||
DeclarationDescriptor selectorDescriptor =
|
DeclarationDescriptor selectorDescriptor =
|
||||||
calleeExpression instanceof KtReferenceExpression
|
calleeExpression instanceof KtReferenceExpression
|
||||||
? context.trace.get(BindingContext.REFERENCE_TARGET, (KtReferenceExpression) calleeExpression) : null;
|
? context.trace.get(BindingContext.REFERENCE_TARGET, (KtReferenceExpression) calleeExpression) : null;
|
||||||
QualifierKt.resolveAsReceiverInQualifiedExpression(qualifierReceiver, context, symbolUsageValidator, selectorDescriptor);
|
|
||||||
|
qualifiedExpressionResolver.resolveAsReceiverInQualifiedExpression(qualifierReceiver, context, selectorDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkNestedClassAccess(
|
private static void checkNestedClassAccess(
|
||||||
@@ -440,10 +441,11 @@ public class CallExpressionResolver {
|
|||||||
Qualifier receiverQualifier = context.trace.get(BindingContext.QUALIFIER, expression.getReceiverExpression());
|
Qualifier receiverQualifier = context.trace.get(BindingContext.QUALIFIER, expression.getReceiverExpression());
|
||||||
|
|
||||||
if (receiverQualifier == null && expressionQualifier != null) {
|
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;
|
"Only class can (package cannot) be accessed by instance reference: " + expressionQualifier;
|
||||||
context.trace.report(NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE
|
context.trace.report(NESTED_CLASS_ACCESSED_VIA_INSTANCE_REFERENCE.on(
|
||||||
.on(selectorExpression, (ClassDescriptor) expressionQualifier.getClassifier()));
|
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.descriptorUtil.hasLowPriorityInOverloadResolution
|
||||||
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
|
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.*
|
||||||
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.ReceiverValue.NO_RECEIVER
|
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.getImplicitReceiversHierarchy
|
||||||
import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope
|
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 result = ResolutionTaskHolder<D, F>(storageManager, context, PriorityProviderImpl<D>(context), tracing)
|
||||||
val taskPrioritizerContext = TaskPrioritizerContext(name, result, context, context.scope, callableDescriptorCollectors)
|
val taskPrioritizerContext = TaskPrioritizerContext(name, result, context, context.scope, callableDescriptorCollectors)
|
||||||
|
|
||||||
if (explicitReceiver is QualifierReceiver) {
|
when (explicitReceiver) {
|
||||||
val qualifierReceiver: QualifierReceiver = explicitReceiver
|
is QualifierReceiver -> {
|
||||||
val receiverScope = LexicalScope.empty(qualifierReceiver.getNestedClassesAndPackageMembersScope().memberScopeAsImportingScope(),
|
val qualifierReceiver: QualifierReceiver = explicitReceiver
|
||||||
qualifierReceiver.descriptor)
|
val receiverScope = qualifierReceiver.getNestedClassesAndPackageMembersScope().memberScopeAsImportingScope()
|
||||||
doComputeTasks(NO_RECEIVER, taskPrioritizerContext.replaceScope(receiverScope))
|
doComputeTasks(NO_RECEIVER, taskPrioritizerContext.replaceScope(receiverScope))
|
||||||
computeTasksForClassObjectReceiver(qualifierReceiver, taskPrioritizerContext)
|
computeTasksForClassObjectReceiver(qualifierReceiver, taskPrioritizerContext)
|
||||||
}
|
}
|
||||||
else {
|
is ReceiverValue -> {
|
||||||
doComputeTasks(explicitReceiver, taskPrioritizerContext)
|
doComputeTasks(explicitReceiver, taskPrioritizerContext)
|
||||||
|
|
||||||
// Temporary fix for code migration (unaryPlus()/unaryMinus())
|
// Temporary fix for code migration (unaryPlus()/unaryMinus())
|
||||||
val unaryConventionName = getUnaryPlusOrMinusOperatorFunctionName(context.call)
|
val unaryConventionName = getUnaryPlusOrMinusOperatorFunctionName(context.call)
|
||||||
if (unaryConventionName != null) {
|
if (unaryConventionName != null) {
|
||||||
val deprecatedName = if (name == OperatorNameConventions.UNARY_PLUS)
|
val deprecatedName = if (name == OperatorNameConventions.UNARY_PLUS)
|
||||||
OperatorNameConventions.PLUS
|
OperatorNameConventions.PLUS
|
||||||
else
|
else
|
||||||
OperatorNameConventions.MINUS
|
OperatorNameConventions.MINUS
|
||||||
|
|
||||||
val additionalContext = TaskPrioritizerContext(deprecatedName, result, context, context.scope, callableDescriptorCollectors)
|
val additionalContext = TaskPrioritizerContext(deprecatedName, result, context, context.scope, callableDescriptorCollectors)
|
||||||
doComputeTasks(explicitReceiver, additionalContext)
|
doComputeTasks(explicitReceiver, additionalContext)
|
||||||
@@ -98,24 +94,26 @@ public class TaskPrioritizer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun <D : CallableDescriptor, F : D> computeTasksForClassObjectReceiver(
|
private fun <D : CallableDescriptor, F : D> computeTasksForClassObjectReceiver(
|
||||||
qualifierReceiver: QualifierReceiver,
|
qualifier: Qualifier,
|
||||||
taskPrioritizerContext: TaskPrioritizerContext<D, F>
|
taskPrioritizerContext: TaskPrioritizerContext<D, F>
|
||||||
) {
|
) {
|
||||||
val companionObject = qualifierReceiver.companionObjectReceiver ?: return
|
if (qualifier is ClassQualifier) {
|
||||||
val classifierDescriptor = qualifierReceiver.classifier
|
val companionObject = qualifierReceiver.companionObjectReceiver ?: return
|
||||||
doComputeTasks(companionObject, taskPrioritizerContext.filterCollectors {
|
val classifierDescriptor = qualifierReceiver.classifier
|
||||||
when {
|
doComputeTasks(companionObject, taskPrioritizerContext.filterCollectors {
|
||||||
classifierDescriptor is ClassDescriptor && classifierDescriptor.getCompanionObjectDescriptor() != null -> {
|
when {
|
||||||
// nested classes and objects should not be accessible via short reference to companion object
|
classifierDescriptor is ClassDescriptor && classifierDescriptor.getCompanionObjectDescriptor() != null -> {
|
||||||
it !is ConstructorDescriptor && it !is FakeCallableDescriptorForObject
|
// 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>) {
|
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 expression: KtExpression
|
||||||
|
|
||||||
public val packageView: PackageViewDescriptor?
|
|
||||||
|
|
||||||
public val classifier: ClassifierDescriptor?
|
|
||||||
|
|
||||||
public val name: Name
|
public val name: Name
|
||||||
get() = classifier?.getName() ?: packageView!!.getName()
|
get() = descriptor.name
|
||||||
|
|
||||||
|
public val descriptor: DeclarationDescriptor
|
||||||
|
|
||||||
// package, classifier or companion object descriptor
|
// package, classifier or companion object descriptor
|
||||||
public val resultingDescriptor: DeclarationDescriptor
|
public val resultingDescriptor: DeclarationDescriptor
|
||||||
@@ -64,15 +62,11 @@ abstract class QualifierReceiver(
|
|||||||
val referenceExpression: KtSimpleNameExpression
|
val referenceExpression: KtSimpleNameExpression
|
||||||
) : Qualifier {
|
) : Qualifier {
|
||||||
|
|
||||||
override val expression: KtExpression = referenceExpression.getTopmostParentQualifiedExpressionForSelector() ?: referenceExpression
|
override val expression: KtExpression
|
||||||
|
get() = referenceExpression.getTopmostParentQualifiedExpressionForSelector() ?: referenceExpression
|
||||||
val descriptor: DeclarationDescriptor
|
|
||||||
get() = classifier ?: packageView ?: throw AssertionError("PackageView and classifier both are null")
|
|
||||||
|
|
||||||
override var resultingDescriptor: DeclarationDescriptor by Delegates.notNull()
|
override var resultingDescriptor: DeclarationDescriptor by Delegates.notNull()
|
||||||
|
|
||||||
abstract val companionObjectReceiver: ReceiverValue?
|
|
||||||
|
|
||||||
abstract fun getNestedClassesAndPackageMembersScope(): MemberScope
|
abstract fun getNestedClassesAndPackageMembersScope(): MemberScope
|
||||||
|
|
||||||
override fun exists() = true
|
override fun exists() = true
|
||||||
@@ -80,10 +74,11 @@ abstract class QualifierReceiver(
|
|||||||
|
|
||||||
class PackageQualifier(
|
class PackageQualifier(
|
||||||
referenceExpression: KtSimpleNameExpression,
|
referenceExpression: KtSimpleNameExpression,
|
||||||
override val packageView: PackageViewDescriptor
|
public val packageView: PackageViewDescriptor
|
||||||
) : QualifierReceiver(referenceExpression) {
|
) : QualifierReceiver(referenceExpression) {
|
||||||
|
|
||||||
override val classifier: ClassifierDescriptor? get() = null
|
override val descriptor: DeclarationDescriptor
|
||||||
|
get() = packageView
|
||||||
|
|
||||||
override val scope: MemberScope get() = packageView.memberScope
|
override val scope: MemberScope get() = packageView.memberScope
|
||||||
|
|
||||||
@@ -95,13 +90,28 @@ class PackageQualifier(
|
|||||||
get() = null
|
get() = null
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClassifierQualifier(
|
abstract class ClassifierQualifier(referenceExpression: KtSimpleNameExpression) : QualifierReceiver(referenceExpression) {
|
||||||
referenceExpression: KtSimpleNameExpression,
|
abstract val classifier: ClassifierDescriptor
|
||||||
override val classifier: ClassifierDescriptor,
|
|
||||||
override val companionObjectReceiver: ReceiverValue?
|
|
||||||
) : QualifierReceiver(referenceExpression) {
|
|
||||||
|
|
||||||
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() {
|
override val scope: MemberScope get() {
|
||||||
if (classifier !is ClassDescriptor) {
|
if (classifier !is ClassDescriptor) {
|
||||||
@@ -140,21 +150,12 @@ class ClassifierQualifier(
|
|||||||
return ChainedScope("Static scope for $name as class or object", *scopes.toTypedArray())
|
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(
|
override fun toString() = "Class{$classifier}"
|
||||||
referenceExpression: KtSimpleNameExpression,
|
|
||||||
classifier: ClassifierDescriptor,
|
|
||||||
bindingContext: BindingContext
|
|
||||||
): ClassifierQualifier {
|
|
||||||
val companionObjectReceiver = (classifier as? ClassDescriptor)?.companionObjectType?.let {
|
|
||||||
ExpressionReceiver.create(referenceExpression, it, bindingContext)
|
|
||||||
}
|
|
||||||
return ClassifierQualifier(referenceExpression, classifier, companionObjectReceiver)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun createQualifier(
|
fun createQualifier(
|
||||||
expression: KtSimpleNameExpression,
|
expression: KtSimpleNameExpression,
|
||||||
receiver: Receiver,
|
receiver: Receiver,
|
||||||
@@ -163,7 +164,8 @@ fun createQualifier(
|
|||||||
val receiverScope = when {
|
val receiverScope = when {
|
||||||
!receiver.exists() -> context.scope
|
!receiver.exists() -> context.scope
|
||||||
receiver is QualifierReceiver -> receiver.scope.memberScopeAsImportingScope()
|
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()
|
val name = expression.getReferencedNameAsName()
|
||||||
@@ -175,7 +177,7 @@ fun createQualifier(
|
|||||||
context.trace.recordScope(context.scope, expression)
|
context.trace.recordScope(context.scope, expression)
|
||||||
|
|
||||||
val qualifier =
|
val qualifier =
|
||||||
if (receiver is PackageQualifier)
|
if (receiver is PackageQualifier) {
|
||||||
if (packageViewDescriptor != null)
|
if (packageViewDescriptor != null)
|
||||||
PackageQualifier(expression, packageViewDescriptor)
|
PackageQualifier(expression, packageViewDescriptor)
|
||||||
else
|
else
|
||||||
@@ -185,92 +187,19 @@ fun createQualifier(
|
|||||||
createClassifierQualifier(expression, classifierDescriptor, context.trace.bindingContext)
|
createClassifierQualifier(expression, classifierDescriptor, context.trace.bindingContext)
|
||||||
else
|
else
|
||||||
PackageQualifier(expression, packageViewDescriptor!!)
|
PackageQualifier(expression, packageViewDescriptor!!)
|
||||||
|
}
|
||||||
|
|
||||||
context.trace.record(QUALIFIER, qualifier.expression, qualifier)
|
context.trace.record(QUALIFIER, qualifier.expression, qualifier)
|
||||||
return qualifier
|
return qualifier
|
||||||
}
|
}
|
||||||
|
|
||||||
fun QualifierReceiver.resolveAsStandaloneExpression(
|
fun createClassifierQualifier(
|
||||||
context: ExpressionTypingContext,
|
referenceExpression: KtSimpleNameExpression,
|
||||||
symbolUsageValidator: SymbolUsageValidator
|
classifier: ClassifierDescriptor,
|
||||||
): KotlinType? {
|
bindingContext: BindingContext
|
||||||
val classifier = this.classifier
|
): ClassifierQualifier {
|
||||||
|
val companionObjectReceiver = (classifier as? ClassDescriptor)?.companionObjectType?.let {
|
||||||
resolveAndRecordReferenceTarget(context, symbolUsageValidator, selector = null)
|
ExpressionReceiver.create(referenceExpression, it, bindingContext)
|
||||||
if (classifier is TypeParameterDescriptor) {
|
|
||||||
context.trace.report(TYPE_PARAMETER_IS_NOT_AN_EXPRESSION.on(referenceExpression, classifier))
|
|
||||||
}
|
}
|
||||||
else if (classifier is ClassDescriptor && !classifier.hasCompanionObject) {
|
return ClassQualifier(referenceExpression, classifier, companionObjectReceiver)
|
||||||
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
|
|
||||||
}
|
|
||||||
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils;
|
|||||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
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.resolve.scopes.receivers.Qualifier;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
|
|
||||||
@@ -78,8 +79,11 @@ public class CodeInsightUtils {
|
|||||||
|
|
||||||
Qualifier qualifier = context.get(BindingContext.QUALIFIER, expression);
|
Qualifier qualifier = context.get(BindingContext.QUALIFIER, expression);
|
||||||
if (qualifier != null) {
|
if (qualifier != null) {
|
||||||
ClassifierDescriptor classifier = qualifier.getClassifier();
|
if (!(qualifier instanceof ClassQualifier)) return null;
|
||||||
if (!(classifier instanceof ClassDescriptor) || ((ClassDescriptor) classifier).getKind() != ClassKind.OBJECT) return null;
|
ClassifierDescriptor classifier = ((ClassQualifier) qualifier).getClassifier();
|
||||||
|
if (!(classifier instanceof ClassDescriptor) || ((ClassDescriptor) classifier).getKind() != ClassKind.OBJECT) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return expression;
|
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.getCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
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.Qualifier
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||||
@@ -110,7 +111,7 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
|
|||||||
receiver is Qualifier -> {
|
receiver is Qualifier -> {
|
||||||
val qualifierType = context.getType(receiver.expression)
|
val qualifierType = context.getType(receiver.expression)
|
||||||
if (qualifierType != null) return TypeInfo(qualifierType, Variance.IN_VARIANCE)
|
if (qualifierType != null) return TypeInfo(qualifierType, Variance.IN_VARIANCE)
|
||||||
|
if (receiver !is ClassQualifier) return null
|
||||||
val classifier = receiver.classifier as? JavaClassDescriptor ?: return null
|
val classifier = receiver.classifier as? JavaClassDescriptor ?: return null
|
||||||
val javaClass = DescriptorToSourceUtilsIde.getAnyDeclaration(project, classifier) as? PsiClass
|
val javaClass = DescriptorToSourceUtilsIde.getAnyDeclaration(project, classifier) as? PsiClass
|
||||||
if (javaClass == null || !javaClass.canRefactor()) return null
|
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.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
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.QualifierReceiver
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
@@ -180,7 +181,7 @@ private fun checkExternalUsages(
|
|||||||
val resolvedCall = calleeExpr.getResolvedCall(context.resolutionFacade.analyze(calleeExpr)) ?: continue
|
val resolvedCall = calleeExpr.getResolvedCall(context.resolutionFacade.analyze(calleeExpr)) ?: continue
|
||||||
val callElement = resolvedCall.call.callElement
|
val callElement = resolvedCall.call.callElement
|
||||||
val dispatchReceiver = resolvedCall.dispatchReceiver
|
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
|
val receiverClassDescriptor = dispatchReceiver.type.constructor.declarationDescriptor as? ClassDescriptor ?: continue
|
||||||
if (!DescriptorUtils.isSubclass(receiverClassDescriptor, targetClassDescriptor)) {
|
if (!DescriptorUtils.isSubclass(receiverClassDescriptor, targetClassDescriptor)) {
|
||||||
conflicts.putValue(callElement, "Pushed member won't be available in '${callElement.text}'")
|
conflicts.putValue(callElement, "Pushed member won't be available in '${callElement.text}'")
|
||||||
|
|||||||
Reference in New Issue
Block a user