/** Observe the changes of the JSDT "Include Path" to synchronize tern script paths. */ @Override public void elementChanged(ElementChangedEvent event) { IJavaScriptElementDelta delta = event.getDelta(); if (delta.getKind() == IJavaScriptElementDelta.CHANGED) { // retrieve the JSDT Project if delta is about "Includes Path" // changes. IJavaScriptProject jsProject = getJavaScriptProjectIfClassPathChanged(delta); if (jsProject != null) { Job configJob = new ConfigureJob(jsProject); configJob.setRule(jsProject.getProject()); configJob.schedule(); } } }
/** * Retrieve the JSDT Project from the delta, if delta is about "Includes Path" changes. * * @param delta the JSDT delta. * @return */ private IJavaScriptProject getJavaScriptProjectIfClassPathChanged(IJavaScriptElementDelta delta) { if (delta.getKind() != IJavaScriptElementDelta.CHANGED) { return null; } IJavaScriptElement element = delta.getElement(); switch (element.getElementType()) { case IJavaScriptElement.JAVASCRIPT_MODEL: IJavaScriptElementDelta[] children = delta.getAffectedChildren(); for (int i = 0, length = children.length; i < length; i++) { IJavaScriptElementDelta child = children[i]; IJavaScriptProject project = getJavaScriptProjectIfClassPathChanged(child); if (project != null) { return project; } } return null; case IJavaScriptElement.JAVASCRIPT_PROJECT: int kind = delta.getKind(); switch (kind) { case IJavaScriptElementDelta.ADDED: case IJavaScriptElementDelta.REMOVED: return null; case IJavaScriptElementDelta.CHANGED: int flags = delta.getFlags(); if ((flags & IJavaScriptElementDelta.F_CLOSED) != 0 || (flags & IJavaScriptElementDelta.F_OPENED) != 0) { return null; } else { children = delta.getAffectedChildren(); for (int i = 0, length = children.length; i < length; i++) { IJavaScriptElementDelta child = children[i]; IJavaScriptProject project = getJavaScriptProjectIfClassPathChanged(child); if (project != null) { return project; } } } return null; } return null; case IJavaScriptElement.PACKAGE_FRAGMENT_ROOT: kind = delta.getKind(); switch (kind) { case IJavaScriptElementDelta.ADDED: case IJavaScriptElementDelta.REMOVED: return null; case IJavaScriptElementDelta.CHANGED: int flags = delta.getFlags(); if ((flags & IJavaScriptElementDelta.F_ADDED_TO_CLASSPATH) > 0 || (flags & IJavaScriptElementDelta.F_REMOVED_FROM_CLASSPATH) > 0) { // "Include Path" has changed, returns the JSDT project. return element.getJavaScriptProject(); } return null; } break; } return null; }
/** * 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. */ protected void processDelta(IJavaScriptElementDelta delta) throws JavaScriptModelException { int kind = delta.getKind(); int flags = delta.getFlags(); final IJavaScriptElement element = delta.getElement(); final boolean isElementValidForView = fBrowsingPart.isValidElement(element); if (!getProvideWorkingCopy() && element instanceof IJavaScriptUnit && ((IJavaScriptUnit) element).isWorkingCopy()) return; if (element != null && element.getElementType() == IJavaScriptElement.JAVASCRIPT_UNIT && !isOnClassPath((IJavaScriptUnit) element)) return; // handle open and closing of a solution or project if (((flags & IJavaScriptElementDelta.F_CLOSED) != 0) || ((flags & IJavaScriptElementDelta.F_OPENED) != 0)) { postRefresh(null); return; } if (kind == IJavaScriptElementDelta.REMOVED) { Object parent = internalGetParent(element); if (isElementValidForView) { if (element instanceof IClassFile) { postRemove(((IClassFile) element).getType()); } else if (element instanceof IJavaScriptUnit && !((IJavaScriptUnit) element).isWorkingCopy()) { postRefresh(null); } else if (element instanceof IJavaScriptUnit && ((IJavaScriptUnit) element).isWorkingCopy()) { if (getProvideWorkingCopy()) postRefresh(null); } else if (parent instanceof IJavaScriptUnit && getProvideWorkingCopy() && !((IJavaScriptUnit) parent).isWorkingCopy()) { if (element instanceof IJavaScriptUnit && ((IJavaScriptUnit) element).isWorkingCopy()) { // working copy removed from system - refresh postRefresh(null); } } else if (element instanceof IJavaScriptUnit && ((IJavaScriptUnit) element).isWorkingCopy() && parent != null && parent.equals(fInput)) // closed editor - removing working copy postRefresh(null); else postRemove(element); } if (fBrowsingPart.isAncestorOf(element, fInput)) { if (element instanceof IJavaScriptUnit && ((IJavaScriptUnit) element).isWorkingCopy()) { postAdjustInputAndSetSelection(((IJavaScriptElement) fInput).getPrimaryElement()); } else postAdjustInputAndSetSelection(null); } if (fInput != null && fInput.equals(element)) postRefresh(null); if (parent instanceof IPackageFragment && fBrowsingPart.isValidElement(parent)) { // refresh if package gets empty (might be filtered) if (isPackageFragmentEmpty((IPackageFragment) parent) && fViewer.testFindItem(parent) != null) postRefresh(null); } return; } if (kind == IJavaScriptElementDelta.ADDED && delta.getMovedFromElement() != null && element instanceof IJavaScriptUnit) return; if (kind == IJavaScriptElementDelta.ADDED) { if (isElementValidForView) { Object parent = internalGetParent(element); if (element instanceof IClassFile) { postAdd(parent, ((IClassFile) element).getType()); } else if (element instanceof IJavaScriptUnit && !((IJavaScriptUnit) element).isWorkingCopy()) { postAdd(parent, ((IJavaScriptUnit) element).getTypes()); } else if (parent instanceof IJavaScriptUnit && getProvideWorkingCopy() && !((IJavaScriptUnit) parent).isWorkingCopy()) { // do nothing } else if (element instanceof IJavaScriptUnit && ((IJavaScriptUnit) element).isWorkingCopy()) { // new working copy comes to live postRefresh(null); } else postAdd(parent, element); } else if (fInput == null) { IJavaScriptElement newInput = fBrowsingPart.findInputForJavaElement(element); if (newInput != null) postAdjustInputAndSetSelection(element); } else if (element instanceof IType && fBrowsingPart.isValidInput(element)) { IJavaScriptElement cu1 = element.getAncestor(IJavaScriptElement.JAVASCRIPT_UNIT); IJavaScriptElement cu2 = ((IJavaScriptElement) fInput).getAncestor(IJavaScriptElement.JAVASCRIPT_UNIT); if (cu1 != null && cu2 != null && cu1.equals(cu2)) postAdjustInputAndSetSelection(element); } return; } if (kind == IJavaScriptElementDelta.CHANGED) { if (fInput != null && fInput.equals(element) && (flags & IJavaScriptElementDelta.F_CHILDREN) != 0 && (flags & IJavaScriptElementDelta.F_FINE_GRAINED) != 0) { postRefresh(null, true); return; } if (isElementValidForView && (flags & IJavaScriptElementDelta.F_MODIFIERS) != 0) { postUpdateIcon(element); } } if (isClassPathChange(delta)) // throw the towel and do a full refresh postRefresh(null); if ((flags & IJavaScriptElementDelta.F_ARCHIVE_CONTENT_CHANGED) != 0 && fInput instanceof IJavaScriptElement) { IPackageFragmentRoot pkgRoot = (IPackageFragmentRoot) element; IJavaScriptElement inputsParent = ((IJavaScriptElement) fInput).getAncestor(IJavaScriptElement.PACKAGE_FRAGMENT_ROOT); if (pkgRoot.equals(inputsParent)) postRefresh(null); } // the source attachment of a JAR has changed if (element instanceof IPackageFragmentRoot && (((flags & IJavaScriptElementDelta.F_SOURCEATTACHED) != 0 || ((flags & IJavaScriptElementDelta.F_SOURCEDETACHED)) != 0))) postUpdateIcon(element); IJavaScriptElementDelta[] affectedChildren = delta.getAffectedChildren(); if (affectedChildren.length > 1) { // a package fragment might become non empty refresh from the parent if (element instanceof IPackageFragment) { IJavaScriptElement parent = (IJavaScriptElement) internalGetParent(element); // avoid posting a refresh to an invisible parent if (element.equals(fInput)) { postRefresh(element); } else { postRefresh(parent); } } // more than one child changed, refresh from here downwards if (element instanceof IPackageFragmentRoot && isElementValidForView) { postRefresh(skipProjectPackageFragmentRoot((IPackageFragmentRoot) element)); return; } } for (int i = 0; i < affectedChildren.length; i++) { processDelta(affectedChildren[i]); } }