Public members should have bigger priority in debugContext
#KT-10634 Fixed
This commit is contained in:
+29
-10
@@ -19,15 +19,13 @@ package org.jetbrains.kotlin.resolve.calls.results
|
||||
import gnu.trove.THashSet
|
||||
import gnu.trove.TObjectHashingStrategy
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.*
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.toHandle
|
||||
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
@@ -42,7 +40,8 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
fun <D : CallableDescriptor> findMaximallySpecific(
|
||||
candidates: Set<MutableResolvedCall<D>>,
|
||||
checkArgumentsMode: CheckArgumentTypesMode,
|
||||
discriminateGenerics: Boolean
|
||||
discriminateGenerics: Boolean,
|
||||
isDebuggerContext: Boolean
|
||||
): MutableResolvedCall<D>? =
|
||||
if (candidates.size <= 1)
|
||||
candidates.firstOrNull()
|
||||
@@ -56,7 +55,7 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
}.singleOrNull()
|
||||
|
||||
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS ->
|
||||
findMaximallySpecificCall(candidates, discriminateGenerics)
|
||||
findMaximallySpecificCall(candidates, discriminateGenerics, isDebuggerContext)
|
||||
}
|
||||
|
||||
fun <D : CallableDescriptor> findMaximallySpecificVariableAsFunctionCalls(candidates: Set<MutableResolvedCall<D>>): Set<MutableResolvedCall<D>> {
|
||||
@@ -67,7 +66,7 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
throw AssertionError("Regular call among variable-as-function calls: $it")
|
||||
}
|
||||
|
||||
val maxSpecificVariableCall = findMaximallySpecificCall(variableCalls, false) ?: return emptySet()
|
||||
val maxSpecificVariableCall = findMaximallySpecificCall(variableCalls, false, false) ?: return emptySet()
|
||||
|
||||
return candidates.filterTo(newResolvedCallSet<MutableResolvedCall<D>>(2)) {
|
||||
it.resultingVariableDescriptor == maxSpecificVariableCall.resultingDescriptor
|
||||
@@ -76,7 +75,8 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
|
||||
private fun <D : CallableDescriptor> findMaximallySpecificCall(
|
||||
candidates: Set<MutableResolvedCall<D>>,
|
||||
discriminateGenerics: Boolean
|
||||
discriminateGenerics: Boolean,
|
||||
isDebuggerContext: Boolean
|
||||
): MutableResolvedCall<D>? {
|
||||
val filteredCandidates = uniquifyCandidatesSet(candidates)
|
||||
|
||||
@@ -97,7 +97,10 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
}
|
||||
}
|
||||
|
||||
return bestCandidatesByParameterTypes.exactMaxWith { call1, call2 -> isOfNotLessSpecificShape(call1, call2) }?.resolvedCall
|
||||
return bestCandidatesByParameterTypes.exactMaxWith {
|
||||
call1, call2 ->
|
||||
isOfNotLessSpecificShape(call1, call2) && isOfNotLessSpecificVisibilityForDebugger(call1, call2, isDebuggerContext)
|
||||
}?.resolvedCall
|
||||
}
|
||||
|
||||
private inline fun <C : Any> Collection<C>.exactMaxWith(isNotWorse: (C, C) -> Boolean): C? {
|
||||
@@ -231,6 +234,22 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
return true
|
||||
}
|
||||
|
||||
private fun <D: CallableDescriptor, K> isOfNotLessSpecificVisibilityForDebugger(
|
||||
call1: CandidateCallWithArgumentMapping<D, K>,
|
||||
call2: CandidateCallWithArgumentMapping<D, K>,
|
||||
isDebuggerContext: Boolean
|
||||
): Boolean {
|
||||
if (isDebuggerContext) {
|
||||
val isMoreVisible1 = Visibilities.compare(
|
||||
call1.resolvedCall.resultingDescriptor.visibility,
|
||||
call2.resolvedCall.resultingDescriptor.visibility
|
||||
)
|
||||
if (isMoreVisible1 != null && isMoreVisible1 < 0) return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if `d1` is definitely not less specific than `d2`,
|
||||
* `false` if `d1` is definitely less specific than `d2`,
|
||||
|
||||
+6
-4
@@ -96,7 +96,8 @@ public class ResolutionResultsHandler {
|
||||
Set<MutableResolvedCall<D>> successfulAndIncomplete = Sets.newLinkedHashSet();
|
||||
successfulAndIncomplete.addAll(successfulCandidates);
|
||||
successfulAndIncomplete.addAll(incompleteCandidates);
|
||||
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(successfulAndIncomplete, true, checkArgumentsMode);
|
||||
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(
|
||||
successfulAndIncomplete, true, context.isDebuggerContext, checkArgumentsMode);
|
||||
if (results.isSingleResult()) {
|
||||
MutableResolvedCall<D> resultingCall = results.getResultingCall();
|
||||
resultingCall.getTrace().moveAllMyDataTo(context.trace);
|
||||
@@ -147,7 +148,7 @@ public class ResolutionResultsHandler {
|
||||
if (severityLevel.contains(ARGUMENTS_MAPPING_ERROR)) {
|
||||
return recordFailedInfo(tracing, trace, thisLevel);
|
||||
}
|
||||
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(thisLevel, false, checkArgumentsMode);
|
||||
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(thisLevel, false, false, checkArgumentsMode);
|
||||
return recordFailedInfo(tracing, trace, results.getResultingCalls());
|
||||
}
|
||||
}
|
||||
@@ -188,6 +189,7 @@ public class ResolutionResultsHandler {
|
||||
public <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> chooseAndReportMaximallySpecific(
|
||||
@NotNull Set<MutableResolvedCall<D>> candidates,
|
||||
boolean discriminateGenerics,
|
||||
boolean isDebuggerContext,
|
||||
@NotNull CheckArgumentTypesMode checkArgumentsMode
|
||||
) {
|
||||
if (candidates.size() == 1) {
|
||||
@@ -203,14 +205,14 @@ public class ResolutionResultsHandler {
|
||||
return OverloadResolutionResultsImpl.success(noOverrides.iterator().next());
|
||||
}
|
||||
|
||||
MutableResolvedCall<D> maximallySpecific = overloadingConflictResolver.findMaximallySpecific(noOverrides, checkArgumentsMode, false);
|
||||
MutableResolvedCall<D> maximallySpecific = overloadingConflictResolver.findMaximallySpecific(noOverrides, checkArgumentsMode, false, isDebuggerContext);
|
||||
if (maximallySpecific != null) {
|
||||
return OverloadResolutionResultsImpl.success(maximallySpecific);
|
||||
}
|
||||
|
||||
if (discriminateGenerics) {
|
||||
MutableResolvedCall<D> maximallySpecificGenericsDiscriminated = overloadingConflictResolver.findMaximallySpecific(
|
||||
noOverrides, checkArgumentsMode, true);
|
||||
noOverrides, checkArgumentsMode, true, isDebuggerContext);
|
||||
if (maximallySpecificGenericsDiscriminated != null) {
|
||||
return OverloadResolutionResultsImpl.success(maximallySpecificGenericsDiscriminated);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
LineBreakpoint created at privateMembersPriority.kt:22
|
||||
LineBreakpoint created at privateMembersPriority.kt:34
|
||||
LineBreakpoint created at privateMembersPriority.kt:41
|
||||
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! privateMembersPriority.PrivateMembersPriorityKt
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
privateMembersPriority.kt:22
|
||||
Compile bytecode for privateFun()
|
||||
privateMembersPriority.kt:34
|
||||
Compile bytecode for javaClass.size
|
||||
privateMembersPriority.kt:41
|
||||
Compile bytecode for TwoPrivateFun().foo(1)
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package privateMembersPriority
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
Receiver2().test1()
|
||||
test2()
|
||||
test3()
|
||||
}
|
||||
|
||||
class Receiver1 {
|
||||
private fun privateFun() = 1
|
||||
}
|
||||
|
||||
class Receiver2 {
|
||||
fun privateFun() = 2
|
||||
|
||||
// In IDE -> privateFun() will return 2, because privateFun from Receiver is invisible in current scope
|
||||
fun test1() {
|
||||
with(Receiver1()) {
|
||||
// EXPRESSION: privateFun()
|
||||
// RESULT: 1: I
|
||||
//Breakpoint!
|
||||
privateFun()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In debuggerContext there are two properties size in ArrayList (java field + kotlin property)
|
||||
fun test2() {
|
||||
val javaClass = arrayListOf(1)
|
||||
|
||||
// EXPRESSION: javaClass.size
|
||||
// RESULT: 1: I
|
||||
//Breakpoint!
|
||||
javaClass.size
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
// EXPRESSION: TwoPrivateFun().foo(1)
|
||||
// RESULT: 1: I
|
||||
//Breakpoint!
|
||||
val a = 1
|
||||
}
|
||||
|
||||
class TwoPrivateFun {
|
||||
private fun foo(i: Int) = 1
|
||||
private fun foo(i: Double) = 2
|
||||
}
|
||||
+6
@@ -778,6 +778,12 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
|
||||
doMultipleBreakpointsTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("privateMembersPriority.kt")
|
||||
public void testPrivateMembersPriority() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/privateMembersPriority.kt");
|
||||
doMultipleBreakpointsTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("whenEntry.kt")
|
||||
public void testWhenEntry() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/whenEntry.kt");
|
||||
|
||||
Reference in New Issue
Block a user