| 1 | //===- HeaderFile.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 "clang/InstallAPI/HeaderFile.h" |
| 10 | #include "llvm/TextAPI/Utils.h" |
| 11 | |
| 12 | using namespace llvm; |
| 13 | namespace clang::installapi { |
| 14 | |
| 15 | llvm::Regex HeaderFile::() { |
| 16 | return llvm::Regex("/(.+)\\.framework/(.+)?Headers/(.+)" ); |
| 17 | } |
| 18 | |
| 19 | std::optional<std::string> (const StringRef FullPath) { |
| 20 | // Headers in usr(/local)*/include. |
| 21 | std::string Pattern = "/include/" ; |
| 22 | auto PathPrefix = FullPath.find(Str: Pattern); |
| 23 | if (PathPrefix != StringRef::npos) { |
| 24 | PathPrefix += Pattern.size(); |
| 25 | return FullPath.drop_front(N: PathPrefix).str(); |
| 26 | } |
| 27 | |
| 28 | // Framework Headers. |
| 29 | SmallVector<StringRef, 4> Matches; |
| 30 | HeaderFile::getFrameworkIncludeRule().match(String: FullPath, Matches: &Matches); |
| 31 | // Returned matches are always in stable order. |
| 32 | if (Matches.size() != 4) |
| 33 | return std::nullopt; |
| 34 | |
| 35 | return Matches[1].drop_front(N: Matches[1].rfind(C: '/') + 1).str() + "/" + |
| 36 | Matches[3].str(); |
| 37 | } |
| 38 | |
| 39 | bool (StringRef Path) { |
| 40 | return StringSwitch<bool>(sys::path::extension(path: Path)) |
| 41 | .Cases(S0: ".h" , S1: ".H" , S2: ".hh" , S3: ".hpp" , S4: ".hxx" , Value: true) |
| 42 | .Default(Value: false); |
| 43 | } |
| 44 | |
| 45 | llvm::Expected<PathSeq> enumerateFiles(FileManager &FM, StringRef Directory) { |
| 46 | PathSeq Files; |
| 47 | std::error_code EC; |
| 48 | auto &FS = FM.getVirtualFileSystem(); |
| 49 | for (llvm::vfs::recursive_directory_iterator i(FS, Directory, EC), ie; |
| 50 | i != ie; i.increment(EC)) { |
| 51 | if (EC) |
| 52 | return errorCodeToError(EC); |
| 53 | |
| 54 | // Skip files that do not exist. This usually happens for broken symlinks. |
| 55 | if (FS.status(Path: i->path()) == std::errc::no_such_file_or_directory) |
| 56 | continue; |
| 57 | |
| 58 | StringRef Path = i->path(); |
| 59 | if (isHeaderFile(Path)) |
| 60 | Files.emplace_back(args&: Path); |
| 61 | } |
| 62 | |
| 63 | return Files; |
| 64 | } |
| 65 | |
| 66 | HeaderGlob::(StringRef GlobString, Regex &&Rule, HeaderType Type) |
| 67 | : GlobString(GlobString), Rule(std::move(Rule)), Type(Type) {} |
| 68 | |
| 69 | bool HeaderGlob::(const HeaderFile &) { |
| 70 | if (Header.getType() != Type) |
| 71 | return false; |
| 72 | |
| 73 | bool Match = Rule.match(String: Header.getPath()); |
| 74 | if (Match) |
| 75 | FoundMatch = true; |
| 76 | return Match; |
| 77 | } |
| 78 | |
| 79 | Expected<std::unique_ptr<HeaderGlob>> HeaderGlob::(StringRef GlobString, |
| 80 | HeaderType Type) { |
| 81 | auto Rule = MachO::createRegexFromGlob(Glob: GlobString); |
| 82 | if (!Rule) |
| 83 | return Rule.takeError(); |
| 84 | |
| 85 | return std::make_unique<HeaderGlob>(args&: GlobString, args: std::move(*Rule), args&: Type); |
| 86 | } |
| 87 | |
| 88 | } // namespace clang::installapi |
| 89 | |