| /******************************************************************************* |
| * Copyright (c) 2004, 2017 Tasktop Technologies and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Tasktop Technologies - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.dltk.internal.mylyn.search; |
| |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IResourceDelta; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.dltk.core.ElementChangedEvent; |
| import org.eclipse.dltk.core.IElementChangedListener; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.IModelElementDelta; |
| import org.eclipse.dltk.internal.ui.search.DLTKSearchResult; |
| import org.eclipse.search.ui.IQueryListener; |
| import org.eclipse.search.ui.ISearchQuery; |
| import org.eclipse.search.ui.NewSearchUI; |
| import org.eclipse.search.ui.text.Match; |
| |
| /** |
| * COPIED FROM: org.eclipse.jdt.internal.ui.search.SearchResultUpdater |
| * |
| * @author Shawn Minto |
| */ |
| public class DLTKActiveSearchResultUpdater implements IElementChangedListener, IQueryListener { |
| |
| private final DLTKSearchResult fResult; |
| |
| private static final int REMOVED_FLAGS = IModelElementDelta.F_MOVED_TO | IModelElementDelta.F_REMOVED_FROM_BUILDPATH |
| | IModelElementDelta.F_CLOSED | IModelElementDelta.F_CONTENT; |
| |
| public DLTKActiveSearchResultUpdater(DLTKSearchResult result) { |
| fResult = result; |
| NewSearchUI.addQueryListener(this); |
| DLTKCore.addElementChangedListener(this); |
| // TODO make this work with resources |
| } |
| |
| @Override |
| public void elementChanged(ElementChangedEvent event) { |
| // long t0= System.currentTimeMillis(); |
| IModelElementDelta delta = event.getDelta(); |
| Set<IAdaptable> removedElements = new HashSet<>(); |
| Set<IAdaptable> potentiallyRemovedElements = new HashSet<>(); |
| collectRemoved(potentiallyRemovedElements, removedElements, delta); |
| if (removedElements.size() > 0) { |
| handleRemoved(removedElements); |
| } |
| if (potentiallyRemovedElements.size() > 0) { |
| handleRemoved(potentiallyRemovedElements); |
| } |
| } |
| |
| private void handleRemoved(Set<IAdaptable> removedElements) { |
| Object[] elements = fResult.getElements(); |
| for (Object element : elements) { |
| if (isContainedInRemoved(removedElements, element)) { |
| if (element instanceof IModelElement) { |
| IModelElement je = (IModelElement) element; |
| if (!je.exists()) { |
| Match[] matches = fResult.getMatches(element); |
| for (Match matche : matches) { |
| fResult.removeMatch(matche); |
| } |
| // XXX remove edge and element |
| } |
| } else if (element instanceof IResource) { |
| IResource resource = (IResource) element; |
| if (!resource.exists()) { |
| Match[] matches = fResult.getMatches(element); |
| for (Match matche : matches) { |
| fResult.removeMatch(matche); |
| } |
| // XXX remove edge and element |
| } |
| |
| } |
| } |
| } |
| } |
| |
| private boolean isContainedInRemoved(Set<IAdaptable> removedElements, Object object) { |
| for (IAdaptable iAdaptable : removedElements) { |
| if (isParentOf(iAdaptable, object)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private boolean isParentOf(Object ancestor, Object descendant) { |
| while (descendant != null && !ancestor.equals(descendant)) { |
| descendant = getParent(descendant); |
| } |
| return descendant != null; |
| } |
| |
| private Object getParent(Object object) { |
| if (object instanceof IModelElement) { |
| return ((IModelElement) object).getParent(); |
| } else if (object instanceof IResource) { |
| return ((IResource) object).getParent(); |
| } |
| return null; |
| } |
| |
| private void collectRemoved(Set<IAdaptable> potentiallyRemovedSet, Set<IAdaptable> removedElements, |
| IModelElementDelta delta) { |
| if (delta.getKind() == IModelElementDelta.REMOVED) { |
| removedElements.add(delta.getElement()); |
| } else if (delta.getKind() == IModelElementDelta.CHANGED) { |
| int flags = delta.getFlags(); |
| if ((flags & REMOVED_FLAGS) != 0) { |
| potentiallyRemovedSet.add(delta.getElement()); |
| } else { |
| IModelElementDelta[] childDeltas = delta.getAffectedChildren(); |
| for (IModelElementDelta childDelta : childDeltas) { |
| collectRemoved(potentiallyRemovedSet, removedElements, childDelta); |
| } |
| } |
| } |
| IResourceDelta[] resourceDeltas = delta.getResourceDeltas(); |
| if (resourceDeltas != null) { |
| for (IResourceDelta resourceDelta : resourceDeltas) { |
| collectRemovals(removedElements, resourceDelta); |
| } |
| } |
| } |
| |
| @Override |
| public void queryAdded(ISearchQuery query) { |
| // don't care |
| } |
| |
| @Override |
| public void queryRemoved(ISearchQuery query) { |
| if (fResult.equals(query.getSearchResult())) { |
| DLTKCore.removeElementChangedListener(this); |
| NewSearchUI.removeQueryListener(this); |
| } |
| } |
| |
| private void collectRemovals(Set<IAdaptable> removals, IResourceDelta delta) { |
| if (delta.getKind() == IResourceDelta.REMOVED) { |
| removals.add(delta.getResource()); |
| } else { |
| IResourceDelta[] children = delta.getAffectedChildren(); |
| for (IResourceDelta element : children) { |
| collectRemovals(removals, element); |
| } |
| } |
| } |
| |
| @Override |
| public void queryStarting(ISearchQuery query) { |
| // not interested |
| } |
| |
| @Override |
| public void queryFinished(ISearchQuery query) { |
| // not interested |
| } |
| |
| } |