From eea0205ab1eb8fa31cda0b4bf0f10212786d0e7d Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Wed, 30 Jun 2010 18:15:14 +0000 Subject: [PATCH] Bug 313027 - Rename refactoring is very slow on large projects --- .../ui/refactoring/rename/CRefactory.java | 7 +- .../rename/CRenameGlobalProcessor.java | 3 +- .../rename/CRenameIncludeProcessor.java | 1 + .../rename/CRenameMacroProcessor.java | 1 + .../rename/CRenameProcessorDelegate.java | 65 +++++++++++- .../rename/CRenameRefactoringInputPage.java | 34 +++++-- .../ui/refactoring/rename/Messages.java | 3 +- .../ui/refactoring/rename/Messages.properties | 3 +- .../refactoring/rename/TextSearchWrapper.java | 98 +++++++++++++------ 9 files changed, 165 insertions(+), 50 deletions(-) diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRefactory.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRefactory.java index bef3c0a3014..9474a1c268a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRefactory.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRefactory.java @@ -44,6 +44,7 @@ public class CRefactory { public static final int OPTION_IN_INACTIVE_CODE = 0x40; public static final int OPTION_IN_CODE = 0x80; 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_LOCAL_VAR = 1; @@ -72,9 +73,9 @@ public class CRefactory { private CRefactory() { } - // runs the rename refactoring + // Runs the rename refactoring. 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; } CRefactoringArgument iarg= new CRefactoringArgument(arg); @@ -101,7 +102,7 @@ public class CRefactory { if (res instanceof IFile == false) { return; } - if (!IDE.saveAllEditors(new IResource[] {ResourcesPlugin.getWorkspace().getRoot()}, false)) { + if (!IDE.saveAllEditors(new IResource[] { ResourcesPlugin.getWorkspace().getRoot() }, false)) { return; } CRefactoringArgument iarg= new CRefactoringArgument((IFile) res, s.getOffset(), s.getLength()); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameGlobalProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameGlobalProcessor.java index b5bb7c60ac8..b590d1c0a10 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameGlobalProcessor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameGlobalProcessor.java @@ -18,7 +18,8 @@ public class CRenameGlobalProcessor extends CRenameProcessorDelegate { public CRenameGlobalProcessor(CRenameProcessor processor, String 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_COMMENT | CRefactory.OPTION_IN_MACRO_DEFINITION); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameIncludeProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameIncludeProcessor.java index 8ce6f377b58..7c5848519ef 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameIncludeProcessor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameIncludeProcessor.java @@ -18,6 +18,7 @@ public class CRenameIncludeProcessor extends CRenameProcessorDelegate { public CRenameIncludeProcessor(CRenameProcessor input, String kind) { super(input, kind); setAvailableOptions(CRefactory.OPTION_ASK_SCOPE | + CRefactory.OPTION_EXHAUSTIVE_FILE_SEARCH | CRefactory.OPTION_IN_COMMENT | CRefactory.OPTION_IN_MACRO_DEFINITION); setOptionsForcingPreview(-1); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameMacroProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameMacroProcessor.java index 0439105c3d2..ad3bfbf2954 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameMacroProcessor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameMacroProcessor.java @@ -24,6 +24,7 @@ public class CRenameMacroProcessor extends CRenameGlobalProcessor { public CRenameMacroProcessor(CRenameProcessor processor, String name) { super(processor, name); setAvailableOptions(CRefactory.OPTION_ASK_SCOPE | + CRefactory.OPTION_EXHAUSTIVE_FILE_SEARCH | CRefactory.OPTION_IN_CODE | CRefactory.OPTION_IN_COMMENT | CRefactory.OPTION_IN_PREPROCESSOR_DIRECTIVE); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameProcessorDelegate.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameProcessorDelegate.java index 2df87eb865a..8bb0227963a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameProcessorDelegate.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameProcessorDelegate.java @@ -8,6 +8,7 @@ * Contributors: * Markus Schorn - initial API and implementation * IBM Corporation - Bug 112366 + * Sergey Prigogin (Google) ******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.rename; @@ -16,8 +17,12 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; +import java.util.Set; 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.IProgressMonitor; 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.index.IIndex; +import org.eclipse.cdt.core.index.IIndexFileLocation; +import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.ui.refactoring.CTextFileChange; /** - * Abstract base for all different rename processors used by the top - * processor. + * Abstract base for all different rename processors used by the top processor. */ public abstract class CRenameProcessorDelegate { private CRenameProcessor fTopProcessor; @@ -50,13 +56,14 @@ public abstract class CRenameProcessorDelegate { protected String fProcessorBaseName; private int fAvailableOptions= CRefactory.OPTION_ASK_SCOPE | + CRefactory.OPTION_EXHAUSTIVE_FILE_SEARCH | CRefactory.OPTION_IN_CODE | CRefactory.OPTION_IN_COMMENT | CRefactory.OPTION_IN_MACRO_DEFINITION | CRefactory.OPTION_IN_STRING_LITERAL; private int fOptionsForcingPreview= - CRefactory.OPTION_IN_CODE | + CRefactory.OPTION_IN_INACTIVE_CODE | CRefactory.OPTION_IN_COMMENT | CRefactory.OPTION_IN_MACRO_DEFINITION | CRefactory.OPTION_IN_PREPROCESSOR_DIRECTIVE | @@ -148,6 +155,54 @@ public abstract class CRenameProcessorDelegate { return getSelectedScope(); } + /** + * Builds an index-based file filter for the name search. + * @return A set of files containing references to the name, or null 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 locations = new HashSet(); + 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 files = new ArrayList(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 { return new RefactoringStatus(); } @@ -162,7 +217,7 @@ public abstract class CRenameProcessorDelegate { fMatches= new ArrayList(); TextSearchWrapper txtSearch= getManager().getTextSearch(); IStatus stat= txtSearch.searchWord(getSearchScope(), file, getSelectedWorkingSet(), - getManager().getCCppPatterns(), getArgument().getName(), + getFileFilter(), getManager().getCCppPatterns(), getArgument().getName(), new SubProgressMonitor(monitor, 1), fMatches); if (monitor.isCanceled()) { throw new OperationCanceledException(); @@ -228,7 +283,7 @@ public abstract class CRenameProcessorDelegate { return result; } - protected void analyzeTextMatches(ArrayList matches, IProgressMonitor monitor, RefactoringStatus status) { + protected void analyzeTextMatches(ArrayList matches, IProgressMonitor monitor, RefactoringStatus status) { CRefactoringArgument argument= getArgument(); IBinding[] renameBindings= getBindingsToBeRenamed(status); if (renameBindings != null && renameBindings.length > 0 && diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameRefactoringInputPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameRefactoringInputPage.java index 906c47e3b54..5f08f5d2279 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameRefactoringInputPage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/CRenameRefactoringInputPage.java @@ -8,6 +8,7 @@ * Contributors: * Markus Schorn - initial API and implementation * Emanuel Graf (Institute for Software, HSR Hochschule fuer Technik) + * Sergey Prigogin (Google) ******************************************************************************/ 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_MACRO_DEFINITION = "macroDefinition"; //$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 String fSearchString; @@ -76,6 +78,7 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage { private Button fWorkingSetButton; private Button fInMacro; private Button fInPreprocessor; + private Button fExhausiveFileSearch; public CRenameRefactoringInputPage() { super(PAGE_NAME); @@ -110,15 +113,15 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage { GridData gd; GridLayout gl; - Label label= new Label(group, SWT.NONE); + Label label= new Label(top, SWT.NONE); label.setText(Messages.CRenameRefactoringInputPage_label_newName); - fNewName= new Text(group, SWT.BORDER); + fNewName= new Text(top, SWT.BORDER); fNewName.setText(fSearchString); fNewName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); fNewName.selectAll(); if (hasOption(CRefactory.OPTION_DO_VIRTUAL)) { - fDoVirtual= new Button(group, SWT.CHECK); + fDoVirtual= new Button(top, SWT.CHECK); fDoVirtual.setText(Messages.CRenameRefactoringInputPage_renameBaseAndDerivedMethods); fDoVirtual.setLayoutData(gd= new GridData()); gd.horizontalSpan= 2; @@ -204,6 +207,16 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage { fInPreprocessor= new Button(group, SWT.CHECK); 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); hookSelectionListeners(); readPreferences(); @@ -270,6 +283,7 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage { registerOptionListener(fInMacro, listenOption); registerOptionListener(fInString, listenOption); registerOptionListener(fInPreprocessor, listenOption); + registerOptionListener(fExhausiveFileSearch, listenOption); } private void registerScopeListener(Button button, final int scope) { @@ -296,7 +310,7 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage { private void onSelectOption() { int selectedOptions= computeSelectedOptions(); - boolean forcePreview= fForcePreviewOptions==-1 || + boolean forcePreview= fForcePreviewOptions == -1 || (selectedOptions & fForcePreviewOptions) != 0; getRenameProcessor().setSelectedOptions(selectedOptions); getRefactoringWizard().setForcePreviewReview(forcePreview); @@ -322,12 +336,11 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage { int choice; try { choice= fDialogSettings.getInt(KEY_SCOPE); - } - catch (Exception e) { + } catch (Exception e) { choice= TextSearchWrapper.SCOPE_RELATED_PROJECTS; } - switch(choice) { + switch (choice) { case TextSearchWrapper.SCOPE_WORKSPACE: fWorkspace.setSelection(true); break; @@ -363,6 +376,7 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage { initOption(fInMacro, KEY_MACRO_DEFINITION); initOption(fInPreprocessor, KEY_PREPROCESSOR); initOption(fInInactiveCode, KEY_INACTIVE); + initOption(fExhausiveFileSearch, KEY_EXHAUSTIVE_FILE_SEARCH); } private int computeSelectedOptions() { @@ -375,6 +389,7 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage { options |= computeOption(fInPreprocessor, CRefactory.OPTION_IN_PREPROCESSOR_DIRECTIVE); options |= computeOption(fInMacro, CRefactory.OPTION_IN_MACRO_DEFINITION); options |= computeOption(fInInactiveCode, CRefactory.OPTION_IN_INACTIVE_CODE); + options |= computeOption(fExhausiveFileSearch, CRefactory.OPTION_EXHAUSTIVE_FILE_SEARCH); return options; } @@ -440,6 +455,9 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage { if (fInInactiveCode != null) { fDialogSettings.put(KEY_INACTIVE, fInInactiveCode.getSelection()); } + if (fExhausiveFileSearch != null) { + fDialogSettings.put(KEY_EXHAUSTIVE_FILE_SEARCH, fExhausiveFileSearch.getSelection()); + } } protected void onSelectWorkingSet() { @@ -488,7 +506,7 @@ public class CRenameRefactoringInputPage extends UserInputWizardPage { } protected void updateEnablement() { - boolean enable= fEnableScopeOptions==-1 || + boolean enable= fEnableScopeOptions == -1 || (computeSelectedOptions() & fEnableScopeOptions) != 0; if (fWorkspace != null) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/Messages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/Messages.java index 391e01e4f65..b260f67a467 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/Messages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/Messages.java @@ -69,10 +69,11 @@ public class Messages extends NLS { public static String CRenameRefactoringInputPage_button_includes; public static String CRenameRefactoringInputPage_button_macroDefinitions; 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_relatedProjects; public static String CRenameRefactoringInputPage_button_workspace; - public static String CRenameRefactoringInputPage_button_strings; public static String CRenameRefactoringInputPage_button_workingSet; public static String CRenameRefactoringInputPage_errorInvalidIdentifier; public static String CRenameRefactoringInputPage_label_newName; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/Messages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/Messages.properties index e697cd274ce..451334b75cf 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/Messages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/Messages.properties @@ -65,10 +65,11 @@ CRenameRefactoringInputPage_button_inactiveCode=Inactive conditional compilation CRenameRefactoringInputPage_button_includes=Include directives CRenameRefactoringInputPage_button_macroDefinitions=Macro definitions CRenameRefactoringInputPage_button_preprocessor=Other preprocessor directives +CRenameRefactoringInputPage_button_strings=String literals +CRenameRefactoringInputPage_button_exhaustiveFileSearch=Exhaustive file search (slow) CRenameRefactoringInputPage_button_singleProject=Project CRenameRefactoringInputPage_button_relatedProjects=Related projects CRenameRefactoringInputPage_button_workspace=All projects -CRenameRefactoringInputPage_button_strings=String literals CRenameRefactoringInputPage_button_workingSet=Working set: CRenameRefactoringInputPage_errorInvalidIdentifier=''{0}'' is not a valid identifier CRenameRefactoringInputPage_label_newName=New Name: diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/TextSearchWrapper.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/TextSearchWrapper.java index f4841b71d02..12f8f7a2bf1 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/TextSearchWrapper.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/rename/TextSearchWrapper.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Markus Schorn - initial API and implementation + * Markus Schorn - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ 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.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; 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.ICElement; 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.Token; @@ -62,7 +65,7 @@ public class TextSearchWrapper { public final static int SCOPE_WORKING_SET = 5; private static class SearchScope extends TextSearchScope { - public static SearchScope newSearchScope(IWorkingSet ws) { + public static SearchScope newSearchScope(IWorkingSet ws, IResource[] filter) { IAdaptable[] adaptables= ws.getElements(); ArrayList resources = new ArrayList(); for (int i = 0; i < adaptables.length; i++) { @@ -72,18 +75,40 @@ public class TextSearchWrapper { 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) { - return new SearchScope(resources, copy); + public static SearchScope newSearchScope(IResource[] roots, IResource[] filter) { + if (filter != null) { + ArrayList files = new ArrayList(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 fFileMatcher= new ArrayList(); - private SearchScope(IResource[] resources, boolean copy) { - fRootResources= copy ? (IResource[]) resources.clone() : resources; + private SearchScope(IResource[] roots) { + fRootResources= roots; } @Override @@ -153,29 +178,30 @@ public class TextSearchWrapper { } } - public TextSearchWrapper() {} + public TextSearchWrapper() { + } - private TextSearchScope createSearchScope(IFile file, int scope, - String workingSetName, String[] patterns) { + private TextSearchScope createSearchScope(IFile file, int scope, String workingSetName, + IResource[] filter, String[] patterns) { switch (scope) { case SCOPE_WORKSPACE: - return defineSearchScope(file.getWorkspace().getRoot(), patterns); + return defineSearchScope(file.getWorkspace().getRoot(), filter, patterns); case SCOPE_SINGLE_PROJECT: - return defineSearchScope(file.getProject(), patterns); + return defineSearchScope(file.getProject(), filter, patterns); case SCOPE_FILE: - return defineSearchScope(file, patterns); + return defineSearchScope(file, filter, patterns); case SCOPE_WORKING_SET: { - TextSearchScope result= defineWorkingSetAsSearchScope(workingSetName, patterns); + TextSearchScope result= defineWorkingSetAsSearchScope(workingSetName, filter, patterns); if (result == null) { - result= defineSearchScope(file.getWorkspace().getRoot(), patterns); + result= defineSearchScope(file.getWorkspace().getRoot(), filter, patterns); } 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 projects= new HashSet(); LinkedList workThrough= new LinkedList(); workThrough.add(project); @@ -190,20 +216,20 @@ public class TextSearchWrapper { } } } - IResource[] resources= projects.toArray(new IResource[projects.size()]); - return defineSearchScope(resources, patterns); + IResource[] roots= projects.toArray(new IResource[projects.size()]); + return defineSearchScope(roots, filter, patterns); } - private TextSearchScope defineWorkingSetAsSearchScope(String wsName, String[] patterns) { - if (wsName == null) { + private TextSearchScope defineWorkingSetAsSearchScope(String workingSetName, IResource[] filter, String[] patterns) { + if (workingSetName == null) { return null; } IWorkingSetManager wsManager= PlatformUI.getWorkbench().getWorkingSetManager(); - IWorkingSet ws= wsManager.getWorkingSet(wsName); + IWorkingSet ws= wsManager.getWorkingSet(workingSetName); if (ws == null) { return null; } - SearchScope result= SearchScope.newSearchScope(ws); + SearchScope result= SearchScope.newSearchScope(ws, filter); applyFilePatterns(result, patterns); return result; } @@ -215,22 +241,32 @@ public class TextSearchWrapper { } } - private TextSearchScope defineSearchScope(IResource resource, String[] patterns) { - SearchScope result= SearchScope.newSearchScope(new IResource[] { resource }, false); + private TextSearchScope defineSearchScope(IResource root, IResource[] filter, String[] patterns) { + SearchScope result= SearchScope.newSearchScope(new IResource[] { root }, filter); applyFilePatterns(result, patterns); return result; } - private TextSearchScope defineSearchScope(IResource[] resources, String[] patterns) { - SearchScope result= SearchScope.newSearchScope(resources, true); + private TextSearchScope defineSearchScope(IResource[] roots, IResource[] filter, String[] patterns) { + SearchScope result= SearchScope.newSearchScope(roots, filter); applyFilePatterns(result, patterns); 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 target) { int startPos= target.size(); TextSearchEngine engine= TextSearchEngine.create(); @@ -243,7 +279,7 @@ public class TextSearchWrapper { 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() { @Override public boolean acceptPatternMatch(TextSearchMatchAccess access) {