[debugger] IJPL-251143 Do not instrument breakpoints with changing local variables

IJ-CR-215549

(cherry picked from commit 18f61afb2c6ad3dae45ac5d1c012ac26e5fdec1c)


(cherry picked from commit 22b67d10a47645524bfea06e72facad70250715a)

IJ-CR-216735

GitOrigin-RevId: cdb9179c16ccedd86c4a80a2e55c3e0111091973
This commit is contained in:
Alexey.Merkulov
2026-08-03 17:29:32 +00:00
committed by intellij-monorepo-bot
parent c29f5f982f
commit 8329aab5c4
2 changed files with 33 additions and 2 deletions
@@ -269,8 +269,17 @@ public final class ExtractLightMethodObjectHandler {
extractMethodObjectProcessor.getExtractProcessor().setShowErrorDialogs(false);
final ExtractMethodObjectProcessor.MyExtractMethodProcessor extractProcessor = extractMethodObjectProcessor.getExtractProcessor();
boolean hasOutputVariables = false;
int startOffsetInContainer;
if (extractProcessor.prepare()) {
// For value-producing fragments, this includes at least the synthetic result variable. Ignore variables declared inside
// the fragment; only variables declared outside need to be written back to the original frame.
for (PsiVariable outputVariable : extractProcessor.getOutputVariables()) {
if (!isDeclaredInside(outputVariable, elementsCopy)) {
hasOutputVariables = true;
break;
}
}
boolean shown = extractProcessor.showDialog();
if (!shown) {
throw new IllegalStateException("Must return success");
@@ -324,7 +333,7 @@ public final class ExtractLightMethodObjectHandler {
final String generatedCall = copy.getText().substring(startOffset, outStatement.getTextOffset()).trim();
return new LightMethodObjectExtractedData(generatedCall,
(PsiClass)CodeStyleManager.getInstance(project).reformat(generatedClass),
originalAnchor, useMagicAccessor);
originalAnchor, useMagicAccessor, hasOutputVariables);
}
private static void generateResult(@NotNull Project project,
@@ -344,6 +353,15 @@ public final class ExtractLightMethodObjectHandler {
}
}
private static boolean isDeclaredInside(@NotNull PsiVariable variable, PsiElement[] elements) {
for (PsiElement element : elements) {
if (PsiTreeUtil.isAncestor(element, variable, false)) {
return true;
}
}
return false;
}
private static @Nullable PsiMethodCallExpression findCallExpression(@NotNull PsiFile copy, @NotNull PsiMethod method) {
PsiMethodCallExpression[] result = new PsiMethodCallExpression[1];
copy.accept(new JavaRecursiveElementVisitor() {
@@ -6,6 +6,7 @@ import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.ApiStatus;
public class LightMethodObjectExtractedData {
public static final Key<PsiMethod> REFERENCE_METHOD = Key.create("CompilingEvaluatorReferenceMethod");
@@ -14,12 +15,19 @@ public class LightMethodObjectExtractedData {
private final PsiClass myGeneratedInnerClass;
private final PsiElement myAnchor;
private final boolean myUseMagicAccessor;
private final boolean myHasOutputVariables;
public LightMethodObjectExtractedData(String generatedCallText, PsiClass generatedInnerClass, PsiElement anchor, boolean useMagicAccessor) {
@ApiStatus.Internal
public LightMethodObjectExtractedData(String generatedCallText,
PsiClass generatedInnerClass,
PsiElement anchor,
boolean useMagicAccessor,
boolean hasOutputVariables) {
myGeneratedCallText = generatedCallText;
myGeneratedInnerClass = generatedInnerClass;
myAnchor = anchor;
myUseMagicAccessor = useMagicAccessor;
myHasOutputVariables = hasOutputVariables;
}
public PsiElement getAnchor() {
@@ -37,4 +45,9 @@ public class LightMethodObjectExtractedData {
public boolean useMagicAccessor() {
return myUseMagicAccessor;
}
@ApiStatus.Internal
public boolean hasOutputVariables() {
return myHasOutputVariables;
}
}