Skip to content

Commit 8623659

Browse files
committed
Fix wrong variable reference in debug tooltip for inherited methods
Add check to confirm the field's declaring type is an ancestor of this's runtime type Fixes : #396
1 parent 010e959 commit 8623659

5 files changed

Lines changed: 114 additions & 1 deletion

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 IBM Corporation.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* IBM Corporation - initial API and implementation
13+
*******************************************************************************/
14+
public class Element {
15+
16+
public Element element;
17+
18+
public Element() {
19+
}
20+
21+
public Element(Element element) {
22+
this.element = element;
23+
}
24+
25+
public void iterateElements() {
26+
System.out.println(element);
27+
if (element != null) {
28+
element.iterateElements();
29+
}
30+
}
31+
32+
@Override
33+
public String toString() {
34+
return getClass().getSimpleName();
35+
}
36+
public static void main(String[] args) {
37+
Element root = new Element(new SubElement(new Element()));
38+
root.iterateElements();
39+
}
40+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 IBM Corporation.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* IBM Corporation - initial API and implementation
13+
*******************************************************************************/
14+
public class SubElement extends Element {
15+
16+
public SubElement(Element element) {
17+
super(element);
18+
}
19+
}

org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,8 @@ synchronized void assert18Project() {
556556
cfgs.add(createLaunchConfiguration(jp, "InnerClassBug"));
557557
cfgs.add(createLaunchConfiguration(jp, "SuperClass"));
558558
cfgs.add(createLaunchConfiguration(jp, "SubClass"));
559+
cfgs.add(createLaunchConfiguration(jp, "Element"));
560+
cfgs.add(createLaunchConfiguration(jp, "SubElement"));
559561
loaded18 = true;
560562
waitForBuild();
561563
}

org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugHoverTests.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ public void testBug572629_ChainFieldHover_ArrayLengthChainsOnVariableThisExpress
438438
removeAllBreakpoints();
439439
}
440440
}
441+
441442
public void testBug572629_ChainFieldHover_3Chains_ExpectValueFromChainAtMiddle() throws Exception {
442443
sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
443444

@@ -1594,4 +1595,42 @@ public void testResolveSameFieldsInSuperAndSub() throws Exception {
15941595
}
15951596
}
15961597

1598+
public void testResolveFieldOnInheritedMethodFrame() throws Exception {
1599+
sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
1600+
1601+
final String typeName = "Element";
1602+
final String expectedMethod = "iterateElements";
1603+
final int framesNumber = 2;
1604+
final int bpLine1 = 26;
1605+
1606+
IJavaBreakpoint bp1 = createLineBreakpoint(bpLine1, "", typeName + ".java", typeName);
1607+
bp1.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
1608+
IFile file = (IFile) bp1.getMarker().getResource();
1609+
assertEquals(typeName + ".java", file.getName());
1610+
IJavaThread thread = null;
1611+
try {
1612+
thread = launchToBreakpoint(typeName);
1613+
CompilationUnitEditor part = openEditorAndValidateStack(expectedMethod, framesNumber, file, thread);
1614+
JavaDebugHover hover = new JavaDebugHover();
1615+
hover.setEditor(part);
1616+
int offset = part.getViewer().getDocument().get().indexOf("element);");
1617+
String variableName = "element";
1618+
IRegion region = new Region(offset, variableName.length());
1619+
String text = selectAndReveal(part, bpLine1, region);
1620+
assertEquals(variableName, text);
1621+
IVariable info = (IVariable) sync(() -> hover.getHoverInfo2(part.getViewer(), region));
1622+
assertNotNull(info);
1623+
String hoverVal = info.getValue().toString();
1624+
assertTrue(hoverVal.contains("SubElement"));
1625+
thread = resume(thread);
1626+
info = (IVariable) sync(() -> hover.getHoverInfo2(part.getViewer(), region));
1627+
assertNotNull(info);
1628+
hoverVal = info.getValue().toString();
1629+
assertTrue(hoverVal.contains("Element"));
1630+
} finally {
1631+
terminateAndRemove(thread);
1632+
removeAllBreakpoints();
1633+
}
1634+
}
1635+
15971636
}

org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugHover.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
5353
import org.eclipse.jdt.core.dom.ThisExpression;
5454
import org.eclipse.jdt.core.manipulation.SharedASTProviderCore;
55+
import org.eclipse.jdt.debug.core.IJavaClassType;
5556
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
5657
import org.eclipse.jdt.debug.core.IJavaObject;
5758
import org.eclipse.jdt.debug.core.IJavaReferenceType;
@@ -650,7 +651,7 @@ private static Predicate<IJavaStackFrame> forLocalVariable(ILocalVariable variab
650651
private static Predicate<IJavaStackFrame> forField(IField field) {
651652
return frame -> {
652653
try {
653-
return frame.getThis() != null && frame.getThis().getJavaType().getName().equals(field.getDeclaringType().getFullyQualifiedName())
654+
return frame.getThis() != null && isInstanceOfDeclaringType(frame.getThis(), field)
654655
&& containsVariable(frame, field.getElementName());
655656
} catch (DebugException e) {
656657
JDIDebugUIPlugin.log(e);
@@ -660,4 +661,16 @@ private static Predicate<IJavaStackFrame> forField(IField field) {
660661

661662
}
662663

664+
private static boolean isInstanceOfDeclaringType(IJavaObject javaObject, IField field) throws DebugException {
665+
String declaringTypeName = field.getDeclaringType().getFullyQualifiedName();
666+
IJavaType type = javaObject.getJavaType();
667+
while (type instanceof IJavaClassType classType) {
668+
if (declaringTypeName.equals(classType.getName())) {
669+
return true;
670+
}
671+
type = classType.getSuperclass();
672+
}
673+
return false;
674+
}
675+
663676
}

0 commit comments

Comments
 (0)