1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-09-01 04:33:36 +02:00

Bug 313027 - Rename refactoring is very slow on large projects

This commit is contained in:
Sergey Prigogin 2010-06-30 18:15:14 +00:00
parent 75abd66291
commit eea0205ab1
9 changed files with 165 additions and 50 deletions

View file

@ -44,6 +44,7 @@ public class CRefactory {
public static final int OPTION_IN_INACTIVE_CODE = 0x40; public static final int OPTION_IN_INACTIVE_CODE = 0x40;
public static final int OPTION_IN_CODE = 0x80; public static final int OPTION_IN_CODE = 0x80;
public static final int OPTION_DO_VIRTUAL = 0x100; public static final int OPTION_DO_VIRTUAL = 0x100;
public static final int OPTION_EXHAUSTIVE_FILE_SEARCH = 0x200;
public static final int ARGUMENT_UNKNOWN = 0; public static final int ARGUMENT_UNKNOWN = 0;
public static final int ARGUMENT_LOCAL_VAR = 1; public static final int ARGUMENT_LOCAL_VAR = 1;
@ -72,9 +73,9 @@ public class CRefactory {
private CRefactory() { private CRefactory() {
} }
// runs the rename refactoring // Runs the rename refactoring.
public void rename(Shell shell, ICElement arg) { public void rename(Shell shell, ICElement arg) {
if (!IDE.saveAllEditors(new IResource[] {ResourcesPlugin.getWorkspace().getRoot()}, false)) { if (!IDE.saveAllEditors(new IResource[] { ResourcesPlugin.getWorkspace().getRoot() }, false)) {
return; return;
} }
CRefactoringArgument iarg= new CRefactoringArgument(arg); CRefactoringArgument iarg= new CRefactoringArgument(arg);
@ -101,7 +102,7 @@ public class CRefactory {
if (res instanceof IFile == false) { if (res instanceof IFile == false) {
return; return;
} }
if (!IDE.saveAllEditors(new IResource[] {ResourcesPlugin.getWorkspace().getRoot()}, false)) { if (!IDE.saveAllEditors(new IResource[] { ResourcesPlugin.getWorkspace().getRoot() }, false)) {
return; return;
} }
CRefactoringArgument iarg= new CRefactoringArgument((IFile) res, s.getOffset(), s.getLength()); CRefactoringArgument iarg= new CRefactoringArgument((IFile) res, s.getOffset(), s.getLength());

View file

@ -18,7 +18,8 @@ public class CRenameGlobalProcessor extends CRenameProcessorDelegate {
public CRenameGlobalProcessor(CRenameProcessor processor, String name) { public CRenameGlobalProcessor(CRenameProcessor processor, String name) {
super(processor, name); super(processor, name);
setAvailableOptions(CRefactory.OPTION_ASK_SCOPE | setAvailableOptions(CRefactory.OPTION_ASK_SCOPE |
CRefactory.OPTION_EXHAUSTIVE_FILE_SEARCH |
CRefactory.OPTION_IN_CODE | CRefactory.OPTION_IN_CODE |
CRefactory.OPTION_IN_COMMENT | CRefactory.OPTION_IN_COMMENT |
CRefactory.OPTION_IN_MACRO_DEFINITION); CRefactory.OPTION_IN_MACRO_DEFINITION);

View file

@ -18,6 +18,7 @@ public class CRenameIncludeProcessor extends CRenameProcessorDelegate {
public CRenameIncludeProcessor(CRenameProcessor input, String kind) { public CRenameIncludeProcessor(CRenameProcessor input, String kind) {
super(input, kind); super(input, kind);
setAvailableOptions(CRefactory.OPTION_ASK_SCOPE | setAvailableOptions(CRefactory.OPTION_ASK_SCOPE |
CRefactory.OPTION_EXHAUSTIVE_FILE_SEARCH |
CRefactory.OPTION_IN_COMMENT | CRefactory.OPTION_IN_COMMENT |
CRefactory.OPTION_IN_MACRO_DEFINITION); CRefactory.OPTION_IN_MACRO_DEFINITION);
setOptionsForcingPreview(-1); setOptionsForcingPreview(-1);

View file

@ -24,6 +24,7 @@ public class CRenameMacroProcessor extends CRenameGlobalProcessor {
public CRenameMacroProcessor(CRenameProcessor processor, String name) { public CRenameMacroProcessor(CRenameProcessor processor, String name) {
super(processor, name); super(processor, name);
setAvailableOptions(CRefactory.OPTION_ASK_SCOPE | setAvailableOptions(CRefactory.OPTION_ASK_SCOPE |
CRefactory.OPTION_EXHAUSTIVE_FILE_SEARCH |
CRefactory.OPTION_IN_CODE | CRefactory.OPTION_IN_CODE |
CRefactory.OPTION_IN_COMMENT | CRefactory.OPTION_IN_COMMENT |
CRefactory.OPTION_IN_PREPROCESSOR_DIRECTIVE); CRefactory.OPTION_IN_PREPROCESSOR_DIRECTIVE);

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* IBM Corporation - Bug 112366 * IBM Corporation - Bug 112366
* Sergey Prigogin (Google)
******************************************************************************/ ******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.rename; package org.eclipse.cdt.internal.ui.refactoring.rename;
@ -16,8 +17,12 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set;
import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.IStatus;
@ -37,12 +42,13 @@ import org.eclipse.text.edits.TextEditGroup;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.ui.refactoring.CTextFileChange; import org.eclipse.cdt.ui.refactoring.CTextFileChange;
/** /**
* Abstract base for all different rename processors used by the top * Abstract base for all different rename processors used by the top processor.
* processor.
*/ */
public abstract class CRenameProcessorDelegate { public abstract class CRenameProcessorDelegate {
private CRenameProcessor fTopProcessor; private CRenameProcessor fTopProcessor;
@ -50,13 +56,14 @@ public abstract class CRenameProcessorDelegate {
protected String fProcessorBaseName; protected String fProcessorBaseName;
private int fAvailableOptions= private int fAvailableOptions=
CRefactory.OPTION_ASK_SCOPE | CRefactory.OPTION_ASK_SCOPE |
CRefactory.OPTION_EXHAUSTIVE_FILE_SEARCH |
CRefactory.OPTION_IN_CODE | CRefactory.OPTION_IN_CODE |
CRefactory.OPTION_IN_COMMENT | CRefactory.OPTION_IN_COMMENT |
CRefactory.OPTION_IN_MACRO_DEFINITION | CRefactory.OPTION_IN_MACRO_DEFINITION |
CRefactory.OPTION_IN_STRING_LITERAL; CRefactory.OPTION_IN_STRING_LITERAL;
private int fOptionsForcingPreview= private int fOptionsForcingPreview=
CRefactory.OPTION_IN_CODE | CRefactory.OPTION_IN_INACTIVE_CODE |
CRefactory.OPTION_IN_COMMENT | CRefactory.OPTION_IN_COMMENT |
CRefactory.OPTION_IN_MACRO_DEFINITION | CRefactory.OPTION_IN_MACRO_DEFINITION |
CRefactory.OPTION_IN_PREPROCESSOR_DIRECTIVE | CRefactory.OPTION_IN_PREPROCESSOR_DIRECTIVE |
@ -148,6 +155,54 @@ public abstract class CRenameProcessorDelegate {
return getSelectedScope(); return getSelectedScope();
} }
/**
* Builds an index-based file filter for the name search.
* @return A set of files containing references to the name, or <code>null</code> if
* exhaustive file search is requested.
*/
private IResource[] getFileFilter() {
if ((getSelectedOptions() & CRefactory.OPTION_EXHAUSTIVE_FILE_SEARCH) != 0) {
return null;
}
IIndex index = getIndex();
if (index == null) {
return null;
}
IBinding binding = getArgument().getBinding();
if (binding == null) {
return null;
}
Set<IIndexFileLocation> locations = new HashSet<IIndexFileLocation>();
try {
index.acquireReadLock();
IIndexName[] names = index.findNames(binding,
IIndex.FIND_ALL_OCCURRENCES | IIndex.SEARCH_ACROSS_LANGUAGE_BOUNDARIES);
for (IIndexName name : names) {
locations.add(name.getFile().getLocation());
}
} catch (InterruptedException e) {
return null;
} catch (CoreException e) {
return null;
} finally {
index.releaseReadLock();
}
ArrayList<IResource> files = new ArrayList<IResource>(locations.size());
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
for (IIndexFileLocation location : locations) {
String fullPath= location.getFullPath();
if (fullPath != null) {
IResource file= workspaceRoot.findMember(fullPath);
if (file != null) {
files.add(file);
}
}
}
return files.toArray(new IResource[files.size()]);
}
public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException { public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException {
return new RefactoringStatus(); return new RefactoringStatus();
} }
@ -162,7 +217,7 @@ public abstract class CRenameProcessorDelegate {
fMatches= new ArrayList<CRefactoringMatch>(); fMatches= new ArrayList<CRefactoringMatch>();
TextSearchWrapper txtSearch= getManager().getTextSearch(); TextSearchWrapper txtSearch= getManager().getTextSearch();
IStatus stat= txtSearch.searchWord(getSearchScope(), file, getSelectedWorkingSet(), IStatus stat= txtSearch.searchWord(getSearchScope(), file, getSelectedWorkingSet(),
getManager().getCCppPatterns(), getArgument().getName(), getFileFilter(), getManager().getCCppPatterns(), getArgument().getName(),
new SubProgressMonitor(monitor, 1), fMatches); new SubProgressMonitor(monitor, 1), fMatches);
if (monitor.isCanceled()) { if (monitor.isCanceled()) {
throw new OperationCanceledException(); throw new OperationCanceledException();
@ -228,7 +283,7 @@ public abstract class CRenameProcessorDelegate {
return result; return result;
} }
protected void analyzeTextMatches(ArrayList<CRefactoringMatch> matches, IProgressMonitor monitor, RefactoringStatus status) { protected void analyzeTextMatches(ArrayList<CRefactoringMatch> matches, IProgressMonitor monitor, RefactoringStatus status) {
CRefactoringArgument argument= getArgument(); CRefactoringArgument argument= getArgument();
IBinding[] renameBindings= getBindingsToBeRenamed(status); IBinding[] renameBindings= getBindingsToBeRenamed(status);
if (renameBindings != null && renameBindings.length > 0 && if (renameBindings != null && renameBindings.length > 0 &&

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Emanuel Graf (Institute for Software, HSR Hochschule fuer Technik) * Emanuel Graf (Institute for Software, HSR Hochschule fuer Technik)
* Sergey Prigogin (Google)
******************************************************************************/ ******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.rename; package org.eclipse.cdt.internal.ui.refactoring.rename;
@ -54,6 +55,7 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
private static final String KEY_INCLUDE = "include"; //$NON-NLS-1$ private static final String KEY_INCLUDE = "include"; //$NON-NLS-1$
private static final String KEY_MACRO_DEFINITION = "macroDefinition"; //$NON-NLS-1$ private static final String KEY_MACRO_DEFINITION = "macroDefinition"; //$NON-NLS-1$
private static final String KEY_PREPROCESSOR = "preprocessor"; //$NON-NLS-1$ private static final String KEY_PREPROCESSOR = "preprocessor"; //$NON-NLS-1$
private static final String KEY_EXHAUSTIVE_FILE_SEARCH = "exhausiveFileSearch"; //$NON-NLS-1$
private IDialogSettings fDialogSettings; private IDialogSettings fDialogSettings;
private String fSearchString; private String fSearchString;
@ -76,6 +78,7 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
private Button fWorkingSetButton; private Button fWorkingSetButton;
private Button fInMacro; private Button fInMacro;
private Button fInPreprocessor; private Button fInPreprocessor;
private Button fExhausiveFileSearch;
public CRenameRefactoringInputPage() { public CRenameRefactoringInputPage() {
super(PAGE_NAME); super(PAGE_NAME);
@ -110,15 +113,15 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
GridData gd; GridData gd;
GridLayout gl; GridLayout gl;
Label label= new Label(group, SWT.NONE); Label label= new Label(top, SWT.NONE);
label.setText(Messages.CRenameRefactoringInputPage_label_newName); label.setText(Messages.CRenameRefactoringInputPage_label_newName);
fNewName= new Text(group, SWT.BORDER); fNewName= new Text(top, SWT.BORDER);
fNewName.setText(fSearchString); fNewName.setText(fSearchString);
fNewName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); fNewName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
fNewName.selectAll(); fNewName.selectAll();
if (hasOption(CRefactory.OPTION_DO_VIRTUAL)) { if (hasOption(CRefactory.OPTION_DO_VIRTUAL)) {
fDoVirtual= new Button(group, SWT.CHECK); fDoVirtual= new Button(top, SWT.CHECK);
fDoVirtual.setText(Messages.CRenameRefactoringInputPage_renameBaseAndDerivedMethods); fDoVirtual.setText(Messages.CRenameRefactoringInputPage_renameBaseAndDerivedMethods);
fDoVirtual.setLayoutData(gd= new GridData()); fDoVirtual.setLayoutData(gd= new GridData());
gd.horizontalSpan= 2; gd.horizontalSpan= 2;
@ -204,6 +207,16 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
fInPreprocessor= new Button(group, SWT.CHECK); fInPreprocessor= new Button(group, SWT.CHECK);
fInPreprocessor.setText(Messages.CRenameRefactoringInputPage_button_preprocessor); fInPreprocessor.setText(Messages.CRenameRefactoringInputPage_button_preprocessor);
} }
if (hasOption(CRefactory.OPTION_EXHAUSTIVE_FILE_SEARCH)) {
skipLine(top);
fExhausiveFileSearch= new Button(top, SWT.CHECK);
fExhausiveFileSearch.setText(Messages.CRenameRefactoringInputPage_button_exhaustiveFileSearch);
fExhausiveFileSearch.setLayoutData(gd= new GridData());
gd.horizontalIndent= 5;
gd.horizontalSpan= 2;
}
Dialog.applyDialogFont(top); Dialog.applyDialogFont(top);
hookSelectionListeners(); hookSelectionListeners();
readPreferences(); readPreferences();
@ -270,6 +283,7 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
registerOptionListener(fInMacro, listenOption); registerOptionListener(fInMacro, listenOption);
registerOptionListener(fInString, listenOption); registerOptionListener(fInString, listenOption);
registerOptionListener(fInPreprocessor, listenOption); registerOptionListener(fInPreprocessor, listenOption);
registerOptionListener(fExhausiveFileSearch, listenOption);
} }
private void registerScopeListener(Button button, final int scope) { private void registerScopeListener(Button button, final int scope) {
@ -296,7 +310,7 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
private void onSelectOption() { private void onSelectOption() {
int selectedOptions= computeSelectedOptions(); int selectedOptions= computeSelectedOptions();
boolean forcePreview= fForcePreviewOptions==-1 || boolean forcePreview= fForcePreviewOptions == -1 ||
(selectedOptions & fForcePreviewOptions) != 0; (selectedOptions & fForcePreviewOptions) != 0;
getRenameProcessor().setSelectedOptions(selectedOptions); getRenameProcessor().setSelectedOptions(selectedOptions);
getRefactoringWizard().setForcePreviewReview(forcePreview); getRefactoringWizard().setForcePreviewReview(forcePreview);
@ -322,12 +336,11 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
int choice; int choice;
try { try {
choice= fDialogSettings.getInt(KEY_SCOPE); choice= fDialogSettings.getInt(KEY_SCOPE);
} } catch (Exception e) {
catch (Exception e) {
choice= TextSearchWrapper.SCOPE_RELATED_PROJECTS; choice= TextSearchWrapper.SCOPE_RELATED_PROJECTS;
} }
switch(choice) { switch (choice) {
case TextSearchWrapper.SCOPE_WORKSPACE: case TextSearchWrapper.SCOPE_WORKSPACE:
fWorkspace.setSelection(true); fWorkspace.setSelection(true);
break; break;
@ -363,6 +376,7 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
initOption(fInMacro, KEY_MACRO_DEFINITION); initOption(fInMacro, KEY_MACRO_DEFINITION);
initOption(fInPreprocessor, KEY_PREPROCESSOR); initOption(fInPreprocessor, KEY_PREPROCESSOR);
initOption(fInInactiveCode, KEY_INACTIVE); initOption(fInInactiveCode, KEY_INACTIVE);
initOption(fExhausiveFileSearch, KEY_EXHAUSTIVE_FILE_SEARCH);
} }
private int computeSelectedOptions() { private int computeSelectedOptions() {
@ -375,6 +389,7 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
options |= computeOption(fInPreprocessor, CRefactory.OPTION_IN_PREPROCESSOR_DIRECTIVE); options |= computeOption(fInPreprocessor, CRefactory.OPTION_IN_PREPROCESSOR_DIRECTIVE);
options |= computeOption(fInMacro, CRefactory.OPTION_IN_MACRO_DEFINITION); options |= computeOption(fInMacro, CRefactory.OPTION_IN_MACRO_DEFINITION);
options |= computeOption(fInInactiveCode, CRefactory.OPTION_IN_INACTIVE_CODE); options |= computeOption(fInInactiveCode, CRefactory.OPTION_IN_INACTIVE_CODE);
options |= computeOption(fExhausiveFileSearch, CRefactory.OPTION_EXHAUSTIVE_FILE_SEARCH);
return options; return options;
} }
@ -440,6 +455,9 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
if (fInInactiveCode != null) { if (fInInactiveCode != null) {
fDialogSettings.put(KEY_INACTIVE, fInInactiveCode.getSelection()); fDialogSettings.put(KEY_INACTIVE, fInInactiveCode.getSelection());
} }
if (fExhausiveFileSearch != null) {
fDialogSettings.put(KEY_EXHAUSTIVE_FILE_SEARCH, fExhausiveFileSearch.getSelection());
}
} }
protected void onSelectWorkingSet() { protected void onSelectWorkingSet() {
@ -488,7 +506,7 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage {
} }
protected void updateEnablement() { protected void updateEnablement() {
boolean enable= fEnableScopeOptions==-1 || boolean enable= fEnableScopeOptions == -1 ||
(computeSelectedOptions() & fEnableScopeOptions) != 0; (computeSelectedOptions() & fEnableScopeOptions) != 0;
if (fWorkspace != null) { if (fWorkspace != null) {

View file

@ -69,10 +69,11 @@ public class Messages extends NLS {
public static String CRenameRefactoringInputPage_button_includes; public static String CRenameRefactoringInputPage_button_includes;
public static String CRenameRefactoringInputPage_button_macroDefinitions; public static String CRenameRefactoringInputPage_button_macroDefinitions;
public static String CRenameRefactoringInputPage_button_preprocessor; public static String CRenameRefactoringInputPage_button_preprocessor;
public static String CRenameRefactoringInputPage_button_strings;
public static String CRenameRefactoringInputPage_button_exhaustiveFileSearch;
public static String CRenameRefactoringInputPage_button_singleProject; public static String CRenameRefactoringInputPage_button_singleProject;
public static String CRenameRefactoringInputPage_button_relatedProjects; public static String CRenameRefactoringInputPage_button_relatedProjects;
public static String CRenameRefactoringInputPage_button_workspace; public static String CRenameRefactoringInputPage_button_workspace;
public static String CRenameRefactoringInputPage_button_strings;
public static String CRenameRefactoringInputPage_button_workingSet; public static String CRenameRefactoringInputPage_button_workingSet;
public static String CRenameRefactoringInputPage_errorInvalidIdentifier; public static String CRenameRefactoringInputPage_errorInvalidIdentifier;
public static String CRenameRefactoringInputPage_label_newName; public static String CRenameRefactoringInputPage_label_newName;

View file

@ -65,10 +65,11 @@ CRenameRefactoringInputPage_button_inactiveCode=Inactive conditional compilation
CRenameRefactoringInputPage_button_includes=Include directives CRenameRefactoringInputPage_button_includes=Include directives
CRenameRefactoringInputPage_button_macroDefinitions=Macro definitions CRenameRefactoringInputPage_button_macroDefinitions=Macro definitions
CRenameRefactoringInputPage_button_preprocessor=Other preprocessor directives CRenameRefactoringInputPage_button_preprocessor=Other preprocessor directives
CRenameRefactoringInputPage_button_strings=String literals
CRenameRefactoringInputPage_button_exhaustiveFileSearch=Exhaustive file search (slow)
CRenameRefactoringInputPage_button_singleProject=Project CRenameRefactoringInputPage_button_singleProject=Project
CRenameRefactoringInputPage_button_relatedProjects=Related projects CRenameRefactoringInputPage_button_relatedProjects=Related projects
CRenameRefactoringInputPage_button_workspace=All projects CRenameRefactoringInputPage_button_workspace=All projects
CRenameRefactoringInputPage_button_strings=String literals
CRenameRefactoringInputPage_button_workingSet=Working set: CRenameRefactoringInputPage_button_workingSet=Working set:
CRenameRefactoringInputPage_errorInvalidIdentifier=''{0}'' is not a valid identifier CRenameRefactoringInputPage_errorInvalidIdentifier=''{0}'' is not a valid identifier
CRenameRefactoringInputPage_label_newName=New Name: CRenameRefactoringInputPage_label_newName=New Name:

View file

@ -6,7 +6,8 @@
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.rename; package org.eclipse.cdt.internal.ui.refactoring.rename;
@ -32,6 +33,7 @@ import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceProxy; import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.core.runtime.SubProgressMonitor;
@ -46,6 +48,7 @@ import org.eclipse.ui.PlatformUI;
import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.utils.PathUtil;
import org.eclipse.cdt.internal.formatter.scanner.SimpleScanner; import org.eclipse.cdt.internal.formatter.scanner.SimpleScanner;
import org.eclipse.cdt.internal.formatter.scanner.Token; import org.eclipse.cdt.internal.formatter.scanner.Token;
@ -62,7 +65,7 @@ public class TextSearchWrapper {
public final static int SCOPE_WORKING_SET = 5; public final static int SCOPE_WORKING_SET = 5;
private static class SearchScope extends TextSearchScope { private static class SearchScope extends TextSearchScope {
public static SearchScope newSearchScope(IWorkingSet ws) { public static SearchScope newSearchScope(IWorkingSet ws, IResource[] filter) {
IAdaptable[] adaptables= ws.getElements(); IAdaptable[] adaptables= ws.getElements();
ArrayList<IResource> resources = new ArrayList<IResource>(); ArrayList<IResource> resources = new ArrayList<IResource>();
for (int i = 0; i < adaptables.length; i++) { for (int i = 0; i < adaptables.length; i++) {
@ -72,18 +75,40 @@ public class TextSearchWrapper {
resources.add(r); resources.add(r);
} }
} }
return newSearchScope(resources.toArray(new IResource[resources.size()]), false); return newSearchScope(resources.toArray(new IResource[resources.size()]), filter);
} }
public static SearchScope newSearchScope(IResource[] resources, boolean copy) { public static SearchScope newSearchScope(IResource[] roots, IResource[] filter) {
return new SearchScope(resources, copy); if (filter != null) {
ArrayList<IResource> files = new ArrayList<IResource>(filter.length);
for (IResource file : filter) {
if (isInForest(file, roots)) {
files.add(file);
}
}
roots = files.toArray(new IResource[files.size()]);
}
return new SearchScope(roots);
} }
private IResource[] fRootResources; /**
* Checks is a file belongs to one of the given containers.
*/
private static boolean isInForest(IResource file, IResource[] roots) {
IPath filePath = file.getFullPath();
for (IResource root : roots) {
if (PathUtil.isPrefix(root.getFullPath(), filePath)) {
return true;
}
}
return false;
}
private IResource[] fRootResources;
private ArrayList<Matcher> fFileMatcher= new ArrayList<Matcher>(); private ArrayList<Matcher> fFileMatcher= new ArrayList<Matcher>();
private SearchScope(IResource[] resources, boolean copy) { private SearchScope(IResource[] roots) {
fRootResources= copy ? (IResource[]) resources.clone() : resources; fRootResources= roots;
} }
@Override @Override
@ -153,29 +178,30 @@ public class TextSearchWrapper {
} }
} }
public TextSearchWrapper() {} public TextSearchWrapper() {
}
private TextSearchScope createSearchScope(IFile file, int scope, private TextSearchScope createSearchScope(IFile file, int scope, String workingSetName,
String workingSetName, String[] patterns) { IResource[] filter, String[] patterns) {
switch (scope) { switch (scope) {
case SCOPE_WORKSPACE: case SCOPE_WORKSPACE:
return defineSearchScope(file.getWorkspace().getRoot(), patterns); return defineSearchScope(file.getWorkspace().getRoot(), filter, patterns);
case SCOPE_SINGLE_PROJECT: case SCOPE_SINGLE_PROJECT:
return defineSearchScope(file.getProject(), patterns); return defineSearchScope(file.getProject(), filter, patterns);
case SCOPE_FILE: case SCOPE_FILE:
return defineSearchScope(file, patterns); return defineSearchScope(file, filter, patterns);
case SCOPE_WORKING_SET: { case SCOPE_WORKING_SET: {
TextSearchScope result= defineWorkingSetAsSearchScope(workingSetName, patterns); TextSearchScope result= defineWorkingSetAsSearchScope(workingSetName, filter, patterns);
if (result == null) { if (result == null) {
result= defineSearchScope(file.getWorkspace().getRoot(), patterns); result= defineSearchScope(file.getWorkspace().getRoot(), filter, patterns);
} }
return result; return result;
} }
} }
return defineRelatedProjectsAsSearchScope(file.getProject(), patterns); return defineRelatedProjectsAsSearchScope(file.getProject(), filter, patterns);
} }
private TextSearchScope defineRelatedProjectsAsSearchScope(IProject project, String[] patterns) { private TextSearchScope defineRelatedProjectsAsSearchScope(IProject project, IResource[] filter, String[] patterns) {
HashSet<IProject> projects= new HashSet<IProject>(); HashSet<IProject> projects= new HashSet<IProject>();
LinkedList<IProject> workThrough= new LinkedList<IProject>(); LinkedList<IProject> workThrough= new LinkedList<IProject>();
workThrough.add(project); workThrough.add(project);
@ -190,20 +216,20 @@ public class TextSearchWrapper {
} }
} }
} }
IResource[] resources= projects.toArray(new IResource[projects.size()]); IResource[] roots= projects.toArray(new IResource[projects.size()]);
return defineSearchScope(resources, patterns); return defineSearchScope(roots, filter, patterns);
} }
private TextSearchScope defineWorkingSetAsSearchScope(String wsName, String[] patterns) { private TextSearchScope defineWorkingSetAsSearchScope(String workingSetName, IResource[] filter, String[] patterns) {
if (wsName == null) { if (workingSetName == null) {
return null; return null;
} }
IWorkingSetManager wsManager= PlatformUI.getWorkbench().getWorkingSetManager(); IWorkingSetManager wsManager= PlatformUI.getWorkbench().getWorkingSetManager();
IWorkingSet ws= wsManager.getWorkingSet(wsName); IWorkingSet ws= wsManager.getWorkingSet(workingSetName);
if (ws == null) { if (ws == null) {
return null; return null;
} }
SearchScope result= SearchScope.newSearchScope(ws); SearchScope result= SearchScope.newSearchScope(ws, filter);
applyFilePatterns(result, patterns); applyFilePatterns(result, patterns);
return result; return result;
} }
@ -215,22 +241,32 @@ public class TextSearchWrapper {
} }
} }
private TextSearchScope defineSearchScope(IResource resource, String[] patterns) { private TextSearchScope defineSearchScope(IResource root, IResource[] filter, String[] patterns) {
SearchScope result= SearchScope.newSearchScope(new IResource[] { resource }, false); SearchScope result= SearchScope.newSearchScope(new IResource[] { root }, filter);
applyFilePatterns(result, patterns); applyFilePatterns(result, patterns);
return result; return result;
} }
private TextSearchScope defineSearchScope(IResource[] resources, String[] patterns) { private TextSearchScope defineSearchScope(IResource[] roots, IResource[] filter, String[] patterns) {
SearchScope result= SearchScope.newSearchScope(resources, true); SearchScope result= SearchScope.newSearchScope(roots, filter);
applyFilePatterns(result, patterns); applyFilePatterns(result, patterns);
return result; return result;
} }
/** /**
* @param monitor * Searches for a given word.
*
* @param scope One of SCOPE_FILE, SCOPE_WORKSPACE, SCOPE_RELATED_PROJECTS, SCOPE_SINGLE_PROJECT,
* or SCOPE_WORKING_SET.
* @param file The file used as an anchor for the scope.
* @param workingSet The name of a working set. Ignored is scope is not SCOPE_WORKING_SET.
* @param filter If not null, further limits the scope of the search.
* @param patterns File name patterns.
* @param word The word to search for.
* @param monitor A progress monitor.
* @param target The list that gets populated with search results.
*/ */
public IStatus searchWord(int scope, IFile resource, String workingSet, String[] patterns, public IStatus searchWord(int scope, IFile file, String workingSet, IResource[] filter, String[] patterns,
String word, IProgressMonitor monitor, final List<CRefactoringMatch> target) { String word, IProgressMonitor monitor, final List<CRefactoringMatch> target) {
int startPos= target.size(); int startPos= target.size();
TextSearchEngine engine= TextSearchEngine.create(); TextSearchEngine engine= TextSearchEngine.create();
@ -243,7 +279,7 @@ public class TextSearchWrapper {
Pattern pattern= Pattern.compile(searchPattern.toString()); Pattern pattern= Pattern.compile(searchPattern.toString());
TextSearchScope searchscope= createSearchScope(resource, scope, workingSet, patterns); TextSearchScope searchscope= createSearchScope(file, scope, workingSet, filter, patterns);
TextSearchRequestor requestor= new TextSearchRequestor() { TextSearchRequestor requestor= new TextSearchRequestor() {
@Override @Override
public boolean acceptPatternMatch(TextSearchMatchAccess access) { public boolean acceptPatternMatch(TextSearchMatchAccess access) {