clang  19.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 /*
20 InstallAPI 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 
37 using namespace llvm;
38 using namespace llvm::json;
39 using namespace llvm::MachO;
40 using namespace clang::installapi;
41 
42 namespace {
43 class Implementation {
44 private:
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 
52 public:
53  std::unique_ptr<MemoryBuffer> InputBuffer;
55  unsigned Version;
56  HeaderSeq HeaderList;
57 
58  Error parse(StringRef Input);
59 };
60 
62 Implementation::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 
69 Expected<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 
86 Expected<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 
94 std::optional<clang::Language>
95 Implementation::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 
108 Error 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 
143 Error 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 
178 llvm::Error
179 FileListReader::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
Implements support for file system lookup, file system caching, and directory search management.
Definition: FileManager.h:53
std::error_code make_error_code(ParseError e)
Definition: Format.cpp:1235
Representations of a library's headers for InstallAPI.
Definition: Context.h:20
std::vector< HeaderFile > HeaderSeq
Definition: HeaderFile.h:137
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