Skip to content

Commit d5d06b3

Browse files
Fix NPE in Navigate to declaration + Support for lambda
Variable Navigation throwing NPE and support for variable navigation in lambda for non-java projects Fix: #712
1 parent 093195d commit d5d06b3

File tree

1 file changed

+106
-18
lines changed

1 file changed

+106
-18
lines changed

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

Lines changed: 106 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@
2323
import org.eclipse.debug.internal.ui.DebugUIPlugin;
2424
import org.eclipse.debug.ui.DebugUITools;
2525
import org.eclipse.jdt.core.ICompilationUnit;
26+
import org.eclipse.jdt.core.IJavaElement;
2627
import org.eclipse.jdt.core.IJavaProject;
28+
import org.eclipse.jdt.core.IOrdinaryClassFile;
2729
import org.eclipse.jdt.core.IType;
2830
import org.eclipse.jdt.core.JavaCore;
2931
import org.eclipse.jdt.core.dom.AST;
3032
import org.eclipse.jdt.core.dom.ASTParser;
3133
import org.eclipse.jdt.core.dom.ASTVisitor;
3234
import org.eclipse.jdt.core.dom.CompilationUnit;
35+
import org.eclipse.jdt.core.dom.LambdaExpression;
3336
import org.eclipse.jdt.core.dom.MethodDeclaration;
3437
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
3538
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
@@ -42,10 +45,14 @@
4245
import org.eclipse.jface.text.IRegion;
4346
import org.eclipse.jface.viewers.IStructuredSelection;
4447
import org.eclipse.ui.IEditorPart;
48+
import org.eclipse.ui.IWorkbenchWindow;
49+
import org.eclipse.ui.PlatformUI;
4550
import org.eclipse.ui.texteditor.IDocumentProvider;
4651
import org.eclipse.ui.texteditor.ITextEditor;
4752

