Resolve unaryPlus as plus with error.
This commit is contained in:
+41
-21
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
|
|||||||
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.CallTransformer
|
import org.jetbrains.kotlin.resolve.calls.CallTransformer
|
||||||
import org.jetbrains.kotlin.resolve.calls.CandidateResolver
|
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.isConventionCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInfixCall
|
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInfixCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.createLookupLocation
|
import org.jetbrains.kotlin.resolve.calls.callUtil.createLookupLocation
|
||||||
@@ -71,27 +72,7 @@ class NewResolveOldInference(
|
|||||||
|
|
||||||
val baseContext = Context(scopeTower, name, context, tracing)
|
val baseContext = Context(scopeTower, name, context, tracing)
|
||||||
|
|
||||||
val processor =
|
var processor = createResolveProcessor(kind, explicitReceiver, context, baseContext)
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.collectAllCandidates) {
|
if (context.collectAllCandidates) {
|
||||||
val allCandidates = towerResolver.collectAllCandidates(baseContext, processor)
|
val allCandidates = towerResolver.collectAllCandidates(baseContext, processor)
|
||||||
@@ -99,11 +80,47 @@ class NewResolveOldInference(
|
|||||||
result.allCandidates = allCandidates.map { it.resolvedCall as MutableResolvedCall<CallableDescriptor> }
|
result.allCandidates = allCandidates.map { it.resolvedCall as MutableResolvedCall<CallableDescriptor> }
|
||||||
return result
|
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)
|
val candidates = towerResolver.runResolve(baseContext, processor, useOrder = kind != CallResolver.ResolveKind.CALLABLE_REFERENCE)
|
||||||
return convertToOverloadResults(candidates, tracing, context)
|
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(
|
private fun createProcessorWithReceiverValueOrEmpty(
|
||||||
explicitReceiver: Receiver?,
|
explicitReceiver: Receiver?,
|
||||||
create: (ReceiverValue?) -> ScopeTowerProcessor<Candidate>
|
create: (ReceiverValue?) -> ScopeTowerProcessor<Candidate>
|
||||||
@@ -219,6 +236,9 @@ class NewResolveOldInference(
|
|||||||
|
|
||||||
private fun checkInfixAndOperator(call: Call, descriptor: CallableDescriptor): List<ResolutionDiagnostic> {
|
private fun checkInfixAndOperator(call: Call, descriptor: CallableDescriptor): List<ResolutionDiagnostic> {
|
||||||
if (descriptor !is FunctionDescriptor || ErrorUtils.isError(descriptor)) return emptyList()
|
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 conventionError = if (isConventionCall(call) && !descriptor.isOperator) InvokeConventionCallNoOperatorModifier else null
|
||||||
val infixError = if (isInfixCall(call) && !descriptor.isInfix) InfixCallNoInfixModifier else null
|
val infixError = if (isInfixCall(call) && !descriptor.isInfix) InfixCallNoInfixModifier else null
|
||||||
|
|||||||
@@ -101,4 +101,5 @@ object ExtensionWithStaticTypeWithDynamicReceiver: ResolutionDiagnostic(Resoluti
|
|||||||
object HiddenDescriptor: ResolutionDiagnostic(ResolutionCandidateApplicability.HIDDEN)
|
object HiddenDescriptor: ResolutionDiagnostic(ResolutionCandidateApplicability.HIDDEN)
|
||||||
|
|
||||||
object InvokeConventionCallNoOperatorModifier : ResolutionDiagnostic(ResolutionCandidateApplicability.CONVENTION_ERROR)
|
object InvokeConventionCallNoOperatorModifier : ResolutionDiagnostic(ResolutionCandidateApplicability.CONVENTION_ERROR)
|
||||||
object InfixCallNoInfixModifier : ResolutionDiagnostic(ResolutionCandidateApplicability.CONVENTION_ERROR)
|
object InfixCallNoInfixModifier : ResolutionDiagnostic(ResolutionCandidateApplicability.CONVENTION_ERROR)
|
||||||
|
object DeprecatedUnaryPlusAsPlus : ResolutionDiagnostic(ResolutionCandidateApplicability.CONVENTION_ERROR)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ operator fun String.unaryPlus(): Int = 0
|
|||||||
fun test() {
|
fun test() {
|
||||||
requireInt(+ "")
|
requireInt(+ "")
|
||||||
requireInt(+ Example())
|
requireInt(+ Example())
|
||||||
requireString(<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>+<!> ExampleDeprecated())
|
requireString(<!DEPRECATED_UNARY_PLUS_MINUS!>+ ExampleDeprecated()<!>)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requireInt(n: Int) {}
|
fun requireInt(n: Int) {}
|
||||||
@@ -26,7 +26,7 @@ class Example2 {
|
|||||||
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun minus() = this
|
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun minus() = this
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>+<!>this
|
<!DEPRECATED_UNARY_PLUS_MINUS!>+this<!>
|
||||||
<!UNRESOLVED_REFERENCE!>-<!>this
|
<!DEPRECATED_UNARY_PLUS_MINUS!>-this<!>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Vendored
+1
-1
@@ -27,7 +27,7 @@ fun dynamic.test() {
|
|||||||
<!DEBUG_INFO_DYNAMIC!>this<!>()
|
<!DEBUG_INFO_DYNAMIC!>this<!>()
|
||||||
|
|
||||||
C() + C()
|
C() + C()
|
||||||
<!UNRESOLVED_REFERENCE!>+<!>C()
|
<!DEPRECATED_UNARY_PLUS_MINUS!><!NO_VALUE_FOR_PARAMETER!>+<!>C()<!>
|
||||||
|
|
||||||
this <!DEBUG_INFO_DYNAMIC!>+<!> C()
|
this <!DEBUG_INFO_DYNAMIC!>+<!> C()
|
||||||
|
|
||||||
|
|||||||
@@ -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 (11: 20) A(0) plus A(1) plus 2
|
||||||
Function call (12: 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 (15: 7) a += 1
|
||||||
Function call (6: 30) fun plus(a: A): A = this + a.n
|
Function call (6: 30) fun plus(a: A): A = this + a.n
|
||||||
|
Unclassified usage (18: 5) +A(0)
|
||||||
Reference in New Issue
Block a user