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

Bug 378317 - Index update mode for resolving unresolved includes and

reindexing files with I/O errors.
This commit is contained in:
Sergey Prigogin 2012-05-09 17:05:51 -07:00
parent fdbfec3f2b
commit ae606fe28b
28 changed files with 599 additions and 120 deletions

View file

@ -178,11 +178,22 @@ public class EmptyIndexFragment implements IIndexFragment {
public IIndexFragmentFileSet createFileSet() {
return null;
}
@Override
public IIndexFragmentFile[] getAllFiles() {
return IIndexFragmentFile.EMPTY_ARRAY;
}
@Override
public IIndexFragmentFile[] getDefectiveFiles() {
return IIndexFragmentFile.EMPTY_ARRAY;
}
@Override
public IIndexFragmentFile[] getFilesWithUnresolvedIncludes() {
return IIndexFragmentFile.EMPTY_ARRAY;
}
@Override
public Object getCachedResult(Object key) {
return null;

View file

@ -18,6 +18,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;
@ -62,6 +63,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexMacro;
@ -85,6 +87,7 @@ import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.pdom.CModelListener;
import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
@ -105,7 +108,7 @@ import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
public class IndexBugsTests extends BaseTestCase {
private static final int INDEX_WAIT_TIME = 8000;
private static final int INDEX_WAIT_TIME = 800000; //XXX
private ICProject fCProject;
protected IIndex fIndex;
@ -2470,4 +2473,58 @@ public class IndexBugsTests extends BaseTestCase {
fIndex.releaseReadLock();
}
}
// // test.cpp
// #include "a.h"
// using ns::INT;
// // a.h
// #include "b.h"
// // b.h
// namespace ns { typedef int INT; }
public void testUpdateUnresolvedIncludes_378317() throws Exception {
// Turn off indexing of unused headers.
IndexerPreferences.set(fCProject.getProject(), IndexerPreferences.KEY_INDEX_UNUSED_HEADERS_WITH_DEFAULT_LANG, "false");
// Turn off automatic index update.
IndexerPreferences.setUpdatePolicy(fCProject.getProject(), IndexerPreferences.UPDATE_POLICY_MANUAL);
try {
String[] contents= getContentsForTest(3);
final IIndexManager indexManager = CCorePlugin.getIndexManager();
TestSourceReader.createFile(fCProject.getProject(), "test.c", contents[0]);
IFile ah= TestSourceReader.createFile(fCProject.getProject(), "a.h", contents[1]);
// b.h is not created yet, so #include "b.h" in a.h is unresolved.
indexManager.reindex(fCProject);
waitForIndexer();
fIndex.acquireReadLock();
try {
IIndexFile[] files = fIndex.getFilesWithUnresolvedIncludes();
assertEquals(1, files.length);
assertEquals(IndexLocationFactory.getWorkspaceIFL(ah), files[0].getLocation());
} finally {
fIndex.releaseReadLock();
}
IFile bh= TestSourceReader.createFile(fCProject.getProject(), "b.h", contents[2]);
indexManager.update(new ICElement[] { fCProject }, IIndexManager.UPDATE_UNRESOLVED_INCLUDES);
waitForIndexer();
fIndex.acquireReadLock();
try {
IIndexFile[] files = fIndex.getFilesWithUnresolvedIncludes();
assertEquals(0, files.length);
IIndexFileLocation location = IndexLocationFactory.getWorkspaceIFL(bh);
files = fIndex.getFiles(IndexLocationFactory.getWorkspaceIFL(bh));
assertEquals(1, files.length);
} finally {
fIndex.releaseReadLock();
}
} finally {
// Restore default indexer preferences.
Properties defaults = IndexerPreferences.getDefaultIndexerProperties();
IndexerPreferences.set(fCProject.getProject(), IndexerPreferences.KEY_INDEX_UNUSED_HEADERS_WITH_DEFAULT_LANG,
defaults.getProperty(IndexerPreferences.KEY_INDEX_UNUSED_HEADERS_WITH_DEFAULT_LANG));
IndexerPreferences.setUpdatePolicy(fCProject.getProject(), IndexerPreferences.getDefaultUpdatePolicy());
}
}
}

View file

@ -95,6 +95,13 @@ public interface IASTPreprocessorIncludeStatement extends IASTPreprocessorStatem
*/
public long getIncludedFileContentsHash();
/**
* Returns time when the included file was read. Corresponds to the start of reading.
* @return time before reading started in milliseconds since epoch
* @since 5.4
*/
public long getIncludedFileReadTime();
/**
* Returns <code>true</code> if I/O errors were encountered while reading the included file.
* @since 5.4
@ -113,5 +120,5 @@ public interface IASTPreprocessorIncludeStatement extends IASTPreprocessorStatem
* if the include creates AST or is unresolved or skipped.
* @since 5.4
*/
public IIndexFile getImportedIndexFile();
public IIndexFile getImportedIndexFile();
}

View file

