84 if (!file.open(QIODevice::ReadOnly)) {
85 *errorString = FMT::tr(
"Cannot open project description file '%1'.\n")
89 QJsonParseError parseError;
90 QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &parseError);
92 *errorString = FMT::tr(
"%1 in %2 at offset %3.\n")
93 .arg(parseError.errorString(), filePath)
94 .arg(parseError.offset);
97 QJsonArray result = doc.isArray() ? doc.array() : QJsonArray{doc.object()};
99 if (!validator.isValidProjectDescription(result))
115 result.reserve(rawProjects.size());
116 for (
const QJsonValue &rawProject : rawProjects) {
117 Project project = convertProject(rawProject);
118 if (!m_errorString.isEmpty())
120 result.push_back(std::move(project));
126 Project convertProject(
const QJsonValue &v)
131 QJsonObject obj = v.toObject();
132 result.filePath = stringValue(obj,
"projectFile"_L1);
133 result.codec = stringValue(obj,
"codec"_L1);
134 result.excluded = wildcardsToRegExes(stringListValue(obj,
"excluded"_L1));
135 result.includePaths = stringListValue(obj,
"includePaths"_L1);
136 result.sources = stringListValue(obj,
"sources"_L1);
137 if (obj.contains(
"translations"_L1))
138 result.translations = stringListValue(obj,
"translations"_L1);
139 result.subProjects = convertProjects(obj.value(
"subProjects"_L1).toArray());
143 bool checkType(
const QJsonValue &v, QJsonValue::Type t,
const QString &key)
147 m_errorString = FMT::tr(
"Key %1 should be %2 but is %3.").arg(key, jsonTypeName(t),
148 jsonTypeName(v.type()));
152 static QString jsonTypeName(QJsonValue::Type t)
156 case QJsonValue::Null:
157 return QStringLiteral(
"null");
158 case QJsonValue::Bool:
159 return QStringLiteral(
"bool");
160 case QJsonValue::Double:
161 return QStringLiteral(
"double");
162 case QJsonValue::String:
163 return QStringLiteral(
"string");
164 case QJsonValue::Array:
165 return QStringLiteral(
"array");
166 case QJsonValue::Object:
167 return QStringLiteral(
"object");
168 case QJsonValue::Undefined:
169 return QStringLiteral(
"undefined");
171 return QStringLiteral(
"unknown");
174 static QVector<QRegularExpression> wildcardsToRegExes(
const QStringList &wildcardPatterns)
176 QVector<QRegularExpression> result;
177 result.reserve(wildcardPatterns.size());
178 for (
const QString &wildcardPattern : wildcardPatterns)
179 result.append(wildcardToRegEx(wildcardPattern));
186 static QRegularExpression wildcardToRegEx(
const QString &wildcardPattern)
188 return QRegularExpression(
190 + QRegularExpression::wildcardToRegularExpression(
192 QRegularExpression::UnanchoredWildcardConversion));
195 QString stringValue(
const QJsonObject &obj,
const QString &key)
197 if (!m_errorString.isEmpty())
199 QJsonValue v = obj.value(key);
202 if (!checkType(v, QJsonValue::String, key))
207 QStringList stringListValue(
const QJsonObject &obj,
const QString &key)
209 if (!m_errorString.isEmpty())
211 QJsonValue v = obj.value(key);
214 if (!checkType(v, QJsonValue::Array, key))
216 return toStringList(v, key);
219 QStringList toStringList(
const QJsonValue &v,
const QString &key)
222 const QJsonArray a = v.toArray();
223 result.reserve(a.count());
224 for (
const QJsonValue &v : a) {
226 m_errorString = FMT::tr(
"Unexpected type %1 in string array in key %2.")
227 .arg(jsonTypeName(v.type()), key);
230 result.append(v.toString());
235 QString &m_errorString;
240Projects projectDescriptionFromFile(
const QString &filePath, QString *errorString)
242 const QJsonArray rawProjects = readRawProjectDescription(filePath, errorString);
243 if (!errorString->isEmpty())
245 ProjectConverter converter(errorString);
246 Projects result = converter.convertProjects(rawProjects);
247 if (!errorString->isEmpty())