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

LabelProvider to decorate indexed files, bug 159731.

This commit is contained in:
Markus Schorn 2008-02-27 10:48:53 +00:00
parent 41becf515a
commit 8c248ed68b
20 changed files with 636 additions and 135 deletions

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2007 IBM Corporation.
* Copyright (c) 2006, 2008 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -9,7 +9,6 @@
* IBM Corporation - initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.pdom.tests;
import junit.framework.Test;
@ -48,12 +47,14 @@ public class CPPFunctionTests extends PDOMTestBase {
return suite(CPPFunctionTests.class);
}
@Override
protected void setUp() throws Exception {
project = createProject("functionTests");
pdom = (PDOM) CCoreInternals.getPDOMManager().getPDOM(project);
pdom.acquireReadLock();
}
@Override
protected void tearDown() throws Exception {
pdom.releaseReadLock();
if (project != null) {
@ -172,17 +173,17 @@ public class CPPFunctionTests extends PDOMTestBase {
for (int i = 0; i < 2; i++) {
ICPPFunction function = (ICPPFunction) bindings[i];
assertEquals(1, pdom.findNames(function, IIndex.FIND_DECLARATIONS_DEFINITIONS).length);
assertEquals(1, pdom.getDefinitions(function).length);
assertEquals(1, pdom.findNames(function, IIndex.FIND_DEFINITIONS).length);
IParameter[] parameters = function.getParameters();
switch (parameters.length) {
case 0:
assertFalse(seen[0]);
assertEquals(1, pdom.getReferences(function).length);
assertEquals(1, pdom.findNames(function, IIndex.FIND_REFERENCES).length);
seen[0] = true;
break;
case 1:
assertFalse(seen[1]);
assertEquals(2, pdom.getReferences(function).length);
assertEquals(2, pdom.findNames(function, IIndex.FIND_REFERENCES).length);
assertEquals("p1", parameters[0].getName());
assertEquals(IBasicType.t_int, ((ICPPBasicType) parameters[0].getType()).getType());
seen[1] = true;

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -8,13 +8,14 @@
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.index;
import java.util.Set;
import org.eclipse.cdt.core.model.ICProject;
/**
* IndexChangeEvents descrive changes to the index.
* IndexChangeEvents describe changes to the index.
* <p>
* <strong>EXPERIMENTAL</strong>. This class or interface has been added as
* part of a work in progress. There is no guarantee that this API will work or
@ -30,4 +31,27 @@ public interface IIndexChangeEvent {
* Returns the project for which the index has changed.
*/
public ICProject getAffectedProject();
/**
* Returns <code>true</code> when the index for the project was loaded for the first time or
* reloaded with a different database.
*/
public boolean isReloaded();
/**
* Returns <code>true</code> when the index for the project was cleared.
*/
public boolean isCleared();
/**
* Returns the set of files that has been cleared in the index. When {@link #isCleared()}
* returns <code>true</code>, the set will be empty.
*/
public Set<IIndexFileLocation> getFilesCleared();
/**
* Returns the set of files that has been added or updated. When {@link #isCleared()} returns
* <code>true</code>, the files of the set have been written after the index was cleared.
*/
public Set<IIndexFileLocation> getFilesWritten();
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -8,12 +8,10 @@
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.index;
/**
* IndexChangeEvents descrive changes to the state of the indexer.
* IndexChangeEvents describe changes to the state of the indexer.
* <p>
* <strong>EXPERIMENTAL</strong>. This class or interface has been added as
* part of a work in progress. There is no guarantee that this API will work or

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -8,29 +8,52 @@
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.index;
import java.util.Set;
import org.eclipse.cdt.core.index.IIndexChangeEvent;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.internal.core.pdom.PDOM.ChangeEvent;
public class IndexChangeEvent implements IIndexChangeEvent {
private ICProject fAffectedProject;
private ChangeEvent fChangeEvent;
public IndexChangeEvent(ICProject projectChanged) {
public IndexChangeEvent(ICProject projectChanged, ChangeEvent e) {
fAffectedProject= projectChanged;
fChangeEvent= e;
}
public IndexChangeEvent() {
fAffectedProject= null;
fChangeEvent= new ChangeEvent();
}
public ICProject getAffectedProject() {
return fAffectedProject;
}
public void setAffectedProject(ICProject project) {
public void setAffectedProject(ICProject project, ChangeEvent e) {
fAffectedProject= project;
fChangeEvent= e;
}
public Set<IIndexFileLocation> getFilesCleared() {
return fChangeEvent.fClearedFiles;
}
public Set<IIndexFileLocation> getFilesWritten() {
return fChangeEvent.fFilesWritten;
}
public boolean isCleared() {
return fChangeEvent.fCleared;
}
public boolean isReloaded() {
return fChangeEvent.fReloaded;
}
}

View file

@ -0,0 +1,53 @@
/*******************************************************************************
* Copyright (c) 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom;
import org.eclipse.cdt.internal.core.index.IndexerStateEvent;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.Job;
/**
* Notifies clients of the indexer state.
*/
class JobChangeListener implements IJobChangeListener {
private final PDOMManager fPDomManager;
JobChangeListener(PDOMManager pdomManager) {
fPDomManager= pdomManager;
}
public void aboutToRun(IJobChangeEvent event) {
}
public void awake(IJobChangeEvent event) {
}
public void done(IJobChangeEvent event) {
if (event.getJob().belongsTo(fPDomManager)) {
if (Job.getJobManager().find(fPDomManager).length == 0) {
fPDomManager.fireStateChange(IndexerStateEvent.STATE_IDLE);
}
}
}
public void running(IJobChangeEvent event) {
}
public void scheduled(IJobChangeEvent event) {
if (event.getJob().belongsTo(fPDomManager)) {
fPDomManager.fireStateChange(IndexerStateEvent.STATE_BUSY);
}
}
public void sleeping(IJobChangeEvent event) {
}
}

View file

@ -20,15 +20,16 @@ import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.IPDOMNode;
import org.eclipse.cdt.core.dom.IPDOMVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException;
@ -45,7 +46,6 @@ import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexLinkage;
import org.eclipse.cdt.core.index.IIndexLocationConverter;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.internal.core.index.IIndexCBindingConstants;
import org.eclipse.cdt.internal.core.index.IIndexFragment;
@ -168,6 +168,30 @@ public class PDOM extends PlatformObject implements IPDOM {
assert END <= Database.CHUNK_SIZE;
}
public static class ChangeEvent {
public Set<IIndexFileLocation> fClearedFiles= new HashSet<IIndexFileLocation>();
public Set<IIndexFileLocation> fFilesWritten= new HashSet<IIndexFileLocation>();
public boolean fCleared= false;
public boolean fReloaded= false;
private void setCleared() {
fReloaded= false;
fCleared= true;
fClearedFiles.clear();
fFilesWritten.clear();
}
public void clear() {
fReloaded= fCleared= false;
fClearedFiles.clear();
fFilesWritten.clear();
}
}
public static interface IListener {
public void handleChange(PDOM pdom, ChangeEvent event);
}
// Local caches
protected Database db;
private BTree fileIndex;
@ -177,7 +201,8 @@ public class PDOM extends PlatformObject implements IPDOM {
private IIndexLocationConverter locationConverter;
private Map<String, IPDOMLinkageFactory> fPDOMLinkageFactoryCache;
private HashMap<Object, Object> fResultCache= new HashMap<Object, Object>();
private List<IListener> listeners;
protected ChangeEvent fEvent= new ChangeEvent();
public PDOM(File dbPath, IIndexLocationConverter locationConverter, Map<String, IPDOMLinkageFactory> linkageFactoryMappings) throws CoreException {
this(dbPath, locationConverter, ChunkCache.getSharedInstance(), linkageFactoryMappings);
@ -231,12 +256,6 @@ public class PDOM extends PlatformObject implements IPDOM {
}
}
public static interface IListener {
public void handleChange(PDOM pdom);
}
private List<IListener> listeners;
public void addListener(IListener listener) {
if (listeners == null)
listeners = new LinkedList<IListener>();
@ -249,12 +268,12 @@ public class PDOM extends PlatformObject implements IPDOM {
listeners.remove(listener);
}
private void fireChange() {
private void fireChange(ChangeEvent event) {
if (listeners == null)
return;
Iterator<IListener> i = listeners.iterator();
while (i.hasNext())
i.next().handleChange(this);
i.next().handleChange(this, event);
}
public Database getDB() {
@ -311,6 +330,7 @@ public class PDOM extends PlatformObject implements IPDOM {
// Clear out the database, everything is set to zero.
db.clear(CURRENT_VERSION);
clearCaches();
fEvent.setCleared();
}
void reloadFromFile(File file) throws CoreException {
@ -325,42 +345,13 @@ public class PDOM extends PlatformObject implements IPDOM {
loadDatabase(file, db.getChunkCache());
db.setExclusiveLock();
oldFile.delete();
fEvent.fReloaded= true;
}
public boolean isEmpty() throws CoreException {
return getFirstLinkageRecord() == 0;
}
/**
* @deprecated use findDefinitions() instead
*/
public IName[] getDefinitions(IBinding binding) throws CoreException {
if (binding instanceof PDOMBinding) {
List<PDOMName> names = new ArrayList<PDOMName>();
for (PDOMName name = ((PDOMBinding)binding).getFirstDefinition();
name != null;
name = name.getNextInBinding())
names.add(name);
return names.toArray(new IIndexName[names.size()]);
}
return IIndexFragmentName.EMPTY_NAME_ARRAY;
}
/**
* @deprecated use findReferences() instead
*/
public IName[] getReferences(IBinding binding) throws CoreException {
if (binding instanceof PDOMBinding) {
List<PDOMName> names = new ArrayList<PDOMName>();
for (PDOMName name = ((PDOMBinding)binding).getFirstReference();
name != null;
name = name.getNextInBinding())
names.add(name);
return names.toArray(new IIndexName[names.size()]);
}
return IIndexFragmentName.EMPTY_NAME_ARRAY;
}
public IIndexFragmentBinding findBinding(IASTName name) throws CoreException {
PDOMLinkage linkage= adaptLinkage(name.getLinkage());
if (linkage != null) {
@ -669,13 +660,15 @@ public class PDOM extends PlatformObject implements IPDOM {
}
assert lockCount == -1;
lastWriteAccess= System.currentTimeMillis();
final ChangeEvent event= fEvent;
fEvent= new ChangeEvent();
synchronized (mutex) {
if (lockCount < 0)
lockCount= establishReadLocks;
mutex.notifyAll();
db.setLocked(lockCount != 0);
}
fireChange();
fireChange(event);
}
@ -932,6 +925,7 @@ public class PDOM extends PlatformObject implements IPDOM {
IndexFilter filter= null;
if (binding instanceof IFunction) {
filter= new IndexFilter() {
@Override
public boolean acceptBinding(IBinding binding) {
try {
if (binding instanceof ICPPFunction) {
@ -945,6 +939,7 @@ public class PDOM extends PlatformObject implements IPDOM {
} else if (binding instanceof IVariable) {
if (!(binding instanceof IField) && !(binding instanceof IParameter)) {
filter= new IndexFilter() {
@Override
public boolean acceptBinding(IBinding binding) {
try {
if (binding instanceof ICPPVariable) {

View file

@ -143,12 +143,11 @@ public class PDOMManager implements IWritableIndexManager, IListener {
private static final ISchedulingRule INIT_INDEXER_SCHEDULING_RULE = new PerInstanceSchedulingRule();
/**
* Protects indexerJob, currentTask and taskQueue.
* Protects fIndexerJob, fCurrentTask and fTaskQueue.
*/
private Object fTaskQueueMutex = new Object();
private final LinkedList<IPDOMIndexerTask> fTaskQueue = new LinkedList<IPDOMIndexerTask>();
private PDOMIndexerJob fIndexerJob;
private IPDOMIndexerTask fCurrentTask;
private LinkedList<IPDOMIndexerTask> fTaskQueue = new LinkedList<IPDOMIndexerTask>();
private int fSourceCount, fHeaderCount, fTickCount;
/**
@ -165,6 +164,7 @@ public class PDOMManager implements IWritableIndexManager, IListener {
private CModelListener fCModelListener= new CModelListener(this);
private ILanguageMappingChangeListener fLanguageChangeListener = new LanguageMappingChangeListener(this);
private final ICProjectDescriptionListener fProjectDescriptionListener;
private final JobChangeListener fJobChangeListener;
private IndexFactory fIndexFactory= new IndexFactory(this);
private IndexProviderManager fIndexProviderManager = new IndexProviderManager();
@ -178,9 +178,11 @@ public class PDOMManager implements IWritableIndexManager, IListener {
private HashMap<IProject, PCL> fPrefListeners= new HashMap<IProject, PCL>();
private ArrayList<IndexerSetupParticipant> fSetupParticipants= new ArrayList<IndexerSetupParticipant>();
private HashSet<ICProject> fPostponedProjects= new HashSet<ICProject>();
private int fLastNotifiedState= IndexerStateEvent.STATE_IDLE;
public PDOMManager() {
fProjectDescriptionListener= new CProjectDescriptionListener(this);
fJobChangeListener= new JobChangeListener(this);
}
public Job startup() {
@ -207,7 +209,7 @@ public class PDOMManager implements IWritableIndexManager, IListener {
// order to avoid a race condition where its not noticed
// that new projects are being created
initializeDatabaseCache();
Job.getJobManager().addJobChangeListener(fJobChangeListener);
fIndexProviderManager.startup();
final CoreModel model = CoreModel.getDefault();
@ -234,15 +236,16 @@ public class PDOMManager implements IWritableIndexManager, IListener {
ResourcesPlugin.getWorkspace().removeResourceChangeListener(fCModelListener);
LanguageManager.getInstance().unregisterLanguageChangeListener(fLanguageChangeListener);
PDOMIndexerJob jobToCancel= null;
synchronized (fTaskQueueMutex) {
synchronized (fTaskQueue) {
fTaskQueue.clear();
jobToCancel= fIndexerJob;
}
if (jobToCancel != null) {
assert !Thread.holdsLock(fTaskQueueMutex);
assert !Thread.holdsLock(fTaskQueue);
jobToCancel.cancelJobs(null, false);
}
Job.getJobManager().removeJobChangeListener(fJobChangeListener);
}
private void initializeDatabaseCache() {
@ -589,7 +592,7 @@ public class PDOMManager implements IWritableIndexManager, IListener {
if (indexer != null) {
getReferencingProjects(indexer.getProject().getProject(), referencing);
}
synchronized (fTaskQueueMutex) {
synchronized (fTaskQueue) {
int i=0;
for (Iterator<IPDOMIndexerTask> it = fTaskQueue.iterator(); it.hasNext();) {
final IPDOMIndexerTask task= it.next();
@ -608,7 +611,6 @@ public class PDOMManager implements IWritableIndexManager, IListener {
fIndexerJob = new PDOMIndexerJob(this);
fIndexerJob.setRule(INDEXER_SCHEDULING_RULE);
fIndexerJob.schedule();
notifyState(IndexerStateEvent.STATE_BUSY);
}
}
}
@ -626,11 +628,10 @@ public class PDOMManager implements IWritableIndexManager, IListener {
IPDOMIndexerTask getNextTask() {
IPDOMIndexerTask result= null;
synchronized (fTaskQueueMutex) {
synchronized (fTaskQueue) {
if (fTaskQueue.isEmpty()) {
fCurrentTask= null;
fIndexerJob= null;
notifyState(IndexerStateEvent.STATE_IDLE);
}
else {
if (fCurrentTask != null) {
@ -647,14 +648,13 @@ public class PDOMManager implements IWritableIndexManager, IListener {
}
void cancelledJob(boolean byManager) {
synchronized (fTaskQueueMutex) {
synchronized (fTaskQueue) {
fCurrentTask= null;
if (!byManager) {
fTaskQueue.clear();
}
if (fTaskQueue.isEmpty()) {
fIndexerJob= null;
notifyState(IndexerStateEvent.STATE_IDLE);
}
else {
fIndexerJob = new PDOMIndexerJob(this);
@ -857,7 +857,7 @@ public class PDOMManager implements IWritableIndexManager, IListener {
private void cancelIndexerJobs(IPDOMIndexer indexer) {
PDOMIndexerJob jobToCancel= null;
synchronized (fTaskQueueMutex) {
synchronized (fTaskQueue) {
for (Iterator<IPDOMIndexerTask> iter = fTaskQueue.iterator(); iter.hasNext();) {
IPDOMIndexerTask task= iter.next();
if (task.getIndexer() == indexer) {
@ -868,7 +868,7 @@ public class PDOMManager implements IWritableIndexManager, IListener {
}
if (jobToCancel != null) {
assert !Thread.holdsLock(fTaskQueueMutex);
assert !Thread.holdsLock(fTaskQueue);
jobToCancel.cancelJobs(indexer, true);
}
}
@ -922,43 +922,43 @@ public class PDOMManager implements IWritableIndexManager, IListener {
fStateListeners.remove(listener);
}
private void notifyState(final int state) {
if (state == IndexerStateEvent.STATE_IDLE) {
synchronized(fTaskQueueMutex) {
fTaskQueueMutex.notifyAll();
void fireStateChange(final int state) {
synchronized(fStateListeners) {
if (fLastNotifiedState == state) {
return;
}
}
if (fStateListeners.isEmpty()) {
return;
}
Job notify= new Job(Messages.PDOMManager_notifyJob_label) {
@Override
protected IStatus run(IProgressMonitor monitor) {
fIndexerStateEvent.setState(state);
Object[] listeners= fStateListeners.getListeners();
monitor.beginTask(Messages.PDOMManager_notifyTask_message, listeners.length);
for (int i = 0; i < listeners.length; i++) {
final IIndexerStateListener listener = (IIndexerStateListener) listeners[i];
SafeRunner.run(new ISafeRunnable(){
public void handleException(Throwable exception) {
CCorePlugin.log(exception);
}
public void run() throws Exception {
listener.indexChanged(fIndexerStateEvent);
}
});
monitor.worked(1);
fLastNotifiedState= state;
if (fStateListeners.isEmpty()) {
return;
}
Job notify= new Job(Messages.PDOMManager_notifyJob_label) {
@Override
protected IStatus run(IProgressMonitor monitor) {
fIndexerStateEvent.setState(state);
Object[] listeners= fStateListeners.getListeners();
monitor.beginTask(Messages.PDOMManager_notifyTask_message, listeners.length);
for (int i = 0; i < listeners.length; i++) {
final IIndexerStateListener listener = (IIndexerStateListener) listeners[i];
SafeRunner.run(new ISafeRunnable(){
public void handleException(Throwable exception) {
CCorePlugin.log(exception);
}
public void run() throws Exception {
listener.indexChanged(fIndexerStateEvent);
}
});
monitor.worked(1);
}
return Status.OK_STATUS;
}
return Status.OK_STATUS;
}
};
notify.setRule(NOTIFICATION_SCHEDULING_RULE);
notify.setSystem(true);
notify.schedule();
};
notify.setRule(NOTIFICATION_SCHEDULING_RULE);
notify.setSystem(true);
notify.schedule();
}
}
public void handleChange(PDOM pdom) {
public void handleChange(PDOM pdom, final PDOM.ChangeEvent e) {
if (fChangeListeners.isEmpty()) {
return;
}
@ -973,7 +973,7 @@ public class PDOMManager implements IWritableIndexManager, IListener {
Job notify= new Job(Messages.PDOMManager_notifyJob_label) {
@Override
protected IStatus run(IProgressMonitor monitor) {
fIndexChangeEvent.setAffectedProject(finalProject);
fIndexChangeEvent.setAffectedProject(finalProject, e);
Object[] listeners= fChangeListeners.getListeners();
monitor.beginTask(Messages.PDOMManager_notifyTask_message, listeners.length);
for (int i = 0; i < listeners.length; i++) {
@ -1032,11 +1032,11 @@ public class PDOMManager implements IWritableIndexManager, IListener {
}
int getMonitorMessage(IProgressMonitor monitor, int currentTicks, int base) {
assert !Thread.holdsLock(fTaskQueueMutex);
assert !Thread.holdsLock(fTaskQueue);
int sourceCount, sourceEstimate, headerCount, tickCount, tickEstimate;
String detail= null;
synchronized (fTaskQueueMutex) {
synchronized (fTaskQueue) {
// add historic data
sourceCount= sourceEstimate= fSourceCount;
headerCount= fHeaderCount;

View file

@ -26,6 +26,7 @@ import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFileSet;
import org.eclipse.cdt.internal.core.index.IIndexFragmentInclude;
import org.eclipse.cdt.internal.core.index.IIndexFragmentName;
import org.eclipse.cdt.internal.core.pdom.PDOM.ChangeEvent;
import org.eclipse.cdt.internal.core.pdom.PDOM.IListener;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
import org.eclipse.core.runtime.CoreException;
@ -214,9 +215,11 @@ public class PDOMProxy implements IPDOM {
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
ChangeEvent event= new ChangeEvent();
event.fReloaded= true;
for (Iterator<IListener> iterator = fListeners.iterator(); iterator.hasNext();) {
IListener listener = iterator.next();
listener.handleChange(fDelegate);
listener.handleChange(fDelegate, event);
}
}

View file

@ -9,7 +9,6 @@
* Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom;
import java.io.File;
@ -75,11 +74,17 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
finally {
fPathResolver= origResolver;
}
final IIndexFileLocation location = pdomFile.getLocation();
fEvent.fClearedFiles.remove(location);
fEvent.fFilesWritten.add(location);
}
public void clearFile(IIndexFragmentFile file, Collection<IIndexFileLocation> contextsRemoved) throws CoreException {
assert file.getIndexFragment() == this;
((PDOMFile) file).clear(contextsRemoved);
fEvent.fClearedFiles.add(file.getLocation());
}
@Override

View file

@ -52,6 +52,7 @@ import org.eclipse.core.runtime.CoreException;
public class PDOMFile implements IIndexFragmentFile {
private final PDOM pdom;
private final int record;
private IIndexFileLocation location;
private static final int FIRST_NAME = 0;
private static final int FIRST_INCLUDE = 4;
@ -90,6 +91,7 @@ public class PDOMFile implements IIndexFragmentFile {
public PDOMFile(PDOM pdom, IIndexFileLocation location, int linkageID) throws CoreException {
this.pdom = pdom;
this.location= location;
Database db = pdom.getDB();
record = db.malloc(RECORD_SIZE);
String locationString = pdom.getLocationConverter().toInternalFormat(location);
@ -109,6 +111,7 @@ public class PDOMFile implements IIndexFragmentFile {
return record;
}
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
@ -119,6 +122,7 @@ public class PDOMFile implements IIndexFragmentFile {
return false;
}
@Override
public final int hashCode() {
return System.identityHashCode(pdom) + 41*record;
}
@ -135,6 +139,7 @@ public class PDOMFile implements IIndexFragmentFile {
int oldRecord = db.getInt(record + LOCATION_REPRESENTATION);
db.free(oldRecord);
db.putInt(record + LOCATION_REPRESENTATION, db.newString(internalLocation).getRecord());
location= null;
}
public int getLinkageID() throws CoreException {
@ -491,12 +496,14 @@ public class PDOMFile implements IIndexFragmentFile {
}
public IIndexFileLocation getLocation() throws CoreException {
Database db = pdom.getDB();
String raw = db.getString(db.getInt(record + LOCATION_REPRESENTATION)).getString();
IIndexFileLocation result = pdom.getLocationConverter().fromInternalFormat(raw);
if(result==null)
throw new CoreException(CCorePlugin.createStatus(Messages.getString("PDOMFile.toExternalProblem")+raw)); //$NON-NLS-1$
return result;
if (location == null) {
Database db = pdom.getDB();
String raw = db.getString(db.getInt(record + LOCATION_REPRESENTATION)).getString();
location= pdom.getLocationConverter().fromInternalFormat(raw);
if(location==null)
throw new CoreException(CCorePlugin.createStatus(Messages.getString("PDOMFile.toExternalProblem")+raw)); //$NON-NLS-1$
}
return location;
}
public boolean hasContent() throws CoreException {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -15,8 +15,13 @@ import org.eclipse.cdt.core.dom.IPDOMIndexerTask;
import org.eclipse.cdt.internal.core.pdom.IndexerProgress;
import org.eclipse.cdt.internal.core.pdom.PDOMManager;
import org.eclipse.cdt.internal.core.pdom.WritablePDOM;
import org.eclipse.cdt.internal.core.pdom.PDOM.ChangeEvent;
import org.eclipse.core.runtime.IProgressMonitor;
/**
* Used to trigger a change notification when a pdom is loaded.
* In this situation the pdom itself does not generate a notification.
*/
public class TriggerNotificationTask implements IPDOMIndexerTask {
private WritablePDOM fPDOM;
@ -36,6 +41,8 @@ public class TriggerNotificationTask implements IPDOMIndexerTask {
}
public void run(IProgressMonitor monitor) {
fManager.handleChange(fPDOM);
ChangeEvent event= new ChangeEvent();
event.fReloaded= true;
fManager.handleChange(fPDOM, event);
}
}

View file

@ -280,9 +280,10 @@ public class CallHierarchyAcrossProjectsTest extends CallHierarchyBaseTest {
openCallHierarchy(editor, false);
TreeViewer tv = getCHTreeViewer();
TreeItem item= checkTreeNode(tv.getTree(), 0, "main()");
TreeItem nextItem= checkTreeNode(item, 0, "MyClass::method1()");
checkTreeNode(item, 1, null); item= nextItem;
final Tree tree = tv.getTree();
checkTreeNode(tree, 0, "main()");
TreeItem item= checkTreeNode(tree, 0, 0, "MyClass::method1()");
checkTreeNode(tree, 0, 1, null);
tv.setExpandedState(item.getData(), true);
TreeItem item0= checkTreeNode(item, 0, "MyClass::method1()");
@ -291,7 +292,7 @@ public class CallHierarchyAcrossProjectsTest extends CallHierarchyBaseTest {
try {
tv.setExpandedState(item0.getData(), true);
nextItem= checkTreeNode(item0, 0, "MyClass::method2()");
checkTreeNode(item0, 0, "MyClass::method2()");
}
catch (Throwable e) {
TreeItem tmp= item0; item0= item1; item1= tmp;
@ -299,7 +300,7 @@ public class CallHierarchyAcrossProjectsTest extends CallHierarchyBaseTest {
// method 1
tv.setExpandedState(item0.getData(), true);
nextItem= checkTreeNode(item0, 0, "MyClass::method2()");
TreeItem nextItem= checkTreeNode(item0, 0, "MyClass::method2()");
checkTreeNode(item0, 1, null); item0= nextItem;
tv.setExpandedState(item0.getData(), true);
checkTreeNode(item0, 0, null);
@ -311,5 +312,4 @@ public class CallHierarchyAcrossProjectsTest extends CallHierarchyBaseTest {
tv.setExpandedState(item1.getData(), true);
checkTreeNode(item1, 0, null);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 828 B

View file

@ -454,3 +454,5 @@ OccurrenceAnnotation.label= C/C++ Occurrences
DocCommentOwner.name = DocCommentOwner
Doxygen.name = Doxygen
indexedFilesDecorator.label = C/C++ Indexed Files

View file

@ -2548,4 +2548,20 @@
singleline="org.eclipse.cdt.ui.text.doctools.doxygen.DoxygenSingleConfiguration">
</owner>
</extension>
<extension
point="org.eclipse.ui.decorators">
<decorator
class="org.eclipse.cdt.internal.ui.viewsupport.IndexedFilesLabelProvider"
id="org.eclipse.cdt.ui.indexedFiles"
label="%indexedFilesDecorator.label"
lightweight="true"
state="false">
<enablement>
<or>
<objectClass name="org.eclipse.cdt.core.model.ITranslationUnit"/>
<objectClass name="org.eclipse.core.resources.IFile"/>
</or>
</enablement>
</decorator>
</extension>
</plugin>

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2007 QNX Software Systems and others.
* Copyright (c) 2005, 2008 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -80,7 +80,7 @@ public class IndexView extends ViewPart implements PDOM.IListener, IElementChang
Filter filter = new Filter();
public boolean isLinking = false;
private volatile boolean fUpdateRequested= false;
private Map fTimestampPerProject= new HashMap();
private Map<String, Long> fTimestampPerProject= new HashMap<String, Long>();
private IndexContentProvider contentProvider;
@ -112,6 +112,7 @@ public class IndexView extends ViewPart implements PDOM.IListener, IElementChang
private static class Filter extends ViewerFilter {
public boolean showExternalDefs = false;
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
if (element instanceof IndexNode) {
IndexNode node= (IndexNode)element;
@ -151,9 +152,9 @@ public class IndexView extends ViewPart implements PDOM.IListener, IElementChang
}
private static class Children implements IPDOMVisitor {
private ArrayList fNodes;
private ArrayList<IPDOMNode> fNodes;
public Children() {
fNodes= new ArrayList();
fNodes= new ArrayList<IPDOMNode>();
}
public boolean visit(IPDOMNode node) throws CoreException {
fNodes.add(node);
@ -162,7 +163,7 @@ public class IndexView extends ViewPart implements PDOM.IListener, IElementChang
public void leave(IPDOMNode node) throws CoreException {
}
public IPDOMNode[] getNodes() {
return (IPDOMNode[]) fNodes.toArray(new IPDOMNode[fNodes.size()]);
return fNodes.toArray(new IPDOMNode[fNodes.size()]);
}
}
@ -171,6 +172,7 @@ public class IndexView extends ViewPart implements PDOM.IListener, IElementChang
super(disp);
}
@Override
public Object getParent(Object element) {
if (element instanceof IndexNode) {
return ((IndexNode) element).fParent;
@ -181,6 +183,7 @@ public class IndexView extends ViewPart implements PDOM.IListener, IElementChang
return null;
}
@Override
protected Object[] syncronouslyComputeChildren(Object parentElement) {
if (parentElement instanceof ICModel) {
ICModel element = (ICModel) parentElement;
@ -205,6 +208,7 @@ public class IndexView extends ViewPart implements PDOM.IListener, IElementChang
}
@Override
protected Object[] asyncronouslyComputeChildren(Object parentElement, IProgressMonitor monitor) {
try {
if (parentElement instanceof ICProject) {
@ -218,7 +222,7 @@ public class IndexView extends ViewPart implements PDOM.IListener, IElementChang
IndexNode node= (IndexNode) parentElement;
ICProject cproject= node.getProject();
if (cproject != null && cproject.getProject().isOpen()) {
Long ts= (Long) fTimestampPerProject.get(cproject.getElementName());
Long ts= fTimestampPerProject.get(cproject.getElementName());
IPDOM pdom= CCoreInternals.getPDOMManager().getPDOM(cproject);
pdom.acquireReadLock();
try {
@ -283,6 +287,7 @@ public class IndexView extends ViewPart implements PDOM.IListener, IElementChang
}
}
@Override
public void createPartControl(Composite parent) {
viewer = new ExtendedTreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
contentProvider= new IndexContentProvider(getSite().getShell().getDisplay());
@ -333,6 +338,7 @@ public class IndexView extends ViewPart implements PDOM.IListener, IElementChang
});
}
@Override
public void dispose() {
super.dispose();
ICModel model = CoreModel.getDefault().getCModel();
@ -404,11 +410,12 @@ public class IndexView extends ViewPart implements PDOM.IListener, IElementChang
manager.add(discardExternalDefsAction);
}
@Override
public void setFocus() {
viewer.getControl().setFocus();
}
public void handleChange(PDOM pdom) {
public void handleChange(PDOM pdom, PDOM.ChangeEvent e) {
requestUpdate();
}
@ -450,19 +457,19 @@ public class IndexView extends ViewPart implements PDOM.IListener, IElementChang
try {
IPDOM pdom = CCoreInternals.getPDOMManager().getPDOM((ICProject)delta.getElement());
pdom.addListener(this);
handleChange(null);
handleChange(null, null);
} catch (CoreException e) {
}
break;
case ICElementDelta.REMOVED:
handleChange(null);
handleChange(null, null);
break;
}
}
}
public long getLastWriteAccess(ICProject cproject) {
Long result= (Long) fTimestampPerProject.get(cproject.getElementName());
Long result= fTimestampPerProject.get(cproject.getElementName());
return result == null ? -1 : result.longValue();
}
}

View file

@ -0,0 +1,276 @@
/*******************************************************************************
* Copyright (c) 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.viewsupport;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
import org.eclipse.swt.SWTException;
import org.eclipse.ui.IDecoratorManager;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexChangeEvent;
import org.eclipse.cdt.core.index.IIndexChangeListener;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexManager;
import org.eclipse.cdt.core.index.IIndexerStateEvent;
import org.eclipse.cdt.core.index.IIndexerStateListener;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICProject;
class IndexedFilesCache implements IIndexChangeListener, IIndexerStateListener, ILabelProviderListener {
private static final String DECORATOR_ID = "org.eclipse.cdt.ui.indexedFiles"; //$NON-NLS-1$
private static final IndexedFilesCache INSTANCE = new IndexedFilesCache();
private static final ISchedulingRule RULE = new ISchedulingRule() {
public boolean contains(ISchedulingRule rule) {
return rule == this;
}
public boolean isConflicting(ISchedulingRule rule) {
return rule == this;
}
};
public static IndexedFilesCache getInstance() {
return INSTANCE;
}
private final HashMap<String, Set<Integer>> fIndexedFiles= new HashMap<String, Set<Integer>>();
private boolean fIsDirty= false;
private boolean fActive= false;
private void scheduleInitialize() {
Job j= new Job(Messages.IndexedFilesCache_jobName) {
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
ICProject[] prj= CoreModel.getDefault().getCModel().getCProjects();
for (ICProject project : prj) {
initialize(project);
}
} catch (CoreException e) {
return e.getStatus();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return Status.CANCEL_STATUS;
}
checkTriggerDecorator(1);
return Status.OK_STATUS;
}
@Override
public boolean belongsTo(Object family) {
return family == IndexedFilesCache.this;
}
};
j.setSystem(true);
j.setRule(RULE);
j.schedule();
}
private void scheduleInitialize(final ICProject project) {
Job j= new Job(Messages.IndexedFilesCache_jobName) {
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
initialize(project);
} catch (CoreException e) {
return e.getStatus();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return Status.CANCEL_STATUS;
}
checkTriggerDecorator(1);
return Status.OK_STATUS;
}
@Override
public boolean belongsTo(Object family) {
return family == IndexedFilesCache.this;
}
};
j.setSystem(true);
j.setRule(RULE);
j.schedule();
}
final protected void initialize(ICProject prj) throws CoreException, InterruptedException {
IIndex index= CCorePlugin.getIndexManager().getIndex(prj, 0);
List<IIndexFileLocation> list= new ArrayList<IIndexFileLocation>();
index.acquireReadLock();
try {
IIndexFile[] files= index.getAllFiles();
for (IIndexFile ifile : files) {
if (ifile.getTimestamp() >= 0) {
list.add(ifile.getLocation());
}
}
if (!list.isEmpty()) {
final String prjName= prj.getElementName();
synchronized(fIndexedFiles) {
Set<Integer> cache= fIndexedFiles.get(prjName);
if (cache == null) {
cache= new HashSet<Integer>();
fIndexedFiles.put(prjName, cache);
}
else {
if (!cache.isEmpty()) {
cache.clear();
fIsDirty= true;
}
}
for (IIndexFileLocation ifl: list) {
final int h= computeHash(ifl);
if (cache.add(h)) {
fIsDirty= true;
}
}
}
}
}
finally {
index.releaseReadLock();
}
}
public void indexChanged(IIndexChangeEvent e) {
// the index manager has reported a change to an index
ICProject cproject= e.getAffectedProject();
if (cproject == null) {
return;
}
synchronized (fIndexedFiles) {
if (!fActive) {
return;
}
if (e.isReloaded()) {
scheduleInitialize(cproject);
}
else {
final String prjName = cproject.getElementName();
if (e.isCleared()) {
if (fIndexedFiles.remove(prjName) != null) {
fIsDirty= true;
}
}
final Set<IIndexFileLocation> filesCleared = e.getFilesCleared();
final Set<IIndexFileLocation> filesWritten = e.getFilesWritten();
if (!(filesCleared.isEmpty() && filesWritten.isEmpty())) {
Set<Integer> cache= fIndexedFiles.get(prjName);
if (cache == null) {
cache= new HashSet<Integer>();
fIndexedFiles.put(prjName, cache);
}
for (IIndexFileLocation ifl: filesCleared) {
final int h= computeHash(ifl);
if (cache.remove(h)) {
fIsDirty= true;
}
}
for (IIndexFileLocation ifl: filesWritten) {
final int h= computeHash(ifl);
if (cache.add(h)) {
fIsDirty= true;
}
}
}
}
}
}
public void indexChanged(IIndexerStateEvent event) {
if (event.indexerIsIdle()) {
checkTriggerDecorator(0);
}
}
private void activate() {
synchronized (fIndexedFiles) {
fActive= true;
PlatformUI.getWorkbench().getDecoratorManager().addListener(this);
final IIndexManager indexManager = CCorePlugin.getIndexManager();
indexManager.addIndexChangeListener(IndexedFilesCache.this);
indexManager.addIndexerStateListener(IndexedFilesCache.this);
scheduleInitialize();
}
}
private void deactivate() {
synchronized (fIndexedFiles) {
fActive= false;
fIndexedFiles.clear();
final IIndexManager indexManager = CCorePlugin.getIndexManager();
indexManager.removeIndexChangeListener(IndexedFilesCache.this);
indexManager.removeIndexerStateListener(IndexedFilesCache.this);
PlatformUI.getWorkbench().getDecoratorManager().removeListener(this);
}
}
final protected void checkTriggerDecorator(int jobCount) {
if (fIsDirty && CCorePlugin.getIndexManager().isIndexerIdle() &&
Job.getJobManager().find(this).length == jobCount) {
fIsDirty= false;
final IWorkbench workbench= PlatformUI.getWorkbench();
try {
workbench.getDisplay().asyncExec(new Runnable(){
public void run() {
workbench.getDecoratorManager().update(DECORATOR_ID);
}
});
}
catch (SWTException e) {
// in case the display is no longer valid
}
}
}
public boolean isIndexed(IProject project, IIndexFileLocation ifl) {
// request from a label provider
synchronized(fIndexedFiles) {
if (!fActive) {
activate();
}
Set<Integer> cache= fIndexedFiles.get(project.getName());
return cache != null && cache.contains(computeHash(ifl));
}
}
private int computeHash(IIndexFileLocation ifl) {
final String fp= ifl.getFullPath();
final int h1= fp == null ? 0 : fp.hashCode() * 43;
return h1 + ifl.getURI().hashCode();
}
public void labelProviderChanged(LabelProviderChangedEvent event) {
final Object src= event.getSource();
if (src instanceof IDecoratorManager) {
IDecoratorManager mng= (IDecoratorManager) src;
if (!mng.getEnabled(DECORATOR_ID)) {
deactivate();
}
}
}
}

View file

@ -0,0 +1,82 @@
/*******************************************************************************
* Copyright (c) 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.viewsupport;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IDecoration;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ILightweightLabelDecorator;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IndexLocationFactory;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CUIPlugin;
/**
* A label provider that marks all translation units that are currently part of the index.
*/
public class IndexedFilesLabelProvider implements ILightweightLabelDecorator {
private static final ImageDescriptor INDEXED=
AbstractUIPlugin.imageDescriptorFromPlugin(CUIPlugin.PLUGIN_ID, "$nl$/icons/ovr16/indexedFile.gif"); //$NON-NLS-1$
public IndexedFilesLabelProvider() {
}
public void addListener(ILabelProviderListener listener) {
}
public void dispose() {
}
public boolean isLabelProperty(Object element, String property) {
return false;
}
public void removeListener(ILabelProviderListener listener) {
}
/**
* Adds the linked resource overlay if the given element is a linked
* resource.
*
* @param element element to decorate
* @param decoration The decoration we are adding to
* @see org.eclipse.jface.viewers.ILightweightLabelDecorator#decorate(Object, IDecoration)
*/
public void decorate(Object element, IDecoration decoration) {
IIndexFileLocation ifl= null;
IProject project= null;
if (element instanceof IFile) {
final IFile file = (IFile) element;
ifl= IndexLocationFactory.getWorkspaceIFL(file);
project= file.getProject();
}
else if (element instanceof ITranslationUnit) {
final ITranslationUnit tu = (ITranslationUnit) element;
ifl= IndexLocationFactory.getIFL(tu);
project= tu.getCProject().getProject();
}
if (isIndexed(project, ifl)) {
decoration.addOverlay(INDEXED, IDecoration.TOP_LEFT);
}
}
private boolean isIndexed(IProject project, IIndexFileLocation ifl) {
if (project == null || ifl == null) {
return false;
}
return IndexedFilesCache.getInstance().isIndexed(project, ifl);
}
}

View file

@ -14,6 +14,7 @@ import org.eclipse.osgi.util.NLS;
public class Messages extends NLS {
private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.ui.viewsupport.messages"; //$NON-NLS-1$
public static String IndexedFilesCache_jobName;
public static String IndexUI_infoNotInIndex;
public static String IndexUI_infoNotInSource;
public static String IndexUI_infoSelectIndexAllFiles;

View file

@ -8,6 +8,7 @@
# Contributors:
# Markus Schorn - initial API and implementation
################################################################################
IndexedFilesCache_jobName=Initialize C/C++ Index Label Provider
IndexUI_infoNotInSource=The element ''{0}'' does not belong to a source file.
IndexUI_infoNotInIndex=The file ''{0}'' is currently not part of the index.
IndexUI_infoSelectIndexAllFiles=For headers that are never included, or sources that are not part of the build, consider selecting the preference 'Index all files'.