[kotlin-dfa] Debugger assist: boxed boolean support

Fixes IDEA-360006 Kotlin Debugger: no DFA if-hint for nullable boolean

GitOrigin-RevId: 4b1476cb9a7fc2d8c2315942dc6cbf7a67f012a4
This commit is contained in:
Tagir Valeev
2024-10-01 16:09:02 +02:00
committed by intellij-monorepo-bot
parent b16db29dc8
commit 757b37a777
2 changed files with 25 additions and 1 deletions

View File

@@ -3,9 +3,11 @@ package org.jetbrains.kotlin.idea.k2.debugger.dfaassist
import com.intellij.codeInspection.dataFlow.TypeConstraint
import com.intellij.codeInspection.dataFlow.TypeConstraints
import com.intellij.codeInspection.dataFlow.jvm.SpecialField
import com.intellij.codeInspection.dataFlow.lang.DfaAnchor
import com.intellij.codeInspection.dataFlow.lang.UnsatisfiedConditionProblem
import com.intellij.codeInspection.dataFlow.memory.DfaMemoryState
import com.intellij.codeInspection.dataFlow.types.DfReferenceType
import com.intellij.codeInspection.dataFlow.types.DfTypes
import com.intellij.codeInspection.dataFlow.value.DfaValue
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue
@@ -171,7 +173,10 @@ class K2DfaAssistProvider : DfaAssistProvider {
val hints = hashMapOf<PsiElement, DfaHint>()
override fun beforePush(args: Array<out DfaValue>, value: DfaValue, anchor: DfaAnchor, state: DfaMemoryState) {
val dfType = state.getDfType(value)
var dfType = state.getDfType(value)
if (dfType is DfReferenceType && dfType.constraint.unboxedType == DfTypes.BOOLEAN) {
dfType = SpecialField.UNBOX.getFromQualifier(state.getDfTypeIncludingDerived(value))
}
var psi = when (anchor) {
is KotlinAnchor.KotlinExpressionAnchor -> {
if (!shouldTrackExpressionValue(anchor.expression)) return

View File

@@ -418,6 +418,25 @@ class K2DfaAssistTest : DfaAssistTest(), ExpectedPluginModeProvider {
}
}
fun testNullableBoolean() {
val text = """
fun main() {
callNullable(false, false)
}
fun callNullable(nullable: Boolean?, nonNullable: Boolean) {
<caret>val abc = 123
if (nullable/*FALSE*/!!) /*unreachable_start*/println("alfa")/*unreachable_end*/
if (nullable/*FALSE*/) /*unreachable_start*/println("bravo")/*unreachable_end*/
if (nonNullable/*FALSE*/) /*unreachable_start*/println("charlie")/*unreachable_end*/
}
"""
doTest(text) { vm, frame ->
frame.addVariable("nullable", MockValue.createValue(false, vm))
frame.addVariable("nonNullable", MockBooleanValue(vm, false))
}
}
private fun doTest(text: String, mockValues: BiConsumer<MockVirtualMachine, MockStackFrame>) {
doTest(text, mockValues, "Test.kt")
}