clang 20.0.0git
FileList.cpp
Go to the documentation of this file.
1//===- FileList.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
12#include "llvm/ADT/StringSwitch.h"
13#include "llvm/Support/Error.h"
14#include "llvm/Support/JSON.h"
15#include "llvm/TextAPI/TextAPIError.h"
16#include <optional>
17
18// clang-format off
19/*
20InstallAPI JSON Input Format specification.
21
22{
23 "headers" : [ # Required: Key must exist.
24 { # Optional: May contain 0 or more header inputs.
25 "path" : "/usr/include/mach-o/dlfn.h", # Required: Path should point to destination
26 # location where applicable.
27 "type" : "public", # Required: Maps to HeaderType for header.
28 "language": "c++" # Optional: Language mode for header.
29 }
30 ],
31 "version" : "3" # Required: Version 3 supports language mode
32 & project header input.
33}
34*/
35// clang-format on
36
37using namespace llvm;
38using namespace llvm::json;
39using namespace llvm::MachO;
40using namespace clang::installapi;
41
42namespace {
43class Implementation {
44private:
45 Expected<StringRef> parseString(const Object *Obj, StringRef Key,
46 StringRef Error);
47 Expected<StringRef> parsePath(const Object *Obj);
48 Expected<HeaderType> parseType(const Object *Obj);
49 std::optional<clang::Language> parseLanguage(const Object *Obj);
50 Error parseHeaders(Array &Headers);
51
52public:
53 std::unique_ptr<MemoryBuffer> InputBuffer;
55 unsigned Version;
56 HeaderSeq HeaderList;
57
58 Error parse(StringRef Input);
59};
60
62Implementation::parseString(const Object *Obj, StringRef Key, StringRef Error) {
63 auto Str = Obj->getString(Key);
64 if (!Str)
65 return make_error<StringError>(Error, inconvertibleErrorCode());
66 return *Str;
67}
68
69Expected<HeaderType> Implementation::parseType(const Object *Obj) {
70 auto TypeStr =
71 parseString(Obj, "type", "required field 'type' not specified");
72 if (!TypeStr)
73 return TypeStr.takeError();
74
75 if (*TypeStr == "public")
76 return HeaderType::Public;
77 else if (*TypeStr == "private")
78 return HeaderType::Private;
79 else if (*TypeStr == "project" && Version >= 2)
80 return HeaderType::Project;
81
82 return make_error<TextAPIError>(TextAPIErrorCode::InvalidInputFormat,
83 "unsupported header type");
84}
85
86Expected<StringRef> Implementation::parsePath(const Object *Obj) {
87 auto Path = parseString(Obj, "path", "required field 'path' not specified");
88 if (!Path)
89 return Path.takeError();
90
91 return *Path;
92}
93
94std::optional<clang::Language>
95Implementation::parseLanguage(const Object *Obj) {
96 auto Language = Obj->getString("language");
97 if (!Language)
98 return std::nullopt;
99
100 return StringSwitch<clang::Language>(*Language)
101 .Case("c", clang::Language::C)
102 .Case("c++", clang::Language::CXX)
103 .Case("objective-c", clang::Language::ObjC)
104 .Case("objective-c++", clang::Language::ObjCXX)
105 .Default(clang::Language::Unknown);
106}
107
108Error Implementation::parseHeaders(Array &Headers) {
109 for (const auto &H : Headers) {
110 auto *Obj = H.getAsObject();
111 if (!Obj)
112 return make_error<StringError>("expect a JSON object",
113 inconvertibleErrorCode());
114 auto Type = parseType(Obj);
115 if (!Type)
116 return Type.takeError();
117 auto Path = parsePath(Obj);
118 if (!Path)
119 return Path.takeError();
120 auto Language = parseLanguage(Obj);
121
122 StringRef PathStr = *Path;
123 if (*Type == HeaderType::Project) {
124 HeaderList.emplace_back(
125 HeaderFile{PathStr, *Type, /*IncludeName=*/"", Language});
126 continue;
127 }
128
129 if (FM)
130 if (!FM->getOptionalFileRef(PathStr))
131 return createFileError(
132 PathStr, make_error_code(std::errc::no_such_file_or_directory));
133
134 auto IncludeName = createIncludeHeaderName(PathStr);
135 HeaderList.emplace_back(PathStr, *Type,
136 IncludeName.has_value() ? IncludeName.value() : "",
137 Language);
138 }
139
140 return Error::success();
141}
142
143Error Implementation::parse(StringRef Input) {
144 auto Val = json::parse(Input);
145 if (!Val)
146 return Val.takeError();
147
148 auto *Root = Val->getAsObject();
149 if (!Root)
150 return make_error<StringError>("not a JSON object",
151 inconvertibleErrorCode());
152
153 auto VersionStr = Root->getString("version");
154 if (!VersionStr)
155 return make_error<TextAPIError>(TextAPIErrorCode::InvalidInputFormat,
156 "required field 'version' not specified");
157 if (VersionStr->getAsInteger(10, Version))
158 return make_error<TextAPIError>(TextAPIErrorCode::InvalidInputFormat,
159 "invalid version number");
160
161 if (Version < 1 || Version > 3)
162 return make_error<TextAPIError>(TextAPIErrorCode::InvalidInputFormat,
163 "unsupported version");
164
165 // Not specifying any header files should be atypical, but valid.
166 auto Headers = Root->getArray("headers");
167 if (!Headers)
168 return Error::success();
169
170 Error Err = parseHeaders(*Headers);
171 if (Err)
172 return Err;
173
174 return Error::success();
175}
176} // namespace
177
178llvm::Error
179FileListReader::loadHeaders(std::unique_ptr<MemoryBuffer> InputBuffer,
180 HeaderSeq &Destination, clang::FileManager *FM) {
181 Implementation Impl;
182 Impl.InputBuffer = std::move(InputBuffer);
183 Impl.FM = FM;
184
185 if (llvm::Error Err = Impl.parse(Impl.InputBuffer->getBuffer()))
186 return Err;
187
188 Destination.reserve(Destination.size() + Impl.HeaderList.size());
189 llvm::move(Impl.HeaderList, std::back_inserter(Destination));
190
191 return Error::success();
192}
MatchType Type
IndirectLocalPath & Path
Implements support for file system lookup, file system caching, and directory search management.
Definition: FileManager.h:53
The base class of the type hierarchy.
Definition: Type.h:1829
static llvm::Error loadHeaders(std::unique_ptr< llvm::MemoryBuffer > InputBuffer, HeaderSeq &Destination, clang::FileManager *FM=nullptr)
Decode JSON input and append header input into destination container.
Definition: FileList.cpp:179
std::error_code make_error_code(ParseError e)
Definition: Format.cpp:1257
The DirectoryScanner for collecting library files on the file system.
Definition: Context.h:20
std::vector< HeaderFile > HeaderSeq
Definition: HeaderFile.h:150
std::optional< std::string > createIncludeHeaderName(const StringRef FullPath)
Assemble expected way header will be included by clients.
Definition: HeaderFile.cpp:19
Language
The language for the input, used to select and validate the language standard and possible actions.
Definition: LangStandard.h:23
@ C
Languages that the frontend can parse and compile.
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30