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 | |