KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > debug > ui > actions > StepIntoSelectionActionDelegate


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.debug.ui.actions;
12
13
14 import org.eclipse.core.runtime.CoreException;
15 import org.eclipse.core.runtime.IAdapterManager;
16 import org.eclipse.core.runtime.Platform;
17 import org.eclipse.debug.core.DebugEvent;
18 import org.eclipse.debug.core.DebugException;
19 import org.eclipse.debug.core.DebugPlugin;
20 import org.eclipse.debug.core.IDebugEventSetListener;
21 import org.eclipse.debug.core.model.IStackFrame;
22 import org.eclipse.debug.core.model.IThread;
23 import org.eclipse.debug.ui.actions.IRunToLineTarget;
24 import org.eclipse.jdt.core.IMember;
25 import org.eclipse.jdt.core.IMethod;
26 import org.eclipse.jdt.core.IType;
27 import org.eclipse.jdt.core.JavaModelException;
28 import org.eclipse.jdt.debug.core.IJavaStackFrame;
29 import org.eclipse.jdt.debug.core.IJavaThread;
30 import org.eclipse.jdt.internal.debug.ui.EvaluationContextManager;
31 import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
32 import org.eclipse.jface.action.IAction;
33 import org.eclipse.jface.text.ITextSelection;
34 import org.eclipse.jface.viewers.ISelection;
35 import org.eclipse.ui.IEditorActionDelegate;
36 import org.eclipse.ui.IEditorPart;
37 import org.eclipse.ui.IWorkbenchWindow;
38 import org.eclipse.ui.IWorkbenchWindowActionDelegate;
39 import org.eclipse.ui.texteditor.IEditorStatusLine;
40 import org.eclipse.ui.texteditor.ITextEditor;
41
42 /**
43  * Steps into the selected method.
44  */

