Copyright (c) 2000, 2019 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: IBM Corporation - initial API and implementation Microsoft Corporation - copied to jdt.core.manipulation
/******************************************************************************* * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation * Microsoft Corporation - copied to jdt.core.manipulation *******************************************************************************/
package org.eclipse.jdt.internal.corext.refactoring; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.resources.IResource; import org.eclipse.ltk.core.refactoring.IRefactoringStatusEntryComparator; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.WorkingCopyOwner; import org.eclipse.jdt.core.search.IJavaSearchScope; import org.eclipse.jdt.core.search.SearchEngine; import org.eclipse.jdt.core.search.SearchMatch; import org.eclipse.jdt.core.search.SearchPattern; import org.eclipse.jdt.core.search.SearchRequestor; import org.eclipse.jdt.internal.corext.util.SearchUtils;
Convenience wrapper for SearchEngine - performs searching and sorts the results by IResource. TODO: throw CoreExceptions from search(..) methods instead of wrapped JavaModelExceptions.
/** * Convenience wrapper for {@link SearchEngine} - performs searching and sorts the results by {@link IResource}. * TODO: throw CoreExceptions from search(..) methods instead of wrapped JavaModelExceptions. */
public class RefactoringSearchEngine { private RefactoringSearchEngine(){ //no instances } //TODO: throw CoreException public static ICompilationUnit[] findAffectedCompilationUnits(SearchPattern pattern, IJavaSearchScope scope, final IProgressMonitor pm, RefactoringStatus status, final boolean tolerateInAccurateMatches) throws JavaModelException { boolean hasNonCuMatches= false; class ResourceSearchRequestor extends SearchRequestor{ boolean hasPotentialMatches= false ; Set<IResource> resources= new HashSet<>(5); private IResource fLastResource; @Override public void acceptSearchMatch(SearchMatch match) { if (!tolerateInAccurateMatches && match.getAccuracy() == SearchMatch.A_INACCURATE) { hasPotentialMatches= true; } if (fLastResource != match.getResource()) { fLastResource= match.getResource(); resources.add(fLastResource); } } } ResourceSearchRequestor requestor = new ResourceSearchRequestor(); try { new SearchEngine().search(pattern, SearchUtils.getDefaultSearchParticipants(), scope, requestor, pm); } catch (CoreException e) { throw new JavaModelException(e); } List<IJavaElement> result= new ArrayList<>(requestor.resources.size()); for (Iterator<IResource> iter= requestor.resources.iterator(); iter.hasNext(); ) { IResource resource= iter.next(); IJavaElement element= JavaCore.create(resource); if (element instanceof ICompilationUnit) { result.add(element); } else { hasNonCuMatches= true; } } addStatusErrors(status, requestor.hasPotentialMatches, hasNonCuMatches); return result.toArray(new ICompilationUnit[result.size()]); } //TODO: throw CoreException public static ICompilationUnit[] findAffectedCompilationUnits(SearchPattern pattern, IJavaSearchScope scope, final IProgressMonitor pm, RefactoringStatus status) throws JavaModelException { return findAffectedCompilationUnits(pattern, scope, pm, status, false); }
Performs a search and groups the resulting SearchMatches by SearchResultGroup.getCompilationUnit().
Params:
  • pattern – the search pattern
  • scope – the search scope
  • monitor – the progress monitor
  • status – an error is added here if inaccurate or non-cu matches have been found
Throws:
See Also:
Returns:a SearchResultGroup[], where each SearchResultGroup has a different getResource()s.
/** * Performs a search and groups the resulting {@link SearchMatch}es by * {@link SearchResultGroup#getCompilationUnit()}. * @param pattern the search pattern * @param scope the search scope * @param monitor the progress monitor * @param status an error is added here if inaccurate or non-cu matches have been found * @return a {@link SearchResultGroup}[], where each {@link SearchResultGroup} * has a different {@link SearchMatch#getResource() getResource()}s. * @see SearchMatch * @throws JavaModelException when the search failed */
//TODO: throw CoreException public static SearchResultGroup[] search(SearchPattern pattern, IJavaSearchScope scope, IProgressMonitor monitor, RefactoringStatus status) throws JavaModelException { return internalSearch(new SearchEngine(), pattern, scope, new CollectingSearchRequestor(), monitor, status); } //TODO: throw CoreException public static SearchResultGroup[] search(SearchPattern pattern, WorkingCopyOwner owner, IJavaSearchScope scope, IProgressMonitor monitor, RefactoringStatus status) throws JavaModelException { return internalSearch(owner != null ? new SearchEngine(owner) : new SearchEngine(), pattern, scope, new CollectingSearchRequestor(), monitor, status); } //TODO: throw CoreException public static SearchResultGroup[] search(SearchPattern pattern, IJavaSearchScope scope, CollectingSearchRequestor requestor, IProgressMonitor monitor, RefactoringStatus status) throws JavaModelException { return internalSearch(new SearchEngine(), pattern, scope, requestor, monitor, status); } //TODO: throw CoreException public static SearchResultGroup[] search(SearchPattern pattern, WorkingCopyOwner owner, IJavaSearchScope scope, CollectingSearchRequestor requestor, IProgressMonitor monitor, RefactoringStatus status) throws JavaModelException { return internalSearch(owner != null ? new SearchEngine(owner) : new SearchEngine(), pattern, scope, requestor, monitor, status); } //TODO: throw CoreException private static SearchResultGroup[] internalSearch(SearchEngine searchEngine, SearchPattern pattern, IJavaSearchScope scope, CollectingSearchRequestor requestor, IProgressMonitor monitor, RefactoringStatus status) throws JavaModelException { try { searchEngine.search(pattern, SearchUtils.getDefaultSearchParticipants(), scope, requestor, monitor); } catch (CoreException e) { throw new JavaModelException(e); } return groupByCu(requestor.getResults(), status); } public static SearchResultGroup[] groupByCu(SearchMatch[] matches, RefactoringStatus status) { return groupByCu(Arrays.asList(matches), status); }
Params:
  • matchList – a List of SearchMatch
  • status – the status to report errors.
Returns:a SearchResultGroup[], grouped by SearchMatch#getResource()
/** * @param matchList a List of SearchMatch * @param status the status to report errors. * @return a SearchResultGroup[], grouped by SearchMatch#getResource() */
public static SearchResultGroup[] groupByCu(List<SearchMatch> matchList, RefactoringStatus status) { Map<IResource, List<SearchMatch>> grouped= new HashMap<>(); boolean hasPotentialMatches= false; boolean hasNonCuMatches= false; for (Iterator<SearchMatch> iter= matchList.iterator(); iter.hasNext();) { SearchMatch searchMatch= iter.next(); if (searchMatch.getAccuracy() == SearchMatch.A_INACCURATE) hasPotentialMatches= true; if (! grouped.containsKey(searchMatch.getResource())) grouped.put(searchMatch.getResource(), new ArrayList<SearchMatch>(1)); grouped.get(searchMatch.getResource()).add(searchMatch); } for (Iterator<IResource> iter= grouped.keySet().iterator(); iter.hasNext();) { IResource resource= iter.next(); IJavaElement element= JavaCore.create(resource); if (! (element instanceof ICompilationUnit)) { iter.remove(); hasNonCuMatches= true; } } SearchResultGroup[] result= new SearchResultGroup[grouped.keySet().size()]; int i= 0; for (Iterator<IResource> iter= grouped.keySet().iterator(); iter.hasNext();) { IResource resource= iter.next(); List<SearchMatch> searchMatches= grouped.get(resource); SearchMatch[] matchArray= searchMatches.toArray(new SearchMatch[searchMatches.size()]); result[i]= new SearchResultGroup(resource, matchArray); i++; } addStatusErrors(status, hasPotentialMatches, hasNonCuMatches); return result; } public static SearchPattern createOrPattern(IJavaElement[] elements, int limitTo) { if (elements == null || elements.length == 0) return null; Set<IJavaElement> set= new HashSet<>(Arrays.asList(elements)); Iterator<IJavaElement> iter= set.iterator(); IJavaElement first= iter.next(); SearchPattern pattern= SearchPattern.createPattern(first, limitTo, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE); if (pattern == null) // check for bug 90138 throw new IllegalArgumentException("Invalid java element: " + first.getHandleIdentifier() + "\n" + first.toString()); //$NON-NLS-1$ //$NON-NLS-2$ while(iter.hasNext()){ IJavaElement each= iter.next(); SearchPattern nextPattern= SearchPattern.createPattern(each, limitTo, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE); if (nextPattern == null) // check for bug 90138 throw new IllegalArgumentException("Invalid java element: " + each.getHandleIdentifier() + "\n" + each.toString()); //$NON-NLS-1$ //$NON-NLS-2$ pattern= SearchPattern.createOrPattern(pattern, nextPattern); } return pattern; } private static boolean containsStatusEntry(final RefactoringStatus status, final RefactoringStatusEntry other) { return status.getEntries(new IRefactoringStatusEntryComparator() { @Override public final int compare(final RefactoringStatusEntry entry1, final RefactoringStatusEntry entry2) { return entry1.getMessage().compareTo(entry2.getMessage()); } }, other).length > 0; } private static void addStatusErrors(RefactoringStatus status, boolean hasPotentialMatches, boolean hasNonCuMatches) { if (hasPotentialMatches) { final RefactoringStatusEntry entry= new RefactoringStatusEntry(RefactoringStatus.ERROR, RefactoringCoreMessages.RefactoringSearchEngine_potential_matches); if (!containsStatusEntry(status, entry)) status.addEntry(entry); } if (hasNonCuMatches) { final RefactoringStatusEntry entry= new RefactoringStatusEntry(RefactoringStatus.ERROR, RefactoringCoreMessages.RefactoringSearchEngine_non_cu_matches); if (!containsStatusEntry(status, entry)) status.addEntry(entry); } } }