diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt index e962bafec6c..8bc7a66e7a7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.TemporaryBindingTrace import org.jetbrains.kotlin.resolve.calls.CallResolver import org.jetbrains.kotlin.resolve.calls.CallTransformer import org.jetbrains.kotlin.resolve.calls.CandidateResolver +import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getUnaryPlusOrMinusOperatorFunctionName import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isConventionCall import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInfixCall import org.jetbrains.kotlin.resolve.calls.callUtil.createLookupLocation @@ -71,27 +72,7 @@ class NewResolveOldInference( val baseContext = Context(scopeTower, name, context, tracing) - val processor = - when (kind) { - CallResolver.ResolveKind.VARIABLE -> createVariableProcessor(baseContext, explicitReceiver) - CallResolver.ResolveKind.FUNCTION -> createFunctionTowerProcessor(baseContext, explicitReceiver) - CallResolver.ResolveKind.CALLABLE_REFERENCE -> CompositeScopeTowerProcessor( - createFunctionProcessor(baseContext, explicitReceiver), - createVariableProcessor(baseContext, explicitReceiver) - ) - CallResolver.ResolveKind.INVOKE -> { - // todo - val call = (context.call as? CallTransformer.CallForImplicitInvoke).sure { - "Call should be CallForImplicitInvoke, but it is: ${context.call}" - } - createProcessorWithReceiverValueOrEmpty(explicitReceiver) { - createCallTowerProcessorForExplicitInvoke(baseContext, call.dispatchReceiver, it) - } - } - CallResolver.ResolveKind.GIVEN_CANDIDATES -> { - throw UnsupportedOperationException("Kind $kind unsupported yet") - } - } + var processor = createResolveProcessor(kind, explicitReceiver, context, baseContext) if (context.collectAllCandidates) { val allCandidates = towerResolver.collectAllCandidates(baseContext, processor) @@ -99,11 +80,47 @@ class NewResolveOldInference( result.allCandidates = allCandidates.map { it.resolvedCall as MutableResolvedCall } return result } + // 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 otherBaseContext = Context(scopeTower, deprecatedName, context, tracing) + processor = CompositeScopeTowerProcessor(processor, createResolveProcessor(kind, explicitReceiver, context, otherBaseContext)) + } val candidates = towerResolver.runResolve(baseContext, processor, useOrder = kind != CallResolver.ResolveKind.CALLABLE_REFERENCE) return convertToOverloadResults(candidates, tracing, context) } + private fun createResolveProcessor( + kind: CallResolver.ResolveKind, + explicitReceiver : Receiver?, + context: BasicCallResolutionContext, + baseContext: Context) + = when (kind) { + CallResolver.ResolveKind.VARIABLE -> createVariableProcessor(baseContext, explicitReceiver) + CallResolver.ResolveKind.FUNCTION -> createFunctionTowerProcessor(baseContext, explicitReceiver) + CallResolver.ResolveKind.CALLABLE_REFERENCE -> CompositeScopeTowerProcessor( + createFunctionProcessor(baseContext, explicitReceiver), + createVariableProcessor(baseContext, explicitReceiver) + ) + CallResolver.ResolveKind.INVOKE -> { + // todo + val call = (context.call as? CallTransformer.CallForImplicitInvoke).sure { + "Call should be CallForImplicitInvoke, but it is: ${context.call}" + } + createProcessorWithReceiverValueOrEmpty(explicitReceiver) { + createCallTowerProcessorForExplicitInvoke(baseContext, call.dispatchReceiver, it) + } + } + CallResolver.ResolveKind.GIVEN_CANDIDATES -> { + throw UnsupportedOperationException("Kind $kind unsupported yet") + } + } + private fun createProcessorWithReceiverValueOrEmpty( explicitReceiver: Receiver?, create: (ReceiverValue?) -> ScopeTowerProcessor @@ -219,6 +236,9 @@ class NewResolveOldInference( private fun checkInfixAndOperator(call: Call, descriptor: CallableDescriptor): List { if (descriptor !is FunctionDescriptor || ErrorUtils.isError(descriptor)) return emptyList() + if (descriptor.name != name && (name == OperatorNameConventions.UNARY_PLUS || name == OperatorNameConventions.UNARY_MINUS)) { + return listOf(DeprecatedUnaryPlusAsPlus) + } val conventionError = if (isConventionCall(call) && !descriptor.isOperator) InvokeConventionCallNoOperatorModifier else null val infixError = if (isInfixCall(call) && !descriptor.isInfix) InfixCallNoInfixModifier else null diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTower.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTower.kt index 8a381f09ce1..269cb3442ab 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTower.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTower.kt @@ -101,4 +101,5 @@ object ExtensionWithStaticTypeWithDynamicReceiver: ResolutionDiagnostic(Resoluti object HiddenDescriptor: ResolutionDiagnostic(ResolutionCandidateApplicability.HIDDEN) object InvokeConventionCallNoOperatorModifier : ResolutionDiagnostic(ResolutionCandidateApplicability.CONVENTION_ERROR) -object InfixCallNoInfixModifier : ResolutionDiagnostic(ResolutionCandidateApplicability.CONVENTION_ERROR) \ No newline at end of file +object InfixCallNoInfixModifier : ResolutionDiagnostic(ResolutionCandidateApplicability.CONVENTION_ERROR) +object DeprecatedUnaryPlusAsPlus : ResolutionDiagnostic(ResolutionCandidateApplicability.CONVENTION_ERROR) diff --git a/compiler/testData/diagnostics/tests/DeprecatedUnaryOperatorConventions.kt b/compiler/testData/diagnostics/tests/DeprecatedUnaryOperatorConventions.kt index 05fe3b86163..26cf5014740 100644 --- a/compiler/testData/diagnostics/tests/DeprecatedUnaryOperatorConventions.kt +++ b/compiler/testData/diagnostics/tests/DeprecatedUnaryOperatorConventions.kt @@ -15,7 +15,7 @@ operator fun String.unaryPlus(): Int = 0 fun test() { requireInt(+ "") requireInt(+ Example()) - requireString(+ ExampleDeprecated()) + requireString(+ ExampleDeprecated()) } fun requireInt(n: Int) {} @@ -26,7 +26,7 @@ class Example2 { operator fun minus() = this fun test() { - +this - -this + +this + -this } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/staticCallsInDynamicContext.kt b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/staticCallsInDynamicContext.kt index b5b9a1399f2..53ff9b7b1b4 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/staticCallsInDynamicContext.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/staticCallsInDynamicContext.kt @@ -27,7 +27,7 @@ fun dynamic.test() { this() C() + C() - +C() + +C() this + C() diff --git a/idea/testData/findUsages/kotlin/conventions/plus.results.txt b/idea/testData/findUsages/kotlin/conventions/plus.results.txt index 94d0ffc3b62..aae3a5f5dab 100644 --- a/idea/testData/findUsages/kotlin/conventions/plus.results.txt +++ b/idea/testData/findUsages/kotlin/conventions/plus.results.txt @@ -2,4 +2,5 @@ Function call (10: 17) A(0) + A(1) + 2 Function call (11: 20) A(0) plus A(1) plus 2 Function call (12: 20) A(0).plus(A(1).plus(2)) Function call (15: 7) a += 1 -Function call (6: 30) fun plus(a: A): A = this + a.n \ No newline at end of file +Function call (6: 30) fun plus(a: A): A = this + a.n +Unclassified usage (18: 5) +A(0) \ No newline at end of file