45 public class StepIntoSelectionActionDelegate implements IEditorActionDelegate, IWorkbenchWindowActionDelegate {
46     
47     private IEditorPart fEditorPart = null;
48     private IWorkbenchWindow fWindow = null;
49     /**
50      * The name of the type being "run to".
51      * @see StepIntoSelectionActionDelegate#runToLineBeforeStepIn(ITextSelection, IJavaStackFrame, IMethod)
52      */

53     private String JavaDoc fRunToLineType= null;
54     /**
55      * The line number being "run to."
56      * @see StepIntoSelectionActionDelegate#runToLineBeforeStepIn(ITextSelection, IJavaStackFrame, IMethod)
57      */

58     private int fRunToLineLine= -1;
59     /**
60      * The debug event list listener used to know when a run to line has finished.
61      * @see StepIntoSelectionActionDelegate#runToLineBeforeStepIn(ITextSelection, IJavaStackFrame, IMethod)
62      */

63     private IDebugEventSetListener listener= null;
64
65     /**
66      * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
67      */

68     public void run(IAction action) {
69         IJavaStackFrame frame = getStackFrame();
70         if (frame == null || !frame.isSuspended()) {
71             // no longer suspended - unexpected
72
return;
73         }
74         ITextSelection textSelection = getTextSelection();
75         try {
76             IMethod method = StepIntoSelectionUtils.getMethod(getTextSelection(),StepIntoSelectionUtils.getJavaElement(getActiveEditor().getEditorInput()));
77             IType callingType = getType();
78             if (method == null || callingType == null) {
79                 return;
80             }
81             int lineNumber = frame.getLineNumber();
82             String JavaDoc callingTypeName = stripInnerNames(callingType.getFullyQualifiedName());
83             String JavaDoc frameName = stripInnerNames(frame.getDeclaringTypeName());
84             // debug line numbers are 1 based, document line numbers are 0 based
85
if (textSelection.getStartLine() == (lineNumber - 1) && callingTypeName.equals(frameName)) {
86                 doStepIn(frame, method);
87             } else {
88                 // not on current line
89
runToLineBeforeStepIn(textSelection, frame.getThread(), method);
90                 return;
91             }
92         }
93         catch (DebugException e) {
94             showErrorMessage(e.getStatus().getMessage());
95             return;
96         }
97         catch(JavaModelException jme) {
98             showErrorMessage(jme.getStatus().getMessage());
99             return;
100         }
101     }
102     
103     /**
104      * Steps into the given method in the given stack frame
105      * @param frame the frame in which the step should begin
106      * @param method the method to step into
107      * @throws DebugException
108      */

109     private void doStepIn(IJavaStackFrame frame, IMethod method) throws DebugException {
110         // ensure top stack frame
111
IStackFrame tos = frame.getThread().getTopStackFrame();
112         if (tos == null) {
113             return;
114         }
115         if (!tos.equals(frame)) {
116             showErrorMessage(ActionMessages.StepIntoSelectionActionDelegate_Step_into_selection_only_available_in_top_stack_frame__3);
117             return;
118         }
119         StepIntoSelectionHandler handler = new StepIntoSelectionHandler((IJavaThread)frame.getThread(), frame, method);
120         handler.step();
121     }
122     
123     /**
124      * When the user chooses to "step into selection" on a line other than
125      * the currently executing one, first perform a "run to line" to get to
126      * the desired location, then perform a "step into selection."
127      */

128     private void runToLineBeforeStepIn(ITextSelection textSelection, final IThread thread, final IMethod method) {
129         fRunToLineType = getType().getFullyQualifiedName();
130         fRunToLineLine = textSelection.getStartLine() + 1;
131         if (fRunToLineType == null || fRunToLineLine == -1) {
132             return;
133         }
134         // see bug 65489 - get the run-to-line adapter from the editor
135
IRunToLineTarget runToLineAction = null;
136         IEditorPart ed = getActiveEditor();
137         if (ed != null) {
138             runToLineAction = (IRunToLineTarget) ed.getAdapter(IRunToLineTarget.class);
139             if (runToLineAction == null) {
140                 IAdapterManager adapterManager = Platform.getAdapterManager();
141                 if (adapterManager.hasAdapter(ed, IRunToLineTarget.class.getName())) {
142                     runToLineAction = (IRunToLineTarget) adapterManager.loadAdapter(ed,IRunToLineTarget.class.getName());
143                 }
144             }
145         }
146         // if no adapter exists, use the Java adapter
147
if (runToLineAction == null) {
148           runToLineAction = new RunToLineAdapter();
149         }
150         listener= new IDebugEventSetListener() {
151             /**
152              * @see IDebugEventSetListener#handleDebugEvents(DebugEvent[])
153              */

154             public void handleDebugEvents(DebugEvent[] events) {
155                 for (int i = 0; i < events.length; i++) {
156                     DebugEvent event = events[i];
157                     switch (event.getKind()) {
158                         case DebugEvent.SUSPEND :
159                             handleSuspendEvent(event);
160                             break;
161                         case DebugEvent.TERMINATE :
162                             handleTerminateEvent(event);
163                             break;
164                         default :
165                             break;
166                     }
167                 }
168             }
169             /**
170              * Listen for the completion of the "run to line." When the thread
171              * suspends at the correct location, perform a "step into selection"
172              * @param event the debug event
173              */

174             private void handleSuspendEvent(DebugEvent event) {
175                 Object JavaDoc source = event.getSource();
176                 if (source instanceof IJavaThread) {
177                     try {
178                         final IJavaStackFrame frame= (IJavaStackFrame) ((IJavaThread) source).getTopStackFrame();
179                         if (isExpectedFrame(frame)) {
180                             DebugPlugin plugin = DebugPlugin.getDefault();
181                             plugin.removeDebugEventListener(listener);
182                             plugin.asyncExec(new Runnable JavaDoc() {
183                                 public void run() {
184                                     try {
185                                         doStepIn(frame, method);
186                                     } catch (DebugException e) {
187                                         showErrorMessage(e.getStatus().getMessage());
188                                     }
189                                 }
190                             });
191                         }
192                     } catch (DebugException e) {
193                         return;
194                     }
195                 }
196             }
197             /**
198              * Returns whether the given frame is the frame that this action is expecting.
199              * This frame is expecting a stack frame for the suspension of the "run to line".
200              * @param frame the given stack frame or <code>null</code>
201              * @return whether the given stack frame is the expected frame
202              * @throws DebugException
203              */

204             private boolean isExpectedFrame(IJavaStackFrame frame) throws DebugException {
205                 return frame != null &&
206                     fRunToLineLine == frame.getLineNumber() &&
207                     frame.getReceivingTypeName().equals(fRunToLineType);
208             }
209             /**
210              * When the debug target we're listening for terminates, stop listening
211              * to debug events.
212              * @param event the debug event
213              */

214             private void handleTerminateEvent(DebugEvent event) {
215                 Object JavaDoc source = event.getSource();
216                 if (thread.getDebugTarget() == source) {
217                     DebugPlugin.getDefault().removeDebugEventListener(listener);
218                 }
219             }
220         };
221         DebugPlugin.getDefault().addDebugEventListener(listener);
222         try {
223             runToLineAction.runToLine(getActiveEditor(), textSelection, thread);
224         } catch (CoreException e) {
225             DebugPlugin.getDefault().removeDebugEventListener(listener);
226             showErrorMessage(ActionMessages.StepIntoSelectionActionDelegate_4);
227             JDIDebugUIPlugin.log(e.getStatus());
228         }
229     }
230     
231     /**
232      * Gets the current text selection from the currently active editor
233      * @return the current text selection
234      */

235     private ITextSelection getTextSelection() {
236         IEditorPart part = getActiveEditor();
237         if (part instanceof ITextEditor) {
238             ITextEditor editor = (ITextEditor)part;
239             return (ITextSelection)editor.getSelectionProvider().getSelection();
240         }
241         showErrorMessage(ActionMessages.StepIntoSelectionActionDelegate_Step_into_selection_only_available_in_Java_editor__4);
242         return null;
243     }
244     
245     /**
246      * Return the type containing the selected text, or <code>null</code> if the
247      * selection is not in a type.
248      */

249     protected IType getType() {
250         IMember member= ActionDelegateHelper.getDefault().getCurrentMember(getTextSelection());
251         IType type= null;
252         if (member instanceof IType) {
253             type = (IType)member;
254         } else if (member != null) {
255             type= member.getDeclaringType();
256         }
257         return type;
258     }
259     
260     /**
261      * Displays an error message in the status area
262      *
263      * @param message
264      */

265     protected void showErrorMessage(String JavaDoc message) {
266         if (getActiveEditor() != null) {
267             IEditorStatusLine statusLine= (IEditorStatusLine) getActiveEditor().getAdapter(IEditorStatusLine.class);
268             if (statusLine != null) {
269                 statusLine.setMessage(true, message, null);
270             }
271         }
272         JDIDebugUIPlugin.getStandardDisplay().beep();
273     }
274
275
276     /**
277      * @see org.eclipse.ui.IEditorActionDelegate#setActiveEditor(org.eclipse.jface.action.IAction, org.eclipse.ui.IEditorPart)
278      */

279     public void setActiveEditor(IAction action, IEditorPart targetEditor) {
280         fEditorPart = targetEditor;
281     }
282     
283     /**
284      * Returns the active editor or <code>null</code>.
285      *
286      * @return active editor or <code>null</code>
287      */

288     protected IEditorPart getActiveEditor() {
289         if (fWindow != null) {
290             // global action
291
return fWindow.getActivePage().getActiveEditor();
292         }
293         // pop-up action
294
return fEditorPart;
295     }
296
297     /**
298      * Strips inner class names from the given type name.
299      *
300      * @param fullyQualifiedName
301      */

302     private String JavaDoc stripInnerNames(String JavaDoc fullyQualifiedName) {
303         // ignore inner class qualification, as the compiler generated names and java model names can be different
304
int index = fullyQualifiedName.indexOf('$');
305         if (index > 0) {
306             return fullyQualifiedName.substring(0, index);
307         }
308         return fullyQualifiedName;
309     }
310     
311     /**
312      * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
313      */

314     public void selectionChanged(IAction action, ISelection selection) {
315     }
316
317     /**
318      * Returns the current stack frame context, or <code>null</code> if none.
319      *
320      * @return the current stack frame context, or <code>null</code> if none
321      */

322     protected IJavaStackFrame getStackFrame() {
323         return EvaluationContextManager.getEvaluationContext(getActiveEditor());
324     }
325         
326     /**
327      * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose()
328      */

329     public void dispose() {}
330
331     /**
332      * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(org.eclipse.ui.IWorkbenchWindow)
333      */

334     public void init(IWorkbenchWindow window) {
335         fWindow = window;
336     }
337
338 }
339
Popular Tags