1 /*******************************************************************************
2 * Copyright (c) 2000, 2011 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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.ui.actions;
13 import java.lang.reflect.InvocationTargetException;
14 import java.util.Iterator;
16 import org.eclipse.swt.widgets.Shell;
18 import org.eclipse.core.runtime.IProgressMonitor;
20 import org.eclipse.jface.operation.IRunnableWithProgress;
21 import org.eclipse.jface.viewers.ISelection;
22 import org.eclipse.jface.viewers.ISelectionProvider;
23 import org.eclipse.jface.viewers.IStructuredSelection;
24 import org.eclipse.jface.viewers.StructuredSelection;
25 import org.eclipse.jface.window.Window;
27 import org.eclipse.jface.text.ITextSelection;
29 import org.eclipse.ui.IWorkbenchPart;
30 import org.eclipse.ui.PlatformUI;
31 import org.eclipse.ui.dialogs.ElementListSelectionDialog;
33 import org.eclipse.jdt.core.IClassFile;
34 import org.eclipse.jdt.core.ICodeAssist;
35 import org.eclipse.jdt.core.ICompilationUnit;
36 import org.eclipse.jdt.core.IJavaElement;
37 import org.eclipse.jdt.core.ISourceRange;
38 import org.eclipse.jdt.core.ISourceReference;
39 import org.eclipse.jdt.core.IType;
40 import org.eclipse.jdt.core.ITypeRoot;
41 import org.eclipse.jdt.core.JavaModelException;
43 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
45 import org.eclipse.jdt.ui.JavaElementLabelProvider;
47 import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
48 import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
50 public class SelectionConverter {
52 private static final IJavaElement[] EMPTY_RESULT= new IJavaElement[0];
54 private SelectionConverter() {
59 * Converts the selection provided by the given part into a structured selection. The following
60 * conversion rules are used:
62 * <li><code>part instanceof JavaEditor</code>: returns a structured selection using code
63 * resolve to convert the editor's text selection.</li>
64 * <li><code>part instanceof IWorkbenchPart</code>: returns the part's selection if it is a
65 * structured selection.</li>
66 * <li><code>default</code>: returns an empty structured selection.</li>
69 * @param part the part
70 * @return the selection
71 * @throws JavaModelException thrown when the type root can not be accessed
73 public static IStructuredSelection getStructuredSelection(IWorkbenchPart part) throws JavaModelException {
74 if (part instanceof JavaEditor)
75 return new StructuredSelection(codeResolve((JavaEditor)part));
76 ISelectionProvider provider= part.getSite().getSelectionProvider();
77 if (provider != null) {
78 ISelection selection= provider.getSelection();
79 if (selection instanceof IStructuredSelection)
80 return (IStructuredSelection)selection;
82 return StructuredSelection.EMPTY;
87 * Converts the given structured selection into an array of Java elements.
88 * An empty array is returned if one of the elements stored in the structured
89 * selection is not of type <code>IJavaElement</code>
90 * @param selection the selection
91 * @return the Java element contained in the selection
93 public static IJavaElement[] getElements(IStructuredSelection selection) {
94 if (!selection.isEmpty()) {
95 IJavaElement[] result= new IJavaElement[selection.size()];
97 for (Iterator<?> iter= selection.iterator(); iter.hasNext(); i++) {
98 Object element= iter.next();
99 if (!(element instanceof IJavaElement))
101 result[i]= (IJavaElement)element;
108 public static boolean canOperateOn(JavaEditor editor) {
111 return getInput(editor) != null;
115 public static IJavaElement[] codeResolveOrInputForked(JavaEditor editor) throws InvocationTargetException, InterruptedException {
116 ITypeRoot input= getInput(editor);
120 ITextSelection selection= (ITextSelection)editor.getSelectionProvider().getSelection();
121 IJavaElement[] result= performForkedCodeResolve(input, selection);
122 if (result.length == 0) {
123 result= new IJavaElement[] {input};
129 * Perform a code resolve at the current selection of an editor
131 * @param editor the editor
132 * @return the resolved elements (only from primary working copies)
133 * @throws JavaModelException when the type root can not be accessed
135 public static IJavaElement[] codeResolve(JavaEditor editor) throws JavaModelException {
136 return codeResolve(editor, true);
140 * Perform a code resolve at the current selection of an editor
142 * @param editor the editor
143 * @param primaryOnly if <code>true</code> only primary working copies will be returned
144 * @return the resolved elements
145 * @throws JavaModelException thrown when the type root can not be accessed
148 public static IJavaElement[] codeResolve(JavaEditor editor, boolean primaryOnly) throws JavaModelException {
149 ITypeRoot input= getInput(editor, primaryOnly);
151 return codeResolve(input, (ITextSelection) editor.getSelectionProvider().getSelection());
156 * Perform a code resolve in a separate thread.
158 * @param editor the editor
159 * @param primaryOnly if <code>true</code> only primary working copies will be returned
160 * @return the resolved elements
161 * @throws InvocationTargetException which wraps any exception or error which occurs while
162 * running the runnable
163 * @throws InterruptedException propagated by the context if the runnable acknowledges
164 * cancelation by throwing this exception
167 public static IJavaElement[] codeResolveForked(JavaEditor editor, boolean primaryOnly) throws InvocationTargetException, InterruptedException {
168 ITypeRoot input= getInput(editor, primaryOnly);
170 return performForkedCodeResolve(input, (ITextSelection) editor.getSelectionProvider().getSelection());
175 * Returns the element surrounding the selection of the given editor.
177 * @param editor the editor
178 * @return the element surrounding the current selection (only from primary working copies), or <code>null</code> if none
179 * @throws JavaModelException if the Java type root does not exist or if an exception occurs
180 * while accessing its corresponding resource
182 public static IJavaElement getElementAtOffset(JavaEditor editor) throws JavaModelException {
183 return getElementAtOffset(editor, true);
187 * Returns the element surrounding the selection of the given editor.
189 * @param editor the editor
190 * @param primaryOnly if <code>true</code> only primary working copies will be returned
191 * @return the element surrounding the current selection, or <code>null</code> if none
192 * @throws JavaModelException if the Java type root does not exist or if an exception occurs
193 * while accessing its corresponding resource
196 public static IJavaElement getElementAtOffset(JavaEditor editor, boolean primaryOnly) throws JavaModelException {
197 ITypeRoot input= getInput(editor, primaryOnly);
199 return getElementAtOffset(input, (ITextSelection) editor.getSelectionProvider().getSelection());
203 public static IType getTypeAtOffset(JavaEditor editor) throws JavaModelException {
204 IJavaElement element= SelectionConverter.getElementAtOffset(editor);
205 IType type= (IType)element.getAncestor(IJavaElement.TYPE);
207 ICompilationUnit unit= SelectionConverter.getInputAsCompilationUnit(editor);
209 type= unit.findPrimaryType();
215 * Returns the input element of the given editor.
217 * @param editor the Java editor
218 * @return the type root which is the editor input (only primary working copies), or <code>null</code> if none
220 public static ITypeRoot getInput(JavaEditor editor) {
221 return getInput(editor, true);
225 * Returns the input element of the given editor.
227 * @param editor the Java editor
228 * @param primaryOnly if <code>true</code> only primary working copies will be returned
229 * @return the type root which is the editor input, or <code>null</code> if none
232 private static ITypeRoot getInput(JavaEditor editor, boolean primaryOnly) {
235 return EditorUtility.getEditorInputJavaElement(editor, primaryOnly);
238 public static ICompilationUnit getInputAsCompilationUnit(JavaEditor editor) {
239 Object editorInput= SelectionConverter.getInput(editor);
240 if (editorInput instanceof ICompilationUnit)
241 return (ICompilationUnit)editorInput;
245 public static IClassFile getInputAsClassFile(JavaEditor editor) {
246 Object editorInput= SelectionConverter.getInput(editor);
247 if (editorInput instanceof IClassFile)
248 return (IClassFile)editorInput;
252 private static IJavaElement[] performForkedCodeResolve(final ITypeRoot input, final ITextSelection selection) throws InvocationTargetException, InterruptedException {
253 final class CodeResolveRunnable implements IRunnableWithProgress {
254 IJavaElement[] result;
255 public void run(IProgressMonitor monitor) throws InvocationTargetException {
257 result= codeResolve(input, selection);
258 } catch (JavaModelException e) {
259 throw new InvocationTargetException(e);
263 CodeResolveRunnable runnable= new CodeResolveRunnable();
264 PlatformUI.getWorkbench().getProgressService().busyCursorWhile(runnable);
265 return runnable.result;
268 public static IJavaElement[] codeResolve(IJavaElement input, ITextSelection selection) throws JavaModelException {
269 if (input instanceof ICodeAssist) {
270 if (input instanceof ICompilationUnit) {
271 JavaModelUtil.reconcile((ICompilationUnit) input);
273 IJavaElement[] elements= ((ICodeAssist)input).codeSelect(selection.getOffset() + selection.getLength(), 0);
274 if (elements.length > 0) {
281 public static IJavaElement getElementAtOffset(ITypeRoot input, ITextSelection selection) throws JavaModelException {
282 if (input instanceof ICompilationUnit) {
283 JavaModelUtil.reconcile((ICompilationUnit) input);
285 IJavaElement ref= input.getElementAt(selection.getOffset());
291 public static IJavaElement resolveEnclosingElement(JavaEditor editor, ITextSelection selection) throws JavaModelException {
292 ITypeRoot input= getInput(editor);
294 return resolveEnclosingElement(input, selection);
298 public static IJavaElement resolveEnclosingElement(IJavaElement input, ITextSelection selection) throws JavaModelException {
299 IJavaElement atOffset= null;
300 if (input instanceof ICompilationUnit) {
301 ICompilationUnit cunit= (ICompilationUnit)input;
302 JavaModelUtil.reconcile(cunit);
303 atOffset= cunit.getElementAt(selection.getOffset());
304 } else if (input instanceof IClassFile) {
305 IClassFile cfile= (IClassFile)input;
306 atOffset= cfile.getElementAt(selection.getOffset());
310 if (atOffset == null) {
313 int selectionEnd= selection.getOffset() + selection.getLength();
314 IJavaElement result= atOffset;
315 if (atOffset instanceof ISourceReference) {
316 ISourceRange range= ((ISourceReference)atOffset).getSourceRange();
317 while (range.getOffset() + range.getLength() < selectionEnd) {
318 result= result.getParent();
319 if (! (result instanceof ISourceReference)) {
323 range= ((ISourceReference)result).getSourceRange();
331 * Shows a dialog for resolving an ambiguous Java element. Utility method that can be called by subclasses.
333 * @param elements the elements to select from
334 * @param shell the parent shell
335 * @param title the title of the selection dialog
336 * @param message the message of the selection dialog
337 * @return returns the selected element or <code>null</code> if the dialog has been cancelled
339 public static IJavaElement selectJavaElement(IJavaElement[] elements, Shell shell, String title, String message) {
340 int nResults= elements.length;
346 int flags= JavaElementLabelProvider.SHOW_DEFAULT | JavaElementLabelProvider.SHOW_QUALIFIED | JavaElementLabelProvider.SHOW_ROOT;
348 ElementListSelectionDialog dialog= new ElementListSelectionDialog(shell, new JavaElementLabelProvider(flags));
349 dialog.setTitle(title);
350 dialog.setMessage(message);
351 dialog.setElements(elements);
353 if (dialog.open() == Window.OK) {
354 return (IJavaElement) dialog.getFirstResult();