mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Moved an improved cache for include paths into the ASTFilePathResolver, where it can be reused with EFS, bug 225302.
This commit is contained in:
parent
3d6501658c
commit
ac29604de3
8 changed files with 167 additions and 202 deletions
|
@ -35,19 +35,17 @@ import org.eclipse.cdt.core.parser.ICodeReaderCache;
|
||||||
import org.eclipse.cdt.core.parser.ParserUtil;
|
import org.eclipse.cdt.core.parser.ParserUtil;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.IIndexBasedCodeReaderFactory;
|
import org.eclipse.cdt.internal.core.parser.scanner.IIndexBasedCodeReaderFactory;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.IncludeFileContent;
|
import org.eclipse.cdt.internal.core.parser.scanner.IncludeFileContent;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.IncludeFileResolutionCache;
|
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.IncludeFileContent.InclusionKind;
|
import org.eclipse.cdt.internal.core.parser.scanner.IncludeFileContent.InclusionKind;
|
||||||
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
|
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
|
||||||
import org.eclipse.cdt.internal.core.pdom.AbstractIndexerTask;
|
import org.eclipse.cdt.internal.core.pdom.AbstractIndexerTask;
|
||||||
import org.eclipse.cdt.internal.core.pdom.AbstractIndexerTask.FileContent;
|
import org.eclipse.cdt.internal.core.pdom.AbstractIndexerTask.FileContent;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IAdaptable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Code reader factory, that fakes code readers for header files already stored in the
|
* Code reader factory, that fakes code readers for header files already stored in the
|
||||||
* index.
|
* index.
|
||||||
*/
|
*/
|
||||||
public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderFactory, IAdaptable {
|
public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderFactory {
|
||||||
private static final class NeedToParseException extends Exception {}
|
private static final class NeedToParseException extends Exception {}
|
||||||
|
|
||||||
private final IIndex fIndex;
|
private final IIndex fIndex;
|
||||||
|
@ -57,7 +55,6 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF
|
||||||
private final ICodeReaderFactory fFallBackFactory;
|
private final ICodeReaderFactory fFallBackFactory;
|
||||||
private final ASTFilePathResolver fPathResolver;
|
private final ASTFilePathResolver fPathResolver;
|
||||||
private final AbstractIndexerTask fRelatedIndexerTask;
|
private final AbstractIndexerTask fRelatedIndexerTask;
|
||||||
private final IncludeFileResolutionCache fIncludeFileResolutionCache;
|
|
||||||
|
|
||||||
public IndexBasedCodeReaderFactory(IIndex index, ASTFilePathResolver pathResolver, int linkage,
|
public IndexBasedCodeReaderFactory(IIndex index, ASTFilePathResolver pathResolver, int linkage,
|
||||||
ICodeReaderFactory fallbackFactory) {
|
ICodeReaderFactory fallbackFactory) {
|
||||||
|
@ -71,13 +68,12 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF
|
||||||
fPathResolver= pathResolver;
|
fPathResolver= pathResolver;
|
||||||
fRelatedIndexerTask= relatedIndexerTask;
|
fRelatedIndexerTask= relatedIndexerTask;
|
||||||
fLinkage= linkage;
|
fLinkage= linkage;
|
||||||
fIncludeFileResolutionCache= new IncludeFileResolutionCache(1024);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getUniqueIdentifier() {
|
public int getUniqueIdentifier() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodeReader createCodeReaderForTranslationUnit(String path) {
|
public CodeReader createCodeReaderForTranslationUnit(String path) {
|
||||||
if (fFallBackFactory != null) {
|
if (fFallBackFactory != null) {
|
||||||
return fFallBackFactory.createCodeReaderForTranslationUnit(path);
|
return fFallBackFactory.createCodeReaderForTranslationUnit(path);
|
||||||
|
@ -92,6 +88,10 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF
|
||||||
return ParserUtil.createReader(path, null);
|
return ParserUtil.createReader(path, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getInclusionExists(String path) {
|
||||||
|
return fPathResolver.doesIncludeFileExist(path);
|
||||||
|
}
|
||||||
|
|
||||||
public IncludeFileContent getContentForInclusion(String path) {
|
public IncludeFileContent getContentForInclusion(String path) {
|
||||||
IIndexFileLocation ifl= fPathResolver.resolveIncludeFile(path);
|
IIndexFileLocation ifl= fPathResolver.resolveIncludeFile(path);
|
||||||
if (ifl == null) {
|
if (ifl == null) {
|
||||||
|
@ -183,12 +183,4 @@ public final class IndexBasedCodeReaderFactory implements IIndexBasedCodeReaderF
|
||||||
public void setLinkage(int linkageID) {
|
public void setLinkage(int linkageID) {
|
||||||
fLinkage= linkageID;
|
fLinkage= linkageID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public Object getAdapter(Class adapter) {
|
|
||||||
if (adapter.isInstance(fIncludeFileResolutionCache)) {
|
|
||||||
return fIncludeFileResolutionCache;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ import org.eclipse.core.runtime.Path;
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
*/
|
*/
|
||||||
public class StandaloneIndexerInputAdapter extends IndexerInputAdapter {
|
public class StandaloneIndexerInputAdapter extends IndexerInputAdapter {
|
||||||
private HashMap fIflCache= new HashMap();
|
private HashMap<String, IIndexFileLocation> fIflCache= new HashMap<String, IIndexFileLocation>();
|
||||||
|
|
||||||
private final StandaloneIndexer fIndexer;
|
private final StandaloneIndexer fIndexer;
|
||||||
|
|
||||||
|
@ -38,28 +38,34 @@ public class StandaloneIndexerInputAdapter extends IndexerInputAdapter {
|
||||||
fIndexer= indexer;
|
fIndexer= indexer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IScannerInfo getBuildConfiguration(int linkageID, Object tu) {
|
public IScannerInfo getBuildConfiguration(int linkageID, Object tu) {
|
||||||
return fIndexer.getScannerInfo();
|
return fIndexer.getScannerInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public long getLastModified(IIndexFileLocation location) {
|
public long getLastModified(IIndexFileLocation location) {
|
||||||
return new File(location.getFullPath()).lastModified();
|
return new File(location.getFullPath()).lastModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isSourceUnit(Object tu) {
|
public boolean isSourceUnit(Object tu) {
|
||||||
return isValidSourceUnitName((String) tu);
|
return isValidSourceUnitName((String) tu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IIndexFileLocation resolveFile(Object tu) {
|
public IIndexFileLocation resolveFile(Object tu) {
|
||||||
return resolveASTPath((String) tu);
|
return resolveASTPath((String) tu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getASTPath(IIndexFileLocation ifl) {
|
public String getASTPath(IIndexFileLocation ifl) {
|
||||||
return ifl.getFullPath();
|
return ifl.getFullPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IIndexFileLocation resolveASTPath(String astPath) {
|
public IIndexFileLocation resolveASTPath(String astPath) {
|
||||||
IIndexFileLocation result= (IIndexFileLocation) fIflCache.get(astPath);
|
IIndexFileLocation result= fIflCache.get(astPath);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
try {
|
try {
|
||||||
astPath = new File(astPath).getCanonicalPath();
|
astPath = new File(astPath).getCanonicalPath();
|
||||||
|
@ -73,13 +79,17 @@ public class StandaloneIndexerInputAdapter extends IndexerInputAdapter {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doesIncludeFileExist(String includePath) {
|
||||||
|
return new File(includePath).exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IIndexFileLocation resolveIncludeFile(String includePath) {
|
public IIndexFileLocation resolveIncludeFile(String includePath) {
|
||||||
IIndexFileLocation result= (IIndexFileLocation) fIflCache.get(includePath);
|
IIndexFileLocation result= fIflCache.get(includePath);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
File file= new File(includePath);
|
File file= new File(includePath);
|
||||||
if (!file.exists()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
includePath = file.getCanonicalPath();
|
includePath = file.getCanonicalPath();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -92,14 +102,17 @@ public class StandaloneIndexerInputAdapter extends IndexerInputAdapter {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isFileBuildConfigured(Object tu) {
|
public boolean isFileBuildConfigured(Object tu) {
|
||||||
return isValidSourceUnitName((String) tu);
|
return isValidSourceUnitName((String) tu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean canBePartOfSDK(IIndexFileLocation ifl) {
|
public boolean canBePartOfSDK(IIndexFileLocation ifl) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public CodeReader getCodeReader(Object tu) {
|
public CodeReader getCodeReader(Object tu) {
|
||||||
try {
|
try {
|
||||||
return new CodeReader((String) tu);
|
return new CodeReader((String) tu);
|
||||||
|
@ -108,10 +121,12 @@ public class StandaloneIndexerInputAdapter extends IndexerInputAdapter {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Object getInputFile(IIndexFileLocation location) {
|
public Object getInputFile(IIndexFileLocation location) {
|
||||||
return location.getFullPath();
|
return location.getFullPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public AbstractLanguage[] getLanguages(Object tu) {
|
public AbstractLanguage[] getLanguages(Object tu) {
|
||||||
ILanguage language = fIndexer.getLanguageMapper().getLanguage((String) tu);
|
ILanguage language = fIndexer.getLanguageMapper().getLanguage((String) tu);
|
||||||
if (language instanceof AbstractLanguage) {
|
if (language instanceof AbstractLanguage) {
|
||||||
|
|
|
@ -45,8 +45,6 @@ import org.eclipse.cdt.core.parser.util.CharArrayIntMap;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayMap;
|
import org.eclipse.cdt.core.parser.util.CharArrayMap;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalException;
|
import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalException;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.IncludeFileResolutionCache.ISPKey;
|
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.IncludeFileResolutionCache.LookupKey;
|
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
|
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.InvalidMacroDefinitionException;
|
import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.InvalidMacroDefinitionException;
|
||||||
import org.eclipse.core.runtime.IAdaptable;
|
import org.eclipse.core.runtime.IAdaptable;
|
||||||
|
@ -93,15 +91,16 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
|
|
||||||
final private IIncludeFileTester<IncludeFileContent> createCodeReaderTester= new IIncludeFileTester<IncludeFileContent>() {
|
final private IIncludeFileTester<IncludeFileContent> createCodeReaderTester= new IIncludeFileTester<IncludeFileContent>() {
|
||||||
public IncludeFileContent checkFile(String path, String fileName) {
|
public IncludeFileContent checkFile(String path, String fileName) {
|
||||||
return createReader(path, fileName);
|
String finalPath = ScannerUtility.createReconciledPath(path, fileName);
|
||||||
|
return fCodeReaderFactory.getContentForInclusion(finalPath);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
final private IIncludeFileTester<String> createPathTester= new IIncludeFileTester<String>() {
|
final private IIncludeFileTester<String> createPathTester= new IIncludeFileTester<String>() {
|
||||||
public String checkFile(String path, String fileName) {
|
public String checkFile(String path, String fileName) {
|
||||||
path= ScannerUtility.createReconciledPath(path, fileName);
|
String finalPath= ScannerUtility.createReconciledPath(path, fileName);
|
||||||
if (new File(path).exists()) {
|
if (fCodeReaderFactory.getInclusionExists(finalPath)) {
|
||||||
return path;
|
return finalPath;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -121,9 +120,6 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
final private String[] fIncludePaths;
|
final private String[] fIncludePaths;
|
||||||
final private String[] fQuoteIncludePaths;
|
final private String[] fQuoteIncludePaths;
|
||||||
private String[][] fPreIncludedFiles= null;
|
private String[][] fPreIncludedFiles= null;
|
||||||
private final IncludeFileResolutionCache fIncludeResolutionCache;
|
|
||||||
private final ISPKey fIncludePathKey;
|
|
||||||
private final ISPKey fQuoteIncludePathKey;
|
|
||||||
|
|
||||||
private int fContentAssistLimit= -1;
|
private int fContentAssistLimit= -1;
|
||||||
private boolean fHandledCompletion= false;
|
private boolean fHandledCompletion= false;
|
||||||
|
@ -162,10 +158,6 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
fMacroExpander= new MacroExpander(this, fMacroDictionary, fLocationMap, fLexOptions);
|
fMacroExpander= new MacroExpander(this, fMacroDictionary, fLocationMap, fLexOptions);
|
||||||
fCodeReaderFactory= wrapReaderFactory(readerFactory);
|
fCodeReaderFactory= wrapReaderFactory(readerFactory);
|
||||||
|
|
||||||
fIncludeResolutionCache= getIncludeResolutionCache(readerFactory);
|
|
||||||
fIncludePathKey= fIncludeResolutionCache.getKey(fIncludePaths);
|
|
||||||
fQuoteIncludePathKey= fIncludeResolutionCache.getKey(fQuoteIncludePaths);
|
|
||||||
|
|
||||||
setupMacroDictionary(configuration, info, language);
|
setupMacroDictionary(configuration, info, language);
|
||||||
|
|
||||||
final String filePath= new String(reader.filename);
|
final String filePath= new String(reader.filename);
|
||||||
|
@ -179,16 +171,6 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IncludeFileResolutionCache getIncludeResolutionCache(ICodeReaderFactory readerFactory) {
|
|
||||||
if (readerFactory instanceof IAdaptable) {
|
|
||||||
IncludeFileResolutionCache cache= (IncludeFileResolutionCache) ((IAdaptable) readerFactory).getAdapter(IncludeFileResolutionCache.class);
|
|
||||||
if (cache != null) {
|
|
||||||
return cache;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new IncludeFileResolutionCache(1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IIndexBasedCodeReaderFactory wrapReaderFactory(final ICodeReaderFactory readerFactory) {
|
private IIndexBasedCodeReaderFactory wrapReaderFactory(final ICodeReaderFactory readerFactory) {
|
||||||
if (readerFactory instanceof IIndexBasedCodeReaderFactory) {
|
if (readerFactory instanceof IIndexBasedCodeReaderFactory) {
|
||||||
return (IIndexBasedCodeReaderFactory) readerFactory;
|
return (IIndexBasedCodeReaderFactory) readerFactory;
|
||||||
|
@ -216,6 +198,9 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
public int getUniqueIdentifier() {
|
public int getUniqueIdentifier() {
|
||||||
return readerFactory.getUniqueIdentifier();
|
return readerFactory.getUniqueIdentifier();
|
||||||
}
|
}
|
||||||
|
public boolean getInclusionExists(String path) {
|
||||||
|
return readerFactory.createCodeReaderForInclusion(path) != null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -759,46 +744,18 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
|
|
||||||
// if we're not include_next, then we are looking for the first occurrence of
|
// if we're not include_next, then we are looking for the first occurrence of
|
||||||
// the file, otherwise, we ignore all the paths before the current directory
|
// the file, otherwise, we ignore all the paths before the current directory
|
||||||
String[] isp;
|
final String[] isp= quoteInclude ? fQuoteIncludePaths : fIncludePaths;
|
||||||
ISPKey ispKey;
|
|
||||||
if (quoteInclude) {
|
|
||||||
isp= fQuoteIncludePaths;
|
|
||||||
ispKey= fQuoteIncludePathKey;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
isp= fIncludePaths;
|
|
||||||
ispKey= fIncludePathKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isp != null ) {
|
if (isp != null ) {
|
||||||
if (includeNext && currentDirectory != null) {
|
int i=0;
|
||||||
final int startpos = findIncludePos(isp, currentDirectory) + 1;
|
if (includeNext && currentDirectory != null) {
|
||||||
for (int i= startpos; i < isp.length; ++i) {
|
i= findIncludePos(isp, currentDirectory) + 1;
|
||||||
reader= tester.checkFile(isp[i], filename);
|
}
|
||||||
if (reader != null) {
|
for (; i < isp.length; ++i) {
|
||||||
return reader;
|
reader= tester.checkFile(isp[i], filename);
|
||||||
}
|
if (reader != null) {
|
||||||
}
|
return reader;
|
||||||
return null;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
final LookupKey lookupKey= fIncludeResolutionCache.getKey(ispKey, filename.toCharArray());
|
|
||||||
Integer offset= fIncludeResolutionCache.getCachedPathOffset(lookupKey);
|
|
||||||
if (offset != null) {
|
|
||||||
if (offset < 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return tester.checkFile(isp[offset], filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i= 0; i < isp.length; ++i) {
|
|
||||||
reader = tester.checkFile(isp[i], filename);
|
|
||||||
if (reader != null) {
|
|
||||||
fIncludeResolutionCache.putCachedPathOffset(lookupKey, i);
|
|
||||||
return reader;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fIncludeResolutionCache.putCachedPathOffset(lookupKey, -1);
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -848,13 +805,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
public void handleProblem(int id, char[] arg, int offset, int endOffset) {
|
public void handleProblem(int id, char[] arg, int offset, int endOffset) {
|
||||||
fLocationMap.encounterProblem(id, arg, offset, endOffset);
|
fLocationMap.encounterProblem(id, arg, offset, endOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IncludeFileContent createReader(String path, String fileName){
|
|
||||||
String finalPath = ScannerUtility.createReconciledPath(path, fileName);
|
|
||||||
return fCodeReaderFactory.getContentForInclusion(finalPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assumes that the pound token has not yet been consumed
|
* Assumes that the pound token has not yet been consumed
|
||||||
* @param ppdCtx
|
* @param ppdCtx
|
||||||
|
|
|
@ -30,4 +30,10 @@ public interface IIndexBasedCodeReaderFactory extends ICodeReaderFactory {
|
||||||
* @see IncludeFileContent
|
* @see IncludeFileContent
|
||||||
*/
|
*/
|
||||||
public IncludeFileContent getContentForInclusion(String fileLocation);
|
public IncludeFileContent getContentForInclusion(String fileLocation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the specified inclusion exists.
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
boolean getInclusionExists(String finalPath);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,107 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
* Copyright (c) 2008 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
|
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
*
|
|
||||||
* Contributors:
|
|
||||||
* Markus Schorn - initial API and implementation
|
|
||||||
*******************************************************************************/
|
|
||||||
package org.eclipse.cdt.internal.core.parser.scanner;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.core.parser.util.WeakHashSet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A limited LRU cache for looking up files in an include search path.
|
|
||||||
* @since 5.0
|
|
||||||
*/
|
|
||||||
public final class IncludeFileResolutionCache {
|
|
||||||
public static class ISPKey {
|
|
||||||
private String[] fISP;
|
|
||||||
private int fHashCode;
|
|
||||||
|
|
||||||
private ISPKey(String[] isp) {
|
|
||||||
fISP= isp;
|
|
||||||
fHashCode= Arrays.hashCode(isp);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return obj != null && Arrays.equals(fISP, ((ISPKey) obj).fISP);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return fHashCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class LookupKey {
|
|
||||||
private ISPKey fCanonicISP;
|
|
||||||
private char[] fName;
|
|
||||||
private int fHashCode;
|
|
||||||
|
|
||||||
private LookupKey(ISPKey ispKey, char[] include) {
|
|
||||||
fCanonicISP= ispKey;
|
|
||||||
fName= include;
|
|
||||||
fHashCode= Arrays.hashCode(include) * 31 + ispKey.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return fHashCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
LookupKey other= (LookupKey) obj;
|
|
||||||
if (fCanonicISP != other.fCanonicISP)
|
|
||||||
return false;
|
|
||||||
if (!Arrays.equals(fName, other.fName))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private WeakHashSet<ISPKey> fCanonicISPs;
|
|
||||||
private LinkedHashMap<LookupKey, Integer> fCache;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a cache for include file resolution using up to the given amount of memory
|
|
||||||
* @param maxSizeKBytes the maximum size of the cache in kilobytes
|
|
||||||
*/
|
|
||||||
public IncludeFileResolutionCache(final int maxSizeKBytes) {
|
|
||||||
final int size= maxSizeKBytes*1024/72; // HashEntry 32 bytes, Key 16 bytes, Name 16 bytes, Integer 8 bytes
|
|
||||||
fCache= new LinkedHashMap<LookupKey, Integer>(size, 0.75f, true) {
|
|
||||||
@Override
|
|
||||||
protected boolean removeEldestEntry(Map.Entry<LookupKey, Integer> eldest) {
|
|
||||||
return size() > size;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
fCanonicISPs= new WeakHashSet<ISPKey>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ISPKey getKey(String[] isp) {
|
|
||||||
return fCanonicISPs.add(new ISPKey(isp));
|
|
||||||
}
|
|
||||||
|
|
||||||
public LookupKey getKey(ISPKey ispKey, char[] filename) {
|
|
||||||
return new LookupKey(ispKey, filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getCachedPathOffset(LookupKey key) {
|
|
||||||
return fCache.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putCachedPathOffset(LookupKey key, int offset) {
|
|
||||||
fCache.put(key, offset);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -25,12 +25,17 @@ public abstract class ASTFilePathResolver {
|
||||||
public abstract IIndexFileLocation resolveASTPath(String astFilePath);
|
public abstract IIndexFileLocation resolveASTPath(String astFilePath);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a path for an inclusion as computed by the preprocessor. Check for existance
|
* Resolve a path for an inclusion as computed by the preprocessor. Check for existence
|
||||||
* and return <code>null</code> if the file does not exist.
|
* and return <code>null</code> if the file does not exist.
|
||||||
* @return an index file location or <code>null</code> if the file does not exist.
|
* @return an index file location or <code>null</code> if the file does not exist.
|
||||||
*/
|
*/
|
||||||
public abstract IIndexFileLocation resolveIncludeFile(String includePath);
|
public abstract IIndexFileLocation resolveIncludeFile(String includePath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for existence of an inclusion as computed by the preprocessor.
|
||||||
|
*/
|
||||||
|
public abstract boolean doesIncludeFileExist(String includePath);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert an index file location to the path as it will be stored in the AST.
|
* Convert an index file location to the path as it will be stored in the AST.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 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
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Markus Schorn - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.core.pdom.indexer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.lang.ref.Reference;
|
||||||
|
import java.lang.ref.SoftReference;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A cache for checking whether a file exists. The cache shall be used for a limited amount of time, only (e.g. one
|
||||||
|
* indexer task). It uses as much memory as it needs. To protect against OutOfMemory situations, a soft reference is
|
||||||
|
* used.
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public final class FileExistsCache {
|
||||||
|
private static final String[] EMPTY_STRING_ARRAY= {};
|
||||||
|
private static final boolean CASE_INSENSITIVE = new File("a").equals(new File("A")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
private static boolean BYPASS_CACHE= Boolean.getBoolean("CDT_INDEXER_BYPASS_FILE_EXISTS_CACHE"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
private Reference<Map<String,String[]>> fCache= null;
|
||||||
|
|
||||||
|
public FileExistsCache() {
|
||||||
|
fCache= new SoftReference<Map<String,String[]>>(new HashMap<String, String[]>()); // before running out of memory the entire map will be thrown away.
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean exists(String path) {
|
||||||
|
File file= new File(path);
|
||||||
|
if (BYPASS_CACHE) {
|
||||||
|
return file.exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
String parent= file.getParent();
|
||||||
|
String name= file.getName();
|
||||||
|
if (CASE_INSENSITIVE)
|
||||||
|
name= name.toUpperCase();
|
||||||
|
|
||||||
|
String[] avail= getExistsCache().get(parent);
|
||||||
|
if (avail == null) {
|
||||||
|
avail= new File(parent).list();
|
||||||
|
if (avail == null || avail.length == 0) {
|
||||||
|
avail= EMPTY_STRING_ARRAY;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (CASE_INSENSITIVE) {
|
||||||
|
for (int i = 0; i < avail.length; i++) {
|
||||||
|
avail[i]= avail[i].toUpperCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Arrays.sort(avail);
|
||||||
|
}
|
||||||
|
getExistsCache().put(parent, avail);
|
||||||
|
}
|
||||||
|
return Arrays.binarySearch(avail, name) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String[]> getExistsCache() {
|
||||||
|
Map<String, String[]> cache= fCache.get();
|
||||||
|
if (cache == null) {
|
||||||
|
cache= new HashMap<String, String[]>();
|
||||||
|
fCache= new SoftReference<Map<String, String[]>>(cache); // before running out of memory the entire map will be thrown away.
|
||||||
|
}
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,7 +42,8 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
|
||||||
private final static boolean CASE_SENSITIVE_FILES= !new File("a").equals(new File("A")); //$NON-NLS-1$//$NON-NLS-2$
|
private final static boolean CASE_SENSITIVE_FILES= !new File("a").equals(new File("A")); //$NON-NLS-1$//$NON-NLS-2$
|
||||||
|
|
||||||
private final ICProject fCProject;
|
private final ICProject fCProject;
|
||||||
private HashMap<String, IIndexFileLocation> fIflCache;
|
private final HashMap<String, IIndexFileLocation> fIflCache;
|
||||||
|
private final FileExistsCache fExistsCache;
|
||||||
|
|
||||||
public ProjectIndexerInputAdapter(ICProject cproject) {
|
public ProjectIndexerInputAdapter(ICProject cproject) {
|
||||||
this(cproject, true);
|
this(cproject, true);
|
||||||
|
@ -50,9 +51,17 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
|
||||||
|
|
||||||
public ProjectIndexerInputAdapter(ICProject cproject, boolean useCache) {
|
public ProjectIndexerInputAdapter(ICProject cproject, boolean useCache) {
|
||||||
fCProject= cproject;
|
fCProject= cproject;
|
||||||
fIflCache= useCache ? new HashMap<String, IIndexFileLocation>() : null;
|
if (useCache) {
|
||||||
|
fIflCache= new HashMap<String, IIndexFileLocation>();
|
||||||
|
fExistsCache= new FileExistsCache();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fIflCache= null;
|
||||||
|
fExistsCache= null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IIndexFileLocation resolveASTPath(String astPath) {
|
public IIndexFileLocation resolveASTPath(String astPath) {
|
||||||
if (fIflCache == null) {
|
if (fIflCache == null) {
|
||||||
return doResolveASTPath(astPath);
|
return doResolveASTPath(astPath);
|
||||||
|
@ -69,19 +78,20 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
|
||||||
return IndexLocationFactory.getIFLExpensive(fCProject, astPath);
|
return IndexLocationFactory.getIFLExpensive(fCProject, astPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IIndexFileLocation resolveIncludeFile(String includePath) {
|
public IIndexFileLocation resolveIncludeFile(String includePath) {
|
||||||
if (fIflCache == null) {
|
if (fIflCache == null) {
|
||||||
return doResolveASTPath(includePath);
|
return doResolveASTPath(includePath);
|
||||||
}
|
}
|
||||||
|
if (!fExistsCache.exists(includePath)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
IIndexFileLocation result= fIflCache.get(includePath);
|
IIndexFileLocation result= fIflCache.get(includePath);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
File location= new File(includePath);
|
|
||||||
if (!location.exists()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
result = doResolveASTPath(includePath);
|
result = doResolveASTPath(includePath);
|
||||||
if (result.getFullPath() == null && !CASE_SENSITIVE_FILES) {
|
if (result.getFullPath() == null && !CASE_SENSITIVE_FILES) {
|
||||||
try {
|
try {
|
||||||
|
File location= new File(includePath);
|
||||||
String canonicalPath= location.getCanonicalPath();
|
String canonicalPath= location.getCanonicalPath();
|
||||||
if (!includePath.equals(canonicalPath)) {
|
if (!includePath.equals(canonicalPath)) {
|
||||||
result= IndexLocationFactory.getExternalIFL(canonicalPath);
|
result= IndexLocationFactory.getExternalIFL(canonicalPath);
|
||||||
|
@ -96,7 +106,16 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doesIncludeFileExist(String includePath) {
|
||||||
|
if (fExistsCache != null) {
|
||||||
|
return fExistsCache.exists(includePath);
|
||||||
|
}
|
||||||
|
return new File(includePath).exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getASTPath(IIndexFileLocation ifl) {
|
public String getASTPath(IIndexFileLocation ifl) {
|
||||||
IPath path= IndexLocationFactory.getAbsolutePath(ifl);
|
IPath path= IndexLocationFactory.getAbsolutePath(ifl);
|
||||||
if (path != null) {
|
if (path != null) {
|
||||||
|
@ -105,6 +124,7 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
|
||||||
return ifl.getURI().getPath();
|
return ifl.getURI().getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IScannerInfo getBuildConfiguration(int linkageID, Object tu) {
|
public IScannerInfo getBuildConfiguration(int linkageID, Object tu) {
|
||||||
IScannerInfo info= ((ITranslationUnit) tu).getScannerInfo(true);
|
IScannerInfo info= ((ITranslationUnit) tu).getScannerInfo(true);
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
|
@ -113,6 +133,7 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public long getLastModified(IIndexFileLocation ifl) {
|
public long getLastModified(IIndexFileLocation ifl) {
|
||||||
String fullPath= ifl.getFullPath();
|
String fullPath= ifl.getFullPath();
|
||||||
if (fullPath != null) {
|
if (fullPath != null) {
|
||||||
|
@ -130,6 +151,7 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
public AbstractLanguage[] getLanguages(Object tuo) {
|
public AbstractLanguage[] getLanguages(Object tuo) {
|
||||||
ITranslationUnit tu= (ITranslationUnit) tuo;
|
ITranslationUnit tu= (ITranslationUnit) tuo;
|
||||||
try {
|
try {
|
||||||
|
@ -144,25 +166,30 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
|
||||||
return new AbstractLanguage[0];
|
return new AbstractLanguage[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isFileBuildConfigured(Object tuo) {
|
public boolean isFileBuildConfigured(Object tuo) {
|
||||||
ITranslationUnit tu= (ITranslationUnit) tuo;
|
ITranslationUnit tu= (ITranslationUnit) tuo;
|
||||||
return !CoreModel.isScannerInformationEmpty(tu.getResource());
|
return !CoreModel.isScannerInformationEmpty(tu.getResource());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isSourceUnit(Object tuo) {
|
public boolean isSourceUnit(Object tuo) {
|
||||||
ITranslationUnit tu= (ITranslationUnit) tuo;
|
ITranslationUnit tu= (ITranslationUnit) tuo;
|
||||||
return tu.isSourceUnit();
|
return tu.isSourceUnit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IIndexFileLocation resolveFile(Object tuo) {
|
public IIndexFileLocation resolveFile(Object tuo) {
|
||||||
ITranslationUnit tu= (ITranslationUnit) tuo;
|
ITranslationUnit tu= (ITranslationUnit) tuo;
|
||||||
return IndexLocationFactory.getIFL(tu);
|
return IndexLocationFactory.getIFL(tu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean canBePartOfSDK(IIndexFileLocation ifl) {
|
public boolean canBePartOfSDK(IIndexFileLocation ifl) {
|
||||||
return ifl.getFullPath() == null;
|
return ifl.getFullPath() == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Object getInputFile(IIndexFileLocation location) {
|
public Object getInputFile(IIndexFileLocation location) {
|
||||||
try {
|
try {
|
||||||
return CoreModelUtil.findTranslationUnitForLocation(location, fCProject);
|
return CoreModelUtil.findTranslationUnitForLocation(location, fCProject);
|
||||||
|
@ -172,6 +199,7 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public CodeReader getCodeReader(Object tuo) {
|
public CodeReader getCodeReader(Object tuo) {
|
||||||
ITranslationUnit tu= (ITranslationUnit) tuo;
|
ITranslationUnit tu= (ITranslationUnit) tuo;
|
||||||
return tu.getCodeReader();
|
return tu.getCodeReader();
|
||||||
|
|
Loading…
Add table
Reference in a new issue