@ -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
@ -436,6 +436,20 @@ public interface IIndex {
*/
public IIndexFile[] getAllFiles() throws CoreException;
/**
* Returns an array of files that were indexed with I/O errors.
* @noreference This method is not intended to be referenced by clients.
* @since 5.4
*/
public IIndexFile[] getDefectiveFiles() throws CoreException;
/**
* Returns an array of files containg unresolved includes.
* @noreference This method is not intended to be referenced by clients.
* @since 5.4
*/
public IIndexFile[] getFilesWithUnresolvedIncludes() throws CoreException;
/**
* Returns the global inline c++ namespaces.
* @throws CoreException

View file

@ -62,6 +62,14 @@ public interface IIndexFile extends IFileNomination {
*/
long getTimestamp() throws CoreException;
/**
* Time when the file was read during indexing. Corresponds to the start of reading.
* @return time of indexing in milliseconds since epoch
* @throws CoreException
* @since 5.4
*/
long getSourceReadTime() throws CoreException;
/**
* Hash of the file contents when the file was indexed.
* @return 64-bit hash of the file content.

View file

@ -113,32 +113,31 @@ public interface IIndexManager extends IPDOMManager {
public final static int ADD_EXTENSION_FRAGMENTS_SEARCH = 0x200;
/**
* Constant for indicating there is no time out period for joining the indexer job.
* Constant for indicating that there is no time out period for joining the indexer job.
* @see IIndexManager#joinIndexer(int, IProgressMonitor)
*/
public final static int FOREVER= -1;
/**
* Constant for indicating to update all translation units.
* Constant for requesting an update of all translation units.
*/
public final static int UPDATE_ALL= 0x1;
/**
* Constant for indicating to update translation units if their timestamp
* has changed.
* Constant for requesting an update of translation units if theit timestamps have changed.
*/
public final static int UPDATE_CHECK_TIMESTAMPS= 0x2;
/**
* Constant for indicating to update translation units if their configuration
* has changed. The flag currently has no effect.
* Constant for requesting an update of translation units if their configurations
* have changed. The flag currently has no effect.
*/
public final static int UPDATE_CHECK_CONFIGURATION= 0x4;
/**
* Constant for requesting to update the external files for a project, also. This flag works only
* if it is used to update one or more projects. It shall be used together with {@link #UPDATE_ALL}
* or {@link #UPDATE_CHECK_TIMESTAMPS}.
* Constant for requesting to update the external files for a project, also. This flag works
* only if it is used to update one or more projects. It shall be used together with
* {@link #UPDATE_ALL} or {@link #UPDATE_CHECK_TIMESTAMPS}.
* @since 5.1
*/
public final static int UPDATE_EXTERNAL_FILES_FOR_PROJECT= 0x8;
@ -168,6 +167,12 @@ public interface IIndexManager extends IPDOMManager {
*/
public final static int RESET_INDEX_INCLUSION= 0x40;
/**
* Constant for requesting an update of translation units that had unresolved includes.
* @since 5.4
*/
public final static int UPDATE_UNRESOLVED_INCLUDES= 0x80;
/**
* Returns the index for the given project.
* @param project the project to get the index for

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2009, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2009, 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
@ -40,13 +40,20 @@ public abstract class FileContent {
public abstract String getFileLocation();
/**
* Returns the modification time of the file containing the content or NULL_TIMESTAMP if
* 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 time when the file was read. Corresponds to the start of reading.
* @return time before reading started in milliseconds since epoch
* @since 5.4
*/
public abstract long getReadTime();
/**
* 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.

View file

@ -758,6 +758,32 @@ public class CIndex implements IIndex {
return result.values().toArray(new IIndexFile[result.size()]);
}
@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) {

View file

@ -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
@ -189,6 +189,16 @@ final public class EmptyCIndex implements IIndex {
return IIndexFile.EMPTY_FILE_ARRAY;
}
@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;

View file

@ -325,6 +325,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.

View file

@ -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,10 +24,15 @@ 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.
*/
@ -57,6 +62,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.
*/
@ -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;
}

View file

@ -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);
}

View file

