public void ensureRefreshedTypeHierarchy(final IRubyElement element, IRunnableContext context) throws InvocationTargetException, InterruptedException { if (element == null || !element.exists()) { freeHierarchy(); return; } boolean hierachyCreationNeeded = (fHierarchy == null || !element.equals(fInputElement)); if (hierachyCreationNeeded || fHierarchyRefreshNeeded) { IRunnableWithProgress op = new IRunnableWithProgress() { public void run(IProgressMonitor pm) throws InvocationTargetException, InterruptedException { try { doHierarchyRefresh(element, pm); } catch (RubyModelException e) { throw new InvocationTargetException(e); } catch (OperationCanceledException e) { throw new InterruptedException(); } } }; fHierarchyRefreshNeeded = true; context.run(true, true, op); fHierarchyRefreshNeeded = false; } }
/* package */ void handleAffectedChildren(IRubyElementDelta delta, IRubyElement element) throws RubyModelException { IRubyElementDelta[] affectedChildren = delta.getAffectedChildren(); if (affectedChildren.length > 1) { // a package fragment might become non empty refresh from the parent if (element instanceof ISourceFolder) { IRubyElement parent = (IRubyElement) internalGetParent(element); if (parent instanceof ISourceFolderRoot) { parent = (IRubyElement) internalGetParent(parent); } // 1GE8SI6: ITPJUI:WIN98 - Rename is not shown in Packages View // avoid posting a refresh to an unvisible parent if (element.equals(fInput)) { postRefresh(element, ORIGINAL, element); } else { postRefresh(parent, PARENT, element); } return; } // more than one child changed, refresh from here downwards if (element instanceof ISourceFolderRoot) { Object toRefresh = skipProjectSourceFolderRoot((ISourceFolderRoot) element); postRefresh(toRefresh, ORIGINAL, toRefresh); } else { postRefresh(element, ORIGINAL, element); } return; } processAffectedChildren(affectedChildren); }
/** * Returns if the text selection is a valid method or not * * @param selection the text selection * @param part the associated workbench part * @return true if the selection is a valid method, false otherwise */ private boolean isMethod(ITextSelection selection, IWorkbenchPart part) { ITextEditor editor = getTextEditor(part); if (editor != null) { IRubyElement element = getRubyElement(editor.getEditorInput()); if (element != null) { try { if (element instanceof IRubyScript) { element = ((IRubyScript) element).getElementAt(selection.getOffset()); } return element != null && element.getElementType() == IRubyElement.METHOD; } catch (RubyModelException e) { return false; } } } return false; }
/* * Assume that the hierarchy is intact (no refresh needed) */ private void processDelta(IRubyElementDelta delta, ArrayList changedTypes) { IRubyElement element = delta.getElement(); switch (element.getElementType()) { case IRubyElement.TYPE: processTypeDelta((IType) element, changedTypes); processChildrenDelta(delta, changedTypes); // (inner types) break; case IRubyElement.RUBY_MODEL: case IRubyElement.RUBY_PROJECT: case IRubyElement.SOURCE_FOLDER_ROOT: case IRubyElement.SOURCE_FOLDER: processChildrenDelta(delta, changedTypes); break; case IRubyElement.SCRIPT: IRubyScript cu = (IRubyScript) element; if (!RubyModelUtil.isPrimary(cu)) { return; } if (delta.getKind() == IRubyElementDelta.CHANGED && isPossibleStructuralChange(delta.getFlags())) { try { if (cu.exists()) { IType[] types = cu.getAllTypes(); for (int i = 0; i < types.length; i++) { processTypeDelta(types[i], changedTypes); } } } catch (RubyModelException e) { RubyPlugin.log(e); } } else { processChildrenDelta(delta, changedTypes); } break; } }
public synchronized void doHierarchyRefresh(IRubyElement element, IProgressMonitor pm) throws RubyModelException { boolean hierachyCreationNeeded = (fHierarchy == null || !element.equals(fInputElement)); // to ensure the order of the two listeners always remove / add listeners on operations // on type hierarchies if (fHierarchy != null) { fHierarchy.removeTypeHierarchyChangedListener(this); RubyCore.removeElementChangedListener(this); } if (hierachyCreationNeeded) { fHierarchy = createTypeHierarchy(element, pm); if (pm != null && pm.isCanceled()) { throw new OperationCanceledException(); } fInputElement = element; } else { fHierarchy.refresh(pm); } if (fHierarchy != null) { fHierarchy.addTypeHierarchyChangedListener(this); RubyCore.addElementChangedListener(this); fHierarchyRefreshNeeded = false; } }
private ITypeHierarchy createTypeHierarchy(IRubyElement element, IProgressMonitor pm) throws RubyModelException { if (element.getElementType() == IRubyElement.TYPE) { IType type = (IType) element; type = getLogicalType(type, type.getFullyQualifiedName()); if (fIsSuperTypesOnly) { return type.newSupertypeHierarchy(pm); } else { return type.newTypeHierarchy(pm); } } else { IRegion region = RubyCore.newRegion(); if (element.getElementType() == IRubyElement.RUBY_PROJECT) { // for projects only add the contained source folders ISourceFolderRoot[] roots = ((IRubyProject) element).getSourceFolderRoots(); for (int i = 0; i < roots.length; i++) { if (!roots[i].isExternal()) { region.add(roots[i]); } } } else if (element.getElementType() == IRubyElement.SOURCE_FOLDER) { ISourceFolderRoot[] roots = element.getRubyProject().getSourceFolderRoots(); String name = element.getElementName(); for (int i = 0; i < roots.length; i++) { ISourceFolder pack = roots[i].getSourceFolder(name); if (pack.exists()) { region.add(pack); } } } else { region.add(element); } IRubyProject jproject = element.getRubyProject(); return jproject.newTypeHierarchy(region, pm); } }
/** * Processes a delta recursively. When more than two children are affected the tree is fully * refreshed starting at this node. The delta is processed in the current thread but the viewer * updates are posted to the UI thread. */ private void processDelta(IRubyElementDelta delta) throws RubyModelException { int kind = delta.getKind(); int flags = delta.getFlags(); IRubyElement element = delta.getElement(); int elementType = element.getElementType(); if (elementType != IRubyElement.RUBY_MODEL && elementType != IRubyElement.RUBY_PROJECT) { IRubyProject proj = element.getRubyProject(); if (proj == null || !proj.getProject() .isOpen()) // TODO: Not needed if parent already did the 'open' check! return; } if (!fIsFlatLayout && elementType == IRubyElement.SOURCE_FOLDER) { fSourceFolderProvider.processDelta(delta); if (processResourceDeltas(delta.getResourceDeltas(), element)) return; handleAffectedChildren(delta, element); return; } if (elementType == IRubyElement.SCRIPT) { IRubyScript cu = (IRubyScript) element; if (!RubyModelUtil.isPrimary(cu)) { return; } if (!getProvideMembers() && cu.isWorkingCopy() && kind == IRubyElementDelta.CHANGED) { return; } if ((kind == IRubyElementDelta.CHANGED) && !isStructuralCUChange(flags)) { return; // test moved ahead } if (!isOnClassPath( cu)) { // TODO: isOnClassPath expensive! Should be put after all cheap tests return; } } if (elementType == IRubyElement.RUBY_PROJECT) { // handle open and closing of a project if ((flags & (IRubyElementDelta.F_CLOSED | IRubyElementDelta.F_OPENED)) != 0) { postRefresh(element, ORIGINAL, element); return; } // if the raw class path has changed we refresh the entire project if ((flags & IRubyElementDelta.F_CLASSPATH_CHANGED) != 0) { postRefresh(element, ORIGINAL, element); return; } } if (kind == IRubyElementDelta.REMOVED) { Object parent = internalGetParent(element); if (element instanceof ISourceFolder) { // refresh package fragment root to allow filtering empty (parent) packages: bug 72923 if (fViewer.testFindItem(parent) != null) postRefresh(parent, PARENT, element); return; } postRemove(element); if (parent instanceof ISourceFolder) postUpdateIcon((ISourceFolder) parent); // we are filtering out empty subpackages, so we // a package becomes empty we remove it from the viewer. if (isSourceFolderEmpty(element.getParent())) { if (fViewer.testFindItem(parent) != null) postRefresh(internalGetParent(parent), GRANT_PARENT, element); } return; } if (kind == IRubyElementDelta.ADDED) { Object parent = internalGetParent(element); // we are filtering out empty subpackages, so we // have to handle additions to them specially. if (parent instanceof ISourceFolder) { Object grandparent = internalGetParent(parent); if (((ISourceFolder) parent).isDefaultPackage()) { parent = grandparent; grandparent = internalGetParent(parent); } // 1GE8SI6: ITPJUI:WIN98 - Rename is not shown in Packages View // avoid posting a refresh to an unvisible parent if (parent.equals(fInput)) { postRefresh(parent, PARENT, element); } else { // refresh from grandparent if parent isn't visible yet if (fViewer.testFindItem(parent) == null) postRefresh(grandparent, GRANT_PARENT, element); else { postRefresh(parent, PARENT, element); } } return; } else { if ((flags & IRubyElementDelta.F_MOVED_FROM) != 0) { postRemove(delta.getMovedFromElement()); } postAdd(parent, element); } } if (elementType == IRubyElement.SCRIPT) { if (kind == IRubyElementDelta.CHANGED) { // isStructuralCUChange already performed above postRefresh(element, ORIGINAL, element); updateSelection(delta); } return; } if (elementType == IRubyElement.SOURCE_FOLDER_ROOT) { // the contents of an external JAR has changed if ((flags & IRubyElementDelta.F_ARCHIVE_CONTENT_CHANGED) != 0) { postRefresh(element, ORIGINAL, element); return; } // the source attachment of a JAR has changed if ((flags & (IRubyElementDelta.F_SOURCEATTACHED | IRubyElementDelta.F_SOURCEDETACHED)) != 0) postUpdateIcon(element); if (isClassPathChange(delta)) { // throw the towel and do a full refresh of the affected java project. postRefresh(element.getRubyProject(), PROJECT, element); return; } } if (processResourceDeltas(delta.getResourceDeltas(), element)) return; handleAffectedChildren(delta, element); }