diff --git a/python/BUILD.bazel b/python/BUILD.bazel
index d925c9e099ba..a5217a9f0eed 100644
--- a/python/BUILD.bazel
+++ b/python/BUILD.bazel
@@ -355,6 +355,7 @@ jvm_library(
"//python/python-uv/common",
"//python/common",
"//python/python-process-output:processOutput",
+ "//platform/xdebugger-impl/shared",
],
exports = [
"//python/openapi:community",
diff --git a/python/intellij.python.community.impl.iml b/python/intellij.python.community.impl.iml
index 24f92f55a91e..1cb0b2c7a959 100644
--- a/python/intellij.python.community.impl.iml
+++ b/python/intellij.python.community.impl.iml
@@ -192,5 +192,6 @@
+
\ No newline at end of file
diff --git a/python/pluginCore/resources/META-INF/plugin.xml b/python/pluginCore/resources/META-INF/plugin.xml
index 32fbea020086..012698bf5ceb 100644
--- a/python/pluginCore/resources/META-INF/plugin.xml
+++ b/python/pluginCore/resources/META-INF/plugin.xml
@@ -21,6 +21,7 @@ The Python plug-in provides smart editing for Python scripts. The feature set of
+
diff --git a/python/pluginResources/intellij.python.community.impl.xml b/python/pluginResources/intellij.python.community.impl.xml
index 621c4f9ebcee..020202b4834d 100644
--- a/python/pluginResources/intellij.python.community.impl.xml
+++ b/python/pluginResources/intellij.python.community.impl.xml
@@ -195,7 +195,6 @@
-
@@ -688,6 +687,9 @@
+
+
+
diff --git a/python/src/com/jetbrains/python/debugger/PyDebuggerEvaluator.java b/python/src/com/jetbrains/python/debugger/PyDebuggerEvaluator.java
deleted file mode 100644
index 060a9eccf432..000000000000
--- a/python/src/com/jetbrains/python/debugger/PyDebuggerEvaluator.java
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
-package com.jetbrains.python.debugger;
-
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.TextRange;
-import com.intellij.xdebugger.XSourcePosition;
-import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
-import com.jetbrains.python.console.PyConsoleIndentUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-
-public class PyDebuggerEvaluator extends XDebuggerEvaluator {
-
- private final Project myProject;
- private final PyFrameAccessor myDebugProcess;
-
- public PyDebuggerEvaluator(@NotNull Project project, final @NotNull PyFrameAccessor debugProcess) {
- myProject = project;
- myDebugProcess = debugProcess;
- }
-
- @Override
- public void evaluate(@NotNull String expression, @NotNull XEvaluationCallback callback, @Nullable XSourcePosition expressionPosition) {
- doEvaluate(expression, callback, true);
- }
-
- private PyDebugValue getNone() {
- return new PyDebugValue("", "NoneType", null, "None", false, null, null, false, false, false, null, null, myDebugProcess);
- }
-
- private void doEvaluate(final String expr, final XEvaluationCallback callback, final boolean doTrunc) {
- ApplicationManager.getApplication().executeOnPooledThread(() -> {
- String expression = expr.trim();
- if (expression.isEmpty()) {
- callback.evaluated(getNone());
- return;
- }
-
- final boolean isExpression = PyDebugSupportUtils.isExpression(myProject, expression);
- try {
- // todo: think on getting results from EXEC
- final PyDebugValue value = myDebugProcess.evaluate(expression, !isExpression, doTrunc);
- if (value.isErrorOnEval()) {
- callback.errorOccurred("{" + value.getType() + "}" + value.getValue()); //NON-NLS
- }
- else {
- callback.evaluated(value);
- }
- }
- catch (PyDebuggerException e) {
- callback.errorOccurred(e.getTracebackError());
- }
- });
- }
-
- @Override
- public @Nullable TextRange getExpressionRangeAtOffset(final Project project,
- final Document document,
- final int offset,
- boolean sideEffectsAllowed) {
- return PyDebugSupportUtils.getExpressionRangeAtOffset(project, document, offset);
- }
-
- @Override
- public @NotNull String formatTextForEvaluation(@NotNull String text) {
- return PyConsoleIndentUtil.normalize(text);
- }
-}
diff --git a/python/src/com/jetbrains/python/debugger/PyDebuggerEvaluator.kt b/python/src/com/jetbrains/python/debugger/PyDebuggerEvaluator.kt
new file mode 100644
index 000000000000..400b1cdbd4f6
--- /dev/null
+++ b/python/src/com/jetbrains/python/debugger/PyDebuggerEvaluator.kt
@@ -0,0 +1,85 @@
+// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package com.jetbrains.python.debugger
+
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.application.ReadAction
+import com.intellij.openapi.editor.Document
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.util.TextRange
+import com.intellij.openapi.util.ThrowableComputable
+import com.intellij.openapi.util.registry.Registry
+import com.intellij.psi.PsiDocumentManager
+import com.intellij.psi.PsiReference
+import com.intellij.xdebugger.XSourcePosition
+import com.intellij.xdebugger.evaluation.XDebuggerEvaluator
+import com.intellij.xdebugger.impl.evaluate.quick.XDebuggerDocumentOffsetEvaluator
+import com.intellij.xdebugger.impl.evaluate.quick.common.ValueHintType
+import com.jetbrains.python.console.PyConsoleIndentUtil
+import com.jetbrains.python.psi.PyCallExpression
+import com.jetbrains.python.psi.PyExpression
+
+internal class PyDebuggerEvaluator(private val myProject: Project, private val myDebugProcess: PyFrameAccessor) : XDebuggerEvaluator(), XDebuggerDocumentOffsetEvaluator {
+ override fun evaluate(expression: String, callback: XEvaluationCallback, expressionPosition: XSourcePosition?): Unit =
+ doEvaluate(expression, callback, true)
+
+
+ private val none: PyDebugValue
+ get() = PyDebugValue("", "NoneType", null, "None", false, null, null, false, false, false, null, null, myDebugProcess)
+
+ private fun doEvaluate(expr: String, callback: XEvaluationCallback, doTrunc: Boolean) {
+ ApplicationManager.getApplication().executeOnPooledThread(Runnable {
+ val expression = expr.trim { it <= ' ' }
+ if (expression.isEmpty()) {
+ callback.evaluated(this.none)
+ return@Runnable
+ }
+
+ val isExpression = PyDebugSupportUtils.isExpression(myProject, expression)
+ try {
+ // todo: think on getting results from EXEC
+ val value = myDebugProcess.evaluate(expression, !isExpression, doTrunc)
+ if (value.isErrorOnEval) {
+ callback.errorOccurred("{" + value.getType() + "}" + value.value) //NON-NLS
+ }
+ else {
+ callback.evaluated(value)
+ }
+ }
+ catch (e: PyDebuggerException) {
+ callback.errorOccurred(e.getTracebackError())
+ }
+ })
+ }
+
+ override fun getExpressionRangeAtOffset(project: Project?, document: Document?, offset: Int, sideEffectsAllowed: Boolean): TextRange? =
+ PyDebugSupportUtils.getExpressionRangeAtOffset(project, document, offset)
+
+ override fun formatTextForEvaluation(text: String): String = PyConsoleIndentUtil.normalize(text)
+
+ override fun evaluate(document: Document, offset: Int, hintType: ValueHintType, callback: XEvaluationCallback) {
+ if (!Registry.`is`("python.debugger.show.value.tooltip")) {
+ callback.errorOccurred("")
+ return
+ }
+
+ val ref = ReadAction.compute(ThrowableComputable {
+ PsiDocumentManager.getInstance(myProject).getPsiFile(document)?.findReferenceAt(offset)
+ })
+ if (ref == null) {
+ callback.errorOccurred("")
+ return
+ }
+
+ val element = ref.getElement()
+ when(element) {
+ is PyExpression -> {
+ if (element.getParent() is PyCallExpression) {
+ callback.errorOccurred("")
+ } else {
+ doEvaluate(element.getText(), callback, false)
+ }
+ }
+ else -> callback.errorOccurred("")
+ }
+ }
+}
\ No newline at end of file