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:
parent
b937c683b4
commit
f6a9f8da22
31 changed files with 2822 additions and 1244 deletions
|
@ -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"/>
|
||||
|
|
|
@ -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
|
||||
|
|
2
core/org.eclipse.cdt.core/browser/ChangeLog
Normal file
2
core/org.eclipse.cdt.core/browser/ChangeLog
Normal file
|
@ -0,0 +1,2 @@
|
|||
2004-04-06 Chris Wiebe
|
||||
initial placement of non-ui code into org.eclipse.cdt.core.browser
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,430 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2004 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.browser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.model.CoreModel;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.model.IParent;
|
||||
import org.eclipse.cdt.core.parser.IScannerInfo;
|
||||
import org.eclipse.cdt.core.parser.IScannerInfoProvider;
|
||||
import org.eclipse.cdt.core.search.ICSearchScope;
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
|
||||
|
||||
/**
|
||||
* To change the template for this generated type comment go to
|
||||
* Window>Preferences>Java>Code Generation>Code and Comments
|
||||
*/
|
||||
public class TypeInfo implements ITypeInfo, Comparable
|
||||
{
|
||||
protected final static String scopeResolutionOperator= "::"; //$NON-NLS-1$
|
||||
protected final static String fileScopeSeparator= " : "; //$NON-NLS-1$
|
||||
private String hashString= null;
|
||||
private int hashCode= 0;
|
||||
private String name= null;
|
||||
private int type= 0;
|
||||
private String[] enclosingNames= null;
|
||||
private IResource resource= null;
|
||||
private IPath path= null;
|
||||
private int startOffset= 0;
|
||||
private int endOffset= 0;
|
||||
private ICElement cElement= null;
|
||||
|
||||
public TypeInfo(String name, int type, String[] enclosingNames, IResource resource, IPath path, int startOffset, int endOffset) {
|
||||
init(name, type, enclosingNames, resource, path, startOffset, endOffset);
|
||||
}
|
||||
|
||||
public TypeInfo(String fullName, int type, IPath path, int startOffset, int endOffset) {
|
||||
String name= fullName;
|
||||
String parentName= null;
|
||||
int qualifierIndex= fullName.lastIndexOf(scopeResolutionOperator);
|
||||
if (qualifierIndex >= 0) {
|
||||
parentName= fullName.substring(0, qualifierIndex);
|
||||
name= fullName.substring(qualifierIndex+2);
|
||||
}
|
||||
String[] enclosingNames= null;
|
||||
if (parentName != null)
|
||||
enclosingNames= parseScopedName(parentName);
|
||||
|
||||
init(name, type, enclosingNames, null, path, startOffset, endOffset);
|
||||
}
|
||||
|
||||
public TypeInfo(TypeInfo info) {
|
||||
init(info.name, info.type, info.enclosingNames, info.resource, info.path, info.startOffset, info.endOffset);
|
||||
}
|
||||
|
||||
private void init(String name, int type, String[] enclosingNames, IResource resource, IPath path, int startOffset, int endOffset) {
|
||||
this.name= name;
|
||||
this.type= type;
|
||||
if (enclosingNames != null) {
|
||||
this.enclosingNames= new String[enclosingNames.length];
|
||||
System.arraycopy(enclosingNames, 0, this.enclosingNames, 0, enclosingNames.length);
|
||||
}
|
||||
this.resource= resource;
|
||||
if (path == null && resource != null)
|
||||
path= resource.getFullPath();
|
||||
this.path= path;
|
||||
this.startOffset= startOffset;
|
||||
this.endOffset= endOffset;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String[] getEnclosingNames() {
|
||||
return enclosingNames;
|
||||
}
|
||||
|
||||
public IResource getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
public IPath getPath() {
|
||||
if (resource != null)
|
||||
return resource.getFullPath();
|
||||
else
|
||||
return path;
|
||||
}
|
||||
|
||||
public IPath getLocation() {
|
||||
if (resource != null)
|
||||
return resource.getLocation();
|
||||
else
|
||||
return path;
|
||||
}
|
||||
|
||||
public int getStartOffset() {
|
||||
return startOffset;
|
||||
}
|
||||
|
||||
public int getEndOffset() {
|
||||
return endOffset;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
if (resource != null)
|
||||
return resource.getName();
|
||||
else if (path != null)
|
||||
return path.lastSegment();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getParentName() {
|
||||
if (enclosingNames != null) {
|
||||
StringBuffer buf= new StringBuffer();
|
||||
for (int i= 0; i < enclosingNames.length; ++i) {
|
||||
if (i > 0)
|
||||
buf.append(scopeResolutionOperator);
|
||||
buf.append(enclosingNames[i]);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getQualifiedParentName() {
|
||||
StringBuffer buf= new StringBuffer();
|
||||
String fileName = getFileName();
|
||||
if (fileName != null)
|
||||
buf.append(fileName);
|
||||
String parentName = getParentName();
|
||||
if (parentName != null) {
|
||||
if (fileName != null)
|
||||
buf.append(fileScopeSeparator);
|
||||
buf.append(parentName);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String getQualifiedName() {
|
||||
StringBuffer buf= new StringBuffer();
|
||||
String parentName = getParentName();
|
||||
if (parentName != null)
|
||||
buf.append(parentName);
|
||||
String name = getName();
|
||||
if (name != null) {
|
||||
if (parentName != null)
|
||||
buf.append(scopeResolutionOperator);
|
||||
buf.append(name);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String getFullyQualifiedName() {
|
||||
StringBuffer buf= new StringBuffer();
|
||||
String fileName = getFileName();
|
||||
if (fileName != null)
|
||||
buf.append(fileName);
|
||||
String parentName = getParentName();
|
||||
if (parentName != null) {
|
||||
if (fileName != null)
|
||||
buf.append(fileScopeSeparator);
|
||||
buf.append(parentName);
|
||||
}
|
||||
String name = getName();
|
||||
if (name != null)
|
||||
if (parentName != null)
|
||||
buf.append(scopeResolutionOperator);
|
||||
else if (fileName != null)
|
||||
buf.append(fileScopeSeparator);
|
||||
buf.append(name);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getFullyQualifiedName();
|
||||
}
|
||||
|
||||
public ICElement getCElement() {
|
||||
if (cElement == null)
|
||||
cElement= resolveCElement();
|
||||
return cElement;
|
||||
}
|
||||
|
||||
private ICElement resolveCElement() {
|
||||
if (resource != null && resource.getType() == IResource.FILE) {
|
||||
ICElement parentElement= CoreModel.getDefault().create((IFile)resource);
|
||||
if (parentElement instanceof IParent) {
|
||||
if (enclosingNames != null) {
|
||||
for (int i= 0; i < enclosingNames.length; ++i) {
|
||||
parentElement= findCElement(parentElement, enclosingNames[i]);
|
||||
if (parentElement == null)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (parentElement != null)
|
||||
return findCElement(parentElement, name);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ICElement findCElement(ICElement celement, String name) {
|
||||
if (isValidType(celement.getElementType()) && celement.getElementName().equals(name))
|
||||
return celement;
|
||||
|
||||
if (celement instanceof IParent) {
|
||||
ICElement[] children = ((IParent)celement).getChildren();
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
ICElement child= children[i];
|
||||
if (isValidType(child.getElementType()) && child.getElementName().equals(name))
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public IPath resolveIncludePath(ICProject cProject) {
|
||||
IPath fullPath= getLocation();
|
||||
if (cProject == null || fullPath == null)
|
||||
return null;
|
||||
IProject project= cProject.getProject();
|
||||
IScannerInfoProvider provider= CCorePlugin.getDefault().getScannerInfoProvider(project);
|
||||
if (provider != null) {
|
||||
IScannerInfo info= provider.getScannerInformation(project);
|
||||
if (info != null) {
|
||||
String[] includePaths= info.getIncludePaths();
|
||||
IPath relativePath= null;
|
||||
int mostSegments= 0;
|
||||
for (int i= 0; i < includePaths.length; ++i) {
|
||||
IPath includePath= new Path(includePaths[i]);
|
||||
if (includePath.isPrefixOf(fullPath)) {
|
||||
int segments= includePath.matchingFirstSegments(fullPath);
|
||||
if (segments > mostSegments) {
|
||||
relativePath= fullPath.removeFirstSegments(segments).setDevice(null);
|
||||
mostSegments= segments;
|
||||
}
|
||||
}
|
||||
}
|
||||
return relativePath;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isEnclosed(ICSearchScope scope) {
|
||||
if (scope == null)
|
||||
return false;
|
||||
|
||||
// check if path is in scope
|
||||
IPath path= getPath();
|
||||
if (path != null && scope.encloses(path.toString()))
|
||||
return true;
|
||||
|
||||
// check include paths of enclosing projects
|
||||
IPath[] projectPaths= scope.enclosingProjects();
|
||||
if (projectPaths != null) {
|
||||
for (int i= 0; i < projectPaths.length; ++i) {
|
||||
IPath projPath= projectPaths[i];
|
||||
ICElement elem= CoreModel.getDefault().create(projPath);
|
||||
if (elem != null && elem instanceof ICProject) {
|
||||
ICProject proj= (ICProject) elem;
|
||||
if (resolveIncludePath(proj) != null)
|
||||
return true;
|
||||
// TODO search referenced projects too?
|
||||
// IProject[] refs= proj.getProject().getReferencedProjects();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
if (hashString == null) {
|
||||
hashCode= getHashString().hashCode();
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
private String getHashString() {
|
||||
if (hashString == null) {
|
||||
StringBuffer buf= new StringBuffer(64);
|
||||
|
||||
IPath path= getLocation();
|
||||
if (path != null)
|
||||
buf.append(path.toString());
|
||||
|
||||
buf.append(" ["); //$NON-NLS-1$
|
||||
buf.append(startOffset);
|
||||
buf.append("-"); //$NON-NLS-1$
|
||||
buf.append(endOffset);
|
||||
buf.append("] "); //$NON-NLS-1$
|
||||
|
||||
String parentName= getParentName();
|
||||
if (parentName != null && parentName.length() > 0) {
|
||||
buf.append(parentName);
|
||||
buf.append(scopeResolutionOperator);
|
||||
}
|
||||
String name= getName();
|
||||
if (name != null && name.length() > 0)
|
||||
buf.append(name);
|
||||
|
||||
buf.append(":"); //$NON-NLS-1$
|
||||
buf.append(type);
|
||||
|
||||
hashString= buf.toString();
|
||||
}
|
||||
return hashString;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof TypeInfo)) {
|
||||
return false;
|
||||
}
|
||||
TypeInfo info= (TypeInfo)obj;
|
||||
if (hashCode() != info.hashCode())
|
||||
return false;
|
||||
return getHashString().equals(info.getHashString());
|
||||
}
|
||||
|
||||
public int compareTo(Object obj) {
|
||||
if (obj == this) {
|
||||
return 0;
|
||||
}
|
||||
if( !(obj instanceof TypeInfo)) {
|
||||
throw new ClassCastException();
|
||||
}
|
||||
TypeInfo info= (TypeInfo)obj;
|
||||
return getHashString().compareTo(info.getHashString());
|
||||
}
|
||||
|
||||
public static boolean isValidType(int type) {
|
||||
switch (type) {
|
||||
case ICElement.C_NAMESPACE:
|
||||
case ICElement.C_CLASS:
|
||||
case ICElement.C_STRUCT:
|
||||
case ICElement.C_UNION:
|
||||
case ICElement.C_ENUMERATION:
|
||||
case ICElement.C_TYPEDEF:
|
||||
// case ICElement.C_TEMPLATE_CLASS:
|
||||
// case ICElement.C_TEMPLATE_STRUCT:
|
||||
// case ICElement.C_TEMPLATE_UNION:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] parseScopedName(String scopedName) {
|
||||
ArrayList names= new ArrayList(5);
|
||||
int lastIndex= 0;
|
||||
String nextName;
|
||||
int qualifierIndex= scopedName.indexOf(scopeResolutionOperator, 0);
|
||||
while (qualifierIndex >= 0) {
|
||||
nextName= scopedName.substring(lastIndex, qualifierIndex);
|
||||
lastIndex= qualifierIndex + scopeResolutionOperator.length();
|
||||
names.add(nextName);
|
||||
qualifierIndex= scopedName.indexOf(scopeResolutionOperator, lastIndex);
|
||||
}
|
||||
nextName= scopedName.substring(lastIndex);
|
||||
names.add(nextName);
|
||||
return (String[]) names.toArray(new String[names.size()]);
|
||||
}
|
||||
|
||||
final static private Comparator TYPE_NAME_COMPARATOR= new Comparator() {
|
||||
public int compare(Object o1, Object o2) {
|
||||
return ((ITypeInfo)o1).getName().compareTo(((ITypeInfo)o2).getName());
|
||||
}
|
||||
};
|
||||
|
||||
public static ITypeInfo findType(String name, IPath path, ITypeInfo[] elements) {
|
||||
if (elements == null)
|
||||
return null;
|
||||
|
||||
ITypeInfo key= new TypeInfo(name, 0, path, 0, 0);
|
||||
|
||||
int index= Arrays.binarySearch(elements, key, TYPE_NAME_COMPARATOR);
|
||||
if (index >= 0 && index < elements.length) {
|
||||
for (int i= index - 1; i >= 0; i--) {
|
||||
ITypeInfo curr= elements[i];
|
||||
if (key.getName().equals(curr.getName())) {
|
||||
if (key.getQualifiedName().equals(curr.getQualifiedName())) {
|
||||
return curr;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i= index; i < elements.length; i++) {
|
||||
ITypeInfo curr= elements[i];
|
||||
if (key.getName().equals(curr.getName())) {
|
||||
if (key.getQualifiedName().equals(curr.getQualifiedName())) {
|
||||
return curr;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
152
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCache.java
vendored
Normal file
152
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCache.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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...
|
204
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacherJob.java
vendored
Normal file
204
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacherJob.java
vendored
Normal 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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
561
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchLocator.java
vendored
Normal file
561
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchLocator.java
vendored
Normal 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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$
|
||||
}
|
||||
}
|
|
@ -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/
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
*/
|
||||
}
|
|
@ -1,210 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2004 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.ui.browser.typeinfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.eclipse.cdt.core.model.CoreModel;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.IParent;
|
||||
import org.eclipse.cdt.core.search.BasicSearchMatch;
|
||||
import org.eclipse.cdt.core.search.ICSearchScope;
|
||||
import org.eclipse.cdt.internal.core.index.StringMatcher;
|
||||
import org.eclipse.cdt.internal.ui.browser.util.ArrayUtil;
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
|
||||
|
||||
/**
|
||||
* To change the template for this generated type comment go to
|
||||
* Window>Preferences>Java>Code Generation>Code and Comments
|
||||
*/
|
||||
public class TypeInfo extends BasicSearchMatch implements ITypeInfo
|
||||
{
|
||||
private final static int[] cElementTypes= {
|
||||
ICElement.C_NAMESPACE,
|
||||
ICElement.C_CLASS,
|
||||
ICElement.C_TEMPLATE_CLASS,
|
||||
ICElement.C_STRUCT,
|
||||
ICElement.C_TEMPLATE_STRUCT,
|
||||
ICElement.C_UNION,
|
||||
ICElement.C_TEMPLATE_UNION,
|
||||
ICElement.C_ENUMERATION,
|
||||
ICElement.C_TYPEDEF
|
||||
};
|
||||
|
||||
public static int[] getAllCElementTypes() {
|
||||
return cElementTypes;
|
||||
}
|
||||
|
||||
public static boolean isValidCElementType(int type) {
|
||||
return ArrayUtil.contains(cElementTypes, type);
|
||||
}
|
||||
|
||||
private final static String scopeResolutionOperator= "::"; //$NON-NLS-1$
|
||||
private final static String fileScopeSeparator= " : "; //$NON-NLS-1$
|
||||
private static final StringMatcher fSystemTypeMatcher= new StringMatcher("_*", true, false); //$NON-NLS-1$
|
||||
|
||||
public TypeInfo() {
|
||||
super();
|
||||
}
|
||||
|
||||
public boolean isEnclosed(ICSearchScope scope) {
|
||||
return scope.encloses(getFilePath());
|
||||
}
|
||||
|
||||
public boolean isSystemType() {
|
||||
// recognized low-level system types eg __FILE
|
||||
String[] names= getEnclosingNames();
|
||||
if (names != null) {
|
||||
for (int i= 0; i < names.length; ++i) {
|
||||
if (fSystemTypeMatcher.match(names[i]))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return fSystemTypeMatcher.match(getName());
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
if (resource != null)
|
||||
return resource.getName();
|
||||
else if (path != null)
|
||||
return path.lastSegment();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
if (resource != null)
|
||||
return resource.getFullPath().toString();
|
||||
else if (path != null)
|
||||
return path.toString();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getFileExtension() {
|
||||
if (resource != null)
|
||||
return resource.getFileExtension();
|
||||
else if (path != null)
|
||||
return path.getFileExtension();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getQualifiedParentName() {
|
||||
StringBuffer buf= new StringBuffer();
|
||||
String fileName = getFileName();
|
||||
if (fileName != null && fileName.length() > 0)
|
||||
buf.append(fileName);
|
||||
String parentName = getParentName();
|
||||
if (parentName != null && parentName.length() > 0) {
|
||||
buf.append(fileScopeSeparator); //$NON-NLS-1$
|
||||
buf.append(parentName);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String getFullyQualifiedName() {
|
||||
StringBuffer buf= new StringBuffer();
|
||||
String fileName = getFileName();
|
||||
if (fileName != null && fileName.length() > 0)
|
||||
buf.append(fileName);
|
||||
String parentName = getParentName();
|
||||
if (parentName != null && parentName.length() > 0) {
|
||||
buf.append(fileScopeSeparator); //$NON-NLS-1$
|
||||
buf.append(parentName);
|
||||
buf.append(scopeResolutionOperator); //$NON-NLS-1$
|
||||
}
|
||||
String name = getName();
|
||||
if (name != null && name.length() > 0)
|
||||
buf.append(name);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String getQualifiedName() {
|
||||
StringBuffer buf= new StringBuffer();
|
||||
String parentName = getParentName();
|
||||
if (parentName != null && parentName.length() > 0) {
|
||||
buf.append(parentName);
|
||||
buf.append(scopeResolutionOperator); //$NON-NLS-1$
|
||||
}
|
||||
String name = getName();
|
||||
if (name != null && name.length() > 0)
|
||||
buf.append(name);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String[] getEnclosingNames() {
|
||||
//TODO pull up this method into BasicSearchMatch
|
||||
//since it already has access to this info
|
||||
String parentName= getParentName();
|
||||
if (parentName == null)
|
||||
return null;
|
||||
|
||||
ArrayList names= new ArrayList(5);
|
||||
int lastIndex= 0;
|
||||
String nextName;
|
||||
int qualifierIndex= parentName.indexOf(scopeResolutionOperator, 0);
|
||||
while (qualifierIndex >= 0) {
|
||||
nextName= parentName.substring(lastIndex, qualifierIndex);
|
||||
lastIndex= qualifierIndex + scopeResolutionOperator.length();
|
||||
names.add(nextName);
|
||||
qualifierIndex= parentName.indexOf(scopeResolutionOperator, lastIndex);
|
||||
}
|
||||
nextName= parentName.substring(lastIndex);
|
||||
names.add(nextName);
|
||||
|
||||
return (String[]) names.toArray(new String[names.size()]);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getFullyQualifiedName();
|
||||
}
|
||||
|
||||
private boolean matchesCType(ICElement celement, String name) {
|
||||
if (isValidCElementType(celement.getElementType()))
|
||||
return celement.getElementName().equals(name);
|
||||
return false;
|
||||
}
|
||||
|
||||
private ICElement findCElement(ICElement celement, String name) {
|
||||
if (matchesCType(celement, name))
|
||||
return celement;
|
||||
else if (celement instanceof IParent) {
|
||||
ICElement[] children = ((IParent)celement).getChildren();
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
if (matchesCType(children[i], name))
|
||||
return children[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ICElement getCElement() {
|
||||
if (resource != null && resource.getType() == IResource.FILE) {
|
||||
ICElement parentElement= CoreModel.getDefault().create((IFile)resource);
|
||||
if (parentElement instanceof IParent) {
|
||||
String[] names= getEnclosingNames();
|
||||
if (names != null) {
|
||||
for (int i= 0; i < names.length; ++i) {
|
||||
parentElement= findCElement(parentElement, names[i]);
|
||||
if (parentElement == null)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (parentElement != null)
|
||||
return findCElement(parentElement, getName());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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=\ -
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue