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 68fdac75a9c..5b6abfe0c97 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 @@ -10,6 +10,7 @@ * Markus Schorn (Wind River Systems) * Andrew Ferguson (Symbian) * Sergey Prigogin (Google) + * Tim Kelly (Nokia) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom; @@ -29,6 +30,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CCorePreferenceConstants; @@ -37,9 +39,13 @@ import org.eclipse.cdt.core.dom.IPDOMIndexerTask; import org.eclipse.cdt.core.dom.IPDOMManager; import org.eclipse.cdt.core.index.IIndex; 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.IIndexInclude; import org.eclipse.cdt.core.index.IIndexLocationConverter; import org.eclipse.cdt.core.index.IIndexManager; import org.eclipse.cdt.core.index.IIndexerStateListener; +import org.eclipse.cdt.core.index.IndexLocationFactory; import org.eclipse.cdt.core.index.IndexerSetupParticipant; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CoreModel; @@ -69,7 +75,9 @@ import org.eclipse.cdt.internal.core.pdom.indexer.PDOMNullIndexer; import org.eclipse.cdt.internal.core.pdom.indexer.PDOMRebuildTask; import org.eclipse.cdt.internal.core.pdom.indexer.PDOMUpdateTask; import org.eclipse.cdt.internal.core.pdom.indexer.ProjectIndexerInputAdapter; +import org.eclipse.cdt.internal.core.pdom.indexer.TranslationUnitCollector; import org.eclipse.cdt.internal.core.pdom.indexer.TriggerNotificationTask; +import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; @@ -82,7 +90,9 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.ListenerList; +import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Preferences; import org.eclipse.core.runtime.QualifiedName; @@ -1379,4 +1389,74 @@ public class PDOMManager implements IWritableIndexManager, IListener { public boolean isProjectRegistered(ICProject project) { return getIndexer(project) != null; } + + /** + * @param cproject the project to check + * @return whether the content in the project fragment of the specified project's index + * is complete (contains all sources) and up to date. + * @throws CoreException + */ + public boolean isProjectContentSynced(ICProject cproject) throws CoreException { + Set sources= new HashSet(); + cproject.accept(new TranslationUnitCollector(sources, null, new NullProgressMonitor())); + + try { + IIndex index= getIndex(cproject); + index.acquireReadLock(); + try { + for(ITranslationUnit tu : sources) { + IResource resource= tu.getResource(); + if(resource instanceof IFile) { + IIndexFileLocation location= IndexLocationFactory.getWorkspaceIFL((IFile)resource); + if(!areSynchronized(index, resource, location)) { + return false; + } + } + } + } finally { + index.releaseReadLock(); + } + } catch(InterruptedException ie) { + CCorePlugin.log(ie); + } + + return true; + } + + /** + * Recursively checks that the specified file, and its include are up-to-date. + * @param index the index to check against + * @param resource the resource to check from the workspace + * @param location the location to check from the index + * @return whether the specified file, and its includes are up-to-date. + * @throws CoreException + */ + private static boolean areSynchronized(IIndex index, IResource resource, IIndexFileLocation location) throws CoreException { + IIndexFile[] file= index.getFiles(location); + + // pre-includes may be listed twice (191989) + if(file.length < 1 || file.length > 2) + return false; + + if(resource.getLocalTimeStamp() != file[0].getTimestamp()) + return false; + + // if it is up-to-date, the includes have not changed and may + // be read from the index. + IIndexInclude[] includes= index.findIncludes(file[0]); + for(IIndexInclude inc : includes) { + IIndexFileLocation newLocation= inc.getIncludesLocation(); + if(newLocation != null) { + String path= newLocation.getFullPath(); + if(path != null) { + IResource newResource= ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path)); + if(!areSynchronized(index, newResource, newLocation)) { + return false; + } + } + } + } + + return true; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOM.java index a80899f47a4..f231605ec87 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOM.java @@ -25,8 +25,9 @@ import org.eclipse.cdt.internal.core.CCoreInternals; import org.eclipse.cdt.internal.core.pdom.WritablePDOM; import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Status; /** * An ISafeRunnable which @@ -36,7 +37,7 @@ import org.eclipse.core.runtime.NullProgressMonitor; *
  • Writes new properties to the PDOM *
      */ -public class GeneratePDOM implements ISafeRunnable { +public class GeneratePDOM { protected IExportProjectProvider pm; protected String[] applicationArguments; protected File targetLocation; @@ -59,13 +60,21 @@ public class GeneratePDOM implements ISafeRunnable { this.deleteOnExit= deleteOnExit; } - public final void run() throws CoreException { + /** + * Executes the PDOM generation + * @return {@link IStatus#OK} if the generated content is complete, {@link IStatus#ERROR} otherwise. + * @throws CoreException if an internal or invalid configuration error occurs + */ + public final IStatus run() throws CoreException { + boolean isContentSynced= false; + + // create the project pm.setApplicationArguments(applicationArguments); final ICProject cproject = pm.createProject(); if(cproject==null) { fail(MessageFormat.format(Messages.GeneratePDOM_ProjectProviderReturnedNullCProject, new Object [] {pm.getClass().getName()})); - return; // cannot be reached, inform the compiler + return null; // cannot be reached, inform the compiler } IIndexLocationConverter converter= pm.getLocationConverter(cproject); @@ -89,21 +98,30 @@ public class GeneratePDOM implements ISafeRunnable { Thread.sleep(200); } - CCoreInternals.getPDOMManager().exportProjectPDOM(cproject, targetLocation, converter); - WritablePDOM exportedPDOM= new WritablePDOM(targetLocation, converter, LanguageManager.getInstance().getPDOMLinkageFactoryMappings()); - exportedPDOM.acquireWriteLock(0); - try { - Map exportProperties= pm.getExportProperties(); - if(exportProperties!=null) { - for(Map.Entry entry : exportProperties.entrySet()) { - exportedPDOM.setProperty(entry.getKey(), entry.getValue()); + // check status + isContentSynced= CCoreInternals.getPDOMManager().isProjectContentSynced(cproject); + + if(isContentSynced) { + // export a .pdom file + CCoreInternals.getPDOMManager().exportProjectPDOM(cproject, targetLocation, converter); + + // write properties to exported PDOM + WritablePDOM exportedPDOM= new WritablePDOM(targetLocation, converter, LanguageManager.getInstance().getPDOMLinkageFactoryMappings()); + exportedPDOM.acquireWriteLock(0); + try { + Map exportProperties= pm.getExportProperties(); + if(exportProperties!=null) { + for(Map.Entry entry : exportProperties.entrySet()) { + exportedPDOM.setProperty(entry.getKey(), entry.getValue()); + } } + exportedPDOM.close(); + } + finally { + exportedPDOM.releaseWriteLock(); } - exportedPDOM.close(); - } - finally { - exportedPDOM.releaseWriteLock(); } + } catch(InterruptedException ie) { String msg= MessageFormat.format(Messages.GeneratePDOM_GenericGenerationFailed, new Object[] {ie.getMessage()}); throw new CoreException(CCorePlugin.createStatus(msg, ie)); @@ -112,10 +130,10 @@ public class GeneratePDOM implements ISafeRunnable { cproject.getProject().delete(true, new NullProgressMonitor()); } } - } - - public void handleException(Throwable exception) { - CCorePlugin.log(exception); + + return isContentSynced ? + new Status(IStatus.OK, CCorePlugin.PLUGIN_ID, Messages.GeneratePDOM_Success) + : new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, Messages.GeneratePDOM_Incomplete); } private void fail(String message) throws CoreException { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOMApplication.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOMApplication.java index 61e345a4932..df0c1972d0c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOMApplication.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/GeneratePDOMApplication.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007 Symbian Software Systems and others. + * Copyright (c) 2007, 2008 Symbian 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 @@ -116,7 +116,11 @@ public class GeneratePDOMApplication implements IApplication { GeneratePDOM generate = new GeneratePDOM(pprovider, appArgs, targetLocation, indexerID); output(Messages.GeneratePDOMApplication_GenerationStarts); - generate.run(); + try { + generate.run(); + } catch(CoreException ce) { + CCorePlugin.log(ce); + } output(Messages.GeneratePDOMApplication_GenerationEnds); return null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/Messages.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/Messages.java index 28825ed99a8..3075a8e0ea3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/Messages.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/Messages.java @@ -15,8 +15,10 @@ import org.eclipse.osgi.util.NLS; public class Messages extends NLS { private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.core.pdom.export.messages"; //$NON-NLS-1$ public static String GeneratePDOM_GenericGenerationFailed; + public static String GeneratePDOM_Incomplete; public static String GeneratePDOM_NullLocationConverter; public static String GeneratePDOM_ProjectProviderReturnedNullCProject; + public static String GeneratePDOM_Success; public static String GeneratePDOMApplication_CouldNotFindInitializer; public static String GeneratePDOMApplication_GenerationEnds; public static String GeneratePDOMApplication_GenerationStarts; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/messages.properties b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/messages.properties index 7d3d9f663a7..205d56c4030 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/messages.properties +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/export/messages.properties @@ -10,9 +10,11 @@ ############################################################################### GeneratePDOMApplication_Initializing=== Initializing GeneratePDOM_GenericGenerationFailed=Generation failed: {0} +GeneratePDOM_Incomplete=Pre-built index content is incomplete or out of date GeneratePDOM_NullLocationConverter=IExportProjectProvider implementation of getLocationConverter() returned null ({0}) -GeneratePDOMApplication_CouldNotFindInitializer=Could not find IExportProjectProvider: {0} GeneratePDOM_ProjectProviderReturnedNullCProject=IExportProjectProvider implementation of createProject() returned null ({0}) +GeneratePDOM_Success=Pre-built index content successfully generated +GeneratePDOMApplication_CouldNotFindInitializer=Could not find IExportProjectProvider: {0} GeneratePDOMApplication_UsingDefaultProjectProvider=-pprovider not specified - defaulting to {0} GeneratePDOMApplication_GenerationStarts=== Generation starts GeneratePDOMApplication_InvalidIndexerID={0} takes zero or one argument diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/TranslationUnitCollector.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/TranslationUnitCollector.java index 5def46b68ee..6bf16893d5a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/TranslationUnitCollector.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/TranslationUnitCollector.java @@ -18,7 +18,7 @@ import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; -final class TranslationUnitCollector implements ICElementVisitor { +final public class TranslationUnitCollector implements ICElementVisitor { private final Collection fSources; private final Collection fHeaders; private final IProgressMonitor fProgressMonitor;