[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[cdt-dev] Analysis and solutions for Open Declaration/Definition: case-senstiive path checks on Win32
|
Title: Analysis and solutions for Open Declaration/Definition: case-senstiive path checks on Win32
The first bug I ran across is simple but devastating. IncludeEntry sometimes stores include paths in a slightly different case than the paths the indexer constructs. (Why? I didn't find out yet.) Due to some parts of Eclipse's Path implementation being case-sensitive on all platforms -- esp. in #isPrefixOf() -- IncludeReference#isOnIncludeEntry() fails to detect that a file is on the include paths.
So the indexer could have totally complete and correct data, but CModelManager#createTranslationUnitFrom() would fail to create a TU for the file. (There seem to be other problems with this method due to the lack of a fallback or any notification when trying to construct a TU for a non-includeable file.)
It's simpler not to touch Path or uses of #isPrefixOf(), so my solution is to store a canonical path in IncludeEntry and canonicalize the input path on entry to IncludeReference#isOnIncludeEntry(). My quick'n'dirty "canonicalization" just lowercases paths when on the Win32 platform, though going through java.io.File#getCanonicalFile() would be best (and would preserve the case displayed in the UI), though with an unknown performance hit. I didn't search for other places where this might be a problem.
IncludeEntry.java:
public IncludeEntry(IPath resourcePath, IPath basePath, IPath baseRef, IPath includePath, boolean isSystemInclude,
IPath[] exclusionPatterns, boolean isExported) {
super(IPathEntry.CDT_INCLUDE, basePath, baseRef, resourcePath, exclusionPatterns, isExported);
this.includePath = (includePath == null) ? Path.EMPTY :
Util.getCanonicalPath(includePath);
this.isSystemInclude = isSystemInclude;
}
...
IncludeReference.java:
/* (non-Javadoc)
* @see org.eclipse.cdt.core.model.IIncludeReference#isOnIncludeEntry(org.eclipse.core.runtime.IPath)
*/
public boolean isOnIncludeEntry(IPath path) {
path = Util.getCanonicalPath(path);
if (fIncludeEntry.getIncludePath().isPrefixOf(path)
&& !CoreModelUtil.isExcluded(path, fIncludeEntry.fullExclusionPatternChars())) {
return true;
}
return false;
}
...
Util.java:
private static boolean hasCaseInsensitiveFileSystem;
static {
hasCaseInsensitiveFileSystem = Platform.getOS().equals(Platform.OS_WIN32);
}
/**
* Get a canonical IPath, for use in IPath#isPrefixOf, #equals, etc.
* to overcome a bug in Path that doesn't account for
* case-insensitive filesystems.
*/
public static IPath getCanonicalPath(IPath path) {
if (hasCaseInsensitiveFileSystem) {
// be stupid for now (instead of using File#toCanonicalFile())
return new Path(path.toOSString().toLowerCase());
}
return path;
}
-- Ed