Skip to main content

[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





Back to the top