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:
parent
fdbfec3f2b
commit
ae606fe28b
28 changed files with 599 additions and 120 deletions
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,19 +1068,9 @@ 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) {
|
||||
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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$
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,11 +529,11 @@ 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,
|
||||
|
@ -1296,6 +1344,8 @@ public class PDOM extends PlatformObject implements IPDOM {
|
|||
|
||||
private void clearCaches() {
|
||||
fileIndex= null;
|
||||
indexOfDefectiveFiles= null;
|
||||
indexOfFiledWithUnresolvedIncludes= null;
|
||||
fLinkageIDCache.clear();
|
||||
clearResultCache();
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -87,6 +87,10 @@ 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.
|
||||
|
@ -94,10 +98,25 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
|
|||
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;
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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,6 +97,7 @@ public class PDOMUpdateTask implements IPDOMIndexerTask {
|
|||
private void createDelegate(ICProject project, IProgressMonitor monitor)
|
||||
throws CoreException, InterruptedException {
|
||||
HashSet<ITranslationUnit> set= new HashSet<ITranslationUnit>();
|
||||
if ((fUpdateOptions & (IIndexManager.UPDATE_ALL | IIndexManager.UPDATE_CHECK_TIMESTAMPS)) != 0) {
|
||||
TranslationUnitCollector collector= new TranslationUnitCollector(set, set, monitor);
|
||||
boolean haveProject= false;
|
||||
if (fFilesAndFolders == null) {
|
||||
|
@ -114,18 +120,42 @@ public class PDOMUpdateTask implements IPDOMIndexerTask {
|
|||
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);
|
||||
ITranslationUnit tu = getTranslationUnit(floc, project);
|
||||
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);
|
||||
set.add(tu);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
index.releaseReadLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((fUpdateOptions & IIndexManager.UPDATE_UNRESOLVED_INCLUDES) != 0) {
|
||||
IIndex index= CCorePlugin.getIndexManager().getIndex(project);
|
||||
index.acquireReadLock();
|
||||
try {
|
||||
// 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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1372,15 +1372,20 @@
|
|||
</or>
|
||||
</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"/>
|
||||
<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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue