Changeset View
Changeset View
Standalone View
Standalone View
plugins/meson/mesonoptions.cpp
- This file was added.
1 | /* This file is part of KDevelop | ||||
---|---|---|---|---|---|
2 | Copyright 2019 Daniel Mensinger <daniel@mensinger-ka.de> | ||||
3 | | ||||
4 | This library is free software; you can redistribute it and/or | ||||
5 | modify it under the terms of the GNU Library General Public | ||||
6 | License as published by the Free Software Foundation; either | ||||
7 | version 2 of the License, or (at your option) any later version. | ||||
8 | | ||||
9 | This library is distributed in the hope that it will be useful, | ||||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
12 | Library General Public License for more details. | ||||
13 | | ||||
14 | You should have received a copy of the GNU Library General Public License | ||||
15 | along with this library; see the file COPYING.LIB. If not, write to | ||||
16 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||||
17 | Boston, MA 02110-1301, USA. | ||||
18 | */ | ||||
19 | | ||||
20 | #include "mesonoptions.h" | ||||
21 | | ||||
22 | #include <QHash> | ||||
23 | #include <QJsonArray> | ||||
24 | #include <QJsonObject> | ||||
25 | #include <QList> | ||||
26 | #include <QWidget> | ||||
27 | #include <algorithm> | ||||
28 | #include <debug.h> | ||||
29 | #include <vector> | ||||
30 | | ||||
31 | using namespace std; | ||||
32 | | ||||
33 | static const QHash<QString, MesonOptionBase::Section> STRING2SECTION = { | ||||
34 | { QStringLiteral("core"), MesonOptionBase::CORE }, | ||||
35 | { QStringLiteral("backend"), MesonOptionBase::BACKEND }, | ||||
36 | { QStringLiteral("base"), MesonOptionBase::BASE }, | ||||
37 | { QStringLiteral("compiler"), MesonOptionBase::COMPILER }, | ||||
38 | { QStringLiteral("directory"), MesonOptionBase::DIRECTORY }, | ||||
39 | { QStringLiteral("user"), MesonOptionBase::USER }, | ||||
40 | { QStringLiteral("test"), MesonOptionBase::TEST }, | ||||
41 | }; | ||||
42 | | ||||
43 | static const QHash<QString, MesonOptionBase::Type> STRING2TYPE = { | ||||
44 | { QStringLiteral("array"), MesonOptionBase::ARRAY }, { QStringLiteral("boolean"), MesonOptionBase::BOOLEAN }, | ||||
45 | { QStringLiteral("combo"), MesonOptionBase::COMBO }, { QStringLiteral("integer"), MesonOptionBase::INTEGER }, | ||||
46 | { QStringLiteral("string"), MesonOptionBase::STRING }, | ||||
47 | }; | ||||
48 | | ||||
49 | MesonOptions::MesonOptions(QJsonArray const& arr) | ||||
50 | { | ||||
51 | fromJSON(arr); | ||||
52 | } | ||||
53 | | ||||
54 | // Option constructors | ||||
55 | | ||||
56 | MesonOptionBase::MesonOptionBase(QString name, QString description, MesonOptionBase::Section section) | ||||
57 | : m_name(name) | ||||
58 | , m_description(description) | ||||
59 | , m_section(section) | ||||
60 | { | ||||
61 | } | ||||
62 | | ||||
63 | MesonOptionArray::MesonOptionArray(QString name, QString description, MesonOptionBase::Section section, | ||||
64 | QStringList value) | ||||
65 | : MesonOptionBase(name, description, section) | ||||
66 | , m_value(value) | ||||
67 | , m_initialValue(value) | ||||
68 | { | ||||
69 | } | ||||
70 | | ||||
71 | MesonOptionBool::MesonOptionBool(QString name, QString description, MesonOptionBase::Section section, bool value) | ||||
72 | : MesonOptionBase(name, description, section) | ||||
73 | , m_value(value) | ||||
74 | , m_initialValue(value) | ||||
75 | { | ||||
76 | } | ||||
77 | | ||||
78 | MesonOptionCombo::MesonOptionCombo(QString name, QString description, MesonOptionBase::Section section, QString value, | ||||
79 | QStringList choices) | ||||
80 | : MesonOptionBase(name, description, section) | ||||
81 | , m_value(value) | ||||
82 | , m_initialValue(value) | ||||
83 | , m_choices(choices) | ||||
84 | { | ||||
85 | } | ||||
86 | | ||||
87 | MesonOptionInteger::MesonOptionInteger(QString name, QString description, MesonOptionBase::Section section, int value) | ||||
88 | : MesonOptionBase(name, description, section) | ||||
89 | , m_value(value) | ||||
90 | , m_initialValue(value) | ||||
91 | { | ||||
92 | } | ||||
93 | | ||||
94 | MesonOptionString::MesonOptionString(QString name, QString description, MesonOptionBase::Section section, QString value) | ||||
95 | : MesonOptionBase(name, description, section) | ||||
96 | , m_value(value) | ||||
97 | , m_initialValue(value) | ||||
98 | { | ||||
99 | } | ||||
100 | | ||||
101 | QStringList MesonOptionCombo::choices() const | ||||
102 | { | ||||
103 | return m_choices; | ||||
104 | } | ||||
105 | | ||||
106 | // Type functions | ||||
107 | | ||||
108 | MesonOptionBase::Type MesonOptionArray::type() const | ||||
109 | { | ||||
110 | return ARRAY; | ||||
111 | } | ||||
112 | | ||||
113 | MesonOptionBase::Type MesonOptionBool::type() const | ||||
114 | { | ||||
115 | return BOOLEAN; | ||||
116 | } | ||||
117 | | ||||
118 | MesonOptionBase::Type MesonOptionCombo::type() const | ||||
119 | { | ||||
120 | return COMBO; | ||||
121 | } | ||||
122 | | ||||
123 | MesonOptionBase::Type MesonOptionInteger::type() const | ||||
124 | { | ||||
125 | return INTEGER; | ||||
126 | } | ||||
127 | | ||||
128 | MesonOptionBase::Type MesonOptionString::type() const | ||||
129 | { | ||||
130 | return STRING; | ||||
131 | } | ||||
132 | | ||||
133 | // Value functions | ||||
134 | | ||||
135 | QString MesonOptionArray::value() const | ||||
136 | { | ||||
137 | QStringList tmp; | ||||
138 | tmp.reserve(m_value.size()); | ||||
139 | transform(begin(m_value), end(m_value), back_inserter(tmp), | ||||
140 | [](QString const& str) -> QString { return QStringLiteral("'") + str + QStringLiteral("'"); }); | ||||
141 | return QStringLiteral("[") + tmp.join(QStringLiteral(", ")) + QStringLiteral("]"); | ||||
142 | } | ||||
143 | | ||||
144 | QString MesonOptionBool::value() const | ||||
145 | { | ||||
146 | return m_value ? QStringLiteral("true") : QStringLiteral("false"); | ||||
147 | } | ||||
148 | | ||||
149 | QString MesonOptionCombo::value() const | ||||
150 | { | ||||
151 | return m_value; | ||||
152 | } | ||||
153 | | ||||
154 | QString MesonOptionInteger::value() const | ||||
155 | { | ||||
156 | return QString::number(m_value); | ||||
157 | } | ||||
158 | | ||||
159 | QString MesonOptionString::value() const | ||||
160 | { | ||||
161 | return m_value; | ||||
162 | } | ||||
163 | | ||||
164 | // Initial value functions | ||||
165 | | ||||
166 | QString MesonOptionArray::initialValue() const | ||||
167 | { | ||||
168 | QStringList tmp; | ||||
169 | tmp.reserve(m_initialValue.size()); | ||||
170 | transform(begin(m_initialValue), end(m_initialValue), back_inserter(tmp), | ||||
171 | [](QString const& str) -> QString { return QStringLiteral("'") + str + QStringLiteral("'"); }); | ||||
172 | return QStringLiteral("[") + tmp.join(QStringLiteral(", ")) + QStringLiteral("]"); | ||||
173 | } | ||||
174 | | ||||
175 | QString MesonOptionBool::initialValue() const | ||||
176 | { | ||||
177 | return m_initialValue ? QStringLiteral("true") : QStringLiteral("false"); | ||||
178 | } | ||||
179 | | ||||
180 | QString MesonOptionCombo::initialValue() const | ||||
181 | { | ||||
182 | return m_initialValue; | ||||
183 | } | ||||
184 | | ||||
185 | QString MesonOptionInteger::initialValue() const | ||||
186 | { | ||||
187 | return QString::number(m_initialValue); | ||||
188 | } | ||||
189 | | ||||
190 | QString MesonOptionString::initialValue() const | ||||
191 | { | ||||
192 | return m_initialValue; | ||||
193 | } | ||||
194 | | ||||
195 | // Reset functions | ||||
196 | | ||||
197 | void MesonOptionArray::reset() | ||||
198 | { | ||||
199 | m_value = m_initialValue; | ||||
200 | } | ||||
201 | | ||||
202 | void MesonOptionBool::reset() | ||||
203 | { | ||||
204 | m_value = m_initialValue; | ||||
205 | } | ||||
206 | | ||||
207 | void MesonOptionCombo::reset() | ||||
208 | { | ||||
209 | m_value = m_initialValue; | ||||
210 | } | ||||
211 | | ||||
212 | void MesonOptionInteger::reset() | ||||
213 | { | ||||
214 | m_value = m_initialValue; | ||||
215 | } | ||||
216 | | ||||
217 | void MesonOptionString::reset() | ||||
218 | { | ||||
219 | m_value = m_initialValue; | ||||
220 | } | ||||
221 | | ||||
222 | // Raw value functions | ||||
223 | | ||||
224 | QStringList MesonOptionArray::rawValue() const | ||||
225 | { | ||||
226 | return m_value; | ||||
227 | } | ||||
228 | | ||||
229 | bool MesonOptionBool::rawValue() const | ||||
230 | { | ||||
231 | return m_value; | ||||
232 | } | ||||
233 | | ||||
234 | QString MesonOptionCombo::rawValue() const | ||||
235 | { | ||||
236 | return m_value; | ||||
237 | } | ||||
238 | | ||||
239 | int MesonOptionInteger::rawValue() const | ||||
240 | { | ||||
241 | return m_value; | ||||
242 | } | ||||
243 | | ||||
244 | QString MesonOptionString::rawValue() const | ||||
245 | { | ||||
246 | return m_value; | ||||
247 | } | ||||
248 | | ||||
249 | // Set value functions | ||||
250 | | ||||
251 | void MesonOptionArray::setValue(QStringList val) | ||||
252 | { | ||||
253 | m_value = val; | ||||
254 | } | ||||
255 | | ||||
256 | void MesonOptionBool::setValue(bool val) | ||||
257 | { | ||||
258 | m_value = val; | ||||
259 | } | ||||
260 | | ||||
261 | void MesonOptionCombo::setValue(QString val) | ||||
262 | { | ||||
263 | m_value = val; | ||||
264 | } | ||||
265 | | ||||
266 | void MesonOptionInteger::setValue(int val) | ||||
267 | { | ||||
268 | m_value = val; | ||||
269 | } | ||||
270 | | ||||
271 | void MesonOptionString::setValue(QString val) | ||||
272 | { | ||||
273 | m_value = val; | ||||
274 | } | ||||
275 | | ||||
276 | // Base option functions | ||||
277 | | ||||
278 | MesonOptionBase::~MesonOptionBase() {} | ||||
279 | | ||||
280 | QString MesonOptionBase::name() const | ||||
281 | { | ||||
282 | return m_name; | ||||
283 | } | ||||
284 | | ||||
285 | QString MesonOptionBase::description() const | ||||
286 | { | ||||
287 | return m_description; | ||||
288 | } | ||||
289 | | ||||
290 | MesonOptionBase::Section MesonOptionBase::section() const | ||||
291 | { | ||||
292 | return m_section; | ||||
293 | } | ||||
294 | | ||||
295 | QString MesonOptionBase::mesonArg() const | ||||
296 | { | ||||
297 | return QStringLiteral("-D") + m_name + QStringLiteral("=") + value(); | ||||
298 | } | ||||
299 | | ||||
300 | bool MesonOptionBase::isUpdated() const | ||||
301 | { | ||||
302 | return value() != initialValue(); | ||||
303 | } | ||||
304 | | ||||
305 | OPT_PTR MesonOptionBase::fromJSON(const QJsonObject& obj) | ||||
306 | { | ||||
307 | auto nameJV = obj[QStringLiteral("name")]; | ||||
308 | auto descriptionJV = obj[QStringLiteral("description")]; | ||||
309 | auto sectionJV = obj[QStringLiteral("section")]; | ||||
310 | auto typeJV = obj[QStringLiteral("type")]; | ||||
311 | auto valueJV = obj[QStringLiteral("value")]; | ||||
312 | | ||||
313 | // Check all values | ||||
314 | for (auto const& i : { nameJV, descriptionJV, sectionJV, typeJV }) { | ||||
315 | if (!i.isString()) { | ||||
316 | qCWarning(KDEV_Meson) << "OPT: Base type validation failed" << typeJV.toString(); | ||||
317 | return nullptr; | ||||
318 | } | ||||
319 | } | ||||
320 | | ||||
321 | auto sectionIter = STRING2SECTION.find(sectionJV.toString()); | ||||
322 | auto typeIter = STRING2TYPE.find(typeJV.toString()); | ||||
323 | | ||||
324 | if (sectionIter == end(STRING2SECTION) || typeIter == end(STRING2TYPE)) { | ||||
325 | qCWarning(KDEV_Meson) << "OPT: Unknown type or section " << typeJV.toString() << " / " << sectionJV.toString(); | ||||
326 | return nullptr; | ||||
327 | } | ||||
328 | | ||||
329 | Section section = *sectionIter; | ||||
330 | Type type = *typeIter; | ||||
331 | QString name = nameJV.toString(); | ||||
332 | QString description = descriptionJV.toString(); | ||||
333 | | ||||
334 | switch (type) { | ||||
335 | case ARRAY: { | ||||
336 | if (!valueJV.isArray()) { | ||||
337 | return nullptr; | ||||
338 | } | ||||
339 | | ||||
340 | QJsonArray raw = valueJV.toArray(); | ||||
341 | QStringList values; | ||||
342 | values.reserve(raw.size()); | ||||
343 | transform(begin(raw), end(raw), back_inserter(values), [](QJsonValue const& v) { return v.toString(); }); | ||||
344 | return make_shared<MesonOptionArray>(name, description, section, values); | ||||
345 | } | ||||
346 | | ||||
347 | case BOOLEAN: | ||||
348 | if (!valueJV.isBool()) { | ||||
349 | return nullptr; | ||||
350 | } | ||||
351 | return make_shared<MesonOptionBool>(name, description, section, valueJV.toBool()); | ||||
352 | | ||||
353 | case COMBO: { | ||||
354 | auto choicesJV = obj[QStringLiteral("choices")]; | ||||
355 | if (!valueJV.isString() || !choicesJV.isArray()) { | ||||
356 | return nullptr; | ||||
357 | } | ||||
358 | | ||||
359 | QJsonArray raw = choicesJV.toArray(); | ||||
360 | QStringList choices; | ||||
361 | choices.reserve(raw.size()); | ||||
362 | transform(begin(raw), end(raw), back_inserter(choices), [](QJsonValue const& v) { return v.toString(); }); | ||||
363 | return make_shared<MesonOptionCombo>(name, description, section, valueJV.toString(), choices); | ||||
364 | } | ||||
365 | | ||||
366 | case INTEGER: | ||||
367 | if (!valueJV.isDouble()) { | ||||
368 | return nullptr; | ||||
369 | } | ||||
370 | return make_shared<MesonOptionInteger>(name, description, section, valueJV.toInt()); | ||||
371 | | ||||
372 | case STRING: | ||||
373 | if (!valueJV.isString()) { | ||||
374 | return nullptr; | ||||
375 | } | ||||
376 | return make_shared<MesonOptionString>(name, description, section, valueJV.toString()); | ||||
377 | } | ||||
378 | | ||||
379 | qCWarning(KDEV_Meson) << "OPT: Unknown type " << typeJV.toString(); | ||||
380 | return nullptr; | ||||
381 | } | ||||
382 | | ||||
383 | int MesonOptions::numChanged() const | ||||
384 | { | ||||
385 | int sum = 0; | ||||
386 | for(auto i : m_options) { | ||||
387 | if (i && i->isUpdated()) { | ||||
388 | ++sum; | ||||
389 | } | ||||
390 | } | ||||
391 | return sum; | ||||
392 | } | ||||
393 | | ||||
394 | | ||||
395 | QStringList MesonOptions::getMesonArgs() const | ||||
396 | { | ||||
397 | QStringList result; | ||||
398 | result.reserve(m_options.size()); | ||||
399 | | ||||
400 | for(auto i : m_options) { | ||||
401 | if (i && i->isUpdated()) { | ||||
402 | result << i->mesonArg(); | ||||
403 | } | ||||
404 | } | ||||
405 | return result; | ||||
406 | } | ||||
407 | | ||||
408 | void MesonOptions::fromJSON(const QJsonArray& arr) | ||||
409 | { | ||||
410 | m_options.clear(); | ||||
411 | m_options.reserve(arr.size()); | ||||
412 | | ||||
413 | for (QJsonValue const& i : arr) { | ||||
414 | if (!i.isObject()) { | ||||
415 | continue; | ||||
416 | } | ||||
417 | | ||||
418 | auto ptr = MesonOptionBase::fromJSON(i.toObject()); | ||||
419 | if (ptr) { | ||||
420 | m_options += ptr; | ||||
421 | } else { | ||||
422 | qCWarning(KDEV_Meson) << "OPT: Failed to parse " << i.toObject(); | ||||
423 | } | ||||
424 | } | ||||
425 | } | ||||
426 | | ||||
427 | void MesonOptions::print() const | ||||
428 | { | ||||
429 | for (auto const& i : m_options) { | ||||
430 | qCDebug(KDEV_Meson) << i->name() << " = " << i->value() << " [" << i->type() << "] -- " << i->section(); | ||||
431 | } | ||||
432 | } | ||||
433 | | ||||
434 | QVector<OPT_PTR> MesonOptions::options() | ||||
435 | { | ||||
436 | return m_options; | ||||
437 | } |