Skip to content

Commit d3155bc

Browse files
Location variable navigation code added
1 parent de48a8d commit d3155bc

File tree

5 files changed

+163
-1
lines changed

5 files changed

+163
-1
lines changed

org.eclipse.jdt.debug.ui/plugin.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ openDeclVarType.tooltip=Open the Variable's Declared Type
121121
openDeclVarTypeHierarchy.label=Open Declared Type &Hierarchy
122122
openDeclVarTypeHierarchy.tooltip=Open the Variable's Declared Type Hierarchy
123123

124+
openDeclLocalVarNavigation.label=Open Local Variable Navigation
125+
openDeclLocalVarNavigation.tooltip=Open Local Variable Navigation
126+
124127
openConcreteVarType.label=Open Act&ual Type
125128
openConcreteVarType.tooltip=Open the Variable's Actual Implementation Type
126129

org.eclipse.jdt.debug.ui/plugin.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,23 @@
747747
enablesFor="1"
748748
id="org.eclipse.jdt.debug.ui.actions.OpenVariableDeclaredType">
749749
</action>
750+
<action
751+
label="%openDeclLocalVarNavigation.label"
752+
helpContextId="open_variable_declared_type_hierarchy_action_context"
753+
tooltip="%openDeclLocalVarNavigation.tooltip"
754+
class="org.eclipse.jdt.internal.debug.ui.actions.OpenDeclLocalVarNavigationAction"
755+
menubarPath="emptyNavigationGroup"
756+
enablesFor="1"
757+
id="org.eclipse.jdt.debug.ui.actions.OpenDeclLocalVarNavigation">
758+
</action>
759+
<visibility>
760+
<not>
761+
<objectState
762+
name="JavaVariableFilter"
763+
value="isLocalVariableValue">
764+
</objectState>
765+
</not>
766+
</visibility>
750767
</objectContribution>
751768
<objectContribution
752769
objectClass="org.eclipse.jdt.debug.core.IJavaVariable"

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.eclipse.jdt.debug.core.IJavaPrimitiveValue;
2828
import org.eclipse.jdt.debug.core.IJavaType;
2929
import org.eclipse.jdt.debug.core.IJavaVariable;
30+
import org.eclipse.jdt.internal.debug.core.model.JDILocalVariable;
3031
import org.eclipse.jdt.internal.debug.core.model.JDINullValue;
3132
import org.eclipse.jdt.internal.debug.core.model.JDIObjectValue;
3233
import org.eclipse.jdt.internal.debug.core.model.JDIPlaceholderValue;
@@ -207,6 +208,9 @@ else if (value.equals("isValuePrimitive")) { //$NON-NLS-1$
207208
if (value.equals("isFieldVariable")) { //$NON-NLS-1$
208209
return var instanceof IJavaFieldVariable;
209210
}
211+
if (value.equals("isLocalVariableValue")) { //$NON-NLS-1$
212+
return !(var instanceof JDILocalVariable);
213+
}
210214
}
211215
else if (name.equals("ConcreteVariableActionFilter") && value.equals("isConcrete")) { //$NON-NLS-1$ //$NON-NLS-2$
212216
return isDeclaredSameAsConcrete(var);
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 IBM Corporation and others.
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+
15+
package org.eclipse.jdt.internal.debug.ui.actions;
16+
17+
import java.util.List;
18+
import java.util.stream.Collectors;
19+
20+
import org.eclipse.core.resources.IProject;
21+
import org.eclipse.core.resources.ResourcesPlugin;
22+
import org.eclipse.core.runtime.CoreException;
23+
import org.eclipse.debug.core.model.IDebugElement;
24+
import org.eclipse.debug.core.model.IStackFrame;
25+
import org.eclipse.jdt.core.ICompilationUnit;
26+
import org.eclipse.jdt.core.IJavaProject;
27+
import org.eclipse.jdt.core.IType;
28+
import org.eclipse.jdt.core.JavaCore;
29+
import org.eclipse.jdt.core.dom.AST;
30+
import org.eclipse.jdt.core.dom.ASTParser;
31+
import org.eclipse.jdt.core.dom.ASTVisitor;
32+
import org.eclipse.jdt.core.dom.CompilationUnit;
33+
import org.eclipse.jdt.core.dom.MethodDeclaration;
34+
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
35+
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
36+
import org.eclipse.jdt.debug.core.IJavaStackFrame;
37+
import org.eclipse.jdt.debug.core.IJavaType;
38+
import org.eclipse.jdt.debug.core.IJavaVariable;
39+
import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
40+
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
41+
import org.eclipse.jdt.ui.JavaUI;
42+
import org.eclipse.jface.text.IDocument;
43+
import org.eclipse.jface.text.IRegion;
44+
import org.eclipse.ui.IEditorPart;
45+
import org.eclipse.ui.texteditor.IDocumentProvider;
46+
import org.eclipse.ui.texteditor.ITextEditor;
47+
48+
public class OpenDeclLocalVarNavigationAction extends OpenVariableTypeAction {
49+
@Override
50+
protected IJavaType getTypeToOpen(IDebugElement element) throws CoreException {
51+
try {
52+
if (element instanceof IJavaVariable varE) {
53+
IJavaType javaType = varE.getJavaType();
54+
String name = varE.getName();
55+
IStackFrame jFrame = javaType.getDebugTarget().getThreads()[0].getTopStackFrame();
56+
if (jFrame instanceof IJavaStackFrame jf) {
57+
jf.getReferenceType().getAllFieldNames();
58+
String type = jf.getLaunch().getLaunchConfiguration().getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String) null);
59+
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(type);
60+
IJavaProject iJavaProject = JavaCore.create(project);
61+
IType iType = iJavaProject.findType(jf.getReceivingTypeName());
62+
String nameMethod = jf.getMethodName();
63+
List<String> frameParams = jf.getArgumentTypeNames();
64+
List<String> ref = frameParams.stream().map(e -> {
65+
int dot = e.lastIndexOf('.');
66+
if(dot>=0) {
67+
return e.substring(dot+1);
68+
}
69+
return e;
70+
}).collect(Collectors.toList());
71+
ICompilationUnit cu = iType.getCompilationUnit();
72+
ASTParser parse = ASTParser.newParser(AST.getJLSLatest());
73+
parse.setSource(cu);
74+
parse.setKind(ASTParser.K_COMPILATION_UNIT);
75+
76+
parse.setResolveBindings(true);
77+
CompilationUnit ast = (CompilationUnit) parse.createAST(null);
78+
ast.accept(new ASTVisitor() {
79+
boolean meth = false;
80+
boolean found = false;
81+
@Override
82+
public boolean visit(MethodDeclaration node) {
83+
if (node.getName().getIdentifier().equals(nameMethod)) {
84+
List<Object> parameters = node.parameters();
85+
List<String> methodParams = parameters.stream().map(p -> ((SingleVariableDeclaration) p).getType().toString()).toList();
86+
if (methodParams.equals(ref)) {
87+
meth = true;
88+
for (Object op : node.parameters()) {
89+
SingleVariableDeclaration parm = (SingleVariableDeclaration) op;
90+
if (parm.getName().getIdentifier().equals(name)) {
91+
highlightLine(ast, cu, node.getStartPosition());
92+
found = true;
93+
return true;
94+
}
95+
}
96+
return true;
97+
}
98+
}
99+
return true;
100+
}
101+
@Override
102+
public boolean visit(VariableDeclarationFragment node) {
103+
if (found) {
104+
return false;
105+
}
106+
if (meth && node.getName().getIdentifier().equals(name)) {
107+
found = true;
108+
highlightLine(ast, cu, node.getStartPosition());
109+
return true;
110+
}
111+
return true;
112+
}
113+
private void highlightLine(CompilationUnit ast, ICompilationUnit cu, int startPos) {
114+
int line = ast.getLineNumber(startPos);
115+
try {
116+
IEditorPart editor = JavaUI.openInEditor(cu);
117+
if (editor instanceof ITextEditor txtEd) {
118+
IDocumentProvider prov = txtEd.getDocumentProvider();
119+
IDocument doc = prov.getDocument(txtEd.getEditorInput());
120+
IRegion lineReg = doc.getLineInformation(line - 1);
121+
txtEd.selectAndReveal(lineReg.getOffset(), lineReg.getLength());
122+
}
123+
} catch (Exception e) {
124+
System.out.println("Exception: " + e.getMessage()); //$NON-NLS-1$
125+
}
126+
}
127+
});
128+
ResourcesPlugin.getWorkspace();
129+
}
130+
}
131+
} catch (CoreException e) {
132+
JDIDebugUIPlugin.statusDialog(e.getStatus());
133+
}
134+
135+
return null;
136+
}
137+
}

org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/OpenTypeAction.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.eclipse.jdt.debug.core.IJavaType;
3434
import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants;
3535
import org.eclipse.jdt.internal.debug.core.JavaDebugUtils;
36+
import org.eclipse.jdt.internal.debug.core.model.JDILocalVariable;
3637
import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
3738
import org.eclipse.jdt.internal.ui.util.OpenTypeHierarchyUtil;
3839
import org.eclipse.jdt.ui.JavaUI;
@@ -77,7 +78,7 @@ public void run(IAction action) {
7778
*/
7879
protected boolean openElement(IAction action, Object element) throws DebugException, CoreException {
7980
IType sourceElement = resolveSourceElement(element);
80-
if (sourceElement != null) {
81+
if (sourceElement != null || (sourceElement == null && element instanceof JDILocalVariable)) {
8182
openInEditor(element, sourceElement);
8283
} else {
8384
IStatus status = new Status(IStatus.INFO, IJavaDebugUIConstants.PLUGIN_ID, IJavaDebugUIConstants.INTERNAL_ERROR, "Source not found", null); //$NON-NLS-1$

0 commit comments

Comments
 (0)