Move auxiliary methods for QualifierReceiver resolution to a separate file
(to be refactored later). Get rid of duplicate type usage validation.
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classObjectType
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassObjectType
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassifierQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.PackageQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
|
||||
import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
|
||||
|
||||
|
||||
public fun resolveAsReceiverInQualifiedExpression(
|
||||
qualifier: QualifierReceiver,
|
||||
context: ExpressionTypingContext,
|
||||
selector: DeclarationDescriptor?,
|
||||
symbolUsageValidator: SymbolUsageValidator
|
||||
) {
|
||||
resolveAndRecordReferenceTarget(qualifier, context, selector, symbolUsageValidator)
|
||||
|
||||
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,
|
||||
symbolUsageValidator: SymbolUsageValidator
|
||||
) {
|
||||
resolveAndRecordReferenceTarget(qualifier, context, selector = null, symbolUsageValidator = symbolUsageValidator)
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveAndRecordReferenceTarget(
|
||||
qualifier: QualifierReceiver,
|
||||
context: ExpressionTypingContext,
|
||||
selector: DeclarationDescriptor?,
|
||||
symbolUsageValidator: SymbolUsageValidator
|
||||
) {
|
||||
// TODO get rid of QualifierReceiver::resultingDescriptor. REFERENCE_TARGET should be enough.
|
||||
qualifier.resultingDescriptor = resolveReferenceTarget(qualifier, context, selector, symbolUsageValidator)
|
||||
context.trace.record(BindingContext.REFERENCE_TARGET, qualifier.referenceExpression, qualifier.resultingDescriptor)
|
||||
}
|
||||
|
||||
private fun resolveReferenceTarget(
|
||||
qualifier: QualifierReceiver,
|
||||
context: ExpressionTypingContext,
|
||||
selector: DeclarationDescriptor?,
|
||||
symbolUsageValidator: SymbolUsageValidator
|
||||
): DeclarationDescriptor {
|
||||
if (qualifier is ClassifierQualifier && 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) {
|
||||
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
|
||||
}
|
||||
@@ -25,16 +25,15 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.calls.CallExpressionElement
|
||||
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.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
|
||||
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.containsFunctionOrVariable
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.findFunction
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.findVariable
|
||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||
import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
|
||||
@@ -598,96 +597,6 @@ 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 ClassifierQualifier && 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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+11
-10
@@ -25,10 +25,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
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.*;
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext;
|
||||
@@ -46,6 +43,7 @@ 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;
|
||||
@@ -70,19 +68,22 @@ public class CallExpressionResolver {
|
||||
@NotNull private final DataFlowAnalyzer dataFlowAnalyzer;
|
||||
@NotNull private final KotlinBuiltIns builtIns;
|
||||
@NotNull private final QualifiedExpressionResolver qualifiedExpressionResolver;
|
||||
@NotNull private final SymbolUsageValidator symbolUsageValidator;
|
||||
|
||||
public CallExpressionResolver(
|
||||
@NotNull CallResolver callResolver,
|
||||
@NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
|
||||
@NotNull DataFlowAnalyzer dataFlowAnalyzer,
|
||||
@NotNull KotlinBuiltIns builtIns,
|
||||
@NotNull QualifiedExpressionResolver qualifiedExpressionResolver
|
||||
@NotNull QualifiedExpressionResolver qualifiedExpressionResolver,
|
||||
@NotNull SymbolUsageValidator symbolUsageValidator
|
||||
) {
|
||||
this.callResolver = callResolver;
|
||||
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
||||
this.dataFlowAnalyzer = dataFlowAnalyzer;
|
||||
this.builtIns = builtIns;
|
||||
this.qualifiedExpressionResolver = qualifiedExpressionResolver;
|
||||
this.symbolUsageValidator = symbolUsageValidator;
|
||||
}
|
||||
|
||||
private ExpressionTypingServices expressionTypingServices;
|
||||
@@ -95,7 +96,7 @@ public class CallExpressionResolver {
|
||||
|
||||
@Nullable
|
||||
public ResolvedCall<FunctionDescriptor> getResolvedCallForFunction(
|
||||
@NotNull Call call, @NotNull KtExpression callExpression,
|
||||
@NotNull Call call,
|
||||
@NotNull ResolutionContext context, @NotNull CheckArgumentTypesMode checkArguments,
|
||||
@NotNull boolean[] result
|
||||
) {
|
||||
@@ -138,7 +139,7 @@ public class CallExpressionResolver {
|
||||
if (qualifier != null) {
|
||||
result[0] = true;
|
||||
if (!isLHSOfDot) {
|
||||
qualifiedExpressionResolver.resolveAsStandaloneExpression(qualifier, context);
|
||||
QualifiedExpressionResolveUtilKt.resolveAsStandaloneExpression(qualifier, context, symbolUsageValidator);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -179,7 +180,7 @@ public class CallExpressionResolver {
|
||||
context, "trace to resolve as function", nameExpression);
|
||||
ResolutionContext newContext = context.replaceTraceAndCache(temporaryForFunction);
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
|
||||
call, nameExpression, newContext, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, result);
|
||||
call, newContext, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, result);
|
||||
if (result[0]) {
|
||||
FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
|
||||
temporaryForFunction.commit();
|
||||
@@ -220,7 +221,7 @@ public class CallExpressionResolver {
|
||||
TemporaryTraceAndCache temporaryForFunction = TemporaryTraceAndCache.create(
|
||||
context, "trace to resolve as function call", callExpression);
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
|
||||
call, callExpression,
|
||||
call,
|
||||
// It's possible start of a call so we should reset safe call chain
|
||||
context.replaceTraceAndCache(temporaryForFunction).replaceInsideCallChain(false),
|
||||
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, result);
|
||||
@@ -425,7 +426,7 @@ public class CallExpressionResolver {
|
||||
calleeExpression instanceof KtReferenceExpression
|
||||
? context.trace.get(BindingContext.REFERENCE_TARGET, (KtReferenceExpression) calleeExpression) : null;
|
||||
|
||||
qualifiedExpressionResolver.resolveAsReceiverInQualifiedExpression(qualifierReceiver, context, selectorDescriptor);
|
||||
QualifiedExpressionResolveUtilKt.resolveAsReceiverInQualifiedExpression(qualifierReceiver, context, selectorDescriptor, symbolUsageValidator);
|
||||
}
|
||||
|
||||
private static void checkNestedClassAccess(
|
||||
|
||||
@@ -12,7 +12,7 @@ class TopLevel {
|
||||
}
|
||||
|
||||
fun useNested() {
|
||||
val <!UNUSED_VARIABLE!>d<!> = TopLevel.<!DEPRECATION, DEPRECATION!>Nested<!>.use()
|
||||
TopLevel.<!DEPRECATION, DEPRECATION!>Nested<!>.Nested2()
|
||||
TopLevel.<!DEPRECATION, DEPRECATION!>Nested<!>.<!UNRESOLVED_REFERENCE!>CompanionNested2<!>()
|
||||
val <!UNUSED_VARIABLE!>d<!> = TopLevel.<!DEPRECATION!>Nested<!>.use()
|
||||
TopLevel.<!DEPRECATION!>Nested<!>.Nested2()
|
||||
TopLevel.<!DEPRECATION!>Nested<!>.<!UNRESOLVED_REFERENCE!>CompanionNested2<!>()
|
||||
}
|
||||
@@ -15,13 +15,13 @@ fun first() {
|
||||
}
|
||||
|
||||
fun useObject() {
|
||||
<!DEPRECATION, DEPRECATION!>Obsolete<!>.use()
|
||||
<!DEPRECATION!>Obsolete<!>.use()
|
||||
val <!UNUSED_VARIABLE!>x<!> = <!DEPRECATION!>Obsolete<!>
|
||||
}
|
||||
|
||||
fun useCompanion() {
|
||||
val <!UNUSED_VARIABLE!>d<!> = <!DEPRECATION!>Another<!>
|
||||
val <!UNUSED_VARIABLE!>x<!> = Another.<!DEPRECATION!>Companion<!>
|
||||
Another.<!DEPRECATION, DEPRECATION!>Companion<!>.use()
|
||||
Another.<!DEPRECATION!>Companion<!>.use()
|
||||
<!DEPRECATION!>Another<!>.use()
|
||||
}
|
||||
Reference in New Issue
Block a user