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