From f6a9f8da2286a132cd225d6f3730527bb8c26db5 Mon Sep 17 00:00:00 2001 From: Alain Magloire Date: Wed, 7 Apr 2004 00:32:13 +0000 Subject: New patch from Chris Wiebe to boost the performance of the TypeInfo, a separation is done via the Core and UI to provide more flexibility for clients using this service. --- core/org.eclipse.cdt.core/.classpath | 1 + core/org.eclipse.cdt.core/ChangeLog | 10 + core/org.eclipse.cdt.core/browser/ChangeLog | 2 + .../eclipse/cdt/core/browser/AllTypesCache.java | 295 +++++++++++ .../org/eclipse/cdt/core/browser/ITypeInfo.java | 112 ++++ .../org/eclipse/cdt/core/browser/TypeInfo.java | 430 ++++++++++++++++ .../cdt/internal/core/browser/cache/TypeCache.java | 152 ++++++ .../core/browser/cache/TypeCacheMessages.java | 50 ++ .../browser/cache/TypeCacheMessages.properties | 13 + .../internal/core/browser/cache/TypeCacherJob.java | 204 ++++++++ .../core/browser/cache/TypeMatchCollector.java | 55 ++ .../core/browser/cache/TypeMatchLocator.java | 561 +++++++++++++++++++++ .../browser/cache/TypeSearchPathCollector.java | 79 +++ .../core/browser/cache/TypeSearchPattern.java | 40 ++ .../cdt/internal/core/browser/util/ArrayUtil.java | 53 ++ .../browser/util/DelegatedProgressMonitor.java | 228 +++++++++ .../cdt/internal/core/browser/util/PathUtil.java | 40 ++ .../internal/core/browser/util/SimpleStack.java | 74 +++ core/org.eclipse.cdt.core/build.properties | 4 +- core/org.eclipse.cdt.ui/ChangeLog | 9 + .../ui/browser/opentype/OpenTypeAction.java | 57 ++- .../ui/browser/opentype/OpenTypeDialog.java | 121 +---- .../cdt/internal/ui/browser/util/ArrayUtil.java | 47 -- .../browser/util/ProgressMonitorMultiWrapper.java | 233 --------- .../cdt/ui/browser/typeinfo/AllTypesCache.java | 483 ------------------ .../eclipse/cdt/ui/browser/typeinfo/ITypeInfo.java | 76 --- .../cdt/ui/browser/typeinfo/ITypeInfoFilter.java | 36 -- .../eclipse/cdt/ui/browser/typeinfo/TypeInfo.java | 210 -------- .../cdt/ui/browser/typeinfo/TypeInfoFilter.java | 43 -- .../ui/browser/typeinfo/TypeInfoLabelProvider.java | 68 +-- .../browser/typeinfo/TypeInfoMessages.properties | 11 +- .../ui/browser/typeinfo/TypeSelectionDialog.java | 464 +++++++++++++++-- .../src/org/eclipse/cdt/ui/CUIPlugin.java | 9 +- 33 files changed, 2924 insertions(+), 1346 deletions(-) create mode 100644 core/org.eclipse.cdt.core/browser/ChangeLog create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/AllTypesCache.java create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeInfo.java create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/TypeInfo.java create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCache.java create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.java create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.properties create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacherJob.java create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchCollector.java create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchLocator.java create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPathCollector.java create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPattern.java create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/ArrayUtil.java create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/DelegatedProgressMonitor.java create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/PathUtil.java create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/SimpleStack.java delete mode 100644 core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/util/ArrayUtil.java delete mode 100644 core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/util/ProgressMonitorMultiWrapper.java delete mode 100644 core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/AllTypesCache.java delete mode 100644 core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/ITypeInfo.java delete mode 100644 core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/ITypeInfoFilter.java delete mode 100644 core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfo.java delete mode 100644 core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoFilter.java diff --git a/core/org.eclipse.cdt.core/.classpath b/core/org.eclipse.cdt.core/.classpath index 5234ce90362..9d6202a599d 100644 --- a/core/org.eclipse.cdt.core/.classpath +++ b/core/org.eclipse.cdt.core/.classpath @@ -7,6 +7,7 @@ + diff --git a/core/org.eclipse.cdt.core/ChangeLog b/core/org.eclipse.cdt.core/ChangeLog index 053ad6f918b..05d287d0928 100644 --- a/core/org.eclipse.cdt.core/ChangeLog +++ b/core/org.eclipse.cdt.core/ChangeLog @@ -1,3 +1,13 @@ +2004-04-06 Alain Magloire + + Patch from Chris Wiebe. + This patch provides some improvements to the Open Type action, such as + per-file type caching (much faster now) and extra filtering options in + the dialog. The non-ui code has also been isolated and moved to + org.eclipse.cdt.core.browser. + + * browser/* + 2004-04-06 Alain Magloire Patch from Sam Robb covering part of PR #52864 diff --git a/core/org.eclipse.cdt.core/browser/ChangeLog b/core/org.eclipse.cdt.core/browser/ChangeLog new file mode 100644 index 00000000000..9ac76acefe8 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/ChangeLog @@ -0,0 +1,2 @@ +2004-04-06 Chris Wiebe + initial placement of non-ui code into org.eclipse.cdt.core.browser diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/AllTypesCache.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/AllTypesCache.java new file mode 100644 index 00000000000..1257fa18cae --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/AllTypesCache.java @@ -0,0 +1,295 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.browser; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ElementChangedEvent; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICElementDelta; +import org.eclipse.cdt.core.model.IElementChangedListener; +import org.eclipse.cdt.core.model.IWorkingCopy; +import org.eclipse.cdt.core.search.ICSearchScope; +import org.eclipse.cdt.core.search.SearchEngine; +import org.eclipse.cdt.internal.core.browser.cache.TypeCache; +import org.eclipse.cdt.internal.core.browser.cache.TypeCacherJob; +import org.eclipse.cdt.internal.core.browser.util.ArrayUtil; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.jobs.Job; + +/** + * Manages a search cache for types in the workspace. Instead of returning objects of type ICElement + * the methods of this class returns a list of the lightweight objects TypeInfo. + *

+ * AllTypesCache runs asynchronously using a background job to rebuild the cache as needed. + * If the cache becomes dirty again while the background job is running, the job is restarted. + *

+ * If getTypes is called in response to a user action, a progress dialog is shown. + * If called before the background job has finished, getTypes waits + * for the completion of the background job. + */ +public class AllTypesCache { + + private static final int INITIAL_DELAY= 5000; + private static TypeCache fgCache; + private static TypeCacherJob fgJob; + private static TypeCacheDeltaListener fgDeltaListener; + + /** + * Defines a simple interface in order to provide + * a level of abstraction between the Core and UI + * code. + */ + public static interface IWorkingCopyProvider { + public IWorkingCopy[] getWorkingCopies(); + } + + /** + * Initializes the AllTypesCache service. + * + * @param provider A working copy provider. + */ + public static void initialize(IWorkingCopyProvider provider) { + fgCache= new TypeCache(); + fgJob= new TypeCacherJob(fgCache, provider); + fgDeltaListener= new TypeCacheDeltaListener(fgCache, fgJob); + + // add delta listener + CoreModel.getDefault().addElementChangedListener(fgDeltaListener); + + // schedule job to run after INITIAL_DELAY + if (fgJob.getState() != Job.RUNNING) { + fgJob.setSearchPaths(null); + fgJob.setPriority(Job.BUILD); + fgJob.schedule(INITIAL_DELAY); + } + } + + /** + * Terminates the service provided by AllTypesCache. + */ + public static void terminate() { + // remove delta listener + CoreModel.getDefault().removeElementChangedListener(fgDeltaListener); + + // terminate background job + fgJob.cancel(); + } + + /* + * Returns the actual type cache. + */ + public static TypeCache getCache() { + return fgCache; + } + + /** + * Returns true if the type cache is up to date. + */ + public static boolean isCacheUpToDate() { + return !fgCache.isDirty(); + } + + /** + * Returns all types in the given scope. + * @param scope The search scope + * @param kinds Array containing CElement types: + * C_NAMESPACE, C_CLASS, C_UNION, C_ENUMERATION, C_TYPEDEF + * @param monitor Progress monitor to display search progress + * @param typesFound The resulting TypeInfo elements are added to this collection + */ + public static void getTypes(ICSearchScope scope, int[] kinds, IProgressMonitor monitor, Collection typesFound) { + if (!isCacheUpToDate()) { + // start job if not already running + if (fgJob.getState() != Job.RUNNING) { + // boost priority since action was user-initiated + fgJob.setSearchPaths(null); + fgJob.setPriority(Job.SHORT); + fgJob.schedule(); + } + + // wait for job to finish + try { + fgJob.join(monitor); + if (monitor != null) + monitor.done(); + } catch (InterruptedException ex) { + return; + } + } + + boolean isWorkspaceScope= scope.equals(SearchEngine.createWorkspaceScope()); + for (Iterator typesIter= fgCache.getAllTypes().iterator(); typesIter.hasNext(); ) { + ITypeInfo info= (ITypeInfo) typesIter.next(); + if ( ArrayUtil.contains(kinds, info.getType()) && + (isWorkspaceScope || info.isEnclosed(scope)) ) { + typesFound.add(info); + } + } + } + + /** + * Listener for changes to CModel. + * @see org.eclipse.cdt.core.model.IElementChangedListener + * @since 3.0 + */ + private static class TypeCacheDeltaListener implements IElementChangedListener { + + private TypeCache fTypeCache; + private TypeCacherJob fTypeCacherJob; + private Set fPaths= new HashSet(5); + private Set fPrefixes= new HashSet(5); + private boolean fFlushAll= false; + + public TypeCacheDeltaListener(TypeCache cache, TypeCacherJob job) { + fTypeCache= cache; + fTypeCacherJob= job; + } + + /* + * @see IElementChangedListener#elementChanged + */ + public void elementChanged(ElementChangedEvent event) { + fPaths.clear(); + fPrefixes.clear(); + fFlushAll= false; + + boolean needsFlushing= processDelta(event.getDelta()); + if (needsFlushing) { + // cancel background job + if (fTypeCacherJob.getState() == Job.RUNNING) { + // wait for job to finish? + try { + fTypeCacherJob.cancel(); + fTypeCacherJob.join(); + } catch (InterruptedException ex) { + } + } + + if (fFlushAll) { + // flush the entire cache + fTypeCacherJob.setSearchPaths(null); + fTypeCache.flushAll(); + } else { + // flush affected files from cache + Set searchPaths= new HashSet(10); + getPrefixMatches(fPrefixes, searchPaths); + searchPaths.addAll(fPaths); + fTypeCacherJob.setSearchPaths(searchPaths); + fTypeCache.flush(searchPaths); + } + + // restart the background job + fTypeCacherJob.setPriority(Job.BUILD); + fTypeCacherJob.schedule(); + } + } + + /* + * returns true if the cache needs to be flushed + */ + private boolean processDelta(ICElementDelta delta) { + ICElement elem= delta.getElement(); + int pathEntryChanged= ICElementDelta.F_ADDED_PATHENTRY_SOURCE | ICElementDelta.F_REMOVED_PATHENTRY_SOURCE | + ICElementDelta.F_CHANGED_PATHENTRY_INCLUDE | ICElementDelta.F_CHANGED_PATHENTRY_MACRO; + boolean isAddedOrRemoved= (delta.getKind() != ICElementDelta.CHANGED) + || ((delta.getFlags() & pathEntryChanged) != 0); + + switch (elem.getElementType()) { + case ICElement.C_MODEL: + { + if (isAddedOrRemoved) { + // CModel has changed + // flush the entire cache + fFlushAll= true; + return true; + } + return processDeltaChildren(delta); + } + + case ICElement.C_PROJECT: + case ICElement.C_CCONTAINER: + { + if (isAddedOrRemoved) { + // project or folder has changed + // flush all files with matching prefix + IPath path= elem.getPath(); + if (path != null) + fPrefixes.add(path); + return true; + } + return processDeltaChildren(delta); + } + + case ICElement.C_NAMESPACE: + case ICElement.C_TEMPLATE_CLASS: + case ICElement.C_CLASS: + case ICElement.C_STRUCT: + case ICElement.C_UNION: + case ICElement.C_ENUMERATION: + case ICElement.C_TYPEDEF: + case ICElement.C_INCLUDE: + case ICElement.C_UNIT: + { + if (isAddedOrRemoved) { + // CElement has changed + // flush file from cache + IPath path= elem.getPath(); + if (path != null) + fPaths.add(path); + return true; + } + return processDeltaChildren(delta); + } + + default: + // fields, methods, imports ect + return false; + } + } + + private boolean processDeltaChildren(ICElementDelta delta) { + ICElementDelta[] children= delta.getAffectedChildren(); + for (int i= 0; i < children.length; i++) { + if (processDelta(children[i])) { + return true; + } + } + return false; + } + + private boolean getPrefixMatches(Set prefixes, Set results) { + Set pathSet= fTypeCache.getAllFiles(); + if (pathSet.isEmpty() || prefixes == null || prefixes.isEmpty()) + return false; + + for (Iterator pathIter= pathSet.iterator(); pathIter.hasNext(); ) { + IPath path= (IPath) pathIter.next(); + + // find paths which match prefix + for (Iterator prefixIter= prefixes.iterator(); prefixIter.hasNext(); ) { + IPath prefix= (IPath) prefixIter.next(); + if (prefix.isPrefixOf(path)) { + results.add(path); + break; + } + } + } + + return !results.isEmpty(); + } + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeInfo.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeInfo.java new file mode 100644 index 00000000000..eceb6f4f065 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeInfo.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.browser; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.search.ICSearchScope; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; + +/** + * Type information. + */ +public interface ITypeInfo { + + /** + * Gets the CElement type. + */ + public int getType(); + + /** + * Gets the type name. + */ + public String getName(); + + /** + * Gets the enclosing type names. + */ + public String[] getEnclosingNames(); + + /** + * Gets the resource where type is located. + */ + public IResource getResource(); + + /** + * Gets the relative path where type is located. + */ + public IPath getPath(); + + /** + * Gets the absolute path where type is located. + */ + public IPath getLocation(); + + /** + * Gets the start offset of type position. + */ + public int getStartOffset(); + + /** + * Gets the end offset of type position. + */ + public int getEndOffset(); + + /** + * Returns true if type is enclosed in the given scope + */ + public boolean isEnclosed(ICSearchScope scope); + + /** + * Gets the filename where this type is located. + */ + public String getFileName(); + + /** + * Gets the fully qualified type container name: Includes enclosing type names, but + * not filename. Identifiers are separated by colons. + */ + public String getParentName(); + + /** + * Gets the type qualified name: Includes enclosing type names, but + * not filename. Identifiers are separated by colons. + */ + public String getQualifiedName(); + + /** + * Gets the fully qualified type container name: Filename or + * enclosing type name with filename. + * All identifiers are separated by colons. + */ + public String getQualifiedParentName(); + + /** + * Gets the fully qualified type name: Includes enclosing type names and + * filename. All identifiers are separated by colons. + */ + public String getFullyQualifiedName(); + + /** + * Gets the CElement which corresponds to this type. + */ + public ICElement getCElement(); + + /** Gets the include path for this type. + * + * @param cProject the C Project to use as a reference. + * @return The path to this type, relative to the longest + * matching include path in the given project, or + * null if not found. + */ + public IPath resolveIncludePath(ICProject cProject); +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/TypeInfo.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/TypeInfo.java new file mode 100644 index 00000000000..fff39f72225 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/TypeInfo.java @@ -0,0 +1,430 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.browser; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; + +import org.eclipse.cdt.core.CCorePlugin; +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.model.IParent; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.IScannerInfoProvider; +import org.eclipse.cdt.core.search.ICSearchScope; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + + +/** + * To change the template for this generated type comment go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +public class TypeInfo implements ITypeInfo, Comparable +{ + protected final static String scopeResolutionOperator= "::"; //$NON-NLS-1$ + protected final static String fileScopeSeparator= " : "; //$NON-NLS-1$ + private String hashString= null; + private int hashCode= 0; + private String name= null; + private int type= 0; + private String[] enclosingNames= null; + private IResource resource= null; + private IPath path= null; + private int startOffset= 0; + private int endOffset= 0; + private ICElement cElement= null; + + public TypeInfo(String name, int type, String[] enclosingNames, IResource resource, IPath path, int startOffset, int endOffset) { + init(name, type, enclosingNames, resource, path, startOffset, endOffset); + } + + public TypeInfo(String fullName, int type, IPath path, int startOffset, int endOffset) { + String name= fullName; + String parentName= null; + int qualifierIndex= fullName.lastIndexOf(scopeResolutionOperator); + if (qualifierIndex >= 0) { + parentName= fullName.substring(0, qualifierIndex); + name= fullName.substring(qualifierIndex+2); + } + String[] enclosingNames= null; + if (parentName != null) + enclosingNames= parseScopedName(parentName); + + init(name, type, enclosingNames, null, path, startOffset, endOffset); + } + + public TypeInfo(TypeInfo info) { + init(info.name, info.type, info.enclosingNames, info.resource, info.path, info.startOffset, info.endOffset); + } + + private void init(String name, int type, String[] enclosingNames, IResource resource, IPath path, int startOffset, int endOffset) { + this.name= name; + this.type= type; + if (enclosingNames != null) { + this.enclosingNames= new String[enclosingNames.length]; + System.arraycopy(enclosingNames, 0, this.enclosingNames, 0, enclosingNames.length); + } + this.resource= resource; + if (path == null && resource != null) + path= resource.getFullPath(); + this.path= path; + this.startOffset= startOffset; + this.endOffset= endOffset; + } + + public String getName() { + return name; + } + + public int getType() { + return type; + } + + public String[] getEnclosingNames() { + return enclosingNames; + } + + public IResource getResource() { + return resource; + } + + public IPath getPath() { + if (resource != null) + return resource.getFullPath(); + else + return path; + } + + public IPath getLocation() { + if (resource != null) + return resource.getLocation(); + else + return path; + } + + public int getStartOffset() { + return startOffset; + } + + public int getEndOffset() { + return endOffset; + } + + public String getFileName() { + if (resource != null) + return resource.getName(); + else if (path != null) + return path.lastSegment(); + else + return null; + } + + public String getParentName() { + if (enclosingNames != null) { + StringBuffer buf= new StringBuffer(); + for (int i= 0; i < enclosingNames.length; ++i) { + if (i > 0) + buf.append(scopeResolutionOperator); + buf.append(enclosingNames[i]); + } + return buf.toString(); + } + return null; + } + + public String getQualifiedParentName() { + StringBuffer buf= new StringBuffer(); + String fileName = getFileName(); + if (fileName != null) + buf.append(fileName); + String parentName = getParentName(); + if (parentName != null) { + if (fileName != null) + buf.append(fileScopeSeparator); + buf.append(parentName); + } + return buf.toString(); + } + + public String getQualifiedName() { + StringBuffer buf= new StringBuffer(); + String parentName = getParentName(); + if (parentName != null) + buf.append(parentName); + String name = getName(); + if (name != null) { + if (parentName != null) + buf.append(scopeResolutionOperator); + buf.append(name); + } + return buf.toString(); + } + + public String getFullyQualifiedName() { + StringBuffer buf= new StringBuffer(); + String fileName = getFileName(); + if (fileName != null) + buf.append(fileName); + String parentName = getParentName(); + if (parentName != null) { + if (fileName != null) + buf.append(fileScopeSeparator); + buf.append(parentName); + } + String name = getName(); + if (name != null) + if (parentName != null) + buf.append(scopeResolutionOperator); + else if (fileName != null) + buf.append(fileScopeSeparator); + buf.append(name); + return buf.toString(); + } + + public String toString() { + return getFullyQualifiedName(); + } + + public ICElement getCElement() { + if (cElement == null) + cElement= resolveCElement(); + return cElement; + } + + private ICElement resolveCElement() { + if (resource != null && resource.getType() == IResource.FILE) { + ICElement parentElement= CoreModel.getDefault().create((IFile)resource); + if (parentElement instanceof IParent) { + if (enclosingNames != null) { + for (int i= 0; i < enclosingNames.length; ++i) { + parentElement= findCElement(parentElement, enclosingNames[i]); + if (parentElement == null) + break; + } + } + if (parentElement != null) + return findCElement(parentElement, name); + } + } + return null; + } + + private ICElement findCElement(ICElement celement, String name) { + if (isValidType(celement.getElementType()) && celement.getElementName().equals(name)) + return celement; + + if (celement instanceof IParent) { + ICElement[] children = ((IParent)celement).getChildren(); + for (int i = 0; i < children.length; i++) { + ICElement child= children[i]; + if (isValidType(child.getElementType()) && child.getElementName().equals(name)) + return child; + } + } + return null; + } + + public IPath resolveIncludePath(ICProject cProject) { + IPath fullPath= getLocation(); + if (cProject == null || fullPath == null) + return null; + IProject project= cProject.getProject(); + IScannerInfoProvider provider= CCorePlugin.getDefault().getScannerInfoProvider(project); + if (provider != null) { + IScannerInfo info= provider.getScannerInformation(project); + if (info != null) { + String[] includePaths= info.getIncludePaths(); + IPath relativePath= null; + int mostSegments= 0; + for (int i= 0; i < includePaths.length; ++i) { + IPath includePath= new Path(includePaths[i]); + if (includePath.isPrefixOf(fullPath)) { + int segments= includePath.matchingFirstSegments(fullPath); + if (segments > mostSegments) { + relativePath= fullPath.removeFirstSegments(segments).setDevice(null); + mostSegments= segments; + } + } + } + return relativePath; + } + } + return null; + } + + public boolean isEnclosed(ICSearchScope scope) { + if (scope == null) + return false; + + // check if path is in scope + IPath path= getPath(); + if (path != null && scope.encloses(path.toString())) + return true; + + // check include paths of enclosing projects + IPath[] projectPaths= scope.enclosingProjects(); + if (projectPaths != null) { + for (int i= 0; i < projectPaths.length; ++i) { + IPath projPath= projectPaths[i]; + ICElement elem= CoreModel.getDefault().create(projPath); + if (elem != null && elem instanceof ICProject) { + ICProject proj= (ICProject) elem; + if (resolveIncludePath(proj) != null) + return true; + // TODO search referenced projects too? + // IProject[] refs= proj.getProject().getReferencedProjects(); + } + } + } + return false; + } + + public int hashCode() { + if (hashString == null) { + hashCode= getHashString().hashCode(); + } + return hashCode; + } + + private String getHashString() { + if (hashString == null) { + StringBuffer buf= new StringBuffer(64); + + IPath path= getLocation(); + if (path != null) + buf.append(path.toString()); + + buf.append(" ["); //$NON-NLS-1$ + buf.append(startOffset); + buf.append("-"); //$NON-NLS-1$ + buf.append(endOffset); + buf.append("] "); //$NON-NLS-1$ + + String parentName= getParentName(); + if (parentName != null && parentName.length() > 0) { + buf.append(parentName); + buf.append(scopeResolutionOperator); + } + String name= getName(); + if (name != null && name.length() > 0) + buf.append(name); + + buf.append(":"); //$NON-NLS-1$ + buf.append(type); + + hashString= buf.toString(); + } + return hashString; + } + + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof TypeInfo)) { + return false; + } + TypeInfo info= (TypeInfo)obj; + if (hashCode() != info.hashCode()) + return false; + return getHashString().equals(info.getHashString()); + } + + public int compareTo(Object obj) { + if (obj == this) { + return 0; + } + if( !(obj instanceof TypeInfo)) { + throw new ClassCastException(); + } + TypeInfo info= (TypeInfo)obj; + return getHashString().compareTo(info.getHashString()); + } + + public static boolean isValidType(int type) { + switch (type) { + case ICElement.C_NAMESPACE: + case ICElement.C_CLASS: + case ICElement.C_STRUCT: + case ICElement.C_UNION: + case ICElement.C_ENUMERATION: + case ICElement.C_TYPEDEF: +// case ICElement.C_TEMPLATE_CLASS: +// case ICElement.C_TEMPLATE_STRUCT: +// case ICElement.C_TEMPLATE_UNION: + return true; + + default: + return false; + } + } + + public static String[] parseScopedName(String scopedName) { + ArrayList names= new ArrayList(5); + int lastIndex= 0; + String nextName; + int qualifierIndex= scopedName.indexOf(scopeResolutionOperator, 0); + while (qualifierIndex >= 0) { + nextName= scopedName.substring(lastIndex, qualifierIndex); + lastIndex= qualifierIndex + scopeResolutionOperator.length(); + names.add(nextName); + qualifierIndex= scopedName.indexOf(scopeResolutionOperator, lastIndex); + } + nextName= scopedName.substring(lastIndex); + names.add(nextName); + return (String[]) names.toArray(new String[names.size()]); + } + + final static private Comparator TYPE_NAME_COMPARATOR= new Comparator() { + public int compare(Object o1, Object o2) { + return ((ITypeInfo)o1).getName().compareTo(((ITypeInfo)o2).getName()); + } + }; + + public static ITypeInfo findType(String name, IPath path, ITypeInfo[] elements) { + if (elements == null) + return null; + + ITypeInfo key= new TypeInfo(name, 0, path, 0, 0); + + int index= Arrays.binarySearch(elements, key, TYPE_NAME_COMPARATOR); + if (index >= 0 && index < elements.length) { + for (int i= index - 1; i >= 0; i--) { + ITypeInfo curr= elements[i]; + if (key.getName().equals(curr.getName())) { + if (key.getQualifiedName().equals(curr.getQualifiedName())) { + return curr; + } + } else { + break; + } + } + for (int i= index; i < elements.length; i++) { + ITypeInfo curr= elements[i]; + if (key.getName().equals(curr.getName())) { + if (key.getQualifiedName().equals(curr.getQualifiedName())) { + return curr; + } + } else { + break; + } + } + } + return null; + } + +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCache.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCache.java new file mode 100644 index 00000000000..90dadd6971c --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCache.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.cache; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.eclipse.cdt.core.browser.TypeInfo; +import org.eclipse.core.runtime.IPath; + +public class TypeCache { + + private static final int INITIAL_FILE_COUNT= 100; + private static final int INITIAL_TYPE_COUNT= INITIAL_FILE_COUNT*20; + private final Map fFileMap= new HashMap(INITIAL_FILE_COUNT); + private final Map fTypeMap= new HashMap(INITIAL_TYPE_COUNT); + private boolean fIsDirty= true; + + private static final class TypeReference { + private TypeInfo fRealInfo= null; + private Set fPaths= new HashSet(1); + + public TypeReference(TypeInfo info, IPath path) { + fRealInfo= info; + fPaths.add(path); + } + + public TypeInfo getInfo() { + return fRealInfo; + } + + public void addPath(IPath path) { + fPaths.add(path); + } + + public void removePath(IPath path) { + fPaths.remove(path); + } + + public Collection getPaths() { + return fPaths; + } + }; + + public TypeCache() { + } + + public synchronized void markAsDirty(boolean dirty) { + fIsDirty= dirty; + } + + public synchronized boolean isDirty() { + return fIsDirty; + } + + public synchronized Set getAllFiles() { + return fFileMap.keySet(); + } + + public synchronized Set getAllTypes() { + return fTypeMap.keySet(); + } + + private TypeInfo addTypeReference(TypeInfo info, IPath path) { + // we use info as a key here. the actual value found in + // the map corresponds to the 'real' TypeInfo object with + // the same hashCode + TypeReference typeRef= (TypeReference) fTypeMap.get(info); + if (typeRef == null) { + // add this type to cache + typeRef= new TypeReference(info, path); + fTypeMap.put(info, typeRef); + } else if (typeRef.getInfo() != info) { + typeRef.addPath(path); + } + return typeRef.getInfo(); + } + + private void removeTypeReference(TypeInfo info, IPath path) { + // we use info as a key here. the actual value found in + // the map corresponds to the 'real' TypeInfo object with + // the same hashCode + TypeReference typeRef= (TypeReference) fTypeMap.get(info); + if (typeRef == null) + return; + + typeRef.removePath(path); + for (Iterator i= typeRef.getPaths().iterator(); i.hasNext(); ) { + IPath p= (IPath) i.next(); + fFileMap.remove(p); + } + fTypeMap.remove(info); + } + + public synchronized void insert(IPath path, Collection types) { + Collection typeSet= (Collection) fFileMap.get(path); + if (typeSet == null) + typeSet= new ArrayList(types.size()); + for (Iterator typesIter= types.iterator(); typesIter.hasNext(); ) { + TypeInfo info= (TypeInfo)typesIter.next(); + TypeInfo newType= addTypeReference(info, path); + typeSet.add(newType); + } + fFileMap.put(path, typeSet); + } + + public synchronized boolean contains(IPath path) { + return fFileMap.containsKey(path); + } + + public synchronized void flush(IPath path) { + Collection typeSet= (Collection) fFileMap.get(path); + if (typeSet != null) { + for (Iterator typesIter= typeSet.iterator(); typesIter.hasNext(); ) { + TypeInfo info= (TypeInfo)typesIter.next(); + removeTypeReference(info, path); + } + fFileMap.remove(path); + } + fIsDirty= true; + } + + public synchronized void flush(Set paths) { + if (paths != null) { + // flush paths from cache + for (Iterator i= paths.iterator(); i.hasNext(); ) { + IPath path= (IPath) i.next(); + flush(path); + } + } + } + + public synchronized void flushAll() { + // flush the entire cache + fFileMap.clear(); + fTypeMap.clear(); + fIsDirty= true; + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.java new file mode 100644 index 00000000000..395d2c30ca7 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.cache; + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class TypeCacheMessages { + + private static final String RESOURCE_BUNDLE= TypeCacheMessages.class.getName(); + + private static ResourceBundle fgResourceBundle; + static { + try { + fgResourceBundle = ResourceBundle.getBundle(RESOURCE_BUNDLE); + } catch (MissingResourceException x) { + fgResourceBundle = null; + } + } + + private TypeCacheMessages() { + } + + public static String getString(String key) { + try { + return fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } catch (NullPointerException e) { + return "#" + key + "#"; //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + public static String getFormattedString(String key, String arg) { + return getFormattedString(key, new String[] { arg }); + } + + public static String getFormattedString(String key, String[] args) { + return MessageFormat.format(getString(key), args); + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.properties b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.properties new file mode 100644 index 00000000000..273052e91ae --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.properties @@ -0,0 +1,13 @@ +############################################################################### +# Copyright (c) 2004 QNX Software Systems Ltd. and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Common Public License v0.5 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/cpl-v05.html +# +# Contributors: +# QNX Software Systems - Initial API and implementation +############################################################################### + +TypeCacherJob.jobName=TypeCache +TypeCacherJob.taskName=Updating Type Info... diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacherJob.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacherJob.java new file mode 100644 index 00000000000..2e1dd094915 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacherJob.java @@ -0,0 +1,204 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.cache; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.browser.AllTypesCache.IWorkingCopyProvider; +import org.eclipse.cdt.core.model.IWorkingCopy; +import org.eclipse.cdt.core.search.ICSearchConstants; +import org.eclipse.cdt.core.search.ICSearchScope; +import org.eclipse.cdt.internal.core.browser.util.DelegatedProgressMonitor; +import org.eclipse.cdt.internal.core.model.CModelManager; +import org.eclipse.cdt.internal.core.search.CWorkspaceScope; +import org.eclipse.cdt.internal.core.search.PatternSearchJob; +import org.eclipse.cdt.internal.core.search.indexing.IndexManager; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.core.runtime.jobs.ISchedulingRule; +import org.eclipse.core.runtime.jobs.Job; + + +/** + * Background job for filling the type cache. + * @see org.eclipse.core.runtime.jobs.Job + * @since 3.0 + */ +public class TypeCacherJob extends Job { + + /** + * An "identity rule" that forces jobs to be queued. + * @see org.eclipse.core.runtime.jobs.ISchedulingRule + * @since 3.0 + */ + final static ISchedulingRule MUTEX_RULE= new ISchedulingRule() { + public boolean contains(ISchedulingRule rule) { + return rule == this; + } + public boolean isConflicting(ISchedulingRule rule) { + return rule == this; + } + }; + + /** + * Constant identifying the job family identifier for the background job. + * @see IJobManager#join(Object, IProgressMonitor) + * @since 3.0 + */ + private static final Object FAMILY= new Object(); + + private DelegatedProgressMonitor fProgressMonitor; + private Set fSearchPaths= new HashSet(50); + private TypeCache fTypeCache; + private IWorkingCopyProvider fWorkingCopyProvider; + + public TypeCacherJob(TypeCache cache, IWorkingCopyProvider provider) { + super(TypeCacheMessages.getString("TypeCacherJob.jobName")); //$NON-NLS-1$ + setPriority(BUILD); + setSystem(true); + //setRule(MUTEX_RULE); + fTypeCache= cache; + fWorkingCopyProvider= provider; + } + + /* (non-Javadoc) + * @see org.eclipse.core.internal.jobs.InternalJob#belongsTo(java.lang.Object) + */ + public boolean belongsTo(Object family) { + return family == FAMILY; + } + + public void setSearchPaths(Set paths) { + fSearchPaths.clear(); + if (paths != null) + fSearchPaths.addAll(paths); + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.jobs.Job#run(IProgressMonitor) + */ + public IStatus run(IProgressMonitor monitor) { + fProgressMonitor= new DelegatedProgressMonitor(monitor); + + try { + search(fProgressMonitor); + fProgressMonitor.done(); + } catch(InterruptedException ex) { + return Status.CANCEL_STATUS; + } catch (OperationCanceledException ex) { + return Status.CANCEL_STATUS; + } finally { + fProgressMonitor= null; + } + + return Status.OK_STATUS; + } + + /** + * Forwards progress info to the progress monitor and + * blocks until the job is finished. + * + * @param monitor Optional progress monitor. + * @throws InterruptedException + * + * @see Job#join + */ + public void join(IProgressMonitor monitor) throws InterruptedException { + if (fProgressMonitor != null) + fProgressMonitor.addDelegate(monitor); + super.join(); + } + + private void search(IProgressMonitor monitor) throws InterruptedException { + + monitor.beginTask(TypeCacheMessages.getString("TypeCacherJob.taskName"), 100); //$NON-NLS-1$ + + IWorkspace workspace= CCorePlugin.getWorkspace(); + if (workspace == null) + throw new InterruptedException(); + + ICSearchScope scope= new CWorkspaceScope(); + + // search for types and #include references + TypeSearchPattern pattern= new TypeSearchPattern(); + for (Iterator pathIter= fSearchPaths.iterator(); pathIter.hasNext(); ) { + IPath path= (IPath) pathIter.next(); + pattern.addDependencySearch(path); + } + TypeSearchPathCollector pathCollector= new TypeSearchPathCollector(); + + CModelManager modelManager= CModelManager.getDefault(); + IndexManager indexManager= modelManager.getIndexManager(); + + if (monitor.isCanceled()) + throw new InterruptedException(); + + SubProgressMonitor subMonitor= new SubProgressMonitor(monitor, 5); + + /* index search */ + indexManager.performConcurrentJob( + new PatternSearchJob( + pattern, + scope, + pathCollector, + indexManager + ), + ICSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, + subMonitor, + null ); + + if (monitor.isCanceled()) + throw new InterruptedException(); + + if (!fSearchPaths.isEmpty()) { + // flush all affected files from cache + fTypeCache.flush(fSearchPaths); + Set dependencyPaths= pathCollector.getDependencyPaths(); + if (dependencyPaths != null && !dependencyPaths.isEmpty()) { + fTypeCache.flush(dependencyPaths); + } + } + + Set allSearchPaths= pathCollector.getPaths(); + if (allSearchPaths == null) + allSearchPaths= new HashSet(); + + // remove cached files + allSearchPaths.removeAll(fTypeCache.getAllFiles()); + + if (monitor.isCanceled()) + throw new InterruptedException(); + + subMonitor= new SubProgressMonitor(monitor, 95); + + IWorkingCopy[] workingCopies= null; + if (fWorkingCopyProvider != null) + workingCopies= fWorkingCopyProvider.getWorkingCopies(); + + TypeMatchCollector collector= new TypeMatchCollector(fTypeCache, subMonitor); + TypeMatchLocator matchLocator= new TypeMatchLocator(collector); + matchLocator.locateMatches(allSearchPaths, workspace, workingCopies); + + if (monitor.isCanceled()) + throw new InterruptedException(); + + fTypeCache.markAsDirty(false); + monitor.done(); + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchCollector.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchCollector.java new file mode 100644 index 00000000000..0e3e726c77f --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchCollector.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.cache; + +import java.util.ArrayList; + +import org.eclipse.cdt.core.browser.TypeInfo; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; + +public class TypeMatchCollector { + private ArrayList results= new ArrayList(); + private TypeCache typeCache; + private IProgressMonitor progressMonitor; + + public TypeMatchCollector(TypeCache cache, IProgressMonitor monitor) { + progressMonitor= monitor; + typeCache= cache; + } + + public IProgressMonitor getProgressMonitor() { + return progressMonitor; + } + + public boolean beginParsing(IPath path) { + // check if path is in the cache already + if (typeCache.contains(path)) + return false; + + results.clear(); + return true; + } + + public void doneParsing(IPath path) { + if (!results.isEmpty()) { + // add types to cache + typeCache.insert(path, results); + } + } + + public void acceptType(String name, int type, String[] enclosingNames, IResource resource, IPath path, int startOffset, int endOffset) { + // create new type info + TypeInfo info= new TypeInfo(name, type, enclosingNames, resource, path, startOffset, endOffset); + results.add(info); + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchLocator.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchLocator.java new file mode 100644 index 00000000000..e20b01c0270 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchLocator.java @@ -0,0 +1,561 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corp. - Rational Software - initial implementation + * QNX Software Systems - adapted for type search + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.cache; + +import java.io.CharArrayReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IWorkingCopy; +import org.eclipse.cdt.core.parser.DefaultProblemHandler; +import org.eclipse.cdt.core.parser.IParser; +import org.eclipse.cdt.core.parser.IProblem; +import org.eclipse.cdt.core.parser.IScanner; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.IScannerInfoProvider; +import org.eclipse.cdt.core.parser.ISourceElementCallbackDelegate; +import org.eclipse.cdt.core.parser.ISourceElementRequestor; +import org.eclipse.cdt.core.parser.ParserFactory; +import org.eclipse.cdt.core.parser.ParserFactoryError; +import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.core.parser.ParserMode; +import org.eclipse.cdt.core.parser.ParserUtil; +import org.eclipse.cdt.core.parser.ScannerInfo; +import org.eclipse.cdt.core.parser.ast.ASTClassKind; +import org.eclipse.cdt.core.parser.ast.IASTASMDefinition; +import org.eclipse.cdt.core.parser.ast.IASTAbstractTypeSpecifierDeclaration; +import org.eclipse.cdt.core.parser.ast.IASTClassReference; +import org.eclipse.cdt.core.parser.ast.IASTClassSpecifier; +import org.eclipse.cdt.core.parser.ast.IASTCodeScope; +import org.eclipse.cdt.core.parser.ast.IASTCompilationUnit; +import org.eclipse.cdt.core.parser.ast.IASTElaboratedTypeSpecifier; +import org.eclipse.cdt.core.parser.ast.IASTEnumerationReference; +import org.eclipse.cdt.core.parser.ast.IASTEnumerationSpecifier; +import org.eclipse.cdt.core.parser.ast.IASTEnumeratorReference; +import org.eclipse.cdt.core.parser.ast.IASTField; +import org.eclipse.cdt.core.parser.ast.IASTFieldReference; +import org.eclipse.cdt.core.parser.ast.IASTFunction; +import org.eclipse.cdt.core.parser.ast.IASTFunctionReference; +import org.eclipse.cdt.core.parser.ast.IASTInclusion; +import org.eclipse.cdt.core.parser.ast.IASTLinkageSpecification; +import org.eclipse.cdt.core.parser.ast.IASTMacro; +import org.eclipse.cdt.core.parser.ast.IASTMethod; +import org.eclipse.cdt.core.parser.ast.IASTMethodReference; +import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition; +import org.eclipse.cdt.core.parser.ast.IASTNamespaceReference; +import org.eclipse.cdt.core.parser.ast.IASTOffsetableNamedElement; +import org.eclipse.cdt.core.parser.ast.IASTParameterReference; +import org.eclipse.cdt.core.parser.ast.IASTQualifiedNameElement; +import org.eclipse.cdt.core.parser.ast.IASTReference; +import org.eclipse.cdt.core.parser.ast.IASTScope; +import org.eclipse.cdt.core.parser.ast.IASTTemplateDeclaration; +import org.eclipse.cdt.core.parser.ast.IASTTemplateInstantiation; +import org.eclipse.cdt.core.parser.ast.IASTTemplateParameterReference; +import org.eclipse.cdt.core.parser.ast.IASTTemplateSpecialization; +import org.eclipse.cdt.core.parser.ast.IASTTypedefDeclaration; +import org.eclipse.cdt.core.parser.ast.IASTTypedefReference; +import org.eclipse.cdt.core.parser.ast.IASTUsingDeclaration; +import org.eclipse.cdt.core.parser.ast.IASTUsingDirective; +import org.eclipse.cdt.core.parser.ast.IASTVariable; +import org.eclipse.cdt.core.parser.ast.IASTVariableReference; +import org.eclipse.cdt.core.search.ICSearchConstants; +import org.eclipse.cdt.core.search.ICSearchPattern; +import org.eclipse.cdt.internal.core.browser.util.PathUtil; +import org.eclipse.cdt.internal.core.browser.util.SimpleStack; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Path; + +public class TypeMatchLocator implements ISourceElementRequestor, ICSearchConstants { + private ISourceElementCallbackDelegate lastDeclaration; + private ICSearchPattern searchPattern; + private TypeMatchCollector resultCollector; + private IProgressMonitor progressMonitor; + private IWorkspaceRoot workspaceRoot= null; + private SimpleStack scopeStack= new SimpleStack(); + private SimpleStack resourceStack= new SimpleStack(); + private static boolean VERBOSE= false; + + public TypeMatchLocator(TypeMatchCollector collector) { + super(); + searchPattern= new TypeSearchPattern(); + resultCollector= collector; + progressMonitor= collector.getProgressMonitor(); + if (progressMonitor == null) + progressMonitor= new NullProgressMonitor(); + } + + public boolean acceptProblem(IProblem problem) { + return DefaultProblemHandler.ruleOnProblem(problem, ParserMode.COMPLETE_PARSE ); + } + public void acceptUsingDirective(IASTUsingDirective usageDirective) { } + public void acceptUsingDeclaration(IASTUsingDeclaration usageDeclaration) { } + public void acceptASMDefinition(IASTASMDefinition asmDefinition) { } + public void acceptAbstractTypeSpecDeclaration(IASTAbstractTypeSpecifierDeclaration abstractDeclaration) { } + public void enterTemplateDeclaration(IASTTemplateDeclaration declaration) { } + public void enterTemplateSpecialization(IASTTemplateSpecialization specialization) { } + public void enterTemplateInstantiation(IASTTemplateInstantiation instantiation) { } + public void exitTemplateDeclaration(IASTTemplateDeclaration declaration) { } + public void exitTemplateSpecialization(IASTTemplateSpecialization specialization) { } + public void exitTemplateExplicitInstantiation(IASTTemplateInstantiation instantiation) { } + public void acceptParameterReference(IASTParameterReference reference) { } + public void acceptTemplateParameterReference(IASTTemplateParameterReference reference) { } + public void acceptTypedefReference( IASTTypedefReference reference ) { } + public void acceptEnumeratorReference(IASTEnumeratorReference reference) { } + public void acceptClassReference(IASTClassReference reference) { } + public void acceptNamespaceReference( IASTNamespaceReference reference ) { } + public void acceptVariableReference( IASTVariableReference reference ) { } + public void acceptFieldReference( IASTFieldReference reference ) { } + public void acceptEnumerationReference( IASTEnumerationReference reference ) { } + public void acceptFunctionReference( IASTFunctionReference reference ) { } + public void acceptMethodReference( IASTMethodReference reference ) { } + public void acceptField(IASTField field) { } + public void acceptMacro(IASTMacro macro) { } + public void acceptVariable(IASTVariable variable) { } + public void acceptFunctionDeclaration(IASTFunction function) { } + public void acceptMethodDeclaration(IASTMethod method) { } + public void enterCodeBlock(IASTCodeScope scope) { } + public void exitCodeBlock(IASTCodeScope scope) { } + + public void acceptTypedefDeclaration(IASTTypedefDeclaration typedef){ + lastDeclaration = typedef; + check( DECLARATIONS, typedef ); + } + + public void acceptEnumerationSpecifier(IASTEnumerationSpecifier enumeration){ + lastDeclaration = enumeration; + check( DECLARATIONS, enumeration ); + } + + public void acceptElaboratedForewardDeclaration(IASTElaboratedTypeSpecifier elaboratedType){ + check( DECLARATIONS, elaboratedType ); + } + + public void enterLinkageSpecification(IASTLinkageSpecification linkageSpec){ + pushScope( linkageSpec ); + } + public void exitLinkageSpecification(IASTLinkageSpecification linkageSpec){ + popScope(); + } + + public void enterCompilationUnit(IASTCompilationUnit compilationUnit) { + pushScope( compilationUnit ); + } + public void exitCompilationUnit(IASTCompilationUnit compilationUnit){ + popScope(); + } + + public void enterFunctionBody(IASTFunction function){ + pushScope( function ); + } + public void exitFunctionBody(IASTFunction function) { + popScope(); + } + + public void enterMethodBody(IASTMethod method) { + pushScope( method ); + } + public void exitMethodBody(IASTMethod method) { + popScope(); + } + + public void enterNamespaceDefinition(IASTNamespaceDefinition namespaceDefinition) { + lastDeclaration = namespaceDefinition; + check( DECLARATIONS, namespaceDefinition ); + check( DEFINITIONS, namespaceDefinition ); + pushScope( namespaceDefinition ); + } + public void exitNamespaceDefinition(IASTNamespaceDefinition namespaceDefinition) { + popScope(); + } + + public void enterClassSpecifier(IASTClassSpecifier classSpecification) { + lastDeclaration = classSpecification; + check( DECLARATIONS, classSpecification ); + pushScope( classSpecification ); + } + public void exitClassSpecifier(IASTClassSpecifier classSpecification) { + popScope(); + } + + public void enterInclusion(IASTInclusion inclusion) { + String includePath = inclusion.getFullFileName(); + + IPath path = new Path( includePath ); + IResource resource = null; + + if (workspaceRoot != null) + resource = workspaceRoot.getFileForLocation( path ); + + if (resource == null) { + // we need to standardize the paths for external headers + path = PathUtil.getCanonicalPath(includePath); + } + + if (resource != null) + resourceStack.push(resource); + else + resourceStack.push(path); + + if (progressMonitor.isCanceled()) + throw new OperationCanceledException(); + } + + public void exitInclusion(IASTInclusion inclusion) { + resourceStack.pop(); + + if (progressMonitor.isCanceled()) + throw new OperationCanceledException(); + } + + protected void report( ISourceElementCallbackDelegate node, int accuracyLevel ){ + int offset = 0; + int end = 0; + IASTOffsetableNamedElement offsetable = null; + String name = null; + int type = 0; + + if( node instanceof IASTReference ){ + IASTReference reference = (IASTReference) node; + offset = reference.getOffset(); + end = offset + reference.getName().length(); + if (VERBOSE) + verbose("Report Match: " + reference.getName()); //$NON-NLS-1$ + } else if( node instanceof IASTOffsetableNamedElement ){ + offsetable= (IASTOffsetableNamedElement) node; + offset = offsetable.getNameOffset() != 0 ? offsetable.getNameOffset() + : offsetable.getStartingOffset(); + end = offsetable.getNameEndOffset(); + if( end == 0 ){ + end = offset + offsetable.getName().length(); + } + + if (VERBOSE) + verbose("Report Match: " + offsetable.getName()); //$NON-NLS-1$ + } + + if (node instanceof IASTReference) + node = lastDeclaration; + + if (node instanceof IASTReference) { + offsetable = (IASTOffsetableNamedElement) ((IASTReference)node).getReferencedElement(); + name = ((IASTReference)node).getName(); + } else if (node instanceof IASTOffsetableNamedElement) { + offsetable = (IASTOffsetableNamedElement)node; + name = offsetable.getName(); + } else { + return; + } + + // skip unnamed structs + if (name == null || name.length() == 0) + return; + + // skip unused types + type= getElementType(offsetable); + if (type == 0) { + return; + } + + // collect enclosing names + String[] enclosingNames = null; + if (offsetable instanceof IASTQualifiedNameElement) { + String[] names = ((IASTQualifiedNameElement) offsetable).getFullyQualifiedName(); + if (names != null && names.length > 1) { + enclosingNames = new String[names.length-1]; + System.arraycopy(names, 0, enclosingNames, 0, names.length-1); + } + } + +// // collect enclosing files +// IPath[] enclosingPaths= null; +// Object[] sourceRefs= resourceStack.toArray(); +// // assert(sourceRefs.length > 0) +// +// // walk through resource stack and +// // collect enclosing paths +// enclosingPaths= new IPath[sourceRefs.length-1]; +// for (int i= 0; i < sourceRefs.length-1; ++i) { +// Object obj= sourceRefs[i]; +// IPath sourcePath= null; +// if (obj instanceof IResource) { +// IResource res= (IResource) obj; +// enclosingPaths[i]= res.getFullPath(); +// } else { +// enclosingPaths[i]= (IPath) obj; +// } +// } + + IResource resource= null; + IPath path= null; + Object obj= (Object) resourceStack.top(); + if (obj instanceof IResource) + resource= (IResource) obj; + else + path= (IPath) obj; + + resultCollector.acceptType(name, type, enclosingNames, resource, path, offset, end); + } + + private void check( LimitTo limit, ISourceElementCallbackDelegate node ){ + + if (progressMonitor.isCanceled()) + throw new OperationCanceledException(); + + // skip local declarations + IASTScope currentScope= (IASTScope)scopeStack.top(); + if (currentScope instanceof IASTFunction || currentScope instanceof IASTMethod) { + return; + } + + // always limit == DECLARATIONS +// +// if( !searchPattern.canAccept( limit ) ) +// return; + + int level = ICSearchPattern.IMPOSSIBLE_MATCH; + + if( node instanceof IASTReference ){ + level = searchPattern.matchLevel( ((IASTReference)node).getReferencedElement(), limit ); + } else { + level = searchPattern.matchLevel( node, limit ); + } + + if( level != ICSearchPattern.IMPOSSIBLE_MATCH ) + { + report( node, level ); + } + } + + private void pushScope( IASTScope scope ){ + scopeStack.push(scope); + + if (progressMonitor.isCanceled()) + throw new OperationCanceledException(); + } + + private IASTScope popScope(){ + IASTScope oldScope= (IASTScope) scopeStack.pop(); + + if (progressMonitor.isCanceled()) + throw new OperationCanceledException(); + + return oldScope; + } + + private static void verbose(String log) { + System.out.println("(" + Thread.currentThread() + ") " + log); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#createReader(java.lang.String) + */ + public Reader createReader(String finalPath) { + return ParserUtil.createReader(finalPath); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#parserTimeout() + */ + public boolean parserTimeout() { + return false; + } + + + public void locateMatches(Set searchPaths, IWorkspace workspace, IWorkingCopy[] workingCopies) throws InterruptedException { + workspaceRoot= (workspace != null) ? workspace.getRoot() : null; + + Set searchablePaths= new HashSet(searchPaths); + Map workingCopyMap= null; + + if (workingCopies != null && workingCopies.length > 0) { + workingCopyMap= new HashMap(workingCopies.length); + for (int i= 0; i < workingCopies.length; ++i) { + IWorkingCopy workingCopy= workingCopies[i]; + IPath wcPath= workingCopy.getOriginalElement().getPath(); + workingCopyMap.put(wcPath, workingCopy); + searchablePaths.add(wcPath); + } + } + + progressMonitor.beginTask("", searchablePaths.size()); //$NON-NLS-1$ + + for (Iterator i= searchablePaths.iterator(); i.hasNext(); ) { + + if (progressMonitor.isCanceled()) + throw new InterruptedException(); + + IPath path= (IPath) i.next(); + + if (!resultCollector.beginParsing(path)) + continue; + + Reader reader= null; + IPath realPath= null; + IProject project= null; + IResource currentResource= null; + IPath currentPath= null; + + progressMonitor.worked(1); + + if (workspaceRoot != null) { + IWorkingCopy workingCopy= null; + if (workingCopyMap != null) + workingCopy= (IWorkingCopy) workingCopyMap.get(path); + if (workingCopy != null) { + currentResource= workingCopy.getResource(); + reader= new CharArrayReader(workingCopy.getContents()); + } else { + currentResource= workspaceRoot.findMember(path, true); + if (currentResource != null && currentResource instanceof IFile) { + IFile file= (IFile) currentResource; + try { + reader= new InputStreamReader(file.getContents()); + } catch (CoreException ex) { + continue; + } + } + } + } + + if (currentResource == null) { + try { + reader= new FileReader(path.toFile()); + } catch (FileNotFoundException ex) { + continue; + } + currentPath= path; + realPath= currentPath; + project= null; + } else { + currentPath= null; + realPath= currentResource.getLocation(); + project= currentResource.getProject(); + } + + if (currentResource != null) + resourceStack.push(currentResource); + else + resourceStack.push(currentPath); + + parseMatches(path, reader, realPath, project); + + resourceStack.pop(); + + resultCollector.doneParsing(path); + + if (progressMonitor.isCanceled()) + throw new InterruptedException(); + } + + progressMonitor.done(); + } + + private void parseMatches(IPath path, Reader reader, IPath realPath, IProject project) throws InterruptedException { + //Get the scanner info + IScannerInfo scanInfo = new ScannerInfo(); + IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(project); + if (provider != null){ + IScannerInfo buildScanInfo = provider.getScannerInformation(project); + if( buildScanInfo != null ) + scanInfo = new ScannerInfo(buildScanInfo.getDefinedSymbols(), buildScanInfo.getIncludePaths()); + } + + ParserLanguage language = null; + if( project != null ){ + language = CoreModel.getDefault().hasCCNature( project ) ? ParserLanguage.CPP : ParserLanguage.C; + } else { + //TODO no project, what language do we use? + language = ParserLanguage.CPP; + } + + IParser parser = null; + try + { + IScanner scanner = ParserFactory.createScanner( reader, realPath.toOSString(), scanInfo, ParserMode.COMPLETE_PARSE, language, this, ParserUtil.getScannerLogService() ); + parser = ParserFactory.createParser( scanner, this, ParserMode.COMPLETE_PARSE, language, ParserUtil.getParserLogService() ); + } + catch( ParserFactoryError pfe ) + { + + } + + if (VERBOSE) + verbose("*** New Search for path: " + path); //$NON-NLS-1$ + + try { + parser.parse(); + } + catch(OperationCanceledException ex) { + throw new InterruptedException(); + } + catch(Exception ex) { + if (VERBOSE){ + ex.printStackTrace(); + } + } + catch(VirtualMachineError vmErr){ + if (VERBOSE){ + verbose("TypeMatchLocator VM Error: "); //$NON-NLS-1$ + vmErr.printStackTrace(); + } + } + } + + private int getElementType(IASTOffsetableNamedElement offsetable) { + if (offsetable instanceof IASTClassSpecifier || + offsetable instanceof IASTElaboratedTypeSpecifier) { + + ASTClassKind kind = null; + if (offsetable instanceof IASTClassSpecifier) { + kind= ((IASTClassSpecifier)offsetable).getClassKind(); + } else { + kind= ((IASTElaboratedTypeSpecifier)offsetable).getClassKind(); + } + + if (kind == ASTClassKind.CLASS) { + return ICElement.C_CLASS; + } else if (kind == ASTClassKind.STRUCT) { + return ICElement.C_STRUCT; + } else if (kind == ASTClassKind.UNION) { + return ICElement.C_UNION; + } + } else if ( offsetable instanceof IASTNamespaceDefinition ){ + return ICElement.C_NAMESPACE; + } else if ( offsetable instanceof IASTEnumerationSpecifier ){ + return ICElement.C_ENUMERATION; + } else if ( offsetable instanceof IASTTypedefDeclaration ){ + return ICElement.C_TYPEDEF; + } + + return 0; + } + +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPathCollector.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPathCollector.java new file mode 100644 index 00000000000..352140e53ef --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPathCollector.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.cache; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.cdt.internal.core.search.IIndexSearchRequestor; +import org.eclipse.core.runtime.Path; + +/** + * Collects type and dependency paths from search results. + */ +public class TypeSearchPathCollector implements IIndexSearchRequestor { + + public Set typePaths= new HashSet(5); + public Set dependencyPaths= new HashSet(5); + + public void acceptClassDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames) { + typePaths.add(resourcePath); + } + + public void acceptNamespaceDeclaration(String resourcePath, char[] typeName, char[][] enclosingTypeNames) { + typePaths.add(resourcePath); + } + + public void acceptIncludeDeclaration(String resourcePath, char[] decodedSimpleName) { + dependencyPaths.add(resourcePath); + } + + public void acceptConstructorDeclaration(String resourcePath, char[] typeName, int parameterCount) { } + public void acceptConstructorReference(String resourcePath, char[] typeName, int parameterCount) { } + public void acceptFieldDeclaration(String resourcePath, char[] fieldName) { } + public void acceptFieldReference(String resourcePath, char[] fieldName) { } + public void acceptInterfaceDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames, char[] packageName) { } + public void acceptFunctionDeclaration(String resourcePath, char[] methodName, int parameterCount) { } + public void acceptMethodDeclaration(String resourcePath, char[] methodName, int parameterCount, char[][] enclosingTypeNames) { } + public void acceptMethodReference(String resourcePath, char[] methodName, int parameterCount) { } + public void acceptPackageReference(String resourcePath, char[] packageName) { } + public void acceptVariableDeclaration(String resourcePath, char[] simpleTypeName) { } + public void acceptFieldDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames) { } + public void acceptMacroDeclaration(String resourcePath, char[] decodedSimpleName) { } + public void acceptSuperTypeReference(String resourcePath, char[] qualification, char[] typeName, char[] enclosingTypeName, char classOrInterface, char[] superQualification, char[] superTypeName, char superClassOrInterface, int modifiers) { } + public void acceptSuperTypeReference(String resourcePath, char[] qualification, char[] typeName, char classOrInterface, char[] superQualification, char[] superTypeName, char superClassOrInterface, int modifiers) { } + public void acceptTypeReference(String resourcePath, char[] typeName) { } + + /** + * Returns the paths that have been collected. + */ + public Set getPaths() { + Set pathSet= new HashSet(typePaths.size()); + for (Iterator i= typePaths.iterator(); i.hasNext(); ) { + String path= (String) i.next(); + pathSet.add(new Path(path)); + } + return pathSet; + } + + /** + * Returns the dependency paths that have been collected. + */ + public Set getDependencyPaths() { + Set pathSet= new HashSet(dependencyPaths.size()); + for (Iterator i= dependencyPaths.iterator(); i.hasNext(); ) { + String path= (String) i.next(); + pathSet.add(new Path(path)); + } + return pathSet; + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPattern.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPattern.java new file mode 100644 index 00000000000..47def56dd5f --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPattern.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.cache; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.search.ICSearchConstants; +import org.eclipse.cdt.core.search.OrPattern; +import org.eclipse.cdt.core.search.SearchEngine; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; + + +public final class TypeSearchPattern extends OrPattern { + public TypeSearchPattern() { + super(); + addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.NAMESPACE, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ + addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.CLASS, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ + addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.STRUCT, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ + addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.UNION, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ + addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.ENUM, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ + addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.TYPEDEF, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ + } + + public void addDependencySearch(IPath path) { + // convert path to absolute or the search will fail + IResource res= CCorePlugin.getWorkspace().getRoot().findMember(path); + if (res != null) + path= res.getRawLocation(); + if (path != null) + addPattern(createPattern(path.toOSString(), ICSearchConstants.INCLUDE, ICSearchConstants.REFERENCES, ICSearchConstants.EXACT_MATCH, true)); + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/ArrayUtil.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/ArrayUtil.java new file mode 100644 index 00000000000..4cd93b656b4 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/ArrayUtil.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.util; + +/** + * A helper class which allows you to perform some + * simple set operations on int arrays. + */ +public class ArrayUtil { + private ArrayUtil() { + } + + // returns true if set contains elem + public static boolean contains(int[] set, int elem) { + if (set == null) + return false; + for (int i= 0; i < set.length; ++i) { + if (set[i] == elem) + return true; + } + return false; + } + + // returns true if set contains all of subset + public static boolean containsAll(int[] set, int[] subset) { + if (set == null || subset == null) + return false; + for (int i= 0; i < subset.length; ++i) { + if (!contains(set, subset[i])) + return false; + } + return true; + } + + // return a copy of fromSet + public static int[] clone(int[] fromSet) { + if (fromSet == null) + return null; + int[] newSet= new int[fromSet.length]; + for (int i= 0; i < fromSet.length; ++i) { + newSet[i]= fromSet[i]; + } + return newSet; + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/DelegatedProgressMonitor.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/DelegatedProgressMonitor.java new file mode 100644 index 00000000000..a28a746d674 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/DelegatedProgressMonitor.java @@ -0,0 +1,228 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.util; + +import java.util.ArrayList; +import java.util.Iterator; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IProgressMonitorWithBlocking; +import org.eclipse.core.runtime.IStatus; + +/** + * A wrapper around one or more progress monitors. Forwards + * IProgressMonitor and IProgressMonitorWithBlocking + * methods to the delegate monitors. + */ +public class DelegatedProgressMonitor implements IProgressMonitor, IProgressMonitorWithBlocking { + + private static int INITIAL_DELEGATE_COUNT = 2; + private final ArrayList fDelegateList = new ArrayList(INITIAL_DELEGATE_COUNT); + private String fTaskName; + private String fSubTask; + private int fTotalWork = IProgressMonitor.UNKNOWN; + private double fWorked; + private boolean fIsBlocked = false; + private boolean fIsCanceled = false; + + /** + * Creates a new delegated monitor. + */ + public DelegatedProgressMonitor() { + } + + /** + * Creates a new delegated monitor, and adds a delegate. + */ + public DelegatedProgressMonitor(IProgressMonitor delegate) { + addDelegate(delegate); + } + + /* + * @see IProgressMonitor#beginTask + */ + public synchronized void beginTask(String name, int totalWork) { + fTaskName = name; + fTotalWork = totalWork; + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + delegate.beginTask(fTaskName, fTotalWork); + } + }); + } + + /* + * @see IProgressMonitor#done + */ + public synchronized void done() { + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + delegate.done(); + } + }); + } + + /* + * @see IProgressMonitor#setTaskName + */ + public synchronized void setTaskName(String name) { + fTaskName = name; + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + delegate.setTaskName(fTaskName); + } + }); + } + + /* + * @see IProgressMonitor#subTask + */ + public synchronized void subTask(String name) { + fSubTask = name; + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + delegate.subTask(fSubTask); + } + }); + } + + /* + * @see IProgressMonitor#worked + */ + public void worked(int work) { + internalWorked(work); + } + + /* + * @see IProgressMonitor#internalWorked + */ + public synchronized void internalWorked(double internalWork) { + fWorked += internalWork; + final double fInternalWork = internalWork; + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + delegate.internalWorked(fInternalWork); + } + }); + } + + /* + * @see IProgressMonitor#isCanceled + */ + public synchronized boolean isCanceled() { + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + fIsCanceled |= delegate.isCanceled(); + } + }); + return fIsCanceled; + } + + /* + * @see IProgressMonitor#setCanceled + */ + public synchronized void setCanceled(boolean canceled) { + fIsCanceled = canceled; + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + delegate.setCanceled(fIsCanceled); + } + }); + } + + /* + * @see IProgressMonitor#setBlocked + */ + public synchronized void setBlocked(IStatus reason) { + fIsBlocked = true; + final IStatus fReason = reason; + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + if (delegate instanceof IProgressMonitorWithBlocking) + ((IProgressMonitorWithBlocking) delegate).setBlocked(fReason); + } + }); + } + + /* + * @see IProgressMonitor#clearBlocked + */ + public synchronized void clearBlocked() { + fIsBlocked = false; + visitDelegates(new IDelegateVisitor() { + public void visit(IProgressMonitor delegate) { + if (delegate instanceof IProgressMonitorWithBlocking) + ((IProgressMonitorWithBlocking) delegate).clearBlocked(); + } + }); + } + + /** + * Adds a delegate. + */ + public synchronized void addDelegate(IProgressMonitor delegate) { + if (fDelegateList.indexOf(delegate) == -1) { + if (fTaskName != null) + syncUp(delegate); + fDelegateList.add(delegate); + } + } + + /** + * Brings delegate in sync with current progress. + */ + private void syncUp(IProgressMonitor delegate) { + delegate.beginTask(fTaskName, fTotalWork); + delegate.internalWorked(fWorked); + if (fSubTask != null && fSubTask.length() > 0) + delegate.subTask(fSubTask); + if (fIsBlocked && delegate instanceof IProgressMonitorWithBlocking) + ((IProgressMonitorWithBlocking) delegate).setBlocked(null); + } + + /** + * Removes a delegate. + */ + public synchronized void removeDelegate(IProgressMonitor delegate) { + int index = fDelegateList.indexOf(delegate); + if (index != -1) { + fDelegateList.remove(index); + } + } + + /** + * Returns the delegate list. + * + * @return An array of progress monitors added using addDelegate(). + */ + public synchronized IProgressMonitor[] getDelegates() { + return (IProgressMonitor[]) fDelegateList.toArray(); + } + + /** + * Defines a delegate visitor. + */ + private static interface IDelegateVisitor { + public void visit(IProgressMonitor delegate); + } + + /** + * Visits each delegate in the delegates list. + */ + private void visitDelegates(IDelegateVisitor visitor) { + // Clone the delegates since they could remove themselves when called + ArrayList delegatesList = (ArrayList) fDelegateList.clone(); + for (Iterator i = delegatesList.iterator(); i.hasNext(); ) { + IProgressMonitor delegate = (IProgressMonitor) i.next(); + visitor.visit(delegate); + } + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/PathUtil.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/PathUtil.java new file mode 100644 index 00000000000..b638a54fbf1 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/PathUtil.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.util; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.core.runtime.Path; + +public class PathUtil { + + private static boolean fWindows = false; + static { + String os = System.getProperty("os.name"); //$NON-NLS-1$ + if (os != null && os.startsWith("Win")) { //$NON-NLS-1$ + fWindows= true; + } + } + public static boolean isWindowsSystem() { + return fWindows; + } + + public static Path getCanonicalPath(String fullPath) { + File file = new File(fullPath); + try { + String canonPath = file.getCanonicalPath(); + return new Path(canonPath); + } catch (IOException ex) { + } + return new Path(fullPath); + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/SimpleStack.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/SimpleStack.java new file mode 100644 index 00000000000..6e06dbc5e3c --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/SimpleStack.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.browser.util; + +import java.util.ArrayList; + +/** + * A helper class which allows you to perform some simple + * stack operations. Avoids the extra overhead of + * synchronization in Java.Util.Stack. + */ +public class SimpleStack { + + private static int INITIAL_STACK_SIZE = 10; + private ArrayList items; + private static boolean VERBOSE = false; + + public SimpleStack() { + items = new ArrayList(INITIAL_STACK_SIZE); + } + + public SimpleStack(int initialSize) { + items = new ArrayList(initialSize); + } + + public Object push(Object item) { + items.add(item); + if (VERBOSE) + trace("push on stack: " + item); //$NON-NLS-1$ + return item; + } + + public Object pop() { + int top = items.size()-1; + if (top < 0) + return null; + Object item = items.get(top); + items.remove(top); + if (VERBOSE) + trace("pop from stack: " + item); //$NON-NLS-1$ + return item; + } + + public Object top() { + int top = items.size()-1; + if (top < 0) + return null; + return items.get(top); + } + + public boolean isEmpty() { + return (items.size() == 0); + } + + public Object[] toArray() { + return items.toArray(); + } + + public Object[] toArray(Object a[]) { + return items.toArray(a); + } + + private static void trace(String msg) { + System.out.println("(" + Thread.currentThread() + ") " + msg); //$NON-NLS-1$ //$NON-NLS-2$ + } +} diff --git a/core/org.eclipse.cdt.core/build.properties b/core/org.eclipse.cdt.core/build.properties index 6801ee61f26..f4c9917c463 100644 --- a/core/org.eclipse.cdt.core/build.properties +++ b/core/org.eclipse.cdt.core/build.properties @@ -20,6 +20,7 @@ src.includes = about.html,\ index/,\ doc/,\ dependency/,\ + browser/,\ .options javadoc.packages = org.eclipse.cdt.core.*,\ org.eclipse.cdt.core.index.*,\ @@ -33,5 +34,6 @@ source.cdtcore.jar = index/,\ src/,\ utils/,\ search/,\ - dependency/ + dependency/,\ + browser/ source.cdtparser.jar = parser/ diff --git a/core/org.eclipse.cdt.ui/ChangeLog b/core/org.eclipse.cdt.ui/ChangeLog index 3c1b427dabd..343d0f348c3 100644 --- a/core/org.eclipse.cdt.ui/ChangeLog +++ b/core/org.eclipse.cdt.ui/ChangeLog @@ -1,3 +1,12 @@ +2004-04-06 Alain Magloire + + This patch provides some improvements to the Open Type action, such as + per-file type caching (much faster now) and extra filtering options in + the dialog. The non-ui code has also been isolated and moved to + org.eclipse.cdt.core.browser. + + * browser/* + 2004-04-06 Alain Magloire Reorder the sorter. diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/opentype/OpenTypeAction.java b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/opentype/OpenTypeAction.java index 169d65b236b..8b7f27cbc07 100644 --- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/opentype/OpenTypeAction.java +++ b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/opentype/OpenTypeAction.java @@ -12,16 +12,16 @@ package org.eclipse.cdt.internal.ui.browser.opentype; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; +import java.util.Collection; +import org.eclipse.cdt.core.browser.AllTypesCache; +import org.eclipse.cdt.core.browser.ITypeInfo; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.resources.FileStorage; import org.eclipse.cdt.core.search.ICSearchScope; import org.eclipse.cdt.core.search.SearchEngine; import org.eclipse.cdt.internal.ui.editor.CEditor; -import org.eclipse.cdt.ui.browser.typeinfo.AllTypesCache; -import org.eclipse.cdt.ui.browser.typeinfo.ITypeInfo; -import org.eclipse.cdt.ui.browser.typeinfo.TypeInfoFilter; import org.eclipse.cdt.internal.ui.util.EditorUtility; import org.eclipse.cdt.internal.ui.util.ExceptionHandler; import org.eclipse.cdt.ui.CUIPlugin; @@ -58,26 +58,26 @@ public class OpenTypeAction implements IWorkbenchWindowActionDelegate { * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction) */ public void run(IAction action) { - final ICSearchScope scope= SearchEngine.createWorkspaceScope(); - Shell shell= CUIPlugin.getDefault().getActiveWorkbenchShell(); - final ArrayList typeList= new ArrayList(); - final TypeInfoFilter filter= new TypeInfoFilter(); + final ICSearchScope scope= SearchEngine.createWorkspaceScope(); + final int[] kinds= { ICElement.C_NAMESPACE, ICElement.C_CLASS, ICElement.C_STRUCT, + ICElement.C_UNION, ICElement.C_ENUMERATION, ICElement.C_TYPEDEF }; + final Collection typeList= new ArrayList(); - if (AllTypesCache.isCacheUpToDate(filter)) { + if (AllTypesCache.isCacheUpToDate()) { // run without progress monitor - AllTypesCache.getTypes(scope, filter, null, typeList); + AllTypesCache.getTypes(scope, kinds, null, typeList); } else { - IRunnableContext runnableContext= new ProgressMonitorDialog(shell); IRunnableWithProgress runnable= new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { - AllTypesCache.getTypes(scope, filter, monitor, typeList); + AllTypesCache.getTypes(scope, kinds, monitor, typeList); if (monitor.isCanceled()) { throw new InterruptedException(); } } }; + IRunnableContext runnableContext= new ProgressMonitorDialog(getShell()); try { runnableContext.run(true, true, runnable); } catch (InvocationTargetException e) { @@ -94,13 +94,14 @@ public class OpenTypeAction implements IWorkbenchWindowActionDelegate { if (typeList.isEmpty()) { String title= OpenTypeMessages.getString("OpenTypeAction.notypes.title"); //$NON-NLS-1$ String message= OpenTypeMessages.getString("OpenTypeAction.notypes.message"); //$NON-NLS-1$ - MessageDialog.openInformation(shell, title, message); + MessageDialog.openInformation(getShell(), title, message); return; } - ITypeInfo[] typeRefs= (ITypeInfo[])typeList.toArray(new ITypeInfo[typeList.size()]); - - OpenTypeDialog dialog= new OpenTypeDialog(shell); - dialog.setElements(typeRefs); + + ITypeInfo[] elements= (ITypeInfo[])typeList.toArray(new ITypeInfo[typeList.size()]); + + OpenTypeDialog dialog= new OpenTypeDialog(getShell()); + dialog.setElements(elements); int result= dialog.open(); if (result != IDialogConstants.OK_ID) @@ -110,28 +111,34 @@ public class OpenTypeAction implements IWorkbenchWindowActionDelegate { if (info == null) return; - if (!openTypeInEditor(shell, info)) + if (!openTypeInEditor(info)) { // could not find definition - String path= info.getFilePath(); - if (path == null || path.length() == 0) - path= OpenTypeMessages.getString("OpenTypeAction.errorNoPath"); //$NON-NLS-1$ + String pathString= null; + IPath path= info.getLocation(); + if (path != null) + pathString= path.toString(); + else + pathString= OpenTypeMessages.getString("OpenTypeAction.errorNoPath"); //$NON-NLS-1$ String title= OpenTypeMessages.getString("OpenTypeAction.errorTitle"); //$NON-NLS-1$ - String message= OpenTypeMessages.getFormattedString("OpenTypeAction.errorMessage", path); //$NON-NLS-1$ - MessageDialog.openError(shell, title, message); + String message= OpenTypeMessages.getFormattedString("OpenTypeAction.errorMessage", pathString); //$NON-NLS-1$ + MessageDialog.openError(getShell(), title, message); } } + protected Shell getShell() { + return CUIPlugin.getDefault().getActiveWorkbenchShell(); + } + /** * Opens an editor and displays the selected type. - * @param shell Workbench shell. * @param info Type to display. * @return true if succesfully displayed. */ - private boolean openTypeInEditor(Shell shell, ITypeInfo info) { + private boolean openTypeInEditor(ITypeInfo info) { IResource res= null; IEditorPart editorPart= null; - IPath path= info.getLocation(); + IPath path= info.getPath(); ICElement celement= info.getCElement(); // attempt to locate the resource diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/opentype/OpenTypeDialog.java b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/opentype/OpenTypeDialog.java index 746e356c7f8..30e939d1952 100644 --- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/opentype/OpenTypeDialog.java +++ b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/opentype/OpenTypeDialog.java @@ -12,12 +12,6 @@ package org.eclipse.cdt.internal.ui.browser.opentype; import org.eclipse.cdt.ui.browser.typeinfo.TypeSelectionDialog; -import org.eclipse.cdt.ui.CUIPlugin; -import org.eclipse.jface.dialogs.IDialogSettings; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; /** @@ -26,128 +20,17 @@ import org.eclipse.swt.widgets.Shell; */ public class OpenTypeDialog extends TypeSelectionDialog { - /** The dialog location. */ - private Point fLocation; - /** The dialog size. */ - private Point fSize; + private static final String DIALOG_SETTINGS= OpenTypeDialog.class.getName(); /** * Constructs an instance of OpenTypeDialog. * @param parent the parent shell. - * @param context the context. */ public OpenTypeDialog(Shell parent) { super(parent); setTitle(OpenTypeMessages.getString("OpenTypeDialog.title")); //$NON-NLS-1$ setMessage(OpenTypeMessages.getString("OpenTypeDialog.message")); //$NON-NLS-1$ - //setFilter(OpenTypeMessages.getString("OpenTypeDialog.filter")); //$NON-NLS-1$ setMatchEmptyString(true); - } - - /* - * @see org.eclipse.jface.window.Window#configureShell(Shell) - */ - protected void configureShell(Shell newShell) { - super.configureShell(newShell); - } - - /* - * @see Window#close() - */ - public boolean close() { - writeSettings(); - return super.close(); - } - - /* - * @see org.eclipse.jface.window.Window#createContents(org.eclipse.swt.widgets.Composite) - */ - protected Control createContents(Composite parent) { - Control control= super.createContents(parent); - readSettings(); - return control; - } - - /* (non-Javadoc) - * @see org.eclipse.jface.window.Window#getInitialSize() - */ - protected Point getInitialSize() { - Point result= super.getInitialSize(); - if (fSize != null) { - result.x= Math.max(result.x, fSize.x); - result.y= Math.max(result.y, fSize.y); - Rectangle display= getShell().getDisplay().getClientArea(); - result.x= Math.min(result.x, display.width); - result.y= Math.min(result.y, display.height); - } - return result; - } - - /* (non-Javadoc) - * @see org.eclipse.jface.window.Window#getInitialLocation(org.eclipse.swt.graphics.Point) - */ - protected Point getInitialLocation(Point initialSize) { - Point result= super.getInitialLocation(initialSize); - if (fLocation != null) { - result.x= fLocation.x; - result.y= fLocation.y; - Rectangle display= getShell().getDisplay().getClientArea(); - int xe= result.x + initialSize.x; - if (xe > display.width) { - result.x-= xe - display.width; - } - int ye= result.y + initialSize.y; - if (ye > display.height) { - result.y-= ye - display.height; - } - } - return result; - } - - /** - * Initializes itself from the dialog settings with the same state - * as at the previous invocation. - */ - private void readSettings() { - IDialogSettings s= getDialogSettings(); - try { - int x= s.getInt("x"); //$NON-NLS-1$ - int y= s.getInt("y"); //$NON-NLS-1$ - fLocation= new Point(x, y); - int width= s.getInt("width"); //$NON-NLS-1$ - int height= s.getInt("height"); //$NON-NLS-1$ - fSize= new Point(width, height); - } catch (NumberFormatException e) { - fLocation= null; - fSize= null; - } - } - - /** - * Stores it current configuration in the dialog store. - */ - private void writeSettings() { - IDialogSettings s= getDialogSettings(); - Point location= getShell().getLocation(); - s.put("x", location.x); //$NON-NLS-1$ - s.put("y", location.y); //$NON-NLS-1$ - Point size= getShell().getSize(); - s.put("width", size.x); //$NON-NLS-1$ - s.put("height", size.y); //$NON-NLS-1$ - } - - /** - * Returns the dialog settings object used to share state - * between several find/replace dialogs. - * - * @return the dialog settings to be used - */ - private IDialogSettings getDialogSettings() { - IDialogSettings settings= CUIPlugin.getDefault().getDialogSettings(); - String sectionName= getClass().getName(); - IDialogSettings subSettings= settings.getSection(sectionName); - if (subSettings == null) - subSettings= settings.addNewSection(sectionName); - return subSettings; + setDialogSettings(DIALOG_SETTINGS); } } diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/util/ArrayUtil.java b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/util/ArrayUtil.java deleted file mode 100644 index fb8e356999a..00000000000 --- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/util/ArrayUtil.java +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2004 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * QNX Software Systems - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.internal.ui.browser.util; - -/** - * A helper class which allows you to perform some - * simple set operations on int arrays. - */ -public class ArrayUtil { - private ArrayUtil() { - } - - // returns true if set contains elem - public static boolean contains(int[] set, int elem) { - for (int i= 0; i < set.length; ++i) { - if (set[i] == elem) - return true; - } - return false; - } - - // returns true if set contains all of subset - public static boolean containsAll(int[] set, int[] subset) { - for (int i= 0; i < subset.length; ++i) { - if (!contains(set, subset[i])) - return false; - } - return true; - } - - // return a copy of fromSet - public static int[] clone(int[] fromSet) { - int[] newSet= new int[fromSet.length]; - for (int i= 0; i < fromSet.length; ++i) { - newSet[i]= newSet[i]; - } - return newSet; - } -} diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/util/ProgressMonitorMultiWrapper.java b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/util/ProgressMonitorMultiWrapper.java deleted file mode 100644 index ddad94f7038..00000000000 --- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/util/ProgressMonitorMultiWrapper.java +++ /dev/null @@ -1,233 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2004 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * QNX Software Systems - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.internal.ui.browser.util; - -import java.util.ArrayList; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IProgressMonitorWithBlocking; -import org.eclipse.core.runtime.IStatus; - -/** - * A wrapper around multiple progress monitors which forwards - * IProgressMonitor and IProgressMonitorWithBlocking - * methods to the wrapped progress monitors. - */ -public class ProgressMonitorMultiWrapper implements IProgressMonitor, IProgressMonitorWithBlocking { - - private double internalWork; - private int totalWork; - private int work; - private String taskName; - private String subtaskName; - private boolean isCanceled= false; - private boolean blocked= false; - - /** The wrapped progress monitors. */ - private final ArrayList fProgressMonitors= new ArrayList(2); - - /** - * Creates a new monitor wrapper. - */ - public ProgressMonitorMultiWrapper() { - } - - /** - * Creates a new monitor wrapper around the given monitor. - */ - public ProgressMonitorMultiWrapper(IProgressMonitor monitor) { - addProgressMonitor(monitor); - } - - /* - * @see IProgressMonitor#beginTask - */ - public void beginTask(String name, int totalWork) { - taskName= name; - this.totalWork= totalWork; - - // Clone the monitors since they could remove themselves when called - ArrayList monitors= (ArrayList) fProgressMonitors.clone(); - for (int i= 0; i < monitors.size(); i++) { - IProgressMonitor monitor= (IProgressMonitor) monitors.get(i); - monitor.beginTask(name, totalWork); - } - } - - /* - * @see IProgressMonitor#setTaskName - */ - public void setTaskName(String name) { - taskName= name; - - // Clone the monitors since they could remove themselves when called - ArrayList monitors= (ArrayList) fProgressMonitors.clone(); - for (int i= 0; i < monitors.size(); i++) { - IProgressMonitor monitor= (IProgressMonitor) monitors.get(i); - monitor.setTaskName(name); - } - } - - /* - * @see IProgressMonitor#subTask - */ - public void subTask(String name) { - subtaskName= name; - - // Clone the monitors since they could remove themselves when called - ArrayList monitors= (ArrayList) fProgressMonitors.clone(); - for (int i= 0; i < monitors.size(); i++) { - IProgressMonitor monitor= (IProgressMonitor) monitors.get(i); - monitor.subTask(name); - } - } - - /* - * @see IProgressMonitor#worked - */ - public void worked(int work) { - this.work= work; - - // Clone the monitors since they could remove themselves when called - ArrayList monitors= (ArrayList) fProgressMonitors.clone(); - for (int i= 0; i < monitors.size(); i++) { - IProgressMonitor monitor= (IProgressMonitor) monitors.get(i); - monitor.worked(work); - } - } - - /* - * @see IProgressMonitor#internalWorked - */ - public void internalWorked(double work) { - internalWork= work; - - // Clone the monitors since they could remove themselves when called - ArrayList monitors= (ArrayList) fProgressMonitors.clone(); - for (int i= 0; i < monitors.size(); i++) { - IProgressMonitor monitor= (IProgressMonitor) monitors.get(i); - monitor.internalWorked(work); - } - } - - /* - * @see IProgressMonitor#done - */ - public void done() { - // Clone the monitors since they could remove themselves when called - ArrayList monitors= (ArrayList) fProgressMonitors.clone(); - for (int i= 0; i < monitors.size(); i++) { - IProgressMonitor monitor= (IProgressMonitor) monitors.get(i); - monitor.done(); - } - } - - /* - * @see IProgressMonitor#setCanceled - */ - public void setCanceled(boolean canceled) { - isCanceled= canceled; - - // Clone the monitors since they could remove themselves when called - ArrayList monitors= (ArrayList) fProgressMonitors.clone(); - for (int i= 0; i < monitors.size(); i++) { - IProgressMonitor monitor= (IProgressMonitor) monitors.get(i); - monitor.setCanceled(canceled); - } - } - - /* - * @see IProgressMonitor#isCanceled - */ - public boolean isCanceled() { - // Clone the monitors since they could remove themselves when called - ArrayList monitors= (ArrayList) fProgressMonitors.clone(); - for (int i= 0; i < monitors.size(); i++) { - IProgressMonitor monitor= (IProgressMonitor) monitors.get(i); - isCanceled |= monitor.isCanceled(); - } - return isCanceled; - } - - /* - * @see IProgressMonitor#setBlocked - */ - public void setBlocked(IStatus reason) { - blocked= true; - - // Clone the monitors since they could remove themselves when called - ArrayList monitors= (ArrayList) fProgressMonitors.clone(); - for (int i= 0; i < monitors.size(); i++) { - IProgressMonitor monitor= (IProgressMonitor) monitors.get(i); - if (monitor instanceof IProgressMonitorWithBlocking) - ((IProgressMonitorWithBlocking) monitor).setBlocked(reason); - } - } - - /* - * @see IProgressMonitor#clearBlocked - */ - public void clearBlocked() { - blocked= false; - - // Clone the monitors since they could remove themselves when called - ArrayList monitors= (ArrayList) fProgressMonitors.clone(); - for (int i= 0; i < monitors.size(); i++) { - IProgressMonitor monitor= (IProgressMonitor) monitors.get(i); - if (monitor instanceof IProgressMonitorWithBlocking) - ((IProgressMonitorWithBlocking) monitor).clearBlocked(); - } - } - - /* - * brings monitor up to date - */ - private void syncUpMonitor(IProgressMonitor monitor) { - if (totalWork > 0) { - monitor.beginTask(taskName, totalWork); - monitor.worked(work); - monitor.internalWorked(internalWork); - if (subtaskName != null && subtaskName.length() > 0) - monitor.subTask(subtaskName); - if (blocked && monitor instanceof IProgressMonitorWithBlocking) - ((IProgressMonitorWithBlocking) monitor).setBlocked(null); - } - } - - /** - * Adds a monitor to the list of wrapped monitors. - */ - public synchronized void addProgressMonitor(IProgressMonitor monitor) { - if (fProgressMonitors.indexOf(monitor) == -1) { - syncUpMonitor(monitor); - fProgressMonitors.add(monitor); - } - } - - /** - * Removes a monitor from the list of wrapped monitors. - */ - public synchronized void removeProgressMonitor(IProgressMonitor monitor) { - int index = fProgressMonitors.indexOf(monitor); - if (index != -1) { - fProgressMonitors.remove(index); - } - } - - /** - * Returns the wrapped progress monitors. - * - * @return the wrapped progress monitors - */ - public IProgressMonitor[] getWrappedProgressMonitors() { - return (IProgressMonitor[]) fProgressMonitors.toArray(); - } -} diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/AllTypesCache.java b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/AllTypesCache.java deleted file mode 100644 index c8812ee1e57..00000000000 --- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/AllTypesCache.java +++ /dev/null @@ -1,483 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2004 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - * QNX Software Systems - adapted for use in CDT - *******************************************************************************/ -package org.eclipse.cdt.ui.browser.typeinfo; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Comparator; -import java.util.Set; - -import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.core.model.CoreModel; -import org.eclipse.cdt.core.model.ElementChangedEvent; -import org.eclipse.cdt.core.model.ICElement; -import org.eclipse.cdt.core.model.ICElementDelta; -import org.eclipse.cdt.core.model.IElementChangedListener; -import org.eclipse.cdt.core.parser.ISourceElementCallbackDelegate; -import org.eclipse.cdt.core.search.BasicSearchResultCollector; -import org.eclipse.cdt.core.search.ICSearchConstants; -import org.eclipse.cdt.core.search.ICSearchPattern; -import org.eclipse.cdt.core.search.ICSearchScope; -import org.eclipse.cdt.core.search.IMatch; -import org.eclipse.cdt.core.search.OrPattern; -import org.eclipse.cdt.core.search.SearchEngine; -import org.eclipse.cdt.internal.ui.browser.util.ArrayUtil; -import org.eclipse.cdt.internal.ui.browser.util.ProgressMonitorMultiWrapper; -import org.eclipse.core.resources.IWorkspace; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.SubProgressMonitor; -import org.eclipse.core.runtime.jobs.ISchedulingRule; -import org.eclipse.core.runtime.jobs.Job; - -/** - * Manages a search cache for types in the workspace. Instead of returning objects of type ICElement - * the methods of this class returns a list of the lightweight objects TypeInfo. - *

- * AllTypesCache runs asynchronously using a background job to rebuild the cache as needed. - * If the cache becomes dirty again while the background job is running, the job is restarted. - *

- * If getAllTypes is called in response to a user action, a progress dialog is shown. - * If called before the background job has finished, getAllTypes waits - * for the completion of the background job. - */ -public class AllTypesCache { - - /** - * Background job for filling the type cache. - * @see org.eclipse.core.runtime.jobs.Job - * @since 3.0 - */ - private static class TypeCacherJob extends Job { - - /** - * An "identity rule" that forces jobs to be queued. - * @see org.eclipse.core.runtime.jobs.ISchedulingRule - * @since 3.0 - */ - final static ISchedulingRule MUTEX_RULE= new ISchedulingRule() { - public boolean contains(ISchedulingRule rule) { - return rule == this; - } - public boolean isConflicting(ISchedulingRule rule) { - return rule == this; - } - }; - - /** - * A comparator for simple type names - */ - private static class TypeNameComparator implements Comparator { - public int compare(Object o1, Object o2) { - return ((TypeInfo)o1).getName().compareTo(((TypeInfo)o2).getName()); - } - } - - /** - * A search result collector for type info. - * @see org.eclipse.cdt.core.search.ICSearchResultCollector - */ - private static class TypeSearchResultCollector extends BasicSearchResultCollector { - - public TypeSearchResultCollector() { - super(); - } - - public TypeSearchResultCollector(IProgressMonitor monitor) { - super(monitor); - } - - public IMatch createMatch(Object fileResource, int start, int end, ISourceElementCallbackDelegate node, IPath realPath ) - { - TypeInfo result= new TypeInfo(); - return super.createMatch( result, fileResource, start, end, node, realPath); - } - - public boolean acceptMatch(IMatch match) throws CoreException { - // filter out unnamed structs - TypeInfo result= (TypeInfo) match; - String name= result.getName(); - if (name == null || name.length() == 0) - return false; - - // make sure we've got a valid type - if (!TypeInfo.isValidCElementType(result.getElementType())) - return false; - - return super.acceptMatch(match); - } - } - - /** - * Constant identifying the job family identifier for the background job. - * @see IJobManager#join(Object, IProgressMonitor) - * @since 3.0 - */ - public static final Object FAMILY= new Object(); - - final static Comparator TYPE_COMPARATOR= new TypeNameComparator(); - - private ProgressMonitorMultiWrapper progressMonitor; - - public TypeCacherJob() { - super(TypeInfoMessages.getString("TypeCacherJob.jobName")); //$NON-NLS-1$ - setPriority(BUILD); - setSystem(true); - //setRule(MUTEX_RULE); - } - - /* (non-Javadoc) - * @see org.eclipse.core.internal.jobs.InternalJob#belongsTo(java.lang.Object) - */ - public boolean belongsTo(Object family) { - return family == FAMILY; - } - - /* (non-Javadoc) - * @see org.eclipse.core.runtime.jobs.Job#shouldRun() - */ - public boolean shouldRun() { - return isCacheDirty(); - } - - /* (non-Javadoc) - * @see org.eclipse.core.runtime.jobs.Job#run(IProgressMonitor) - */ - public IStatus run(IProgressMonitor monitor) { - progressMonitor= new ProgressMonitorMultiWrapper(monitor); - progressMonitor.beginTask(TypeInfoMessages.getString("TypeCacherJob.taskName"), 100); //$NON-NLS-1$ - - SubProgressMonitor subMonitor= new SubProgressMonitor(progressMonitor, 100); - TypeSearchResultCollector collector= new TypeSearchResultCollector(subMonitor); - - IWorkspace workspace= CCorePlugin.getWorkspace(); - if (workspace == null) { - return Status.CANCEL_STATUS; - } - - ICSearchScope scope= SearchEngine.createWorkspaceScope(); - SearchEngine engine= new SearchEngine(); - - ICSearchPattern pattern= createSearchPattern(); - try { - flushCache(); - // start the search engine - if (progressMonitor.isCanceled()) - throw new InterruptedException(); - engine.search(workspace, pattern, scope, collector, true); - if (progressMonitor.isCanceled()) - throw new InterruptedException(); - progressMonitor.done(); - } catch(InterruptedException ex) { - return Status.CANCEL_STATUS; - } finally { - progressMonitor= null; - } - - Set searchResults= collector.getSearchResults(); - - if (searchResults != null) { - TypeInfo[] result= (TypeInfo[]) searchResults.toArray(new TypeInfo[searchResults.size()]); - Arrays.sort(result, TYPE_COMPARATOR); - setCache(result); - } - else { - TypeInfo[] result= new TypeInfo[0]; - setCache(result); - } - return Status.OK_STATUS; - } - - /* - * creates a search pattern based on the cache types - */ - private ICSearchPattern createSearchPattern() { - OrPattern pattern= new OrPattern(); - int[] types= getCacheTypes(); - for (int i= 0; i < types.length; ++i) { - switch (types[i]) { - case ICElement.C_NAMESPACE: - pattern.addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.NAMESPACE, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ - break; - - case ICElement.C_CLASS: // fall through - case ICElement.C_TEMPLATE_CLASS: - pattern.addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.CLASS, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ - break; - - case ICElement.C_STRUCT: // fall through - case ICElement.C_TEMPLATE_STRUCT: - pattern.addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.STRUCT, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ - break; - - case ICElement.C_UNION: // fall through - case ICElement.C_TEMPLATE_UNION: - pattern.addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.UNION, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ - break; - - case ICElement.C_ENUMERATION: - pattern.addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.ENUM, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ - break; - - case ICElement.C_TYPEDEF: - pattern.addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.TYPEDEF, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$ - break; - - default: - break; - } - } - return pattern; - } - - /** - * Forwards progress info to the progress monitor and - * blocks until the job is finished. - * - * @param monitor Optional progress monitor. - * @throws InterruptedException - * - * @see Job#join - */ - public void join(IProgressMonitor monitor) throws InterruptedException { - if (progressMonitor != null) - progressMonitor.addProgressMonitor(monitor); - super.join(); - } - } - - /** - * Listener for changes to CModel. - * @see org.eclipse.cdt.core.model.IElementChangedListener - * @since 3.0 - */ - private static class TypeCacheDeltaListener implements IElementChangedListener { - /* - * @see IElementChangedListener#elementChanged - */ - public void elementChanged(ElementChangedEvent event) { - //TODO optimization: calculate deltas per file and - // update the cache selectively - boolean needsFlushing= processDelta(event.getDelta()); - if (needsFlushing) { - // mark cache as dirty and reschedule the - // background job - setCacheDirty(); - if (fgJob.getState() == Job.RUNNING) - fgJob.cancel(); - fgJob.setPriority(Job.BUILD); - fgJob.schedule(); - } - } - - /* - * returns true if the cache needs to be flushed - */ - private boolean processDelta(ICElementDelta delta) { - ICElement elem= delta.getElement(); - int pathEntryChanged= ICElementDelta.F_ADDED_PATHENTRY_SOURCE | ICElementDelta.F_REMOVED_PATHENTRY_SOURCE | - ICElementDelta.F_CHANGED_PATHENTRY_INCLUDE | ICElementDelta.F_CHANGED_PATHENTRY_MACRO; - boolean isAddedOrRemoved= (delta.getKind() != ICElementDelta.CHANGED) - || ((delta.getFlags() & pathEntryChanged) != 0); - - switch (elem.getElementType()) { - case ICElement.C_MODEL: - case ICElement.C_PROJECT: - case ICElement.C_CCONTAINER: - case ICElement.C_NAMESPACE: - case ICElement.C_TEMPLATE_CLASS: - case ICElement.C_CLASS: - case ICElement.C_STRUCT: - case ICElement.C_UNION: - case ICElement.C_ENUMERATION: - case ICElement.C_TYPEDEF: - case ICElement.C_INCLUDE: - case ICElement.C_UNIT: - if (isAddedOrRemoved) { - return true; - } - return processChildrenDelta(delta); - default: - // fields, methods, imports ect - return false; - } - } - - private boolean isPossibleStructuralChange(int flags) { - return (flags & (ICElementDelta.F_CONTENT | ICElementDelta.F_FINE_GRAINED)) == ICElementDelta.F_CONTENT; - } - - private boolean processChildrenDelta(ICElementDelta delta) { - ICElementDelta[] children= delta.getAffectedChildren(); - for (int i= 0; i < children.length; i++) { - if (processDelta(children[i])) { - return true; - } - } - return false; - } - } - - private static final int INITIAL_DELAY= 5000; - private static final TypeCacherJob fgJob= new TypeCacherJob(); - private static final TypeCacheDeltaListener fgDeltaListener= new TypeCacheDeltaListener(); - private static int[] fgCacheTypes= TypeInfo.getAllCElementTypes(); - private static TypeInfo[] fgCacheData; - private static int fgNumberOfCacheFlushes; - private static boolean cacheIsDirty= true; - - /** - * Initializes the AllTypesCache service. - */ - public static void initialize() { - // add delta listener - CoreModel.getDefault().addElementChangedListener(fgDeltaListener); - - // schedule job to run after INITIAL_DELAY - if (fgJob.getState() != Job.RUNNING) { - fgJob.setPriority(Job.BUILD); - fgJob.schedule(INITIAL_DELAY); - } - } - - /** - * Terminates the service provided by AllTypesCache. - */ - public static void terminate() { - // remove delta listener - CoreModel.getDefault().removeElementChangedListener(fgDeltaListener); - - // terminate background job - fgJob.cancel(); - } - - /* - * Sets the cache contents. - */ - private static synchronized void setCache(TypeInfo[] cache) { - fgCacheData= cache; - cacheIsDirty= false; - } - - /* - * Gets the cache contents. - */ - private static synchronized TypeInfo[] getCache() { - return fgCacheData; - } - - /* - * Clears the cache. - */ - private static synchronized void flushCache() { - fgCacheData= null; - ++fgNumberOfCacheFlushes; - cacheIsDirty= true; - } - - /* - * Marks cache as dirty. - */ - private static synchronized void setCacheDirty() { - cacheIsDirty= true; - } - - /* - * Tests if cache is dirty. - */ - private static synchronized boolean isCacheDirty() { - return cacheIsDirty; - } - - /* - * Sets which types are stored in the cache. - */ - private static synchronized void setCacheTypes(int[] cElementTypes) { - fgCacheTypes= ArrayUtil.clone(cElementTypes); - } - - /* - * Gets types stored in the cache. - */ - private static synchronized int[] getCacheTypes() { - return fgCacheTypes; - } - - /** - * Returns all types in the given scope, matching the given filter. - * @param filter Filter for the type info. - * @param monitor Progress monitor. - * @param typesFound The resulting TypeInfo elements are added to this collection - */ - public static void getTypes(ICSearchScope scope, ITypeInfoFilter filter, IProgressMonitor monitor, Collection typesFound) { - TypeInfo[] allTypes= getAllTypes(filter, monitor); - if (allTypes != null) { - boolean isWorkspaceScope= scope.equals(SearchEngine.createWorkspaceScope()); - for (int i= 0; i < allTypes.length; i++) { - TypeInfo info= allTypes[i]; - if (isWorkspaceScope || info.isEnclosed(scope)) { - if (filter.match(info)) - typesFound.add(info); - } - } - } - } - - /** - * Returns all types in the workspace. The returned array must not be - * modified. The elements in the array are sorted by simple type name. - */ - public static TypeInfo[] getAllTypes(ITypeInfoFilter filter, IProgressMonitor monitor) { - - // check if requested types are in cache - if (!ArrayUtil.containsAll(getCacheTypes(), filter.getCElementTypes())) - { - // mark cache dirty and cancel the running job - setCacheDirty(); - if (fgJob.getState() == Job.RUNNING) - fgJob.cancel(); - setCacheTypes(filter.getCElementTypes()); - } - - if (isCacheDirty()) { - // start job if not already running - if (fgJob.getState() != Job.RUNNING) { - // boost priority since action was user-initiated - fgJob.setPriority(Job.SHORT); - fgJob.schedule(); - } - - // wait for job to finish - try { - fgJob.join(monitor); - if (monitor != null) - monitor.done(); - } catch (InterruptedException ex) { - return null; - } - } - return getCache(); - } - - /** - * Returns true if the type cache is up to date. - */ - public static boolean isCacheUpToDate(ITypeInfoFilter filter) { - // check if requested types are in cache - if (!ArrayUtil.containsAll(getCacheTypes(), filter.getCElementTypes())) - return false; - return !isCacheDirty(); - } -} diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/ITypeInfo.java b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/ITypeInfo.java deleted file mode 100644 index 2621ab982a4..00000000000 --- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/ITypeInfo.java +++ /dev/null @@ -1,76 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2004 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * QNX Software Systems - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.ui.browser.typeinfo; - -import org.eclipse.cdt.core.model.ICElement; -import org.eclipse.cdt.core.search.ICSearchScope; -import org.eclipse.cdt.core.search.IMatch; - -/** - * Type information. - */ -public interface ITypeInfo extends IMatch { - - /** - * Returns true if type is enclosed in the given scope - */ - public boolean isEnclosed(ICSearchScope scope); - - /** - * Returns true if the type is a low-level system type. - * e.g. __FILE - */ - public boolean isSystemType(); - - /** - * Gets the enclosing type names. - */ - public String[] getEnclosingNames(); - - /** - * Gets the filename where this type is located. - */ - public String getFileName(); - - /** - * Gets the file path where this type is located. - */ - public String getFilePath(); - - /** - * Gets the extension of the file where this type is located. - */ - public String getFileExtension(); - - /** - * Gets the type qualified name: Includes enclosing type names, but - * not filename. Identifiers are separated by colons. - */ - public String getQualifiedName(); - - /** - * Gets the fully qualified type container name: Filename or - * enclosing type name with filename. - * All identifiers are separated by colons. - */ - public String getQualifiedParentName(); - - /** - * Gets the fully qualified type name: Includes enclosing type names and - * filename. All identifiers are separated by colons. - */ - public String getFullyQualifiedName(); - - /** - * Gets the CElement which corresponds to this type. - */ - public ICElement getCElement(); -} diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/ITypeInfoFilter.java b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/ITypeInfoFilter.java deleted file mode 100644 index e4895d22ab7..00000000000 --- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/ITypeInfoFilter.java +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2004 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * QNX Software Systems - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.ui.browser.typeinfo; - -/** - * Filter for type info. - */ -public interface ITypeInfoFilter { - - /** - * Gets the C types handled by this filter. - * - * @return An array of ICElement types. - * - */ - public int[] getCElementTypes(); - - /** - * Matches type info against filter. - * - * @param info The object to filter. - * @return true if successful match. - */ - public boolean match(ITypeInfo info); - /** - * Returns true if info matches the filter. - */ -} diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfo.java b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfo.java deleted file mode 100644 index 1bd7d00848d..00000000000 --- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfo.java +++ /dev/null @@ -1,210 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2004 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * QNX Software Systems - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.ui.browser.typeinfo; - -import java.util.ArrayList; - -import org.eclipse.cdt.core.model.CoreModel; -import org.eclipse.cdt.core.model.ICElement; -import org.eclipse.cdt.core.model.IParent; -import org.eclipse.cdt.core.search.BasicSearchMatch; -import org.eclipse.cdt.core.search.ICSearchScope; -import org.eclipse.cdt.internal.core.index.StringMatcher; -import org.eclipse.cdt.internal.ui.browser.util.ArrayUtil; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IResource; - - -/** - * To change the template for this generated type comment go to - * Window>Preferences>Java>Code Generation>Code and Comments - */ -public class TypeInfo extends BasicSearchMatch implements ITypeInfo -{ - private final static int[] cElementTypes= { - ICElement.C_NAMESPACE, - ICElement.C_CLASS, - ICElement.C_TEMPLATE_CLASS, - ICElement.C_STRUCT, - ICElement.C_TEMPLATE_STRUCT, - ICElement.C_UNION, - ICElement.C_TEMPLATE_UNION, - ICElement.C_ENUMERATION, - ICElement.C_TYPEDEF - }; - - public static int[] getAllCElementTypes() { - return cElementTypes; - } - - public static boolean isValidCElementType(int type) { - return ArrayUtil.contains(cElementTypes, type); - } - - private final static String scopeResolutionOperator= "::"; //$NON-NLS-1$ - private final static String fileScopeSeparator= " : "; //$NON-NLS-1$ - private static final StringMatcher fSystemTypeMatcher= new StringMatcher("_*", true, false); //$NON-NLS-1$ - - public TypeInfo() { - super(); - } - - public boolean isEnclosed(ICSearchScope scope) { - return scope.encloses(getFilePath()); - } - - public boolean isSystemType() { - // recognized low-level system types eg __FILE - String[] names= getEnclosingNames(); - if (names != null) { - for (int i= 0; i < names.length; ++i) { - if (fSystemTypeMatcher.match(names[i])) - return true; - } - } - return fSystemTypeMatcher.match(getName()); - } - - public String getFileName() { - if (resource != null) - return resource.getName(); - else if (path != null) - return path.lastSegment(); - else - return null; - } - - public String getFilePath() { - if (resource != null) - return resource.getFullPath().toString(); - else if (path != null) - return path.toString(); - else - return null; - } - - public String getFileExtension() { - if (resource != null) - return resource.getFileExtension(); - else if (path != null) - return path.getFileExtension(); - else - return null; - } - - public String getQualifiedParentName() { - StringBuffer buf= new StringBuffer(); - String fileName = getFileName(); - if (fileName != null && fileName.length() > 0) - buf.append(fileName); - String parentName = getParentName(); - if (parentName != null && parentName.length() > 0) { - buf.append(fileScopeSeparator); //$NON-NLS-1$ - buf.append(parentName); - } - return buf.toString(); - } - - public String getFullyQualifiedName() { - StringBuffer buf= new StringBuffer(); - String fileName = getFileName(); - if (fileName != null && fileName.length() > 0) - buf.append(fileName); - String parentName = getParentName(); - if (parentName != null && parentName.length() > 0) { - buf.append(fileScopeSeparator); //$NON-NLS-1$ - buf.append(parentName); - buf.append(scopeResolutionOperator); //$NON-NLS-1$ - } - String name = getName(); - if (name != null && name.length() > 0) - buf.append(name); - return buf.toString(); - } - - public String getQualifiedName() { - StringBuffer buf= new StringBuffer(); - String parentName = getParentName(); - if (parentName != null && parentName.length() > 0) { - buf.append(parentName); - buf.append(scopeResolutionOperator); //$NON-NLS-1$ - } - String name = getName(); - if (name != null && name.length() > 0) - buf.append(name); - return buf.toString(); - } - - public String[] getEnclosingNames() { - //TODO pull up this method into BasicSearchMatch - //since it already has access to this info - String parentName= getParentName(); - if (parentName == null) - return null; - - ArrayList names= new ArrayList(5); - int lastIndex= 0; - String nextName; - int qualifierIndex= parentName.indexOf(scopeResolutionOperator, 0); - while (qualifierIndex >= 0) { - nextName= parentName.substring(lastIndex, qualifierIndex); - lastIndex= qualifierIndex + scopeResolutionOperator.length(); - names.add(nextName); - qualifierIndex= parentName.indexOf(scopeResolutionOperator, lastIndex); - } - nextName= parentName.substring(lastIndex); - names.add(nextName); - - return (String[]) names.toArray(new String[names.size()]); - } - - public String toString() { - return getFullyQualifiedName(); - } - - private boolean matchesCType(ICElement celement, String name) { - if (isValidCElementType(celement.getElementType())) - return celement.getElementName().equals(name); - return false; - } - - private ICElement findCElement(ICElement celement, String name) { - if (matchesCType(celement, name)) - return celement; - else if (celement instanceof IParent) { - ICElement[] children = ((IParent)celement).getChildren(); - for (int i = 0; i < children.length; i++) { - if (matchesCType(children[i], name)) - return children[i]; - } - } - return null; - } - - public ICElement getCElement() { - if (resource != null && resource.getType() == IResource.FILE) { - ICElement parentElement= CoreModel.getDefault().create((IFile)resource); - if (parentElement instanceof IParent) { - String[] names= getEnclosingNames(); - if (names != null) { - for (int i= 0; i < names.length; ++i) { - parentElement= findCElement(parentElement, names[i]); - if (parentElement == null) - break; - } - } - if (parentElement != null) - return findCElement(parentElement, getName()); - } - } - return null; - } -} diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoFilter.java b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoFilter.java deleted file mode 100644 index 81a24f9209b..00000000000 --- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoFilter.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2004 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * QNX Software Systems - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.ui.browser.typeinfo; - -import org.eclipse.cdt.internal.ui.browser.util.ArrayUtil; - -/** - * The default type filter. - */ -public class TypeInfoFilter implements ITypeInfoFilter { - - public int[] getCElementTypes() { - return TypeInfo.getAllCElementTypes(); - } - - public TypeInfoFilter() { - } - - protected boolean hideSystemTypes() { - return true; - } - - public boolean match(ITypeInfo info) { - // check if type is handled - if (!ArrayUtil.contains(getCElementTypes(), info.getElementType())) - return false; - - // filter out low-level system types eg __FILE - //TODO make this a preferences option - if (hideSystemTypes() && info.isSystemType()) - return false; - - return true; - } -} diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoLabelProvider.java b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoLabelProvider.java index 89dcb588ab2..091f3946395 100644 --- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoLabelProvider.java +++ b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoLabelProvider.java @@ -11,9 +11,11 @@ *******************************************************************************/ package org.eclipse.cdt.ui.browser.typeinfo; +import org.eclipse.cdt.core.browser.ITypeInfo; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.internal.ui.CPluginImages; +import org.eclipse.core.runtime.IPath; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.swt.graphics.Image; @@ -90,32 +92,57 @@ public class TypeInfoLabelProvider extends LabelProvider { } if (isSet(SHOW_ROOT_POSTFIX)) { - String path= typeRef.getFilePath(); - if (path != null && path.length() > 0) { + IPath path= typeRef.getPath(); + if (path != null) { buf.append(TypeInfoMessages.getString("TypeInfoLabelProvider.dash"));//$NON-NLS-1$ - buf.append(path); + buf.append(path.toString()); } } return buf.toString(); } - private Image getFileIcon(ITypeInfo typeRef) + /* non java-doc + * @see ILabelProvider#getImage + */ + public Image getImage(Object element) { + if (!(element instanceof ITypeInfo)) + return super.getImage(element); + + ITypeInfo typeRef= (ITypeInfo) element; + if (isSet(SHOW_TYPE_CONTAINER_ONLY)) { + return getContainerIcon(typeRef); + } else if (isSet(SHOW_FILENAME_ONLY)) { + return getFileIcon(typeRef.getPath()); + } else { + return getTypeIcon(typeRef.getType()); + } + } + + public static Image getContainerIcon(ITypeInfo typeRef) { - String ext = typeRef.getFileExtension(); - if (ext != null) { - String[] exts = CoreModel.getDefault().getHeaderExtensions(); - for (int i = 0; i < exts.length; i++) { - if (exts[i].equalsIgnoreCase(ext)) { - return HEADER_ICON; + //TODO get enclosing types and parent type icon + return getFileIcon(typeRef.getPath()); + } + + public static Image getFileIcon(IPath path) + { + if (path != null) { + String ext= path.getFileExtension(); + if (ext != null) { + String[] exts = CoreModel.getDefault().getHeaderExtensions(); + for (int i = 0; i < exts.length; i++) { + if (exts[i].equalsIgnoreCase(ext)) { + return HEADER_ICON; + } } } } return SOURCE_ICON; } - private Image getIcon(ITypeInfo typeRef) + public static Image getTypeIcon(int type) { - switch (typeRef.getElementType()) + switch (type) { case ICElement.C_NAMESPACE: return NAMESPACE_ICON; @@ -142,21 +169,4 @@ public class TypeInfoLabelProvider extends LabelProvider { return CLASS_ICON; } } - - /* non java-doc - * @see ILabelProvider#getImage - */ - public Image getImage(Object element) { - if (!(element instanceof ITypeInfo)) - return super.getImage(element); - - ITypeInfo typeRef= (ITypeInfo) element; - if (isSet(SHOW_TYPE_CONTAINER_ONLY)) { - return getFileIcon(typeRef); - } else if (isSet(SHOW_FILENAME_ONLY)) { - return getFileIcon(typeRef); - } else { - return getIcon(typeRef); - } - } } diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoMessages.properties b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoMessages.properties index 544dfe5a680..0fa80b8eed7 100644 --- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoMessages.properties +++ b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoMessages.properties @@ -9,11 +9,16 @@ # QNX Software Systems - Initial API and implementation ############################################################################### -TypeCacherJob.jobName=TypeCache -TypeCacherJob.taskName=Updating Type Info... - TypeSelectionDialog.lowerLabel=&Qualifier: TypeSelectionDialog.upperLabel=&Matching types: +TypeSelectionDialog.filterLabel=Visible types: +TypeSelectionDialog.filterNamespaces=namespace +TypeSelectionDialog.filterClasses=class +TypeSelectionDialog.filterStructs=struct +TypeSelectionDialog.filterTypedefs=typedef +TypeSelectionDialog.filterEnums=enum +TypeSelectionDialog.filterUnions=union +TypeSelectionDialog.filterLowLevelTypes=Show low-level types TypeInfoLabelProvider.default_filename=default TypeInfoLabelProvider.dash=\ - diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeSelectionDialog.java b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeSelectionDialog.java index e1e3f1b2736..52e249dae72 100644 --- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeSelectionDialog.java +++ b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeSelectionDialog.java @@ -12,12 +12,29 @@ package org.eclipse.cdt.ui.browser.typeinfo; import java.util.ArrayList; +import java.util.Collection; import java.util.Comparator; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import org.eclipse.cdt.core.browser.*; +import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.internal.ui.util.StringMatcher; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.FilteredList; import org.eclipse.ui.dialogs.TwoPaneElementSelector; @@ -29,40 +46,70 @@ public class TypeSelectionDialog extends TwoPaneElementSelector { private static class TypeFilterMatcher implements FilteredList.FilterMatcher { - private static final char END_SYMBOL= '<'; - private static final char ANY_STRING= '*'; - private final static String scopeResolutionOperator= "::"; //$NON-NLS-1$ + private static final char END_SYMBOL = '<'; + private static final char ANY_STRING = '*'; + private final static String scopeResolutionOperator = "::"; //$NON-NLS-1$ private StringMatcher fMatcher; private StringMatcher fQualifierMatcher; private StringMatcher fScopedQualifierMatcher; + private Collection fVisibleTypes = new HashSet(); + private boolean fShowLowLevelTypes = false; /* * @see FilteredList.FilterMatcher#setFilter(String, boolean) */ public void setFilter(String pattern, boolean ignoreCase, boolean ignoreWildCards) { - int qualifierIndex= pattern.lastIndexOf(scopeResolutionOperator); //$NON-NLS-1$ + int qualifierIndex = pattern.lastIndexOf(scopeResolutionOperator); // type if (qualifierIndex == -1) { - fQualifierMatcher= null; - fScopedQualifierMatcher= null; - fMatcher= new StringMatcher(adjustPattern(pattern), ignoreCase, ignoreWildCards); - + fQualifierMatcher = null; + fScopedQualifierMatcher = null; + fMatcher = new StringMatcher(adjustPattern(pattern), ignoreCase, ignoreWildCards); // qualified type } else { - String pattern1 = pattern.substring(0, qualifierIndex + scopeResolutionOperator.length()); - fQualifierMatcher= new StringMatcher(adjustPattern(pattern1), ignoreCase, ignoreWildCards); + String prefixPattern = pattern.substring(0, qualifierIndex + scopeResolutionOperator.length()); + fQualifierMatcher = new StringMatcher(adjustPattern(prefixPattern), ignoreCase, ignoreWildCards); StringBuffer buf = new StringBuffer(); buf.append(ANY_STRING); buf.append(scopeResolutionOperator); - buf.append(pattern1); - String pattern2= buf.toString(); - fScopedQualifierMatcher= new StringMatcher(adjustPattern(pattern2), ignoreCase, ignoreWildCards); - String pattern3 = pattern.substring(qualifierIndex + scopeResolutionOperator.length()); - fMatcher= new StringMatcher(adjustPattern(pattern3), ignoreCase, ignoreWildCards); + buf.append(prefixPattern); + String scopedPattern = buf.toString(); + fScopedQualifierMatcher = new StringMatcher(adjustPattern(scopedPattern), ignoreCase, ignoreWildCards); + String namePattern = pattern.substring(qualifierIndex + scopeResolutionOperator.length()); + fMatcher = new StringMatcher(adjustPattern(namePattern), ignoreCase, ignoreWildCards); } } + + public void setVisibleTypes(Collection visibleTypes) { + fVisibleTypes.clear(); + fVisibleTypes.addAll(visibleTypes); + } + + public Collection getVisibleTypes() { + return fVisibleTypes; + } + + public void setShowLowLevelTypes(boolean show) { + fShowLowLevelTypes = show; + } + + public boolean getShowLowLevelTypes() { + return fShowLowLevelTypes; + } + + private boolean isLowLevelType(ITypeInfo info) { + String[] enclosingNames = info.getEnclosingNames(); + // filter out low-level system types eg __FILE + if (enclosingNames != null) { + for (int i = 0; i < enclosingNames.length; ++i) { + if (enclosingNames[i].startsWith("_")) //$NON-NLS-1$ + return true; + } + } + return info.getName().startsWith("_"); //$NON-NLS-1$ + } /* * @see FilteredList.FilterMatcher#match(Object) @@ -71,31 +118,37 @@ public class TypeSelectionDialog extends TwoPaneElementSelector { if (!(element instanceof ITypeInfo)) return false; - TypeInfo type= (TypeInfo) element; + TypeInfo info = (TypeInfo) element; + + if (fVisibleTypes != null && !fVisibleTypes.contains(new Integer(info.getType()))) + return false; - if (!fMatcher.match(type.getName())) + if (!fShowLowLevelTypes && isLowLevelType(info)) + return false; + + if (!fMatcher.match(info.getName())) return false; if (fQualifierMatcher == null) return true; - if (fQualifierMatcher.match(type.getQualifiedName())) + if (fQualifierMatcher.match(info.getQualifiedName())) return true; else - return fScopedQualifierMatcher.match(type.getQualifiedName()); + return fScopedQualifierMatcher.match(info.getQualifiedName()); } private String adjustPattern(String pattern) { - int length= pattern.length(); + int length = pattern.length(); if (length > 0) { switch (pattern.charAt(length - 1)) { case END_SYMBOL: - pattern= pattern.substring(0, length - 1); + pattern = pattern.substring(0, length - 1); break; case ANY_STRING: break; default: - pattern= pattern + ANY_STRING; + pattern = pattern + ANY_STRING; } } return pattern; @@ -104,51 +157,384 @@ public class TypeSelectionDialog extends TwoPaneElementSelector { private static class StringComparator implements Comparator { public int compare(Object left, Object right) { - String leftString= (String) left; - String rightString= (String) right; + String leftString = (String) left; + String rightString = (String) right; - int result= leftString.compareToIgnoreCase(rightString); + int result = leftString.compareToIgnoreCase(rightString); if (result == 0) - result= leftString.compareTo(rightString); + result = leftString.compareTo(rightString); return result; } } + + private static final String DIALOG_SETTINGS = TypeSelectionDialog.class.getName(); + private static final String SETTINGS_X_POS = "x"; //$NON-NLS-1$ + private static final String SETTINGS_Y_POS = "y"; //$NON-NLS-1$ + private static final String SETTINGS_WIDTH = "width"; //$NON-NLS-1$ + private static final String SETTINGS_HEIGHT = "height"; //$NON-NLS-1$ + private static final String SETTINGS_SHOW_NAMESPACES = "show_namespaces"; //$NON-NLS-1$ + private static final String SETTINGS_SHOW_CLASSES = "show_classes"; //$NON-NLS-1$ + private static final String SETTINGS_SHOW_STRUCTS = "show_structs"; //$NON-NLS-1$ + private static final String SETTINGS_SHOW_TYPEDEFS = "show_typedefs"; //$NON-NLS-1$ + private static final String SETTINGS_SHOW_ENUMS = "show_enums"; //$NON-NLS-1$ + private static final String SETTINGS_SHOW_UNIONS = "show_unions"; //$NON-NLS-1$ + private static final String SETTINGS_SHOW_LOWLEVEL = "show_lowlevel"; //$NON-NLS-1$ + + private static final TypeInfoLabelProvider fElementRenderer = new TypeInfoLabelProvider(TypeInfoLabelProvider.SHOW_TYPE_ONLY); + private static final TypeInfoLabelProvider fQualifierRenderer = new TypeInfoLabelProvider(TypeInfoLabelProvider.SHOW_TYPE_CONTAINER_ONLY + TypeInfoLabelProvider.SHOW_ROOT_POSTFIX); + private static final TypeFilterMatcher fFilterMatcher = new TypeFilterMatcher(); + private static final StringComparator fStringComparator = new StringComparator(); + + private static final int[] fAllTypes = { ICElement.C_NAMESPACE, ICElement.C_CLASS, + ICElement.C_STRUCT, ICElement.C_TYPEDEF, ICElement.C_ENUMERATION, + ICElement.C_UNION }; + + private Set fKnownTypes = new HashSet(fAllTypes.length); + private Text fTextWidget; + private boolean fSelectFilterText = false; + private FilteredList fNewFilteredList; + private String fDialogSection; + private Point fLocation; + private Point fSize; + /** * Constructs a type selection dialog. * @param parent the parent shell. - * @param context the runnable context. - * @param scope the C search scope. */ public TypeSelectionDialog(Shell parent) { - super(parent, new TypeInfoLabelProvider(TypeInfoLabelProvider.SHOW_TYPE_ONLY), - new TypeInfoLabelProvider(TypeInfoLabelProvider.SHOW_TYPE_CONTAINER_ONLY + TypeInfoLabelProvider.SHOW_ROOT_POSTFIX)); + super(parent, fElementRenderer, fQualifierRenderer); setUpperListLabel(TypeInfoMessages.getString("TypeSelectionDialog.upperLabel")); //$NON-NLS-1$ setLowerListLabel(TypeInfoMessages.getString("TypeSelectionDialog.lowerLabel")); //$NON-NLS-1$ + setVisibleTypes(fAllTypes); + setDialogSettings(DIALOG_SETTINGS); + } + + /** + * Sets the filter pattern. + * @param filter the filter pattern. + * @param selectText true if filter text should be initially selected + * @see org.eclipse.ui.dialogs.AbstractElementListSelectionDialog#setFilter(java.lang.String) + */ + public void setFilter(String filter, boolean selectText) { + super.setFilter(filter); + fSelectFilterText = selectText; } - /* - * @see AbstractElementListSelectionDialog#createFilteredList(Composite) + /** + * Sets which CElement types are visible in the dialog. + * + * @param types Array of CElement types. + */ + public void setVisibleTypes(int[] types) { + fKnownTypes.clear(); + for (int i = 0; i < types.length; ++i) { + fKnownTypes.add(new Integer(types[i])); + } + } + + /** + * Sets section name to use when storing the dialog settings. + * + * @param section Name of section. + */ + public void setDialogSettings(String section) { + fDialogSection = section + "Settings"; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.ui.dialogs.AbstractElementListSelectionDialog#createFilterText(org.eclipse.swt.widgets.Composite) + */ + protected Text createFilterText(Composite parent) { + fTextWidget = super.createFilterText(parent); + + // create type checkboxes below filter text + createTypeFilterArea(parent); + + return fTextWidget; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.dialogs.AbstractElementListSelectionDialog#createFilteredList(org.eclipse.swt.widgets.Composite) */ protected FilteredList createFilteredList(Composite parent) { - FilteredList list= super.createFilteredList(parent); - - fFilteredList.setFilterMatcher(new TypeFilterMatcher()); - fFilteredList.setComparator(new StringComparator()); + fNewFilteredList = super.createFilteredList(parent); + fNewFilteredList.setFilterMatcher(fFilterMatcher); + fNewFilteredList.setComparator(fStringComparator); + return fNewFilteredList; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.window.Window#create() + */ + public void create() { + super.create(); + if (!fSelectFilterText) + fTextWidget.setSelection(0,0); + } + + /* + * @see Window#close() + */ + public boolean close() { + writeSettings(getDialogSettings()); + return super.close(); + } + + /* + * @see org.eclipse.jface.window.Window#createContents(org.eclipse.swt.widgets.Composite) + */ + protected Control createContents(Composite parent) { + readSettings(getDialogSettings()); + return super.createContents(parent); + } + + /** + * Creates a type filter checkbox. + */ + private Button createTypeCheckbox(Composite parent, Integer typeObject) { + String name; + int type = typeObject.intValue(); + switch (type) { + case ICElement.C_NAMESPACE: + name = TypeInfoMessages.getString("TypeSelectionDialog.filterNamespaces"); //$NON-NLS-1$ + break; + case ICElement.C_CLASS: + name = TypeInfoMessages.getString("TypeSelectionDialog.filterClasses"); //$NON-NLS-1$ + break; + case ICElement.C_STRUCT: + name = TypeInfoMessages.getString("TypeSelectionDialog.filterStructs"); //$NON-NLS-1$ + break; + case ICElement.C_TYPEDEF: + name = TypeInfoMessages.getString("TypeSelectionDialog.filterTypedefs"); //$NON-NLS-1$ + break; + case ICElement.C_ENUMERATION: + name = TypeInfoMessages.getString("TypeSelectionDialog.filterEnums"); //$NON-NLS-1$ + break; + case ICElement.C_UNION: + name = TypeInfoMessages.getString("TypeSelectionDialog.filterUnions"); //$NON-NLS-1$ + break; + default: + return null; + }; + Image icon = TypeInfoLabelProvider.getTypeIcon(type); + + final Integer fTypeObject = typeObject; + Button checkbox = new Button(parent, SWT.CHECK); + checkbox.setFont(parent.getFont()); + checkbox.setText(name); + checkbox.setImage(icon); + checkbox.setSelection(fFilterMatcher.getVisibleTypes().contains(fTypeObject)); + checkbox.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + if (e.widget instanceof Button) { + Button checkbox = (Button) e.widget; + if (checkbox.getSelection()) + fFilterMatcher.getVisibleTypes().add(fTypeObject); + else + fFilterMatcher.getVisibleTypes().remove(fTypeObject); + updateElements(); + } + } + }); + return checkbox; + } + + /** + * Creates an area to filter types. + * + * @param parent area to create controls in + */ + private void createTypeFilterArea(Composite parent) { + createLabel(parent, TypeInfoMessages.getString("TypeSelectionDialog.filterLabel")); //$NON-NLS-1$ - return list; + Composite upperRow = new Composite(parent, SWT.NONE); + RowLayout layout = new RowLayout(); + layout.spacing = 10; + layout.marginTop = 0; + layout.marginLeft = 0; + upperRow.setLayout(layout); + + // the for loop is here to guarantee we always + // create the checkboxes in the same order + for (int i = 0; i < fAllTypes.length; ++i) { + Integer typeObject = new Integer(fAllTypes[i]); + if (fKnownTypes.contains(typeObject)) + createTypeCheckbox(upperRow, typeObject); + } + + Composite lowerRow = new Composite(parent, SWT.NONE); + lowerRow.setLayout(layout); + + String name = TypeInfoMessages.getString("TypeSelectionDialog.filterLowLevelTypes"); //$NON-NLS-1$ + Button checkbox = new Button(lowerRow, SWT.CHECK); + checkbox.setFont(lowerRow.getFont()); + checkbox.setText(name); + checkbox.setSelection(fFilterMatcher.getShowLowLevelTypes()); + checkbox.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + if (e.widget instanceof Button) { + Button button = (Button) e.widget; + fFilterMatcher.setShowLowLevelTypes(button.getSelection()); + updateElements(); + } + } + }); } + /** + * Forces redraw of elements list. + */ + private void updateElements() { + fNewFilteredList.setFilter(fTextWidget.getText()); + } + + /** + * Returns the dialog settings object used to save state + * for this dialog. + * + * @return the dialog settings to be used + */ + protected IDialogSettings getDialogSettings() { + IDialogSettings allSettings = CUIPlugin.getDefault().getDialogSettings(); + IDialogSettings section = allSettings.getSection(fDialogSection); + if (section == null) { + section = allSettings.addNewSection(fDialogSection); + writeDefaultSettings(section); + } + return section; + } + + /** + * Stores current configuration in the dialog store. + */ + protected void writeSettings(IDialogSettings section) { + Point location = getShell().getLocation(); + section.put(SETTINGS_X_POS, location.x); + section.put(SETTINGS_Y_POS, location.y); + + Point size = getShell().getSize(); + section.put(SETTINGS_WIDTH, size.x); + section.put(SETTINGS_HEIGHT, size.y); + + section.put(SETTINGS_SHOW_NAMESPACES, fFilterMatcher.getVisibleTypes().contains(new Integer(ICElement.C_NAMESPACE))); + section.put(SETTINGS_SHOW_CLASSES, fFilterMatcher.getVisibleTypes().contains(new Integer(ICElement.C_CLASS))); + section.put(SETTINGS_SHOW_STRUCTS, fFilterMatcher.getVisibleTypes().contains(new Integer(ICElement.C_STRUCT))); + section.put(SETTINGS_SHOW_TYPEDEFS, fFilterMatcher.getVisibleTypes().contains(new Integer(ICElement.C_TYPEDEF))); + section.put(SETTINGS_SHOW_ENUMS, fFilterMatcher.getVisibleTypes().contains(new Integer(ICElement.C_ENUMERATION))); + section.put(SETTINGS_SHOW_UNIONS, fFilterMatcher.getVisibleTypes().contains(new Integer(ICElement.C_UNION))); + section.put(SETTINGS_SHOW_LOWLEVEL, fFilterMatcher.getShowLowLevelTypes()); + } + + /** + * Stores default dialog settings. + */ + protected void writeDefaultSettings(IDialogSettings section) { + section.put(SETTINGS_SHOW_NAMESPACES, true); + section.put(SETTINGS_SHOW_CLASSES, true); + section.put(SETTINGS_SHOW_STRUCTS, true); + section.put(SETTINGS_SHOW_TYPEDEFS, true); + section.put(SETTINGS_SHOW_ENUMS, true); + section.put(SETTINGS_SHOW_UNIONS, true); + section.put(SETTINGS_SHOW_LOWLEVEL, false); + } + + /** + * Initializes itself from the dialog settings with the same state + * as at the previous invocation. + */ + protected void readSettings(IDialogSettings section) { + try { + int x = section.getInt(SETTINGS_X_POS); + int y = section.getInt(SETTINGS_Y_POS); + fLocation = new Point(x, y); + int width = section.getInt(SETTINGS_WIDTH); + int height = section.getInt(SETTINGS_HEIGHT); + fSize = new Point(width, height); + } catch (NumberFormatException e) { + fLocation = null; + fSize = null; + } + + if (section.getBoolean(SETTINGS_SHOW_NAMESPACES)) { + Integer typeObject = new Integer(ICElement.C_NAMESPACE); + if (fKnownTypes.contains(typeObject)) + fFilterMatcher.getVisibleTypes().add(typeObject); + } + if (section.getBoolean(SETTINGS_SHOW_CLASSES)) { + Integer typeObject = new Integer(ICElement.C_CLASS); + if (fKnownTypes.contains(typeObject)) + fFilterMatcher.getVisibleTypes().add(typeObject); + } + if (section.getBoolean(SETTINGS_SHOW_STRUCTS)) { + Integer typeObject = new Integer(ICElement.C_STRUCT); + if (fKnownTypes.contains(typeObject)) + fFilterMatcher.getVisibleTypes().add(typeObject); + } + if (section.getBoolean(SETTINGS_SHOW_TYPEDEFS)) { + Integer typeObject = new Integer(ICElement.C_TYPEDEF); + if (fKnownTypes.contains(typeObject)) + fFilterMatcher.getVisibleTypes().add(typeObject); + } + if (section.getBoolean(SETTINGS_SHOW_ENUMS)) { + Integer typeObject = new Integer(ICElement.C_ENUMERATION); + if (fKnownTypes.contains(typeObject)) + fFilterMatcher.getVisibleTypes().add(typeObject); + } + if (section.getBoolean(SETTINGS_SHOW_UNIONS)) { + Integer typeObject = new Integer(ICElement.C_UNION); + if (fKnownTypes.contains(typeObject)) + fFilterMatcher.getVisibleTypes().add(typeObject); + } + fFilterMatcher.setShowLowLevelTypes(section.getBoolean(SETTINGS_SHOW_LOWLEVEL)); + } + + /* (non-Cdoc) + * @see org.eclipse.jface.window.Window#getInitialSize() + */ + protected Point getInitialSize() { + Point result = super.getInitialSize(); + if (fSize != null) { + result.x = Math.max(result.x, fSize.x); + result.y = Math.max(result.y, fSize.y); + Rectangle display = getShell().getDisplay().getClientArea(); + result.x = Math.min(result.x, display.width); + result.y = Math.min(result.y, display.height); + } + return result; + } + + /* (non-Cdoc) + * @see org.eclipse.jface.window.Window#getInitialLocation(org.eclipse.swt.graphics.Point) + */ + protected Point getInitialLocation(Point initialSize) { + Point result = super.getInitialLocation(initialSize); + if (fLocation != null) { + result.x = fLocation.x; + result.y = fLocation.y; + Rectangle display = getShell().getDisplay().getClientArea(); + int xe = result.x + initialSize.x; + if (xe > display.width) { + result.x -= xe - display.width; + } + int ye = result.y + initialSize.y; + if (ye > display.height) { + result.y -= ye - display.height; + } + } + return result; + } + /* * @see org.eclipse.ui.dialogs.SelectionStatusDialog#computeResult() */ protected void computeResult() { - ITypeInfo selection= (ITypeInfo) getLowerSelectedElement(); + ITypeInfo selection = (ITypeInfo) getLowerSelectedElement(); if (selection == null) return; - List result= new ArrayList(1); + List result = new ArrayList(1); result.add(selection); setResult(result); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java index 0d4abcd89b9..d95e3f30b56 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java @@ -21,6 +21,7 @@ import java.util.ResourceBundle; import java.util.Set; import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.browser.AllTypesCache; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.IWorkingCopy; @@ -44,7 +45,6 @@ import org.eclipse.cdt.internal.ui.text.CTextTools; import org.eclipse.cdt.internal.ui.util.ImageDescriptorRegistry; import org.eclipse.cdt.internal.ui.util.ProblemMarkerManager; import org.eclipse.cdt.internal.ui.util.Util; -import org.eclipse.cdt.ui.browser.typeinfo.AllTypesCache; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; @@ -338,7 +338,12 @@ public class CUIPlugin extends AbstractUIPlugin { public void run() { registerAdapters(); CPluginImages.initialize(); - AllTypesCache.initialize(); + + AllTypesCache.initialize(new AllTypesCache.IWorkingCopyProvider() { + public IWorkingCopy[] getWorkingCopies() { + return CUIPlugin.getSharedWorkingCopies(); + } + }); } }); } -- cgit v1.2.3