]> git.uio.no Git - ifi-stolz-refaktor.git/blame - case-study/jdt-before/ui/org/eclipse/jdt/internal/ui/callhierarchy/CallHierarchyUI.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-before / ui / org / eclipse / jdt / internal / ui / callhierarchy / CallHierarchyUI.java
CommitLineData
1b2798f6
EK
1/*******************************************************************************
2 * Copyright (c) 2000, 2012 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 * Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation
10 * (report 36180: Callers/Callees view)
11 * Stephan Herrmann (stephan@cs.tu-berlin.de):
12 * - bug 75800: [call hierarchy] should allow searches for fields
13 *******************************************************************************/
14package org.eclipse.jdt.internal.ui.callhierarchy;
15
16import java.util.ArrayList;
17import java.util.Iterator;
18import java.util.List;
19
20import org.eclipse.swt.widgets.Shell;
21
22import org.eclipse.core.runtime.Assert;
23import org.eclipse.core.runtime.CoreException;
24import org.eclipse.core.runtime.IStatus;
25import org.eclipse.core.runtime.Status;
26
27import org.eclipse.jface.dialogs.ErrorDialog;
28import org.eclipse.jface.dialogs.MessageDialog;
29import org.eclipse.jface.preference.IPreferenceStore;
30import org.eclipse.jface.viewers.ISelection;
31import org.eclipse.jface.viewers.IStructuredSelection;
32import org.eclipse.jface.viewers.StructuredSelection;
33
34import org.eclipse.ui.IEditorPart;
35import org.eclipse.ui.IViewReference;
36import org.eclipse.ui.IWorkbenchPage;
37import org.eclipse.ui.IWorkbenchWindow;
38import org.eclipse.ui.PartInitException;
39
40import org.eclipse.ui.texteditor.ITextEditor;
41
42import org.eclipse.jdt.core.IJavaElement;
43import org.eclipse.jdt.core.IMember;
44import org.eclipse.jdt.core.ISourceRange;
45import org.eclipse.jdt.core.JavaModelException;
46
47import org.eclipse.jdt.internal.corext.callhierarchy.CallHierarchy;
48import org.eclipse.jdt.internal.corext.callhierarchy.CallLocation;
49import org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper;
50import org.eclipse.jdt.internal.corext.util.Messages;
51
52import org.eclipse.jdt.ui.JavaUI;
53
54import org.eclipse.jdt.internal.ui.IJavaStatusConstants;
55import org.eclipse.jdt.internal.ui.JavaPlugin;
56import org.eclipse.jdt.internal.ui.actions.SelectionConverter;
57import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
58import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
59
60public class CallHierarchyUI {
61 private static final int DEFAULT_MAX_CALL_DEPTH= 10;
62 private static final String PREF_MAX_CALL_DEPTH = "PREF_MAX_CALL_DEPTH"; //$NON-NLS-1$
63
64 private static CallHierarchyUI fgInstance;
65 private int fViewCount= 0;
66 private final List<IMember[]> fMethodHistory= new ArrayList<IMember[]>();
67
68 /**
69 * List of the Call Hierarchy views in LRU order, where the most recently used view is at index 0.
70 * @since 3.7
71 */
72 private List<CallHierarchyViewPart> fLRUCallHierarchyViews= new ArrayList<CallHierarchyViewPart>();
73
74 private CallHierarchyUI() {
75 // Do nothing
76 }
77
78 public static CallHierarchyUI getDefault() {
79 if (fgInstance == null) {
80 fgInstance = new CallHierarchyUI();
81 }
82
83 return fgInstance;
84 }
85
86 /**
87 * Returns the maximum tree level allowed
88 * @return int
89 */
90 public int getMaxCallDepth() {
91 int maxCallDepth;
92
93 IPreferenceStore settings = JavaPlugin.getDefault().getPreferenceStore();
94 maxCallDepth = settings.getInt(PREF_MAX_CALL_DEPTH);
95 if (maxCallDepth < 1 || maxCallDepth > 99) {
96 maxCallDepth= DEFAULT_MAX_CALL_DEPTH;
97 }
98
99 return maxCallDepth;
100 }
101
102 public void setMaxCallDepth(int maxCallDepth) {
103 IPreferenceStore settings = JavaPlugin.getDefault().getPreferenceStore();
104 settings.setValue(PREF_MAX_CALL_DEPTH, maxCallDepth);
105 }
106
107 public static void jumpToMember(IJavaElement element) {
108 if (element != null) {
109 try {
110 JavaUI.openInEditor(element, true, true);
111 } catch (JavaModelException e) {
112 JavaPlugin.log(e);
113 } catch (PartInitException e) {
114 JavaPlugin.log(e);
115 }
116 }
117 }
118
119 public static void jumpToLocation(CallLocation callLocation) {
120 try {
121 IEditorPart methodEditor = JavaUI.openInEditor(callLocation.getMember(), false, false);
122 if (methodEditor instanceof ITextEditor) {
123 ITextEditor editor = (ITextEditor) methodEditor;
124 editor.selectAndReveal(callLocation.getStart(),
125 (callLocation.getEnd() - callLocation.getStart()));
126 }
127 } catch (JavaModelException e) {
128 JavaPlugin.log(e);
129 } catch (PartInitException e) {
130 JavaPlugin.log(e);
131 }
132 }
133
134 /**
135 * Opens the element in the editor or shows an error dialog if that fails.
136 *
137 * @param element the element to open
138 * @param shell parent shell for error dialog
139 * @param activateOnOpen <code>true</code> if the editor should be activated
140 * @return <code>true</code> iff no error occurred while trying to open the editor,
141 * <code>false</code> iff an error dialog was raised.
142 */
143 public static boolean openInEditor(Object element, Shell shell, boolean activateOnOpen) {
144 CallLocation callLocation= CallHierarchy.getCallLocation(element);
145
146 try {
147 IMember enclosingMember;
148 int selectionStart;
149 int selectionLength;
150
151 if (callLocation != null) {
152 enclosingMember= callLocation.getMember();
153 selectionStart= callLocation.getStart();
154 selectionLength= callLocation.getEnd() - selectionStart;
155 } else if (element instanceof MethodWrapper) {
156 enclosingMember= ((MethodWrapper) element).getMember();
157 ISourceRange selectionRange= enclosingMember.getNameRange();
158 if (selectionRange == null)
159 selectionRange= enclosingMember.getSourceRange();
160 if (selectionRange == null)
161 return true;
162 selectionStart= selectionRange.getOffset();
163 selectionLength= selectionRange.getLength();
164 } else {
165 return true;
166 }
167
168 IEditorPart methodEditor = JavaUI.openInEditor(enclosingMember, activateOnOpen, false);
169 if (methodEditor instanceof ITextEditor) {
170 ITextEditor editor = (ITextEditor) methodEditor;
171 editor.selectAndReveal(selectionStart, selectionLength);
172 }
173 return true;
174 } catch (JavaModelException e) {
175 JavaPlugin.log(new Status(IStatus.ERROR, JavaPlugin.getPluginId(),
176 IJavaStatusConstants.INTERNAL_ERROR,
177 CallHierarchyMessages.CallHierarchyUI_open_in_editor_error_message, e));
178
179 ErrorDialog.openError(shell, CallHierarchyMessages.OpenLocationAction_error_title,
180 CallHierarchyMessages.CallHierarchyUI_open_in_editor_error_message,
181 e.getStatus());
182 return false;
183 } catch (PartInitException x) {
184 String name;
185 if (callLocation != null)
186 name= callLocation.getCalledMember().getElementName();
187 else if (element instanceof MethodWrapper)
188 name= ((MethodWrapper) element).getName();
189 else
190 name= ""; //$NON-NLS-1$
191 MessageDialog.openError(shell, CallHierarchyMessages.OpenLocationAction_error_title,
192 Messages.format(
193 CallHierarchyMessages.CallHierarchyUI_open_in_editor_error_messageArgs,
194 new String[] { name, x.getMessage() }));
195 return false;
196 }
197 }
198
199 public static IEditorPart isOpenInEditor(Object elem) {
200 IJavaElement javaElement= null;
201 if (elem instanceof MethodWrapper) {
202 javaElement= ((MethodWrapper) elem).getMember();
203 } else if (elem instanceof CallLocation) {
204 javaElement= ((CallLocation) elem).getMember();
205 }
206 if (javaElement != null) {
207 return EditorUtility.isOpenInEditor(javaElement);
208 }
209 return null;
210 }
211
212 public static CallHierarchyViewPart openSelectionDialog(IMember[] candidates, IWorkbenchWindow window) {
213 Assert.isTrue(candidates != null);
214
215 IMember input= null;
216 if (candidates.length > 1) {
217 String title= CallHierarchyMessages.CallHierarchyUI_selectionDialog_title;
218 String message= CallHierarchyMessages.CallHierarchyUI_selectionDialog_message;
219 input= (IMember) SelectionConverter.selectJavaElement(candidates, window.getShell(), title, message);
220 } else if (candidates.length == 1) {
221 input= candidates[0];
222 }
223 if (input == null)
224 return openView(new IMember[] {}, window);
225
226 return openView(new IMember[] { input }, window);
227 }
228
229 public static CallHierarchyViewPart openView(IMember[] input, IWorkbenchWindow window) {
230 if (input.length == 0) {
231 MessageDialog.openInformation(window.getShell(), CallHierarchyMessages.CallHierarchyUI_selectionDialog_title,
232 CallHierarchyMessages.CallHierarchyUI_open_operation_unavialable);
233 return null;
234 }
235 IWorkbenchPage page= window.getActivePage();
236 try {
237 CallHierarchyViewPart viewPart= getDefault().findLRUCallHierarchyViewPart(page); //find the first view which is not pinned
238 String secondaryId= null;
239 if (viewPart == null) {
240 if (page.findViewReference(CallHierarchyViewPart.ID_CALL_HIERARCHY) != null) //all the current views are pinned, open a new instance
241 secondaryId= String.valueOf(++getDefault().fViewCount);
242 } else
243 secondaryId= viewPart.getViewSite().getSecondaryId();
244 viewPart= (CallHierarchyViewPart)page.showView(CallHierarchyViewPart.ID_CALL_HIERARCHY, secondaryId, IWorkbenchPage.VIEW_ACTIVATE);
245 viewPart.setInputElements(input);
246 return viewPart;
247 } catch (CoreException e) {
248 ExceptionHandler.handle(e, window.getShell(),
249 CallHierarchyMessages.CallHierarchyUI_error_open_view, e.getMessage());
250 }
251 return null;
252 }
253
254 /**
255 * Finds the first Call Hierarchy view part instance that is not pinned.
256 *
257 * @param page the active page
258 * @return the Call Hierarchy view part to open or <code>null</code> if none found
259 * @since 3.7
260 */
261 private CallHierarchyViewPart findLRUCallHierarchyViewPart(IWorkbenchPage page) {
262 boolean viewFoundInPage= false;
263 for (Iterator<CallHierarchyViewPart> iter= fLRUCallHierarchyViews.iterator(); iter.hasNext();) {
264 CallHierarchyViewPart view= iter.next();
265 if (page.equals(view.getSite().getPage())) {
266 if (!view.isPinned()) {
267 return view;
268 }
269 viewFoundInPage= true;
270 }
271 }
272 if (!viewFoundInPage) {
273 // find unresolved views
274 IViewReference[] viewReferences= page.getViewReferences();
275 for (int i= 0; i < viewReferences.length; i++) {
276 IViewReference curr= viewReferences[i];
277 if (CallHierarchyViewPart.ID_CALL_HIERARCHY.equals(curr.getId()) && page.equals(curr.getPage())) {
278 CallHierarchyViewPart view= (CallHierarchyViewPart)curr.getView(true);
279 if (view != null && !view.isPinned()) {
280 return view;
281 }
282 }
283 }
284 }
285 return null;
286 }
287
288 /**
289 * Adds the activated view part to the head of the list.
290 *
291 * @param view the Call Hierarchy view part
292 * @since 3.7
293 */
294 void callHierarchyViewActivated(CallHierarchyViewPart view) {
295 fLRUCallHierarchyViews.remove(view);
296 fLRUCallHierarchyViews.add(0, view);
297 }
298
299 /**
300 * Removes the closed view part from the list.
301 *
302 * @param view the closed view part
303 * @since 3.7
304 */
305 void callHierarchyViewClosed(CallHierarchyViewPart view) {
306 fLRUCallHierarchyViews.remove(view);
307 }
308
309 /**
310 * Converts an ISelection (containing MethodWrapper instances) to an ISelection
311 * with the MethodWrapper's replaced by their corresponding IMembers. If the selection
312 * contains elements which are not MethodWrapper instances or not already IMember instances
313 * they are discarded.
314 * @param selection The selection to convert.
315 * @return An ISelection containing IMember's in place of MethodWrapper instances.
316 */
317 static ISelection convertSelection(ISelection selection) {
318 if (selection.isEmpty()) {
319 return selection;
320 }
321
322 if (selection instanceof IStructuredSelection) {
323 IStructuredSelection structuredSelection= (IStructuredSelection) selection;
324 List<IMember> javaElements= new ArrayList<IMember>();
325 for (Iterator<?> iter= structuredSelection.iterator(); iter.hasNext();) {
326 Object element= iter.next();
327 if (element instanceof MethodWrapper) {
328 IMember member= ((MethodWrapper)element).getMember();
329 if (member != null) {
330 javaElements.add(member);
331 }
332 } else if (element instanceof IMember) {
333 javaElements.add((IMember) element);
334 } else if (element instanceof CallLocation) {
335 IMember member = ((CallLocation) element).getMember();
336 javaElements.add(member);
337 }
338 }
339 return new StructuredSelection(javaElements);
340 }
341 return StructuredSelection.EMPTY;
342 }
343
344 /**
345 * Clears the history and updates all the open views.
346 *
347 * @since 3.7
348 */
349 void clearHistory() {
350 for (Iterator<CallHierarchyViewPart> iter= fLRUCallHierarchyViews.iterator(); iter.hasNext();) {
351 CallHierarchyViewPart part= iter.next();
352 part.setHistoryEntries(new IMember[0][]);
353 part.setInputElements(null);
354 }
355 }
356
357 /**
358 * Returns the method history.
359 *
360 * @return the method history
361 * @since 3.7
362 */
363 List<IMember[]> getMethodHistory() {
364 return fMethodHistory;
365 }
366}