122bool QQmlDirParser::parse(
const QString &source)
124 quint16 lineNumber = 0;
125 bool firstLine =
true;
127 auto readImport = [&](
const QString *sections,
int sectionCount, Import::Flags flags) {
129 if (sectionCount == 2) {
130 import = Import(sections[1], QTypeRevision(), flags);
131 }
else if (sectionCount == 3) {
132 if (sections[2] == QLatin1String(
"auto")) {
133 import = Import(sections[1], QTypeRevision(), flags | Import::Auto);
135 const auto version = parseVersion(sections[2]);
136 if (version.isValid()) {
137 import = Import(sections[1], version, flags);
139 reportError(lineNumber, 0,
140 QStringLiteral(
"invalid version %1, expected <major>.<minor>")
146 reportError(lineNumber, 0,
147 QStringLiteral(
"%1 requires 1 or 2 arguments, but %2 were provided")
148 .arg(sections[0]).arg(sectionCount - 1));
151 if (sections[0] == QStringLiteral(
"import"))
152 _imports.append(import);
154 _dependencies.append(import);
158 auto readExport = [&](
const QString *sections,
int sectionCount) {
159 if (sectionCount < 2) {
160 reportError(lineNumber, 0,
161 QStringLiteral(
"export at least 1 argument, but none were provided"));
165 const QTypeRevision version = parseVersion(sections[1]);
166 if (!version.isValid()) {
167 reportError(lineNumber, 0,
168 QStringLiteral(
"invalid version %1, expected <major>.<minor>")
173 _exports.append(version);
174 for (
int i = 2; i < sectionCount; ++i) {
176 const int major = parseInt(sections[i], &ok);
178 reportError(lineNumber, 0,
179 QStringLiteral(
"invalid major version %1, expected integer")
186 _exports.append(QTypeRevision::fromVersion(major, 254));
192 auto readPlugin = [&](
const QString *sections,
int sectionCount,
bool isOptional) {
193 if (sectionCount < 2 || sectionCount > 3) {
194 reportError(lineNumber, 0, QStringLiteral(
"plugin directive requires one or two "
195 "arguments, but %1 were provided")
196 .arg(sectionCount - 1));
200 const Plugin entry(sections[1], sections[2], isOptional);
201 _plugins.append(entry);
205 const QChar *ch = source.constData();
206 while (!ch->isNull()) {
209 bool invalidLine =
false;
210 const QChar *lineStart = ch;
213 if (*ch == QLatin1Char(
'\n')) {
221 int sectionCount = 0;
224 if (*ch == QLatin1Char(
'#')) {
229 if (sectionCount >= 4) {
230 reportError(lineNumber, ch - lineStart, QLatin1String(
"unexpected token"));
236 sections[sectionCount++] = (*ch == QLatin1Char(
'"'))
237 ? scanQuotedWord(ch, lineNumber, ch - lineStart)
241 }
while (*ch != QLatin1Char(
'\n') && !ch->isNull());
247 reportError(lineNumber, 0,
248 QStringLiteral(
"invalid qmldir directive contains too many tokens"));
250 }
else if (sectionCount == 0) {
253 }
else if (sections[0] == QLatin1String(
"module")) {
254 if (sectionCount != 2) {
255 reportError(lineNumber, 0,
256 QStringLiteral(
"module identifier directive requires one argument, but %1 were provided").arg(sectionCount - 1));
259 if (!_typeNamespace.isEmpty()) {
260 reportError(lineNumber, 0,
261 QStringLiteral(
"only one module identifier directive may be defined in a qmldir file"));
265 reportError(lineNumber, 0,
266 QStringLiteral(
"module identifier directive must be the first directive in a qmldir file"));
270 _typeNamespace = sections[1];
272 }
else if (sections[0] == QLatin1String(
"plugin")) {
273 if (!readPlugin(sections, sectionCount,
false))
275 }
else if (sections[0] == QLatin1String(
"optional")) {
276 if (sectionCount < 2) {
277 reportError(lineNumber, 0, QStringLiteral(
"optional directive requires further "
278 "arguments, but none were provided."));
282 if (sections[1] == QStringLiteral(
"plugin")) {
283 if (!readPlugin(sections + 1, sectionCount - 1,
true))
285 }
else if (sections[1] == QLatin1String(
"import")) {
286 if (!readImport(sections + 1, sectionCount - 1, Import::Optional))
289 reportError(lineNumber, 0, QStringLiteral(
"only import and plugin can be optional, "
290 "not %1.").arg(sections[1]));
293 }
else if (sections[0] == QLatin1String(
"default")) {
294 if (sectionCount < 2) {
295 reportError(lineNumber, 0,
296 QStringLiteral(
"default directive requires further "
297 "arguments, but none were provided."));
300 if (sections[1] == QLatin1String(
"import")) {
301 if (!readImport(sections + 1, sectionCount - 1,
302 Import::Flags({ Import::Optional, Import::OptionalDefault })))
305 reportError(lineNumber, 0,
306 QStringLiteral(
"only optional imports can have a default, "
310 }
else if (sections[0] == QLatin1String(
"classname")) {
311 if (sectionCount < 2) {
312 reportError(lineNumber, 0,
313 QStringLiteral(
"classname directive requires an argument, but %1 were provided").arg(sectionCount - 1));
318 _classNames.append(sections[1]);
320 }
else if (sections[0] == QLatin1String(
"internal")) {
321 if (sectionCount == 3) {
322 Component entry(sections[1], sections[2], QTypeRevision());
323 entry.internal =
true;
324 _components.insert(entry.typeName, entry);
325 }
else if (sectionCount == 4) {
326 const QTypeRevision version = parseVersion(sections[2]);
327 if (version.isValid()) {
328 Component entry(sections[1], sections[3], version);
329 entry.internal =
true;
330 _components.insert(entry.typeName, entry);
332 reportError(lineNumber, 0,
333 QStringLiteral(
"invalid version %1, expected <major>.<minor>")
338 reportError(lineNumber, 0,
339 QStringLiteral(
"internal types require 2 or 3 arguments, "
340 "but %1 were provided").arg(sectionCount - 1));
343 }
else if (sections[0] == QLatin1String(
"singleton")) {
344 if (sectionCount < 3 || sectionCount > 4) {
345 reportError(lineNumber, 0,
346 QStringLiteral(
"singleton types require 2 or 3 arguments, but %1 were provided").arg(sectionCount - 1));
348 }
else if (sectionCount == 3) {
351 Component entry(sections[1], sections[2], QTypeRevision());
352 entry.singleton =
true;
353 _components.insert(entry.typeName, entry);
357 const QTypeRevision version = parseVersion(sections[2]);
358 if (version.isValid()) {
359 const QString &fileName = sections[3];
360 Component entry(sections[1], fileName, version);
361 entry.singleton =
true;
362 _components.insert(entry.typeName, entry);
364 reportError(lineNumber, 0, QStringLiteral(
"invalid version %1, expected <major>.<minor>").arg(sections[2]));
367 }
else if (sections[0] == QLatin1String(
"typeinfo")) {
368 if (sectionCount != 2) {
369 reportError(lineNumber, 0,
370 QStringLiteral(
"typeinfo requires 1 argument, but %1 were provided").arg(sectionCount - 1));
373 _typeInfos.append(sections[1]);
374 }
else if (sections[0] == QLatin1String(
"designersupported")) {
375 if (sectionCount != 1)
376 reportError(lineNumber, 0, QStringLiteral(
"designersupported does not expect any argument"));
378 _designerSupported =
true;
379 }
else if (sections[0] == QLatin1String(
"static")) {
380 if (sectionCount != 1)
381 reportError(lineNumber, 0, QStringLiteral(
"static does not expect any argument"));
383 _isStaticModule =
true;
384 }
else if (sections[0] == QLatin1String(
"system")) {
385 if (sectionCount != 1)
386 reportError(lineNumber, 0, QStringLiteral(
"system does not expect any argument"));
388 _isSystemModule =
true;
389 }
else if (sections[0] == QLatin1String(
"import")
390 || sections[0] == QLatin1String(
"depends")) {
391 if (!readImport(sections, sectionCount, Import::Default))
393 }
else if (sections[0] == QLatin1String(
"export")) {
394 if (!readExport(sections, sectionCount))
396 }
else if (sections[0] == QLatin1String(
"prefer")) {
397 if (sectionCount < 2) {
398 reportError(lineNumber, 0,
399 QStringLiteral(
"prefer directive requires one argument, "
400 "but %1 were provided").arg(sectionCount - 1));
404 if (!_preferredPath.isEmpty()) {
405 reportError(lineNumber, 0, QStringLiteral(
406 "only one prefer directive may be defined in a qmldir file"));
410 if (!sections[1].endsWith(u'/')) {
412 reportError(lineNumber, 0, QStringLiteral(
413 "the preferred directory has to end with a '/'"));
417 _preferredPath = sections[1];
418 }
else if (sections[0] == QLatin1String(
"linktarget")) {
419 if (sectionCount < 2) {
420 reportError(lineNumber, 0,
421 QStringLiteral(
"linktarget directive requires an argument, "
422 "but %1 were provided")
423 .arg(sectionCount - 1));
427 if (!_linkTarget.isEmpty()) {
431 "only one linktarget directive may be defined in a qmldir file"));
435 _linkTarget = sections[1];
436 }
else if (sectionCount == 2) {
438 insertComponentOrScript(sections[0], sections[1], QTypeRevision());
439 }
else if (sectionCount == 3) {
440 const QTypeRevision version = parseVersion(sections[1]);
441 if (version.isValid()) {
442 insertComponentOrScript(sections[0], sections[2], version);
446 QStringLiteral(
"invalid version %1, expected <major>.<minor>")
450 reportError(lineNumber, 0,
451 QStringLiteral(
"a component declaration requires two or three arguments, but %1 were provided").arg(sectionCount));