1919
2020import org .eclipse .core .resources .IProject ;
2121import org .eclipse .core .resources .ResourcesPlugin ;
22+ import org .eclipse .core .runtime .NullProgressMonitor ;
2223import org .eclipse .debug .core .model .IStackFrame ;
2324import org .eclipse .debug .internal .ui .DebugUIPlugin ;
2425import org .eclipse .debug .ui .DebugUITools ;
26+ import org .eclipse .jdt .core .IClassFile ;
2527import org .eclipse .jdt .core .ICompilationUnit ;
28+ import org .eclipse .jdt .core .IJavaElement ;
2629import org .eclipse .jdt .core .IJavaProject ;
30+ import org .eclipse .jdt .core .IOrdinaryClassFile ;
31+ import org .eclipse .jdt .core .IPackageFragment ;
2732import org .eclipse .jdt .core .IType ;
2833import org .eclipse .jdt .core .JavaCore ;
34+ import org .eclipse .jdt .core .JavaModelException ;
2935import org .eclipse .jdt .core .dom .AST ;
3036import org .eclipse .jdt .core .dom .ASTParser ;
3137import org .eclipse .jdt .core .dom .ASTVisitor ;
3238import org .eclipse .jdt .core .dom .CompilationUnit ;
39+ import org .eclipse .jdt .core .dom .LambdaExpression ;
3340import org .eclipse .jdt .core .dom .MethodDeclaration ;
3441import org .eclipse .jdt .core .dom .SingleVariableDeclaration ;
3542import org .eclipse .jdt .core .dom .VariableDeclarationFragment ;
4249import org .eclipse .jface .text .IRegion ;
4350import org .eclipse .jface .viewers .IStructuredSelection ;
4451import org .eclipse .ui .IEditorPart ;
52+ import org .eclipse .ui .IWorkbenchWindow ;
53+ import org .eclipse .ui .PartInitException ;
54+ import org .eclipse .ui .PlatformUI ;
4555import org .eclipse .ui .texteditor .IDocumentProvider ;
4656import org .eclipse .ui .texteditor .ITextEditor ;
4757
4858public class NavigateToVarDeclAction extends ObjectActionDelegate {
59+
60+ private IType iTypeGlobal ;
4961 @ Override
5062 public void run (IAction action ) {
5163 IStructuredSelection selection = getCurrentSelection ();
@@ -58,10 +70,22 @@ public void run(IAction action) {
5870 Object frame = DebugUITools .getDebugContext ();
5971 if (frame instanceof IStackFrame jFrame ) {
6072 if (jFrame instanceof IJavaStackFrame javaStackFrame ) {
73+ IJavaProject iJavaProject = null ;
6174 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 );
75+ if (type == null ) {
76+ for (IJavaProject proj : JavaCore .create (ResourcesPlugin .getWorkspace ().getRoot ()).getJavaProjects ()) {
77+ IType type2 = proj .findType (javaStackFrame .getDeclaringTypeName ());
78+ if (type2 != null && type2 .exists ()) {
79+ iJavaProject = proj ;
80+ }
81+ }
82+ }
83+ if (iJavaProject == null && type != null ) {
84+ IProject project = ResourcesPlugin .getWorkspace ().getRoot ().getProject (type );
85+ iJavaProject = JavaCore .create (project );
86+ }
6487 IType iType = iJavaProject .findType (javaStackFrame .getReceivingTypeName ());
88+ int currentLine = javaStackFrame .getLineNumber ();
6589 String currentMethod = javaStackFrame .getMethodName ();
6690 List <String > frameParams = javaStackFrame .getArgumentTypeNames ();
6791 List <String > ref = frameParams .stream ().map (e -> {
@@ -71,48 +95,130 @@ public void run(IAction action) {
7195 }
7296 return e ;
7397 }).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 );
98+ final ICompilationUnit [] cu = { null };
99+ if (iType == null ) {
100+ IWorkbenchWindow window = PlatformUI .getWorkbench ().getActiveWorkbenchWindow ();
101+ IEditorPart editor = window .getActivePage ().getActiveEditor ();
102+ IJavaElement element = JavaUI .getEditorInputJavaElement (editor .getEditorInput ());
103+ cu [0 ] = (element instanceof ICompilationUnit cuElement ) ? cuElement : null ;
104+ } else {
105+ cu [0 ] = iType .getCompilationUnit ();
106+ }
107+ ASTParser parser = ASTParser .newParser (AST .getJLSLatest ());
108+ if (cu [0 ] == null && iType != null ) {
109+ IOrdinaryClassFile classFile = iType .getClassFile ();
110+ if (classFile != null && classFile .getSource () != null ) {
111+ String source = classFile .getSource ();
112+ parser .setSource (source .toCharArray ());
113+ parser .setKind (ASTParser .K_COMPILATION_UNIT );
114+ iTypeGlobal = iType ;
115+ }
116+ } else if (cu [0 ] == null && iType == null ) {
117+ final IJavaElement javaElement = getJavaElement (javaStackFrame );
118+ cu [0 ] = getCompilationUnit (javaElement );
119+ if (javaElement != null ) {
120+ if (javaElement instanceof ICompilationUnit ) {
121+ parser .setSource ((ICompilationUnit ) javaElement );
122+ } else if (javaElement instanceof IClassFile ) {
123+ parser .setSource ((IClassFile ) javaElement );
124+ } else {
125+ String source = getSourceContent (javaElement );
126+ if (source != null ) {
127+ parser .setSource (source .toCharArray ());
128+ } else {
129+ return ; // No source
130+ }
131+ }
132+ parser .setResolveBindings (true );
133+ }
134+ } else {
135+ parser .setSource (cu [0 ]);
136+ parser .setKind (ASTParser .K_COMPILATION_UNIT );
137+ parser .setResolveBindings (true );
138+ }
139+ CompilationUnit ast = (CompilationUnit ) parser .createAST (null );
80140 ast .accept (new ASTVisitor () {
81141 boolean meth = false ;
82142 boolean found = false ;
143+ boolean inTargetContext = false ;
83144 @ Override
84145 public boolean visit (MethodDeclaration node ) {
85146 if (node .getName ().getIdentifier ().equals (currentMethod )) {
86147 List <Object > parameters = node .parameters ();
87148 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 ;
149+ int start = node .getStartPosition ();
150+ int end = start + node .getLength ();
151+ int startLine = ast .getLineNumber (start );
152+ int endLine = ast .getLineNumber (end );
153+ if (currentLine >= startLine && currentLine <= endLine ) {
154+ inTargetContext = true ;
155+ if (methodParams .equals (ref )) {
156+ meth = true ;
157+ for (Object op : node .parameters ()) {
158+ SingleVariableDeclaration parm = (SingleVariableDeclaration ) op ;
159+ if (parm .getName ().getIdentifier ().equals (name )) {
160+ final ICompilationUnit finalCu = cu [0 ];
161+ highlightLine (ast , finalCu , parm .getStartPosition ());
162+ found = true ;
163+ return false ;
164+ }
96165 }
166+ return true ;
97167 }
98- return true ;
99168 }
100169 }
101170 return true ;
102171 }
103172
173+ @ Override
174+ public void endVisit (MethodDeclaration node ) {
175+ inTargetContext = false ;
176+ }
177+
104178 @ Override
105179 public boolean visit (VariableDeclarationFragment node ) {
106180 if (found ) {
107181 return false ;
108182 }
109- if (meth && node .getName ().getIdentifier ().equals (name )) {
183+ if (( meth || inTargetContext ) && node .getName ().getIdentifier ().equals (name )) {
110184 found = true ;
111- highlightLine (ast , cu , node .getStartPosition ());
185+ final ICompilationUnit finalCu = cu [0 ];
186+ highlightLine (ast , finalCu , node .getStartPosition ());
112187 return false ;
113188 }
114189 return true ;
115190 }
191+
192+ @ Override
193+ public boolean visit (LambdaExpression node ) {
194+ if (found ) {
195+ return false ;
196+ }
197+ List <Object > parameters = node .parameters ();
198+ int start = node .getStartPosition ();
199+ int end = start + node .getLength ();
200+ int startLine = ast .getLineNumber (start );
201+ int endLine = ast .getLineNumber (end );
202+ if (currentLine >= startLine && currentLine <= endLine ) {
203+ inTargetContext = true ;
204+ for (Object param : parameters ) {
205+ if (param instanceof SingleVariableDeclaration ) {
206+ SingleVariableDeclaration svd = (SingleVariableDeclaration ) param ;
207+ if (svd .getName ().getIdentifier ().equals (name )) {
208+ highlightLine (ast , cu [0 ], svd .getStartPosition ());
209+ found = true ;
210+ return false ;
211+ }
212+ }
213+ }
214+ }
215+ return true ;
216+ }
217+
218+ @ Override
219+ public void endVisit (LambdaExpression node ) {
220+ inTargetContext = false ;
221+ }
116222 });
117223 }
118224 }
@@ -135,15 +241,151 @@ public boolean visit(VariableDeclarationFragment node) {
135241 private void highlightLine (CompilationUnit ast , ICompilationUnit cu , int startPos ) {
136242 int line = ast .getLineNumber (startPos );
137243 try {
138- IEditorPart editor = JavaUI .openInEditor (cu );
244+ IEditorPart editor = null ;
245+ if (cu != null && cu .exists ()) {
246+ try {
247+ editor = JavaUI .openInEditor (cu );
248+ } catch (PartInitException e ) { // We can ignore the PartInitException
249+ DebugUIPlugin .log (e );
250+ }
251+ }
252+ if (editor == null && iTypeGlobal != null && iTypeGlobal .getClassFile () != null ) {
253+ try {
254+ editor = JavaUI .openInEditor (iTypeGlobal .getClassFile ());
255+ } catch (PartInitException e ) { // We can ignore the PartInitException
256+ DebugUIPlugin .log (e );
257+ }
258+ }
259+ if (editor == null ) {
260+ IWorkbenchWindow window = PlatformUI .getWorkbench ().getActiveWorkbenchWindow ();
261+ if (window != null && window .getActivePage () != null ) {
262+ editor = window .getActivePage ().getActiveEditor ();
263+ }
264+ }
139265 if (editor instanceof ITextEditor txtEd ) {
140266 IDocumentProvider prov = txtEd .getDocumentProvider ();
141267 IDocument doc = prov .getDocument (txtEd .getEditorInput ());
142- IRegion lineReg = doc .getLineInformation (line - 1 );
268+ int adjustedLine = Math .max (0 , line - 1 );
269+ IRegion lineReg = doc .getLineInformation (adjustedLine );
143270 txtEd .selectAndReveal (lineReg .getOffset (), lineReg .getLength ());
144271 }
145272 } catch (Exception e ) {
146273 DebugUIPlugin .log (e );
147274 }
148275 }
149- }
276+
277+ /**
278+ * Gets the Java element for the current stack frame
279+ *
280+ * @param frame
281+ * IJavaStackFrame of the element
282+ */
283+ private IJavaElement getJavaElement (IJavaStackFrame frame ) {
284+ try {
285+ String projectName = frame .getLaunch ().getLaunchConfiguration ().getAttribute (IJavaLaunchConfigurationConstants .ATTR_PROJECT_NAME , (String ) null );
286+ if (projectName != null ) {
287+ IProject project = ResourcesPlugin .getWorkspace ().getRoot ().getProject (projectName );
288+ if (project .exists ()) {
289+ IJavaProject javaProject = JavaCore .create (project );
290+ IType type = javaProject .findType (frame .getReceivingTypeName ());
291+ if (type != null ) {
292+ return type .getCompilationUnit ();
293+ }
294+ }
295+ }
296+ IType globalType = findTypeInWorkspace (frame .getDeclaringTypeName ());
297+ if (globalType != null ) {
298+ return globalType ;
299+ }
300+ IWorkbenchWindow window = PlatformUI .getWorkbench ().getActiveWorkbenchWindow ();
301+ if (window != null && window .getActivePage () != null ) {
302+ IEditorPart editor = window .getActivePage ().getActiveEditor ();
303+ if (editor != null ) {
304+ return JavaUI .getEditorInputJavaElement (editor .getEditorInput ());
305+ }
306+ }
307+ } catch (Exception e ) {
308+ DebugUIPlugin .log (e );
309+ }
310+ return null ;
311+ }
312+
313+ /**
314+ * Finds a type in the entire workspace
315+ *
316+ * @param fullyQualifiedName
317+ */
318+ private IType findTypeInWorkspace (String fullyQualifiedName ) {
319+ try {
320+ for (IJavaProject project : JavaCore .create (ResourcesPlugin .getWorkspace ().getRoot ()).getJavaProjects ()) {
321+ IType type = project .findType (fullyQualifiedName );
322+ if (type != null ) {
323+ return type ;
324+ }
325+ }
326+ } catch (JavaModelException e ) {
327+ DebugUIPlugin .log (e );
328+ }
329+ return null ;
330+ }
331+
332+ /**
333+ * Gets source content for a Java element
334+ *
335+ * @param element
336+ * IJavaElement of the element
337+ */
338+ private String getSourceContent (IJavaElement element ) {
339+ try {
340+ if (element instanceof ICompilationUnit ) {
341+ return ((ICompilationUnit ) element ).getSource ();
342+ } else if (element instanceof IClassFile ) {
343+ return ((IClassFile ) element ).getSource ();
344+ } else if (element instanceof IType ) {
345+ return ((IType ) element ).getSource ();
346+ }
347+ } catch (JavaModelException e ) {
348+ DebugUIPlugin .log (e );
349+ }
350+ return null ;
351+ }
352+
353+ /**
354+ * Gets the Compilation unit for the JavaElement
355+ *
356+ * @param element
357+ * IJavaElement of the java element
358+ */
359+ public ICompilationUnit getCompilationUnit (IJavaElement element ) {
360+ if (element == null ) {
361+ return null ;
362+ }
363+ if (element instanceof ICompilationUnit ) {
364+ return (ICompilationUnit ) element ;
365+ }
366+ if (element instanceof IType ) {
367+ return ((IType ) element ).getCompilationUnit ();
368+ }
369+ if (element instanceof IClassFile ) {
370+ try {
371+ return ((IClassFile ) element ).getWorkingCopy (null , new NullProgressMonitor ());
372+ } catch (JavaModelException e ) {
373+ DebugUIPlugin .log (e );
374+ return null ;
375+ }
376+ }
377+ IJavaElement ancestor = element .getAncestor (IJavaElement .COMPILATION_UNIT );
378+ if (ancestor instanceof ICompilationUnit ) {
379+ return (ICompilationUnit ) ancestor ;
380+ }
381+ if (element instanceof IPackageFragment ) {
382+ try {
383+ ICompilationUnit [] units = ((IPackageFragment ) element ).getCompilationUnits ();
384+ return units .length > 0 ? units [0 ] : null ;
385+ } catch (JavaModelException e ) {
386+ DebugUIPlugin .log (e );
387+ }
388+ }
389+ return null ;
390+ }
391+ }
0 commit comments