1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

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.
This commit is contained in:
Alain Magloire 2004-04-07 00:32:13 +00:00
parent b937c683b4
commit f6a9f8da22
31 changed files with 2822 additions and 1244 deletions

View file

@ -7,6 +7,7 @@
<classpathentry kind="src" path="search"/>
<classpathentry kind="src" path="dependency"/>
<classpathentry kind="src" path="parser"/>
<classpathentry kind="src" path="browser"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>

View file

@ -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

View file

@ -0,0 +1,2 @@
2004-04-06 Chris Wiebe
initial placement of non-ui code into org.eclipse.cdt.core.browser

View file

@ -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 <code>ICElement</code>
* the methods of this class returns a list of the lightweight objects <code>TypeInfo</code>.
* <P>
* 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.
* <P>
* If <code>getTypes</code> 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 <code>TypeInfo</code> 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();
}
}
}

View file

@ -8,47 +8,74 @@
* Contributors:
* QNX Software Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.browser.typeinfo;
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.cdt.core.search.IMatch;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
/**
* Type information.
*/
public interface ITypeInfo extends IMatch {
/**
* Returns true if type is enclosed in the given scope
*/
public boolean isEnclosed(ICSearchScope scope);
public interface ITypeInfo {
/**
* Returns true if the type is a low-level system type.
* e.g. __FILE
* Gets the CElement type.
*/
public boolean isSystemType();
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 file path where this type is located.
* Gets the fully qualified type container name: Includes enclosing type names, but
* not filename. Identifiers are separated by colons.
*/
public String getFilePath();
/**
* Gets the extension of the file where this type is located.
*/
public String getFileExtension();
public String getParentName();
/**
* Gets the type qualified name: Includes enclosing type names, but
@ -73,4 +100,13 @@ public interface ITypeInfo extends IMatch {
* 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
* <code>null</code> if not found.
*/
public IPath resolveIncludePath(ICProject cProject);
}

View file

@ -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&gt;Preferences&gt;Java&gt;Code Generation&gt;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;
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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...

View file

@ -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();
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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));
}
}

View file

@ -8,7 +8,7 @@
* Contributors:
* QNX Software Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.browser.util;
package org.eclipse.cdt.internal.core.browser.util;
/**
* A helper class which allows you to perform some
@ -20,6 +20,8 @@ public class 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;
@ -29,6 +31,8 @@ public class ArrayUtil {
// 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;
@ -38,9 +42,11 @@ public class ArrayUtil {
// 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]= newSet[i];
newSet[i]= fromSet[i];
}
return newSet;
}

View file

@ -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
* <code>IProgressMonitor</code> and <code>IProgressMonitorWithBlocking</code>
* 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 <code>addDelegate()</code>.
*/
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);
}
}
}

View file

@ -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);
}
}

View file

@ -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$
}
}

View file

@ -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/

View file

@ -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.

View file

@ -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 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();
final ArrayList typeList= new ArrayList();
final TypeInfoFilter filter= new TypeInfoFilter();
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

View file

@ -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 <code>OpenTypeDialog</code>.
* @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);
}
}

View file

@ -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
* <code>IProgressMonitor</code> and <code>IProgressMonitorWithBlocking</code>
* 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();
}
}

View file

@ -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 <code>ICElement</code>
* the methods of this class returns a list of the lightweight objects <code>TypeInfo</code>.
* <P>
* 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.
* <P>
* If <code>getAllTypes</code> 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 <code>TypeInfo</code> 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();
}
}

View file

@ -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 <code>true</code> if successful match.
*/
public boolean match(ITypeInfo info);
/**
* Returns <code>true</code> if <code>info</code> matches the filter.
*/
}

View file

@ -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&gt;Preferences&gt;Java&gt;Code Generation&gt;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;
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}
}

View file

@ -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=\ -

View file

@ -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 <code>true</code> 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;
}
/**
* 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) {
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 AbstractElementListSelectionDialog#createFilteredList(Composite)
* @see Window#close()
*/
protected FilteredList createFilteredList(Composite parent) {
FilteredList list= super.createFilteredList(parent);
fFilteredList.setFilterMatcher(new TypeFilterMatcher());
fFilteredList.setComparator(new StringComparator());
return list;
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$
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);
}

View file

@ -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();
}
});
}
});
}