qmltypes: Add information about QQmlCustomParser
Adds a macro called QML_CUSTOMPARSER which will result in a hasCustomParser flag to be set in qmltypes. Also ensures qmllint does not warn about unknown properties when a class utilizes custom parsers. Fixes: QTBUG-93027 Change-Id: I7559d79c9bf06a0a7a93f54370948f12d09dd64e Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
facffe8e57
commit
077b8f8df4
|
@ -54,6 +54,7 @@ QtObject {
|
|||
property bool isSingleton: false
|
||||
property bool isCreatable: name.length > 0
|
||||
property bool isComposite: false
|
||||
property bool hasCustomParser: false
|
||||
property string accessSemantics: "reference"
|
||||
property string defaultProperty
|
||||
}
|
||||
|
|
|
@ -137,4 +137,6 @@
|
|||
#define QML_UNAVAILABLE \
|
||||
QML_FOREIGN(QQmlTypeNotAvailable)
|
||||
|
||||
#define QML_CUSTOMPARSER Q_CLASSINFO("QML.HasCustomParser", "true")
|
||||
|
||||
#endif // QQMLREGISTRATION_H
|
||||
|
|
|
@ -73,6 +73,7 @@ class Q_AUTOTEST_EXPORT QQmlConnections : public QObject, public QQmlParserStatu
|
|||
Q_PROPERTY(bool ignoreUnknownSignals READ ignoreUnknownSignals WRITE setIgnoreUnknownSignals)
|
||||
QML_NAMED_ELEMENT(Connections)
|
||||
QML_ADDED_IN_VERSION(2, 0)
|
||||
QML_CUSTOMPARSER
|
||||
|
||||
public:
|
||||
QQmlConnections(QObject *parent=nullptr);
|
||||
|
|
|
@ -112,7 +112,8 @@ public:
|
|||
Creatable = 0x1,
|
||||
Composite = 0x2,
|
||||
Singleton = 0x4,
|
||||
Script = 0x8,
|
||||
Script = 0x8,
|
||||
CustomParser = 0x10,
|
||||
};
|
||||
Q_DECLARE_FLAGS(Flags, Flag)
|
||||
Q_FLAGS(Flags);
|
||||
|
@ -264,10 +265,15 @@ public:
|
|||
bool isCreatable() const { return m_flags & Creatable; }
|
||||
bool isComposite() const { return m_flags & Composite; }
|
||||
bool isScript() const { return m_flags & Script; }
|
||||
bool hasCustomParser() const { return m_flags & CustomParser; }
|
||||
void setIsSingleton(bool v) { m_flags = v ? (m_flags | Singleton) : (m_flags & ~Singleton); }
|
||||
void setIsCreatable(bool v) { m_flags = v ? (m_flags | Creatable) : (m_flags & ~Creatable); }
|
||||
void setIsComposite(bool v) { m_flags = v ? (m_flags | Composite) : (m_flags & ~Composite); }
|
||||
void setIsScript(bool v) { m_flags = v ? (m_flags | Script) : (m_flags & ~Script); }
|
||||
void setHasCustomParser(bool v)
|
||||
{
|
||||
m_flags = v ? (m_flags | CustomParser) : (m_flags & ~CustomParser);
|
||||
}
|
||||
|
||||
void setAccessSemantics(AccessSemantics semantics) { m_semantics = semantics; }
|
||||
AccessSemantics accessSemantics() const { return m_semantics; }
|
||||
|
|
|
@ -234,6 +234,8 @@ void QQmlJSTypeDescriptionReader::readComponent(UiObjectDefinition *ast)
|
|||
scope->setIsCreatable(readBoolBinding(script));
|
||||
} else if (name == QLatin1String("isComposite")) {
|
||||
scope->setIsComposite(readBoolBinding(script));
|
||||
} else if (name == QLatin1String("hasCustomParser")) {
|
||||
scope->setHasCustomParser(readBoolBinding(script));
|
||||
} else if (name == QLatin1String("accessSemantics")) {
|
||||
const QString semantics = readStringBinding(script);
|
||||
if (semantics == QLatin1String("reference")) {
|
||||
|
@ -253,8 +255,10 @@ void QQmlJSTypeDescriptionReader::readComponent(UiObjectDefinition *ast)
|
|||
} else {
|
||||
addWarning(script->firstSourceLocation(),
|
||||
tr("Expected only name, prototype, defaultProperty, attachedType, "
|
||||
"valueType, exports, interfaces, isSingleton, isCreatable, isComposite and "
|
||||
"exportMetaObjectRevisions script bindings, not \"%1\".").arg(name));
|
||||
"valueType, exports, interfaces, isSingleton, isCreatable, "
|
||||
"isComposite, hasCustomParser and "
|
||||
"exportMetaObjectRevisions script bindings, not \"%1\".")
|
||||
.arg(name));
|
||||
}
|
||||
} else {
|
||||
addWarning(member->firstSourceLocation(),
|
||||
|
|
|
@ -85,6 +85,7 @@ class Q_QMLMODELS_PRIVATE_EXPORT QQmlListModel : public QAbstractListModel
|
|||
Q_PROPERTY(QObject *agent READ agent CONSTANT REVISION(2, 14))
|
||||
QML_NAMED_ELEMENT(ListModel)
|
||||
QML_ADDED_IN_VERSION(2, 0)
|
||||
QML_CUSTOMPARSER
|
||||
|
||||
public:
|
||||
QQmlListModel(QObject *parent=nullptr);
|
||||
|
|
|
@ -177,6 +177,9 @@ void QmlTypesClassDescription::collect(
|
|||
foreignTypeName = value;
|
||||
} else if (name == QLatin1String("QML.Root")) {
|
||||
isRootClass = true;
|
||||
} else if (name == QLatin1String("QML.HasCustomParser")) {
|
||||
if (value == QLatin1String("true"))
|
||||
hasCustomParser = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ struct QmlTypesClassDescription
|
|||
bool isCreatable = true;
|
||||
bool isSingleton = false;
|
||||
bool isRootClass = false;
|
||||
bool hasCustomParser = false;
|
||||
QStringList implementsInterfaces;
|
||||
|
||||
enum CollectMode {
|
||||
|
|
|
@ -103,6 +103,9 @@ void QmlTypesCreator::writeClassProperties(const QmlTypesClassDescription &colle
|
|||
if (collector.isSingleton)
|
||||
m_qml.writeScriptBinding(QLatin1String("isSingleton"), QLatin1String("true"));
|
||||
|
||||
if (collector.hasCustomParser)
|
||||
m_qml.writeScriptBinding(QLatin1String("hasCustomParser"), QLatin1String("true"));
|
||||
|
||||
m_qml.writeArrayBinding(QLatin1String("exportMetaObjectRevisions"), metaObjects);
|
||||
|
||||
if (!collector.attachedType.isEmpty())
|
||||
|
|
|
@ -61,12 +61,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPropertyChanges : public QQuickStateOperation
|
|||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(QQuickPropertyChanges)
|
||||
|
||||
Q_PROPERTY(QObject *target READ object WRITE setObject)
|
||||
Q_PROPERTY(bool restoreEntryValues READ restoreEntryValues WRITE setRestoreEntryValues)
|
||||
Q_PROPERTY(bool explicit READ isExplicit WRITE setIsExplicit)
|
||||
QML_NAMED_ELEMENT(PropertyChanges)
|
||||
QML_ADDED_IN_VERSION(2, 0)
|
||||
QML_CUSTOMPARSER
|
||||
|
||||
public:
|
||||
QQuickPropertyChanges();
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import QtQuick 2.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
width: 100; height: 100
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "red_color"
|
||||
PropertyChanges { target: root; color: "red" }
|
||||
},
|
||||
State {
|
||||
name: "blue_color"
|
||||
PropertyChanges { target: root; color: "blue" }
|
||||
}
|
||||
]
|
||||
}
|
|
@ -709,6 +709,7 @@ void TestQmllint::cleanQmlCode_data()
|
|||
QTest::newRow("multilineStringEscaped") << QStringLiteral("multilineStringEscaped.qml");
|
||||
QTest::newRow("propertyOverride") << QStringLiteral("propertyOverride.qml");
|
||||
QTest::newRow("propertyBindingValue") << QStringLiteral("propertyBindingValue.qml");
|
||||
QTest::newRow("customParser") << QStringLiteral("customParser.qml");
|
||||
}
|
||||
|
||||
void TestQmllint::cleanQmlCode()
|
||||
|
|
|
@ -287,6 +287,11 @@ bool FindWarningVisitor::visit(QQmlJS::AST::UiScriptBinding *uisb)
|
|||
}
|
||||
|
||||
if (!qmlScope->hasProperty(name.toString())) {
|
||||
// These warnings do not apply for custom parsers and need to be handled on a case by
|
||||
// case basis
|
||||
if (qmlScope->baseType()->hasCustomParser())
|
||||
return true;
|
||||
|
||||
// TODO: Can this be in a better suited category?
|
||||
m_logger.log(
|
||||
QStringLiteral("Binding assigned to \"%1\", but no property \"%1\" "
|
||||
|
|
Loading…
Reference in New Issue