mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Correctly resolving includes like "path/../file.h", bug 246129
This commit is contained in:
parent
0c73673ec2
commit
7b7875106f
14 changed files with 443 additions and 118 deletions
|
@ -66,5 +66,4 @@ public class FileCodeReaderFactory implements ICodeReaderFactory {
|
||||||
public ICodeReaderCache getCodeReaderCache() {
|
public ICodeReaderCache getCodeReaderCache() {
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 <ext/../external_type.h>\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(".."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,6 @@
|
||||||
* Markus Schorn - initial API and implementation
|
* Markus Schorn - initial API and implementation
|
||||||
* Andrew Ferguson (Symbian)
|
* Andrew Ferguson (Symbian)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
package org.eclipse.cdt.internal.index.tests;
|
package org.eclipse.cdt.internal.index.tests;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
@ -81,7 +80,9 @@ public class IndexBugsTests extends BaseTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TestSuite suite() {
|
public static TestSuite suite() {
|
||||||
return suite(IndexBugsTests.class);
|
final TestSuite ts = suite(IndexBugsTests.class);
|
||||||
|
ts.addTest(Bug246129.suite());
|
||||||
|
return ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
#ifndef DUMMY_H_
|
||||||
|
#define DUMMY_H_
|
||||||
|
#endif
|
|
@ -0,0 +1,5 @@
|
||||||
|
#ifndef TYPE_H_
|
||||||
|
#define TYPE_H_
|
||||||
|
class Type {
|
||||||
|
};
|
||||||
|
#endif
|
|
@ -0,0 +1,9 @@
|
||||||
|
#include <type.h>
|
||||||
|
#include <external_type.h>
|
||||||
|
void check()
|
||||||
|
{
|
||||||
|
Type t;
|
||||||
|
Wrapper w;
|
||||||
|
ExternalType et;
|
||||||
|
ExternalWrapper ew;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef WRAPPER_TYPE_H_
|
||||||
|
#define WRAPPER_TYPE_H_
|
||||||
|
#include <ext/../type.h>
|
||||||
|
class Wrapper {
|
||||||
|
};
|
||||||
|
#endif
|
|
@ -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.NullCodeReaderFactory;
|
||||||
import org.eclipse.cdt.internal.core.dom.SavedCodeReaderFactory;
|
import org.eclipse.cdt.internal.core.dom.SavedCodeReaderFactory;
|
||||||
import org.eclipse.cdt.internal.core.index.IndexBasedCodeReaderFactory;
|
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.parser.ParserLogService;
|
||||||
import org.eclipse.cdt.internal.core.pdom.indexer.ProjectIndexerIncludeResolutionHeuristics;
|
import org.eclipse.cdt.internal.core.pdom.indexer.ProjectIndexerIncludeResolutionHeuristics;
|
||||||
import org.eclipse.cdt.internal.core.pdom.indexer.ProjectIndexerInputAdapter;
|
import org.eclipse.cdt.internal.core.pdom.indexer.ProjectIndexerInputAdapter;
|
||||||
|
@ -930,20 +931,25 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodeReader getCodeReader() {
|
public CodeReader getCodeReader() {
|
||||||
CodeReader reader;
|
|
||||||
IPath location= getLocation();
|
IPath location= getLocation();
|
||||||
if (isWorkingCopy() || location == null) {
|
if (location == null)
|
||||||
if (location == null) {
|
return new CodeReader(getContents());
|
||||||
reader= new CodeReader(getContents());
|
if (isWorkingCopy()) {
|
||||||
}
|
return new CodeReader(location.toOSString(), getContents());
|
||||||
else {
|
|
||||||
reader= new CodeReader(location.toString(), 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) {
|
public IScannerInfo getScannerInfo(boolean force) {
|
||||||
|
|
|
@ -10,12 +10,10 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser;
|
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.CodeReader;
|
||||||
import org.eclipse.cdt.core.parser.ICodeReaderCache;
|
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
|
* 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.
|
* Creates a new CodeReader for the given file location.
|
||||||
*/
|
*/
|
||||||
public CodeReader get(String location) {
|
public CodeReader get(String location) {
|
||||||
CodeReader ret = null;
|
try {
|
||||||
ret = InternalParserUtil.createFileReader(location);
|
return new CodeReader(location);
|
||||||
return ret;
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This provides support for PartialWorkingCopyCodeReaderFactory.
|
|
||||||
* @param finalPath
|
|
||||||
* @param workingCopies
|
|
||||||
*/
|
|
||||||
public CodeReader createReader(String finalPath, Iterator<IWorkingCopy> workingCopies ) {
|
|
||||||
return InternalParserUtil.createFileReader(finalPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns null.
|
* Returns null.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.index;
|
package org.eclipse.cdt.internal.core.index;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
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.core.parser.ParserUtil;
|
||||||
import org.eclipse.cdt.internal.core.dom.AbstractCodeReaderFactory;
|
import org.eclipse.cdt.internal.core.dom.AbstractCodeReaderFactory;
|
||||||
import org.eclipse.cdt.internal.core.dom.IIncludeFileResolutionHeuristics;
|
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.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.IncludeFileContent.InclusionKind;
|
import org.eclipse.cdt.internal.core.parser.scanner.IncludeFileContent.InclusionKind;
|
||||||
|
@ -162,9 +164,15 @@ public final class IndexBasedCodeReaderFactory extends AbstractCodeReaderFactory
|
||||||
CCorePlugin.log(e);
|
CCorePlugin.log(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeReader codeReader= createCodeReaderForInclusion(path);
|
try {
|
||||||
if (codeReader != null) {
|
CodeReader codeReader= InternalParserUtil.createCodeReader(ifl);
|
||||||
return new IncludeFileContent(codeReader);
|
if (codeReader != null) {
|
||||||
|
return new IncludeFileContent(codeReader);
|
||||||
|
}
|
||||||
|
} catch (CoreException e) {
|
||||||
|
CCorePlugin.log(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
CCorePlugin.log(e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,32 +6,80 @@
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* 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;
|
package org.eclipse.cdt.internal.core.parser;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
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.CodeReader;
|
||||||
import org.eclipse.cdt.core.parser.ParserFactory;
|
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 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()) {
|
if (includeFile.isFile()) {
|
||||||
try {
|
|
||||||
//use the canonical path so that in case of non-case-sensitive OSs
|
//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
|
//the CodeReader always has the same name as the file on disk with
|
||||||
//no differences in case.
|
//no differences in case.
|
||||||
return new CodeReader(includeFile.getCanonicalPath());
|
return new CodeReader(includeFile.getCanonicalPath());
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,19 @@ public class ScannerUtility {
|
||||||
* - replace multiple separators by single one
|
* - replace multiple separators by single one
|
||||||
* - skip "/./"
|
* - skip "/./"
|
||||||
* - skip quotes
|
* - 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 <ext/../vector>
|
||||||
|
*
|
||||||
|
* GCC include tree
|
||||||
|
* include_gcc/ext/...
|
||||||
|
* /vector
|
||||||
|
*
|
||||||
|
* (ls include_1/ext/../vector does not work either).
|
||||||
*
|
*
|
||||||
* @param originalPath - path to process
|
* @param originalPath - path to process
|
||||||
* @return - reconciled path
|
* @return - reconciled path
|
||||||
|
@ -87,29 +99,12 @@ public class ScannerUtility {
|
||||||
aus[j++] = DOT;
|
aus[j++] = DOT;
|
||||||
aus[j++] = c;
|
aus[j++] = c;
|
||||||
}
|
}
|
||||||
// we found "/.." sequence. Look ahead.
|
// Processed as usual
|
||||||
else {
|
else {
|
||||||
// we found "/../" (or "/.." is at the end of string)
|
i++;
|
||||||
// we should delete previous segment of output path
|
noSepBefore = true;
|
||||||
if (i == len1 || ein[i+2] == SLASH || ein[i+2] == BSLASH) {
|
aus[j++] = DOT;
|
||||||
i+=2;
|
aus[j++] = DOT;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
{} // do nothing when "." is last symbol
|
{} // do nothing when "." is last symbol
|
||||||
|
|
|
@ -13,11 +13,10 @@
|
||||||
package org.eclipse.cdt.core.parser;
|
package org.eclipse.cdt.core.parser;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Collections;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
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.ILRUCacheable;
|
||||||
import org.eclipse.cdt.internal.core.util.OverflowingLRUCache;
|
import org.eclipse.cdt.internal.core.util.OverflowingLRUCache;
|
||||||
import org.eclipse.core.resources.IFile;
|
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.IResourceDelta;
|
||||||
import org.eclipse.core.resources.IWorkspace;
|
import org.eclipse.core.resources.IWorkspace;
|
||||||
import org.eclipse.core.resources.ResourcesPlugin;
|
import org.eclipse.core.resources.ResourcesPlugin;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
|
@ -140,25 +140,44 @@ public class CodeReaderCache implements ICodeReaderCache {
|
||||||
* @param key the path of the CodeReader to retrieve
|
* @param key the path of the CodeReader to retrieve
|
||||||
*/
|
*/
|
||||||
public synchronized CodeReader get(String key) {
|
public synchronized CodeReader get(String key) {
|
||||||
CodeReader ret = null;
|
CodeReader result = null;
|
||||||
if (cache.getSpaceLimit() > 0)
|
if (cache.getSpaceLimit() > 0)
|
||||||
ret = cache.get(key);
|
result= cache.get(key);
|
||||||
|
|
||||||
// not in the cache
|
if (result != null)
|
||||||
if (ret == 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
|
// for efficiency: check File.exists before ParserUtil#createReader()
|
||||||
if (!(new File(key).exists()))
|
// bug 100947 fix: don't want to attempt to create a code reader if there is no file for the key
|
||||||
return null;
|
final File jfile = new File(key);
|
||||||
|
if (!(jfile.exists()))
|
||||||
final List<IWorkingCopy> emptyList= Collections.emptyList();
|
return null;
|
||||||
ret = ParserUtil.createReader(key, emptyList.iterator());
|
|
||||||
|
|
||||||
|
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)
|
if (cache.getSpaceLimit() > 0)
|
||||||
put(ret);
|
put(result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (CoreException ce) {
|
||||||
|
} catch (IOException e) {
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
package org.eclipse.cdt.core.parser;
|
package org.eclipse.cdt.core.parser;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.model.IWorkingCopy;
|
import org.eclipse.cdt.core.model.IWorkingCopy;
|
||||||
|
@ -62,49 +61,29 @@ public class ParserUtil
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CodeReader createReader( String finalPath, Iterator<IWorkingCopy> workingCopies )
|
public static CodeReader createReader(String path, Iterator<IWorkingCopy> workingCopies) {
|
||||||
{
|
// check to see if the file which this path points to points to an
|
||||||
// check to see if the file which this path points to points to an
|
|
||||||
// IResource in the workspace
|
// IResource in the workspace
|
||||||
try
|
try {
|
||||||
{
|
IResource file = getResourceForFilename(path);
|
||||||
IResource resultingResource = getResourceForFilename(finalPath);
|
if (file instanceof IFile) {
|
||||||
|
// check for a working copy
|
||||||
if( resultingResource != null && resultingResource.getType() == IResource.FILE )
|
if (workingCopies != null && workingCopies.hasNext()) {
|
||||||
{
|
char[] buffer = findWorkingCopy(file, workingCopies);
|
||||||
// this is the file for sure
|
if (buffer != null)
|
||||||
// check the working copy
|
return new CodeReader(InternalParserUtil.normalizePath(path, (IFile) file), buffer);
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return InternalParserUtil.createWorkspaceFileReader(path, (IFile) file);
|
||||||
}
|
}
|
||||||
|
return InternalParserUtil.createExternalFileReader(path);
|
||||||
|
} catch (CoreException ce) {
|
||||||
|
} catch (IOException e) {
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
}
|
}
|
||||||
catch( CoreException ce )
|
return null;
|
||||||
{
|
|
||||||
}
|
|
||||||
catch( IOException e )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
catch( IllegalStateException e )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
return InternalParserUtil.createFileReader(finalPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static IResource getResourceForFilename(String finalPath) {
|
public static IResource getResourceForFilename(String finalPath) {
|
||||||
IWorkspace workspace = ResourcesPlugin.getWorkspace();
|
IWorkspace workspace = ResourcesPlugin.getWorkspace();
|
||||||
if( workspace == null )
|
if( workspace == null )
|
||||||
|
|
Loading…
Add table
Reference in a new issue