/src/CMake/Source/cmFileAPI.h
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file LICENSE.rst or https://cmake.org/licensing for details. */ |
3 | | #pragma once |
4 | | |
5 | | #include "cmConfigure.h" // IWYU pragma: keep |
6 | | |
7 | | #include <map> |
8 | | #include <memory> |
9 | | #include <string> |
10 | | #include <unordered_set> |
11 | | #include <vector> |
12 | | |
13 | | #include <cm3p/json/reader.h> |
14 | | #include <cm3p/json/value.h> |
15 | | #include <cm3p/json/writer.h> |
16 | | |
17 | | class cmake; |
18 | | |
19 | | class cmFileAPI |
20 | | { |
21 | | public: |
22 | | cmFileAPI(cmake* cm); |
23 | | |
24 | | /** Read fileapi queries from disk. */ |
25 | | void ReadQueries(); |
26 | | |
27 | | /** Get the list of configureLog object kind versions requested. */ |
28 | | std::vector<unsigned int> GetConfigureLogVersions(); |
29 | | |
30 | | /** Identify the situation in which WriteReplies is called. */ |
31 | | enum class IndexFor |
32 | | { |
33 | | Success, |
34 | | FailedConfigure, |
35 | | FailedCompute, |
36 | | FailedGenerate, |
37 | | }; |
38 | | |
39 | | /** Write fileapi replies to disk. */ |
40 | | void WriteReplies(IndexFor indexFor); |
41 | | |
42 | | /** Get the "cmake" instance with which this was constructed. */ |
43 | 0 | cmake* GetCMakeInstance() const { return this->CMakeInstance; } |
44 | | |
45 | | /** Convert a JSON object or array into an object with a single |
46 | | "jsonFile" member specifying a file named with the given prefix |
47 | | and holding the original object. Other JSON types are unchanged. */ |
48 | | Json::Value MaybeJsonFile(Json::Value in, std::string const& prefix); |
49 | | |
50 | | /** Report file-api capabilities for cmake -E capabilities. */ |
51 | | static Json::Value ReportCapabilities(); |
52 | | |
53 | | // Keep in sync with ObjectKindName. |
54 | | enum class ObjectKind |
55 | | { |
56 | | CodeModel, |
57 | | ConfigureLog, |
58 | | Cache, |
59 | | CMakeFiles, |
60 | | Toolchains, |
61 | | InternalTest |
62 | | }; |
63 | | |
64 | | bool AddProjectQuery(ObjectKind kind, unsigned majorVersion, |
65 | | unsigned minorVersion); |
66 | | |
67 | | /** Build a JSON object with major and minor fields. */ |
68 | | static Json::Value BuildVersion(unsigned int major, unsigned int minor); |
69 | | |
70 | | private: |
71 | | cmake* CMakeInstance; |
72 | | |
73 | | /** The api/v1 directory location. */ |
74 | | std::string APIv1; |
75 | | |
76 | | /** api/v1 directory in the user's shared CMake config directory. */ |
77 | | std::string UserAPIv1; |
78 | | |
79 | | /** The set of files we have just written to the reply directory. */ |
80 | | std::unordered_set<std::string> ReplyFiles; |
81 | | |
82 | | static std::vector<std::string> LoadDir(std::string const& dir); |
83 | | void RemoveOldReplyFiles(); |
84 | | |
85 | | /** Identify one object kind and major version. */ |
86 | | struct Object |
87 | | { |
88 | | ObjectKind Kind; |
89 | | unsigned int Version = 0; |
90 | | friend bool operator<(Object l, Object r) |
91 | 0 | { |
92 | 0 | if (l.Kind != r.Kind) { |
93 | 0 | return l.Kind < r.Kind; |
94 | 0 | } |
95 | 0 | return l.Version < r.Version; |
96 | 0 | } |
97 | | friend bool operator==(Object l, Object r) |
98 | 0 | { |
99 | 0 | return l.Kind == r.Kind && l.Version == r.Version; |
100 | 0 | } |
101 | 0 | friend bool operator!=(Object l, Object r) { return !(l == r); } |
102 | | }; |
103 | | |
104 | | /** Represent content of a query directory. */ |
105 | | struct Query |
106 | | { |
107 | | /** Known object kind-version pairs. */ |
108 | | std::vector<Object> Known; |
109 | | /** Unknown object kind names. */ |
110 | | std::vector<std::string> Unknown; |
111 | | }; |
112 | | |
113 | | /** Represent one request in a client 'query.json'. */ |
114 | | struct ClientRequest : public Object |
115 | | { |
116 | | /** Empty if request is valid, else the error string. */ |
117 | | std::string Error; |
118 | | }; |
119 | | |
120 | | /** Represent the "requests" in a client 'query.json'. */ |
121 | | struct ClientRequests : public std::vector<ClientRequest> |
122 | | { |
123 | | /** Empty if requests field is valid, else the error string. */ |
124 | | std::string Error; |
125 | | }; |
126 | | |
127 | | /** Represent the content of a client query.json file. */ |
128 | | struct ClientQueryJson |
129 | | { |
130 | | /** The error string if parsing failed, else empty. */ |
131 | | std::string Error; |
132 | | |
133 | | /** The 'query.json' object "client" member if it exists, else null. */ |
134 | | Json::Value ClientValue; |
135 | | |
136 | | /** The 'query.json' object "requests" member if it exists, else null. */ |
137 | | Json::Value RequestsValue; |
138 | | |
139 | | /** Requests extracted from 'query.json'. */ |
140 | | ClientRequests Requests; |
141 | | }; |
142 | | |
143 | | /** Represent content of a client query directory. */ |
144 | | struct ClientQuery |
145 | | { |
146 | | /** The content of the client query directory except 'query.json'. */ |
147 | | Query DirQuery; |
148 | | |
149 | | /** True if 'query.json' exists. */ |
150 | | bool HaveQueryJson = false; |
151 | | |
152 | | /** The 'query.json' content. */ |
153 | | ClientQueryJson QueryJson; |
154 | | }; |
155 | | |
156 | | /** Whether the top-level query directory exists at all. */ |
157 | | bool QueryExists = false; |
158 | | |
159 | | /** The content of the top-level query directory. */ |
160 | | Query TopQuery; |
161 | | |
162 | | /** The content of each "client-$client" query directory. */ |
163 | | std::map<std::string, ClientQuery> ClientQueries; |
164 | | |
165 | | /** Reply index object generated for object kind/version. |
166 | | This populates the "objects" field of the reply index. */ |
167 | | std::map<Object, Json::Value> ReplyIndexObjects; |
168 | | |
169 | | /** Identify the situation in which WriteReplies was called. */ |
170 | | IndexFor ReplyIndexFor = IndexFor::Success; |
171 | | |
172 | | std::unique_ptr<Json::CharReader> JsonReader; |
173 | | std::unique_ptr<Json::StreamWriter> JsonWriter; |
174 | | |
175 | | bool ReadJsonFile(std::string const& file, Json::Value& value, |
176 | | std::string& error); |
177 | | |
178 | | std::string WriteJsonFile( |
179 | | Json::Value const& value, std::string const& prefix, |
180 | | std::string (*computeSuffix)(std::string const&) = ComputeSuffixHash); |
181 | | static std::string ComputeSuffixHash(std::string const&); |
182 | | static std::string ComputeSuffixTime(std::string const&); |
183 | | |
184 | | static bool ReadQuery(std::string const& query, |
185 | | std::vector<Object>& objects); |
186 | | void ReadClient(std::string const& client); |
187 | | void ReadClientQuery(std::string const& client, ClientQueryJson& q); |
188 | | |
189 | | Json::Value BuildReplyIndex(); |
190 | | Json::Value BuildCMake(); |
191 | | Json::Value BuildReply(Query const& q); |
192 | | Json::Value BuildReplyEntry(Object object); |
193 | | static Json::Value BuildReplyError(std::string const& error); |
194 | | Json::Value const& AddReplyIndexObject(Object o); |
195 | | |
196 | | static char const* ObjectKindName(ObjectKind kind); |
197 | | static std::string ObjectName(Object o); |
198 | | |
199 | | Json::Value BuildObject(Object object); |
200 | | |
201 | | ClientRequests BuildClientRequests(Json::Value const& requests); |
202 | | ClientRequest BuildClientRequest(Json::Value const& request); |
203 | | Json::Value BuildClientReply(ClientQuery const& q); |
204 | | Json::Value BuildClientReplyResponses(ClientRequests const& requests); |
205 | | Json::Value BuildClientReplyResponse(ClientRequest const& request); |
206 | | |
207 | | struct RequestVersion |
208 | | { |
209 | | unsigned int Major = 0; |
210 | | unsigned int Minor = 0; |
211 | | }; |
212 | | static bool ReadRequestVersions(Json::Value const& version, |
213 | | std::vector<RequestVersion>& versions, |
214 | | std::string& error); |
215 | | static bool ReadRequestVersion(Json::Value const& version, bool inArray, |
216 | | std::vector<RequestVersion>& result, |
217 | | std::string& error); |
218 | | static std::string NoSupportedVersion( |
219 | | std::vector<RequestVersion> const& versions); |
220 | | |
221 | | void BuildClientRequestCodeModel( |
222 | | ClientRequest& r, std::vector<RequestVersion> const& versions); |
223 | | Json::Value BuildCodeModel(Object object); |
224 | | |
225 | | void BuildClientRequestConfigureLog( |
226 | | ClientRequest& r, std::vector<RequestVersion> const& versions); |
227 | | Json::Value BuildConfigureLog(Object object); |
228 | | |
229 | | void BuildClientRequestCache(ClientRequest& r, |
230 | | std::vector<RequestVersion> const& versions); |
231 | | Json::Value BuildCache(Object object); |
232 | | |
233 | | void BuildClientRequestCMakeFiles( |
234 | | ClientRequest& r, std::vector<RequestVersion> const& versions); |
235 | | Json::Value BuildCMakeFiles(Object object); |
236 | | |
237 | | void BuildClientRequestToolchains( |
238 | | ClientRequest& r, std::vector<RequestVersion> const& versions); |
239 | | Json::Value BuildToolchains(Object object); |
240 | | |
241 | | void BuildClientRequestInternalTest( |
242 | | ClientRequest& r, std::vector<RequestVersion> const& versions); |
243 | | Json::Value BuildInternalTest(Object object); |
244 | | }; |