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,49 +95,137 @@ 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 );
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 ;
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 iCompilationUnit ) {
121+ parser .setSource (iCompilationUnit );
122+ } else if (javaElement instanceof IClassFile iClassFile ) {
123+ parser .setSource (iClassFile );
124+ } else if (javaElement instanceof IType typeNew ) {
125+ char [] source = typeNew .getSource ().toCharArray ();
126+ if (source != null ) {
127+ parser .setSource (source );
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+
140+ if (parser .createAST (null ) instanceof CompilationUnit ast ) {
141+ ast .accept (new ASTVisitor () {
142+ boolean meth = false ;
143+ boolean found = false ;
144+ boolean inTargetContext = false ;
145+ @ Override
146+ public boolean visit (MethodDeclaration node ) {
147+ if (node .getName ().getIdentifier ().equals (currentMethod )) {
148+ List <Object > parameters = node .parameters ();
149+ List <String > methodParams = parameters .stream ().map (p -> ((SingleVariableDeclaration ) p ).getType ().toString ()).toList ();
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+ if (methodParams .equals (ref )) {
157+ meth = true ;
158+ for (Object op : node .parameters ()) {
159+ if (op instanceof SingleVariableDeclaration param ) {
160+ if (param .getName ().getIdentifier ().equals (name )) {
161+ final ICompilationUnit finalCu = cu [0 ];
162+ highlightLine (ast , finalCu , param .getStartPosition ());
163+ found = true ;
164+ return false ;
165+ }
166+ }
167+ }
168+ return true ;
96169 }
97170 }
98- return true ;
99171 }
172+ return true ;
100173 }
101- return true ;
102- }
103174
104- @ Override
105- public boolean visit ( VariableDeclarationFragment node ) {
106- if ( found ) {
107- return false ;
175+ @ Override
176+ public void endVisit ( MethodDeclaration node ) {
177+ inTargetContext = false ;
178+
108179 }
109- if (meth && node .getName ().getIdentifier ().equals (name )) {
110- found = true ;
111- highlightLine (ast , cu , node .getStartPosition ());
112- return false ;
180+
181+ @ Override
182+ public boolean visit (VariableDeclarationFragment node ) {
183+ if (found ) {
184+ return false ;
185+ }
186+ if ((meth || inTargetContext ) && node .getName ().getIdentifier ().equals (name )) {
187+ found = true ;
188+ final ICompilationUnit finalCu = cu [0 ];
189+ highlightLine (ast , finalCu , node .getStartPosition ());
190+ return false ;
191+ }
192+ return true ;
113193 }
114- return true ;
115- }
116- });
194+
195+ @ Override
196+ public boolean visit (LambdaExpression node ) {
197+ if (found ) {
198+ return false ;
199+ }
200+ List <Object > parameters = node .parameters ();
201+ int start = node .getStartPosition ();
202+ int end = start + node .getLength ();
203+ int startLine = ast .getLineNumber (start );
204+ int endLine = ast .getLineNumber (end );
205+ if (currentLine >= startLine && currentLine <= endLine ) {
206+ inTargetContext = true ;
207+ for (Object param : parameters ) {
208+ if (param instanceof SingleVariableDeclaration ) {
209+ if (param instanceof SingleVariableDeclaration svd ) {
210+ if (svd .getName ().getIdentifier ().equals (name )) {
211+ highlightLine (ast , cu [0 ], svd .getStartPosition ());
212+ found = true ;
213+ return false ;
214+ }
215+ }
216+ }
217+ }
218+ }
219+ return true ;
220+ }
221+
222+ @ Override
223+ public void endVisit (LambdaExpression node ) {
224+ inTargetContext = false ;
225+ }
226+ });
227+
228+ }
117229 }
118230 }
119231 }
@@ -135,15 +247,128 @@ public boolean visit(VariableDeclarationFragment node) {
135247 private void highlightLine (CompilationUnit ast , ICompilationUnit cu , int startPos ) {
136248 int line = ast .getLineNumber (startPos );
137249 try {
138- IEditorPart editor = JavaUI .openInEditor (cu );
250+ IEditorPart editor = null ;
251+ if (cu != null && cu .exists ()) {
252+ try {
253+ editor = JavaUI .openInEditor (cu );
254+ } catch (PartInitException e ) { // We can ignore the PartInitException
255+ DebugUIPlugin .log (e );
256+ }
257+ }
258+ if (editor == null && iTypeGlobal != null && iTypeGlobal .getClassFile () != null ) {
259+ try {
260+ editor = JavaUI .openInEditor (iTypeGlobal .getClassFile ());
261+ } catch (PartInitException e ) { // We can ignore the PartInitException
262+ DebugUIPlugin .log (e );
263+ }
264+ }
265+ if (editor == null ) {
266+ IWorkbenchWindow window = PlatformUI .getWorkbench ().getActiveWorkbenchWindow ();
267+ if (window != null && window .getActivePage () != null ) {
268+ editor = window .getActivePage ().getActiveEditor ();
269+ }
270+ }
139271 if (editor instanceof ITextEditor txtEd ) {
140272 IDocumentProvider prov = txtEd .getDocumentProvider ();
141273 IDocument doc = prov .getDocument (txtEd .getEditorInput ());
142- IRegion lineReg = doc .getLineInformation (line - 1 );
274+ int adjustedLine = Math .max (0 , line - 1 );
275+ IRegion lineReg = doc .getLineInformation (adjustedLine );
143276 txtEd .selectAndReveal (lineReg .getOffset (), lineReg .getLength ());
144277 }
145278 } catch (Exception e ) {
146279 DebugUIPlugin .log (e );
147280 }
148281 }
149- }
282+
283+ /**
284+ * Gets the Java element for the current stack frame
285+ *
286+ * @param frame
287+ * IJavaStackFrame of the element
288+ */
289+ private IJavaElement getJavaElement (IJavaStackFrame frame ) {
290+ try {
291+ String projectName = frame .getLaunch ().getLaunchConfiguration ().getAttribute (IJavaLaunchConfigurationConstants .ATTR_PROJECT_NAME , (String ) null );
292+ if (projectName != null ) {
293+ IProject project = ResourcesPlugin .getWorkspace ().getRoot ().getProject (projectName );
294+ if (project .exists ()) {
295+ IJavaProject javaProject = JavaCore .create (project );
296+ IType type = javaProject .findType (frame .getReceivingTypeName ());
297+ if (type != null ) {
298+ return type .getCompilationUnit ();
299+ }
300+ }
301+ }
302+ IType globalType = findTypeInWorkspace (frame .getDeclaringTypeName ());
303+ if (globalType != null ) {
304+ return globalType ;
305+ }
306+ IWorkbenchWindow window = PlatformUI .getWorkbench ().getActiveWorkbenchWindow ();
307+ if (window != null && window .getActivePage () != null ) {
308+ IEditorPart editor = window .getActivePage ().getActiveEditor ();
309+ if (editor != null ) {
310+ return JavaUI .getEditorInputJavaElement (editor .getEditorInput ());
311+ }
312+ }
313+ } catch (Exception e ) {
314+ DebugUIPlugin .log (e );
315+ }
316+ return null ;
317+ }
318+
319+ /**
320+ * Finds a type in the entire workspace
321+ *
322+ * @param fullyQualifiedName
323+ */
324+ private IType findTypeInWorkspace (String fullyQualifiedName ) {
325+ try {
326+ for (IJavaProject project : JavaCore .create (ResourcesPlugin .getWorkspace ().getRoot ()).getJavaProjects ()) {
327+ IType type = project .findType (fullyQualifiedName );
328+ if (type != null ) {
329+ return type ;
330+ }
331+ }
332+ } catch (JavaModelException e ) {
333+ DebugUIPlugin .log (e );
334+ }
335+ return null ;
336+ }
337+
338+ /**
339+ * Gets the Compilation unit for the JavaElement
340+ *
341+ * @param element
342+ * IJavaElement of the java element
343+ */
344+ public ICompilationUnit getCompilationUnit (IJavaElement element ) {
345+ if (element == null ) {
346+ return null ;
347+ }
348+
349+ if (element instanceof IClassFile classFile ) {
350+ try {
351+ return classFile .getWorkingCopy (null , new NullProgressMonitor ());
352+ } catch (JavaModelException e ) {
353+ DebugUIPlugin .log (e );
354+ return null ;
355+ }
356+ }
357+ IJavaElement ancestor = element .getAncestor (IJavaElement .COMPILATION_UNIT );
358+ if (ancestor instanceof ICompilationUnit iCompilationUnit ) {
359+ return iCompilationUnit ;
360+ }
361+ if (element instanceof IPackageFragment ) {
362+ try {
363+ ICompilationUnit [] units = null ;
364+ if (element instanceof IPackageFragment fragment ) {
365+ units = fragment .getCompilationUnits ();
366+ }
367+ return units .length > 0 ? units [0 ] : null ;
368+ } catch (JavaModelException e ) {
369+ DebugUIPlugin .log (e );
370+ }
371+ }
372+ return null ;
373+ }
374+ }
0 commit comments