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