From dd94ffddfb1debc90a20fba501c1cf7197908e06 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 15 Mar 2011 15:48:12 +0100 Subject: [PATCH] 1. nestedClasses() now return only those classes that are directly nested 2. when creating a breakpoint request and 2 classes have executable code on the same line, prefer outer class 3. when creating a breakpoint request and there are several code locations on the same line, prefer the one with the minimal codeIndex --- .../debugger/engine/PositionManagerImpl.java | 25 +++++++++------ .../debugger/jdi/VirtualMachineProxyImpl.java | 32 +++++++++++++------ .../ui/breakpoints/LineBreakpoint.java | 25 +++++++++++---- 3 files changed, 56 insertions(+), 26 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java index 59d5cd78a61b..d52466171885 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java @@ -99,11 +99,14 @@ public class PositionManagerImpl implements PositionManager { waitRequestor.set(new ClassPrepareRequestor() { public void processClassPrepare(DebugProcess debuggerProcess, ReferenceType referenceType) { final CompoundPositionManager positionManager = ((DebugProcessImpl)debuggerProcess).getPositionManager(); - if (positionManager.locationsOfLine(referenceType, position).size() > 0) { - requestor.processClassPrepare(debuggerProcess, referenceType); + final List positionClasses = positionManager.getAllClasses(position); + if (positionClasses.isEmpty()) { + // fallback + if (positionManager.locationsOfLine(referenceType, position).size() > 0) { + requestor.processClassPrepare(debuggerProcess, referenceType); + } } else { - final List positionClasses = positionManager.getAllClasses(position); if (positionClasses.contains(referenceType)) { requestor.processClassPrepare(debuggerProcess, referenceType); } @@ -267,15 +270,17 @@ public class PositionManagerImpl implements PositionManager { final List nestedTypes = vmProxy.nestedTypes(fromClass); - for (ReferenceType nested : nestedTypes) { - final ReferenceType found = findNested(nested, classToFind, classPosition); - if (found != null) { - return found; - } - } - try { final int lineNumber = classPosition.getLine() + 1; + + for (ReferenceType nested : nestedTypes) { + final ReferenceType found = findNested(nested, classToFind, classPosition); + if (found != null) { + // check if enclosing class also has executable code at the same line, and if yes, prefer enclosing class + return fromClass.locationsOfLine(lineNumber).isEmpty()? found : fromClass; + } + } + if (fromClass.locationsOfLine(lineNumber).size() > 0) { return fromClass; } diff --git a/java/debugger/impl/src/com/intellij/debugger/jdi/VirtualMachineProxyImpl.java b/java/debugger/impl/src/com/intellij/debugger/jdi/VirtualMachineProxyImpl.java index 60215e2b7da4..586e4bfe1325 100644 --- a/java/debugger/impl/src/com/intellij/debugger/jdi/VirtualMachineProxyImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/jdi/VirtualMachineProxyImpl.java @@ -38,10 +38,7 @@ import org.jetbrains.annotations.NotNull; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.*; public class VirtualMachineProxyImpl implements JdiTimer, VirtualMachineProxy { private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.jdi.VirtualMachineProxyImpl"); @@ -87,12 +84,29 @@ public class VirtualMachineProxyImpl implements JdiTimer, VirtualMachineProxy { List nestedTypes = myNestedClassesCache.get(refType); if (nestedTypes == null) { final List list = refType.nestedTypes(); - nestedTypes = new ArrayList(list.size()); - final ClassLoaderReference outerLoader = refType.classLoader(); - for (ReferenceType type : list) { - if (outerLoader == null? type.classLoader() == null : outerLoader.equals(type.classLoader())) { - nestedTypes.add(type); + final int size = list.size(); + if (size > 0) { + final Set candidates = new HashSet(); + final ClassLoaderReference outerLoader = refType.classLoader(); + for (ReferenceType nested : list) { + if (outerLoader == null? nested.classLoader() == null : outerLoader.equals(nested.classLoader())) { + candidates.add(nested); + } } + + if (!candidates.isEmpty()) { + // keep only direct nested types + final Set nested2 = new HashSet(); + for (final ReferenceType candidate : candidates) { + nested2.addAll(nestedTypes(candidate)); + } + candidates.removeAll(nested2); + } + + nestedTypes = candidates.isEmpty()? Collections.emptyList() : new ArrayList(candidates); + } + else { + nestedTypes = Collections.emptyList(); } myNestedClassesCache.put(refType, nestedTypes); } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java index 9ea0bfe2ba0c..2063ce7313cc 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java @@ -130,16 +130,27 @@ public class LineBreakpoint extends BreakpointWithHighlighter { try { List locs = debugProcess.getPositionManager().locationsOfLine(classType, getSourcePosition()); if (locs.size() > 0) { - for (final Location location : locs) { - if (LOG.isDebugEnabled()) { - LOG.debug("Found location for reference type " + classType.name() + " at line " + getLineIndex() + "; isObsolete: " + (debugProcess.getVirtualMachineProxy().versionHigher("1.4") && location.method().isObsolete())); + Location minLocation = null; + for (final Location loc : locs) { + if (minLocation == null) { + minLocation = loc; } - BreakpointRequest request = debugProcess.getRequestsManager().createBreakpointRequest(LineBreakpoint.this, location); - debugProcess.getRequestsManager().enableRequest(request); - if (LOG.isDebugEnabled()) { - LOG.debug("Created breakpoint request for reference type " + classType.name() + " at line " + getLineIndex()); + else if (loc.codeIndex() < minLocation.codeIndex()) { + minLocation = loc; } } + + assert minLocation != null; + + if (LOG.isDebugEnabled()) { + LOG.debug("Found location for reference type " + classType.name() + " at line " + getLineIndex() + "; isObsolete: " + (debugProcess.getVirtualMachineProxy().versionHigher("1.4") && minLocation + .method().isObsolete())); + } + BreakpointRequest request = debugProcess.getRequestsManager().createBreakpointRequest(LineBreakpoint.this, minLocation); + debugProcess.getRequestsManager().enableRequest(request); + if (LOG.isDebugEnabled()) { + LOG.debug("Created breakpoint request for reference type " + classType.name() + " at line " + getLineIndex()); + } } else { // there's no executable code in this class