From 617c5a8476de74553ba810858caf843a54ef01ce Mon Sep 17 00:00:00 2001 From: Ken Ryall Date: Fri, 18 Jan 2008 22:55:23 +0000 Subject: [PATCH] Bug 212166, search bug fixes. --- .../core/browser/util/IndexModelUtil.java | 4 + .../cdt/ui/tests/search/BasicSearchTest.java | 148 ++++++++++++++++-- .../internal/ui/search/CSearchMessages.java | 4 + .../ui/search/CSearchMessages.properties | 10 +- .../ui/search/IPDOMSearchContentProvider.java | 30 ++++ .../ui/search/PDOMSearchLabelProvider.java | 55 ++++++- .../search/PDOMSearchListContentProvider.java | 72 ++++++++- .../search/PDOMSearchListLabelProvider.java | 1 + .../internal/ui/search/PDOMSearchQuery.java | 23 ++- .../internal/ui/search/PDOMSearchResult.java | 23 ++- .../search/PDOMSearchTreeContentProvider.java | 21 ++- .../search/PDOMSearchTreeLabelProvider.java | 1 + .../ui/search/PDOMSearchViewPage.java | 70 +++++++++ 13 files changed, 441 insertions(+), 21 deletions(-) diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/IndexModelUtil.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/IndexModelUtil.java index fb7b880d10f..84b75199944 100644 --- a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/IndexModelUtil.java +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/IndexModelUtil.java @@ -20,6 +20,7 @@ import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.ICompositeType; import org.eclipse.cdt.core.dom.ast.IEnumeration; +import org.eclipse.cdt.core.dom.ast.IEnumerator; import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IParameter; import org.eclipse.cdt.core.dom.ast.ITypedef; @@ -132,6 +133,9 @@ public class IndexModelUtil { if (binding instanceof IVariable) { elementType = ICElement.C_VARIABLE; } + if (binding instanceof IEnumerator) { + elementType = ICElement.C_ENUMERATOR; + } return elementType; } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/search/BasicSearchTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/search/BasicSearchTest.java index f4d6c01a135..a54bede9abe 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/search/BasicSearchTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/search/BasicSearchTest.java @@ -8,6 +8,8 @@ * Contributors: * Andrew Ferguson (Symbian) - Initial implementation * Markus Schorn (Wind River Systems) + * IBM Corporation + * Ed Swartz (Nokia) *******************************************************************************/ package org.eclipse.cdt.ui.tests.search; @@ -20,6 +22,7 @@ import junit.framework.TestSuite; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.jface.operation.IRunnableContext; @@ -37,6 +40,7 @@ import org.osgi.framework.Bundle; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.IPDOMManager; +import org.eclipse.cdt.core.index.IIndexManager; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.testplugin.CProjectHelper; @@ -112,24 +116,148 @@ public class BasicSearchTest extends BaseUITestCase { StructuredViewer viewer= pdomsvp.getViewer(); ILabelProvider labpv= (ILabelProvider) viewer.getLabelProvider(); IStructuredContentProvider scp= (IStructuredContentProvider) viewer.getContentProvider(); - - String label0= labpv.getText(scp.getElements(result)[0]); - String label1= labpv.getText(scp.getElements(result)[1]); - - // the content provider does not sort the result, so we have to do it: - if (label0.compareTo(label1) < 0) { - String h= label0; label0= label1; label1= h; - } + + // project results are in a project node, containing directories and files + Object[] resultElements = scp.getElements(result); + String label0= labpv.getText(resultElements[0]); + // external results are in a tree, directory containing files + Object externalResult = resultElements[1]; + String path1= labpv.getText(externalResult); + String file1= labpv.getText(scp.getElements(externalResult)[0]); // check the results are rendered String expected0= fCProject.getProject().getName(); String expected1= new Path(externalFile.getAbsolutePath()).toString(); assertEquals(expected0,label0); - assertEquals(expected1,label1); + assertEquals(expected1,new Path(path1).append(file1).toString()); } + + // int x, y, xx, yy; + public void testNoIndexerEnabled_158955() throws Exception { + // rebuild the index with no indexer + CCorePlugin.getIndexManager().setIndexerId(fCProject, IIndexManager.ID_NO_INDEXER); + CCorePlugin.getIndexManager().reindex(fCProject); + assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000, new NullProgressMonitor())); + + // open a query + PDOMSearchQuery query= makeProjectQuery("x"); + PDOMSearchResult result= runQuery(query); + assertEquals(0, result.getElements().length); + + ISearchResultViewPart vp= NewSearchUI.getSearchResultView(); + ISearchResultPage page= vp.getActivePage(); + assertTrue(""+page, page instanceof PDOMSearchViewPage); + + PDOMSearchViewPage pdomsvp= (PDOMSearchViewPage) page; + StructuredViewer viewer= pdomsvp.getViewer(); + ILabelProvider labpv= (ILabelProvider) viewer.getLabelProvider(); + IStructuredContentProvider scp= (IStructuredContentProvider) viewer.getContentProvider(); + + // first result is a project node + Object firstRootNode = scp.getElements(result)[0]; + String label0= labpv.getText(firstRootNode); + // ... containing a status message + IStatus firstRootChildNode= (IStatus) scp.getElements(firstRootNode)[0]; + + assertEquals(IStatus.WARNING, firstRootChildNode.getSeverity()); + // can't really verify text in case message is localized... + } + + final int INDEXER_IN_PROGRESS_FILE_COUNT = 10; + final int INDEXER_IN_PROGRESS_STRUCT_COUNT = 100; + + // #include "hugeHeader0.h" + + public void testIndexerInProgress() throws Exception { + // make an external file + File dir= CProjectHelper.freshDir(); + + // make other project files so we can get incomplete results during indexing + for (int i = 1; i < 10; i++) { + TestSourceReader.createFile(fCProject.getProject(), new Path("references" + i + ".cpp"), + "#include \"hugeHeader" + i + ".h\"\n"); + } + + for (int f = 0; f < INDEXER_IN_PROGRESS_FILE_COUNT; f++) { + File externalFile= new File(dir, "hugeHeader" + f + ".h"); + externalFile.deleteOnExit(); + FileWriter fw= new FileWriter(externalFile); + for (int i = 0; i < INDEXER_IN_PROGRESS_STRUCT_COUNT; i++) { + fw.write("typedef struct confusingType_" + f + "_" + i + " {\n"); + if (i == 0) + fw.write(" void *data" + i + ";\n"); + else + fw.write(" myConfusingType_" + f + "_" + (i-1) +" *data" + i + ";\n"); + fw.write(" int a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;\n"); + fw.write("} myConfusingType_" + f + "_" + i + ";\n"); + } + fw.close(); + } + + // rebuild the index and DO NOT JOIN + TestScannerProvider.sIncludes= new String[] {dir.getAbsolutePath()}; + CCorePlugin.getIndexManager().reindex(fCProject); + + // immediate test, likely 0 matches + coreTestIndexerInProgress(false); + + // wait some amount of time to get non-zero and hopefully non-complete results + Thread.sleep(500); + if (!CCorePlugin.getIndexManager().isIndexerIdle()) + coreTestIndexerInProgress(false); + + // now join and test again to get the full results + assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000, new NullProgressMonitor())); + + coreTestIndexerInProgress(true); + } /** - * Run the specified query, and return the result. When this method returns the + * + */ + private void coreTestIndexerInProgress(boolean expectComplete) { + // open a query + PDOMSearchQuery query= makeProjectQuery("data*"); + PDOMSearchResult result= runQuery(query); + + final int maximumHits = INDEXER_IN_PROGRESS_FILE_COUNT * INDEXER_IN_PROGRESS_STRUCT_COUNT; + Object[] elements = result.getElements(); + if (expectComplete) + assertEquals(maximumHits, elements.length); + else + assertTrue(maximumHits >= elements.length); // >= because may still be done + + ISearchResultViewPart vp= NewSearchUI.getSearchResultView(); + ISearchResultPage page= vp.getActivePage(); + assertTrue(""+page, page instanceof PDOMSearchViewPage); + + PDOMSearchViewPage pdomsvp= (PDOMSearchViewPage) page; + StructuredViewer viewer= pdomsvp.getViewer(); + ILabelProvider labpv= (ILabelProvider) viewer.getLabelProvider(); + IStructuredContentProvider scp= (IStructuredContentProvider) viewer.getContentProvider(); + + if (!expectComplete) { + // even if we don't think the indexer is complete, we can't be 100% sure + // the indexer didn't finish before the query started, so don't fail here + // if all the hits were found + if (elements.length < maximumHits) { + // first result is an IStatus indicating indexer was busy + IStatus firstRootNode = (IStatus) scp.getElements(result)[0]; + + assertEquals(IStatus.WARNING, firstRootNode.getSeverity()); + // can't really verify text in case message is localized... + } + } else { + // must NOT have the IStatus + Object firstRootNode = scp.getElements(result)[0]; + + assertFalse(firstRootNode instanceof IStatus); + } + + } + + /** + * Run the specified query, and return the result. When tehis method returns the * search page will have been opened. * @param query * @return diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/CSearchMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/CSearchMessages.java index 1ce68cc7f22..28243c35948 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/CSearchMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/CSearchMessages.java @@ -85,6 +85,10 @@ public final class CSearchMessages extends NLS { public static String OccurrencesFinder_occurrence_description; public static String OccurrencesFinder_occurrence_write_description; + public static String PDOMSearchListContentProvider_IndexerNotEnabledMessageFormat; + public static String PDOMSearchListContentProvider_ProjectClosedMessageFormat; + public static String CSearchMessages_IndexRunningIncompleteWarning; + static { NLS.initializeMessages(BUNDLE_NAME, CSearchMessages.class); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/CSearchMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/CSearchMessages.properties index c203f44dc45..04967f72f7a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/CSearchMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/CSearchMessages.properties @@ -7,6 +7,7 @@ # # Contributors: # IBM Corporation - initial API and implementation +# Ed Swartz (Nokia) ############################################################################### group_declarations=Dec&larations @@ -15,7 +16,7 @@ group_references=Re&ferences # Examples of the display for the following value are # "(1 match)", where {0} is 1 and "(5 matches)", where {0} is 2 or more. -CSearchResultCollector_matches= ({0} {0, choice, 1\#match|2\#matches}) +CSearchResultCollector_matches= ({0} {0, choice, 0\#matches|1\#match|2\#matches}) CSearchPage_searchFor_label= Search For CSearchPage_searchFor_type= &Type @@ -75,6 +76,12 @@ PDOMSearch_query_refs_label = Find references to PDOMSearch_query_defs_label = Find definitions of PDOMSearch_query_decls_label = Find declarations of PDOMSearchPatternQuery_PatternQuery_labelPatternInScope={0} {1} in {2} +PDOMSearchTreeContentProvider_IndexerNotEnabledWarning=(unknown results: indexer is not enabled) +PDOMSearchTreeContentProvider_ProjectClosedWarning=(unknown results: project is closed) +PDOMSearchListContentProvider_IndexerNotEnabledMessageFormat=(project ''{0}'' - unknown results: indexer is not enabled) +PDOMSearchListContentProvider_ProjectClosedMessageFormat=(project ''{0}'' - unknown results: project is closed) +PDOMSearchTreeLabelProvider_URIContainerLabel=URIs +CSearchMessages_IndexRunningIncompleteWarning=(incomplete or inaccurate results: indexer was busy during search) PDOMSearch_query_pattern_error = Illegal Search String SelectionParseAction_FileOpenFailure_format=Could not open file ''{0}'', verify index is up-to-date SelectionParseAction_SelectedTextNotSymbol_message=Selected text cannot be mapped to a symbol name @@ -91,3 +98,4 @@ OccurrencesFinder_label_singular=''{0}'' - 1 occurrence in ''{1}'' OccurrencesFinder_label_plural=''{0}'' - {1} occurrences in ''{2}'' OccurrencesFinder_occurrence_description=Occurrence of ''{0}'' OccurrencesFinder_occurrence_write_description=Write occurrence of ''{0}'' +PDOMSearchLabelProvider_FileAndPathFormat={0} ({1}) diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/IPDOMSearchContentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/IPDOMSearchContentProvider.java index b47d4307fe3..df184fa8483 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/IPDOMSearchContentProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/IPDOMSearchContentProvider.java @@ -7,16 +7,46 @@ * * Contributors: * QNX - Initial API and implementation + * Ed Swartz (Nokia) *******************************************************************************/ package org.eclipse.cdt.internal.ui.search; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +import org.eclipse.cdt.ui.CUIPlugin; + /** + * The content in the tree and list views may be either: + *

+ * IStatus - warnings or errors from the search
+ * ICElement - for C/C++ elements, including TUs, folders, projects
+ * IPath - directory container, full path
+ * IIndexFileLocation - for file entries inside IPath directory containers
+ * {@link IPDOMSearchContentProvider#URI_CONTAINER} - container for URIs + * URI - from IIndexFileLocations not resolvable to the local filesystem, under URI_CONTAINER
* @author Doug Schaefer + * @author Ed Swartz * */ public interface IPDOMSearchContentProvider { + /** This node encapsulates results in the search tree for results not resolvable to files. */ + static Object URI_CONTAINER = new Object(); + + /** This node appears in the tree when the indexer was running during the search + * to warn the user that the results are suspicious. + *

+ * TODO: it would be better if IIndexManager told us which projects specifically + * were being indexed at the time, so we could annotate per-project whose results are suspicious + * (which may be none at all for a given search). + * See the handling of {@link PDOMSearchResult#wasIndexerBusy()}. + */ + static IStatus INCOMPLETE_RESULTS_NODE = + new Status(IStatus.WARNING, CUIPlugin.PLUGIN_ID, + CSearchMessages.CSearchMessages_IndexRunningIncompleteWarning); + public void elementsChanged(Object[] elements); public void clear(); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchLabelProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchLabelProvider.java index 1da11060411..9ab080db056 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchLabelProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchLabelProvider.java @@ -7,14 +7,20 @@ * * Contributors: * Markus Schorn - initial API and implementation + * Ed Swartz (Nokia) *******************************************************************************/ package org.eclipse.cdt.internal.ui.search; +import java.net.URI; + import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.search.ui.text.AbstractTextSearchViewPage; import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.index.IndexLocationFactory; @@ -25,7 +31,16 @@ import org.eclipse.cdt.internal.ui.viewsupport.CElementImageProvider; import org.eclipse.cdt.internal.ui.viewsupport.CUILabelProvider; /** + * The content in the tree and list views may be either: + *

+ * IStatus - warnings or errors from the search
+ * ICElement - for C/C++ elements, including TUs, folders, projects
+ * IPath - directory container, full path
+ * IIndexFileLocation - for file entries inside IPath directory containers
+ * {@link IPDOMSearchContentProvider#URI_CONTAINER} - container for URIs
+ * URI - for IIndexFileLocations not resolvable to the local filesystem, under URI_CONTAINER
* @author Doug Schaefer + * @author Ed Swartz * */ public class PDOMSearchLabelProvider extends LabelProvider { @@ -44,10 +59,33 @@ public class PDOMSearchLabelProvider extends LabelProvider { if (element instanceof PDOMSearchElement) return fTypeInfoLabelProvider.getImage(((PDOMSearchElement)element).getTypeInfo()); - if (element instanceof IIndexFileLocation) { + if (element instanceof IIndexFileLocation + || element instanceof URI) { return CPluginImages.get(CPluginImages.IMG_OBJS_INCLUDE); } + if (element == IPDOMSearchContentProvider.URI_CONTAINER) { + // TODO: perhaps a better icon? + return CPluginImages.get(CPluginImages.IMG_OBJS_INCLUDES_CONTAINER); + } + + if (element instanceof IPath) { + return CPluginImages.get(CPluginImages.IMG_OBJS_INCLUDES_FOLDER); + } + + if (element instanceof IStatus) { + IStatus status = (IStatus) element; + ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); + switch (status.getSeverity()) { + case IStatus.WARNING: + return sharedImages.getImage(ISharedImages.IMG_OBJS_WARN_TSK); + case IStatus.ERROR: + return sharedImages.getImage(ISharedImages.IMG_OBJS_ERROR_TSK); + default: + return sharedImages.getImage(ISharedImages.IMG_OBJS_INFO_TSK); + } + } + return fCElementLabelProvider.getImage(element); } @@ -56,13 +94,26 @@ public class PDOMSearchLabelProvider extends LabelProvider { return fTypeInfoLabelProvider.getText(((PDOMSearchElement)element).getTypeInfo()); } + if (element instanceof IPath) { + return ((IPath) element).toString(); + } + if (element instanceof IIndexFileLocation) { IPath path= IndexLocationFactory.getPath((IIndexFileLocation)element); if(path!=null) { - return path.toString(); + // these are categorized into directories already + return path.lastSegment(); } } + if (element instanceof URI) { + return ((URI)element).toString(); + } + + if (element instanceof IStatus) { + return ((IStatus) element).getMessage(); + } + return fCElementLabelProvider.getText(element); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchListContentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchListContentProvider.java index 41a3138a7cc..98ba06bd943 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchListContentProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchListContentProvider.java @@ -7,14 +7,30 @@ * * Contributors: * QNX - Initial API and implementation + * Ed Swartz (Nokia) *******************************************************************************/ package org.eclipse.cdt.internal.ui.search; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; +import com.ibm.icu.text.MessageFormat; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.ui.CUIPlugin; + /** * @author Doug Schaefer * @@ -26,7 +42,60 @@ public class PDOMSearchListContentProvider implements private PDOMSearchResult result; public Object[] getElements(Object inputElement) { - return result.getElements(); + Set uncoveredProjects = new HashSet(); + + PDOMSearchResult result = (PDOMSearchResult) inputElement; + + Object[] results = result.getElements(); + List resultList = new ArrayList(Arrays.asList(results)); + + // see if indexer was busy + if (result.wasIndexerBusy()) { + resultList.add(IPDOMSearchContentProvider.INCOMPLETE_RESULTS_NODE); + } + + // see which projects returned results + for (int i = 0; i < results.length; i++) { + if (results[i] instanceof PDOMSearchElement) { + PDOMSearchElement searchElement = (PDOMSearchElement) results[i]; + String path = searchElement.getLocation().getFullPath(); + if (path != null) { + uncoveredProjects.add(new Path(path).segment(0)); + } + } + } + + // add message for all the projects which have no results + ICProject[] projects = ((PDOMSearchQuery)result.getQuery()).getProjects(); + for (int i = 0; i < projects.length; ++i) { + ICProject project = projects[i]; + boolean foundProject = uncoveredProjects.contains(project.getProject().getName()); + if (!foundProject) { + if (project.isOpen()) { + if (!CCorePlugin.getIndexManager().isProjectIndexed(project)) { + resultList.add(createUnindexedProjectWarningElement(project)); + } + } else { + resultList.add(createClosedProjectWarningElement(project)); + } + } + } + + return resultList.toArray(); + } + + private Status createUnindexedProjectWarningElement(ICProject project) { + return new Status(IStatus.WARNING, CUIPlugin.PLUGIN_ID, + MessageFormat.format( + CSearchMessages.PDOMSearchListContentProvider_IndexerNotEnabledMessageFormat, + new Object[] { project.getProject().getName() })); + } + + private Status createClosedProjectWarningElement(ICProject project) { + return new Status(IStatus.WARNING, CUIPlugin.PLUGIN_ID, + MessageFormat.format( + CSearchMessages.PDOMSearchListContentProvider_ProjectClosedMessageFormat, + new Object[] { project.getProject().getName() })); } public void dispose() { @@ -35,6 +104,7 @@ public class PDOMSearchListContentProvider implements public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { this.viewer = (TableViewer)viewer; result = (PDOMSearchResult)newInput; + viewer.refresh(); } public void elementsChanged(Object[] elements) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchListLabelProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchListLabelProvider.java index 6fccadd3009..330916afc63 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchListLabelProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchListLabelProvider.java @@ -8,6 +8,7 @@ * Contributors: * QNX - Initial API and implementation * Markus Schorn (Wind River Systems) + * Ed Swartz (Nokia) *******************************************************************************/ package org.eclipse.cdt.internal.ui.search; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchQuery.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchQuery.java index f63623bbee1..895e5088d15 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchQuery.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchQuery.java @@ -8,6 +8,7 @@ * Contributors: * QNX - Initial API and implementation * Markus Schorn (Wind River Systems) + * Ed Swartz (Nokia) *******************************************************************************/ package org.eclipse.cdt.internal.ui.search; @@ -32,6 +33,7 @@ import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.ui.CUIPlugin; /** @@ -59,7 +61,16 @@ public abstract class PDOMSearchQuery implements ISearchQuery { try { if (scope == null) { // All CDT projects in workspace - projects = CoreModel.getDefault().getCModel().getCProjects(); + ICProject[] allProjects = CoreModel.getDefault().getCModel().getCProjects(); + + // Filter out closed projects for this case + for (int i = 0; i < allProjects.length; i++) { + if (!allProjects[i].isOpen()) { + allProjects[i] = null; + } + } + + projects = (ICProject[]) ArrayUtil.removeNulls(ICProject.class, allProjects); } else { Map projectMap = new HashMap(); @@ -131,6 +142,8 @@ public abstract class PDOMSearchQuery implements ISearchQuery { PDOMSearchResult result= (PDOMSearchResult) getSearchResult(); result.removeAll(); + result.setIndexerBusy(!CCorePlugin.getIndexManager().isIndexerIdle()); + try { IIndex index= CCorePlugin.getIndexManager().getIndex(projects, 0); try { @@ -150,4 +163,12 @@ public abstract class PDOMSearchQuery implements ISearchQuery { } abstract protected IStatus runWithIndex(IIndex index, IProgressMonitor monitor); + + /** + * Get the projects involved in the search. + * @return array, never null + */ + public ICProject[] getProjects() { + return projects; + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchResult.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchResult.java index 2828243be78..0c51c35d96f 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchResult.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchResult.java @@ -8,6 +8,7 @@ * Contributors: * QNX - Initial API and implementation * Markus Schorn (Wind River Systems) + * Ed Swartz (Nokia) *******************************************************************************/ package org.eclipse.cdt.internal.ui.search; @@ -40,6 +41,7 @@ import org.eclipse.cdt.core.index.IndexLocationFactory; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.internal.ui.util.ExternalEditorInput; +import org.eclipse.cdt.internal.ui.util.Messages; /** * @author Doug Schaefer @@ -48,6 +50,7 @@ import org.eclipse.cdt.internal.ui.util.ExternalEditorInput; public class PDOMSearchResult extends AbstractTextSearchResult implements IEditorMatchAdapter, IFileMatchAdapter { private PDOMSearchQuery query; + private boolean indexerBusy; public PDOMSearchResult(PDOMSearchQuery query) { super(); @@ -152,7 +155,10 @@ public class PDOMSearchResult extends AbstractTextSearchResult implements IEdito } public String getLabel() { - return query.getLabel(); + // report pattern and number of matches + String label = query.getLabel(); + String countLabel = Messages.format(CSearchMessages.CSearchResultCollector_matches, new Integer(getElements().length)); + return label + " " + countLabel; //$NON-NLS-1$ } public String getTooltip() { @@ -167,4 +173,19 @@ public class PDOMSearchResult extends AbstractTextSearchResult implements IEdito return query; } + /** + * Remember whether the indexer was busy when the search was performed. + * @param b + */ + public void setIndexerBusy(boolean b) { + this.indexerBusy = b; + } + + /** + * Tell if the indexer was busy when search results were gathered. + */ + public boolean wasIndexerBusy() { + return indexerBusy; + } + } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchTreeContentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchTreeContentProvider.java index 0e81e3eeb1c..c9874ac3d0c 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchTreeContentProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchTreeContentProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2007 QNX Software Systems and others. + * Copyright (c) 2006, 2008 QNX Software Systems 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 @@ -8,6 +8,7 @@ * Contributors: * QNX - Initial API and implementation * Markus Schorn (Wind River Systems) + * Ed Swartz (Nokia) *******************************************************************************/ package org.eclipse.cdt.internal.ui.search; @@ -43,7 +44,7 @@ public class PDOMSearchTreeContentProvider implements ITreeContentProvider, IPDO private TreeViewer viewer; private PDOMSearchResult result; private Map tree = new HashMap(); - + public Object[] getChildren(Object parentElement) { Set children = (Set)tree.get(parentElement); if (children == null) @@ -67,7 +68,7 @@ public class PDOMSearchTreeContentProvider implements ITreeContentProvider, IPDO } public Object[] getElements(Object inputElement) { - return getChildren(result); + return getChildren(inputElement); } public void dispose() { @@ -115,8 +116,18 @@ public class PDOMSearchTreeContentProvider implements ITreeContentProvider, IPDO } } if (!handled) { - insertChild(element.getLocation(), element); - insertChild(result, element.getLocation()); + // insert a folder and then the file under that + IPath path = IndexLocationFactory.getAbsolutePath(location); + if (path != null) { + IPath directory = path.removeLastSegments(1); + insertChild(location, element); + insertChild(directory, location); + insertChild(result, directory); + } else { + // URI not representable as a file + insertChild(IPDOMSearchContentProvider.URI_CONTAINER, location.getURI()); + insertChild(result, IPDOMSearchContentProvider.URI_CONTAINER); + } } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchTreeLabelProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchTreeLabelProvider.java index a90aac653d1..34cebb0c3a8 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchTreeLabelProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchTreeLabelProvider.java @@ -8,6 +8,7 @@ * Contributors: * QNX - Initial API and implementation * Markus Schorn (Wind River Systems) + * Ed Swartz (Nokia) *******************************************************************************/ package org.eclipse.cdt.internal.ui.search; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchViewPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchViewPage.java index f558086b39a..18805df10e9 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchViewPage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchViewPage.java @@ -7,15 +7,20 @@ * * Contributors: * QNX - Initial API and implementation + * Ed Swartz (Nokia) *******************************************************************************/ package org.eclipse.cdt.internal.ui.search; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.search.ui.text.AbstractTextSearchViewPage; import org.eclipse.search.ui.text.Match; import org.eclipse.ui.IEditorPart; @@ -24,6 +29,7 @@ import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.index.IndexLocationFactory; +import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.internal.ui.util.EditorUtility; @@ -54,14 +60,78 @@ public class PDOMSearchViewPage extends AbstractTextSearchViewPage { contentProvider.clear(); } + /** + * Supply a sorter for the list and tree content providers to supply some order to the + * large numbers of matches that may result. + *

+ * This sorter categorizes the different kinds of ICElement matches (as well as IStatus + * messages and External Files groups) to place them in groups. The items within a + * category are sorted in the default way {@link ViewerSorter#compare(Viewer, Object, Object)} works, + * by comparing text labels. + *

+ * A potential concern here is that, in sorting the elements by name, the user may + * find himself randomly jumping around a file when navigating search results in order. + * As this only happens when a search matches different identifiers or identifiers of + * different types, and since the user can use a textual search within a file to navigate + * the same results (ignoring extraneous hits in comments or disabled code), I argue it's not + * a big deal. Furthermore, usually it would be a wildcard search that would result in + * this situation -- indicating the user doesn't know the identifier and wants to find it using + * search. In such a case, a sorted list of results in much more friendly to navigate. + * @author eswartz + * + */ + private class SearchViewerComparator extends ViewerComparator { + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ViewerComparator#category(java.lang.Object) + */ + public int category(Object element) { + // place status messages first + if (element instanceof IStatus) { + return -1000; + } + + // keep elements of the same type together + if (element instanceof PDOMSearchElement) { + PDOMSearchElement searchElement = (PDOMSearchElement)element; + int type = searchElement.getTypeInfo().getCElementType(); + // handle unknown types + if (type < 0) { + type = 0; + } + return type; + } else if (element instanceof ICElement) { + int type = ((ICElement) element).getElementType(); + // handle unknown types + if (type < 0) { + type = 0; + } + return Math.min(Math.max(0, type), 900); + } + + // place external folders next to last + if (element instanceof IPath || element instanceof IIndexFileLocation) { + return 999; + } + + // place external file matches last + if (element == IPDOMSearchContentProvider.URI_CONTAINER) { + return 1000; + } + + return 2000; + } + } + protected void configureTreeViewer(TreeViewer viewer) { contentProvider = new PDOMSearchTreeContentProvider(); + viewer.setComparator(new SearchViewerComparator()); viewer.setContentProvider((PDOMSearchTreeContentProvider)contentProvider); viewer.setLabelProvider(new PDOMSearchTreeLabelProvider(this)); } protected void configureTableViewer(TableViewer viewer) { contentProvider = new PDOMSearchListContentProvider(); + viewer.setComparator(new SearchViewerComparator()); viewer.setContentProvider((PDOMSearchListContentProvider)contentProvider); viewer.setLabelProvider(new PDOMSearchListLabelProvider(this)); }