IDEA-165155 Java conditional breakpoint on expression or single-line lambda does not give access to lambda parameters

This commit is contained in:
Egor.Ushakov
2017-04-05 15:04:27 +03:00
parent adabf98718
commit 04a549e4bb
7 changed files with 109 additions and 68 deletions
@@ -25,6 +25,7 @@ import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
import com.intellij.debugger.requests.ClassPrepareRequestor;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
@@ -203,18 +204,26 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio
return new JavaSourcePosition(sourcePosition, location.declaringType(), method, lambdaOrdinal);
}
private static class JavaSourcePosition extends RemappedSourcePosition {
public static class JavaSourcePosition extends RemappedSourcePosition {
private final String myExpectedClassName;
private final String myExpectedMethodName;
private final int myLambdaOrdinal;
public JavaSourcePosition(SourcePosition delegate, ReferenceType declaringType, Method method, int lambdaOrdinal) {
public JavaSourcePosition(@NotNull SourcePosition delegate, ReferenceType declaringType, Method method, int lambdaOrdinal) {
super(delegate);
myExpectedClassName = declaringType != null ? declaringType.name() : null;
myExpectedMethodName = method != null ? method.name() : null;
myLambdaOrdinal = lambdaOrdinal;
}
public JavaSourcePosition(@NotNull SourcePosition delegate, int lambdaOrdinal) {
super(delegate);
assert lambdaOrdinal > -1;
myExpectedClassName = null;
myExpectedMethodName = "lambda$"; // fake lambda name
myLambdaOrdinal = lambdaOrdinal;
}
private PsiElement remapElement(PsiElement element) {
String name = JVMNameUtil.getClassVMName(getEnclosingClass(element));
if (name != null && !name.equals(myExpectedClassName)) {
@@ -244,37 +253,34 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio
@Override
public SourcePosition mapDelegate(final SourcePosition original) {
return ApplicationManager.getApplication().runReadAction(new Computable<SourcePosition>() {
@Override
public SourcePosition compute() {
PsiFile file = original.getFile();
int line = original.getLine();
if (DebuggerUtilsEx.isLambdaName(myExpectedMethodName) && myLambdaOrdinal > -1) {
List<PsiLambdaExpression> lambdas = DebuggerUtilsEx.collectLambdas(original, true);
return ReadAction.compute(() -> {
PsiFile file = original.getFile();
int line = original.getLine();
if (DebuggerUtilsEx.isLambdaName(myExpectedMethodName) && myLambdaOrdinal > -1) {
List<PsiLambdaExpression> lambdas = DebuggerUtilsEx.collectLambdas(original, true);
Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
if (document == null || line >= document.getLineCount()) {
return original;
}
if (myLambdaOrdinal < lambdas.size()) {
PsiElement firstElem = DebuggerUtilsEx.getFirstElementOnTheLine(lambdas.get(myLambdaOrdinal), document, line);
if (firstElem != null) {
return SourcePosition.createFromElement(firstElem);
}
Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
if (document == null || line >= document.getLineCount()) {
return original;
}
if (myLambdaOrdinal < lambdas.size()) {
PsiElement firstElem = DebuggerUtilsEx.getFirstElementOnTheLine(lambdas.get(myLambdaOrdinal), document, line);
if (firstElem != null) {
return SourcePosition.createFromElement(firstElem);
}
}
else {
// There may be more than one class/method code on the line, so we need to find out the correct place
for (PsiElement elem : getLineElements(file, line)) {
PsiElement remappedElement = remapElement(elem);
if (remappedElement != null) {
if (remappedElement.getTextOffset() <= original.getOffset()) break;
return SourcePosition.createFromElement(remappedElement);
}
}
}
return original;
}
else {
// There may be more than one class/method code on the line, so we need to find out the correct place
for (PsiElement elem : getLineElements(file, line)) {
PsiElement remappedElement = remapElement(elem);
if (remappedElement != null) {
if (remappedElement.getTextOffset() <= original.getOffset()) break;
return SourcePosition.createFromElement(remappedElement);
}
}
}
return original;
});
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@ abstract class RemappedSourcePosition extends SourcePosition {
private SourcePosition myDelegate;
private boolean myMapped = false;
public RemappedSourcePosition(SourcePosition delegate) {
public RemappedSourcePosition(@NotNull SourcePosition delegate) {
myDelegate = delegate;
}
@@ -761,6 +761,20 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils {
return null;
}
@Nullable
public static SourcePosition toSourcePosition(@Nullable XSourcePosition position, Project project) {
if (position != null) {
if (position instanceof JavaXSourcePosition) {
return ((JavaXSourcePosition)position).mySourcePosition;
}
PsiFile psiFile = PsiManager.getInstance(project).findFile(position.getFile());
if (psiFile != null) {
return SourcePosition.createFromLine(psiFile, position.getLine());
}
}
return null;
}
private static class JavaXSourcePosition implements XSourcePosition, ExecutionPointHighlighter.HighlighterProvider {
private final SourcePosition mySourcePosition;
@NotNull private final VirtualFile myFile;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@ import com.intellij.debugger.engine.JVMNameUtil;
import com.intellij.debugger.engine.events.DebuggerCommandImpl;
import com.intellij.debugger.engine.requests.RequestManagerImpl;
import com.intellij.debugger.impl.DebuggerContextImpl;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
@@ -235,14 +236,9 @@ public abstract class BreakpointWithHighlighter<P extends JavaBreakpointProperti
@Override
public void reload() {
ApplicationManager.getApplication().assertReadAccessAllowed();
XSourcePosition position = myXBreakpoint.getSourcePosition();
PsiFile psiFile = getPsiFile();
if (position != null && psiFile != null) {
mySourcePosition = SourcePosition.createFromLine(psiFile, position.getLine());
reload(psiFile);
}
else {
mySourcePosition = null;
mySourcePosition = DebuggerUtilsEx.toSourcePosition(myXBreakpoint.getSourcePosition(), myProject);
if (mySourcePosition != null) {
reload(mySourcePosition.getFile());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package com.intellij.debugger.ui.breakpoints;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.HelpID;
import com.intellij.debugger.SourcePosition;
import com.intellij.debugger.engine.PositionManagerImpl;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.editor.Document;
@@ -33,6 +34,7 @@ import com.intellij.xdebugger.breakpoints.XBreakpoint;
import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule;
import com.intellij.xdebugger.impl.XSourcePositionImpl;
import com.intellij.xdebugger.impl.breakpoints.XLineBreakpointImpl;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -99,12 +101,11 @@ public class JavaLineBreakpointType extends JavaLineBreakpointTypeBase<JavaLineB
@NotNull
@Override
public List<JavaBreakpointVariant> computeVariants(@NotNull Project project, @NotNull XSourcePosition position) {
PsiFile file = PsiManager.getInstance(project).findFile(position.getFile());
if (file == null) {
SourcePosition pos = DebuggerUtilsEx.toSourcePosition(position, project);
if (pos == null) {
return Collections.emptyList();
}
SourcePosition pos = SourcePosition.createFromLine(file, position.getLine());
List<PsiLambdaExpression> lambdas = DebuggerUtilsEx.collectLambdas(pos, true);
if (lambdas.isEmpty()) {
return Collections.emptyList();
@@ -116,7 +117,7 @@ public class JavaLineBreakpointType extends JavaLineBreakpointTypeBase<JavaLineB
return Collections.emptyList();
}
Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
Document document = PsiDocumentManager.getInstance(project).getDocument(pos.getFile());
if (document == null) {
return Collections.emptyList();
}
@@ -246,22 +247,49 @@ public class JavaLineBreakpointType extends JavaLineBreakpointTypeBase<JavaLineB
@Nullable
@Override
public TextRange getHighlightRange(XLineBreakpoint<JavaLineBreakpointProperties> breakpoint) {
JavaLineBreakpointProperties properties = breakpoint.getProperties();
if (properties != null) {
Integer ordinal = properties.getLambdaOrdinal();
if (ordinal != null) {
Breakpoint javaBreakpoint = BreakpointManager.getJavaBreakpoint(breakpoint);
if (javaBreakpoint instanceof LineBreakpoint) {
PsiElement method = getContainingMethod((LineBreakpoint)javaBreakpoint);
if (method != null) {
return method.getTextRange();
}
Integer ordinal = getLambdaOrdinal(breakpoint);
if (ordinal != null) {
Breakpoint javaBreakpoint = BreakpointManager.getJavaBreakpoint(breakpoint);
if (javaBreakpoint instanceof LineBreakpoint) {
PsiElement method = getContainingMethod((LineBreakpoint)javaBreakpoint);
if (method != null) {
return method.getTextRange();
}
}
}
return null;
}
@Override
public XSourcePosition getSourcePosition(@NotNull XBreakpoint<JavaLineBreakpointProperties> breakpoint) {
Integer ordinal = getLambdaOrdinal(breakpoint);
if (ordinal != null && ordinal > -1) {
SourcePosition linePosition = createLineSourcePosition((XLineBreakpointImpl)breakpoint);
if (linePosition != null) {
return DebuggerUtilsEx.toXSourcePosition(new PositionManagerImpl.JavaSourcePosition(linePosition, ordinal));
}
}
return null;
}
@Nullable
private static Integer getLambdaOrdinal(XBreakpoint<JavaLineBreakpointProperties> breakpoint) {
JavaLineBreakpointProperties properties = breakpoint.getProperties();
return properties != null ? properties.getLambdaOrdinal() : null;
}
@Nullable
private static SourcePosition createLineSourcePosition(XLineBreakpointImpl breakpoint) {
VirtualFile file = breakpoint.getFile();
if (file != null) {
PsiFile psiFile = PsiManager.getInstance(breakpoint.getProject()).findFile(file);
if (psiFile != null) {
return SourcePosition.createFromLine(psiFile, breakpoint.getLine());
}
}
return null;
}
@Override
public boolean canBeHitInOtherPlaces() {
return true; // line breakpoints could be hit in other versions of the same classes
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -76,10 +76,10 @@ public abstract class XLineBreakpointType<P extends XBreakpointProperties> exten
}
/**
* Source position for line breakpoint is determined by its file and line
* Source position for line breakpoint by default is determined by its file and line
*/
@Override
public final XSourcePosition getSourcePosition(@NotNull XBreakpoint<P> breakpoint) {
public XSourcePosition getSourcePosition(@NotNull XBreakpoint<P> breakpoint) {
return null;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,8 +17,6 @@ package com.intellij.xdebugger.impl.breakpoints;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
@@ -148,7 +146,7 @@ public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreak
}
@Nullable
private VirtualFile getFile() {
public VirtualFile getFile() {
return VirtualFileManager.getInstance().findFileByUrl(getFileUrl());
}
@@ -191,13 +189,12 @@ public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreak
@Override
public XSourcePosition getSourcePosition() {
if (mySourcePosition != null) {
return mySourcePosition;
}
mySourcePosition = super.getSourcePosition();
if (mySourcePosition == null) {
new ReadAction() {
@Override
protected void run(@NotNull Result result) {
mySourcePosition = XDebuggerUtil.getInstance().createPosition(getFile(), getLine());
}
}.execute();
mySourcePosition = XDebuggerUtil.getInstance().createPosition(getFile(), getLine());
}
return mySourcePosition;
}