[debugger] Convert DfaAssistProvider to Kotlin

GitOrigin-RevId: ce66166e4fea23a31231c657969df36ff8ed6d0d
This commit is contained in:
Maksim Zuev
2025-06-13 16:50:41 +00:00
committed by intellij-monorepo-bot
parent 7f143cd6f6
commit cf175fb5da
2 changed files with 70 additions and 59 deletions
@@ -1,50 +1,32 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.debugger.engine.dfaassist;
package com.intellij.debugger.engine.dfaassist
import com.intellij.codeInspection.dataFlow.TypeConstraint;
import com.intellij.codeInspection.dataFlow.TypeConstraints;
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.jdi.StackFrameProxyEx;
import com.intellij.lang.LanguageExtension;
import com.intellij.psi.PsiElement;
import com.sun.jdi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.intellij.codeInspection.dataFlow.TypeConstraint
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue
import com.intellij.debugger.engine.evaluation.EvaluateException
import com.intellij.debugger.jdi.StackFrameProxyEx
import com.intellij.lang.LanguageExtension
import com.intellij.psi.PsiElement
import com.sun.jdi.*
/**
* Language specific helpers to implement DFAAssist (for JVM languages only)
*/
public interface DfaAssistProvider {
LanguageExtension<DfaAssistProvider> EP_NAME = new LanguageExtension<>("com.intellij.debugger.dfaAssistProvider");
/**
* A sentinel to represent null constant.
*
* @see #getJdiValueForDfaVariable(StackFrameProxyEx, DfaVariableValue, PsiElement)
*/
Value NullConst = new Value() {
@Override
public VirtualMachine virtualMachine() { return null; }
@Override
public Type type() { return null; }
@Override
public String toString() { return "null"; }
};
interface DfaAssistProvider {
/**
* Represents a 'virtual' boxed value which in fact does not exist in the VM memory.
* Can be useful to virtually undo optimizations like instantiation of inline function generic parameter with a primitive value in Kotlin.
*
* @param value a primitive value to box
* @param type type of the box (e.g. {@code java.lang.Integer})
* @param type type of the box (e.g. `java.lang.Integer`)
*/
record BoxedValue(@NotNull Value value, @NotNull ReferenceType type) implements Value {
@Override
public VirtualMachine virtualMachine() {
return value.virtualMachine();
data class BoxedValue(val value: Value, val type: ReferenceType) : Value {
override fun virtualMachine(): VirtualMachine? {
return value.virtualMachine()
}
override fun type(): Type {
return type
}
}
@@ -56,7 +38,7 @@ public interface DfaAssistProvider {
* @return true if debugger location likely matches to the editor location;
* false if definitely doesn't match (in this case, DFA Assist will be turned off)
*/
boolean locationMatches(@NotNull PsiElement element, @NotNull Location location);
fun locationMatches(element: PsiElement, location: Location): Boolean
/**
* @param element psi element the debugger state points at
@@ -64,46 +46,75 @@ public interface DfaAssistProvider {
* Currently, at this anchor interpretation stack must be empty. May return null if DFA assist cannot start
* at current context.
*/
@Nullable PsiElement getAnchor(@NotNull PsiElement element);
fun getAnchor(element: PsiElement): PsiElement?
/**
* @param anchor anchor returned by {@link #getAnchor(PsiElement)} call
* @param anchor anchor returned by [.getAnchor] call
* @return code block to analyze via DFA assist (e.g., method body, loop body, etc.)
*/
@Nullable PsiElement getCodeBlock(@NotNull PsiElement anchor);
fun getCodeBlock(anchor: PsiElement): PsiElement?
/**
* @param proxy proxy to create JDI values
* @param var DfaVariableValue to find value for
* @param anchor anchor previously returned by {@link #getAnchor(PsiElement)} call, where analysis takes place
* @param anchor anchor previously returned by [.getAnchor] call, where analysis takes place
* @return JDI value for a variable; null if value is not known; NullConst if value is known to be null
* (use {@link #wrap(Value)} utility method for this purpose).
* (use [.wrap] utility method for this purpose).
* @throws EvaluateException if proxy throws
*/
@Nullable Value getJdiValueForDfaVariable(@NotNull StackFrameProxyEx proxy,
@NotNull DfaVariableValue var,
@NotNull PsiElement anchor) throws EvaluateException;
@Throws(EvaluateException::class)
fun getJdiValueForDfaVariable(
proxy: StackFrameProxyEx,
`var`: DfaVariableValue,
anchor: PsiElement,
): Value?
/**
* @return a new listener to attach to DFA session that will gather DFAAssist hints
*/
@NotNull DebuggerDfaListener createListener();
fun createListener(): DebuggerDfaListener
/**
* @param anchor a context PsiElement previously returned by {@link #getAnchor(PsiElement)}
* @param anchor a context PsiElement previously returned by [.getAnchor]
* @param jvmClassName JVM class name like "java/lang/String"
* @return a {@link TypeConstraint} suitable for the current language;
* {@link TypeConstraints#TOP} if class is not resolved
* @return a [TypeConstraint] suitable for the current language;
* [com.intellij.codeInspection.dataFlow.TypeConstraints.TOP] if class is not resolved
*/
@NotNull TypeConstraint constraintFromJvmClassName(@NotNull PsiElement anchor, @NotNull String jvmClassName);
fun constraintFromJvmClassName(anchor: PsiElement, jvmClassName: String): TypeConstraint
/**
* A helper method to implement {@link #getJdiValueForDfaVariable(StackFrameProxyEx, DfaVariableValue, PsiElement)}
*
* @param value value to wrap
* @return NullConst if value is null; value otherwise
*/
static @NotNull Value wrap(@Nullable Value value) {
return value == null ? NullConst : value;
companion object {
/**
* A helper method to implement [.getJdiValueForDfaVariable]
*
* @param value value to wrap
* @return NullConst if value is null; value otherwise
*/
@JvmStatic
fun wrap(value: Value?): Value {
return value ?: NullConst
}
@JvmField
val EP_NAME: LanguageExtension<DfaAssistProvider?> = LanguageExtension<DfaAssistProvider?>("com.intellij.debugger.dfaAssistProvider")
/**
* A sentinel to represent null constant.
*
* @see .getJdiValueForDfaVariable
*/
@JvmField
val NullConst: Value = object : Value {
override fun virtualMachine(): VirtualMachine? {
return null
}
override fun type(): Type? {
return null
}
override fun toString(): String {
return "null"
}
}
}
}
@@ -108,9 +108,9 @@ interface JdiValueInfo {
return new StringConstant(stringReference.value());
}
if (value instanceof DfaAssistProvider.BoxedValue boxedValue) {
DfConstantType<?> wrappedConstant = primitiveConstant(boxedValue.value());
DfConstantType<?> wrappedConstant = primitiveConstant(boxedValue.getValue());
if (wrappedConstant != null) {
return new ObjectWithSpecialField(boxedValue.type(), SpecialField.UNBOX, new PrimitiveConstant(wrappedConstant));
return new ObjectWithSpecialField(boxedValue.getType(), SpecialField.UNBOX, new PrimitiveConstant(wrappedConstant));
}
}
if (value instanceof ObjectReference ref) {