blob: a7f0ee72b1dd8b14b533db41d20e5a2ddc2dfda7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.corext.refactoring.rename;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.ltk.core.refactoring.GroupCategorySet;
import org.eclipse.ltk.core.refactoring.GroupCategory;
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.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility;
import org.eclipse.jdt.internal.corext.refactoring.rename.RefactoringScanner.TextMatch;
import org.eclipse.jdt.internal.corext.refactoring.tagging.ITextUpdating;
import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
class TextMatchUpdater {
private static final String TEXT_EDIT_LABEL= RefactoringCoreMessages.TextMatchUpdater_update;
private static final GroupCategorySet TEXTUAL_MATCHES= new GroupCategorySet(
new GroupCategory("org.eclipse.jdt.internal.corext.textualMatches", //$NON-NLS-1$
RefactoringCoreMessages.TextMatchUpdater_textualMatches_name,
RefactoringCoreMessages.TextMatchUpdater_textualMatches_description));
private final IJavaSearchScope fScope;
private final TextChangeManager fManager;
private final SearchResultGroup[] fReferences;
private final boolean fOnlyQualified;
private final RefactoringScanner fScanner;
private final String fNewName;
private final int fCurrentNameLength;
private TextMatchUpdater(TextChangeManager manager, IJavaSearchScope scope, String currentName, String currentQualifier, String newName, SearchResultGroup[] references, boolean onlyQualified){
Assert.isNotNull(manager);
Assert.isNotNull(scope);
Assert.isNotNull(references);
fManager= manager;
fScope= scope;
fReferences= references;
fOnlyQualified= onlyQualified;
fNewName= newName;
fCurrentNameLength= currentName.length();
fScanner= new RefactoringScanner(currentName, currentQualifier);
}
static void perform(IProgressMonitor pm, IJavaSearchScope scope, String currentName, String currentQualifier, String newName, TextChangeManager manager, SearchResultGroup[] references, boolean onlyQualified) throws JavaModelException{
new TextMatchUpdater(manager, scope, currentName, currentQualifier, newName, references, onlyQualified).updateTextMatches(pm);
}
static void perform(IProgressMonitor pm, IJavaSearchScope scope, ITextUpdating processor, TextChangeManager manager, SearchResultGroup[] references) throws JavaModelException{
new TextMatchUpdater(manager, scope, processor.getCurrentElementName(), processor.getCurrentElementQualifier(), processor.getNewElementName(), references, false).updateTextMatches(pm);
}
private void updateTextMatches(IProgressMonitor pm) throws JavaModelException {
try{
IProject[] projectsInScope= getProjectsInScope();
pm.beginTask("", projectsInScope.length); //$NON-NLS-1$
for (int i =0 ; i < projectsInScope.length; i++){
if (pm.isCanceled())
throw new OperationCanceledException();
addTextMatches(projectsInScope[i], new SubProgressMonitor(pm, 1));
}
} finally{
pm.done();
}
}
private IProject[] getProjectsInScope() {
IPath[] enclosingProjects= fScope.enclosingProjectsAndJars();
Set enclosingProjectSet= new HashSet();
enclosingProjectSet.addAll(Arrays.asList(enclosingProjects));
ArrayList projectsInScope= new ArrayList();
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
for (int i =0 ; i < projects.length; i++){
if (enclosingProjectSet.contains(projects[i].getFullPath()))
projectsInScope.add(projects[i]);
}
return (IProject[]) projectsInScope.toArray(new IProject[projectsInScope.size()]);
}
private void addTextMatches(IResource resource, IProgressMonitor pm) throws JavaModelException{
try{
String task= RefactoringCoreMessages.TextMatchUpdater_searching + resource.getFullPath();
if (resource instanceof IFile){
IJavaElement element= JavaCore.create(resource);
// don't start pm task (flickering label updates; finally {pm.done()} is enough)
if (!(element instanceof ICompilationUnit))
return;
if (! element.exists())
return;
if (! fScope.encloses(element))
return;
addCuTextMatches((ICompilationUnit) element);
} else if (resource instanceof IContainer){
IResource[] members= ((IContainer) resource).members();
pm.beginTask(task, members.length);
pm.subTask(task);
for (int i = 0; i < members.length; i++) {
if (pm.isCanceled())
throw new OperationCanceledException();
addTextMatches(members[i], new SubProgressMonitor(pm, 1));
}
}
} catch (JavaModelException e){
throw e;
} catch (CoreException e){
throw new JavaModelException(e);
} finally{
pm.done();
}
}
private void addCuTextMatches(ICompilationUnit cu) throws JavaModelException{
fScanner.scan(cu);
Set matches= fScanner.getMatches(); //Set of TextMatch
if (matches.size() == 0)
return;
removeReferences(cu, matches);
if (matches.size() != 0)
addTextUpdates(cu, matches);
}
private void removeReferences(ICompilationUnit cu, Set matches) {
for (int i= 0; i < fReferences.length; i++) {
SearchResultGroup group= fReferences[i];
if (cu.equals(group.getCompilationUnit())) {
removeReferences(matches, group);
}
}
}
private void removeReferences(Set matches, SearchResultGroup group) {
SearchMatch[] searchResults= group.getSearchResults();
for (int r= 0; r < searchResults.length; r++) {
//int start= searchResults[r].getStart(); // doesn't work for pack.ReferencedType
int unqualifiedStart= searchResults[r].getOffset() + searchResults[r].getLength() - fCurrentNameLength;
for (Iterator iter= matches.iterator(); iter.hasNext();) {
TextMatch element= (TextMatch) iter.next();
if (element.getStartPosition() == unqualifiedStart)
iter.remove();
}
}
}
private void addTextUpdates(ICompilationUnit cu, Set matches) {
for (Iterator resultIter= matches.iterator(); resultIter.hasNext();){
TextMatch match= (TextMatch) resultIter.next();
if (!match.isQualified() && fOnlyQualified)
continue;
int matchStart= match.getStartPosition();
ReplaceEdit edit= new ReplaceEdit(matchStart, fCurrentNameLength, fNewName);
TextChangeCompatibility.addTextEdit(fManager.get(cu), TEXT_EDIT_LABEL, edit, TEXTUAL_MATCHES);
}
}
}