121bool QQmlDirParser::parse(
const QString &source)
123 quint16 lineNumber = 0;
124 bool firstLine =
true;
126 auto readImport = [&](
const QString *sections,
int sectionCount, Import::Flags flags) {
128 if (sectionCount == 2) {
129 import = Import(sections[1], QTypeRevision(), flags);
130 }
else if (sectionCount == 3) {
131 if (sections[2] == QLatin1String(
"auto")) {
132 import = Import(sections[1], QTypeRevision(), flags | Import::Auto);
134 const auto version = parseVersion(sections[2]);
135 if (version.isValid()) {
136 import = Import(sections[1], version, flags);
138 reportError(lineNumber, 0,
139 QStringLiteral(
"invalid version %1, expected <major>.<minor>")
145 reportError(lineNumber, 0,
146 QStringLiteral(
"%1 requires 1 or 2 arguments, but %2 were provided")
147 .arg(sections[0]).arg(sectionCount - 1));
150 if (sections[0] == QStringLiteral(
"import"))
151 _imports.append(import);
153 _dependencies.append(import);
157 auto readPlugin = [&](
const QString *sections,
int sectionCount,
bool isOptional) {
158 if (sectionCount < 2 || sectionCount > 3) {
159 reportError(lineNumber, 0, QStringLiteral(
"plugin directive requires one or two "
160 "arguments, but %1 were provided")
161 .arg(sectionCount - 1));
165 const Plugin entry(sections[1], sections[2], isOptional);
166 _plugins.append(entry);
170 const QChar *ch = source.constData();
171 while (!ch->isNull()) {
174 bool invalidLine =
false;
175 const QChar *lineStart = ch;
178 if (*ch == QLatin1Char(
'\n')) {
186 int sectionCount = 0;
189 if (*ch == QLatin1Char(
'#')) {
194 if (sectionCount >= 4) {
195 reportError(lineNumber, ch - lineStart, QLatin1String(
"unexpected token"));
201 sections[sectionCount++] = (*ch == QLatin1Char(
'"'))
202 ? scanQuotedWord(ch, lineNumber, ch - lineStart)
206 }
while (*ch != QLatin1Char(
'\n') && !ch->isNull());
212 reportError(lineNumber, 0,
213 QStringLiteral(
"invalid qmldir directive contains too many tokens"));
215 }
else if (sectionCount == 0) {
218 }
else if (sections[0] == QLatin1String(
"module")) {
219 if (sectionCount != 2) {
220 reportError(lineNumber, 0,
221 QStringLiteral(
"module identifier directive requires one argument, but %1 were provided").arg(sectionCount - 1));
224 if (!_typeNamespace.isEmpty()) {
225 reportError(lineNumber, 0,
226 QStringLiteral(
"only one module identifier directive may be defined in a qmldir file"));
230 reportError(lineNumber, 0,
231 QStringLiteral(
"module identifier directive must be the first directive in a qmldir file"));
235 _typeNamespace = sections[1];
237 }
else if (sections[0] == QLatin1String(
"plugin")) {
238 if (!readPlugin(sections, sectionCount,
false))
240 }
else if (sections[0] == QLatin1String(
"optional")) {
241 if (sectionCount < 2) {
242 reportError(lineNumber, 0, QStringLiteral(
"optional directive requires further "
243 "arguments, but none were provided."));
247 if (sections[1] == QStringLiteral(
"plugin")) {
248 if (!readPlugin(sections + 1, sectionCount - 1,
true))
250 }
else if (sections[1] == QLatin1String(
"import")) {
251 if (!readImport(sections + 1, sectionCount - 1, Import::Optional))
254 reportError(lineNumber, 0, QStringLiteral(
"only import and plugin can be optional, "
255 "not %1.").arg(sections[1]));
258 }
else if (sections[0] == QLatin1String(
"default")) {
259 if (sectionCount < 2) {
260 reportError(lineNumber, 0,
261 QStringLiteral(
"default directive requires further "
262 "arguments, but none were provided."));
265 if (sections[1] == QLatin1String(
"import")) {
266 if (!readImport(sections + 1, sectionCount - 1,
267 Import::Flags({ Import::Optional, Import::OptionalDefault })))
270 reportError(lineNumber, 0,
271 QStringLiteral(
"only optional imports can have a default, "
275 }
else if (sections[0] == QLatin1String(
"classname")) {
276 if (sectionCount < 2) {
277 reportError(lineNumber, 0,
278 QStringLiteral(
"classname directive requires an argument, but %1 were provided").arg(sectionCount - 1));
283 _classNames.append(sections[1]);
285 }
else if (sections[0] == QLatin1String(
"internal")) {
286 if (sectionCount == 3) {
287 Component entry(sections[1], sections[2], QTypeRevision());
288 entry.internal =
true;
289 _components.insert(entry.typeName, entry);
290 }
else if (sectionCount == 4) {
291 const QTypeRevision version = parseVersion(sections[2]);
292 if (version.isValid()) {
293 Component entry(sections[1], sections[3], version);
294 entry.internal =
true;
295 _components.insert(entry.typeName, entry);
297 reportError(lineNumber, 0,
298 QStringLiteral(
"invalid version %1, expected <major>.<minor>")
303 reportError(lineNumber, 0,
304 QStringLiteral(
"internal types require 2 or 3 arguments, "
305 "but %1 were provided").arg(sectionCount - 1));
308 }
else if (sections[0] == QLatin1String(
"singleton")) {
309 if (sectionCount < 3 || sectionCount > 4) {
310 reportError(lineNumber, 0,
311 QStringLiteral(
"singleton types require 2 or 3 arguments, but %1 were provided").arg(sectionCount - 1));
313 }
else if (sectionCount == 3) {
316 Component entry(sections[1], sections[2], QTypeRevision());
317 entry.singleton =
true;
318 _components.insert(entry.typeName, entry);
322 const QTypeRevision version = parseVersion(sections[2]);
323 if (version.isValid()) {
324 const QString &fileName = sections[3];
325 Component entry(sections[1], fileName, version);
326 entry.singleton =
true;
327 _components.insert(entry.typeName, entry);
329 reportError(lineNumber, 0, QStringLiteral(
"invalid version %1, expected <major>.<minor>").arg(sections[2]));
332 }
else if (sections[0] == QLatin1String(
"typeinfo")) {
333 if (sectionCount != 2) {
334 reportError(lineNumber, 0,
335 QStringLiteral(
"typeinfo requires 1 argument, but %1 were provided").arg(sectionCount - 1));
338 _typeInfos.append(sections[1]);
339 }
else if (sections[0] == QLatin1String(
"designersupported")) {
340 if (sectionCount != 1)
341 reportError(lineNumber, 0, QStringLiteral(
"designersupported does not expect any argument"));
343 _designerSupported =
true;
344 }
else if (sections[0] == QLatin1String(
"static")) {
345 if (sectionCount != 1)
346 reportError(lineNumber, 0, QStringLiteral(
"static does not expect any argument"));
348 _isStaticModule =
true;
349 }
else if (sections[0] == QLatin1String(
"system")) {
350 if (sectionCount != 1)
351 reportError(lineNumber, 0, QStringLiteral(
"system does not expect any argument"));
353 _isSystemModule =
true;
354 }
else if (sections[0] == QLatin1String(
"import")
355 || sections[0] == QLatin1String(
"depends")) {
356 if (!readImport(sections, sectionCount, Import::Default))
358 }
else if (sections[0] == QLatin1String(
"prefer")) {
359 if (sectionCount < 2) {
360 reportError(lineNumber, 0,
361 QStringLiteral(
"prefer directive requires one argument, "
362 "but %1 were provided").arg(sectionCount - 1));
366 if (!_preferredPath.isEmpty()) {
367 reportError(lineNumber, 0, QStringLiteral(
368 "only one prefer directive may be defined in a qmldir file"));
372 if (!sections[1].endsWith(u'/')) {
374 reportError(lineNumber, 0, QStringLiteral(
375 "the preferred directory has to end with a '/'"));
379 _preferredPath = sections[1];
380 }
else if (sections[0] == QLatin1String(
"linktarget")) {
381 if (sectionCount < 2) {
382 reportError(lineNumber, 0,
383 QStringLiteral(
"linktarget directive requires an argument, "
384 "but %1 were provided")
385 .arg(sectionCount - 1));
389 if (!_linkTarget.isEmpty()) {
393 "only one linktarget directive may be defined in a qmldir file"));
397 _linkTarget = sections[1];
398 }
else if (sectionCount == 2) {
400 insertComponentOrScript(sections[0], sections[1], QTypeRevision());
401 }
else if (sectionCount == 3) {
402 const QTypeRevision version = parseVersion(sections[1]);
403 if (version.isValid()) {
404 insertComponentOrScript(sections[0], sections[2], version);
408 QStringLiteral(
"invalid version %1, expected <major>.<minor>")
412 reportError(lineNumber, 0,
413 QStringLiteral(
"a component declaration requires two or three arguments, but %1 were provided").arg(sectionCount));