4853
public class NavigateToVarDeclAction extends ObjectActionDelegate {
54+
55+
private IType iTypeGlobal;
4956
@Override
5057
public void run(IAction action) {
5158
IStructuredSelection selection = getCurrentSelection();
@@ -58,10 +65,22 @@ public void run(IAction action) {
5865
Object frame = DebugUITools.getDebugContext();
5966
if (frame instanceof IStackFrame jFrame) {
6067
if (jFrame instanceof IJavaStackFrame javaStackFrame) {
68+
IJavaProject iJavaProject = null;
6169
String type = javaStackFrame.getLaunch().getLaunchConfiguration().getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String) null);
62-
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(type);
63-
IJavaProject iJavaProject = JavaCore.create(project);
70+
if (type == null) {
71+
for (IJavaProject proj : JavaCore.create(ResourcesPlugin.getWorkspace().getRoot()).getJavaProjects()) {
72+
IType type2 = proj.findType(javaStackFrame.getDeclaringTypeName());
73+
if (type2 != null && type2.exists()) {
74+
iJavaProject = proj;
75+
}
76+
}
77+
}
78+
if (iJavaProject == null && type != null) {
79+
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(type);
80+
iJavaProject = JavaCore.create(project);
81+
}
6482
IType iType = iJavaProject.findType(javaStackFrame.getReceivingTypeName());
83+
int currentLine = javaStackFrame.getLineNumber();
6584
String currentMethod = javaStackFrame.getMethodName();
6685
List<String> frameParams = javaStackFrame.getArgumentTypeNames();
6786
List<String> ref = frameParams.stream().map(e -> {
@@ -71,48 +90,114 @@ public void run(IAction action) {
7190
}
7291
return e;
7392
}).collect(Collectors.toList());
74-
ICompilationUnit cu = iType.getCompilationUnit();
75-
ASTParser parse = ASTParser.newParser(AST.getJLSLatest());
76-
parse.setSource(cu);
77-
parse.setKind(ASTParser.K_COMPILATION_UNIT);
78-
parse.setResolveBindings(true);
79-
CompilationUnit ast = (CompilationUnit) parse.createAST(null);
93+
ICompilationUnit cu;
94+
95+
if (iType == null) {
96+
97+
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
98+
IEditorPart editor = window.getActivePage().getActiveEditor();
99+
IJavaElement element = JavaUI.getEditorInputJavaElement(editor.getEditorInput());
100+
cu = (element instanceof ICompilationUnit cuElement) ? cuElement : null;
101+
} else {
102+
cu = iType.getCompilationUnit();
103+
}
104+
ASTParser parser = ASTParser.newParser(AST.getJLSLatest());
105+
if (cu == null) {
106+
IOrdinaryClassFile classFile = iType.getClassFile();
107+
if (classFile != null && classFile.getSource() != null) {
108+
String source = classFile.getSource();
109+
parser.setSource(source.toCharArray());
110+
parser.setKind(ASTParser.K_COMPILATION_UNIT);
111+
iTypeGlobal = iType;
112+
}
113+
} else {
114+
parser.setSource(cu);
115+
parser.setKind(ASTParser.K_COMPILATION_UNIT);
116+
parser.setResolveBindings(true);
117+
}
118+
119+
CompilationUnit ast = (CompilationUnit) parser.createAST(null);
80120
ast.accept(new ASTVisitor() {
81121
boolean meth = false;
82122
boolean found = false;
123+
boolean inTargetContext = false;
83124
@Override
84125
public boolean visit(MethodDeclaration node) {
85126
if (node.getName().getIdentifier().equals(currentMethod)) {
86127
List<Object> parameters = node.parameters();
87128
List<String> methodParams = parameters.stream().map(p -> ((SingleVariableDeclaration) p).getType().toString()).toList();
88-
if (methodParams.equals(ref)) {
89-
meth = true;
90-
for (Object op : node.parameters()) {
91-
SingleVariableDeclaration parm = (SingleVariableDeclaration) op;
92-
if (parm.getName().getIdentifier().equals(name)) {
93-
highlightLine(ast, cu, node.getStartPosition());
94-
found = true;
95-
return false;
129+
int start = node.getStartPosition();
130+
int end = start + node.getLength();
131+
int startLine = ast.getLineNumber(start);
132+
int endLine = ast.getLineNumber(end);
133+
if (currentLine >= startLine && currentLine <= endLine) {
134+
inTargetContext = true;
135+
if (methodParams.equals(ref)) {
136+
meth = true;
137+
for (Object op : node.parameters()) {
138+
SingleVariableDeclaration parm = (SingleVariableDeclaration) op;
139+
if (parm.getName().getIdentifier().equals(name)) {
140+
highlightLine(ast, cu, parm.getStartPosition());
141+
found = true;
142+
return false;
143+
}
96144
}
145+
return true;
97146
}
98-
return true;
99147
}
100148
}
101149
return true;
102150
}
103151

152+
@Override
153+
public void endVisit(MethodDeclaration node) {
154+
inTargetContext = false;
155+
}
156+
104157
@Override
105158
public boolean visit(VariableDeclarationFragment node) {
106159
if (found) {
107160
return false;
108161
}
109-
if (meth && node.getName().getIdentifier().equals(name)) {
162+
if ((meth || inTargetContext) && node.getName().getIdentifier().equals(name)) {
110163
found = true;
111164
highlightLine(ast, cu, node.getStartPosition());
112165
return false;
113166
}
114167
return true;
115168
}
169+
170+
@Override
171+
public boolean visit(LambdaExpression node) {
172+
if (found) {
173+
return false;
174+
}
175+
List<Object> parameters = node.parameters();
176+
int start = node.getStartPosition();
177+
int end = start + node.getLength();
178+
int startLine = ast.getLineNumber(start);
179+
int endLine = ast.getLineNumber(end);
180+
if (currentLine >= startLine && currentLine <= endLine) {
181+
inTargetContext = true;
182+
for (Object param : parameters) {
183+
if (param instanceof SingleVariableDeclaration) {
184+
SingleVariableDeclaration svd = (SingleVariableDeclaration) param;
185+
if (svd.getName().getIdentifier().equals(name)) {
186+
highlightLine(ast, cu, svd.getStartPosition());
187+
found = true;
188+
return false;
189+
}
190+
}
191+
}
192+
}
193+
return true;
194+
195+
}
196+
197+
@Override
198+
public void endVisit(LambdaExpression node) {
199+
inTargetContext = false;
200+
}
116201
});
117202
}
118203
}
@@ -136,6 +221,9 @@ private void highlightLine(CompilationUnit ast, ICompilationUnit cu, int startPo
136221
int line = ast.getLineNumber(startPos);
137222
try {
138223
IEditorPart editor = JavaUI.openInEditor(cu);
224+
if (editor == null) {
225+
editor = JavaUI.openInEditor(iTypeGlobal.getClassFile());
226+
}
139227
if (editor instanceof ITextEditor txtEd) {
140228
IDocumentProvider prov = txtEd.getDocumentProvider();
141229
IDocument doc = prov.getDocument(txtEd.getEditorInput());

0 commit comments

Comments
 (0)