diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolveUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolveUtil.kt new file mode 100644 index 00000000000..e6fe2ba52cb --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolveUtil.kt @@ -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 +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt index ef2da026227..af8d174c527 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt @@ -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 - } - } /* 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 5ec3b14ce41..8bbe95da69c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.java @@ -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 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 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 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( diff --git a/compiler/testData/diagnostics/tests/deprecated/nestedTypesUsage.kt b/compiler/testData/diagnostics/tests/deprecated/nestedTypesUsage.kt index 210f7b5ed08..775fc3c01f6 100644 --- a/compiler/testData/diagnostics/tests/deprecated/nestedTypesUsage.kt +++ b/compiler/testData/diagnostics/tests/deprecated/nestedTypesUsage.kt @@ -12,7 +12,7 @@ class TopLevel { } fun useNested() { - val d = TopLevel.Nested.use() - TopLevel.Nested.Nested2() - TopLevel.Nested.CompanionNested2() + val d = TopLevel.Nested.use() + TopLevel.Nested.Nested2() + TopLevel.Nested.CompanionNested2() } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/deprecated/objectUsage.kt b/compiler/testData/diagnostics/tests/deprecated/objectUsage.kt index da074c35159..ed34c52ae70 100644 --- a/compiler/testData/diagnostics/tests/deprecated/objectUsage.kt +++ b/compiler/testData/diagnostics/tests/deprecated/objectUsage.kt @@ -15,13 +15,13 @@ fun first() { } fun useObject() { - Obsolete.use() + Obsolete.use() val x = Obsolete } fun useCompanion() { val d = Another val x = Another.Companion - Another.Companion.use() + Another.Companion.use() Another.use() } \ No newline at end of file