aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaximilian Goldstein <max.goldstein@qt.io>2020-11-20 13:20:52 +0100
committerMaximilian Goldstein <max.goldstein@qt.io>2020-11-23 10:06:41 +0100
commit588d624837ae0174139f8db930ad20612463b1dd (patch)
tree13ef2dba7f6cc9ec4f22fe517c2c16f01db3ad06
parent87533900738d65ad278722b292852c998e987c10 (diff)
qmltyperegistrar: Expose interface information
Change-Id: Ica3f5c6696542921bc8d399cd46d901ba06f6d83 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
-rw-r--r--src/imports/tooling/Component.qml1
-rw-r--r--src/qmlcompiler/qqmljsscope_p.h4
-rw-r--r--src/qmlcompiler/qqmljstypedescriptionreader.cpp47
-rw-r--r--src/qmlcompiler/qqmljstypedescriptionreader_p.h3
-rw-r--r--src/qmltyperegistrar/qmltypesclassdescription.cpp9
-rw-r--r--src/qmltyperegistrar/qmltypesclassdescription.h1
-rw-r--r--src/qmltyperegistrar/qmltypescreator.cpp8
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp6
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h24
9 files changed, 98 insertions, 5 deletions
diff --git a/src/imports/tooling/Component.qml b/src/imports/tooling/Component.qml
index d87e613907..0045a75a6d 100644
--- a/src/imports/tooling/Component.qml
+++ b/src/imports/tooling/Component.qml
@@ -47,6 +47,7 @@ QtObject {
property string prototype
property var exports: []
property var exportMetaObjectRevisions: []
+ property var interfaces: []
property string attachedType
property string valueType
property bool isSingleton: false
diff --git a/src/qmlcompiler/qqmljsscope_p.h b/src/qmlcompiler/qqmljsscope_p.h
index de6ea58906..0801e6eb7e 100644
--- a/src/qmlcompiler/qqmljsscope_p.h
+++ b/src/qmlcompiler/qqmljsscope_p.h
@@ -185,6 +185,9 @@ public:
void addExport(const QString &name, const QString &package, const QTypeRevision &version);
QList<Export> exports() const { return m_exports; }
+ void setInterfaceNames(const QStringList& interfaces) { m_interfaceNames = interfaces; }
+ QStringList interfaceNames() { return m_interfaceNames; }
+
// If isComposite(), this is the QML/JS name of the prototype. Otherwise it's the
// relevant base class (in the hierarchy starting from QObject) of a C++ type.
void setBaseTypeName(const QString &baseTypeName) { m_baseTypeName = baseTypeName; }
@@ -272,6 +275,7 @@ private:
ScopeType m_scopeType = QMLScope;
QList<Export> m_exports;
+ QStringList m_interfaceNames;
QString m_defaultPropertyName;
QString m_attachedTypeName;
diff --git a/src/qmlcompiler/qqmljstypedescriptionreader.cpp b/src/qmlcompiler/qqmljstypedescriptionreader.cpp
index 8bdfd89370..6f474bbe10 100644
--- a/src/qmlcompiler/qqmljstypedescriptionreader.cpp
+++ b/src/qmlcompiler/qqmljstypedescriptionreader.cpp
@@ -220,6 +220,8 @@ void QQmlJSTypeDescriptionReader::readComponent(UiObjectDefinition *ast)
scope->setDefaultPropertyName(readStringBinding(script));
} else if (name == QLatin1String("exports")) {
readExports(script, scope);
+ } else if (name == QLatin1String("interfaces")) {
+ readInterfaces(script, scope);
} else if (name == QLatin1String("exportMetaObjectRevisions")) {
readMetaObjectRevisions(script, scope);
} else if (name == QLatin1String("attachedType")) {
@@ -249,7 +251,7 @@ void QQmlJSTypeDescriptionReader::readComponent(UiObjectDefinition *ast)
} else {
addWarning(script->firstSourceLocation(),
tr("Expected only name, prototype, defaultProperty, attachedType, "
- "valueType, exports, isSingleton, isCreatable, isComposite and "
+ "valueType, exports, interfaces, isSingleton, isCreatable, isComposite and "
"exportMetaObjectRevisions script bindings, not \"%1\".").arg(name));
}
} else {
@@ -551,35 +553,47 @@ int QQmlJSTypeDescriptionReader::readIntBinding(UiScriptBinding *ast)
return i;
}
-void QQmlJSTypeDescriptionReader::readExports(UiScriptBinding *ast, const QQmlJSScope::Ptr &scope)
+ArrayPattern* QQmlJSTypeDescriptionReader::getArray(UiScriptBinding *ast)
{
Q_ASSERT(ast);
if (!ast->statement) {
addError(ast->colonToken, tr("Expected array of strings after colon."));
- return;
+ return nullptr;
}
auto *expStmt = cast<ExpressionStatement *>(ast->statement);
if (!expStmt) {
addError(ast->statement->firstSourceLocation(),
tr("Expected array of strings after colon."));
- return;
+ return nullptr;
}
auto *arrayLit = cast<ArrayPattern *>(expStmt->expression);
if (!arrayLit) {
addError(expStmt->firstSourceLocation(), tr("Expected array of strings after colon."));
- return;
+ return nullptr;
}
+ return arrayLit;
+}
+
+void QQmlJSTypeDescriptionReader::readExports(UiScriptBinding *ast, const QQmlJSScope::Ptr &scope)
+{
+ auto *arrayLit = getArray(ast);
+
+ if (!arrayLit)
+ return;
+
for (PatternElementList *it = arrayLit->elements; it; it = it->next) {
auto *stringLit = cast<StringLiteral *>(it->element->initializer);
+
if (!stringLit) {
addError(arrayLit->firstSourceLocation(),
tr("Expected array literal with only string literal members."));
return;
}
+
QString exp = stringLit->value.toString();
int slashIdx = exp.indexOf(QLatin1Char('/'));
int spaceIdx = exp.indexOf(QLatin1Char(' '));
@@ -601,6 +615,29 @@ void QQmlJSTypeDescriptionReader::readExports(UiScriptBinding *ast, const QQmlJS
}
}
+void QQmlJSTypeDescriptionReader::readInterfaces(UiScriptBinding *ast, const QQmlJSScope::Ptr &scope)
+{
+ auto *arrayLit = getArray(ast);
+
+ if (!arrayLit)
+ return;
+
+ QStringList list;
+
+ for (PatternElementList *it = arrayLit->elements; it; it = it->next) {
+ auto *stringLit = cast<StringLiteral *>(it->element->initializer);
+ if (!stringLit) {
+ addError(arrayLit->firstSourceLocation(),
+ tr("Expected array literal with only string literal members."));
+ return;
+ }
+
+ list << stringLit->value.toString();
+ }
+
+ scope->setInterfaceNames(list);
+}
+
void QQmlJSTypeDescriptionReader::readMetaObjectRevisions(UiScriptBinding *ast,
const QQmlJSScope::Ptr &scope)
{
diff --git a/src/qmlcompiler/qqmljstypedescriptionreader_p.h b/src/qmlcompiler/qqmljstypedescriptionreader_p.h
index 770a53f01d..f99cda0605 100644
--- a/src/qmlcompiler/qqmljstypedescriptionreader_p.h
+++ b/src/qmlcompiler/qqmljstypedescriptionreader_p.h
@@ -80,12 +80,15 @@ private:
QTypeRevision readNumericVersionBinding(QQmlJS::AST::UiScriptBinding *ast);
int readIntBinding(QQmlJS::AST::UiScriptBinding *ast);
void readExports(QQmlJS::AST::UiScriptBinding *ast, const QQmlJSScope::Ptr &scope);
+ void readInterfaces(QQmlJS::AST::UiScriptBinding *ast, const QQmlJSScope::Ptr &scope);
void readMetaObjectRevisions(QQmlJS::AST::UiScriptBinding *ast, const QQmlJSScope::Ptr &scope);
void readEnumValues(QQmlJS::AST::UiScriptBinding *ast, QQmlJSMetaEnum *metaEnum);
void addError(const QQmlJS::SourceLocation &loc, const QString &message);
void addWarning(const QQmlJS::SourceLocation &loc, const QString &message);
+ QQmlJS::AST::ArrayPattern *getArray(QQmlJS::AST::UiScriptBinding *ast);
+
QString m_fileName;
QString m_source;
QString m_errorMessage;
diff --git a/src/qmltyperegistrar/qmltypesclassdescription.cpp b/src/qmltyperegistrar/qmltypesclassdescription.cpp
index 94cfd2c2a4..add59ddd17 100644
--- a/src/qmltyperegistrar/qmltypesclassdescription.cpp
+++ b/src/qmltyperegistrar/qmltypesclassdescription.cpp
@@ -66,6 +66,15 @@ void QmlTypesClassDescription::collect(const QJsonObject *classDef,
const QJsonObject *origClassDef = classDef; // if we find QML.Foreign, classDef changes.
if (file.isEmpty() && classDef->value(QLatin1String("registerable")).toBool())
file = classDef->value(QLatin1String("inputFile")).toString();
+
+ if (classDef->contains(QLatin1String("interfaces"))) {
+ QJsonArray array = classDef->value(QLatin1String("interfaces")).toArray();
+ for (const QJsonValue& value : array) {
+ auto object = value.toArray()[0].toObject();
+ implementsInterfaces << object[QLatin1String("className")].toString();
+ }
+ }
+
const auto classInfos = classDef->value(QLatin1String("classInfos")).toArray();
for (const QJsonValue classInfo : classInfos) {
const QJsonObject obj = classInfo.toObject();
diff --git a/src/qmltyperegistrar/qmltypesclassdescription.h b/src/qmltyperegistrar/qmltypesclassdescription.h
index 7e496159ff..fd172d1922 100644
--- a/src/qmltyperegistrar/qmltypesclassdescription.h
+++ b/src/qmltyperegistrar/qmltypesclassdescription.h
@@ -52,6 +52,7 @@ struct QmlTypesClassDescription
bool isCreatable = true;
bool isSingleton = false;
bool isRootClass = false;
+ QStringList implementsInterfaces;
enum CollectMode {
TopLevel,
diff --git a/src/qmltyperegistrar/qmltypescreator.cpp b/src/qmltyperegistrar/qmltypescreator.cpp
index df257d1f53..2a3c10829a 100644
--- a/src/qmltyperegistrar/qmltypescreator.cpp
+++ b/src/qmltyperegistrar/qmltypescreator.cpp
@@ -96,6 +96,14 @@ void QmlTypesCreator::writeClassProperties(const QmlTypesClassDescription &colle
if (!collector.attachedType.isEmpty())
m_qml.writeScriptBinding(QLatin1String("attachedType"), enquote(collector.attachedType));
+
+ if (!collector.implementsInterfaces.isEmpty()) {
+ QStringList interfaces;
+ for (const QString &interface : collector.implementsInterfaces)
+ interfaces << enquote(interface);
+
+ m_qml.writeArrayBinding(QLatin1String("interfaces"), interfaces);
+ }
}
void QmlTypesCreator::writeType(const QJsonObject &property, const QString &key, bool isReadonly,
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
index 3d3a0e7fbd..f8ffa1166f 100644
--- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
@@ -111,4 +111,10 @@ void tst_qmltyperegistrar::pastMajorVersions()
QVERIFY2(!c.isError(), qPrintable(c.errorString()));
}
+void tst_qmltyperegistrar::implementsInterfaces()
+{
+ QVERIFY(qmltypesData.contains("interfaces: [\"Interface\"]"));
+ QVERIFY(qmltypesData.contains("interfaces: [\"Interface\", \"Interface2\"]"));
+}
+
QTEST_MAIN(tst_qmltyperegistrar)
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
index 3c00e04357..b13debcf1b 100644
--- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
@@ -34,6 +34,29 @@
#include <QtQml/qqml.h>
#include <QtCore/qproperty.h>
+class Interface {};
+class Interface2 {};
+
+QT_BEGIN_NAMESPACE
+Q_DECLARE_INTERFACE(Interface, "io.qt.bugreports.Interface");
+Q_DECLARE_INTERFACE(Interface2, "io.qt.bugreports.Interface2");
+QT_END_NAMESPACE
+
+
+class ImplementsInterfaces : public QObject, public Interface
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_IMPLEMENTS_INTERFACES(Interface)
+};
+
+class ImplementsInterfaces2 : public QObject, public Interface, public Interface2
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_IMPLEMENTS_INTERFACES(Interface Interface2)
+};
+
class ExcessiveVersion : public QObject
{
Q_OBJECT
@@ -124,6 +147,7 @@ private slots:
void isBindable();
void restrictToImportVersion();
void pastMajorVersions();
+ void implementsInterfaces();
private:
QByteArray qmltypesData;