diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/FileCodeReaderFactory.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/FileCodeReaderFactory.java index fad45cc8a31..4acf6ee73c9 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/FileCodeReaderFactory.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/FileCodeReaderFactory.java @@ -66,5 +66,4 @@ public class FileCodeReaderFactory implements ICodeReaderFactory { public ICodeReaderCache getCodeReaderCache() { return cache; } - } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/Bug246129.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/Bug246129.java new file mode 100644 index 00000000000..99bd2d508a6 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/Bug246129.java @@ -0,0 +1,256 @@ +package org.eclipse.cdt.internal.index.tests; + +import java.io.File; +import java.io.FileWriter; + +import junit.framework.TestSuite; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IScope; +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.IIndexInclude; +import org.eclipse.cdt.core.index.IndexFilter; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.IPathEntry; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.testplugin.CProjectHelper; +import org.eclipse.cdt.core.testplugin.TestScannerProvider; +import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; + +public class Bug246129 extends IndexTestBase { + + public static TestSuite suite() { + TestSuite suite = suite(Bug246129.class, "_"); + // suite.addTest(new Bug246129("include ext/../type.h")); + return suite; + } + + private ICProject fProject; + + private IFile fSource; + + private IFolder fWrapperIncludeFolder; + + private IFolder fIncludeFolder; + + private File fTmpDir; + + private File fExternalWrapperIncludeFolder; + + private File fExternalWrapperHeader; + + private File fExternalIncludeFolder; + + private File fExternalHeader; + + private File fExternalExtFolder; + + IIndex fIndex; + + boolean fFalseFriendsAccepted; + + public Bug246129(String name) { + super(name); + } + + protected void setUp() throws Exception { + super.setUp(); + if (fProject == null) { + + // Populate workspace + fProject = createProject(true, "resources/indexTests/bug246129"); + + fSource = fProject.getProject().getFile("source.cpp"); + + fWrapperIncludeFolder = fProject.getProject().getFolder( + "wrapper_include"); + + fIncludeFolder = fProject.getProject().getFolder("include"); + + // Create header files external to the workspace. + fTmpDir = CProjectHelper.freshDir(); + + fExternalWrapperIncludeFolder = new File(fTmpDir, + "wrapper_include"); + fExternalWrapperIncludeFolder.mkdir(); + + fExternalWrapperHeader = new File( + fExternalWrapperIncludeFolder, "external_type.h"); + fExternalWrapperHeader.createNewFile(); + FileWriter writer = new FileWriter(fExternalWrapperHeader); + writer.write("#ifndef EXTERNAL_WRAPPER_TYPE_H_\n"); + writer.write("#define EXTERNAL_WRAPPER_TYPE_H_\n"); + writer.write("#include \n"); + writer.write("class ExternalWrapper {\n"); + writer.write("};\n"); + writer.write("#endif\n"); + writer.close(); + + fExternalIncludeFolder = new File(fTmpDir, "include"); + fExternalIncludeFolder.mkdir(); + + fExternalExtFolder = new File(fExternalIncludeFolder, "ext"); + fExternalExtFolder.mkdir(); + + fExternalHeader = new File(fExternalIncludeFolder, + "external_type.h"); + fExternalHeader.createNewFile(); + writer = new FileWriter(fExternalHeader); + writer.write("#ifndef EXTERNAL_TYPE_H_\n"); + writer.write("#define EXTERNAL_TYPE_H_\n"); + writer.write("class ExternalType {\n"); + writer.write("};\n"); + writer.write("#endif\n"); + writer.close(); + + // The indexer needs non-empty build info in order to index + // source files if index-all-files is turned off. + IPathEntry[] entries = new IPathEntry[] { CoreModel + .newIncludeEntry(fProject.getPath(), null, + fWrapperIncludeFolder.getLocation()), + CoreModel.newIncludeEntry(fProject.getPath(), null, + fIncludeFolder.getLocation()) }; + + fProject.setRawPathEntries(entries, NPM); + + // However, the scanner info provider used by the unit tests + // needs separate setup, and this one must be complete. + TestScannerProvider.sIncludes = new String[] { + fWrapperIncludeFolder.getLocation().toOSString(), + fIncludeFolder.getLocation().toOSString(), + fExternalWrapperIncludeFolder.getAbsolutePath(), + fExternalIncludeFolder.getAbsolutePath() }; + + IndexerPreferences.set(fProject.getProject(), + IndexerPreferences.KEY_INDEX_ALL_FILES, "false"); + + File falseFriendDirectory = new File(fWrapperIncludeFolder + .getLocation().toOSString() + + "/ext/.."); + + fFalseFriendsAccepted = falseFriendDirectory.exists(); + + CCorePlugin.getIndexManager().reindex(fProject); + assertTrue(CCorePlugin.getIndexManager().joinIndexer(10000, NPM)); + fIndex = CCorePlugin.getIndexManager().getIndex(fProject); + } + } + + protected void tearDown() throws Exception { + fExternalWrapperHeader.delete(); + fExternalWrapperIncludeFolder.delete(); + + fExternalHeader.delete(); + fExternalExtFolder.delete(); + fExternalIncludeFolder.delete(); + + fTmpDir.delete(); + + super.tearDown(); + } + + private void assertSymbolInIndex(String symbolName) throws Exception { + IIndexBinding[] bindings = fIndex.findBindings( + symbolName + .toCharArray(), false, IndexFilter.ALL, NPM); + assertTrue(bindings.length > 0); + } + + public void testIndex() throws Exception { + + try { + + fIndex.acquireReadLock(); + IIndexFile[] indexFiles = fIndex.getAllFiles(); + + // Check that all header files have been found, provided the + // File implementation does support it. + if (fFalseFriendsAccepted) { + assertEquals(3, indexFiles.length); + } else { + assertEquals(5, indexFiles.length); + } + + // The wrapper classes are found regardless whether false friends + // are + // accepted or not. + assertSymbolInIndex("Wrapper"); + assertSymbolInIndex("ExternalWrapper"); + + // The Type class is only known on platforms with a File + // implementation sorting out the false friends. + if (!fFalseFriendsAccepted) { + assertSymbolInIndex("Type"); + assertSymbolInIndex("ExternalType"); + } + + // Check that all paths are normalized. + for (IIndexFile indexFile : indexFiles) { + + IIndexInclude[] includes = indexFile.getIncludes(); + + for (IIndexInclude i : includes) { + IIndexFileLocation location = i.getIncludesLocation(); + assertNotNull(location); + + assertFalse(location.getURI().toASCIIString() + .contains("..")); + + String fullPath = location.getFullPath(); + if (fullPath != null) { + assertFalse(fullPath.contains("..")); + } + } + } + + } finally { + fIndex.releaseReadLock(); + } + } + + private void assertSymbolInAst(IScope scope, String symbolName) + throws Exception { + IBinding[] bindings = scope.find(symbolName); + assertTrue(bindings.length > 0); + } + + public void testAst() throws Exception { + ITranslationUnit tu = CoreModel.getDefault().createTranslationUnitFrom( + fProject, fSource.getLocation()); + + IASTTranslationUnit ast = tu.getAST(); + + // The wrapper classes are found regardless whether false friends + // are + // accepted or not. + IScope topLevel = ast.getScope(); + assertSymbolInAst(topLevel, "Wrapper"); + assertSymbolInAst(topLevel, "ExternalWrapper"); + + // The Type class is only known on platforms with a File + // implementation sorting out the false friends. + if (!fFalseFriendsAccepted) { + assertSymbolInAst(topLevel, "Type"); + assertSymbolInAst(topLevel, "ExternalType"); + } + + // Check that all paths are normalized. + IASTPreprocessorIncludeStatement[] includes = ast + .getIncludeDirectives(); + for (IASTPreprocessorIncludeStatement i : includes) { + String includedPath = i.getPath(); + + assertNotNull(includedPath); + assertFalse(includedPath.contains("..")); + } + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java index 187ec3315a3..3fcd29db2e0 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java @@ -9,7 +9,6 @@ * Markus Schorn - initial API and implementation * Andrew Ferguson (Symbian) *******************************************************************************/ - package org.eclipse.cdt.internal.index.tests; import java.io.ByteArrayInputStream; @@ -81,7 +80,9 @@ public class IndexBugsTests extends BaseTestCase { } public static TestSuite suite() { - return suite(IndexBugsTests.class); + final TestSuite ts = suite(IndexBugsTests.class); + ts.addTest(Bug246129.suite()); + return ts; } @Override diff --git a/core/org.eclipse.cdt.core.tests/resources/indexTests/bug246129/include/ext/dummy.h b/core/org.eclipse.cdt.core.tests/resources/indexTests/bug246129/include/ext/dummy.h new file mode 100644 index 00000000000..a9102685163 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/resources/indexTests/bug246129/include/ext/dummy.h @@ -0,0 +1,3 @@ +#ifndef DUMMY_H_ +#define DUMMY_H_ +#endif diff --git a/core/org.eclipse.cdt.core.tests/resources/indexTests/bug246129/include/type.h b/core/org.eclipse.cdt.core.tests/resources/indexTests/bug246129/include/type.h new file mode 100644 index 00000000000..ed2633ab8e9 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/resources/indexTests/bug246129/include/type.h @@ -0,0 +1,5 @@ +#ifndef TYPE_H_ +#define TYPE_H_ +class Type { +}; +#endif diff --git a/core/org.eclipse.cdt.core.tests/resources/indexTests/bug246129/source.cpp b/core/org.eclipse.cdt.core.tests/resources/indexTests/bug246129/source.cpp new file mode 100644 index 00000000000..0a80efe64a6 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/resources/indexTests/bug246129/source.cpp @@ -0,0 +1,9 @@ +#include +#include +void check() +{ + Type t; + Wrapper w; + ExternalType et; + ExternalWrapper ew; +} diff --git a/core/org.eclipse.cdt.core.tests/resources/indexTests/bug246129/wrapper_include/type.h b/core/org.eclipse.cdt.core.tests/resources/indexTests/bug246129/wrapper_include/type.h new file mode 100644 index 00000000000..b7cbee32247 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/resources/indexTests/bug246129/wrapper_include/type.h @@ -0,0 +1,6 @@ +#ifndef WRAPPER_TYPE_H_ +#define WRAPPER_TYPE_H_ +#include +class Wrapper { +}; +#endif diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java index 2b2a7c248cf..d99f6791b70 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java @@ -69,6 +69,7 @@ import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.internal.core.dom.NullCodeReaderFactory; import org.eclipse.cdt.internal.core.dom.SavedCodeReaderFactory; import org.eclipse.cdt.internal.core.index.IndexBasedCodeReaderFactory; +import org.eclipse.cdt.internal.core.parser.InternalParserUtil; import org.eclipse.cdt.internal.core.parser.ParserLogService; import org.eclipse.cdt.internal.core.pdom.indexer.ProjectIndexerIncludeResolutionHeuristics; import org.eclipse.cdt.internal.core.pdom.indexer.ProjectIndexerInputAdapter; @@ -930,20 +931,25 @@ public class TranslationUnit extends Openable implements ITranslationUnit { } public CodeReader getCodeReader() { - CodeReader reader; IPath location= getLocation(); - if (isWorkingCopy() || location == null) { - if (location == null) { - reader= new CodeReader(getContents()); - } - else { - reader= new CodeReader(location.toString(), getContents()); - } + if (location == null) + return new CodeReader(getContents()); + if (isWorkingCopy()) { + return new CodeReader(location.toOSString(), getContents()); } - else { - reader= ParserUtil.createReader(location.toString(), null); + + IResource res= getResource(); + try { + if (res instanceof IFile) + return InternalParserUtil.createWorkspaceFileReader(location.toOSString(), (IFile) res); + else + return InternalParserUtil.createExternalFileReader(location.toOSString()); + } catch (CoreException e) { + CCorePlugin.log(e); + } catch (IOException e) { + CCorePlugin.log(e); } - return reader; + return null; } public IScannerInfo getScannerInfo(boolean force) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/EmptyCodeReaderCache.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/EmptyCodeReaderCache.java index d36222a8045..7b37a81aa3a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/EmptyCodeReaderCache.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/EmptyCodeReaderCache.java @@ -10,12 +10,10 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser; -import java.util.Iterator; +import java.io.IOException; -import org.eclipse.cdt.core.model.IWorkingCopy; import org.eclipse.cdt.core.parser.CodeReader; import org.eclipse.cdt.core.parser.ICodeReaderCache; -import org.eclipse.cdt.internal.core.parser.InternalParserUtil; /** * This is an empty implementation of the ICodeReaderCache interface. It is used to implement a @@ -32,20 +30,13 @@ public class EmptyCodeReaderCache implements ICodeReaderCache { * Creates a new CodeReader for the given file location. */ public CodeReader get(String location) { - CodeReader ret = null; - ret = InternalParserUtil.createFileReader(location); - return ret; + try { + return new CodeReader(location); + } catch (IOException e) { + } + return null; } - /** - * This provides support for PartialWorkingCopyCodeReaderFactory. - * @param finalPath - * @param workingCopies - */ - public CodeReader createReader(String finalPath, Iterator workingCopies ) { - return InternalParserUtil.createFileReader(finalPath); - } - /** * Returns null. */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedCodeReaderFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedCodeReaderFactory.java index 37864dfa152..ceda8eddacf 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedCodeReaderFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedCodeReaderFactory.java @@ -14,6 +14,7 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.index; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -36,6 +37,7 @@ import org.eclipse.cdt.core.parser.ICodeReaderCache; import org.eclipse.cdt.core.parser.ParserUtil; import org.eclipse.cdt.internal.core.dom.AbstractCodeReaderFactory; import org.eclipse.cdt.internal.core.dom.IIncludeFileResolutionHeuristics; +import org.eclipse.cdt.internal.core.parser.InternalParserUtil; 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.InclusionKind; @@ -162,9 +164,15 @@ public final class IndexBasedCodeReaderFactory extends AbstractCodeReaderFactory CCorePlugin.log(e); } - CodeReader codeReader= createCodeReaderForInclusion(path); - if (codeReader != null) { - return new IncludeFileContent(codeReader); + try { + CodeReader codeReader= InternalParserUtil.createCodeReader(ifl); + if (codeReader != null) { + return new IncludeFileContent(codeReader); + } + } catch (CoreException e) { + CCorePlugin.log(e); + } catch (IOException e) { + CCorePlugin.log(e); } return null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/InternalParserUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/InternalParserUtil.java index b88385f8844..6e962f33de0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/InternalParserUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/InternalParserUtil.java @@ -6,32 +6,80 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM Corporation - initial API and implementation + * John Camelon (IBM Corporation) - initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.parser; import java.io.File; import java.io.IOException; +import java.io.InputStream; +import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.parser.CodeReader; import org.eclipse.cdt.core.parser.ParserFactory; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; /** - * @author jcamelon + * Utility for creating code readers */ public class InternalParserUtil extends ParserFactory { - public static CodeReader createFileReader(String finalPath) { - File includeFile = new File(finalPath); + /** + * Normalizes the path by using the location of the file, if possible. + */ + public static String normalizePath(String path, IFile file) { + IPath loc= file.getLocation(); + if (loc != null) { + path= loc.toOSString(); + } + return path; + } + + /** + * Creates a code reader for an external location, normalizing path to + * canonical path. + */ + public static CodeReader createExternalFileReader(String externalLocation) throws IOException { + File includeFile = new File(externalLocation); if (includeFile.isFile()) { - try { //use the canonical path so that in case of non-case-sensitive OSs //the CodeReader always has the same name as the file on disk with //no differences in case. - return new CodeReader(includeFile.getCanonicalPath()); - } catch (IOException e) { - } + return new CodeReader(includeFile.getCanonicalPath()); } return null; } + + /** + * Creates a code reader for an external location, normalizing path to + * canonical path. + */ + public static CodeReader createWorkspaceFileReader(String path, IFile file) throws CoreException, IOException{ + path = normalizePath(path, file); + InputStream in= file.getContents(); + try { + return new CodeReader(path, file.getCharset(), in); + } finally { + try { + in.close(); + } catch (IOException e) { + } + } + } + + public static CodeReader createCodeReader(IIndexFileLocation ifl) throws CoreException, IOException { + String fullPath= ifl.getFullPath(); + if (fullPath != null) { + IResource res= ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(fullPath)); + if (res instanceof IFile) + return createWorkspaceFileReader(ifl.getURI().getPath(), (IFile) res); + } + return createExternalFileReader(ifl.getURI().getPath()); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerUtility.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerUtility.java index 327c689adc5..80d033e1ee6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerUtility.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerUtility.java @@ -30,7 +30,19 @@ public class ScannerUtility { * - replace multiple separators by single one * - skip "/./" * - skip quotes - * - process "/../" (skip previous directory level) + * + * Note: "/../" is left untouched on purpose in order to work properly under + * circumstances such as this: + * + * header file at include_1/vector: + * // Is supposed to find the STL vector header: + * #include + * + * GCC include tree + * include_gcc/ext/... + * /vector + * + * (ls include_1/ext/../vector does not work either). * * @param originalPath - path to process * @return - reconciled path @@ -87,29 +99,12 @@ public class ScannerUtility { aus[j++] = DOT; aus[j++] = c; } - // we found "/.." sequence. Look ahead. + // Processed as usual else { - // we found "/../" (or "/.." is at the end of string) - // we should delete previous segment of output path - if (i == len1 || ein[i+2] == SLASH || ein[i+2] == BSLASH) { - i+=2; - noSepBefore = false; - if (j > 1) { // there is at least 1 segment before - int k = j - 2; - while ( k >= 0 ) { - if (aus[k] == File.separatorChar) break; - k--; - } - j = k + 1; // set index to previous segment or to 0 - } - } - // Case "/..blabla" processed as usual - else { - i++; - noSepBefore = true; - aus[j++] = DOT; - aus[j++] = DOT; - } + i++; + noSepBefore = true; + aus[j++] = DOT; + aus[j++] = DOT; } } else {} // do nothing when "." is last symbol diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/parser/CodeReaderCache.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/parser/CodeReaderCache.java index 943aa44b99a..ce5a0ff2bf6 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/parser/CodeReaderCache.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/parser/CodeReaderCache.java @@ -13,11 +13,10 @@ package org.eclipse.cdt.core.parser; import java.io.File; -import java.util.Collections; -import java.util.List; +import java.io.IOException; import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.core.model.IWorkingCopy; +import org.eclipse.cdt.internal.core.parser.InternalParserUtil; import org.eclipse.cdt.internal.core.util.ILRUCacheable; import org.eclipse.cdt.internal.core.util.OverflowingLRUCache; import org.eclipse.core.resources.IFile; @@ -27,6 +26,7 @@ import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; @@ -140,25 +140,44 @@ public class CodeReaderCache implements ICodeReaderCache { * @param key the path of the CodeReader to retrieve */ public synchronized CodeReader get(String key) { - CodeReader ret = null; + CodeReader result = null; if (cache.getSpaceLimit() > 0) - ret = cache.get(key); + result= cache.get(key); - // not in the cache - if (ret == null) { - // for efficiency: check File.exists before ParserUtil#createReader() - // bug 100947 fix: don't want to attempt to create a code reader if there is no file for the key - if (!(new File(key).exists())) - return null; - - final List emptyList= Collections.emptyList(); - ret = ParserUtil.createReader(key, emptyList.iterator()); + if (result != null) + return result; + + // for efficiency: check File.exists before ParserUtil#createReader() + // bug 100947 fix: don't want to attempt to create a code reader if there is no file for the key + final File jfile = new File(key); + if (!(jfile.exists())) + return null; + try { + IResource file = ParserUtil.getResourceForFilename(key); + if (file instanceof IFile) { + key= InternalParserUtil.normalizePath(key, (IFile) file); + result= cache.get(key); + if (result != null) + return result; + + result= InternalParserUtil.createWorkspaceFileReader(key, (IFile) file); + } + key= jfile.getCanonicalPath(); + result= cache.get(key); + if (result != null) + return result; + + result= InternalParserUtil.createExternalFileReader(key); if (cache.getSpaceLimit() > 0) - put(ret); + put(result); + + return result; + } catch (CoreException ce) { + } catch (IOException e) { + } catch (IllegalStateException e) { } - - return ret; + return null; } /** diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/parser/ParserUtil.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/parser/ParserUtil.java index 06dd882928f..065b43fa593 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/parser/ParserUtil.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/parser/ParserUtil.java @@ -12,7 +12,6 @@ package org.eclipse.cdt.core.parser; import java.io.IOException; -import java.io.InputStream; import java.util.Iterator; import org.eclipse.cdt.core.model.IWorkingCopy; @@ -62,49 +61,29 @@ public class ParserUtil return null; } - public static CodeReader createReader( String finalPath, Iterator workingCopies ) - { - // check to see if the file which this path points to points to an + public static CodeReader createReader(String path, Iterator workingCopies) { + // check to see if the file which this path points to points to an // IResource in the workspace - try - { - IResource resultingResource = getResourceForFilename(finalPath); - - if( resultingResource != null && resultingResource.getType() == IResource.FILE ) - { - // this is the file for sure - // check the working copy - if( workingCopies != null && workingCopies.hasNext() ) - { - char[] buffer = findWorkingCopy( resultingResource, workingCopies ); - if( buffer != null ) - return new CodeReader(finalPath, buffer); - } - InputStream in = null; - try - { - in = ((IFile)resultingResource).getContents(); - return new CodeReader(finalPath, ((IFile)resultingResource).getCharset(), in); - } finally { - if (in != null) - { - in.close(); - } + try { + IResource file = getResourceForFilename(path); + if (file instanceof IFile) { + // check for a working copy + if (workingCopies != null && workingCopies.hasNext()) { + char[] buffer = findWorkingCopy(file, workingCopies); + if (buffer != null) + return new CodeReader(InternalParserUtil.normalizePath(path, (IFile) file), buffer); } + return InternalParserUtil.createWorkspaceFileReader(path, (IFile) file); } + return InternalParserUtil.createExternalFileReader(path); + } catch (CoreException ce) { + } catch (IOException e) { + } catch (IllegalStateException e) { } - catch( CoreException ce ) - { - } - catch( IOException e ) - { - } - catch( IllegalStateException e ) - { - } - return InternalParserUtil.createFileReader(finalPath); + return null; } + public static IResource getResourceForFilename(String finalPath) { IWorkspace workspace = ResourcesPlugin.getWorkspace(); if( workspace == null )