From 8c248ed68bc4382fe6413b58a1391af74a0e1f90 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Wed, 27 Feb 2008 10:48:53 +0000 Subject: [PATCH] LabelProvider to decorate indexed files, bug 159731. --- .../internal/pdom/tests/CPPFunctionTests.java | 11 +- .../cdt/core/index/IIndexChangeEvent.java | 30 +- .../cdt/core/index/IIndexerStateEvent.java | 6 +- .../internal/core/index/IndexChangeEvent.java | 31 +- .../internal/core/pdom/JobChangeListener.java | 53 ++++ .../eclipse/cdt/internal/core/pdom/PDOM.java | 79 +++-- .../cdt/internal/core/pdom/PDOMManager.java | 100 +++---- .../cdt/internal/core/pdom/PDOMProxy.java | 5 +- .../cdt/internal/core/pdom/WritablePDOM.java | 9 +- .../cdt/internal/core/pdom/dom/PDOMFile.java | 19 +- .../pdom/indexer/TriggerNotificationTask.java | 11 +- .../CallHierarchyAcrossProjectsTest.java | 12 +- .../icons/ovr16/indexedFile.gif | Bin 0 -> 828 bytes core/org.eclipse.cdt.ui/plugin.properties | 2 + core/org.eclipse.cdt.ui/plugin.xml | 16 + .../cdt/internal/ui/indexview/IndexView.java | 27 +- .../ui/viewsupport/IndexedFilesCache.java | 276 ++++++++++++++++++ .../IndexedFilesLabelProvider.java | 82 ++++++ .../cdt/internal/ui/viewsupport/Messages.java | 1 + .../ui/viewsupport/messages.properties | 1 + 20 files changed, 636 insertions(+), 135 deletions(-) create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/JobChangeListener.java create mode 100644 core/org.eclipse.cdt.ui/icons/ovr16/indexedFile.gif create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/IndexedFilesCache.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/IndexedFilesLabelProvider.java diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPFunctionTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPFunctionTests.java index 0b544e2122b..a0cfce22d09 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPFunctionTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPFunctionTests.java @@ -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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexChangeEvent.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexChangeEvent.java index 2819ffe2ee9..5a4e5806150 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexChangeEvent.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexChangeEvent.java @@ -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. *