@ -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,
@ -404,6 +405,19 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
fIncludedFileTimestamp= timestamp;
}
@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) {

View file

@ -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.

View file

@ -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 {

View file

@ -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$

View file

@ -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;
}
/**
@ -166,6 +171,11 @@ public class InternalFileContent extends FileContent {
return fTimestamp;
}
@Override
public long getReadTime() {
return fReadTime;
}
@Override
public long getFileSize() {
return fFileSize;

View file

@ -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);
}
}

View file

@ -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();
}

View file

@ -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;
@ -318,6 +318,20 @@ public class PDOMProxy implements IPDOM {
return IIndexFragmentFile.EMPTY_ARRAY;
}
@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 {

View file

@ -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();

View file

@ -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;

View file

@ -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());
@ -309,6 +311,18 @@ public class PDOMFile implements IIndexFragmentFile {
db.putLong(record + TIME_STAMP, timestamp);
}
@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();
@ -571,6 +585,7 @@ public class PDOMFile implements IIndexFragmentFile {
m.delete();
}
setFirstMacroReference(null);
setSourceReadTime(0);
setTimestamp(-1);
}
@ -644,6 +659,17 @@ public class PDOMFile implements IIndexFragmentFile {
return result.toArray(new IIndexInclude[result.size()]);
}
@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>();

View file

@ -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

View file

@ -460,8 +460,9 @@ CDTIndexer.fastindexer=C/C++ Indexer
IndexView.name=C/C++ Index
RebuildIndex.name=&Rebuild
SyncIndex.name=&Update with Modified Files
FreshenIndex.name=&Freshen All Files
SyncIndex.name=&Update with Modified Files
UpdateUnresolvedIncludes.name=R&e-resolve Unresolved Includes
SearchUnresolvedIncludes.name=Search for Unresolved &Includes
CreateParserLog.name=Create Parser &Log File

View file

@ -1372,15 +1372,20 @@
</or>
</visibility>
<action
class="org.eclipse.cdt.internal.ui.actions.FreshenIndexAction"
id="org.eclipse.cdt.ui.updateIndexAction"
label="%FreshenIndex.name"
menubarPath="org.eclipse.cdt.ui.indexmenu/update"/>
class="org.eclipse.cdt.internal.ui.actions.UpdateUnresolvedIncludesAction"
id="org.eclipse.cdt.ui.updateUnresolvedIncludesAction"
label="%UpdateUnresolvedIncludes.name"
menubarPath="org.eclipse.cdt.ui.indexmenu/update"/>
<action
class="org.eclipse.cdt.internal.ui.actions.UpdateIndexWithModifiedFilesAction"
id="org.eclipse.cdt.ui.syncIndexWithDiskAction"
label="%SyncIndex.name"
menubarPath="org.eclipse.cdt.ui.indexmenu/update"/>
class="org.eclipse.cdt.internal.ui.actions.UpdateIndexWithModifiedFilesAction"
id="org.eclipse.cdt.ui.syncIndexWithDiskAction"
label="%SyncIndex.name"
menubarPath="org.eclipse.cdt.ui.indexmenu/update"/>
<action
class="org.eclipse.cdt.internal.ui.actions.FreshenIndexAction"
id="org.eclipse.cdt.ui.updateIndexAction"
label="%FreshenIndex.name"
menubarPath="org.eclipse.cdt.ui.indexmenu/update"/>
<menu
id="org.eclipse.cdt.ui.indexmenu"
label="%Index.menu"
@ -1445,15 +1450,20 @@
value="org.eclipse.cdt.core.cnature"/>
</visibility>
<action
class="org.eclipse.cdt.internal.ui.actions.FreshenIndexAction"
id="org.eclipse.cdt.ui.updateIndexAction"
label="%FreshenIndex.name"
class="org.eclipse.cdt.internal.ui.actions.UpdateUnresolvedIncludesAction"
id="org.eclipse.cdt.ui.updateUnresolvedIncludesAction"
label="%UpdateUnresolvedIncludes.name"
menubarPath="org.eclipse.cdt.ui.indexmenu/update"/>
<action
class="org.eclipse.cdt.internal.ui.actions.UpdateIndexWithModifiedFilesAction"
id="org.eclipse.cdt.ui.syncIndexWithDiskAction"
label="%SyncIndex.name"
menubarPath="org.eclipse.cdt.ui.indexmenu/update"/>
<action
class="org.eclipse.cdt.internal.ui.actions.FreshenIndexAction"
id="org.eclipse.cdt.ui.updateIndexAction"
label="%FreshenIndex.name"
menubarPath="org.eclipse.cdt.ui.indexmenu/update"/>
<action
class="org.eclipse.cdt.internal.ui.actions.RebuildIndexAction"
id="org.eclipse.cdt.ui.rebuildIndexAction"

View file

@ -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
@ -7,6 +7,7 @@
*
* Contributors:
* Markus Schorn - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.actions;
@ -18,6 +19,7 @@ public class UpdateIndexWithModifiedFilesAction extends AbstractUpdateIndexActio
return IIndexManager.UPDATE_CHECK_TIMESTAMPS |
IIndexManager.UPDATE_CHECK_CONFIGURATION |
IIndexManager.UPDATE_EXTERNAL_FILES_FOR_PROJECT |
IIndexManager.UPDATE_CHECK_CONTENTS_HASH;
IIndexManager.UPDATE_CHECK_CONTENTS_HASH |
IIndexManager.UPDATE_UNRESOLVED_INCLUDES;
}
}

View file

@ -0,0 +1,20 @@
/*******************************************************************************
* Copyright (c) 2012 Google, Inc and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.actions;
import org.eclipse.cdt.core.index.IIndexManager;
public class UpdateUnresolvedIncludesAction extends AbstractUpdateIndexAction {
@Override
protected int getUpdateOptions() {
return IIndexManager.UPDATE_UNRESOLVED_INCLUDES;
}
}