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