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
This commit is contained in:
Eugene Zhuravlev
2011-03-15 15:49:11 +01:00
parent c6a8e01deb
commit dd94ffddfb
3 changed files with 56 additions and 26 deletions
@@ -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<ReferenceType> positionClasses = positionManager.getAllClasses(position);
if (positionClasses.isEmpty()) {
// fallback
if (positionManager.locationsOfLine(referenceType, position).size() > 0) {
requestor.processClassPrepare(debuggerProcess, referenceType);
}
}
else {
final List<ReferenceType> positionClasses = positionManager.getAllClasses(position);
if (positionClasses.contains(referenceType)) {
requestor.processClassPrepare(debuggerProcess, referenceType);
}
@@ -267,15 +270,17 @@ public class PositionManagerImpl implements PositionManager {
final List<ReferenceType> 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;
}
@@ -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<ReferenceType> nestedTypes = myNestedClassesCache.get(refType);
if (nestedTypes == null) {
final List<ReferenceType> list = refType.nestedTypes();
nestedTypes = new ArrayList<ReferenceType>(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<ReferenceType> candidates = new HashSet<ReferenceType>();
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<ReferenceType> nested2 = new HashSet<ReferenceType>();
for (final ReferenceType candidate : candidates) {
nested2.addAll(nestedTypes(candidate));
}
candidates.removeAll(nested2);
}
nestedTypes = candidates.isEmpty()? Collections.<ReferenceType>emptyList() : new ArrayList<ReferenceType>(candidates);
}
else {
nestedTypes = Collections.emptyList();
}
myNestedClassesCache.put(refType, nestedTypes);
}
@@ -130,16 +130,27 @@ public class LineBreakpoint extends BreakpointWithHighlighter {
try {
List<Location> 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