]> git.uio.no Git - ifi-stolz-refaktor.git/blame - case-study/jdt-before/ui/org/eclipse/jdt/ui/actions/OrganizeImportsAction.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-before / ui / org / eclipse / jdt / ui / actions / OrganizeImportsAction.java
CommitLineData
1b2798f6
EK
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
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11package org.eclipse.jdt.ui.actions;
12
13import java.lang.reflect.InvocationTargetException;
14import java.util.Comparator;
15
16import com.ibm.icu.text.Collator;
17
18import org.eclipse.core.runtime.Assert;
19
20import org.eclipse.jface.action.IAction;
21import org.eclipse.jface.action.IStatusLineManager;
22import org.eclipse.jface.dialogs.MessageDialog;
23import org.eclipse.jface.operation.IRunnableContext;
24import org.eclipse.jface.viewers.ILabelProvider;
25import org.eclipse.jface.viewers.ISelection;
26import org.eclipse.jface.viewers.IStructuredSelection;
27import org.eclipse.jface.viewers.StructuredSelection;
28import org.eclipse.jface.window.Window;
29
30import org.eclipse.jface.text.DocumentEvent;
31import org.eclipse.jface.text.IEditingSupport;
32import org.eclipse.jface.text.IEditingSupportRegistry;
33import org.eclipse.jface.text.IRegion;
34import org.eclipse.jface.text.IRewriteTarget;
35import org.eclipse.jface.text.ITextSelection;
36import org.eclipse.jface.text.source.ISourceViewer;
37
38import org.eclipse.ui.IEditorPart;
39import org.eclipse.ui.IObjectActionDelegate;
40import org.eclipse.ui.IWorkbenchPart;
41import org.eclipse.ui.IWorkbenchSite;
42import org.eclipse.ui.PlatformUI;
43import org.eclipse.ui.progress.IProgressService;
44
45import org.eclipse.jdt.core.ICompilationUnit;
46import org.eclipse.jdt.core.IJavaElement;
47import org.eclipse.jdt.core.ISourceRange;
48import org.eclipse.jdt.core.compiler.IProblem;
49import org.eclipse.jdt.core.dom.CompilationUnit;
50import org.eclipse.jdt.core.search.TypeNameMatch;
51
52import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
53import org.eclipse.jdt.internal.corext.codemanipulation.OrganizeImportsOperation;
54import org.eclipse.jdt.internal.corext.codemanipulation.OrganizeImportsOperation.IChooseImportQuery;
55import org.eclipse.jdt.internal.corext.util.History;
56import org.eclipse.jdt.internal.corext.util.Messages;
57import org.eclipse.jdt.internal.corext.util.QualifiedTypeNameHistory;
58
59import org.eclipse.jdt.ui.JavaUI;
60import org.eclipse.jdt.ui.SharedASTProvider;
61
62import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
63import org.eclipse.jdt.internal.ui.actions.ActionMessages;
64import org.eclipse.jdt.internal.ui.actions.ActionUtil;
65import org.eclipse.jdt.internal.ui.actions.MultiOrganizeImportAction;
66import org.eclipse.jdt.internal.ui.actions.WorkbenchRunnableAdapter;
67import org.eclipse.jdt.internal.ui.dialogs.MultiElementListSelectionDialog;
68import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
69import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
70import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
71import org.eclipse.jdt.internal.ui.util.ElementValidator;
72import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
73import org.eclipse.jdt.internal.ui.util.TypeNameMatchLabelProvider;
74
75/**
76 * Organizes the imports of a compilation unit.
77 * <p>
78 * The action is applicable to selections containing elements of
79 * type <code>ICompilationUnit</code> or <code>IPackage
80 * </code>.
81 *
82 * <p>
83 * This class may be instantiated; it is not intended to be subclassed.
84 * </p>
85 *
86 * @since 2.0
87 *
88 * @noextend This class is not intended to be subclassed by clients.
89 */
90public class OrganizeImportsAction extends SelectionDispatchAction {
91
92 private static final OrganizeImportComparator ORGANIZE_IMPORT_COMPARATOR= new OrganizeImportComparator();
93
94 private JavaEditor fEditor;
95 /** <code>true</code> if the query dialog is showing. */
96 private boolean fIsQueryShowing= false;
97 private final MultiOrganizeImportAction fCleanUpDelegate;
98
99 /* (non-Javadoc)
100 * Class implements IObjectActionDelegate
101 */
102 public static class ObjectDelegate implements IObjectActionDelegate {
103 private OrganizeImportsAction fAction;
104 public void setActivePart(IAction action, IWorkbenchPart targetPart) {
105 fAction= new OrganizeImportsAction(targetPart.getSite());
106 }
107 public void run(IAction action) {
108 fAction.run();
109 }
110 public void selectionChanged(IAction action, ISelection selection) {
111 if (fAction == null)
112 action.setEnabled(false);
113 }
114 }
115
116 private static final class OrganizeImportComparator implements Comparator<String> {
117
118 public int compare(String o1, String o2) {
119 if (o1.equals(o2))
120 return 0;
121
122 History history= QualifiedTypeNameHistory.getDefault();
123
124 int pos1= history.getPosition(o1);
125 int pos2= history.getPosition(o2);
126
127 if (pos1 == pos2)
128 return Collator.getInstance().compare(o1, o2);
129
130 if (pos1 > pos2) {
131 return -1;
132 } else {
133 return 1;
134 }
135 }
136
137 }
138
139 /**
140 * Creates a new <code>OrganizeImportsAction</code>. The action requires
141 * that the selection provided by the site's selection provider is of type <code>
142 * org.eclipse.jface.viewers.IStructuredSelection</code>.
143 *
144 * @param site the site providing context information for this action
145 */
146 public OrganizeImportsAction(IWorkbenchSite site) {
147 super(site);
148
149 fCleanUpDelegate= new MultiOrganizeImportAction(site);
150
151 setText(ActionMessages.OrganizeImportsAction_label);
152 setToolTipText(ActionMessages.OrganizeImportsAction_tooltip);
153 setDescription(ActionMessages.OrganizeImportsAction_description);
154
155 PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IJavaHelpContextIds.ORGANIZE_IMPORTS_ACTION);
156 }
157
158 /**
159 * Note: This constructor is for internal use only. Clients should not call this constructor.
160 * @param editor the Java editor
161 *
162 * @noreference This constructor is not intended to be referenced by clients.
163 */
164 public OrganizeImportsAction(JavaEditor editor) {
165 super(editor.getEditorSite());
166
167 fEditor= editor;
168 fCleanUpDelegate= new MultiOrganizeImportAction(editor);
169
170 setText(ActionMessages.OrganizeImportsAction_label);
171 setToolTipText(ActionMessages.OrganizeImportsAction_tooltip);
172 setDescription(ActionMessages.OrganizeImportsAction_description);
173
174 PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IJavaHelpContextIds.ORGANIZE_IMPORTS_ACTION);
175
176 setEnabled(fCleanUpDelegate.isEnabled());
177 }
178
179 /* (non-Javadoc)
180 * Method declared on SelectionDispatchAction.
181 */
182 @Override
183 public void selectionChanged(ITextSelection selection) {
184 fCleanUpDelegate.selectionChanged(selection);
185 setEnabled(fCleanUpDelegate.isEnabled());
186 }
187
188 /* (non-Javadoc)
189 * Method declared on SelectionDispatchAction.
190 */
191 @Override
192 public void selectionChanged(IStructuredSelection selection) {
193 fCleanUpDelegate.selectionChanged(selection);
194 setEnabled(fCleanUpDelegate.isEnabled());
195 }
196
197 /* (non-Javadoc)
198 * Method declared on SelectionDispatchAction.
199 */
200 @Override
201 public void run(ITextSelection selection) {
202 ICompilationUnit cu= getCompilationUnit(fEditor);
203 if (cu != null) {
204 run(cu);
205 }
206 }
207
208 private static ICompilationUnit getCompilationUnit(JavaEditor editor) {
209 IJavaElement element= JavaUI.getEditorInputJavaElement(editor.getEditorInput());
210 if (!(element instanceof ICompilationUnit))
211 return null;
212
213 return (ICompilationUnit)element;
214 }
215
216 /* (non-Javadoc)
217 * Method declared on SelectionDispatchAction.
218 */
219 @Override
220 public void run(IStructuredSelection selection) {
221 ICompilationUnit[] cus= fCleanUpDelegate.getCompilationUnits(selection);
222 if (cus.length == 0) {
223 MessageDialog.openInformation(getShell(), ActionMessages.OrganizeImportsAction_EmptySelection_title, ActionMessages.OrganizeImportsAction_EmptySelection_description);
224 } else if (cus.length == 1) {
225 run(cus[0]);
226 } else {
227 fCleanUpDelegate.run(selection);
228 }
229 }
230
231 /**
232 * Perform organize import on multiple compilation units. No editors are opened.
233 * @param cus The compilation units to run on
234 */
235 public void runOnMultiple(final ICompilationUnit[] cus) {
236 if (cus.length == 0)
237 return;
238
239 fCleanUpDelegate.run(new StructuredSelection(cus));
240 }
241
242 /**
243 * Runs the organize import action on a single compilation unit
244 *
245 * @param cu The compilation unit to process
246 */
247 public void run(ICompilationUnit cu) {
248
249 JavaEditor editor= null;
250 if (fEditor != null) {
251 editor= fEditor;
252
253 //organize imports from within editor -> editor has focus
254 if (!ElementValidator.check(cu, getShell(), ActionMessages.OrganizeImportsAction_error_title, true))
255 return;
256 } else {
257 IEditorPart openEditor= EditorUtility.isOpenInEditor(cu);
258 if (!(openEditor instanceof JavaEditor)) {
259 fCleanUpDelegate.run(new StructuredSelection(cu));
260 return;
261 }
262
263 editor= (JavaEditor) openEditor;
264 //organize imports from package explorer -> editor does not have focus
265 if (!ElementValidator.check(cu, getShell(), ActionMessages.OrganizeImportsAction_error_title, false))
266 return;
267 }
268
269 Assert.isNotNull(editor);
270 if (!ActionUtil.isEditable(editor, getShell(), cu))
271 return;
272
273 CompilationUnit astRoot= SharedASTProvider.getAST(cu, SharedASTProvider.WAIT_ACTIVE_ONLY, null);
274
275 CodeGenerationSettings settings= JavaPreferencesSettings.getCodeGenerationSettings(cu.getJavaProject());
276 OrganizeImportsOperation op= new OrganizeImportsOperation(cu, astRoot, settings.importIgnoreLowercase, !cu.isWorkingCopy(), true, createChooseImportQuery(editor));
277
278 IRewriteTarget target= (IRewriteTarget) editor.getAdapter(IRewriteTarget.class);
279 if (target != null) {
280 target.beginCompoundChange();
281 }
282
283 IProgressService progressService= PlatformUI.getWorkbench().getProgressService();
284 IRunnableContext context= getSite().getWorkbenchWindow();
285 if (context == null) {
286 context= progressService;
287 }
288 IEditingSupport helper= createViewerHelper();
289 try {
290 registerHelper(helper, editor);
291 progressService.runInUI(context, new WorkbenchRunnableAdapter(op, op.getScheduleRule()), op.getScheduleRule());
292 IProblem parseError= op.getParseError();
293 if (parseError != null) {
294 String message= Messages.format(ActionMessages.OrganizeImportsAction_single_error_parse, parseError.getMessage());
295 MessageDialog.openInformation(getShell(), ActionMessages.OrganizeImportsAction_error_title, message);
296 if (parseError.getSourceStart() != -1) {
297 editor.selectAndReveal(parseError.getSourceStart(), parseError.getSourceEnd() - parseError.getSourceStart() + 1);
298 }
299 } else {
300 setStatusBarMessage(getOrganizeInfo(op), editor);
301 }
302 } catch (InvocationTargetException e) {
303 ExceptionHandler.handle(e, getShell(), ActionMessages.OrganizeImportsAction_error_title, ActionMessages.OrganizeImportsAction_error_message);
304 } catch (InterruptedException e) {
305 } finally {
306 deregisterHelper(helper, editor);
307 if (target != null) {
308 target.endCompoundChange();
309 }
310 }
311 }
312
313 private String getOrganizeInfo(OrganizeImportsOperation op) {
314 int nImportsAdded= op.getNumberOfImportsAdded();
315 if (nImportsAdded >= 0) {
316 if (nImportsAdded == 1) {
317 return ActionMessages.OrganizeImportsAction_summary_added_singular;
318 } else {
319 return Messages.format(ActionMessages.OrganizeImportsAction_summary_added_plural, String.valueOf(nImportsAdded));
320 }
321 } else {
322 if (nImportsAdded == -1) {
323 return ActionMessages.OrganizeImportsAction_summary_removed_singular;
324 } else {
325 return Messages.format(ActionMessages.OrganizeImportsAction_summary_removed_plural, String.valueOf(-nImportsAdded));
326 }
327 }
328 }
329
330 private IChooseImportQuery createChooseImportQuery(final JavaEditor editor) {
331 return new IChooseImportQuery() {
332 public TypeNameMatch[] chooseImports(TypeNameMatch[][] openChoices, ISourceRange[] ranges) {
333 return doChooseImports(openChoices, ranges, editor);
334 }
335 };
336 }
337
338 private TypeNameMatch[] doChooseImports(TypeNameMatch[][] openChoices, final ISourceRange[] ranges, final JavaEditor editor) {
339 // remember selection
340 ISelection sel= editor.getSelectionProvider().getSelection();
341 TypeNameMatch[] result= null;
342 ILabelProvider labelProvider= new TypeNameMatchLabelProvider(TypeNameMatchLabelProvider.SHOW_FULLYQUALIFIED);
343
344 MultiElementListSelectionDialog dialog= new MultiElementListSelectionDialog(getShell(), labelProvider) {
345 @Override
346 protected void handleSelectionChanged() {
347 super.handleSelectionChanged();
348 // show choices in editor
349 doListSelectionChanged(getCurrentPage(), ranges, editor);
350 }
351 };
352 fIsQueryShowing= true;
353 dialog.setTitle(ActionMessages.OrganizeImportsAction_selectiondialog_title);
354 dialog.setMessage(ActionMessages.OrganizeImportsAction_selectiondialog_message);
355 dialog.setElements(openChoices);
356 dialog.setComparator(ORGANIZE_IMPORT_COMPARATOR);
357 if (dialog.open() == Window.OK) {
358 Object[] res= dialog.getResult();
359 result= new TypeNameMatch[res.length];
360 for (int i= 0; i < res.length; i++) {
361 Object[] array= (Object[]) res[i];
362 if (array.length > 0) {
363 result[i]= (TypeNameMatch) array[0];
364 QualifiedTypeNameHistory.remember(result[i].getFullyQualifiedName());
365 }
366 }
367 }
368 // restore selection
369 if (sel instanceof ITextSelection) {
370 ITextSelection textSelection= (ITextSelection) sel;
371 editor.selectAndReveal(textSelection.getOffset(), textSelection.getLength());
372 }
373 fIsQueryShowing= false;
374 return result;
375 }
376
377 private void doListSelectionChanged(int page, ISourceRange[] ranges, JavaEditor editor) {
378 if (ranges != null && page >= 0 && page < ranges.length) {
379 ISourceRange range= ranges[page];
380 editor.selectAndReveal(range.getOffset(), range.getLength());
381 }
382 }
383
384 private void setStatusBarMessage(String message, JavaEditor editor) {
385 IStatusLineManager manager= editor.getEditorSite().getActionBars().getStatusLineManager();
386 manager.setMessage(message);
387 }
388
389 private IEditingSupport createViewerHelper() {
390 return new IEditingSupport() {
391 public boolean isOriginator(DocumentEvent event, IRegion subjectRegion) {
392 return true; // assume true, since we only register while we are active
393 }
394 public boolean ownsFocusShell() {
395 return fIsQueryShowing;
396 }
397
398 };
399 }
400
401 private void registerHelper(IEditingSupport helper, JavaEditor editor) {
402 ISourceViewer viewer= editor.getViewer();
403 if (viewer instanceof IEditingSupportRegistry) {
404 IEditingSupportRegistry registry= (IEditingSupportRegistry) viewer;
405 registry.register(helper);
406 }
407 }
408
409 private void deregisterHelper(IEditingSupport helper, JavaEditor editor) {
410 ISourceViewer viewer= editor.getViewer();
411 if (viewer instanceof IEditingSupportRegistry) {
412 IEditingSupportRegistry registry= (IEditingSupportRegistry) viewer;
413 registry.unregister(helper);
414 }
415 }
416}