1 | /******************************************************************************* |
---|---|
2 | * Copyright (c) 2000, 2022 IBM Corporation and others. |
3 | * |
4 | * This program and the accompanying materials |
5 | * are made available under the terms of the Eclipse Public License 2.0 |
6 | * which accompanies this distribution, and is available at |
7 | * https://www.eclipse.org/legal/epl-2.0/ |
8 | * |
9 | * SPDX-License-Identifier: EPL-2.0 |
10 | * |
11 | * Contributors: |
12 | * IBM Corporation - initial API and implementation |
13 | *******************************************************************************/ |
14 | |
15 | package org.eclipse.jdt.astview.views; |
16 | |
17 | import java.text.MessageFormat; |
18 | import java.util.ArrayList; |
19 | import java.util.Iterator; |
20 | import java.util.List; |
21 | |
22 | import org.eclipse.jdt.astview.ASTViewImages; |
23 | import org.eclipse.jdt.astview.ASTViewPlugin; |
24 | import org.eclipse.jdt.astview.EditorUtility; |
25 | import org.eclipse.jdt.astview.TreeInfoCollector; |
26 | |
27 | import org.eclipse.swt.SWT; |
28 | import org.eclipse.swt.custom.SashForm; |
29 | import org.eclipse.swt.custom.ViewForm; |
30 | import org.eclipse.swt.events.FocusAdapter; |
31 | import org.eclipse.swt.events.FocusEvent; |
32 | import org.eclipse.swt.widgets.Composite; |
33 | import org.eclipse.swt.widgets.Label; |
34 | import org.eclipse.swt.widgets.Menu; |
35 | import org.eclipse.swt.widgets.Tree; |
36 | import org.eclipse.swt.widgets.TreeItem; |
37 | |
38 | import org.eclipse.core.runtime.CoreException; |
39 | import org.eclipse.core.runtime.IPath; |
40 | import org.eclipse.core.runtime.IStatus; |
41 | import org.eclipse.core.runtime.ListenerList; |
42 | import org.eclipse.core.runtime.Status; |
43 | |
44 | import org.eclipse.core.filebuffers.FileBuffers; |
45 | import org.eclipse.core.filebuffers.IFileBuffer; |
46 | import org.eclipse.core.filebuffers.IFileBufferListener; |
47 | import org.eclipse.core.filebuffers.ITextFileBuffer; |
48 | |
49 | import org.eclipse.jface.action.Action; |
50 | import org.eclipse.jface.action.IAction; |
51 | import org.eclipse.jface.action.IMenuManager; |
52 | import org.eclipse.jface.action.IToolBarManager; |
53 | import org.eclipse.jface.action.MenuManager; |
54 | import org.eclipse.jface.action.Separator; |
55 | import org.eclipse.jface.commands.ActionHandler; |
56 | import org.eclipse.jface.dialogs.ErrorDialog; |
57 | import org.eclipse.jface.dialogs.IDialogSettings; |
58 | import org.eclipse.jface.dialogs.InputDialog; |
59 | import org.eclipse.jface.dialogs.MessageDialog; |
60 | import org.eclipse.jface.viewers.AbstractTreeViewer; |
61 | import org.eclipse.jface.viewers.DoubleClickEvent; |
62 | import org.eclipse.jface.viewers.IDoubleClickListener; |
63 | import org.eclipse.jface.viewers.ISelection; |
64 | import org.eclipse.jface.viewers.ISelectionChangedListener; |
65 | import org.eclipse.jface.viewers.ISelectionProvider; |
66 | import org.eclipse.jface.viewers.IStructuredSelection; |
67 | import org.eclipse.jface.viewers.SelectionChangedEvent; |
68 | import org.eclipse.jface.viewers.StructuredSelection; |
69 | import org.eclipse.jface.viewers.TreeViewer; |
70 | import org.eclipse.jface.viewers.Viewer; |
71 | import org.eclipse.jface.viewers.ViewerFilter; |
72 | import org.eclipse.jface.window.Window; |
73 | |
74 | import org.eclipse.jface.text.DocumentEvent; |
75 | import org.eclipse.jface.text.IDocument; |
76 | import org.eclipse.jface.text.IDocumentListener; |
77 | import org.eclipse.jface.text.ITextSelection; |
78 | |
79 | import org.eclipse.ui.IActionBars; |
80 | import org.eclipse.ui.IEditorPart; |
81 | import org.eclipse.ui.IPartListener2; |
82 | import org.eclipse.ui.ISelectionListener; |
83 | import org.eclipse.ui.ISelectionService; |
84 | import org.eclipse.ui.ISharedImages; |
85 | import org.eclipse.ui.IViewPart; |
86 | import org.eclipse.ui.IViewSite; |
87 | import org.eclipse.ui.IWorkbenchActionConstants; |
88 | import org.eclipse.ui.IWorkbenchCommandConstants; |
89 | import org.eclipse.ui.IWorkbenchPart; |
90 | import org.eclipse.ui.IWorkbenchPartReference; |
91 | import org.eclipse.ui.IWorkbenchWindow; |
92 | import org.eclipse.ui.PartInitException; |
93 | import org.eclipse.ui.PlatformUI; |
94 | import org.eclipse.ui.actions.ActionFactory; |
95 | import org.eclipse.ui.actions.ContributionItemFactory; |
96 | import org.eclipse.ui.handlers.IHandlerService; |
97 | import org.eclipse.ui.keys.IBindingService; |
98 | import org.eclipse.ui.part.DrillDownAdapter; |
99 | import org.eclipse.ui.part.IShowInSource; |
100 | import org.eclipse.ui.part.IShowInTarget; |
101 | import org.eclipse.ui.part.IShowInTargetList; |
102 | import org.eclipse.ui.part.ShowInContext; |
103 | import org.eclipse.ui.part.ViewPart; |
104 | |
105 | import org.eclipse.ui.texteditor.ITextEditor; |
106 | |
107 | import org.eclipse.jdt.core.ICompilationUnit; |
108 | import org.eclipse.jdt.core.IJavaElement; |
109 | import org.eclipse.jdt.core.IJavaProject; |
110 | import org.eclipse.jdt.core.IPackageFragment; |
111 | import org.eclipse.jdt.core.IProblemRequestor; |
112 | import org.eclipse.jdt.core.ITypeRoot; |
113 | import org.eclipse.jdt.core.JavaCore; |
114 | import org.eclipse.jdt.core.JavaModelException; |
115 | import org.eclipse.jdt.core.WorkingCopyOwner; |
116 | import org.eclipse.jdt.core.compiler.IProblem; |
117 | import org.eclipse.jdt.core.dom.AST; |
118 | import org.eclipse.jdt.core.dom.ASTNode; |
119 | import org.eclipse.jdt.core.dom.ASTParser; |
120 | import org.eclipse.jdt.core.dom.ASTRequestor; |
121 | import org.eclipse.jdt.core.dom.ASTVisitor; |
122 | import org.eclipse.jdt.core.dom.Block; |
123 | import org.eclipse.jdt.core.dom.CompilationUnit; |
124 | import org.eclipse.jdt.core.dom.Expression; |
125 | import org.eclipse.jdt.core.dom.ExpressionStatement; |
126 | import org.eclipse.jdt.core.dom.IBinding; |
127 | import org.eclipse.jdt.core.dom.NodeFinder; |
128 | import org.eclipse.jdt.core.dom.Statement; |
129 | import org.eclipse.jdt.core.dom.SwitchExpression; |
130 | import org.eclipse.jdt.core.dom.YieldStatement; |
131 | import org.eclipse.jdt.core.manipulation.SharedASTProviderCore; |
132 | |
133 | import org.eclipse.jdt.ui.JavaUI; |
134 | |
135 | import org.eclipse.jdt.internal.ui.util.ASTHelper; |
136 | |
137 | |
138 | public class ASTView extends ViewPart implements IShowInSource, IShowInTargetList { |
139 | |
140 | static final int JLS_LATEST= AST.getJLSLatest(); |
141 | private static final int JLS19= ASTHelper.JLS19; |
142 | private static final int JLS18= ASTHelper.JLS18; |
143 | private static final int JLS17= ASTHelper.JLS17; |
144 | private static final int JLS16= ASTHelper.JLS16; |
145 | private static final int JLS15= ASTHelper.JLS15; |
146 | private static final int JLS14= ASTHelper.JLS14; |
147 | private static final int JLS13= ASTHelper.JLS13; |
148 | private static final int JLS12= ASTHelper.JLS12; |
149 | private static final int JLS11= ASTHelper.JLS11; |
150 | private static final int JLS10= ASTHelper.JLS10; |
151 | private static final int JLS9= ASTHelper.JLS9; |
152 | private static final int JLS8= ASTHelper.JLS8; |
153 | private static final int JLS4= ASTHelper.JLS4; |
154 | private static final int JLS3= ASTHelper.JLS3; |
155 | private static final int JLS2= ASTHelper.JLS2; |
156 | |
157 | private class ASTViewSelectionProvider implements ISelectionProvider { |
158 | ListenerList<ISelectionChangedListener> fListeners= new ListenerList<>(ListenerList.IDENTITY); |
159 | |
160 | @Override |
161 | public void addSelectionChangedListener(ISelectionChangedListener listener) { |
162 | fListeners.add(listener); |
163 | } |
164 | |
165 | @Override |
166 | public ISelection getSelection() { |
167 | IStructuredSelection selection= (IStructuredSelection) fViewer.getSelection(); |
168 | ArrayList<Object> externalSelection= new ArrayList<>(); |
169 | for (Iterator<?> iter= selection.iterator(); iter.hasNext();) { |
170 | Object unwrapped= ASTView.unwrapAttribute(iter.next()); |
171 | if (unwrapped != null) |
172 | externalSelection.add(unwrapped); |
173 | } |
174 | return new StructuredSelection(externalSelection); |
175 | } |
176 | |
177 | @Override |
178 | public void removeSelectionChangedListener(ISelectionChangedListener listener) { |
179 | fListeners.remove(listener); |
180 | } |
181 | |
182 | @Override |
183 | public void setSelection(ISelection selection) { |
184 | //not supported |
185 | } |
186 | } |
187 | |
188 | private class ASTLevelToggle extends Action { |
189 | private int fLevel; |
190 | |
191 | public ASTLevelToggle(String label, int level) { |
192 | super(label, AS_RADIO_BUTTON); |
193 | fLevel= level; |
194 | if (level == getCurrentASTLevel()) { |
195 | setChecked(true); |
196 | } |
197 | } |
198 | |
199 | public int getLevel() { |
200 | return fLevel; |
201 | } |
202 | |
203 | @Override |
204 | public void run() { |
205 | setASTLevel(fLevel, true); |
206 | } |
207 | } |
208 | |
209 | private class ASTInputKindAction extends Action { |
210 | public static final int USE_PARSER= 1; |
211 | public static final int USE_RECONCILE= 2; |
212 | public static final int USE_CACHE= 3; |
213 | public static final int USE_FOCAL= 4; |
214 | |
215 | private int fInputKind; |
216 | |
217 | public ASTInputKindAction(String label, int inputKind) { |
218 | super(label, AS_RADIO_BUTTON); |
219 | fInputKind= inputKind; |
220 | if (inputKind == getCurrentInputKind()) { |
221 | setChecked(true); |
222 | } |
223 | } |
224 | |
225 | public int getInputKind() { |
226 | return fInputKind; |
227 | } |
228 | |
229 | @Override |
230 | public void run() { |
231 | setASTInputType(fInputKind); |
232 | } |
233 | } |
234 | |
235 | |
236 | private static class ListenerMix implements ISelectionListener, IFileBufferListener, IDocumentListener, ISelectionChangedListener, IDoubleClickListener, IPartListener2 { |
237 | |
238 | private boolean fASTViewVisible= true; |
239 | private ASTView fView; |
240 | |
241 | public ListenerMix(ASTView view) { |
242 | fView= view; |
243 | } |
244 | |
245 | public void dispose() { |
246 | fView= null; |
247 | } |
248 | |
249 | @Override |
250 | public void selectionChanged(IWorkbenchPart part, ISelection selection) { |
251 | if (fASTViewVisible) { |
252 | fView.handleEditorPostSelectionChanged(part, selection); |
253 | } |
254 | } |
255 | |
256 | @Override |
257 | public void bufferCreated(IFileBuffer buffer) { |
258 | // not interesting |
259 | } |
260 | |
261 | @Override |
262 | public void bufferDisposed(IFileBuffer buffer) { |
263 | if (buffer instanceof ITextFileBuffer) { |
264 | fView.handleDocumentDisposed(); |
265 | } |
266 | } |
267 | |
268 | @Override |
269 | public void bufferContentAboutToBeReplaced(IFileBuffer buffer) { |
270 | // not interesting |
271 | } |
272 | |
273 | @Override |
274 | public void bufferContentReplaced(IFileBuffer buffer) { |
275 | // not interesting |
276 | } |
277 | |
278 | @Override |
279 | public void stateChanging(IFileBuffer buffer) { |
280 | // not interesting |
281 | } |
282 | |
283 | @Override |
284 | public void dirtyStateChanged(IFileBuffer buffer, boolean isDirty) { |
285 | // not interesting |
286 | } |
287 | |
288 | @Override |
289 | public void stateValidationChanged(IFileBuffer buffer, boolean isStateValidated) { |
290 | // not interesting |
291 | } |
292 | |
293 | @Override |
294 | public void underlyingFileMoved(IFileBuffer buffer, IPath path) { |
295 | // not interesting |
296 | } |
297 | |
298 | @Override |
299 | public void underlyingFileDeleted(IFileBuffer buffer) { |
300 | // not interesting |
301 | } |
302 | |
303 | @Override |
304 | public void stateChangeFailed(IFileBuffer buffer) { |
305 | // not interesting |
306 | } |
307 | |
308 | @Override |
309 | public void documentAboutToBeChanged(DocumentEvent event) { |
310 | // not interesting |
311 | } |
312 | |
313 | @Override |
314 | public void documentChanged(DocumentEvent event) { |
315 | fView.handleDocumentChanged(); |
316 | } |
317 | |
318 | @Override |
319 | public void selectionChanged(SelectionChangedEvent event) { |
320 | fView.handleSelectionChanged(event.getSelection()); |
321 | } |
322 | |
323 | @Override |
324 | public void doubleClick(DoubleClickEvent event) { |
325 | fView.handleDoubleClick(); |
326 | } |
327 | |
328 | @Override |
329 | public void partHidden(IWorkbenchPartReference partRef) { |
330 | IWorkbenchPart part= partRef.getPart(false); |
331 | if (part == fView) { |
332 | fASTViewVisible= false; |
333 | } |
334 | } |
335 | |
336 | @Override |
337 | public void partVisible(IWorkbenchPartReference partRef) { |
338 | IWorkbenchPart part= partRef.getPart(false); |
339 | if (part == fView) { |
340 | fASTViewVisible= true; |
341 | } |
342 | } |
343 | |
344 | @Override |
345 | public void partActivated(IWorkbenchPartReference partRef) { |
346 | // not interesting |
347 | } |
348 | |
349 | @Override |
350 | public void partBroughtToTop(IWorkbenchPartReference partRef) { |
351 | // not interesting |
352 | } |
353 | |
354 | @Override |
355 | public void partClosed(IWorkbenchPartReference partRef) { |
356 | fView.notifyWorkbenchPartClosed(partRef); |
357 | } |
358 | |
359 | @Override |
360 | public void partDeactivated(IWorkbenchPartReference partRef) { |
361 | // not interesting |
362 | } |
363 | |
364 | @Override |
365 | public void partOpened(IWorkbenchPartReference partRef) { |
366 | // not interesting |
367 | } |
368 | |
369 | @Override |
370 | public void partInputChanged(IWorkbenchPartReference partRef) { |
371 | // not interesting |
372 | } |
373 | } |
374 | |
375 | private static final class StatementChecker extends ASTVisitor { |
376 | |
377 | @Override |
378 | public boolean visit(YieldStatement node) { |
379 | try { |
380 | if (node != null && node.isImplicit() && isInSwitchExpression(node)) { |
381 | ASTNode parent= node.getParent(); |
382 | List<Statement> statements= null; |
383 | if (parent instanceof Block) { |
384 | statements= ((Block) parent).statements(); |
385 | } else if (parent instanceof SwitchExpression) { |
386 | statements= ((SwitchExpression) parent).statements(); |
387 | } |
388 | if (statements == null) { |
389 | return true; |
390 | } |
391 | Expression exp= node.getExpression(); |
392 | if (exp == null) { |
393 | return true; |
394 | } else { |
395 | int index= statements.indexOf(node); |
396 | statements.remove(node); |
397 | node.setExpression(null); |
398 | ExpressionStatement exprStmt= node.getAST().newExpressionStatement(exp); |
399 | exprStmt.setSourceRange(node.getStartPosition(), node.getLength()); |
400 | statements.add(index, exprStmt); |
401 | exprStmt.accept(this); |
402 | return false; |
403 | } |
404 | } |
405 | } catch (UnsupportedOperationException e) { |
406 | // do nothing |
407 | } |
408 | return true; |
409 | } |
410 | |
411 | private boolean isInSwitchExpression(YieldStatement node) { |
412 | boolean result= false; |
413 | ASTNode parent= node; |
414 | while (parent != null) { |
415 | if (parent instanceof SwitchExpression) { |
416 | result= true; |
417 | break; |
418 | } |
419 | parent= parent.getParent(); |
420 | } |
421 | return result; |
422 | } |
423 | } |
424 | |
425 | private final static String SETTINGS_LINK_WITH_EDITOR= "link_with_editor"; //$NON-NLS-1$ |
426 | private final static String SETTINGS_INPUT_KIND= "input_kind"; //$NON-NLS-1$ |
427 | private final static String SETTINGS_NO_BINDINGS= "create_bindings"; //$NON-NLS-1$ |
428 | private final static String SETTINGS_NO_STATEMENTS_RECOVERY= "no_statements_recovery"; //$NON-NLS-1$ |
429 | private final static String SETTINGS_NO_BINDINGS_RECOVERY= "no_bindings_recovery"; //$NON-NLS-1$ |
430 | private final static String SETTINGS_IGNORE_METHOD_BODIES= "ignore_method_bodies"; //$NON-NLS-1$ |
431 | private final static String SETTINGS_SHOW_NON_RELEVANT="show_non_relevant";//$NON-NLS-1$ |
432 | private final static String SETTINGS_JLS= "jls"; //$NON-NLS-1$ |
433 | |
434 | private SashForm fSash; |
435 | private TreeViewer fViewer; |
436 | private ASTViewLabelProvider fASTLabelProvider; |
437 | private TreeViewer fTray; |
438 | |
439 | private DrillDownAdapter fDrillDownAdapter; |
440 | private Action fFocusAction; |
441 | private Action fRefreshAction; |
442 | private Action fCreateBindingsAction; |
443 | private Action fStatementsRecoveryAction; |
444 | private Action fBindingsRecoveryAction; |
445 | private Action fIgnoreMethodBodiesAction; |
446 | private Action fFilterNonRelevantAction; |
447 | private Action fFindDeclaringNodeAction; |
448 | private Action fParseBindingFromKeyAction; |
449 | private Action fParseBindingFromElementAction; |
450 | private Action fCollapseAction; |
451 | private Action fExpandAction; |
452 | private Action fClearAction; |
453 | private TreeCopyAction fCopyAction; |
454 | private Action fDoubleClickAction; |
455 | private Action fLinkWithEditor; |
456 | private Action fAddToTrayAction; |
457 | private Action fDeleteAction; |
458 | |
459 | private ASTLevelToggle[] fASTVersionToggleActions; |
460 | private int fCurrentASTLevel; |
461 | |
462 | private ASTInputKindAction[] fASTInputKindActions; |
463 | private int fCurrentInputKind; |
464 | |
465 | private ITextEditor fEditor; |
466 | private ITypeRoot fTypeRoot; |
467 | private CompilationUnit fRoot; |
468 | private IDocument fCurrentDocument; |
469 | private ArrayList<Object> fTrayRoots; |
470 | |
471 | private boolean fDoLinkWithEditor; |
472 | private boolean fCreateBindings; |
473 | private NonRelevantFilter fNonRelevantFilter; |
474 | private boolean fStatementsRecovery; |
475 | private boolean fBindingsRecovery; |
476 | private boolean fIgnoreMethodBodies; |
477 | |
478 | private Object fPreviousDouble; |
479 | |
480 | private ListenerMix fSuperListener; |
481 | private ISelectionChangedListener fTrayUpdater; |
482 | |
483 | private IDialogSettings fDialogSettings; |
484 | |
485 | |
486 | public ASTView() { |
487 | fSuperListener= null; |
488 | fDialogSettings= ASTViewPlugin.getDefault().getDialogSettings(); |
489 | fDoLinkWithEditor= fDialogSettings.getBoolean(SETTINGS_LINK_WITH_EDITOR); |
490 | try { |
491 | fCurrentInputKind= fDialogSettings.getInt(SETTINGS_INPUT_KIND); |
492 | } catch (NumberFormatException e) { |
493 | fCurrentInputKind= ASTInputKindAction.USE_PARSER; |
494 | } |
495 | fCreateBindings= !fDialogSettings.getBoolean(SETTINGS_NO_BINDINGS); // inverse so that default is to create bindings |
496 | fStatementsRecovery= !fDialogSettings.getBoolean(SETTINGS_NO_STATEMENTS_RECOVERY); // inverse so that default is use recovery |
497 | fBindingsRecovery= !fDialogSettings.getBoolean(SETTINGS_NO_BINDINGS_RECOVERY); // inverse so that default is use recovery |
498 | fIgnoreMethodBodies= fDialogSettings.getBoolean(SETTINGS_IGNORE_METHOD_BODIES); |
499 | fCurrentASTLevel= JLS_LATEST; |
500 | try { |
501 | int level= fDialogSettings.getInt(SETTINGS_JLS); |
502 | switch (level) { |
503 | case JLS2: |
504 | case JLS3: |
505 | case JLS4: |
506 | case JLS8: |
507 | case JLS9: |
508 | case JLS10: |
509 | case JLS11: |
510 | case JLS12: |
511 | case JLS13: |
512 | case JLS14: |
513 | case JLS15: |
514 | case JLS16: |
515 | case JLS17: |
516 | case JLS18: |
517 | case JLS19: |
518 | fCurrentASTLevel= level; |
519 | } |
520 | } catch (NumberFormatException e) { |
521 | // ignore |
522 | } |
523 | fNonRelevantFilter= new NonRelevantFilter(); |
524 | fNonRelevantFilter.setShowNonRelevant(fDialogSettings.getBoolean(SETTINGS_SHOW_NON_RELEVANT)); |
525 | } |
526 | |
527 | final void notifyWorkbenchPartClosed(IWorkbenchPartReference partRef) { |
528 | if (fEditor != null && fEditor.equals(partRef.getPart(false))) { |
529 | try { |
530 | setInput(null); |
531 | } catch (CoreException e) { |
532 | // ignore |
533 | } |
534 | } |
535 | } |
536 | |
537 | @Override |
538 | public void init(IViewSite site) throws PartInitException { |
539 | super.setSite(site); |
540 | if (fSuperListener == null) { |
541 | fSuperListener= new ListenerMix(this); |
542 | |
543 | ISelectionService service= site.getWorkbenchWindow().getSelectionService(); |
544 | service.addPostSelectionListener(fSuperListener); |
545 | site.getPage().addPartListener(fSuperListener); |
546 | FileBuffers.getTextFileBufferManager().addFileBufferListener(fSuperListener); |
547 | } |
548 | } |
549 | |
550 | public int getCurrentASTLevel() { |
551 | return fCurrentASTLevel; |
552 | } |
553 | |
554 | public int getCurrentInputKind() { |
555 | return fCurrentInputKind; |
556 | } |
557 | |
558 | public void setInput(ITextEditor editor) throws CoreException { |
559 | if (fEditor != null) { |
560 | uninstallModificationListener(); |
561 | } |
562 | |
563 | fEditor= null; |
564 | fRoot= null; |
565 | |
566 | if (editor != null) { |
567 | ITypeRoot typeRoot= EditorUtility.getJavaInput(editor); |
568 | if (typeRoot == null) { |
569 | throw new CoreException(getErrorStatus("Editor not showing a CU or class file", null)); //$NON-NLS-1$ |
570 | } |
571 | fTypeRoot= typeRoot; |
572 | |
573 | ISelection selection= editor.getSelectionProvider().getSelection(); |
574 | if (selection instanceof ITextSelection) { |
575 | ITextSelection textSelection= (ITextSelection) selection; |
576 | fRoot= internalSetInput(typeRoot, textSelection.getOffset(), textSelection.getLength()); |
577 | fEditor= editor; |
578 | } |
579 | installModificationListener(); |
580 | } |
581 | |
582 | } |
583 | |
584 | private CompilationUnit internalSetInput(ITypeRoot input, int offset, int length) throws CoreException { |
585 | if (input.getBuffer() == null) { |
586 | throw new CoreException(getErrorStatus("Input has no buffer", null)); //$NON-NLS-1$ |
587 | } |
588 | |
589 | CompilationUnit root; |
590 | try { |
591 | root= createAST(input, offset); |
592 | resetView(root); |
593 | if (root == null) { |
594 | setContentDescription("AST could not be created."); //$NON-NLS-1$ |
595 | return null; |
596 | } |
597 | } catch (RuntimeException e) { |
598 | throw new CoreException(getErrorStatus("Could not create AST:\n" + e.getMessage(), e)); //$NON-NLS-1$ |
599 | } |
600 | |
601 | try { |
602 | ASTNode node= NodeFinder.perform(root, offset, length); |
603 | if (node != null) { |
604 | fViewer.getTree().setRedraw(false); |
605 | try { |
606 | fASTLabelProvider.setSelectedRange(node.getStartPosition(), node.getLength()); |
607 | fViewer.setSelection(new StructuredSelection(node), true); |
608 | } finally { |
609 | fViewer.getTree().setRedraw(true); |
610 | } |
611 | } |
612 | } catch (RuntimeException e) { |
613 | showAndLogError("Could not select node for editor selection", e); //$NON-NLS-1$ |
614 | } |
615 | |
616 | return root; |
617 | } |
618 | |
619 | private void clearView() { |
620 | resetView(null); |
621 | setContentDescription("Open a Java editor and press the 'Show AST of active editor' toolbar button"); //$NON-NLS-1$ |
622 | } |
623 | |
624 | |
625 | private void resetView(CompilationUnit root) { |
626 | fViewer.setInput(root); |
627 | fViewer.getTree().setEnabled(root != null); |
628 | fSash.setMaximizedControl(fViewer.getTree()); |
629 | fTrayRoots= new ArrayList<>(); |
630 | if (fTray != null) |
631 | fTray.setInput(fTrayRoots); |
632 | setASTUptoDate(root != null); |
633 | fClearAction.setEnabled(root != null); |
634 | fFindDeclaringNodeAction.setEnabled(root != null); |
635 | fPreviousDouble= null; // avoid leaking AST |
636 | } |
637 | |
638 | private CompilationUnit createAST(ITypeRoot input, int offset) throws JavaModelException, CoreException { |
639 | long startTime; |
640 | long endTime; |
641 | CompilationUnit root; |
642 | |
643 | if ((getCurrentInputKind() == ASTInputKindAction.USE_RECONCILE)) { |
644 | final IProblemRequestor problemRequestor= new IProblemRequestor() { //strange: don't get bindings when supplying null as problemRequestor |
645 | @Override |
646 | public void acceptProblem(IProblem problem) {/*not interested*/} |
647 | @Override |
648 | public void beginReporting() {/*not interested*/} |
649 | @Override |
650 | public void endReporting() {/*not interested*/} |
651 | @Override |
652 | public boolean isActive() { |
653 | return true; |
654 | } |
655 | }; |
656 | WorkingCopyOwner workingCopyOwner= new WorkingCopyOwner() { |
657 | @Override |
658 | public IProblemRequestor getProblemRequestor(ICompilationUnit workingCopy) { |
659 | return problemRequestor; |
660 | } |
661 | }; |
662 | ICompilationUnit wc= input.getWorkingCopy(workingCopyOwner, null); |
663 | try { |
664 | int reconcileFlags= ICompilationUnit.FORCE_PROBLEM_DETECTION; |
665 | if (fStatementsRecovery) |
666 | reconcileFlags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY; |
667 | if (fBindingsRecovery) |
668 | reconcileFlags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY; |
669 | if (fIgnoreMethodBodies) |
670 | reconcileFlags |= ICompilationUnit.IGNORE_METHOD_BODIES; |
671 | startTime= System.currentTimeMillis(); |
672 | root= wc.reconcile(fCurrentASTLevel, reconcileFlags, null, null); |
673 | endTime= System.currentTimeMillis(); |
674 | } finally { |
675 | wc.discardWorkingCopy(); |
676 | } |
677 | |
678 | } else if (input instanceof ICompilationUnit && (getCurrentInputKind() == ASTInputKindAction.USE_CACHE)) { |
679 | ICompilationUnit cu= (ICompilationUnit) input; |
680 | startTime= System.currentTimeMillis(); |
681 | root= SharedASTProviderCore.getAST(cu, SharedASTProviderCore.WAIT_NO, null); |
682 | endTime= System.currentTimeMillis(); |
683 | |
684 | } else { |
685 | ASTParser parser= ASTParser.newParser(fCurrentASTLevel); |
686 | parser.setResolveBindings(fCreateBindings); |
687 | parser.setSource(input); |
688 | parser.setStatementsRecovery(fStatementsRecovery); |
689 | parser.setBindingsRecovery(fBindingsRecovery); |
690 | parser.setIgnoreMethodBodies(fIgnoreMethodBodies); |
691 | if (getCurrentInputKind() == ASTInputKindAction.USE_FOCAL) { |
692 | parser.setFocalPosition(offset); |
693 | } |
694 | startTime= System.currentTimeMillis(); |
695 | root= (CompilationUnit) parser.createAST(null); |
696 | endTime= System.currentTimeMillis(); |
697 | } |
698 | if (root != null) { |
699 | root.accept(new StatementChecker()); |
700 | updateContentDescription(input, root, endTime - startTime); |
701 | } |
702 | return root; |
703 | } |
704 | |
705 | protected void refreshASTSettingsActions() { |
706 | boolean enabled; |
707 | switch (getCurrentInputKind()) { |
708 | case ASTInputKindAction.USE_CACHE: |
709 | enabled= false; |
710 | break; |
711 | default: |
712 | enabled= true; |
713 | break; |
714 | } |
715 | fCreateBindingsAction.setEnabled(enabled && getCurrentInputKind() != ASTInputKindAction.USE_RECONCILE); |
716 | fStatementsRecoveryAction.setEnabled(enabled); |
717 | fBindingsRecoveryAction.setEnabled(enabled); |
718 | fIgnoreMethodBodiesAction.setEnabled(enabled); |
719 | for (ASTView.ASTLevelToggle action : fASTVersionToggleActions) { |
720 | action.setEnabled(enabled); |
721 | } |
722 | } |
723 | |
724 | private void updateContentDescription(IJavaElement element, CompilationUnit root, long time) { |
725 | StringBuilder version= new StringBuilder("AST Level ").append(root.getAST().apiLevel()); |
726 | switch (getCurrentInputKind()) { |
727 | case ASTInputKindAction.USE_RECONCILE: |
728 | version.append(", from reconciler"); //$NON-NLS-1$ |
729 | break; |
730 | case ASTInputKindAction.USE_CACHE: |
731 | version.append(", from ASTProvider"); //$NON-NLS-1$ |
732 | break; |
733 | case ASTInputKindAction.USE_FOCAL: |
734 | version.append(", using focal position"); //$NON-NLS-1$ |
735 | break; |
736 | default: |
737 | break; |
738 | } |
739 | TreeInfoCollector collector= new TreeInfoCollector(root); |
740 | |
741 | String msg= "{0} ({1}). Creation time: {2,number} ms. Size: {3,number} nodes, {4,number} bytes (AST nodes only)."; //$NON-NLS-1$ |
742 | Object[] args= { element.getElementName(), version.toString(), Long.valueOf(time), Integer.valueOf(collector.getNumberOfNodes()), Integer.valueOf(collector.getSize())}; |
743 | setContentDescription(MessageFormat.format(msg, args)); |
744 | |
745 | } |
746 | |
747 | @Override |
748 | public void dispose() { |
749 | if (fSuperListener != null) { |
750 | if (fEditor != null) { |
751 | uninstallModificationListener(); |
752 | } |
753 | ISelectionService service= getSite().getWorkbenchWindow().getSelectionService(); |
754 | service.removePostSelectionListener(fSuperListener); |
755 | getSite().getPage().removePartListener(fSuperListener); |
756 | FileBuffers.getTextFileBufferManager().removeFileBufferListener(fSuperListener); |
757 | fSuperListener.dispose(); // removes reference to view |
758 | fSuperListener= null; |
759 | } |
760 | if (fTrayUpdater != null) { |
761 | fViewer.removePostSelectionChangedListener(fTrayUpdater); |
762 | fTray.removePostSelectionChangedListener(fTrayUpdater); |
763 | fTrayUpdater= null; |
764 | } |
765 | super.dispose(); |
766 | } |
767 | |
768 | private IStatus getErrorStatus(String message, Throwable th) { |
769 | return new Status(IStatus.ERROR, ASTViewPlugin.getPluginId(), IStatus.ERROR, message, th); |
770 | } |
771 | |
772 | @Override |
773 | public void createPartControl(Composite parent) { |
774 | fSash= new SashForm(parent, SWT.VERTICAL | SWT.SMOOTH); |
775 | fViewer = new TreeViewer(fSash, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); |
776 | fDrillDownAdapter = new DrillDownAdapter(fViewer); |
777 | fViewer.setContentProvider(new ASTViewContentProvider()); |
778 | fASTLabelProvider= new ASTViewLabelProvider(); |
779 | fViewer.setLabelProvider(fASTLabelProvider); |
780 | fViewer.addSelectionChangedListener(fSuperListener); |
781 | fViewer.addDoubleClickListener(fSuperListener); |
782 | fViewer.addFilter(new ViewerFilter() { |
783 | @Override |
784 | public boolean select(Viewer viewer, Object parentElement, Object element) { |
785 | if (!fCreateBindings && element instanceof Binding) |
786 | return false; |
787 | return true; |
788 | } |
789 | }); |
790 | fViewer.addFilter(fNonRelevantFilter); |
791 | |
792 | |
793 | ViewForm trayForm= new ViewForm(fSash, SWT.NONE); |
794 | Label label= new Label(trayForm, SWT.NONE); |
795 | label.setText(" Comparison Tray (* = selection in the upper tree):"); //$NON-NLS-1$ |
796 | trayForm.setTopLeft(label); |
797 | |
798 | fTray= new TreeViewer(trayForm, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); |
799 | trayForm.setContent(fTray.getTree()); |
800 | |
801 | fTrayRoots= new ArrayList<>(); |
802 | fTray.setContentProvider(new TrayContentProvider()); |
803 | final TrayLabelProvider trayLabelProvider= new TrayLabelProvider(); |
804 | fTray.setLabelProvider(trayLabelProvider); |
805 | fTray.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS); |
806 | fTrayUpdater= event -> { |
807 | IStructuredSelection viewerSelection= (IStructuredSelection) fViewer.getSelection(); |
808 | if (viewerSelection.size() == 1) { |
809 | Object first= viewerSelection.getFirstElement(); |
810 | if (unwrapAttribute(first) != null) { |
811 | trayLabelProvider.setViewerElement(first); |
812 | return; |
813 | } |
814 | } |
815 | trayLabelProvider.setViewerElement(null); |
816 | }; |
817 | fTray.addPostSelectionChangedListener(fTrayUpdater); |
818 | fViewer.addPostSelectionChangedListener(fTrayUpdater); |
819 | fTray.addDoubleClickListener(event -> performTrayDoubleClick()); |
820 | fTray.addSelectionChangedListener(event -> { |
821 | IStructuredSelection selection= (IStructuredSelection) event.getSelection(); |
822 | fDeleteAction.setEnabled(selection.size() >= 1 && fTray.getTree().isFocusControl()); |
823 | }); |
824 | fTray.getTree().addFocusListener(new FocusAdapter() { |
825 | @Override |
826 | public void focusGained(FocusEvent e) { |
827 | IStructuredSelection selection= (IStructuredSelection) fTray.getSelection(); |
828 | fDeleteAction.setEnabled(selection.size() >= 1); |
829 | } |
830 | @Override |
831 | public void focusLost(FocusEvent e) { |
832 | fDeleteAction.setEnabled(false); |
833 | } |
834 | }); |
835 | |
836 | makeActions(); |
837 | hookContextMenu(); |
838 | hookTrayContextMenu(); |
839 | contributeToActionBars(); |
840 | getSite().setSelectionProvider(new ASTViewSelectionProvider()); |
841 | |
842 | try { |
843 | IEditorPart part= EditorUtility.getActiveEditor(); |
844 | if (part instanceof ITextEditor) { |
845 | setInput((ITextEditor) part); |
846 | } |
847 | } catch (CoreException e) { |
848 | // ignore |
849 | } |
850 | if (fTypeRoot == null) { |
851 | clearView(); |
852 | } else { |
853 | setASTUptoDate(fTypeRoot != null); |
854 | } |
855 | } |
856 | |
857 | |
858 | private void hookContextMenu() { |
859 | MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$ |
860 | menuMgr.setRemoveAllWhenShown(true); |
861 | menuMgr.addMenuListener(this::fillContextMenu); |
862 | Menu menu = menuMgr.createContextMenu(fViewer.getControl()); |
863 | fViewer.getControl().setMenu(menu); |
864 | getSite().registerContextMenu(menuMgr, fViewer); |
865 | } |
866 | |
867 | private void hookTrayContextMenu() { |
868 | MenuManager menuMgr = new MenuManager("#TrayPopupMenu"); //$NON-NLS-1$ |
869 | menuMgr.setRemoveAllWhenShown(true); |
870 | menuMgr.addMenuListener(manager -> { |
871 | manager.add(fCopyAction); |
872 | manager.add(fDeleteAction); |
873 | manager.add(new Separator()); |
874 | manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); |
875 | }); |
876 | Menu menu = menuMgr.createContextMenu(fTray.getControl()); |
877 | fTray.getControl().setMenu(menu); |
878 | getSite().registerContextMenu("#TrayPopupMenu", menuMgr, fTray); //$NON-NLS-1$ |
879 | } |
880 | |
881 | private void contributeToActionBars() { |
882 | IActionBars bars = getViewSite().getActionBars(); |
883 | fillLocalPullDown(bars.getMenuManager()); |
884 | fillLocalToolBar(bars.getToolBarManager()); |
885 | bars.setGlobalActionHandler(ActionFactory.COPY.getId(), fCopyAction); |
886 | bars.setGlobalActionHandler(ActionFactory.REFRESH.getId(), fFocusAction); |
887 | bars.setGlobalActionHandler(ActionFactory.DELETE.getId(), fDeleteAction); |
888 | |
889 | IHandlerService handlerService= getViewSite().getService(IHandlerService.class); |
890 | handlerService.activateHandler(IWorkbenchCommandConstants.NAVIGATE_TOGGLE_LINK_WITH_EDITOR, new ActionHandler(fLinkWithEditor)); |
891 | } |
892 | |
893 | private void fillLocalPullDown(IMenuManager manager) { |
894 | for (ASTView.ASTLevelToggle action : fASTVersionToggleActions) { |
895 | manager.add(action); |
896 | } |
897 | manager.add(new Separator()); |
898 | manager.add(fCreateBindingsAction); |
899 | manager.add(fStatementsRecoveryAction); |
900 | manager.add(fBindingsRecoveryAction); |
901 | manager.add(fIgnoreMethodBodiesAction); |
902 | manager.add(new Separator()); |
903 | for (ASTView.ASTInputKindAction action : fASTInputKindActions) { |
904 | manager.add(action); |
905 | } |
906 | manager.add(new Separator()); |
907 | manager.add(fFindDeclaringNodeAction); |
908 | manager.add(fParseBindingFromKeyAction); |
909 | manager.add(fParseBindingFromElementAction); |
910 | manager.add(new Separator()); |
911 | manager.add(fFilterNonRelevantAction); |
912 | manager.add(fLinkWithEditor); |
913 | } |
914 | |
915 | protected void fillContextMenu(IMenuManager manager) { |
916 | ISelection selection= getSite().getSelectionProvider().getSelection(); |
917 | if (!selection.isEmpty() && ((IStructuredSelection) selection).getFirstElement() instanceof IJavaElement) { |
918 | MenuManager showInSubMenu= new MenuManager(getShowInMenuLabel()); |
919 | IWorkbenchWindow workbenchWindow= getSite().getWorkbenchWindow(); |
920 | showInSubMenu.add(ContributionItemFactory.VIEWS_SHOW_IN.create(workbenchWindow)); |
921 | manager.add(showInSubMenu); |
922 | manager.add(new Separator()); |
923 | } |
924 | manager.add(fFocusAction); |
925 | manager.add(fRefreshAction); |
926 | manager.add(fClearAction); |
927 | manager.add(fCollapseAction); |
928 | manager.add(fExpandAction); |
929 | manager.add(new Separator()); |
930 | manager.add(fCopyAction); |
931 | if (fAddToTrayAction.isEnabled()) |
932 | manager.add(fAddToTrayAction); |
933 | manager.add(new Separator()); |
934 | |
935 | fDrillDownAdapter.addNavigationActions(manager); |
936 | // Other plug-ins can contribute there actions here |
937 | manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); |
938 | } |
939 | |
940 | private String getShowInMenuLabel() { |
941 | String keyBinding= null; |
942 | |
943 | IBindingService bindingService= PlatformUI.getWorkbench().getAdapter(IBindingService.class); |
944 | if (bindingService != null) |
945 | keyBinding= bindingService.getBestActiveBindingFormattedFor(IWorkbenchCommandConstants.NAVIGATE_SHOW_IN_QUICK_MENU); |
946 | |
947 | if (keyBinding == null) |
948 | keyBinding= ""; //$NON-NLS-1$ |
949 | |
950 | return "Sho&w In" + '\t' + keyBinding; |
951 | } |
952 | |
953 | private void fillLocalToolBar(IToolBarManager manager) { |
954 | manager.add(fFocusAction); |
955 | manager.add(fRefreshAction); |
956 | manager.add(fClearAction); |
957 | manager.add(new Separator()); |
958 | fDrillDownAdapter.addNavigationActions(manager); |
959 | manager.add(new Separator()); |
960 | manager.add(fExpandAction); |
961 | manager.add(fCollapseAction); |
962 | manager.add(fLinkWithEditor); |
963 | } |
964 | |
965 | private void setASTUptoDate(boolean isuptoDate) { |
966 | fRefreshAction.setEnabled(!isuptoDate && fTypeRoot != null); |
967 | } |
968 | |
969 | private void makeActions() { |
970 | fRefreshAction = new Action() { |
971 | @Override |
972 | public void run() { |
973 | performRefresh(); |
974 | } |
975 | }; |
976 | fRefreshAction.setText("&Refresh AST"); //$NON-NLS-1$ |
977 | fRefreshAction.setToolTipText("Refresh AST"); //$NON-NLS-1$ |
978 | fRefreshAction.setEnabled(false); |
979 | ASTViewImages.setImageDescriptors(fRefreshAction, ASTViewImages.REFRESH); |
980 | |
981 | fClearAction = new Action() { |
982 | @Override |
983 | public void run() { |
984 | performClear(); |
985 | } |
986 | }; |
987 | fClearAction.setText("&Clear AST"); //$NON-NLS-1$ |
988 | fClearAction.setToolTipText("Clear AST and release memory"); //$NON-NLS-1$ |
989 | fClearAction.setEnabled(false); |
990 | ASTViewImages.setImageDescriptors(fClearAction, ASTViewImages.CLEAR); |
991 | |
992 | fASTInputKindActions= new ASTInputKindAction[] { |
993 | new ASTInputKindAction("Use ASTParser.&createAST", ASTInputKindAction.USE_PARSER), //$NON-NLS-1$ |
994 | new ASTInputKindAction("Use ASTParser with &focal position", ASTInputKindAction.USE_FOCAL), //$NON-NLS-1$ |
995 | new ASTInputKindAction("Use ICompilationUnit.&reconcile", ASTInputKindAction.USE_RECONCILE), //$NON-NLS-1$ |
996 | new ASTInputKindAction("Use SharedASTProvider.&getAST", ASTInputKindAction.USE_CACHE) //$NON-NLS-1$ |
997 | }; |
998 | |
999 | fCreateBindingsAction = new Action("&Create Bindings", IAction.AS_CHECK_BOX) { //$NON-NLS-1$ |
1000 | @Override |
1001 | public void run() { |
1002 | performCreateBindings(); |
1003 | } |
1004 | }; |
1005 | fCreateBindingsAction.setChecked(fCreateBindings); |
1006 | fCreateBindingsAction.setToolTipText("Create Bindings"); //$NON-NLS-1$ |
1007 | fCreateBindingsAction.setEnabled(true); |
1008 | |
1009 | fStatementsRecoveryAction = new Action("&Statements Recovery", IAction.AS_CHECK_BOX) { //$NON-NLS-1$ |
1010 | @Override |
1011 | public void run() { |
1012 | performStatementsRecovery(); |
1013 | } |
1014 | }; |
1015 | fStatementsRecoveryAction.setChecked(fStatementsRecovery); |
1016 | fStatementsRecoveryAction.setEnabled(true); |
1017 | |
1018 | fBindingsRecoveryAction = new Action("&Bindings Recovery", IAction.AS_CHECK_BOX) { //$NON-NLS-1$ |
1019 | @Override |
1020 | public void run() { |
1021 | performBindingsRecovery(); |
1022 | } |
1023 | }; |
1024 | fBindingsRecoveryAction.setChecked(fBindingsRecovery); |
1025 | fBindingsRecoveryAction.setEnabled(true); |
1026 | |
1027 | fIgnoreMethodBodiesAction = new Action("&Ignore Method Bodies", IAction.AS_CHECK_BOX) { //$NON-NLS-1$ |
1028 | @Override |
1029 | public void run() { |
1030 | performIgnoreMethodBodies(); |
1031 | } |
1032 | }; |
1033 | fIgnoreMethodBodiesAction.setChecked(fIgnoreMethodBodies); |
1034 | fIgnoreMethodBodiesAction.setEnabled(true); |
1035 | |
1036 | fFilterNonRelevantAction = new Action("&Hide Non-Relevant Attributes", IAction.AS_CHECK_BOX) { //$NON-NLS-1$ |
1037 | @Override |
1038 | public void run() { |
1039 | performFilterNonRelevant(); |
1040 | } |
1041 | }; |
1042 | fFilterNonRelevantAction.setChecked(! fNonRelevantFilter.isShowNonRelevant()); |
1043 | fFilterNonRelevantAction.setToolTipText("Hide non-relevant binding attributes"); //$NON-NLS-1$ |
1044 | fFilterNonRelevantAction.setEnabled(true); |
1045 | |
1046 | fFindDeclaringNodeAction= new Action("Find &Declaring Node...", IAction.AS_PUSH_BUTTON) { //$NON-NLS-1$ |
1047 | @Override |
1048 | public void run() { |
1049 | performFindDeclaringNode(); |
1050 | } |
1051 | }; |
1052 | fFindDeclaringNodeAction.setToolTipText("Find Declaring Node..."); //$NON-NLS-1$ |
1053 | fFindDeclaringNodeAction.setEnabled(false); |
1054 | |
1055 | fParseBindingFromElementAction= new Action("&Parse Binding from &Element Handle...", IAction.AS_PUSH_BUTTON) { //$NON-NLS-1$ |
1056 | @Override |
1057 | public void run() { |
1058 | performParseBindingFromElement(); |
1059 | } |
1060 | }; |
1061 | fParseBindingFromElementAction.setToolTipText("Parse Binding from Element Handle..."); //$NON-NLS-1$ |
1062 | fParseBindingFromElementAction.setEnabled(true); |
1063 | |
1064 | fParseBindingFromKeyAction= new Action("Parse Binding from &Key...", IAction.AS_PUSH_BUTTON) { //$NON-NLS-1$ |
1065 | @Override |
1066 | public void run() { |
1067 | performParseBindingFromKey(); |
1068 | } |
1069 | }; |
1070 | fParseBindingFromKeyAction.setToolTipText("Parse Binding from Key..."); //$NON-NLS-1$ |
1071 | fParseBindingFromKeyAction.setEnabled(true); |
1072 | |
1073 | fFocusAction = new Action() { |
1074 | @Override |
1075 | public void run() { |
1076 | performSetFocus(); |
1077 | } |
1078 | }; |
1079 | fFocusAction.setText("&Show AST of active editor"); //$NON-NLS-1$ |
1080 | fFocusAction.setToolTipText("Show AST of active editor"); //$NON-NLS-1$ |
1081 | fFocusAction.setActionDefinitionId(IWorkbenchCommandConstants.FILE_REFRESH); |
1082 | ASTViewImages.setImageDescriptors(fFocusAction, ASTViewImages.SETFOCUS); |
1083 | |
1084 | fCollapseAction = new Action() { |
1085 | @Override |
1086 | public void run() { |
1087 | performCollapse(); |
1088 | } |
1089 | }; |
1090 | fCollapseAction.setText("C&ollapse"); //$NON-NLS-1$ |
1091 | fCollapseAction.setToolTipText("Collapse Selected Node"); //$NON-NLS-1$ |
1092 | fCollapseAction.setEnabled(false); |
1093 | ASTViewImages.setImageDescriptors(fCollapseAction, ASTViewImages.COLLAPSE); |
1094 | |
1095 | fExpandAction = new Action() { |
1096 | @Override |
1097 | public void run() { |
1098 | performExpand(); |
1099 | } |
1100 | }; |
1101 | fExpandAction.setText("E&xpand"); //$NON-NLS-1$ |
1102 | fExpandAction.setToolTipText("Expand Selected Node"); //$NON-NLS-1$ |
1103 | fExpandAction.setEnabled(false); |
1104 | ASTViewImages.setImageDescriptors(fExpandAction, ASTViewImages.EXPAND); |
1105 | |
1106 | fCopyAction= new TreeCopyAction(new Tree[] {fViewer.getTree(), fTray.getTree()}); |
1107 | |
1108 | fDoubleClickAction = new Action() { |
1109 | @Override |
1110 | public void run() { |
1111 | performDoubleClick(); |
1112 | } |
1113 | }; |
1114 | |
1115 | fLinkWithEditor = new Action() { |
1116 | @Override |
1117 | public void run() { |
1118 | performLinkWithEditor(); |
1119 | } |
1120 | }; |
1121 | fLinkWithEditor.setChecked(fDoLinkWithEditor); |
1122 | fLinkWithEditor.setText("&Link with Editor"); //$NON-NLS-1$ |
1123 | fLinkWithEditor.setToolTipText("Link With Editor"); //$NON-NLS-1$ |
1124 | fLinkWithEditor.setActionDefinitionId(IWorkbenchCommandConstants.NAVIGATE_TOGGLE_LINK_WITH_EDITOR); |
1125 | ASTViewImages.setImageDescriptors(fLinkWithEditor, ASTViewImages.LINK_WITH_EDITOR); |
1126 | |
1127 | fASTVersionToggleActions= new ASTLevelToggle[] { |
1128 | new ASTLevelToggle("AST Level &2 (1.2)", JLS2), //$NON-NLS-1$ |
1129 | new ASTLevelToggle("AST Level &3 (1.5)", JLS3), //$NON-NLS-1$ |
1130 | new ASTLevelToggle("AST Level &4 (1.7)", JLS4), //$NON-NLS-1$ |
1131 | new ASTLevelToggle("AST Level &8 (1.8)", JLS8), //$NON-NLS-1$ |
1132 | new ASTLevelToggle("AST Level &9 (9)", JLS9), //$NON-NLS-1$ |
1133 | new ASTLevelToggle("AST Level 1&0 (10)", JLS10), //$NON-NLS-1$ |
1134 | new ASTLevelToggle("AST Level 1&1 (11)", JLS11), //$NON-NLS-1$ |
1135 | new ASTLevelToggle("AST Level 1&2 (12)", JLS12), //$NON-NLS-1$ |
1136 | new ASTLevelToggle("AST Level 1&3 (13)", JLS13), //$NON-NLS-1$ |
1137 | new ASTLevelToggle("AST Level 1&4 (14)", JLS14), //$NON-NLS-1$ |
1138 | new ASTLevelToggle("AST Level 1&5 (15)", JLS15), //$NON-NLS-1$ |
1139 | new ASTLevelToggle("AST Level 1&6 (16)", JLS16), //$NON-NLS-1$ |
1140 | new ASTLevelToggle("AST Level 1&7 (17)", JLS17), //$NON-NLS-1$ |
1141 | new ASTLevelToggle("AST Level 1&8 (18)", JLS18), //$NON-NLS-1$ |
1142 | new ASTLevelToggle("AST Level 1&9 (19)", JLS19), //$NON-NLS-1$ |
1143 | }; |
1144 | |
1145 | fAddToTrayAction= new Action() { |
1146 | @Override |
1147 | public void run() { |
1148 | performAddToTray(); |
1149 | } |
1150 | }; |
1151 | fAddToTrayAction.setText("&Add to Comparison Tray"); //$NON-NLS-1$ |
1152 | fAddToTrayAction.setToolTipText("Add Selected Node to Comparison Tray"); //$NON-NLS-1$ |
1153 | fAddToTrayAction.setEnabled(false); |
1154 | ASTViewImages.setImageDescriptors(fAddToTrayAction, ASTViewImages.ADD_TO_TRAY); |
1155 | |
1156 | fDeleteAction= new Action() { |
1157 | @Override |
1158 | public void run() { |
1159 | performDelete(); |
1160 | } |
1161 | }; |
1162 | fDeleteAction.setText("&Delete"); //$NON-NLS-1$ |
1163 | fDeleteAction.setToolTipText("Delete Binding from Tray"); //$NON-NLS-1$ |
1164 | fDeleteAction.setEnabled(false); |
1165 | fDeleteAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_DELETE)); |
1166 | fDeleteAction.setId(ActionFactory.DELETE.getId()); |
1167 | fDeleteAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_DELETE); |
1168 | |
1169 | refreshASTSettingsActions(); |
1170 | } |
1171 | |
1172 | |
1173 | private void refreshAST() throws CoreException { |
1174 | ASTNode node= getASTNodeNearSelection((IStructuredSelection) fViewer.getSelection()); |
1175 | int offset= 0; |
1176 | int length= 0; |
1177 | if (node != null) { |
1178 | offset= node.getStartPosition(); |
1179 | length= node.getLength(); |
1180 | } |
1181 | |
1182 | internalSetInput(fTypeRoot, offset, length); |
1183 | } |
1184 | |
1185 | protected void setASTLevel(int level, boolean doRefresh) { |
1186 | int oldLevel= fCurrentASTLevel; |
1187 | fCurrentASTLevel= level; |
1188 | |
1189 | fDialogSettings.put(SETTINGS_JLS, fCurrentASTLevel); |
1190 | |
1191 | if (doRefresh && fTypeRoot != null && oldLevel != fCurrentASTLevel) { |
1192 | try { |
1193 | refreshAST(); |
1194 | } catch (CoreException e) { |
1195 | showAndLogError("Could not set AST to new level.", e); //$NON-NLS-1$ |
1196 | // set back to old level |
1197 | fCurrentASTLevel= oldLevel; |
1198 | } |
1199 | } |
1200 | // update action state |
1201 | for (ASTView.ASTLevelToggle action : fASTVersionToggleActions) { |
1202 | action.setChecked(action.getLevel() == fCurrentASTLevel); |
1203 | } |
1204 | } |
1205 | |
1206 | protected void setASTInputType(int inputKind) { |
1207 | if (inputKind != fCurrentInputKind) { |
1208 | fCurrentInputKind= inputKind; |
1209 | fDialogSettings.put(SETTINGS_INPUT_KIND, inputKind); |
1210 | for (ASTView.ASTInputKindAction action : fASTInputKindActions) { |
1211 | action.setChecked(action.getInputKind() == inputKind); |
1212 | } |
1213 | refreshASTSettingsActions(); |
1214 | performRefresh(); |
1215 | } |
1216 | } |
1217 | |
1218 | private ASTNode getASTNodeNearSelection(IStructuredSelection selection) { |
1219 | Object elem= selection.getFirstElement(); |
1220 | if (elem instanceof ASTAttribute) { |
1221 | return ((ASTAttribute) elem).getParentASTNode(); |
1222 | } else if (elem instanceof ASTNode) { |
1223 | return (ASTNode) elem; |
1224 | } |
1225 | return null; |
1226 | } |
1227 | |
1228 | private void installModificationListener() { |
1229 | fCurrentDocument= fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput()); |
1230 | fCurrentDocument.addDocumentListener(fSuperListener); |
1231 | } |
1232 | |
1233 | private void uninstallModificationListener() { |
1234 | if (fCurrentDocument != null) { |
1235 | fCurrentDocument.removeDocumentListener(fSuperListener); |
1236 | fCurrentDocument= null; |
1237 | } |
1238 | } |
1239 | |
1240 | protected void handleDocumentDisposed() { |
1241 | uninstallModificationListener(); |
1242 | } |
1243 | |
1244 | protected void handleDocumentChanged() { |
1245 | setASTUptoDate(false); |
1246 | } |
1247 | |
1248 | protected void handleSelectionChanged(ISelection selection) { |
1249 | fExpandAction.setEnabled(!selection.isEmpty()); |
1250 | fCollapseAction.setEnabled(!selection.isEmpty()); |
1251 | fCopyAction.setEnabled(!selection.isEmpty()); |
1252 | |
1253 | boolean addEnabled= false; |
1254 | IStructuredSelection structuredSelection= (IStructuredSelection) selection; |
1255 | if (structuredSelection.size() == 1 && fViewer.getTree().isFocusControl()) { |
1256 | Object first= structuredSelection.getFirstElement(); |
1257 | Object unwrapped= ASTView.unwrapAttribute(first); |
1258 | addEnabled= unwrapped != null; |
1259 | } |
1260 | fAddToTrayAction.setEnabled(addEnabled); |
1261 | } |
1262 | |
1263 | protected void handleEditorPostSelectionChanged(IWorkbenchPart part, ISelection selection) { |
1264 | if (!(selection instanceof ITextSelection)) { |
1265 | return; |
1266 | } |
1267 | ITextSelection textSelection= (ITextSelection) selection; |
1268 | if (part == fEditor) { |
1269 | fViewer.getTree().setRedraw(false); |
1270 | try { |
1271 | fASTLabelProvider.setSelectedRange(textSelection.getOffset(), textSelection.getLength()); |
1272 | } finally { |
1273 | fViewer.getTree().setRedraw(true); |
1274 | } |
1275 | } |
1276 | if (!fDoLinkWithEditor) { |
1277 | return; |
1278 | } |
1279 | if (fRoot == null || part != fEditor) { |
1280 | if (part instanceof ITextEditor && (EditorUtility.getJavaInput((ITextEditor) part) != null)) { |
1281 | try { |
1282 | setInput((ITextEditor) part); |
1283 | } catch (CoreException e) { |
1284 | setContentDescription(e.getStatus().getMessage()); |
1285 | } |
1286 | } |
1287 | |
1288 | } else { // fRoot != null && part == fEditor |
1289 | doLinkWithEditor(selection); |
1290 | } |
1291 | } |
1292 | |
1293 | private void doLinkWithEditor(ISelection selection) { |
1294 | ITextSelection textSelection= (ITextSelection) selection; |
1295 | int offset= textSelection.getOffset(); |
1296 | int length= textSelection.getLength(); |
1297 | |
1298 | ASTNode covering= NodeFinder.perform(fRoot, offset, length); |
1299 | if (covering != null) { |
1300 | fViewer.reveal(covering); |
1301 | fViewer.setSelection(new StructuredSelection(covering)); |
1302 | } |
1303 | } |
1304 | |
1305 | protected void handleDoubleClick() { |
1306 | fDoubleClickAction.run(); |
1307 | } |
1308 | |
1309 | protected void performLinkWithEditor() { |
1310 | fDoLinkWithEditor= fLinkWithEditor.isChecked(); |
1311 | fDialogSettings.put(SETTINGS_LINK_WITH_EDITOR, fDoLinkWithEditor); |
1312 | |
1313 | |
1314 | if (fDoLinkWithEditor && fEditor != null) { |
1315 | ISelectionProvider selectionProvider= fEditor.getSelectionProvider(); |
1316 | if (selectionProvider != null) { // can be null when editor is closed |
1317 | doLinkWithEditor(selectionProvider.getSelection()); |
1318 | } |
1319 | } |
1320 | } |
1321 | |
1322 | protected void performCollapse() { |
1323 | IStructuredSelection selection= (IStructuredSelection) fViewer.getSelection(); |
1324 | if (selection.isEmpty()) { |
1325 | fViewer.collapseAll(); |
1326 | } else { |
1327 | fViewer.getTree().setRedraw(false); |
1328 | for (Object s : selection.toArray()) { |
1329 | fViewer.collapseToLevel(s, AbstractTreeViewer.ALL_LEVELS); |
1330 | } |
1331 | fViewer.getTree().setRedraw(true); |
1332 | } |
1333 | } |
1334 | |
1335 | protected void performExpand() { |
1336 | IStructuredSelection selection= (IStructuredSelection) fViewer.getSelection(); |
1337 | if (selection.isEmpty()) { |
1338 | fViewer.expandToLevel(3); |
1339 | } else { |
1340 | fViewer.getTree().setRedraw(false); |
1341 | for (Object s : selection.toArray()) { |
1342 | fViewer.expandToLevel(s, 3); |
1343 | } |
1344 | fViewer.getTree().setRedraw(true); |
1345 | } |
1346 | } |
1347 | |
1348 | protected void performSetFocus() { |
1349 | IEditorPart part= EditorUtility.getActiveEditor(); |
1350 | if (part instanceof ITextEditor) { |
1351 | try { |
1352 | setInput((ITextEditor) part); |
1353 | } catch (CoreException e) { |
1354 | showAndLogError("Could not set AST view input ", e); //$NON-NLS-1$ |
1355 | } |
1356 | } |
1357 | } |
1358 | |
1359 | protected void performRefresh() { |
1360 | if (fTypeRoot != null) { |
1361 | try { |
1362 | refreshAST(); |
1363 | } catch (CoreException e) { |
1364 | showAndLogError("Could not set AST view input ", e); //$NON-NLS-1$ |
1365 | } |
1366 | } |
1367 | } |
1368 | |
1369 | protected void performClear() { |
1370 | fTypeRoot= null; |
1371 | try { |
1372 | setInput(null); |
1373 | } catch (CoreException e) { |
1374 | showAndLogError("Could not reset AST view ", e); //$NON-NLS-1$ |
1375 | } |
1376 | clearView(); |
1377 | } |
1378 | |
1379 | private void showAndLogError(String message, CoreException e) { |
1380 | ASTViewPlugin.log(message, e); |
1381 | ErrorDialog.openError(getSite().getShell(), "AST View", message, e.getStatus()); //$NON-NLS-1$ |
1382 | } |
1383 | |
1384 | private void showAndLogError(String message, Throwable e) { |
1385 | IStatus status= new Status(IStatus.ERROR, ASTViewPlugin.getPluginId(), 0, message, e); |
1386 | ASTViewPlugin.log(status); |
1387 | ErrorDialog.openError(getSite().getShell(), "AST View", null, status); //$NON-NLS-1$ |
1388 | } |
1389 | |
1390 | protected void performCreateBindings() { |
1391 | fCreateBindings= fCreateBindingsAction.isChecked(); |
1392 | fDialogSettings.put(SETTINGS_NO_BINDINGS, !fCreateBindings); |
1393 | performRefresh(); |
1394 | } |
1395 | |
1396 | protected void performStatementsRecovery() { |
1397 | fStatementsRecovery= fStatementsRecoveryAction.isChecked(); |
1398 | fDialogSettings.put(SETTINGS_NO_STATEMENTS_RECOVERY, !fStatementsRecovery); |
1399 | performRefresh(); |
1400 | } |
1401 | |
1402 | protected void performBindingsRecovery() { |
1403 | fBindingsRecovery= fBindingsRecoveryAction.isChecked(); |
1404 | fDialogSettings.put(SETTINGS_NO_BINDINGS_RECOVERY, !fBindingsRecovery); |
1405 | performRefresh(); |
1406 | } |
1407 | |
1408 | protected void performIgnoreMethodBodies() { |
1409 | fIgnoreMethodBodies= fIgnoreMethodBodiesAction.isChecked(); |
1410 | fDialogSettings.put(SETTINGS_IGNORE_METHOD_BODIES, fIgnoreMethodBodies); |
1411 | performRefresh(); |
1412 | } |
1413 | |
1414 | protected void performFilterNonRelevant() { |
1415 | boolean showNonRelevant= !fFilterNonRelevantAction.isChecked(); |
1416 | fNonRelevantFilter.setShowNonRelevant(showNonRelevant); |
1417 | fDialogSettings.put(SETTINGS_SHOW_NON_RELEVANT, showNonRelevant); |
1418 | fViewer.refresh(); |
1419 | } |
1420 | |
1421 | protected void performFindDeclaringNode() { |
1422 | String msg= "Find Declaring Node from Key"; |
1423 | String key= askForKey(msg); |
1424 | if (key == null) |
1425 | return; |
1426 | ASTNode node= fRoot.findDeclaringNode(key); |
1427 | if (node != null) { |
1428 | fViewer.setSelection(new StructuredSelection(node), true); |
1429 | } else { |
1430 | MessageDialog.openError( |
1431 | getSite().getShell(), |
1432 | "Find Declaring Node from Key", |
1433 | "The declaring node for key '" + key + "' could not be found"); |
1434 | } |
1435 | } |
1436 | |
1437 | private String askForKey(String dialogTitle) { |
1438 | InputDialog dialog= new InputDialog(getSite().getShell(), dialogTitle, "Key: (optionally surrounded by <KEY: \"> and <\">)", "", null); |
1439 | if (dialog.open() != Window.OK) |
1440 | return null; |
1441 | |
1442 | String key= dialog.getValue(); |
1443 | if (key.startsWith("KEY: \"") && key.endsWith("\"")) |
1444 | key= key.substring(6, key.length() - 1); |
1445 | return key; |
1446 | } |
1447 | |
1448 | protected void performParseBindingFromKey() { |
1449 | String msg= "Parse Binding from Key"; |
1450 | String key= askForKey(msg); |
1451 | if (key == null) |
1452 | return; |
1453 | ASTParser parser= ASTParser.newParser(fCurrentASTLevel); |
1454 | parser.setResolveBindings(true); |
1455 | parser.setProject(fTypeRoot.getJavaProject()); |
1456 | class MyASTRequestor extends ASTRequestor { |
1457 | String fBindingKey; |
1458 | IBinding fBinding; |
1459 | @Override |
1460 | public void acceptBinding(String bindingKey, IBinding binding) { |
1461 | fBindingKey= bindingKey; |
1462 | fBinding= binding; |
1463 | } |
1464 | } |
1465 | MyASTRequestor requestor= new MyASTRequestor(); |
1466 | ASTAttribute item; |
1467 | Object viewerInput= fViewer.getInput(); |
1468 | try { |
1469 | parser.createASTs(new ICompilationUnit[0], new String[] { key }, requestor, null); |
1470 | if (requestor.fBindingKey != null) { |
1471 | String name= requestor.fBindingKey + ": " + Binding.getBindingLabel(requestor.fBinding); |
1472 | item= new Binding(viewerInput, name, requestor.fBinding, true); |
1473 | } else { |
1474 | item= new Error(viewerInput, "Key not resolved: " + key, null); |
1475 | } |
1476 | } catch (RuntimeException e) { |
1477 | item= new Error(viewerInput, "Error resolving key: " + key, e); |
1478 | } |
1479 | fViewer.add(viewerInput, item); |
1480 | fViewer.setSelection(new StructuredSelection(item), true); |
1481 | } |
1482 | |
1483 | protected void performParseBindingFromElement() { |
1484 | InputDialog dialog= new InputDialog(getSite().getShell(), "Parse Binding from Java Element", "IJavaElement#getHandleIdentifier():", "", null); |
1485 | if (dialog.open() != Window.OK) |
1486 | return; |
1487 | |
1488 | String handleIdentifier= dialog.getValue(); |
1489 | IJavaElement handle= JavaCore.create(handleIdentifier); |
1490 | |
1491 | Object viewerInput= fViewer.getInput(); |
1492 | ASTAttribute item; |
1493 | if (handle == null) { |
1494 | item= new Error(viewerInput, "handleIdentifier not resolved: " + handleIdentifier, null); |
1495 | } else if (! handle.exists()) { |
1496 | item= new Error(viewerInput, "element does not exist: " + handleIdentifier, null); |
1497 | } else if (handle.getJavaProject() == null) { |
1498 | item= new Error(viewerInput, "getJavaProject() is null: " + handleIdentifier, null); |
1499 | } else { |
1500 | IJavaProject project= handle.getJavaProject(); |
1501 | ASTParser parser= ASTParser.newParser(fCurrentASTLevel); |
1502 | parser.setProject(project); |
1503 | IBinding[] bindings= parser.createBindings(new IJavaElement[] { handle }, null); |
1504 | String name= handleIdentifier + ": " + Binding.getBindingLabel(bindings[0]); |
1505 | item= new Binding(viewerInput, name, bindings[0], true); |
1506 | } |
1507 | fViewer.add(viewerInput, item); |
1508 | fViewer.setSelection(new StructuredSelection(item), true); |
1509 | } |
1510 | |
1511 | protected void performDoubleClick() { |
1512 | if (fEditor == null) { |
1513 | return; |
1514 | } |
1515 | |
1516 | ISelection selection = fViewer.getSelection(); |
1517 | Object obj = ((IStructuredSelection) selection).getFirstElement(); |
1518 | |
1519 | boolean isTripleClick= (obj == fPreviousDouble); |
1520 | fPreviousDouble= isTripleClick ? null : obj; |
1521 | |
1522 | if (obj instanceof ExceptionAttribute) { |
1523 | Throwable exception= ((ExceptionAttribute) obj).getException(); |
1524 | if (exception != null) { |
1525 | String label= ((ExceptionAttribute) obj).getLabel(); |
1526 | showAndLogError("An error occurred while calculating an AST View Label:\n" + label, exception); //$NON-NLS-1$ |
1527 | return; |
1528 | } |
1529 | } |
1530 | |
1531 | ASTNode node= null, nodeEnd= null; |
1532 | if (obj instanceof ASTNode) { |
1533 | node= (ASTNode) obj; |
1534 | |
1535 | } else if (obj instanceof NodeProperty) { |
1536 | Object val= ((NodeProperty) obj).getNode(); |
1537 | if (val instanceof ASTNode) { |
1538 | node= (ASTNode) val; |
1539 | } else if (val instanceof List) { |
1540 | List<?> list= (List<?>) val; |
1541 | if (list.size() > 0) { |
1542 | node= (ASTNode) list.get(0); |
1543 | nodeEnd= (ASTNode) list.get(list.size() - 1); |
1544 | } else { |
1545 | fViewer.getTree().getDisplay().beep(); |
1546 | } |
1547 | } |
1548 | |
1549 | } else if (obj instanceof Binding) { |
1550 | IBinding binding= ((Binding) obj).getBinding(); |
1551 | ASTNode declaring= fRoot.findDeclaringNode(binding); |
1552 | if (declaring != null) { |
1553 | fViewer.reveal(declaring); |
1554 | fViewer.setSelection(new StructuredSelection(declaring)); |
1555 | } else { |
1556 | fViewer.getTree().getDisplay().beep(); |
1557 | } |
1558 | return; |
1559 | |
1560 | } else if (obj instanceof ProblemNode) { |
1561 | ProblemNode problemNode= (ProblemNode) obj; |
1562 | EditorUtility.selectInEditor(fEditor, problemNode.getOffset(), problemNode.getLength()); |
1563 | return; |
1564 | |
1565 | } else if (obj instanceof JavaElement) { |
1566 | IJavaElement javaElement= ((JavaElement) obj).getJavaElement(); |
1567 | if (javaElement instanceof IPackageFragment) { |
1568 | try { |
1569 | IViewPart packageExplorer= getSite().getPage().showView(JavaUI.ID_PACKAGES); |
1570 | if (packageExplorer instanceof IShowInTarget) { |
1571 | IShowInTarget showInTarget= (IShowInTarget) packageExplorer; |
1572 | showInTarget.show(getShowInContext()); |
1573 | } |
1574 | } catch (PartInitException e) { |
1575 | showAndLogError("Could not open Package Explorer.", e); //$NON-NLS-1$ |
1576 | } |
1577 | } else { |
1578 | try { |
1579 | IEditorPart editorPart= JavaUI.openInEditor(javaElement); |
1580 | if (editorPart != null) |
1581 | JavaUI.revealInEditor(editorPart, javaElement); |
1582 | } catch (PartInitException e) { |
1583 | showAndLogError("Could not open editor.", e); //$NON-NLS-1$ |
1584 | } catch (JavaModelException e) { |
1585 | showAndLogError("Could not open editor.", e); //$NON-NLS-1$ |
1586 | } |
1587 | } |
1588 | return; |
1589 | } |
1590 | |
1591 | if (node != null) { |
1592 | int offset= isTripleClick ? fRoot.getExtendedStartPosition(node) : node.getStartPosition(); |
1593 | int length; |
1594 | if (nodeEnd == null) { |
1595 | length= isTripleClick ? fRoot.getExtendedLength(node) : node.getLength(); |
1596 | } else { |
1597 | length= isTripleClick |
1598 | ? fRoot.getExtendedStartPosition(nodeEnd) + fRoot.getExtendedLength(nodeEnd) - fRoot.getExtendedStartPosition(node) |
1599 | : nodeEnd.getStartPosition() + nodeEnd.getLength() - node.getStartPosition(); |
1600 | } |
1601 | EditorUtility.selectInEditor(fEditor, offset, length); |
1602 | } |
1603 | } |
1604 | |
1605 | protected void performAddToTray() { |
1606 | IStructuredSelection selection= (IStructuredSelection) fViewer.getSelection(); |
1607 | Object firstElement= selection.getFirstElement(); |
1608 | if (! fTrayRoots.contains(firstElement)) { |
1609 | fTrayRoots.add(firstElement); |
1610 | fTray.setInput(fTrayRoots); |
1611 | } |
1612 | if (fSash.getMaximizedControl() != null) { |
1613 | int trayHeight= fTray.getTree().getItemHeight() * (2 + TrayContentProvider.DEFAULT_CHILDREN_COUNT); |
1614 | int sashHeight= fSash.getClientArea().height; |
1615 | fSash.setWeights(new int[] { sashHeight - trayHeight, trayHeight }); |
1616 | fSash.setMaximizedControl(null); |
1617 | } |
1618 | setTraySelection(selection); |
1619 | } |
1620 | |
1621 | private void setTraySelection(IStructuredSelection selection) { |
1622 | fTray.setSelection(selection, true); |
1623 | TreeItem[] itemSelection= fTray.getTree().getSelection(); |
1624 | if (itemSelection.length > 0) |
1625 | fTray.getTree().setTopItem(itemSelection[0]); |
1626 | } |
1627 | |
1628 | protected void performTrayDoubleClick() { |
1629 | IStructuredSelection selection= (IStructuredSelection) fTray.getSelection(); |
1630 | if (selection.size() != 1) |
1631 | return; |
1632 | Object obj = selection.getFirstElement(); |
1633 | if (obj instanceof ExceptionAttribute) { |
1634 | Throwable exception= ((ExceptionAttribute) obj).getException(); |
1635 | if (exception != null) { |
1636 | String label= ((ExceptionAttribute) obj).getLabel(); |
1637 | showAndLogError("An error occurred while calculating an AST View Label:\n" + label, exception); //$NON-NLS-1$ |
1638 | return; |
1639 | } |
1640 | } |
1641 | if (obj instanceof Binding) { |
1642 | Binding binding= (Binding) obj; |
1643 | fViewer.setSelection(new StructuredSelection(binding), true); |
1644 | } |
1645 | } |
1646 | |
1647 | protected void performDelete() { |
1648 | boolean removed= false; |
1649 | IStructuredSelection selection= (IStructuredSelection) fTray.getSelection(); |
1650 | for (Iterator<?> iter= selection.iterator(); iter.hasNext();) { |
1651 | Object obj= iter.next(); |
1652 | if (obj instanceof DynamicAttributeProperty) |
1653 | obj= ((DynamicAttributeProperty) obj).getParent(); |
1654 | if (obj instanceof DynamicBindingProperty) |
1655 | obj= ((DynamicBindingProperty) obj).getParent(); |
1656 | |
1657 | removed|= fTrayRoots.remove(obj); |
1658 | } |
1659 | if (removed) |
1660 | fTray.setInput(fTrayRoots); |
1661 | } |
1662 | |
1663 | @Override |
1664 | public void setFocus() { |
1665 | fViewer.getControl().setFocus(); |
1666 | } |
1667 | |
1668 | @Override |
1669 | public ShowInContext getShowInContext() { |
1670 | return new ShowInContext(null, getSite().getSelectionProvider().getSelection()); |
1671 | } |
1672 | |
1673 | @Override |
1674 | public String[] getShowInTargetIds() { |
1675 | return new String[] { "org.eclipse.jdt.jeview.views.JavaElementView", JavaUI.ID_PACKAGES }; |
1676 | } |
1677 | |
1678 | /** |
1679 | * @param attribute an attribute |
1680 | * @return the object inside the attribute, or <code>null</code> iff none |
1681 | */ |
1682 | static Object unwrapAttribute(Object attribute) { |
1683 | if (attribute instanceof Binding) { |
1684 | return ((Binding) attribute).getBinding(); |
1685 | } else if (attribute instanceof JavaElement) { |
1686 | return ((JavaElement) attribute).getJavaElement(); |
1687 | } else if (attribute instanceof ASTNode) { |
1688 | return attribute; |
1689 | } else { |
1690 | return null; |
1691 | } |
1692 | } |
1693 | } |
1694 |
Members