diff options
author | Sergey Prigogin | 2012-05-10 00:05:51 +0000 |
---|---|---|
committer | Sergey Prigogin | 2012-05-10 00:12:45 +0000 |
commit | ae606fe28bd730d640f6ec722da99628e813984d (patch) | |
tree | 2ceb0c5d500221d61fd20d897258e0a269878701 /core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal | |
parent | fdbfec3f2bb2334d5818cc7bc3bed2cc75c151a8 (diff) | |
download | org.eclipse.cdt-ae606fe28bd730d640f6ec722da99628e813984d.tar.gz org.eclipse.cdt-ae606fe28bd730d640f6ec722da99628e813984d.tar.xz org.eclipse.cdt-ae606fe28bd730d640f6ec722da99628e813984d.zip |
Bug 378317 - Index update mode for resolving unresolved includes and
reindexing files with I/O errors.
Diffstat (limited to 'core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal')
17 files changed, 429 insertions, 92 deletions
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java index 1fbc93e4b55..c3dde20b6f0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java @@ -759,6 +759,32 @@ public class CIndex implements IIndex { } @Override + public IIndexFile[] getDefectiveFiles() throws CoreException { + HashMap<IIndexFileLocation, IIndexFile> result= new HashMap<IIndexFileLocation, IIndexFile>(); + for (IIndexFragment fragment : fFragments) { + for (IIndexFragmentFile file : fragment.getDefectiveFiles()) { + if (file.hasContent()) { + result.put(file.getLocation(), file); + } + } + } + return result.values().toArray(new IIndexFile[result.size()]); + } + + @Override + public IIndexFile[] getFilesWithUnresolvedIncludes() throws CoreException { + HashMap<IIndexFileLocation, IIndexFile> result= new HashMap<IIndexFileLocation, IIndexFile>(); + for (IIndexFragment fragment : fFragments) { + for (IIndexFragmentFile file : fragment.getFilesWithUnresolvedIncludes()) { + if (file.hasContent()) { + result.put(file.getLocation(), file); + } + } + } + return result.values().toArray(new IIndexFile[result.size()]); + } + + @Override public IIndexScope[] getInlineNamespaces() throws CoreException { if (SPECIALCASE_SINGLES && fFragments.length == 1) { return fFragments[0].getInlineNamespaces(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java index 503ede13120..9168511d58d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2011 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2012 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 @@ -190,6 +190,16 @@ final public class EmptyCIndex implements IIndex { } @Override + public IIndexFile[] getDefectiveFiles() { + return IIndexFile.EMPTY_FILE_ARRAY; + } + + @Override + public IIndexFile[] getFilesWithUnresolvedIncludes() { + return IIndexFile.EMPTY_FILE_ARRAY; + } + + @Override public IIndexBinding[] findBindings(char[] name, boolean fileScopeOnly, IndexFilter filter, IProgressMonitor monitor) { return IIndexBinding.EMPTY_INDEX_BINDING_ARRAY; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java index 2b2ac26362f..7a2bc0ccf72 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java @@ -326,6 +326,16 @@ public interface IIndexFragment { IIndexFragmentFile[] getAllFiles() throws CoreException; /** + * @return an array of files that were indexed with I/O errors. + */ + IIndexFragmentFile[] getDefectiveFiles() throws CoreException; + + /** + * @return an array of files containg unresolved includes. + */ + IIndexFragmentFile[] getFilesWithUnresolvedIncludes() throws CoreException; + + /** * Caches an object with the key, the cache must be cleared at latest when the fragment no * longer holds a locks. * @param replace if <code>false</code> an existing entry will not be replaced. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java index f6ca6b05ca2..0577e408b1b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2011 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2012 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 @@ -24,11 +24,16 @@ public interface IIndexFragmentFile extends IIndexFile { IIndexFragment getIndexFragment(); /** - * Sets the timestamp of the file + * Sets the timestamp of the file. */ void setTimestamp(long timestamp) throws CoreException; /** + * Sets the file read time. + */ + void setSourceReadTime(long time) throws CoreException; + + /** * Sets the hash of the file content. */ void setContentsHash(long hash) throws CoreException; @@ -58,6 +63,12 @@ public interface IIndexFragmentFile extends IIndexFile { boolean hasContent() throws CoreException; /** + * Checks if the file contains at least one unresolved include. + * @return {@code true} if the file contains an unresolved include + */ + boolean hasUnresolvedInclude() throws CoreException; + + /** * Returns the id of the linkage this file belongs to. */ @Override @@ -74,4 +85,5 @@ public interface IIndexFragmentFile extends IIndexFile { * The file 'source' must belong to the same fragment as this file. */ void transferContext(IIndexFragmentFile source) throws CoreException; + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/InternalParserUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/InternalParserUtil.java index 37ac0d0b27b..a9de019b08e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/InternalParserUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/InternalParserUtil.java @@ -155,6 +155,7 @@ public class InternalParserUtil extends ParserFactory { InputStream input; try { + long fileReadTime = System.currentTimeMillis(); IFileStore store = EFS.getStore(file.getLocationURI()); IFileInfo fileInfo = store.fetchInfo(); input= file.getContents(true); @@ -173,7 +174,7 @@ public class InternalParserUtil extends ParserFactory { } try { return createFileContent(path, file.getCharset(), input, - fileInfo.getLastModified(), fileInfo.getLength()); + fileInfo.getLastModified(), fileInfo.getLength(), fileReadTime); } finally { try { input.close(); @@ -201,6 +202,7 @@ public class InternalParserUtil extends ParserFactory { * canonical path. */ public static InternalFileContent createExternalFileContent(String externalLocation, String encoding) { + long fileReadTime = System.currentTimeMillis(); File includeFile = null; String path = null; if (!UNCPathConverter.isUNC(externalLocation)) { @@ -228,7 +230,7 @@ public class InternalParserUtil extends ParserFactory { return null; } try { - return createFileContent(path, encoding, in, timestamp, fileSize); + return createFileContent(path, encoding, in, timestamp, fileSize, fileReadTime); } finally { try { in.close(); @@ -240,13 +242,13 @@ public class InternalParserUtil extends ParserFactory { } private static InternalFileContent createFileContent(String path, String charset, InputStream in, - long fileTimestamp, long fileSize) { + long fileTimestamp, long fileSize, long fileReadTime) { try { AbstractCharArray chars= FileCharArray.create(path, charset, in); if (chars == null) return null; - return new InternalFileContent(path, chars, fileTimestamp, fileSize); + return new InternalFileContent(path, chars, fileTimestamp, fileSize, fileReadTime); } catch (IOException e) { CCorePlugin.log(e); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java index 8cf8471286d..43bc89e7012 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java @@ -298,6 +298,7 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces private long fIncludedFileContentsHash; private long fIncludedFileTimestamp = -1; private long fIncludedFileSize; + private long fIncludedFileReadTime; private boolean fErrorInIncludedFile; public ASTInclusionStatement(IASTTranslationUnit parent, @@ -405,6 +406,19 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces } @Override + public long getIncludedFileReadTime() { + if (fNominationDelegate != null) { + return 0; + } + return fIncludedFileReadTime; + } + + public void setIncludedFileReadTime(long time) { + assert fNominationDelegate == null; + fIncludedFileReadTime= time; + } + + @Override public long getIncludedFileSize() { if (fNominationDelegate != null) { return 0; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java index 0829535d524..46da6f2a30b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java @@ -302,7 +302,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { if (contextPath == null) { contextPath= fRootContent.getFileLocation(); } - configureIncludeSearchPath(new File(contextPath).getParentFile(), info); + fIncludeSearchPath = configureIncludeSearchPath(new File(contextPath).getParentFile(), info); setupMacroDictionary(configuration, info, language); ILocationCtx ctx= fLocationMap.pushTranslationUnit(fRootContent.getFileLocation(), fRootContent.getSource()); @@ -396,37 +396,39 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return array == null ? CharArrayUtils.EMPTY_CHAR_ARRAY : array; } - private void configureIncludeSearchPath(File directory, IScannerInfo info) { + public static IncludeSearchPathElement[] configureIncludeSearchPath(File directory, IScannerInfo info) { + IncludeSearchPathElement[] includeSearchPath = null; String[] searchPath= info.getIncludePaths(); int idx= 0; if (info instanceof IExtendedScannerInfo) { final IExtendedScannerInfo einfo= (IExtendedScannerInfo) info; final String[] quoteIncludeSearchPath= einfo.getLocalIncludePath(); if (quoteIncludeSearchPath != null && quoteIncludeSearchPath.length > 0) { - fIncludeSearchPath= new IncludeSearchPathElement[quoteIncludeSearchPath.length + searchPath.length]; - for (String qip : quoteIncludeSearchPath) { - fIncludeSearchPath[idx++]= new IncludeSearchPathElement(makeAbsolute(directory, qip), true); + includeSearchPath= new IncludeSearchPathElement[quoteIncludeSearchPath.length + searchPath.length]; + for (String path : quoteIncludeSearchPath) { + includeSearchPath[idx++]= new IncludeSearchPathElement(makeAbsolute(directory, path), true); } } } - if (fIncludeSearchPath == null) { - fIncludeSearchPath= new IncludeSearchPathElement[searchPath.length]; + if (includeSearchPath == null) { + includeSearchPath= new IncludeSearchPathElement[searchPath.length]; } for (String path : searchPath) { - fIncludeSearchPath[idx++]= new IncludeSearchPathElement(makeAbsolute(directory, path), false); + includeSearchPath[idx++]= new IncludeSearchPathElement(makeAbsolute(directory, path), false); } + return includeSearchPath; } - private String makeAbsolute(File directory, String inlcudePath) { - if (directory == null || new File(inlcudePath).isAbsolute()) { - return inlcudePath; + private static String makeAbsolute(File directory, String includePath) { + if (directory == null || new File(includePath).isAbsolute()) { + return includePath; } - return ScannerUtility.createReconciledPath(directory.getAbsolutePath(), inlcudePath); + return ScannerUtility.createReconciledPath(directory.getAbsolutePath(), includePath); } private void setupMacroDictionary(IScannerExtensionConfiguration config, IScannerInfo info, ParserLanguage lang) { - // built in macros + // Built-in macros fMacroDictionary.put(__CDT_PARSER__.getNameCharArray(), __CDT_PARSER__); fMacroDictionary.put(__STDC__.getNameCharArray(), __STDC__); fMacroDictionary.put(__FILE__.getNameCharArray(), __FILE__); @@ -1066,20 +1068,10 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { private <T> T findInclusion(final String includeDirective, final boolean quoteInclude, final boolean includeNext, final String currentFile, final IIncludeFileTester<T> tester) { T reader = null; - // Filename is an absolute path - if (new File(includeDirective).isAbsolute()) { - return tester.checkFile(includeDirective, false, null); - } - // Filename is a Linux absolute path on a windows machine - if (File.separatorChar == '\\' && includeDirective.length() > 0) { - final char firstChar = includeDirective.charAt(0); - if (firstChar == '\\' || firstChar == '/') { - if (currentFile != null && currentFile.length() > 1 && currentFile.charAt(1) == ':') { - return tester.checkFile(currentFile.substring(0, 2) + includeDirective, false, null); - } - return tester.checkFile(includeDirective, false, null); - } - } + String absoluteInclusionPath = getAbsoluteInclusionPath(includeDirective, currentFile); + if (absoluteInclusionPath != null) { + return tester.checkFile(absoluteInclusionPath, false, null); + } if (currentFile != null && quoteInclude && !includeNext) { // Check to see if we find a match in the current directory @@ -1134,6 +1126,24 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return null; } + public static String getAbsoluteInclusionPath(String includeDirective, String currentFile) { + // Filename is an absolute path + if (new File(includeDirective).isAbsolute()) { + return includeDirective; + } + // Filename is a Linux absolute path on a Windows machine + if (File.separatorChar == '\\' && includeDirective.length() > 0) { + final char firstChar = includeDirective.charAt(0); + if (firstChar == '\\' || firstChar == '/') { + if (currentFile != null && currentFile.length() > 1 && currentFile.charAt(1) == ':') { + return currentFile.substring(0, 2) + includeDirective; + } + return includeDirective; + } + } + return null; + } + private IncludeSearchPathElement findFileInIncludePath(String file, String includeDirective) { for (IncludeSearchPathElement path : fIncludeSearchPath) { String fileLocation = path.getLocation(includeDirective); @@ -1490,6 +1500,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { stmt.setIncludedFileTimestamp(fi.getTimestamp()); stmt.setIncludedFileSize(fi.getFileSize()); stmt.setIncludedFileContentsHash(source.getContentsHash()); + stmt.setIncludedFileReadTime(fi.getReadTime()); stmt.setErrorInIncludedFile(source.hasError()); if (!fCurrentContext.isPragmaOnce()) { // Track the loaded version count, even in a non-pragma-once context. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/FileCharArray.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/FileCharArray.java index 66708a23bb3..94c45ff9255 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/FileCharArray.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/FileCharArray.java @@ -186,6 +186,7 @@ public class FileCharArray extends LazyCharArray { decode(channel, chunk.fSourceOffset, chunk.fSourceEndOffset, CharBuffer.wrap(dest)); } catch (IOException e) { // File cannot be read + CCorePlugin.log(e); fHasError = true; } finally { try { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/IncludeSearchPathElement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/IncludeSearchPathElement.java index 7cd2ef5e4da..458dbc3f632 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/IncludeSearchPathElement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/IncludeSearchPathElement.java @@ -15,7 +15,7 @@ import java.io.File; /** * Represents an entry of the include search path */ -final class IncludeSearchPathElement { +public final class IncludeSearchPathElement { private static final boolean NON_SLASH_SEPARATOR = File.separatorChar != '/'; public static final String FRAMEWORK_VAR = "__framework__"; //$NON-NLS-1$ public static final String FILE_VAR = "__header__"; //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContent.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContent.java index d8daeb12efb..5ce1b706be9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContent.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContent.java @@ -60,6 +60,7 @@ public class InternalFileContent extends FileContent { private IncludeSearchPathElement fFoundOnPath; private final long fTimestamp; private final long fFileSize; + private final long fReadTime; /** * For skipping include files. @@ -79,7 +80,8 @@ public class InternalFileContent extends FileContent { fSource= null; fNonPragmaOnceFiles= null; fTimestamp= NULL_TIMESTAMP; - fFileSize = NULL_FILE_SIZE; + fFileSize= NULL_FILE_SIZE; + fReadTime= 0; } /** @@ -87,7 +89,7 @@ public class InternalFileContent extends FileContent { * @throws IllegalArgumentException in case the codeReader or its location is <code>null</code>. */ public InternalFileContent(String filePath, AbstractCharArray content, long timestamp, - long fileSize) throws IllegalArgumentException { + long fileSize, long fileReadTime) throws IllegalArgumentException { if (content == null) { throw new IllegalArgumentException(); } @@ -101,7 +103,8 @@ public class InternalFileContent extends FileContent { throw new IllegalArgumentException(); } fTimestamp= timestamp; - fFileSize = fileSize; + fFileSize= fileSize; + fReadTime= fileReadTime; } /** @@ -123,6 +126,7 @@ public class InternalFileContent extends FileContent { } fTimestamp= NULL_TIMESTAMP; fFileSize = NULL_FILE_SIZE; + fReadTime= 0; } /** @@ -144,6 +148,7 @@ public class InternalFileContent extends FileContent { fNonPragmaOnceFiles= nonPragmaOnceVersions; fTimestamp= NULL_TIMESTAMP; fFileSize = NULL_FILE_SIZE; + fReadTime= 0; } /** @@ -167,6 +172,11 @@ public class InternalFileContent extends FileContent { } @Override + public long getReadTime() { + return fReadTime; + } + + @Override public long getFileSize() { return fFileSize; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java index 8a15c8298a1..b86005f0d7a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java @@ -584,6 +584,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { final boolean forceAll= (fUpdateFlags & IIndexManager.UPDATE_ALL) != 0; final boolean checkTimestamps= (fUpdateFlags & IIndexManager.UPDATE_CHECK_TIMESTAMPS) != 0; final boolean checkFileContentsHash = (fUpdateFlags & IIndexManager.UPDATE_CHECK_CONTENTS_HASH) != 0; + final boolean forceUnresolvedIncludes = (fUpdateFlags & IIndexManager.UPDATE_UNRESOLVED_INCLUDES) != 0; final boolean both = fIndexHeadersWithoutContext == UnusedHeaderStrategy.useBoth; int count= 0; int forceFirst= fForceNumberFiles; @@ -616,7 +617,9 @@ public abstract class AbstractIndexerTask extends PDOMWriter { if (ifile != null && ifile.getLinkageID() == linkageID && ifile.hasContent()) { foundInLinkage = true; indexFiles[i]= null; // Take the file. - boolean update= force || isModified(checkTimestamps, checkFileContentsHash, ifl, tu, ifile); + boolean update= force || + (forceUnresolvedIncludes && ifile.hasUnresolvedInclude()) || + isModified(checkTimestamps, checkFileContentsHash, ifl, tu, ifile); if (update && requestUpdate(linkageID, ifl, ifile, tu, updateKind)) { count++; linkages.set(linkageID); @@ -639,7 +642,9 @@ public abstract class AbstractIndexerTask extends PDOMWriter { iFilesToRemove.add(ifile); count++; } else { - boolean update= force || isModified(checkTimestamps, checkFileContentsHash, ifl, tu, ifile); + boolean update= force || + (forceUnresolvedIncludes && ifile.hasUnresolvedInclude()) || + isModified(checkTimestamps, checkFileContentsHash, ifl, tu, ifile); final int linkageID = ifile.getLinkageID(); if (update && requestUpdate(linkageID, ifl, ifile, tu, UpdateKind.OTHER_HEADER)) { count++; @@ -648,7 +653,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { } } } - for (int lid = linkages.nextSetBit(0); lid >= 0; lid= linkages.nextSetBit(lid+1)) { + for (int lid = linkages.nextSetBit(0); lid >= 0; lid= linkages.nextSetBit(lid + 1)) { addPerLinkage(lid, ifl, files); } } 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 3d027cb7c6b..b7f081a4cc9 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 @@ -72,6 +72,7 @@ import org.eclipse.cdt.internal.core.pdom.db.BTree; import org.eclipse.cdt.internal.core.pdom.db.ChunkCache; import org.eclipse.cdt.internal.core.pdom.db.DBProperties; import org.eclipse.cdt.internal.core.pdom.db.Database; +import org.eclipse.cdt.internal.core.pdom.db.IBTreeComparator; import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor; import org.eclipse.cdt.internal.core.pdom.dom.BindingCollector; import org.eclipse.cdt.internal.core.pdom.dom.FindBinding; @@ -215,10 +216,11 @@ public class PDOM extends PlatformObject implements IPDOM { * 122.0 - Compacting strings * 123.0 - Combined file size and encoding hash code. * 124.0 - GCC attributes and NO_RETURN flag for functions. + * 125.0 - Indexes for unresolved includes and files indexed with I/O errors. */ - private static final int MIN_SUPPORTED_VERSION= version(124, 0); - private static final int MAX_SUPPORTED_VERSION= version(124, Short.MAX_VALUE); - private static final int DEFAULT_VERSION = version(124, 0); + private static final int MIN_SUPPORTED_VERSION= version(125, 0); + private static final int MAX_SUPPORTED_VERSION= version(125, Short.MAX_VALUE); + private static final int DEFAULT_VERSION = version(125, 0); private static int version(int major, int minor) { return (major << 16) + minor; @@ -251,8 +253,10 @@ public class PDOM extends PlatformObject implements IPDOM { public static final int LINKAGES = Database.DATA_AREA; public static final int FILE_INDEX = Database.DATA_AREA + 4; - public static final int PROPERTIES = Database.DATA_AREA + 8; - public static final int END= Database.DATA_AREA + 12; + public static final int INDEX_OF_DEFECTIVE_FILES = Database.DATA_AREA + 8; + public static final int INDEX_OF_FILES_WITH_UNRESOLVED_INCLUDES = Database.DATA_AREA + 12; + public static final int PROPERTIES = Database.DATA_AREA + 16; + public static final int END= Database.DATA_AREA + 20; static { assert END <= Database.CHUNK_SIZE; } @@ -303,9 +307,19 @@ public class PDOM extends PlatformObject implements IPDOM { public void handleChange(PDOM pdom, ChangeEvent event); } + // Primitive comparator that compares database offsets of two records. + private static final IBTreeComparator offsetComparator = new IBTreeComparator() { + @Override + public int compare(long record1, long record2) throws CoreException { + return record1 < record2 ? -1 : record1 == record2 ? 0 : 1; + } + }; + // Local caches protected Database db; private BTree fileIndex; + private BTree indexOfDefectiveFiles; + private BTree indexOfFiledWithUnresolvedIncludes; private Map<Integer, PDOMLinkage> fLinkageIDCache = new HashMap<Integer, PDOMLinkage>(); private File fPath; private IIndexLocationConverter locationConverter; @@ -432,6 +446,26 @@ public class PDOM extends PlatformObject implements IPDOM { return fileIndex; } + /** + * Returns the index of files that were read with I/O errors. + */ + public BTree getIndexOfDefectiveFiles() throws CoreException { + if (indexOfDefectiveFiles == null) + indexOfDefectiveFiles = new BTree(getDB(), INDEX_OF_DEFECTIVE_FILES, offsetComparator); + return indexOfDefectiveFiles; + } + + /** + * Returns the index of files containg unresolved includes. + */ + public BTree getIndexOfFilesWithUnresolvedIncludes() throws CoreException { + if (indexOfFiledWithUnresolvedIncludes == null) { + indexOfFiledWithUnresolvedIncludes = + new BTree(getDB(), INDEX_OF_FILES_WITH_UNRESOLVED_INCLUDES, offsetComparator); + } + return indexOfFiledWithUnresolvedIncludes; + } + @Deprecated @Override public PDOMFile getFile(int linkageID, IIndexFileLocation location) throws CoreException { @@ -471,8 +505,22 @@ public class PDOM extends PlatformObject implements IPDOM { @Override public IIndexFragmentFile[] getAllFiles() throws CoreException { - final List<PDOMFile> locations = new ArrayList<PDOMFile>(); - getFileIndex().accept(new IBTreeVisitor() { + return getFiles(getFileIndex()); + } + + @Override + public IIndexFragmentFile[] getDefectiveFiles() throws CoreException { + return getFiles(getIndexOfDefectiveFiles()); + } + + @Override + public IIndexFragmentFile[] getFilesWithUnresolvedIncludes() throws CoreException { + return getFiles(getIndexOfFilesWithUnresolvedIncludes()); + } + + private IIndexFragmentFile[] getFiles(BTree index) throws CoreException { + final List<PDOMFile> files = new ArrayList<PDOMFile>(); + index.accept(new IBTreeVisitor() { @Override public int compare(long record) throws CoreException { return 0; @@ -481,13 +529,13 @@ public class PDOM extends PlatformObject implements IPDOM { @Override public boolean visit(long record) throws CoreException { PDOMFile file = PDOMFile.recreateFile(PDOM.this, record); - locations.add(file); + files.add(file); return true; } }); - return locations.toArray(new IIndexFragmentFile[locations.size()]); + return files.toArray(new IIndexFragmentFile[files.size()]); } - + protected IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location, ISignificantMacros sigMacros) throws CoreException { PDOMLinkage linkage= createLinkage(linkageID); @@ -1296,6 +1344,8 @@ public class PDOM extends PlatformObject implements IPDOM { private void clearCaches() { fileIndex= null; + indexOfDefectiveFiles= null; + indexOfFiledWithUnresolvedIncludes= null; fLinkageIDCache.clear(); clearResultCache(); } 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 20f4d820d0a..99d43bc24d3 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2012 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 @@ -41,7 +41,7 @@ import org.eclipse.core.runtime.IProgressMonitor; /** * The PDOMProxy is returned by the PDOMManager before the indexer kicks in. Also and more * importantly it is returned when the indexer has been shut down (clients may not be aware - * of this yet). Doing that prevents the creation of empty pdoms for deleted projects. + * of this yet). Doing that prevents the creation of empty PDOMs for deleted projects. */ public class PDOMProxy implements IPDOM { private PDOM fDelegate; @@ -319,6 +319,20 @@ public class PDOMProxy implements IPDOM { } @Override + public synchronized IIndexFragmentFile[] getDefectiveFiles() throws CoreException { + if (fDelegate != null) + return fDelegate.getDefectiveFiles(); + return IIndexFragmentFile.EMPTY_ARRAY; + } + + @Override + public synchronized IIndexFragmentFile[] getFilesWithUnresolvedIncludes() throws CoreException { + if (fDelegate != null) + return fDelegate.getFilesWithUnresolvedIncludes(); + return IIndexFragmentFile.EMPTY_ARRAY; + } + + @Override public synchronized IIndexFragmentBinding[] findMacroContainers(Pattern pattern, IndexFilter filter, IProgressMonitor monitor) throws CoreException { if (fDelegate != null) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java index c3b7c051b92..bcdc654fe9f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java @@ -79,6 +79,7 @@ abstract public class PDOMWriter { final long timestamp; final long fileSize; final long contentsHash; + final long sourceReadTime; final boolean hasError; public FileInAST(IASTPreprocessorIncludeStatement includeStmt, FileContentKey key) { @@ -87,6 +88,7 @@ abstract public class PDOMWriter { timestamp= includeStmt.getIncludedFileTimestamp(); fileSize = includeStmt.getIncludedFileSize(); contentsHash= includeStmt.getIncludedFileContentsHash(); + sourceReadTime= includeStmt.getIncludedFileReadTime(); hasError= includeStmt.isErrorInIncludedFile(); } @@ -96,6 +98,7 @@ abstract public class PDOMWriter { timestamp= codeReader.getTimestamp(); fileSize= codeReader.getFileSize(); contentsHash= codeReader.getContentsHash(); + sourceReadTime= codeReader.getReadTime(); hasError= codeReader.hasError(); } @@ -577,6 +580,7 @@ abstract public class PDOMWriter { index.setFileContent(file, linkageID, includeInfoArray, macros, names, fResolver, lock); } file.setTimestamp(astFile.hasError ? 0 : astFile.timestamp); + file.setSourceReadTime(astFile.sourceReadTime); file.setSizeAndEncodingHashcode(computeFileSizeAndEncodingHashcode(astFile.fileSize, location)); file.setContentsHash(astFile.contentsHash); file = index.commitUncommittedFile(); 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 aaeb280dfd8..89b1b26d487 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 @@ -87,17 +87,36 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment { public IIndexFragmentFile commitUncommittedFile() throws CoreException { if (uncommittedFile == null) return null; + + int defectiveStateChange = uncommittedFile.getTimestamp() == 0 ? 1 : 0; + int unresolvedIncludeStateChange = uncommittedFile.hasUnresolvedInclude() ? 1 : 0; + PDOMFile file; if (fileBeingUpdated == null) { // New file, insert it into the index. file = uncommittedFile; - getFileIndex().insert(file.getRecord()); + getFileIndex().insert(file.getRecord()); } else { // Existing file. + if (fileBeingUpdated.getTimestamp() == 0) + defectiveStateChange -= 1; + if (fileBeingUpdated.hasUnresolvedInclude()) + unresolvedIncludeStateChange -= 1; fileBeingUpdated.replaceContentsFrom(uncommittedFile); file = fileBeingUpdated; fileBeingUpdated = null; } + if (defectiveStateChange > 0) { + getIndexOfDefectiveFiles().insert(file.getRecord()); + } else if (defectiveStateChange < 0) { + getIndexOfDefectiveFiles().delete(file.getRecord()); + } + if (unresolvedIncludeStateChange > 0) { + getIndexOfFilesWithUnresolvedIncludes().insert(file.getRecord()); + } else if (unresolvedIncludeStateChange < 0) { + getIndexOfFilesWithUnresolvedIncludes().delete(file.getRecord()); + } + fEvent.fFilesWritten.add(uncommittedKey.getLocation()); uncommittedFile = null; uncommittedKey = null; 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 816e1dbcbb1..e44b2170e72 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 @@ -72,13 +72,14 @@ public class PDOMFile implements IIndexFragmentFile { private static final int LOCATION_REPRESENTATION = FIRST_MACRO + Database.PTR_SIZE; private static final int LINKAGE_ID= LOCATION_REPRESENTATION + Database.PTR_SIZE; // size 3 private static final int FLAGS= LINKAGE_ID + 3; // size 1 - private static final int TIME_STAMP = FLAGS + 1; // long - private static final int CONTENT_HASH= TIME_STAMP + 8; // long + private static final int TIME_STAMP= FLAGS + 1; // long + private static final int SOURCE_READ_TIME= TIME_STAMP + 8; // long + private static final int CONTENT_HASH= SOURCE_READ_TIME + 8; // long private static final int SIZE_AND_ENCODING_HASH= CONTENT_HASH + 8; private static final int LAST_USING_DIRECTIVE= SIZE_AND_ENCODING_HASH + 4; private static final int FIRST_MACRO_REFERENCE= LAST_USING_DIRECTIVE + Database.PTR_SIZE; private static final int SIGNIFICANT_MACROS= FIRST_MACRO_REFERENCE + Database.PTR_SIZE; - private static final int RECORD_SIZE= SIGNIFICANT_MACROS + Database.PTR_SIZE; // 8*PTR_SIZE + 3+1+8+8+4 = 56 + private static final int RECORD_SIZE= SIGNIFICANT_MACROS + Database.PTR_SIZE; // 8*PTR_SIZE + 3+1+8+8+8+4 = 64 private static final int FLAG_PRAGMA_ONCE_SEMANTICS = 0x01; @@ -205,6 +206,7 @@ public class PDOMFile implements IIndexFragmentFile { } setTimestamp(sourceFile.getTimestamp()); + setSourceReadTime(sourceFile.getSourceReadTime()); setSizeAndEncodingHashcode(sourceFile.getSizeAndEncodingHashcode()); setContentsHash(sourceFile.getContentsHash()); @@ -310,6 +312,18 @@ public class PDOMFile implements IIndexFragmentFile { } @Override + public long getSourceReadTime() throws CoreException { + Database db = fLinkage.getDB(); + return db.getLong(record + SOURCE_READ_TIME); + } + + @Override + public void setSourceReadTime(long time) throws CoreException { + Database db= fLinkage.getDB(); + db.putLong(record + SOURCE_READ_TIME, time); + } + + @Override public long getContentsHash() throws CoreException { Database db = fLinkage.getDB(); return db.getLong(record + CONTENT_HASH); @@ -571,6 +585,7 @@ public class PDOMFile implements IIndexFragmentFile { m.delete(); } setFirstMacroReference(null); + setSourceReadTime(0); setTimestamp(-1); } @@ -645,6 +660,17 @@ public class PDOMFile implements IIndexFragmentFile { } @Override + public boolean hasUnresolvedInclude() throws CoreException { + PDOMInclude include = getFirstInclude(); + while (include != null) { + if (!include.isResolved() && include.isActive()) + return true; + include = include.getNextInIncludes(); + } + return false; + } + + @Override public IIndexMacro[] getMacros() throws CoreException { List<PDOMMacro> result= new ArrayList<PDOMMacro>(); PDOMMacro macro = getFirstMacro(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMUpdateTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMUpdateTask.java index 349ea0fde3f..df8621199c4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMUpdateTask.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMUpdateTask.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2012 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 @@ -11,6 +11,7 @@ ******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.indexer; +import java.io.File; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -22,13 +23,18 @@ import org.eclipse.cdt.core.dom.IPDOMManager; import org.eclipse.cdt.core.index.IIndex; 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.IIndexManager; import org.eclipse.cdt.core.index.IndexLocationFactory; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.internal.core.model.ExternalTranslationUnit; +import org.eclipse.cdt.internal.core.parser.scanner.CPreprocessor; +import org.eclipse.cdt.internal.core.parser.scanner.IncludeSearchPathElement; +import org.eclipse.cdt.internal.core.parser.scanner.ScannerUtility; import org.eclipse.cdt.internal.core.pdom.IndexerProgress; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; @@ -42,19 +48,18 @@ import org.eclipse.osgi.util.NLS; * A task for updating an index, suitable for all indexers. */ public class PDOMUpdateTask implements IPDOMIndexerTask { - protected static final String TRUE= String.valueOf(true); - protected static final ITranslationUnit[] NO_TUS = {}; + private static final ITranslationUnit[] NO_TUS = {}; private final IPDOMIndexer fIndexer; - private final IndexerProgress fProgress; private final int fUpdateOptions; + private final IndexerProgress fProgress; private volatile IPDOMIndexerTask fDelegate; private ArrayList<ICElement> fFilesAndFolders; public PDOMUpdateTask(IPDOMIndexer indexer, int updateOptions) { fIndexer= indexer; - fProgress= createProgress(); fUpdateOptions= updateOptions; + fProgress= createProgress(); } private IndexerProgress createProgress() { @@ -92,40 +97,65 @@ public class PDOMUpdateTask implements IPDOMIndexerTask { private void createDelegate(ICProject project, IProgressMonitor monitor) throws CoreException, InterruptedException { HashSet<ITranslationUnit> set= new HashSet<ITranslationUnit>(); - TranslationUnitCollector collector= new TranslationUnitCollector(set, set, monitor); - boolean haveProject= false; - if (fFilesAndFolders == null) { - project.accept(collector); - } else { - for (ICElement elem : fFilesAndFolders) { - if (elem.getElementType() == ICElement.C_PROJECT) { - haveProject= true; + if ((fUpdateOptions & (IIndexManager.UPDATE_ALL | IIndexManager.UPDATE_CHECK_TIMESTAMPS)) != 0) { + TranslationUnitCollector collector= new TranslationUnitCollector(set, set, monitor); + boolean haveProject= false; + if (fFilesAndFolders == null) { + project.accept(collector); + } else { + for (ICElement elem : fFilesAndFolders) { + if (elem.getElementType() == ICElement.C_PROJECT) { + haveProject= true; + } + elem.accept(collector); + } + } + if (haveProject && (fUpdateOptions & IIndexManager.UPDATE_EXTERNAL_FILES_FOR_PROJECT) != 0) { + final String projectPrefix= project.getProject().getFullPath().toString() + IPath.SEPARATOR; + IIndex index= CCorePlugin.getIndexManager().getIndex(project); + index.acquireReadLock(); + try { + IIndexFile[] files= index.getAllFiles(); + for (IIndexFile indexFile : files) { + IIndexFileLocation floc= indexFile.getLocation(); + final String fullPath = floc.getFullPath(); + if (fullPath == null || !fullPath.startsWith(projectPrefix)) { + ITranslationUnit tu = getTranslationUnit(floc, project); + if (tu != null) { + set.add(tu); + } + } + } + } finally { + index.releaseReadLock(); } - elem.accept(collector); } } - if (haveProject && (fUpdateOptions & IIndexManager.UPDATE_EXTERNAL_FILES_FOR_PROJECT) != 0) { - final String projectPrefix= project.getProject().getFullPath().toString() + IPath.SEPARATOR; + + if ((fUpdateOptions & IIndexManager.UPDATE_UNRESOLVED_INCLUDES) != 0) { IIndex index= CCorePlugin.getIndexManager().getIndex(project); index.acquireReadLock(); try { - IIndexFile[] files= index.getAllFiles(); - for (IIndexFile indexFile : files) { - IIndexFileLocation floc= indexFile.getLocation(); - final String fullPath = floc.getFullPath(); - if (fullPath == null || !fullPath.startsWith(projectPrefix)) { - IPath path= IndexLocationFactory.getAbsolutePath(floc); - if (path != null) { - ITranslationUnit tu= CoreModel.getDefault().createTranslationUnitFrom(project, path); - if (tu != null) { - if (fullPath != null) { - if (tu instanceof ExternalTranslationUnit) { - IResource file= ResourcesPlugin.getWorkspace().getRoot().findMember(fullPath); - if (file instanceof IFile) { - ((ExternalTranslationUnit) tu).setResource((IFile) file); - } - } - } + // Files that were indexed with I/O errors. + IIndexFile[] files= index.getDefectiveFiles(); + for (IIndexFile file : files) { + ITranslationUnit tu = getTranslationUnit(file.getLocation(), project); + if (tu != null) { + set.add(tu); + } + } + + // Files with unresolved includes. + files= index.getFilesWithUnresolvedIncludes(); + if (files.length > 0) { + ProjectIndexerInputAdapter inputAdapter = new ProjectIndexerInputAdapter(project, true); + ProjectIndexerIncludeResolutionHeuristics includeResolutionHeuristics = + new ProjectIndexerIncludeResolutionHeuristics(project.getProject(), inputAdapter); + for (IIndexFile file : files) { + ITranslationUnit tu = getTranslationUnit(file.getLocation(), project); + if (tu != null) { + IScannerInfo scannerInfo = tu.getScannerInfo(true); + if (canResolveUnresolvedInclude(file, scannerInfo, includeResolutionHeuristics)) { set.add(tu); } } @@ -135,15 +165,108 @@ public class PDOMUpdateTask implements IPDOMIndexerTask { index.releaseReadLock(); } } + ITranslationUnit[] tus= set.toArray(new ITranslationUnit[set.size()]); IPDOMIndexerTask delegate= fIndexer.createTask(NO_TUS, tus, NO_TUS); if (delegate instanceof PDOMIndexerTask) { final PDOMIndexerTask task = (PDOMIndexerTask) delegate; task.setUpdateFlags(fUpdateOptions); } - synchronized (this) { - fDelegate= delegate; + setDelegate(delegate); + } + + private ITranslationUnit getTranslationUnit(IIndexFileLocation location, ICProject project) { + IPath path= IndexLocationFactory.getAbsolutePath(location); + if (path == null) + return null; + ITranslationUnit tu= CoreModel.getDefault().createTranslationUnitFrom(project, path); + if (tu != null) { + final String fullPath = location.getFullPath(); + if (fullPath != null) { + if (tu instanceof ExternalTranslationUnit) { + IResource file= ResourcesPlugin.getWorkspace().getRoot().findMember(fullPath); + if (file instanceof IFile) { + ((ExternalTranslationUnit) tu).setResource((IFile) file); + } + } + } + } + return tu; + } + + private boolean canResolveUnresolvedInclude(IIndexFile file, IScannerInfo scannerInfo, + ProjectIndexerIncludeResolutionHeuristics includeResolutionHeuristics) { + try { + String filePath = IndexLocationFactory.getAbsolutePath(file.getLocation()).toOSString(); + long fileReadTime = file.getSourceReadTime(); + IncludeSearchPathElement[] includeSearchPath = + CPreprocessor.configureIncludeSearchPath(new File(filePath).getParentFile(), scannerInfo); + for (IIndexInclude include : file.getIncludes()) { + if (!include.isResolved() && include.isActive() && + canResolveInclude(include, filePath, fileReadTime, includeSearchPath, includeResolutionHeuristics)) { + return true; + } + } + } catch (CoreException e) { + CCorePlugin.log(e); } + return false; + } + + private boolean canResolveInclude(IIndexInclude include, String currentFile, long timestamp, + IncludeSearchPathElement[] includeSearchPath, + ProjectIndexerIncludeResolutionHeuristics includeResolutionHeuristics) throws CoreException { + String includeName = include.getFullName(); + String filePath = CPreprocessor.getAbsoluteInclusionPath(includeName, currentFile); + if (filePath != null && fileIsNotOlderThanTimestamp(filePath, timestamp)) { + return true; + } + + if (currentFile != null && !include.isSystemInclude()) { + // Check to see if we find a match in the current directory + final File currentDir= new File(currentFile).getParentFile(); + if (currentDir != null) { + filePath = ScannerUtility.createReconciledPath(currentDir.getAbsolutePath(), includeName); + if (!filePath.equals(currentFile) && fileIsNotOlderThanTimestamp(filePath, timestamp)) { + return true; + } + } + } + + // Unlike CPreprocessor.findInclusion we are searching include path from the beginning. + // This simplification may produce false positives, but by checking file modification time + // we guarantee that any false positive won't be produced again when this task runs + // next time. + for (IncludeSearchPathElement path : includeSearchPath) { + if (!include.isSystemInclude() || !path.isForQuoteIncludesOnly()) { + filePath = path.getLocation(includeName); + if (filePath != null && fileIsNotOlderThanTimestamp(filePath, timestamp)) { + return true; + } + } + } + if (includeResolutionHeuristics != null) { + filePath= includeResolutionHeuristics.findInclusion(includeName, currentFile); + if (filePath != null && fileIsNotOlderThanTimestamp(filePath, timestamp)) { + return true; + } + } + + return false; + } + + /** + * Returns true if the file exists and is not older than the given timestamp. + */ + private boolean fileIsNotOlderThanTimestamp(String filename, long timestamp) { + // We are subtracting 1 second from the timestamp to account for limited precision + // of File.lastModified() method and possible asynchrony between clocks on multi-CPU + // systems. This may produce false positives, but they are pretty harmless. + return new File(filename).lastModified() >= timestamp - 1000; + } + + private synchronized void setDelegate(IPDOMIndexerTask delegate) { + fDelegate= delegate; } @Override |