diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIncludeStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIncludeStatement.java index a3b29a8e594..01c773d3041 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIncludeStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIncludeStatement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * Copyright (c) 2004, 2012 IBM Corporation 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,15 +8,15 @@ * Contributors: * IBM - Initial API and implementation * Markus Schorn (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast; import org.eclipse.cdt.core.index.IIndexFile; import org.eclipse.cdt.core.parser.ISignificantMacros; - /** - * This interface represent a preprocessor #include statement. + * This interface represents a preprocessor #include statement. * * @noextend This interface is not intended to be extended by clients. * @noimplement This interface is not intended to be implemented by clients. @@ -76,12 +76,30 @@ public interface IASTPreprocessorIncludeStatement extends IASTPreprocessorStatem */ public ISignificantMacros[] getLoadedVersions(); + /** + * Returns the modification time of the included file, or -1 if the file was not read. + * @since 5.4 + */ + public long getIncludedFileTimestamp(); + + /** + * Returns the size of the included file, or -1 if the file was not read. + * @since 5.4 + */ + public long getIncludedFileSize(); + /** * Returns a hash-code for the contents of the file included, or 0 * if the content has not been parsed. * @since 5.4 */ - public long getContentsHash(); + public long getIncludedFileContentsHash(); + + /** + * Returns true if I/O errors were encountered while reading the included file. + * @since 5.4 + */ + public boolean isErrorInIncludedFile(); /** * Returns true, if an attempt will be or has been made to create AST for the target diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/FileContent.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/FileContent.java index 97bcf49542c..f9a93b043a8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/FileContent.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/FileContent.java @@ -29,11 +29,37 @@ import org.eclipse.core.runtime.IPath; * @since 5.2 */ public abstract class FileContent { + /** @since 5.4 */ + public static final long NULL_TIMESTAMP = -1; + /** @since 5.4 */ + public static final long NULL_FILE_SIZE = -1; + /** * Returns the location of this file content as it will appear in {@link IASTFileLocation#getFileName()} */ public abstract String getFileLocation(); + /** + * Returns the modification time of the file containing the content or NULL_TIMESTAMP if + * the content does not originate from a file. A zero value may be returned if there was + * an I/O error. + * @since 5.4 + */ + public abstract long getTimestamp(); + + /** + * Returns the size of the file, or NULL_FILE_SIZE if the content does not originate from + * a file. A zero value may be returned if there was an I/O error. + * @since 5.4 + */ + public abstract long getFileSize(); + + /** + * Returns {@code true} if there were I/O errors while retrieving contents of this file. + * @since 5.4 + */ + public abstract boolean hasError(); + /** * Returns a 64-bit hash value of the file contents. */ @@ -47,7 +73,7 @@ public abstract class FileContent { public static FileContent create(String filePath, char[] contents) { return new InternalFileContent(filePath, new CharArray(contents)); } - + /** * Creates a file content object for a translation-unit, which may be a working copy. */ 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 c47c98eeaec..37ac0d0b27b 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 @@ -27,6 +27,7 @@ import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent; import org.eclipse.cdt.internal.core.resources.PathCanonicalizationStrategy; import org.eclipse.cdt.utils.UNCPathConverter; import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileInfo; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; @@ -152,28 +153,30 @@ public class InternalParserUtil extends ParserFactory { String path= file.getLocationURI().getPath(); path= normalizePath(path, file); - InputStream in; + InputStream input; try { - in= file.getContents(true); - if (!(in instanceof FileInputStream)) { + IFileStore store = EFS.getStore(file.getLocationURI()); + IFileInfo fileInfo = store.fetchInfo(); + input= file.getContents(true); + if (!(input instanceof FileInputStream)) { /* - * In general, non-local file-systems will not use FileInputStream. Instead make a - * cached copy of the file and open an input stream to that. + * In general, non-local file-systems will not use FileInputStream. + * Instead make a cached copy of the file and open an input stream to that. */ - IFileStore store = EFS.getStore(file.getLocationURI()); File fileCache = store.toLocalFile(EFS.CACHE, null); try { - in = new FileInputStream(fileCache); + input = new FileInputStream(fileCache); } catch (FileNotFoundException e) { CCorePlugin.log(e); return null; } } try { - return createFileContent(path, file.getCharset(), in); + return createFileContent(path, file.getCharset(), input, + fileInfo.getLastModified(), fileInfo.getLength()); } finally { try { - in.close(); + input.close(); } catch (IOException e) { } } @@ -215,6 +218,8 @@ public class InternalParserUtil extends ParserFactory { } } if (includeFile != null && includeFile.isFile()) { + long timestamp = includeFile.lastModified(); + long fileSize = includeFile.length(); FileInputStream in; try { in = new FileInputStream(includeFile); @@ -223,7 +228,7 @@ public class InternalParserUtil extends ParserFactory { return null; } try { - return createFileContent(path, encoding, in); + return createFileContent(path, encoding, in, timestamp, fileSize); } finally { try { in.close(); @@ -234,13 +239,14 @@ public class InternalParserUtil extends ParserFactory { return null; } - private static InternalFileContent createFileContent(String path, String charset, InputStream in) { + private static InternalFileContent createFileContent(String path, String charset, InputStream in, + long fileTimestamp, long fileSize) { try { AbstractCharArray chars= FileCharArray.create(path, charset, in); if (chars == null) return null; - return new InternalFileContent(path, chars); + return new InternalFileContent(path, chars, fileTimestamp, fileSize); } 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 605bdf42a9c..8cf8471286d 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2011 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 @@ -7,6 +7,7 @@ * * Contributors: * Markus Schorn - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.parser.scanner; @@ -294,7 +295,10 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces private boolean fCreatesAST; private ISignificantMacros fSignificantMacros; private ISignificantMacros[] fLoadedVersions = NO_VERSIONS; - private long fContentsHash; + private long fIncludedFileContentsHash; + private long fIncludedFileTimestamp = -1; + private long fIncludedFileSize; + private boolean fErrorInIncludedFile; public ASTInclusionStatement(IASTTranslationUnit parent, int startNumber, int nameStartNumber, int nameEndNumber, int endNumber, @@ -388,17 +392,56 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces } @Override - public long getContentsHash() { + public long getIncludedFileTimestamp() { if (fNominationDelegate != null) { return 0; } - return fContentsHash; + return fIncludedFileTimestamp; } - public void setContentsHash(long hash) { + public void setIncludedFileTimestamp(long timestamp) { + assert fNominationDelegate == null; + fIncludedFileTimestamp= timestamp; + } + + @Override + public long getIncludedFileSize() { + if (fNominationDelegate != null) { + return 0; + } + return fIncludedFileSize; + } + + public void setIncludedFileSize(long size) { + assert fNominationDelegate == null; + fIncludedFileSize= size; + } + + @Override + public long getIncludedFileContentsHash() { + if (fNominationDelegate != null) { + return 0; + } + return fIncludedFileContentsHash; + } + + public void setIncludedFileContentsHash(long hash) { assert fNominationDelegate == null; fCreatesAST= true; - fContentsHash= hash; + fIncludedFileContentsHash= hash; + } + + @Override + public boolean isErrorInIncludedFile() { + if (fNominationDelegate != null) { + return false; + } + return fErrorInIncludedFile; + } + + public void setErrorInIncludedFile(boolean error) { + assert fNominationDelegate == null; + fErrorInIncludedFile= error; } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/AbstractCharArray.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/AbstractCharArray.java index 72d90942cc9..dfe7e27a2da 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/AbstractCharArray.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/AbstractCharArray.java @@ -53,6 +53,11 @@ public abstract class AbstractCharArray { */ public abstract void arraycopy(int offset, char[] destination, int destinationPos, int length); + /** + * Returns {@code true} if there were I/O errors while retrieving contents of this array. + */ + public abstract boolean hasError(); + /** * This method is slow. Use only for debugging. */ 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 fc66bb4a861..0829535d524 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2011 IBM Corporation and others. + * Copyright (c) 2004, 2012 IBM Corporation 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 @@ -1487,7 +1487,10 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { detectIncludeGuard(path, source, fctx); fCurrentContext= fctx; stmt= ctx.getInclusionStatement(); - stmt.setContentsHash(source.getContentsHash()); + stmt.setIncludedFileTimestamp(fi.getTimestamp()); + stmt.setIncludedFileSize(fi.getFileSize()); + stmt.setIncludedFileContentsHash(source.getContentsHash()); + stmt.setErrorInIncludedFile(source.hasError()); if (!fCurrentContext.isPragmaOnce()) { // Track the loaded version count, even in a non-pragma-once context. loadedVerisons= fFileContentProvider.getLoadedVersions(path); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CharArray.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CharArray.java index ba1748cf60a..00fad00fc6e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CharArray.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CharArray.java @@ -55,6 +55,11 @@ public final class CharArray extends AbstractCharArray { return offset < fArray.length; } + @Override + public boolean hasError() { + return false; + } + @Override public long getContentsHash() { if (hash64 == 0 && fArray.length != 0) { 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 eba6c0652af..66708a23bb3 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 @@ -30,7 +30,8 @@ import org.eclipse.cdt.core.CCorePlugin; public class FileCharArray extends LazyCharArray { private static final String UTF8_CHARSET_NAME = "UTF-8"; //$NON-NLS-1$ - public static AbstractCharArray create(String fileName, String charSet, InputStream in) throws IOException { + public static AbstractCharArray create(String fileName, String charSet, InputStream in) + throws IOException { // No support for non-local files. if (!(in instanceof FileInputStream)) { return null; @@ -48,7 +49,8 @@ public class FileCharArray extends LazyCharArray { return new FileCharArray(fileName, charSet); } - private static AbstractCharArray decodeSmallFile(FileChannel channel, int lsize, String charSet) throws IOException { + private static AbstractCharArray decodeSmallFile(FileChannel channel, int lsize, String charSet) + throws IOException { ByteBuffer byteBuffer = ByteBuffer.allocate(lsize); channel.read(byteBuffer); byteBuffer.flip(); @@ -80,8 +82,9 @@ public class FileCharArray extends LazyCharArray { return buf; } - private String fFileName; - private String fCharSet; + private final String fFileName; + private final String fCharSet; + private boolean fHasError; private FileChannel fChannel; private long fNextFileOffset; private int fNextCharOffset; @@ -97,8 +100,9 @@ public class FileCharArray extends LazyCharArray { FileInputStream fis; try { fis = new FileInputStream(fFileName); - } catch (FileNotFoundException e1) { + } catch (FileNotFoundException e) { // File has been deleted in the meantime + fHasError = true; return null; } fChannel= fis.getChannel(); @@ -121,8 +125,9 @@ public class FileCharArray extends LazyCharArray { try { assert fChannel != null; final Charset charset = Charset.forName(fCharSet); - final CharsetDecoder decoder = charset.newDecoder().onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE); + final CharsetDecoder decoder = charset.newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); int needBytes = 3 + (int) (CHUNK_SIZE * (double) decoder.averageCharsPerByte()); // avoid rounding errors. final ByteBuffer in = ByteBuffer.allocate(needBytes); @@ -141,7 +146,7 @@ public class FileCharArray extends LazyCharArray { skipUTF8ByteOrderMark(in, fCharSet); } result = decoder.decode(in, dest, eof); - fileOffset+= in.position(); + fileOffset += in.position(); } while (result == CoderResult.UNDERFLOW && !eof); dest.flip(); @@ -154,14 +159,14 @@ public class FileCharArray extends LazyCharArray { } final char[] chars = extractChars(dest); Chunk chunk = newChunk(fNextFileOffset, fileOffset, fNextCharOffset, chars); - fNextFileOffset= fileOffset; - fNextCharOffset+= chars.length; - + fNextFileOffset = fileOffset; + fNextCharOffset += chars.length; return chunk; } catch (Exception e) { // The file cannot be read CCorePlugin.log(e); - fReachedEOF= true; + fHasError = true; + fReachedEOF = true; return null; } } @@ -173,6 +178,7 @@ public class FileCharArray extends LazyCharArray { fis = new FileInputStream(fFileName); } catch (FileNotFoundException e1) { // File has been deleted in the meantime + fHasError = true; return; } try { @@ -180,6 +186,7 @@ public class FileCharArray extends LazyCharArray { decode(channel, chunk.fSourceOffset, chunk.fSourceEndOffset, CharBuffer.wrap(dest)); } catch (IOException e) { // File cannot be read + fHasError = true; } finally { try { fis.close(); @@ -188,7 +195,8 @@ public class FileCharArray extends LazyCharArray { } } - private void decode(FileChannel channel, long fileOffset, long fileEndOffset, CharBuffer dest) throws IOException { + private void decode(FileChannel channel, long fileOffset, long fileEndOffset, CharBuffer dest) + throws IOException { final Charset charset = Charset.forName(fCharSet); final CharsetDecoder decoder = charset.newDecoder() .onMalformedInput(CodingErrorAction.REPLACE) @@ -205,4 +213,9 @@ public class FileCharArray extends LazyCharArray { } decoder.decode(in, dest, true); } + + @Override + public boolean hasError() { + return fHasError; + } } 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 56534886481..d8daeb12efb 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 @@ -6,8 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Markus Schorn - initial API and implementation - * Sergey Prigogin (Google) + * Markus Schorn - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.parser.scanner; @@ -55,9 +55,11 @@ public class InternalFileContent extends FileContent { private final String fFileLocation; private final List fNonPragmaOnceFiles; private boolean fHeuristic; - private boolean fIsSource= false; + private boolean fIsSource; private List fFiles; private IncludeSearchPathElement fFoundOnPath; + private final long fTimestamp; + private final long fFileSize; /** * For skipping include files. @@ -76,13 +78,16 @@ public class InternalFileContent extends FileContent { fUsingDirectives= null; fSource= null; fNonPragmaOnceFiles= null; + fTimestamp= NULL_TIMESTAMP; + fFileSize = NULL_FILE_SIZE; } /** * For reading include files from disk. * @throws IllegalArgumentException in case the codeReader or its location is null. */ - public InternalFileContent(String filePath, AbstractCharArray content) throws IllegalArgumentException { + public InternalFileContent(String filePath, AbstractCharArray content, long timestamp, + long fileSize) throws IllegalArgumentException { if (content == null) { throw new IllegalArgumentException(); } @@ -95,6 +100,29 @@ public class InternalFileContent extends FileContent { if (fFileLocation == null) { throw new IllegalArgumentException(); } + fTimestamp= timestamp; + fFileSize = fileSize; + } + + /** + * For reading in-memory buffers. + * @throws IllegalArgumentException in case the codeReader or its location is null. + */ + public InternalFileContent(String filePath, CharArray content) throws IllegalArgumentException { + if (content == null) { + throw new IllegalArgumentException(); + } + fKind= InclusionKind.USE_SOURCE; + fFileLocation= filePath; + fSource= content; + fMacroDefinitions= null; + fUsingDirectives= null; + fNonPragmaOnceFiles= null; + if (fFileLocation == null) { + throw new IllegalArgumentException(); + } + fTimestamp= NULL_TIMESTAMP; + fFileSize = NULL_FILE_SIZE; } /** @@ -104,8 +132,9 @@ public class InternalFileContent extends FileContent { * @param files * @throws IllegalArgumentException in case the fileLocation or the macroDefinitions are null. */ - public InternalFileContent(String fileLocation, List macroDefinitions, List usingDirectives, - List files, List nonPragmaOnceVersions) { + public InternalFileContent(String fileLocation, List macroDefinitions, + List usingDirectives, List files, + List nonPragmaOnceVersions) { fKind= InclusionKind.FOUND_IN_INDEX; fFileLocation= fileLocation; fSource= null; @@ -113,6 +142,8 @@ public class InternalFileContent extends FileContent { fMacroDefinitions= macroDefinitions; fFiles= files; fNonPragmaOnceFiles= nonPragmaOnceVersions; + fTimestamp= NULL_TIMESTAMP; + fFileSize = NULL_FILE_SIZE; } /** @@ -130,14 +161,26 @@ public class InternalFileContent extends FileContent { return fFileLocation; } - /** - * Returns a 64-bit hash value of the file contents. - */ + @Override + public long getTimestamp() { + return fTimestamp; + } + + @Override + public long getFileSize() { + return fFileSize; + } + @Override public long getContentsHash() { return fSource != null ? fSource.getContentsHash() : 0; } + @Override + public boolean hasError() { + return fSource != null && fSource.hasError(); + } + /** * Valid with {@link InclusionKind#USE_SOURCE}. * @return the codeReader or null if kind is different to {@link InclusionKind#USE_SOURCE}. @@ -200,7 +243,7 @@ public class InternalFileContent extends FileContent { public void setFoundOnPath(IncludeSearchPathElement isp) { fFoundOnPath= isp; } - + /** * This method is slow. Use only for debugging. */ 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 9c30c079929..a67dc06a458 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 @@ -725,7 +725,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { @Override protected void reportFileWrittenToIndex(FileInAST file, IIndexFragmentFile ifile) throws CoreException { - final FileContentKey fck = file.fFileContentKey; + final FileContentKey fck = file.fileContentKey; final IIndexFileLocation location = fck.getLocation(); boolean wasCounted= false; UpdateKind kind= UpdateKind.OTHER_HEADER; @@ -748,7 +748,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { } } fIndexContentCache.remove(ifile); - fIndexFilesCache.remove(file.fFileContentKey.getLocation()); + fIndexFilesCache.remove(file.fileContentKey.getLocation()); LocationTask task= fOneLinkageTasks.remove(location); if (task != null && task != locTask) { @@ -978,8 +978,9 @@ public abstract class AbstractIndexerTask extends PDOMWriter { } - private DependsOnOutdatedFileException parseFile(Object tu, AbstractLanguage lang, IIndexFileLocation ifl, IScannerInfo scanInfo, - FileContext ctx, IProgressMonitor pm) throws CoreException, InterruptedException { + private DependsOnOutdatedFileException parseFile(Object tu, AbstractLanguage lang, + IIndexFileLocation ifl, IScannerInfo scanInfo, FileContext ctx, IProgressMonitor pm) + throws CoreException, InterruptedException { IPath path= getLabel(ifl); Throwable th= null; try { @@ -995,7 +996,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { IASTTranslationUnit ast= createAST(lang, codeReader, scanInfo, isSource, fASTOptions, ctx, pm); fStatistics.fParsingTime += System.currentTimeMillis() - start; if (ast != null) { - writeToIndex(lang.getLinkageID(), ast, codeReader.getContentsHash(), ctx, pm); + writeToIndex(lang.getLinkageID(), ast, codeReader, ctx, pm); } } catch (CoreException e) { th= e; @@ -1133,7 +1134,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { throw new IllegalArgumentException("Invalid file content provider"); //$NON-NLS-1$ } - private void writeToIndex(final int linkageID, IASTTranslationUnit ast, long fileContentsHash, + private void writeToIndex(final int linkageID, IASTTranslationUnit ast, FileContent codeReader, FileContext ctx, IProgressMonitor pm) throws CoreException, InterruptedException { HashSet enteredFiles= new HashSet(); ArrayList orderedFileKeys= new ArrayList(); @@ -1149,11 +1150,11 @@ public abstract class AbstractIndexerTask extends PDOMWriter { IIndexFragmentFile newFile= selectIndexFile(linkageID, topIfl, ast.getSignificantMacros()); if (ctx != null) { - orderedFileKeys.add(new FileInAST(null, topKey, fileContentsHash)); + orderedFileKeys.add(new FileInAST(topKey, codeReader)); // File can be reused ctx.fNewFile= newFile; } else if (newFile == null) { - orderedFileKeys.add(new FileInAST(null, topKey, fileContentsHash)); + orderedFileKeys.add(new FileInAST(topKey, codeReader)); } FileInAST[] fileKeys= orderedFileKeys.toArray(new FileInAST[orderedFileKeys.size()]); @@ -1184,7 +1185,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { collectOrderedFileKeys(linkageID, element, enteredFiles, orderedFileKeys); } if (isFirstEntry && selectIndexFile(linkageID, ifl, include.getSignificantMacros()) == null) { - orderedFileKeys.add(new FileInAST(include, fileKey, include.getContentsHash())); + orderedFileKeys.add(new FileInAST(include, fileKey)); } } } @@ -1193,7 +1194,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { LinkageTask map = findRequestMap(linkageID); if (map != null) { for (FileInAST fileKey : fileKeys) { - LocationTask locTask = map.find(fileKey.fFileContentKey.getLocation()); + LocationTask locTask = map.find(fileKey.fileContentKey.getLocation()); if (locTask != null) { if (locTask.fCountedUnknownVersion) { locTask.fCountedUnknownVersion= false; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/IndexerInputAdapter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/IndexerInputAdapter.java index d49d6c13d81..69349d5fac2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/IndexerInputAdapter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/IndexerInputAdapter.java @@ -37,12 +37,12 @@ public abstract class IndexerInputAdapter extends ASTFilePathResolver { /** * Returns the size of the file in bytes, or 0 if the file does not exist. */ - public abstract long getFileSize(IIndexFileLocation ifl); + public abstract long getFileSize(IIndexFileLocation location); /** * Returns the encoding for the file. */ - public abstract String getEncoding(IIndexFileLocation ifl); + public abstract String getEncoding(IIndexFileLocation location); /** * Create an index location for the given input file. @@ -70,7 +70,7 @@ public abstract class IndexerInputAdapter extends ASTFilePathResolver { * @param ifl The Location of the file. * @return {@code true} if the file should be indexed unconditionally. */ - public abstract boolean isIndexedUnconditionally(IIndexFileLocation ifl); + public abstract boolean isIndexedUnconditionally(IIndexFileLocation location); /** * Tests whether the file in the index is allowed to be part of an SDK. If not 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 ed854f09862..c3b7c051b92 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2011 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 @@ -48,6 +48,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; 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.parser.FileContent; import org.eclipse.cdt.core.parser.IProblem; import org.eclipse.cdt.core.parser.ISignificantMacros; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; @@ -67,24 +68,40 @@ import org.eclipse.core.runtime.Status; import org.eclipse.osgi.util.NLS; /** - * Abstract class to write information from AST + * Abstract class to write information from AST. * @since 4.0 */ abstract public class PDOMWriter { - public static class FileInAST { - final IASTPreprocessorIncludeStatement fIncludeStatement; - final FileContentKey fFileContentKey; - final long fContentsHash; - public FileInAST(IASTPreprocessorIncludeStatement includeStmt, FileContentKey key, long contentsHash) { - fIncludeStatement= includeStmt; - fFileContentKey= key; - fContentsHash= contentsHash; + public static class FileInAST { + final IASTPreprocessorIncludeStatement includeStatement; + final FileContentKey fileContentKey; + final long timestamp; + final long fileSize; + final long contentsHash; + final boolean hasError; + + public FileInAST(IASTPreprocessorIncludeStatement includeStmt, FileContentKey key) { + includeStatement= includeStmt; + fileContentKey= key; + timestamp= includeStmt.getIncludedFileTimestamp(); + fileSize = includeStmt.getIncludedFileSize(); + contentsHash= includeStmt.getIncludedFileContentsHash(); + hasError= includeStmt.isErrorInIncludedFile(); } - + + public FileInAST(FileContentKey key, FileContent codeReader) { + includeStatement= null; + fileContentKey= key; + timestamp= codeReader.getTimestamp(); + fileSize= codeReader.getFileSize(); + contentsHash= codeReader.getContentsHash(); + hasError= codeReader.hasError(); + } + @Override public String toString() { - return fFileContentKey.toString(); + return fileContentKey.toString(); } } @@ -198,7 +215,7 @@ abstract public class PDOMWriter { Data data= new Data(ast, selectedFiles, index); for (FileInAST file : selectedFiles) { - data.fSymbolMap.put(file.fIncludeStatement, new Symbols()); + data.fSymbolMap.put(file.includeStatement, new Symbols()); } @@ -215,7 +232,7 @@ abstract public class PDOMWriter { if (taskUpdater != null) { Set locations= new HashSet(); for (FileInAST file : selectedFiles) { - locations.add(file.fFileContentKey.getLocation()); + locations.add(file.fileContentKey.getLocation()); } taskUpdater.updateTasks(ast.getComments(), locations.toArray(new IIndexFileLocation[locations.size()])); } @@ -223,7 +240,7 @@ abstract public class PDOMWriter { List stati = data.fStati; String path= null; if (selectedFiles.length > 0) { - path= selectedFiles[selectedFiles.length - 1].fFileContentKey.getLocation().getURI().getPath(); + path= selectedFiles[selectedFiles.length - 1].fileContentKey.getLocation().getURI().getPath(); } else { path= ast.getFilePath().toString(); } @@ -252,13 +269,13 @@ abstract public class PDOMWriter { final FileInAST fileInAST= data.fSelectedFiles[i]; if (fileInAST != null) { if (fShowActivity) { - trace("Indexer: adding " + fileInAST.fFileContentKey.getLocation().getURI()); //$NON-NLS-1$ + trace("Indexer: adding " + fileInAST.fileContentKey.getLocation().getURI()); //$NON-NLS-1$ } Throwable th= null; YieldableIndexLock lock = new YieldableIndexLock(data.fIndex, flushIndex); lock.acquire(); try { - final boolean isReplacement= ctx != null && fileInAST.fIncludeStatement == null; + final boolean isReplacement= ctx != null && fileInAST.includeStatement == null; IIndexFragmentFile ifile= null; if (!isReplacement || newFile == null) { ifile= storeFileInIndex(data, fileInAST, linkageID, lock); @@ -294,7 +311,7 @@ abstract public class PDOMWriter { } if (th != null) { data.fStati.add(createStatus(NLS.bind(Messages.PDOMWriter_errorWhileParsing, - fileInAST.fFileContentKey.getLocation().getURI().getPath()), th)); + fileInAST.fileContentKey.getLocation().getURI().getPath()), th)); } fStatistics.fAddToIndexTime += lock.getCumulativeLockTime(); } @@ -307,7 +324,7 @@ abstract public class PDOMWriter { if (pm.isCanceled()) { return; } - Symbols symbols= data.fSymbolMap.get(file.fIncludeStatement); + Symbols symbols= data.fSymbolMap.get(file.includeStatement); final ArrayList names= symbols.fNames; boolean reported= false; @@ -351,7 +368,7 @@ abstract public class PDOMWriter { if (th != null) { if (!reported) { data.fStati.add(CCorePlugin.createStatus(NLS.bind(Messages.PDOMWriter_errorResolvingName, - name.toString(), file.fFileContentKey.getLocation().getURI().getPath()), th)); + name.toString(), file.fileContentKey.getLocation().getURI().getPath()), th)); } reported= true; j.remove(); @@ -516,8 +533,8 @@ abstract public class PDOMWriter { // contents of the old file from the temporary one, then delete the temporary file. // The write lock on the index can be yielded between adding names to the temporary file, // if another thread is waiting for a read lock. - final FileContentKey fileKey = astFile.fFileContentKey; - final IASTPreprocessorIncludeStatement owner= astFile.fIncludeStatement; + final FileContentKey fileKey = astFile.fileContentKey; + final IASTPreprocessorIncludeStatement owner= astFile.includeStatement; IIndexFileLocation location = fileKey.getLocation(); ISignificantMacros significantMacros = fileKey.getSignificantMacros(); @@ -559,9 +576,9 @@ abstract public class PDOMWriter { IncludeInformation[] includeInfoArray= includeInfos.toArray(new IncludeInformation[includeInfos.size()]); index.setFileContent(file, linkageID, includeInfoArray, macros, names, fResolver, lock); } - file.setTimestamp(fResolver.getLastModified(location)); - file.setSizeAndEncodingHashcode(computeFileSizeAndEncodingHashcode(location)); - file.setContentsHash(astFile.fContentsHash); + file.setTimestamp(astFile.hasError ? 0 : astFile.timestamp); + file.setSizeAndEncodingHashcode(computeFileSizeAndEncodingHashcode(astFile.fileSize, location)); + file.setContentsHash(astFile.contentsHash); file = index.commitUncommittedFile(); } finally { index.clearUncommittedFile(); @@ -570,7 +587,11 @@ abstract public class PDOMWriter { } protected int computeFileSizeAndEncodingHashcode(IIndexFileLocation location) { - return ((int) fResolver.getFileSize(location)) + 31 * fResolver.getEncoding(location).hashCode(); + return computeFileSizeAndEncodingHashcode((int) fResolver.getFileSize(location), location); + } + + private int computeFileSizeAndEncodingHashcode(long size, IIndexFileLocation location) { + return (int) size + 31 * fResolver.getEncoding(location).hashCode(); } private boolean isContextFor(IIndexFragmentFile oldFile, IASTPreprocessorIncludeStatement stmt) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java index bfb8c6cba4c..e24dce8546a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java @@ -320,7 +320,7 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter { ITranslationUnit tu= (ITranslationUnit) tuo; if (tu.getLocation() == null) return null; - + final FileContent reader= FileContent.create(tu); if (reader != null) { IIndexFileLocation ifl= IndexLocationFactory.getIFL(tu);