This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Treat paths case-insensitively depending on the platform
ClosedPublic

Authored by kadircet on Feb 15 2021, 12:04 AM.

Details

Summary

Path{Match,Exclude} and MountPoint were checking paths case-sensitively
on all platforms, as with other features, this was causing problems on
windows. Since users can have capital drive letters on config files, but
editors might lower-case them.

This patch addresses that issue by:

  • Normalizing all the paths being passed to ConfigProvider in ClangdServer.
  • Storing MountPoint and regexes used for pathmatching in case-folded manner.

Diff Detail

Event Timeline

kadircet created this revision.Feb 15 2021, 12:04 AM
kadircet requested review of this revision.Feb 15 2021, 12:04 AM

Thanks for the important fix.

This contains a mixture of changing comparison-of-paths to be case insensitive, and case-normalizing stored paths so we can use case-sensitive comparisons.

I think we should stick to *only* changing comparison-of-path logic as much as possible, because:

  • both approaches are ad-hoc and error prone - forgetting to fold/insensitive-compare will introduce a bug
  • it's more obvious where to fix a sensitive-compare, and it has fewer unexpected effects
  • in many configs we only ever see one case for a given file, case-folding can introduce bugs here where insensitive-comparison cannot
  • there's a risk we won't be case-preserving, which can be annoying or really matter (e.g. on a mac volume that *is* case sensitive)
clang-tools-extra/clangd/ConfigCompile.cpp
201

I'm starting to think Path.h should export a CLANGD_PATH_INSENSITIVE macro, this condition is in a bunch of places. (particularly tests)

I nearly did this last time and came to the conclusion it wasn't quite enough :-\

kadircet updated this revision to Diff 323951.Feb 16 2021, 3:30 AM
  • Don't case fold stored strings, or the ones passing interface boundaries
  • Define a pathIsAncestor helper instead and use that for comparison of MountPoint
  • Expose a CLANGD_PATH_CASE_INSENSITIVE macro, which is defined whenever the platform treats paths case-insensitively
kadircet marked an inline comment as done.Feb 16 2021, 3:30 AM
sammccall accepted this revision.Feb 16 2021, 6:10 AM

Nice, thank you!

clang-tools-extra/clangd/support/Path.cpp
22

we should decide what the preconditions are here

Could assert both are absolute paths, this places a burden on callers.

I do like the idea this is "just" a smarter lexical startswith. (I'd consider pathStartsWith rather than pathIsAncestor for this reason)
In this case we should doc it (e.g. foo/./bar is not an ancestor of foo/bar/baz) and return false when Ancestor is empty (rather than crash)

clang-tools-extra/clangd/support/Path.h
18

(we could conditionally define this as either 0 or 1 and then use it for regex flags without ifdef, up to you)

This revision is now accepted and ready to land.Feb 16 2021, 6:10 AM
kadircet updated this revision to Diff 323997.Feb 16 2021, 6:56 AM
kadircet marked an inline comment as done.
  • s/pathIsAncestor/pathStartsWith
  • Fix tests
clang-tools-extra/clangd/support/Path.cpp
22

oops nice catch. going with the latter option.

This revision was landed with ongoing or failed builds.Feb 16 2021, 11:21 AM
This revision was automatically updated to reflect the committed changes.