aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmltypeloader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/qqmltypeloader.cpp')
-rw-r--r--src/qml/qml/qqmltypeloader.cpp212
1 files changed, 171 insertions, 41 deletions
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 27230cd669..842eb53a3b 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -1172,7 +1172,7 @@ void QQmlDataLoader::shutdownThread()
}
QQmlTypeLoader::Blob::Blob(const QUrl &url, QQmlDataBlob::Type type, QQmlTypeLoader *loader)
-: QQmlDataBlob(url, type), m_typeLoader(loader), m_imports(loader)
+ : QQmlDataBlob(url, type), m_typeLoader(loader), m_imports(loader), m_isSingleton(false)
{
}
@@ -1336,6 +1336,51 @@ bool QQmlTypeLoader::Blob::addImport(const QQmlScript::Import &import, QList<QQm
return true;
}
+bool QQmlTypeLoader::Blob::addPragma(const QQmlScript::Pragma &pragma, QList<QQmlError> *errors)
+{
+ Q_ASSERT(errors);
+
+ if (pragma.type == QQmlScript::Pragma::Singleton) {
+ QUrl myUrl = url();
+
+ QQmlType *ret = QQmlMetaType::qmlType(myUrl, true);
+ if (!ret) {
+ QQmlError error;
+ error.setDescription(QQmlTypeLoader::tr("No matching type found, pragma Singleton files cannot be used by QQmlComponent."));
+ error.setUrl(myUrl);
+ error.setLine(pragma.location.start.line);
+ error.setColumn(pragma.location.start.column);
+ errors->prepend(error);
+ return false;
+ }
+
+ if (!ret->isCompositeSingleton()) {
+ QQmlError error;
+ error.setDescription(QQmlTypeLoader::tr("pragma Singleton used with a non composite singleton type %1").arg(ret->qmlTypeName()));
+ error.setUrl(myUrl);
+ error.setLine(pragma.location.start.line);
+ error.setColumn(pragma.location.start.column);
+ errors->prepend(error);
+ return false;
+ }
+ // This flag is used for error checking when a qmldir file marks a type as
+ // composite singleton, but there is no pragma Singleton defined in QML.
+ m_isSingleton = true;
+ } else {
+ QQmlError error;
+ error.setDescription(QLatin1String("Invalid pragma"));
+ error.setUrl(url());
+ error.setLine(pragma.location.start.line);
+ error.setColumn(pragma.location.start.column);
+ errors->prepend(error);
+ return false;
+ }
+
+ return true;
+}
+
+
+
void QQmlTypeLoader::Blob::dependencyError(QQmlDataBlob *blob)
{
if (blob->type() == QQmlDataBlob::QmldirFile) {
@@ -1941,6 +1986,11 @@ const QSet<QString> &QQmlTypeData::namespaces() const
return m_namespaces;
}
+const QList<QQmlTypeData::TypeReference> &QQmlTypeData::compositeSingletons() const
+{
+ return m_compositeSingletons;
+}
+
QQmlCompiledData *QQmlTypeData::compiledData() const
{
return m_compiledData;
@@ -2015,6 +2065,36 @@ void QQmlTypeData::done()
}
// ---
+ // Check all composite singleton type dependencies for errors
+ for (int ii = 0; !isError() && ii < m_compositeSingletons.count(); ++ii) {
+ const TypeReference &type = m_compositeSingletons.at(ii);
+ Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError());
+ if (type.typeData && type.typeData->isError()) {
+ QString typeName = type.type->qmlTypeName();
+
+ QList<QQmlError> errors = type.typeData->errors();
+ QQmlError error;
+ error.setUrl(finalUrl());
+ error.setLine(type.location.line);
+ error.setColumn(type.location.column);
+ error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
+ errors.prepend(error);
+ setError(errors);
+ }
+ }
+
+ // If the type is CompositeSingleton but there was no pragma Singleton in the
+ // QML file, lets report an error.
+ QQmlType *type = QQmlMetaType::qmlType(url(), true);
+ if (type && type->isCompositeSingleton() && !m_isSingleton) {
+ QString typeName = type->qmlTypeName();
+
+ QQmlError error;
+ error.setDescription(QQmlTypeLoader::tr("qmldir defines type as singleton, but no pragma Singleton found in type %1.").arg(typeName));
+ error.setUrl(finalUrl());
+ setError(error);
+ }
+
// Compile component
if (!isError())
compile();
@@ -2140,6 +2220,14 @@ void QQmlTypeData::dataReceived(const Data &data)
return;
}
}
+
+ foreach (const QQmlScript::Pragma &pragma, scriptParser.pragmas()) {
+ if (!addPragma(pragma, &errors)) {
+ Q_ASSERT(errors.size());
+ setError(errors);
+ return;
+ }
+ }
}
void QQmlTypeData::allDependenciesDone()
@@ -2327,61 +2415,51 @@ void QQmlTypeData::resolveTypes()
m_scripts << ref;
}
- // --- old compiler:
- foreach (QQmlScript::TypeReference *parserRef, scriptParser.referencedTypes()) {
+ // Lets handle resolved composite singleton types
+ foreach (const QQmlImports::CompositeSingletonReference &csRef, m_imports.resolvedCompositeSingletons()) {
TypeReference ref;
+ QQmlScript::TypeReference parserRef;
+ parserRef.name = csRef.typeName;
+ // we are basing our type on the information from qmldir and therefore
+ // do not have a proper location.
+ parserRef.firstUse = NULL;
+
+ if (!csRef.prefix.isEmpty()) {
+ parserRef.name.prepend(csRef.prefix + QLatin1Char('.'));
+ // Add a reference to the enclosing namespace
+ m_namespaces.insert(csRef.prefix);
+ }
int majorVersion = -1;
int minorVersion = -1;
- QQmlImportNamespace *typeNamespace = 0;
- QList<QQmlError> errors;
- bool typeFound = m_imports.resolveType(parserRef->name, &ref.type,
- &majorVersion, &minorVersion, &typeNamespace, &errors);
- if (!typeNamespace && !typeFound && !m_implicitImportLoaded) {
- // Lazy loading of implicit import
- if (loadImplicitImport()) {
- // Try again to find the type
- errors.clear();
- typeFound = m_imports.resolveType(parserRef->name, &ref.type,
- &majorVersion, &minorVersion, &typeNamespace, &errors);
- } else {
- return; //loadImplicitImport() hit an error, and called setError already
- }
+ if (!resolveType(&parserRef, majorVersion, minorVersion, ref))
+ return;
+
+ if (ref.type->isCompositeSingleton()) {
+ ref.typeData = typeLoader()->getType(ref.type->sourceUrl());
+ addDependency(ref.typeData);
+ ref.prefix = csRef.prefix;
+
+ m_compositeSingletons << ref;
}
+ }
- if (!typeFound || typeNamespace) {
- // Known to not be a type:
- // - known to be a namespace (Namespace {})
- // - type with unknown namespace (UnknownNamespace.SomeType {})
- QQmlError error;
- if (typeNamespace) {
- error.setDescription(QQmlTypeLoader::tr("Namespace %1 cannot be used as a type").arg(parserRef->name));
- } else {
- if (errors.size()) {
- error = errors.takeFirst();
- } else {
- // this should not be possible!
- // Description should come from error provided by addImport() function.
- error.setDescription(QQmlTypeLoader::tr("Unreported error adding script import to import database"));
- }
- error.setUrl(m_imports.baseUrl());
- error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(parserRef->name).arg(error.description()));
- }
+ // --- old compiler:
+ foreach (QQmlScript::TypeReference *parserRef, scriptParser.referencedTypes()) {
+ TypeReference ref;
- Q_ASSERT(parserRef->firstUse);
- error.setLine(parserRef->firstUse->location.start.line);
- error.setColumn(parserRef->firstUse->location.start.column);
+ int majorVersion = -1;
+ int minorVersion = -1;
- errors.prepend(error);
- setError(errors);
+ if (!resolveType(parserRef, majorVersion, minorVersion, ref))
return;
- }
if (ref.type->isComposite()) {
ref.typeData = typeLoader()->getType(ref.type->sourceUrl());
addDependency(ref.typeData);
}
+
ref.majorVersion = majorVersion;
ref.minorVersion = minorVersion;
@@ -2466,6 +2544,58 @@ void QQmlTypeData::resolveTypes()
}
}
+bool QQmlTypeData::resolveType(const QQmlScript::TypeReference *parserRef, int &majorVersion, int &minorVersion, TypeReference &ref)
+{
+ QQmlImportNamespace *typeNamespace = 0;
+ QList<QQmlError> errors;
+
+ bool typeFound = m_imports.resolveType(parserRef->name, &ref.type,
+ &majorVersion, &minorVersion, &typeNamespace, &errors);
+ if (!typeNamespace && !typeFound && !m_implicitImportLoaded) {
+ // Lazy loading of implicit import
+ if (loadImplicitImport()) {
+ // Try again to find the type
+ errors.clear();
+ typeFound = m_imports.resolveType(parserRef->name, &ref.type,
+ &majorVersion, &minorVersion, &typeNamespace, &errors);
+ } else {
+ return false; //loadImplicitImport() hit an error, and called setError already
+ }
+ }
+
+ if (!typeFound || typeNamespace) {
+ // Known to not be a type:
+ // - known to be a namespace (Namespace {})
+ // - type with unknown namespace (UnknownNamespace.SomeType {})
+ QQmlError error;
+ if (typeNamespace) {
+ error.setDescription(QQmlTypeLoader::tr("Namespace %1 cannot be used as a type").arg(parserRef->name));
+ } else {
+ if (errors.size()) {
+ error = errors.takeFirst();
+ } else {
+ // this should not be possible!
+ // Description should come from error provided by addImport() function.
+ error.setDescription(QQmlTypeLoader::tr("Unreported error adding script import to import database"));
+ }
+ error.setUrl(m_imports.baseUrl());
+ error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(parserRef->name).arg(error.description()));
+ }
+
+ if (parserRef->firstUse)
+ {
+ error.setLine(parserRef->firstUse->location.start.line);
+ error.setColumn(parserRef->firstUse->location.start.column);
+ }
+
+ errors.prepend(error);
+ setError(errors);
+ return false;
+ }
+
+ return true;
+}
+
void QQmlTypeData::scriptImported(QQmlScriptBlob *blob, const QQmlScript::Location &location, const QString &qualifier, const QString &/*nameSpace*/)
{
ScriptReference ref;