Debugger: Remove debugger-related hacks in resolution
Candidate ordering should be the same in ordinary Kotlin code and in evaluated expressions. With the invention of 'foo_field' syntax, there is no need to do these nasty things any more.
This commit is contained in:
+3
-4
@@ -105,7 +105,7 @@ public class ResolutionResultsHandler {
|
|||||||
successfulAndIncomplete.addAll(successfulCandidates);
|
successfulAndIncomplete.addAll(successfulCandidates);
|
||||||
successfulAndIncomplete.addAll(incompleteCandidates);
|
successfulAndIncomplete.addAll(incompleteCandidates);
|
||||||
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(
|
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(
|
||||||
successfulAndIncomplete, true, context.isDebuggerContext, checkArgumentsMode, languageVersionSettings);
|
successfulAndIncomplete, true, checkArgumentsMode, languageVersionSettings);
|
||||||
if (results.isSingleResult()) {
|
if (results.isSingleResult()) {
|
||||||
MutableResolvedCall<D> resultingCall = results.getResultingCall();
|
MutableResolvedCall<D> resultingCall = results.getResultingCall();
|
||||||
resultingCall.getTrace().moveAllMyDataTo(context.trace);
|
resultingCall.getTrace().moveAllMyDataTo(context.trace);
|
||||||
@@ -160,7 +160,7 @@ public class ResolutionResultsHandler {
|
|||||||
return recordFailedInfo(tracing, trace, myResolver.filterOutEquivalentCalls(new LinkedHashSet<>(thisLevel)));
|
return recordFailedInfo(tracing, trace, myResolver.filterOutEquivalentCalls(new LinkedHashSet<>(thisLevel)));
|
||||||
}
|
}
|
||||||
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(
|
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(
|
||||||
thisLevel, false, false, checkArgumentsMode, languageVersionSettings);
|
thisLevel, false, checkArgumentsMode, languageVersionSettings);
|
||||||
return recordFailedInfo(tracing, trace, results.getResultingCalls());
|
return recordFailedInfo(tracing, trace, results.getResultingCalls());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,7 +196,6 @@ public class ResolutionResultsHandler {
|
|||||||
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> chooseAndReportMaximallySpecific(
|
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> chooseAndReportMaximallySpecific(
|
||||||
@NotNull Set<MutableResolvedCall<D>> candidates,
|
@NotNull Set<MutableResolvedCall<D>> candidates,
|
||||||
boolean discriminateGenerics,
|
boolean discriminateGenerics,
|
||||||
boolean isDebuggerContext,
|
|
||||||
@NotNull CheckArgumentTypesMode checkArgumentsMode,
|
@NotNull CheckArgumentTypesMode checkArgumentsMode,
|
||||||
@NotNull LanguageVersionSettings languageVersionSettings
|
@NotNull LanguageVersionSettings languageVersionSettings
|
||||||
) {
|
) {
|
||||||
@@ -217,7 +216,7 @@ public class ResolutionResultsHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Set<MutableResolvedCall<D>> specificCalls =
|
Set<MutableResolvedCall<D>> specificCalls =
|
||||||
myResolver.chooseMaximallySpecificCandidates(refinedCandidates, checkArgumentsMode, discriminateGenerics, isDebuggerContext);
|
myResolver.chooseMaximallySpecificCandidates(refinedCandidates, checkArgumentsMode, discriminateGenerics);
|
||||||
|
|
||||||
if (specificCalls.size() == 1) {
|
if (specificCalls.size() == 1) {
|
||||||
return OverloadResolutionResultsImpl.success(specificCalls.iterator().next());
|
return OverloadResolutionResultsImpl.success(specificCalls.iterator().next());
|
||||||
|
|||||||
@@ -129,8 +129,6 @@ class KotlinCallResolver(
|
|||||||
expectedType: UnwrappedType?,
|
expectedType: UnwrappedType?,
|
||||||
candidates: Collection<KotlinResolutionCandidate>
|
candidates: Collection<KotlinResolutionCandidate>
|
||||||
): CallResolutionResult {
|
): CallResolutionResult {
|
||||||
val isDebuggerContext = candidateFactory.scopeTower.isDebuggerContext
|
|
||||||
|
|
||||||
var refinedCandidates = candidates
|
var refinedCandidates = candidates
|
||||||
if (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.RefinedSamAdaptersPriority)) {
|
if (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.RefinedSamAdaptersPriority)) {
|
||||||
val nonSynthesized = candidates.filter { !it.resolvedCall.candidateDescriptor.isSynthesized }
|
val nonSynthesized = candidates.filter { !it.resolvedCall.candidateDescriptor.isSynthesized }
|
||||||
@@ -142,8 +140,7 @@ class KotlinCallResolver(
|
|||||||
val maximallySpecificCandidates = overloadingConflictResolver.chooseMaximallySpecificCandidates(
|
val maximallySpecificCandidates = overloadingConflictResolver.chooseMaximallySpecificCandidates(
|
||||||
refinedCandidates,
|
refinedCandidates,
|
||||||
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||||
discriminateGenerics = true, // todo
|
discriminateGenerics = true // todo
|
||||||
isDebuggerContext = isDebuggerContext
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return kotlinCallCompleter.runCompletion(candidateFactory, maximallySpecificCandidates, expectedType, resolutionCallbacks)
|
return kotlinCallCompleter.runCompletion(candidateFactory, maximallySpecificCandidates, expectedType, resolutionCallbacks)
|
||||||
|
|||||||
+1
-2
@@ -130,8 +130,7 @@ class CallableReferenceResolver(
|
|||||||
return callableReferenceOverloadConflictResolver.chooseMaximallySpecificCandidates(
|
return callableReferenceOverloadConflictResolver.chooseMaximallySpecificCandidates(
|
||||||
candidates,
|
candidates,
|
||||||
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||||
discriminateGenerics = false, // we can't specify generics explicitly for callable references
|
discriminateGenerics = false // we can't specify generics explicitly for callable references
|
||||||
isDebuggerContext = scopeTower.isDebuggerContext
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-2
@@ -49,8 +49,6 @@ internal object CheckVisibility : ResolutionPart() {
|
|||||||
val containingDescriptor = scopeTower.lexicalScope.ownerDescriptor
|
val containingDescriptor = scopeTower.lexicalScope.ownerDescriptor
|
||||||
val dispatchReceiverArgument = resolvedCall.dispatchReceiverArgument
|
val dispatchReceiverArgument = resolvedCall.dispatchReceiverArgument
|
||||||
|
|
||||||
if (scopeTower.isDebuggerContext) return
|
|
||||||
|
|
||||||
val receiverValue = dispatchReceiverArgument?.receiver?.receiverValue ?: Visibilities.ALWAYS_SUITABLE_RECEIVER
|
val receiverValue = dispatchReceiverArgument?.receiver?.receiverValue ?: Visibilities.ALWAYS_SUITABLE_RECEIVER
|
||||||
val invisibleMember =
|
val invisibleMember =
|
||||||
Visibilities.findInvisibleMember(receiverValue, resolvedCall.candidateDescriptor, containingDescriptor) ?: return
|
Visibilities.findInvisibleMember(receiverValue, resolvedCall.candidateDescriptor, containingDescriptor) ?: return
|
||||||
|
|||||||
+12
-33
@@ -61,13 +61,12 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
fun chooseMaximallySpecificCandidates(
|
fun chooseMaximallySpecificCandidates(
|
||||||
candidates: Collection<C>,
|
candidates: Collection<C>,
|
||||||
checkArgumentsMode: CheckArgumentTypesMode,
|
checkArgumentsMode: CheckArgumentTypesMode,
|
||||||
discriminateGenerics: Boolean,
|
discriminateGenerics: Boolean
|
||||||
isDebuggerContext: Boolean
|
|
||||||
): Set<C> {
|
): Set<C> {
|
||||||
candidates.setIfOneOrEmpty()?.let { return it }
|
candidates.setIfOneOrEmpty()?.let { return it }
|
||||||
|
|
||||||
val fixedCandidates = if (getVariableCandidates(candidates.first()) != null) {
|
val fixedCandidates = if (getVariableCandidates(candidates.first()) != null) {
|
||||||
findMaximallySpecificVariableAsFunctionCalls(candidates, isDebuggerContext) ?: return LinkedHashSet(candidates)
|
findMaximallySpecificVariableAsFunctionCalls(candidates) ?: return LinkedHashSet(candidates)
|
||||||
} else {
|
} else {
|
||||||
candidates
|
candidates
|
||||||
}
|
}
|
||||||
@@ -93,13 +92,13 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
return noOverrides
|
return noOverrides
|
||||||
}
|
}
|
||||||
|
|
||||||
val maximallySpecific = findMaximallySpecific(noOverrides, checkArgumentsMode, false, isDebuggerContext)
|
val maximallySpecific = findMaximallySpecific(noOverrides, checkArgumentsMode, false)
|
||||||
if (maximallySpecific != null) {
|
if (maximallySpecific != null) {
|
||||||
return setOf(maximallySpecific)
|
return setOf(maximallySpecific)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (discriminateGenerics) {
|
if (discriminateGenerics) {
|
||||||
val maximallySpecificGenericsDiscriminated = findMaximallySpecific(noOverrides, checkArgumentsMode, true, isDebuggerContext)
|
val maximallySpecificGenericsDiscriminated = findMaximallySpecific(noOverrides, checkArgumentsMode, true)
|
||||||
if (maximallySpecificGenericsDiscriminated != null) {
|
if (maximallySpecificGenericsDiscriminated != null) {
|
||||||
return setOf(maximallySpecificGenericsDiscriminated)
|
return setOf(maximallySpecificGenericsDiscriminated)
|
||||||
}
|
}
|
||||||
@@ -141,8 +140,7 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
private fun findMaximallySpecific(
|
private fun findMaximallySpecific(
|
||||||
candidates: Set<C>,
|
candidates: Set<C>,
|
||||||
checkArgumentsMode: CheckArgumentTypesMode,
|
checkArgumentsMode: CheckArgumentTypesMode,
|
||||||
discriminateGenerics: Boolean,
|
discriminateGenerics: Boolean
|
||||||
isDebuggerContext: Boolean
|
|
||||||
): C? =
|
): C? =
|
||||||
if (candidates.size <= 1)
|
if (candidates.size <= 1)
|
||||||
candidates.firstOrNull()
|
candidates.firstOrNull()
|
||||||
@@ -155,29 +153,29 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS ->
|
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS ->
|
||||||
findMaximallySpecificCall(candidates, discriminateGenerics, isDebuggerContext)
|
findMaximallySpecificCall(candidates, discriminateGenerics)
|
||||||
?: hasSAMConversion?.let { hasConversion ->
|
?: hasSAMConversion?.let { hasConversion ->
|
||||||
findMaximallySpecificCall(
|
findMaximallySpecificCall(
|
||||||
candidates.filterNotTo(mutableSetOf()) { hasConversion(it) },
|
candidates.filterNotTo(mutableSetOf()) { hasConversion(it) },
|
||||||
discriminateGenerics, isDebuggerContext
|
discriminateGenerics
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
?: findMaximallySpecificCall(
|
?: findMaximallySpecificCall(
|
||||||
candidates.filterNotTo(mutableSetOf()) { createFlatSignature(it).isSyntheticMember },
|
candidates.filterNotTo(mutableSetOf()) { createFlatSignature(it).isSyntheticMember },
|
||||||
discriminateGenerics, isDebuggerContext
|
discriminateGenerics
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// null means ambiguity between variables
|
// null means ambiguity between variables
|
||||||
private fun findMaximallySpecificVariableAsFunctionCalls(candidates: Collection<C>, isDebuggerContext: Boolean): Set<C>? {
|
private fun findMaximallySpecificVariableAsFunctionCalls(candidates: Collection<C>): Set<C>? {
|
||||||
val variableCalls = candidates.mapTo(newResolvedCallSet(candidates.size)) {
|
val variableCalls = candidates.mapTo(newResolvedCallSet(candidates.size)) {
|
||||||
getVariableCandidates(it) ?: throw AssertionError("Regular call among variable-as-function calls: $it")
|
getVariableCandidates(it) ?: throw AssertionError("Regular call among variable-as-function calls: $it")
|
||||||
}
|
}
|
||||||
|
|
||||||
val maxSpecificVariableCalls = chooseMaximallySpecificCandidates(
|
val maxSpecificVariableCalls = chooseMaximallySpecificCandidates(
|
||||||
variableCalls, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
variableCalls, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||||
isDebuggerContext = isDebuggerContext, discriminateGenerics = false
|
discriminateGenerics = false
|
||||||
)
|
)
|
||||||
|
|
||||||
val maxSpecificVariableCall = maxSpecificVariableCalls.singleOrNull() ?: return null
|
val maxSpecificVariableCall = maxSpecificVariableCalls.singleOrNull() ?: return null
|
||||||
@@ -186,11 +184,7 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findMaximallySpecificCall(
|
private fun findMaximallySpecificCall(candidates: Set<C>, discriminateGenerics: Boolean): C? {
|
||||||
candidates: Set<C>,
|
|
||||||
discriminateGenerics: Boolean,
|
|
||||||
isDebuggerContext: Boolean
|
|
||||||
): C? {
|
|
||||||
val filteredCandidates = uniquifyCandidatesSet(candidates)
|
val filteredCandidates = uniquifyCandidatesSet(candidates)
|
||||||
|
|
||||||
if (filteredCandidates.size <= 1) return filteredCandidates.singleOrNull()
|
if (filteredCandidates.size <= 1) return filteredCandidates.singleOrNull()
|
||||||
@@ -205,9 +199,7 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bestCandidatesByParameterTypes.exactMaxWith { call1, call2 ->
|
return bestCandidatesByParameterTypes.exactMaxWith { call1, call2 -> isOfNotLessSpecificShape(call1, call2) }?.origin
|
||||||
isOfNotLessSpecificShape(call1, call2) && isOfNotLessSpecificVisibilityForDebugger(call1, call2, isDebuggerContext)
|
|
||||||
}?.origin
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <C : Any> Collection<C>.exactMaxWith(isNotWorse: (C, C) -> Boolean): C? {
|
private inline fun <C : Any> Collection<C>.exactMaxWith(isNotWorse: (C, C) -> Boolean): C? {
|
||||||
@@ -361,19 +353,6 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isOfNotLessSpecificVisibilityForDebugger(
|
|
||||||
call1: FlatSignature<C>,
|
|
||||||
call2: FlatSignature<C>,
|
|
||||||
isDebuggerContext: Boolean
|
|
||||||
): Boolean {
|
|
||||||
if (isDebuggerContext) {
|
|
||||||
val isMoreVisible1 = Visibilities.compare(call1.descriptorVisibility(), call2.descriptorVisibility())
|
|
||||||
if (isMoreVisible1 != null && isMoreVisible1 < 0) return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns `true` if `d1` is definitely not less specific than `d2`,
|
* Returns `true` if `d1` is definitely not less specific than `d2`,
|
||||||
* `false` if `d1` is definitely less specific than `d2`,
|
* `false` if `d1` is definitely less specific than `d2`,
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ internal abstract class AbstractScopeTowerLevel(
|
|||||||
}
|
}
|
||||||
if (dispatchReceiverSmartCastType != null) diagnostics.add(UsedSmartCastForDispatchReceiver(dispatchReceiverSmartCastType))
|
if (dispatchReceiverSmartCastType != null) diagnostics.add(UsedSmartCastForDispatchReceiver(dispatchReceiverSmartCastType))
|
||||||
|
|
||||||
val shouldSkipVisibilityCheck = scopeTower.isDebuggerContext || scopeTower.isNewInferenceEnabled
|
val shouldSkipVisibilityCheck = scopeTower.isNewInferenceEnabled
|
||||||
if (!shouldSkipVisibilityCheck) {
|
if (!shouldSkipVisibilityCheck) {
|
||||||
Visibilities.findInvisibleMember(
|
Visibilities.findInvisibleMember(
|
||||||
getReceiverValueWithSmartCast(dispatchReceiver?.receiverValue, dispatchReceiverSmartCastType),
|
getReceiverValueWithSmartCast(dispatchReceiver?.receiverValue, dispatchReceiverSmartCastType),
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = ArrayList<String>()
|
||||||
|
<caret>val x = 5
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
a.<error descr="[INVISIBLE_MEMBER] Cannot access 'ensureCapacityInternal': it is private in 'ArrayList'">ensureCapacityInternal</error>(0)
|
||||||
Generated
+5
@@ -111,6 +111,11 @@ public class CodeFragmentHighlightingTestGenerated extends AbstractCodeFragmentH
|
|||||||
runTest("idea/testData/checker/codeFragments/privateMember.kt");
|
runTest("idea/testData/checker/codeFragments/privateMember.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("privateMembers.kt")
|
||||||
|
public void testPrivateMembers() throws Exception {
|
||||||
|
runTest("idea/testData/checker/codeFragments/privateMembers.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("protectedMember.kt")
|
@TestMetadata("protectedMember.kt")
|
||||||
public void testProtectedMember() throws Exception {
|
public void testProtectedMember() throws Exception {
|
||||||
runTest("idea/testData/checker/codeFragments/protectedMember.kt");
|
runTest("idea/testData/checker/codeFragments/protectedMember.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user