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.compileCommands = stringValue(obj,
"compileCommands"_L1);
134 result.codec = stringValue(obj,
"codec"_L1);
135 result.excluded = wildcardsToRegExes(stringListValue(obj,
"excluded"_L1));
136 result.includePaths = stringListValue(obj,
"includePaths"_L1);
137 result.sources = stringListValue(obj,
"sources"_L1);
138 if (obj.contains(
"translations"_L1))
139 result.translations = stringListValue(obj,
"translations"_L1);
140 result.subProjects = convertProjects(obj.value(
"subProjects"_L1).toArray());
144 bool checkType(
const QJsonValue &v, QJsonValue::Type t,
const QString &key)
148 m_errorString = FMT::tr(
"Key %1 should be %2 but is %3.").arg(key, jsonTypeName(t),
149 jsonTypeName(v.type()));
153 static QString jsonTypeName(QJsonValue::Type t)
157 case QJsonValue::Null:
158 return QStringLiteral(
"null");
159 case QJsonValue::Bool:
160 return QStringLiteral(
"bool");
161 case QJsonValue::Double:
162 return QStringLiteral(
"double");
163 case QJsonValue::String:
164 return QStringLiteral(
"string");
165 case QJsonValue::Array:
166 return QStringLiteral(
"array");
167 case QJsonValue::Object:
168 return QStringLiteral(
"object");
169 case QJsonValue::Undefined:
170 return QStringLiteral(
"undefined");
172 return QStringLiteral(
"unknown");
175 static QVector<QRegularExpression> wildcardsToRegExes(
const QStringList &wildcardPatterns)
177 QVector<QRegularExpression> result;
178 result.reserve(wildcardPatterns.size());
179 for (
const QString &wildcardPattern : wildcardPatterns)
180 result.append(wildcardToRegEx(wildcardPattern));
187 static QRegularExpression wildcardToRegEx(
const QString &wildcardPattern)
189 return QRegularExpression(
191 + QRegularExpression::wildcardToRegularExpression(
193 QRegularExpression::UnanchoredWildcardConversion));
196 QString stringValue(
const QJsonObject &obj,
const QString &key)
198 if (!m_errorString.isEmpty())
200 QJsonValue v = obj.value(key);
203 if (!checkType(v, QJsonValue::String, key))
208 QStringList stringListValue(
const QJsonObject &obj,
const QString &key)
210 if (!m_errorString.isEmpty())
212 QJsonValue v = obj.value(key);
215 if (!checkType(v, QJsonValue::Array, key))
217 return toStringList(v, key);
220 QStringList toStringList(
const QJsonValue &v,
const QString &key)
223 const QJsonArray a = v.toArray();
224 result.reserve(a.count());
225 for (
const QJsonValue v : a) {
227 m_errorString = FMT::tr(
"Unexpected type %1 in string array in key %2.")
228 .arg(jsonTypeName(v.type()), key);
231 result.append(v.toString());
236 QString &m_errorString;
241 const QJsonArray rawProjects = readRawProjectDescription(filePath, errorString);
242 if (!errorString->isEmpty())
245 Projects result = converter.convertProjects(rawProjects);
246 if (!errorString->isEmpty())