* EXPERIMENTAL. 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 true when the index for the project was loaded for the first time or + * reloaded with a different database. + */ + public boolean isReloaded(); + + /** + * Returns true 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 true, the set will be empty. + */ + public Set getFilesCleared(); + + /** + * Returns the set of files that has been added or updated. When {@link #isCleared()} returns + * true, the files of the set have been written after the index was cleared. + */ + public Set getFilesWritten(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexerStateEvent.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexerStateEvent.java index 9543dab11e8..23f8da3ef96 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexerStateEvent.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexerStateEvent.java @@ -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. *

* EXPERIMENTAL. This class or interface has been added as * part of a work in progress. There is no guarantee that this API will work or diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexChangeEvent.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexChangeEvent.java index e508e463e5b..31db4631674 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexChangeEvent.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexChangeEvent.java @@ -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 getFilesCleared() { + return fChangeEvent.fClearedFiles; + } + + public Set getFilesWritten() { + return fChangeEvent.fFilesWritten; + } + + public boolean isCleared() { + return fChangeEvent.fCleared; + } + + public boolean isReloaded() { + return fChangeEvent.fReloaded; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/JobChangeListener.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/JobChangeListener.java new file mode 100644 index 00000000000..73718480512 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/JobChangeListener.java @@ -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) { + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index 79b9a39c3ed..e35b0797f71 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -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 fClearedFiles= new HashSet(); + public Set fFilesWritten= new HashSet(); + 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,8 +201,9 @@ public class PDOM extends PlatformObject implements IPDOM { private IIndexLocationConverter locationConverter; private Map fPDOMLinkageFactoryCache; private HashMap fResultCache= new HashMap(); + private List listeners; + protected ChangeEvent fEvent= new ChangeEvent(); - public PDOM(File dbPath, IIndexLocationConverter locationConverter, Map 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 listeners; - public void addListener(IListener listener) { if (listeners == null) listeners = new LinkedList(); @@ -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 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 names = new ArrayList(); - 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 names = new ArrayList(); - 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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java index 077149d3221..94c85b8e71b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java @@ -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 fTaskQueue = new LinkedList(); private PDOMIndexerJob fIndexerJob; private IPDOMIndexerTask fCurrentTask; - private LinkedList fTaskQueue = new LinkedList(); 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 fPrefListeners= new HashMap(); private ArrayList fSetupParticipants= new ArrayList(); private HashSet fPostponedProjects= new HashSet(); + 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 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 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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java index 9dd5700c700..3c33b386b54 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java @@ -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 iterator = fListeners.iterator(); iterator.hasNext();) { IListener listener = iterator.next(); - listener.handleChange(fDelegate); + listener.handleChange(fDelegate, event); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java index ccdc925d16f..ebac516694c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java @@ -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 contextsRemoved) throws CoreException { assert file.getIndexFragment() == this; - ((PDOMFile) file).clear(contextsRemoved); + ((PDOMFile) file).clear(contextsRemoved); + + fEvent.fClearedFiles.add(file.getLocation()); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java index 7e3f765d90c..0bd4595e8ce 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java @@ -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 { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/TriggerNotificationTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/TriggerNotificationTask.java index d7b7d9eb101..b97cd66487d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/TriggerNotificationTask.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/TriggerNotificationTask.java @@ -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); } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyAcrossProjectsTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyAcrossProjectsTest.java index 72c623ede28..716079a134e 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyAcrossProjectsTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CallHierarchyAcrossProjectsTest.java @@ -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); } - } diff --git a/core/org.eclipse.cdt.ui/icons/ovr16/indexedFile.gif b/core/org.eclipse.cdt.ui/icons/ovr16/indexedFile.gif new file mode 100644 index 0000000000000000000000000000000000000000..9b4c11c4572ebfff6c6624038e8dc06004ddbd7c GIT binary patch literal 828 zcmW+!F^X1U5PO2KD+q#}V4|VlifR z;PL(cyh$?2_ugH-y?piQ>^MLE99yT`=X86V^6zxIN&UR}{^K_R0Ru@RWeGHtdwW{ibM&1$;Y&1uGJs5Pvi zhdrDjponRW%4Z%Eo zE0JZzwCrlvxN@lpF-vF2UEMWZx#q+g8-aPMr)COpf{w8ec`w-mgC^H%sJ$_JXvox> zkC@kJY{f)Y&VnoNl?ria0?J4lTWybxHrwi5(d}-}zu(u_-%h8~ + + + + + + + + + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/indexview/IndexView.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/indexview/IndexView.java index e2d38f7bb79..e44c215e80c 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/indexview/IndexView.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/indexview/IndexView.java @@ -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 fTimestampPerProject= new HashMap(); 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 fNodes; public Children() { - fNodes= new ArrayList(); + fNodes= new ArrayList(); } 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(); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/IndexedFilesCache.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/IndexedFilesCache.java new file mode 100644 index 00000000000..c44c97d3498 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/IndexedFilesCache.java @@ -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> fIndexedFiles= new HashMap>(); + 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 list= new ArrayList(); + 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 cache= fIndexedFiles.get(prjName); + if (cache == null) { + cache= new HashSet(); + 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 filesCleared = e.getFilesCleared(); + final Set filesWritten = e.getFilesWritten(); + if (!(filesCleared.isEmpty() && filesWritten.isEmpty())) { + Set cache= fIndexedFiles.get(prjName); + if (cache == null) { + cache= new HashSet(); + 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 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(); + } + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/IndexedFilesLabelProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/IndexedFilesLabelProvider.java new file mode 100644 index 00000000000..831844257cd --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/IndexedFilesLabelProvider.java @@ -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); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/Messages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/Messages.java index 7230e5dfd6c..3dfdba03aa8 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/Messages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/Messages.java @@ -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; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/messages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/messages.properties index f672ee384a2..52402c7d06f 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/messages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/messages.properties @@ -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'.