Skip to content

Commit 3cc1183

Browse files
Fix NPE in Navigate to declaration + Support for lambda (#715)
Variable Navigation throwing NPE and support for variable navigation in lambda for non-java projects Fix: #712
1 parent d4763b2 commit 3cc1183

File tree

1 file changed

+111
-50
lines changed

1 file changed

+111
-50
lines changed

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

Lines changed: 111 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -17,31 +17,30 @@
1717
import java.util.List;
1818
import java.util.stream.Collectors;
1919

20-
import org.eclipse.core.resources.IProject;
21-
import org.eclipse.core.resources.ResourcesPlugin;
2220
import org.eclipse.debug.core.model.IStackFrame;
2321
import org.eclipse.debug.internal.ui.DebugUIPlugin;
2422
import org.eclipse.debug.ui.DebugUITools;
23+
import org.eclipse.jdt.core.IClassFile;
2524
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;
25+
import org.eclipse.jdt.core.IJavaElement;
26+
import org.eclipse.jdt.core.WorkingCopyOwner;
2927
import org.eclipse.jdt.core.dom.AST;
3028
import org.eclipse.jdt.core.dom.ASTParser;
3129
import org.eclipse.jdt.core.dom.ASTVisitor;
3230
import org.eclipse.jdt.core.dom.CompilationUnit;
31+
import org.eclipse.jdt.core.dom.LambdaExpression;
3332
import org.eclipse.jdt.core.dom.MethodDeclaration;
3433
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
3534
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
3635
import org.eclipse.jdt.debug.core.IJavaStackFrame;
3736
import org.eclipse.jdt.debug.core.IJavaVariable;
38-
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
3937
import org.eclipse.jdt.ui.JavaUI;
4038
import org.eclipse.jface.action.IAction;
4139
import org.eclipse.jface.text.IDocument;
4240
import org.eclipse.jface.text.IRegion;
4341
import org.eclipse.jface.viewers.IStructuredSelection;
4442
import org.eclipse.ui.IEditorPart;
43+
import org.eclipse.ui.IWorkbenchWindow;
4544
import org.eclipse.ui.texteditor.IDocumentProvider;
4645
import org.eclipse.ui.texteditor.ITextEditor;
4746

@@ -58,10 +57,7 @@ public void run(IAction action) {
5857
Object frame = DebugUITools.getDebugContext();
5958
if (frame instanceof IStackFrame jFrame) {
6059
if (jFrame instanceof IJavaStackFrame javaStackFrame) {
61-
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);
64-
IType iType = iJavaProject.findType(javaStackFrame.getReceivingTypeName());
60+
int currentLine = javaStackFrame.getLineNumber();
6561
String currentMethod = javaStackFrame.getMethodName();
6662
List<String> frameParams = javaStackFrame.getArgumentTypeNames();
6763
List<String> ref = frameParams.stream().map(e -> {
@@ -71,49 +67,112 @@ public void run(IAction action) {
7167
}
7268
return e;
7369
}).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);
80-
ast.accept(new ASTVisitor() {
81-
boolean meth = false;
82-
boolean found = false;
83-
@Override
84-
public boolean visit(MethodDeclaration node) {
85-
if (node.getName().getIdentifier().equals(currentMethod)) {
86-
List<Object> parameters = node.parameters();
87-
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;
70+
final ICompilationUnit[] cu = { null };
71+
IWorkbenchWindow window = getWorkbenchWindow();
72+
IEditorPart editor = window.getActivePage().getActiveEditor();
73+
IJavaElement element = JavaUI.getEditorInputJavaElement(editor.getEditorInput());
74+
75+
if (element instanceof ICompilationUnit icu) {
76+
cu[0] = icu;
77+
} else if (element instanceof IClassFile icf) {
78+
cu[0] = icf.getWorkingCopy(new WorkingCopyOwner() {
79+
}, null);
80+
} else {
81+
cu[0] = null;
82+
}
83+
84+
ASTParser parser = ASTParser.newParser(AST.getJLSLatest());
85+
parser.setSource(cu[0]);
86+
parser.setKind(ASTParser.K_COMPILATION_UNIT);
87+
parser.setResolveBindings(true);
88+
89+
if (parser.createAST(null) instanceof CompilationUnit ast) {
90+
ast.accept(new ASTVisitor() {
91+
boolean meth = false;
92+
boolean found = false;
93+
boolean inTargetContext = false;
94+
@Override
95+
public boolean visit(MethodDeclaration node) {
96+
if (node.getName().getIdentifier().equals(currentMethod)) {
97+
List<Object> parameters = node.parameters();
98+
List<String> methodParams = parameters.stream().map(p -> ((SingleVariableDeclaration) p).getType().toString()).toList();
99+
int start = node.getStartPosition();
100+
int end = start + node.getLength();
101+
int startLine = ast.getLineNumber(start);
102+
int endLine = ast.getLineNumber(end);
103+
if (currentLine >= startLine && currentLine <= endLine) {
104+
inTargetContext = true;
105+
if (methodParams.equals(ref)) {
106+
meth = true;
107+
for (Object op : node.parameters()) {
108+
if (op instanceof SingleVariableDeclaration param) {
109+
if (param.getName().getIdentifier().equals(name)) {
110+
final ICompilationUnit finalCu = cu[0];
111+
highlightLine(ast, finalCu, param.getStartPosition(), editor);
112+
found = true;
113+
return false;
114+
}
115+
}
116+
}
117+
return true;
96118
}
97119
}
98-
return true;
99120
}
121+
return true;
100122
}
101-
return true;
102-
}
103123

104-
@Override
105-
public boolean visit(VariableDeclarationFragment node) {
106-
if (found) {
107-
return false;
124+
@Override
125+
public void endVisit(MethodDeclaration node) {
126+
inTargetContext = false;
127+
108128
}
109-
if (meth && node.getName().getIdentifier().equals(name)) {
110-
found = true;
111-
highlightLine(ast, cu, node.getStartPosition());
112-
return false;
129+
130+
@Override
131+
public boolean visit(VariableDeclarationFragment node) {
132+
if (found) {
133+
return false;
134+
}
135+
if ((meth || inTargetContext) && node.getName().getIdentifier().equals(name)) {
136+
found = true;
137+
final ICompilationUnit finalCu = cu[0];
138+
highlightLine(ast, finalCu, node.getStartPosition(), editor);
139+
return false;
140+
}
141+
return true;
113142
}
114-
return true;
115-
}
116-
});
143+
144+
@Override
145+
public boolean visit(LambdaExpression node) {
146+
if (found) {
147+
return false;
148+
}
149+
List<Object> parameters = node.parameters();
150+
int start = node.getStartPosition();
151+
int end = start + node.getLength();
152+
int startLine = ast.getLineNumber(start);
153+
int endLine = ast.getLineNumber(end);
154+
if (currentLine >= startLine && currentLine <= endLine) {
155+
inTargetContext = true;
156+
for (Object param : parameters) {
157+
if (param instanceof SingleVariableDeclaration svd) {
158+
if (svd.getName().getIdentifier().equals(name)) {
159+
highlightLine(ast, cu[0], svd.getStartPosition(), editor);
160+
found = true;
161+
return false;
162+
}
163+
}
164+
}
165+
}
166+
return true;
167+
}
168+
169+
@Override
170+
public void endVisit(LambdaExpression node) {
171+
inTargetContext = false;
172+
}
173+
});
174+
175+
}
117176
}
118177
}
119178
}
@@ -131,19 +190,21 @@ public boolean visit(VariableDeclarationFragment node) {
131190
* compilation unit of the code
132191
* @param startPos
133192
* start position of the code want to highlight
193+
* @param editor
194+
* active editor info
134195
*/
135-
private void highlightLine(CompilationUnit ast, ICompilationUnit cu, int startPos) {
196+
private void highlightLine(CompilationUnit ast, ICompilationUnit cu, int startPos, IEditorPart editor) {
136197
int line = ast.getLineNumber(startPos);
137198
try {
138-
IEditorPart editor = JavaUI.openInEditor(cu);
139199
if (editor instanceof ITextEditor txtEd) {
140200
IDocumentProvider prov = txtEd.getDocumentProvider();
141201
IDocument doc = prov.getDocument(txtEd.getEditorInput());
142-
IRegion lineReg = doc.getLineInformation(line - 1);
202+
int adjustedLine = Math.max(0, line - 1);
203+
IRegion lineReg = doc.getLineInformation(adjustedLine);
143204
txtEd.selectAndReveal(lineReg.getOffset(), lineReg.getLength());
144205
}
145206
} catch (Exception e) {
146207
DebugUIPlugin.log(e);
147208
}
148209
}
149-
}
210+
}

0 commit comments

Comments
 (0)