Resolve unaryPlus as plus with error.

This commit is contained in:
Stanislav Erokhin
2015-12-17 16:43:44 +03:00
parent 1a6f9b8d1c
commit 7521b89b3e
5 changed files with 49 additions and 27 deletions
@@ -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<CallableDescriptor> }
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<Candidate>
@@ -219,6 +236,9 @@ class NewResolveOldInference(
private fun checkInfixAndOperator(call: Call, descriptor: CallableDescriptor): List<ResolutionDiagnostic> {
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
@@ -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)
object InfixCallNoInfixModifier : ResolutionDiagnostic(ResolutionCandidateApplicability.CONVENTION_ERROR)
object DeprecatedUnaryPlusAsPlus : ResolutionDiagnostic(ResolutionCandidateApplicability.CONVENTION_ERROR)
@@ -15,7 +15,7 @@ operator fun String.unaryPlus(): Int = 0
fun test() {
requireInt(+ "")
requireInt(+ Example())
requireString(<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>+<!> ExampleDeprecated())
requireString(<!DEPRECATED_UNARY_PLUS_MINUS!>+ ExampleDeprecated()<!>)
}
fun requireInt(n: Int) {}
@@ -26,7 +26,7 @@ class Example2 {
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun minus() = this
fun test() {
<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>+<!>this
<!UNRESOLVED_REFERENCE!>-<!>this
<!DEPRECATED_UNARY_PLUS_MINUS!>+this<!>
<!DEPRECATED_UNARY_PLUS_MINUS!>-this<!>
}
}
@@ -27,7 +27,7 @@ fun dynamic.test() {
<!DEBUG_INFO_DYNAMIC!>this<!>()
C() + C()
<!UNRESOLVED_REFERENCE!>+<!>C()
<!DEPRECATED_UNARY_PLUS_MINUS!><!NO_VALUE_FOR_PARAMETER!>+<!>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 (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
Function call (6: 30) fun plus(a: A): A = this + a.n
Unclassified usage (18: 5) +A(0)