xref: /llvm-project/clang-tools-extra/clangd/support/Path.cpp (revision 86029e4c220b91be728f6ff6a17cad098821e657)
1 //===--- Path.cpp -------------------------------------------*- C++-*------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "support/Path.h"
10 #include "llvm/Support/Path.h"
11 namespace clang {
12 namespace clangd {
13 
14 #ifdef CLANGD_PATH_CASE_INSENSITIVE
maybeCaseFoldPath(PathRef Path)15 std::string maybeCaseFoldPath(PathRef Path) { return Path.lower(); }
pathEqual(PathRef A,PathRef B)16 bool pathEqual(PathRef A, PathRef B) { return A.equals_insensitive(B); }
17 #else  // NOT CLANGD_PATH_CASE_INSENSITIVE
18 std::string maybeCaseFoldPath(PathRef Path) { return Path.str(); }
19 bool pathEqual(PathRef A, PathRef B) { return A == B; }
20 #endif // CLANGD_PATH_CASE_INSENSITIVE
21 
absoluteParent(PathRef Path)22 PathRef absoluteParent(PathRef Path) {
23   assert(llvm::sys::path::is_absolute(Path));
24 #if defined(_WIN32)
25   // llvm::sys says "C:\" is absolute, and its parent is "C:" which is relative.
26   // This unhelpful behavior seems to have been inherited from boost.
27   if (llvm::sys::path::relative_path(Path).empty()) {
28     return PathRef();
29   }
30 #endif
31   PathRef Result = llvm::sys::path::parent_path(Path);
32   assert(Result.empty() || llvm::sys::path::is_absolute(Result));
33   return Result;
34 }
35 
pathStartsWith(PathRef Ancestor,PathRef Path,llvm::sys::path::Style Style)36 bool pathStartsWith(PathRef Ancestor, PathRef Path,
37                     llvm::sys::path::Style Style) {
38   assert(llvm::sys::path::is_absolute(Ancestor) &&
39          llvm::sys::path::is_absolute(Path));
40   // If ancestor ends with a separator drop that, so that we can match /foo/ as
41   // a parent of /foo.
42   if (llvm::sys::path::is_separator(Ancestor.back(), Style))
43     Ancestor = Ancestor.drop_back();
44   // Ensure Path starts with Ancestor.
45   if (!pathEqual(Ancestor, Path.take_front(Ancestor.size())))
46     return false;
47   Path = Path.drop_front(Ancestor.size());
48   // Then make sure either two paths are equal or Path has a separator
49   // afterwards.
50   return Path.empty() || llvm::sys::path::is_separator(Path.front(), Style);
51 }
52 } // namespace clangd
53 } // namespace clang
54