QmlDesigner: Implement support for SignalDeclarationProperty

This allows implementing a signal with a signature.
e.g. signal mySignal(int i)

Task-number: QDS-7319
Change-Id: I23cb000a218d709218322e7f31c86076d3ad949b
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Marco Bubke <marco.bubke@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
Thomas Hartmann
2022-07-19 15:00:42 +02:00
parent 217c66cca8
commit 56b14c9d18
26 changed files with 486 additions and 8 deletions

View File

@@ -155,8 +155,14 @@ void AddPropertyVisitor::addInMembers(QmlJS::AST::UiObjectInitializer *initializ
Q_ASSERT(!"unknown property type");
}
if (!m_dynamicTypeName.isEmpty())
newPropertyTemplate.prepend(QStringLiteral("property %1 ").arg(QString::fromUtf8(m_dynamicTypeName)));
if (!m_dynamicTypeName.isEmpty()) {
if (m_dynamicTypeName == "signal") {
newPropertyTemplate = "signal %1%2";
} else {
newPropertyTemplate.prepend(
QStringLiteral("property %1 ").arg(QString::fromUtf8(m_dynamicTypeName)));
}
}
if (isOneLiner) {
if (needsPreceedingSemicolon)

View File

@@ -137,7 +137,14 @@ void ChangePropertyVisitor::replaceMemberValue(UiObjectMember *propertyMember, b
startOffset = arrayBinding->lbracketToken.offset;
endOffset = arrayBinding->rbracketToken.end();
} else if (auto publicMember = AST::cast<UiPublicMember*>(propertyMember)) {
if (publicMember->statement) {
if (publicMember->type == AST::UiPublicMember::Signal) {
startOffset = publicMember->firstSourceLocation().offset;
if (publicMember->semicolonToken.isValid())
endOffset = publicMember->semicolonToken.end();
else
endOffset = publicMember->lastSourceLocation().end();
replacement.prepend(QStringLiteral("signal %1 ").arg(publicMember->name));
} else if (publicMember->statement) {
startOffset = publicMember->statement->firstSourceLocation().offset;
if (publicMember->semicolonToken.isValid())
endOffset = publicMember->semicolonToken.end();

View File

@@ -51,6 +51,7 @@ class QMLDESIGNERCORE_EXPORT NodeAbstractProperty;
class QMLDESIGNERCORE_EXPORT BindingProperty;
class QMLDESIGNERCORE_EXPORT NodeProperty;
class QMLDESIGNERCORE_EXPORT SignalHandlerProperty;
class QMLDESIGNERCORE_EXPORT SignalDeclarationProperty;
class QmlObjectNode;
@@ -88,6 +89,7 @@ public:
BindingProperty toBindingProperty() const;
NodeProperty toNodeProperty() const;
SignalHandlerProperty toSignalHandlerProperty() const;
SignalDeclarationProperty toSignalDeclarationProperty() const;
bool isVariantProperty() const;
bool isNodeListProperty() const;
@@ -95,6 +97,7 @@ public:
bool isBindingProperty() const;
bool isNodeProperty() const;
bool isSignalHandlerProperty() const;
bool isSignalDeclarationProperty() const;
bool isDynamic() const;
TypeName dynamicTypeName() const;

View File

@@ -185,6 +185,7 @@ public:
virtual void bindingPropertiesAboutToBeChanged(const QList<BindingProperty> &propertyList);
virtual void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange);
virtual void signalHandlerPropertiesChanged(const QVector<SignalHandlerProperty>& propertyList, PropertyChangeFlags propertyChange);
virtual void signalDeclarationPropertiesChanged(const QVector<SignalDeclarationProperty>& propertyList, PropertyChangeFlags propertyChange);
virtual void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion);
virtual void nodeTypeChanged(const ModelNode& node, const TypeName &type, int majorVersion, int minorVersion);

View File

@@ -51,6 +51,7 @@ class AbstractProperty;
class BindingProperty;
class VariantProperty;
class SignalHandlerProperty;
class SignalDeclarationProperty;
class Model;
class AbstractView;
class NodeListProperty;
@@ -128,6 +129,7 @@ public:
VariantProperty variantProperty(const PropertyName &name) const;
BindingProperty bindingProperty(const PropertyName &name) const;
SignalHandlerProperty signalHandlerProperty(const PropertyName &name) const;
SignalDeclarationProperty signalDeclarationProperty(const PropertyName &name) const;
NodeListProperty nodeListProperty(const PropertyName &name) const;
NodeProperty nodeProperty(const PropertyName &name) const;
NodeAbstractProperty nodeAbstractProperty(const PropertyName &name) const;

View File

@@ -87,6 +87,7 @@ public:
void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange) override;
void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange) override;
void signalHandlerPropertiesChanged(const QVector<SignalHandlerProperty>& propertyList,PropertyChangeFlags propertyChange) override;
void signalDeclarationPropertiesChanged(const QVector<SignalDeclarationProperty>& propertyList, PropertyChangeFlags propertyChange) override;
void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent,
const NodeAbstractProperty &oldPropertyParent,
AbstractView::PropertyChangeFlags propertyChange) override;

View File

@@ -30,7 +30,7 @@
namespace QmlDesigner {
class QMLDESIGNERCORE_EXPORT SignalHandlerProperty : public QmlDesigner::AbstractProperty
class QMLDESIGNERCORE_EXPORT SignalHandlerProperty : public AbstractProperty
{
friend ModelNode;
friend Internal::ModelPrivate;
@@ -50,4 +50,21 @@ protected:
SignalHandlerProperty(const PropertyName &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view);
};
class QMLDESIGNERCORE_EXPORT SignalDeclarationProperty : public AbstractProperty
{
friend ModelNode;
friend Internal::ModelPrivate;
friend AbstractProperty;
public:
void setSignature(const QString &source);
QString signature() const;
SignalDeclarationProperty();
SignalDeclarationProperty(const SignalDeclarationProperty &property, AbstractView *view);
protected:
SignalDeclarationProperty(const PropertyName &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view);
};
} // namespace QmlDesigner

View File

@@ -203,6 +203,19 @@ SignalHandlerProperty AbstractProperty::toSignalHandlerProperty() const
return SignalHandlerProperty();
}
SignalDeclarationProperty AbstractProperty::toSignalDeclarationProperty() const
{
if (!isValid())
throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, m_propertyName);
SignalDeclarationProperty propertyNode(name(), internalNode(), model(), view());
if (propertyNode.isSignalDeclarationProperty())
return propertyNode;
return SignalDeclarationProperty();
}
NodeListProperty AbstractProperty::toNodeListProperty() const
{
if (!isValid())
@@ -307,6 +320,18 @@ bool AbstractProperty::isSignalHandlerProperty() const
return false;
}
bool AbstractProperty::isSignalDeclarationProperty() const
{
if (!isValid())
throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, m_propertyName);
if (internalNode()->hasProperty(name())) {
Q_ASSERT(internalNode()->property(name()));
return internalNode()->property(name())->isSignalDeclarationProperty();
}
return false;
}
bool AbstractProperty::isBindingProperty() const
{

View File

@@ -351,6 +351,10 @@ void AbstractView::signalHandlerPropertiesChanged(const QVector<SignalHandlerPro
{
}
void AbstractView::signalDeclarationPropertiesChanged(const QVector<SignalDeclarationProperty>& /*propertyList*/, PropertyChangeFlags /*propertyChange*/)
{
}
void AbstractView::rootNodeTypeChanged(const QString &/*type*/, int /*majorVersion*/, int /*minorVersion*/)
{
}

View File

@@ -215,6 +215,15 @@ InternalSignalHandlerProperty::Pointer InternalNode::signalHandlerProperty(const
return InternalSignalHandlerProperty::Pointer();
}
InternalSignalDeclarationProperty::Pointer InternalNode::signalDeclarationProperty(const PropertyName &name) const
{
InternalProperty::Pointer property = m_namePropertyHash.value(name);
if (property->isSignalDeclarationProperty())
return property.staticCast<InternalSignalDeclarationProperty>();
return InternalSignalDeclarationProperty::Pointer();
}
InternalVariantProperty::Pointer InternalNode::variantProperty(const PropertyName &name) const
{
InternalProperty::Pointer property = m_namePropertyHash.value(name);
@@ -236,6 +245,12 @@ void InternalNode::addSignalHandlerProperty(const PropertyName &name)
m_namePropertyHash.insert(name, newProperty);
}
void InternalNode::addSignalDeclarationProperty(const PropertyName &name)
{
InternalProperty::Pointer newProperty(InternalSignalDeclarationProperty::create(name, internalPointer()));
m_namePropertyHash.insert(name, newProperty);
}
InternalNodeListProperty::Pointer InternalNode::nodeListProperty(const PropertyName &name) const
{
InternalProperty::Pointer property = m_namePropertyHash.value(name);

View File

@@ -92,6 +92,7 @@ public:
InternalProperty::Pointer property(const PropertyName &name) const;
InternalBindingProperty::Pointer bindingProperty(const PropertyName &name) const;
InternalSignalHandlerProperty::Pointer signalHandlerProperty(const PropertyName &name) const;
InternalSignalDeclarationProperty::Pointer signalDeclarationProperty(const PropertyName &name) const;
InternalVariantProperty::Pointer variantProperty(const PropertyName &name) const;
InternalNodeListProperty::Pointer nodeListProperty(const PropertyName &name) const;
InternalNodeAbstractProperty::Pointer nodeAbstractProperty(const PropertyName &name) const;
@@ -99,11 +100,11 @@ public:
void addBindingProperty(const PropertyName &name);
void addSignalHandlerProperty(const PropertyName &name);
void addSignalDeclarationProperty(const PropertyName &name);
void addNodeListProperty(const PropertyName &name);
void addVariantProperty(const PropertyName &name);
void addNodeProperty(const PropertyName &name, const TypeName &dynamicTypeName);
PropertyNameList propertyNameList() const;
bool hasProperties() const;

View File

@@ -107,6 +107,11 @@ bool InternalProperty::isSignalHandlerProperty() const
return false;
}
bool InternalProperty::isSignalDeclarationProperty() const
{
return false;
}
QSharedPointer<InternalVariantProperty> InternalProperty::toVariantProperty() const
{
@@ -143,6 +148,12 @@ QSharedPointer<InternalSignalHandlerProperty> InternalProperty::toSignalHandlerP
return internalPointer().staticCast<InternalSignalHandlerProperty>();
}
QSharedPointer<InternalSignalDeclarationProperty> InternalProperty::toSignalDeclarationProperty() const
{
Q_ASSERT(internalPointer().dynamicCast<InternalSignalDeclarationProperty>());
return internalPointer().staticCast<InternalSignalDeclarationProperty>();
}
void InternalProperty::remove()
{
propertyOwner()->removeProperty(name());

View File

@@ -36,6 +36,7 @@ namespace Internal {
class InternalBindingProperty;
class InternalSignalHandlerProperty;
class InternalSignalDeclarationProperty;
class InternalVariantProperty;
class InternalNodeListProperty;
class InternalNodeProperty;
@@ -62,6 +63,7 @@ public:
virtual bool isNodeProperty() const;
virtual bool isNodeAbstractProperty() const;
virtual bool isSignalHandlerProperty() const;
virtual bool isSignalDeclarationProperty() const;
QSharedPointer<InternalBindingProperty> toBindingProperty() const;
QSharedPointer<InternalVariantProperty> toVariantProperty() const;
@@ -69,6 +71,7 @@ public:
QSharedPointer<InternalNodeProperty> toNodeProperty() const;
QSharedPointer<InternalNodeAbstractProperty> toNodeAbstractProperty() const;
QSharedPointer<InternalSignalHandlerProperty> toSignalHandlerProperty() const;
QSharedPointer<InternalSignalDeclarationProperty> toSignalDeclarationProperty() const;
InternalNodePointer propertyOwner() const;

View File

@@ -63,5 +63,42 @@ bool InternalSignalHandlerProperty::isSignalHandlerProperty() const
return true;
}
InternalSignalDeclarationProperty::Pointer InternalSignalDeclarationProperty::create(const PropertyName &name, const InternalNodePointer &propertyOwner)
{
auto newPointer(new InternalSignalDeclarationProperty(name, propertyOwner));
InternalSignalDeclarationProperty::Pointer smartPointer(newPointer);
newPointer->setInternalWeakPointer(smartPointer);
newPointer->setDynamicTypeName("signal");
return smartPointer;
}
bool InternalSignalDeclarationProperty::isValid() const
{
return InternalProperty::isValid() && isSignalDeclarationProperty();
}
QString InternalSignalDeclarationProperty::signature() const
{
return m_signature;
}
void InternalSignalDeclarationProperty::setSignature(const QString &signature)
{
m_signature = signature;
}
bool InternalSignalDeclarationProperty::isSignalDeclarationProperty() const
{
return true;
}
InternalSignalDeclarationProperty::InternalSignalDeclarationProperty(const PropertyName &name, const InternalNodePointer &propertyOwner)
: InternalProperty(name, propertyOwner)
{
}
} // namespace Internal
} // namespace QmlDesigner

View File

@@ -51,5 +51,26 @@ private:
QString m_source;
};
class InternalSignalDeclarationProperty : public InternalProperty
{
public:
using Pointer = QSharedPointer<InternalSignalDeclarationProperty>;
static Pointer create(const PropertyName &name, const InternalNodePointer &propertyOwner);
bool isValid() const override;
QString signature() const;
void setSignature(const QString &source);
bool isSignalDeclarationProperty() const override;
protected:
InternalSignalDeclarationProperty(const PropertyName &name, const InternalNodePointer &propertyOwner);
private:
QString m_signature;
};
} // namespace Internal
} // namespace QmlDesigner

View File

@@ -843,6 +843,22 @@ void ModelPrivate::notifySignalHandlerPropertiesChanged(
});
}
void ModelPrivate::notifySignalDeclarationPropertiesChanged(
const QVector<InternalSignalDeclarationPropertyPointer> &internalPropertyList,
AbstractView::PropertyChangeFlags propertyChange)
{
notifyNodeInstanceViewLast([&](AbstractView *view) {
QVector<SignalDeclarationProperty> propertyList;
for (const InternalSignalDeclarationPropertyPointer &signalHandlerProperty : internalPropertyList) {
propertyList.append(SignalDeclarationProperty(signalHandlerProperty->name(),
signalHandlerProperty->propertyOwner(),
m_model,
view));
}
view->signalDeclarationPropertiesChanged(propertyList, propertyChange);
});
}
void ModelPrivate::notifyScriptFunctionsChanged(const InternalNodePointer &node,
const QStringList &scriptFunctionList)
{
@@ -1100,6 +1116,19 @@ void ModelPrivate::setSignalHandlerProperty(const InternalNodePointer &node, con
notifySignalHandlerPropertiesChanged({signalHandlerProperty}, propertyChange);
}
void ModelPrivate::setSignalDeclarationProperty(const InternalNodePointer &node, const PropertyName &name, const QString &signature)
{
AbstractView::PropertyChangeFlags propertyChange = AbstractView::NoAdditionalChanges;
if (!node->hasProperty(name)) {
node->addSignalDeclarationProperty(name);
propertyChange = AbstractView::PropertiesAdded;
}
InternalSignalDeclarationPropertyPointer signalDeclarationProperty = node->signalDeclarationProperty(name);
signalDeclarationProperty->setSignature(signature);
notifySignalDeclarationPropertiesChanged({signalDeclarationProperty}, propertyChange);
}
void ModelPrivate::setVariantProperty(const InternalNodePointer &node, const PropertyName &name, const QVariant &value)
{
AbstractView::PropertyChangeFlags propertyChange = AbstractView::NoAdditionalChanges;

View File

@@ -53,6 +53,7 @@ class InternalNode;
class InternalProperty;
class InternalBindingProperty;
class InternalSignalHandlerProperty;
class InternalSignalDeclarationProperty;
class InternalVariantProperty;
class InternalNodeAbstractProperty;
class InternalNodeListProperty;
@@ -61,6 +62,7 @@ using InternalNodePointer = QSharedPointer<InternalNode>;
using InternalPropertyPointer = QSharedPointer<InternalProperty>;
using InternalBindingPropertyPointer = QSharedPointer<InternalBindingProperty>;
using InternalSignalHandlerPropertyPointer = QSharedPointer<InternalSignalHandlerProperty>;
using InternalSignalDeclarationPropertyPointer = QSharedPointer<InternalSignalDeclarationProperty>;
using InternalVariantPropertyPointer = QSharedPointer<InternalVariantProperty>;
using InternalNodeAbstractPropertyPointer = QSharedPointer<InternalNodeAbstractProperty>;
using InternalNodeListPropertyPointer = QSharedPointer<InternalNodeListProperty>;
@@ -154,6 +156,7 @@ public:
const QList<InternalBindingPropertyPointer> &internalPropertyList);
void notifyBindingPropertiesChanged(const QList<InternalBindingPropertyPointer> &internalPropertyList, AbstractView::PropertyChangeFlags propertyChange);
void notifySignalHandlerPropertiesChanged(const QVector<InternalSignalHandlerPropertyPointer> &propertyList, AbstractView::PropertyChangeFlags propertyChange);
void notifySignalDeclarationPropertiesChanged(const QVector<InternalSignalDeclarationPropertyPointer> &propertyList, AbstractView::PropertyChangeFlags propertyChange);
void notifyVariantPropertiesChanged(const InternalNodePointer &node, const PropertyNameList &propertyNameList, AbstractView::PropertyChangeFlags propertyChange);
void notifyScriptFunctionsChanged(const InternalNodePointer &node, const QStringList &scriptFunctionList);
@@ -221,6 +224,7 @@ public:
void setBindingProperty(const InternalNodePointer &node, const PropertyName &name, const QString &expression);
void setSignalHandlerProperty(const InternalNodePointer &node, const PropertyName &name, const QString &source);
void setSignalDeclarationProperty(const InternalNodePointer &node, const PropertyName &name, const QString &signature);
void setVariantProperty(const InternalNodePointer &node, const PropertyName &name, const QVariant &value);
void setDynamicVariantProperty(const InternalNodePointer &node, const PropertyName &name, const TypeName &propertyType, const QVariant &value);
void setDynamicBindingProperty(const InternalNodePointer &node, const PropertyName &name, const TypeName &dynamicPropertyType, const QString &expression);

View File

@@ -487,6 +487,13 @@ SignalHandlerProperty ModelNode::signalHandlerProperty(const PropertyName &name)
return SignalHandlerProperty(name, m_internalNode, model(), view());
}
SignalDeclarationProperty ModelNode::signalDeclarationProperty(const PropertyName &name) const
{
if (!isValid())
throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
return SignalDeclarationProperty(name, m_internalNode, model(), view());
}
/*!
\brief Returns a NodeProperty

View File

@@ -356,6 +356,8 @@ QmlRefactoring::PropertyType ModelToTextMerger::propertyType(const AbstractPrope
return QmlRefactoring::ObjectBinding;
else if (property.isVariantProperty())
return QmlRefactoring::ScriptBinding;
else if (property.isSignalDeclarationProperty())
return QmlRefactoring::ScriptBinding;
Q_ASSERT(false); //Cannot convert property type
return QmlRefactoring::Invalid;

View File

@@ -101,6 +101,8 @@ QString QmlTextGenerator::toQml(const AbstractProperty &property, int indentDept
return property.toBindingProperty().expression();
} else if (property.isSignalHandlerProperty()) {
return property.toSignalHandlerProperty().source();
} else if (property.isSignalDeclarationProperty()) {
return property.toSignalDeclarationProperty().signature();
} else if (property.isNodeProperty()) {
return toQml(property.toNodeProperty().modelNode(), indentDepth);
} else if (property.isNodeListProperty()) {
@@ -288,6 +290,10 @@ QString QmlTextGenerator::propertyToQml(const AbstractProperty &property, int in
+ QString::fromUtf8(property.name())
+ QStringLiteral(": ")
+ toQml(property, indentDepth);
}
if (property.isSignalDeclarationProperty()) {
result = m_tabSettings.indentationString(0, indentDepth, 0) + "signal" + " "
+ QString::fromUtf8(property.name()) + " " + toQml(property, indentDepth);
} else {
result = m_tabSettings.indentationString(0, indentDepth, 0)
+ QString::fromUtf8(property.name())

View File

@@ -261,6 +261,22 @@ void RewriterView::signalHandlerPropertiesChanged(const QVector<SignalHandlerPro
applyChanges();
}
void RewriterView::signalDeclarationPropertiesChanged(const QVector<SignalDeclarationProperty> &propertyList, PropertyChangeFlags propertyChange)
{
Q_ASSERT(textModifier());
if (textToModelMerger()->isActive())
return;
QList<AbstractProperty> usefulPropertyList;
for (const SignalDeclarationProperty &property : propertyList)
usefulPropertyList.append(property);
modelToTextMerger()->propertiesChanged(usefulPropertyList, propertyChange);
if (!isModificationGroupActive())
applyChanges();
}
void RewriterView::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange)
{
Q_ASSERT(textModifier());

View File

@@ -107,4 +107,57 @@ PropertyName SignalHandlerProperty::prefixRemoved(const PropertyName &propertyNa
return nameAsString.toLatin1();
}
SignalDeclarationProperty::SignalDeclarationProperty() = default;
SignalDeclarationProperty::SignalDeclarationProperty(const SignalDeclarationProperty &property,
AbstractView *view)
: AbstractProperty(property.name(), property.internalNode(), property.model(), view)
{}
SignalDeclarationProperty::SignalDeclarationProperty(
const PropertyName &propertyName,
const Internal::InternalNodePointer &internalNode,
Model *model,
AbstractView *view)
: AbstractProperty(propertyName, internalNode, model, view)
{
}
void SignalDeclarationProperty::setSignature(const QString &signature)
{
Internal::WriteLocker locker(model());
if (!isValid())
throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
if (name() == "id") { // the ID for a node is independent of the state, so it has to be set with ModelNode::setId
throw InvalidPropertyException(__LINE__, __FUNCTION__, __FILE__, name());
}
if (signature.isEmpty())
throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, name());
if (internalNode()->hasProperty(name())) { //check if oldValue != value
Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
if (internalProperty->isSignalDeclarationProperty()
&& internalProperty->toSignalDeclarationProperty()->signature() == signature)
return;
}
if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isSignalDeclarationProperty())
privateModel()->removeProperty(internalNode()->property(name()));
privateModel()->setSignalDeclarationProperty(internalNode(), name(), signature);
}
QString SignalDeclarationProperty::signature() const
{
if (internalNode()->hasProperty(name())
&& internalNode()->property(name())->isSignalDeclarationProperty())
return internalNode()->signalDeclarationProperty(name())->signature();
return QString();
}
} // namespace QmlDesigner

View File

@@ -1357,8 +1357,21 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
} else if (auto script = AST::cast<AST::UiScriptBinding *>(member)) {
modelPropertyNames.remove(syncScriptBinding(modelNode, QString(), script, context, differenceHandler));
} else if (auto property = AST::cast<AST::UiPublicMember *>(member)) {
if (property->type == AST::UiPublicMember::Signal)
continue; // QML designer doesn't support this yet.
if (property->type == AST::UiPublicMember::Signal) {
const QStringView astName = property->name;
AbstractProperty modelProperty = modelNode.property(astName.toUtf8());
QString signature = "()";
if (property->parameters) {
signature = "("
+ textAt(context->doc(),
property->parameters->firstSourceLocation(),
property->parameters->lastSourceLocation())
+ ")";
}
syncSignalDeclarationProperty(modelProperty, signature, differenceHandler);
continue; // Done
}
const QStringView astName = property->name;
QString astValue;
@@ -1693,6 +1706,19 @@ void TextToModelMerger::syncVariantProperty(AbstractProperty &modelProperty,
}
}
void TextToModelMerger::syncSignalDeclarationProperty(AbstractProperty &modelProperty,
const QString &signature,
DifferenceHandler &differenceHandler)
{
if (modelProperty.isSignalHandlerProperty()) {
SignalDeclarationProperty signalHandlerProperty = modelProperty.toSignalDeclarationProperty();
if (signalHandlerProperty.signature() != signature)
differenceHandler.signalDeclarationSignatureDiffer(signalHandlerProperty, signature);
} else {
differenceHandler.shouldBeSignalDeclarationProperty(modelProperty, signature);
}
}
void TextToModelMerger::syncNodeListProperty(NodeListProperty &modelListProperty,
const QList<AST::UiObjectMember *> arrayMembers,
ReadingContext *context,
@@ -1834,6 +1860,13 @@ void ModelValidator::signalHandlerSourceDiffer(SignalHandlerProperty &modelPrope
QTC_ASSERT(compareJavaScriptExpression(modelProperty.source(), javascript), return);
}
void ModelValidator::signalDeclarationSignatureDiffer(SignalDeclarationProperty &modelProperty, const QString &signature)
{
Q_UNUSED(modelProperty)
Q_UNUSED(signature)
QTC_ASSERT(compareJavaScriptExpression(modelProperty.signature(), signature), return);
}
void ModelValidator::shouldBeSignalHandlerProperty(AbstractProperty &modelProperty, const QString & /*javascript*/)
{
Q_UNUSED(modelProperty)
@@ -1841,6 +1874,13 @@ void ModelValidator::shouldBeSignalHandlerProperty(AbstractProperty &modelProper
Q_ASSERT(0);
}
void ModelValidator::shouldBeSignalDeclarationProperty(AbstractProperty &modelProperty, const QString & /*javascript*/)
{
Q_UNUSED(modelProperty)
Q_ASSERT(modelProperty.isSignalDeclarationProperty());
Q_ASSERT(0);
}
void ModelValidator::shouldBeNodeListProperty(AbstractProperty &modelProperty,
const QList<AST::UiObjectMember *> /*arrayMembers*/,
ReadingContext * /*context*/)
@@ -1989,6 +2029,11 @@ void ModelAmender::signalHandlerSourceDiffer(SignalHandlerProperty &modelPropert
modelProperty.setSource(javascript);
}
void ModelAmender::signalDeclarationSignatureDiffer(SignalDeclarationProperty &modelProperty, const QString &signature)
{
modelProperty.setSignature(signature);
}
void ModelAmender::shouldBeSignalHandlerProperty(AbstractProperty &modelProperty, const QString &javascript)
{
ModelNode theNode = modelProperty.parentModelNode();
@@ -1996,6 +2041,13 @@ void ModelAmender::shouldBeSignalHandlerProperty(AbstractProperty &modelProperty
newModelProperty.setSource(javascript);
}
void ModelAmender::shouldBeSignalDeclarationProperty(AbstractProperty &modelProperty, const QString &signature)
{
ModelNode theNode = modelProperty.parentModelNode();
SignalDeclarationProperty newModelProperty = theNode.signalDeclarationProperty(modelProperty.name());
newModelProperty.setSignature(signature);
}
void ModelAmender::shouldBeNodeListProperty(AbstractProperty &modelProperty,
const QList<AST::UiObjectMember *> arrayMembers,
ReadingContext *context)

View File

@@ -107,6 +107,9 @@ public:
const QList<QmlJS::AST::UiObjectMember *> &arrayMembers,
ReadingContext *context,
DifferenceHandler &differenceHandler);
void syncSignalDeclarationProperty(AbstractProperty &modelProperty,
const QString &signature,
DifferenceHandler &differenceHandler);
void syncVariantProperty(AbstractProperty &modelProperty,
const QVariant &astValue,
const TypeName &astType,
@@ -187,11 +190,15 @@ public:
const TypeName &astType) = 0;
virtual void signalHandlerSourceDiffer(SignalHandlerProperty &modelProperty,
const QString &javascript) = 0;
virtual void signalDeclarationSignatureDiffer(SignalDeclarationProperty &modelProperty,
const QString &signature) = 0;
virtual void shouldBeBindingProperty(AbstractProperty &modelProperty,
const QString &javascript,
const TypeName &astType) = 0;
virtual void shouldBeSignalHandlerProperty(AbstractProperty &modelProperty,
const QString &javascript) = 0;
virtual void shouldBeSignalDeclarationProperty(AbstractProperty &modelProperty,
const QString &signature) = 0;
virtual void shouldBeNodeListProperty(AbstractProperty &modelProperty,
const QList<QmlJS::AST::UiObjectMember *> arrayMembers,
ReadingContext *context) = 0;
@@ -241,6 +248,10 @@ public:
const TypeName &astType) override;
void signalHandlerSourceDiffer(SignalHandlerProperty &modelProperty,
const QString &javascript) override;
void signalDeclarationSignatureDiffer(SignalDeclarationProperty &modelProperty,
const QString &signature) override;
void shouldBeSignalDeclarationProperty(AbstractProperty &modelProperty,
const QString &signature) override;
void shouldBeSignalHandlerProperty(AbstractProperty &modelProperty,
const QString &javascript) override;
void shouldBeNodeListProperty(AbstractProperty &modelProperty,
@@ -290,6 +301,10 @@ public:
const TypeName &astType) override;
void signalHandlerSourceDiffer(SignalHandlerProperty &modelProperty,
const QString &javascript) override;
void signalDeclarationSignatureDiffer(SignalDeclarationProperty &modelProperty,
const QString &signature) override;
void shouldBeSignalDeclarationProperty(AbstractProperty &modelProperty,
const QString &signature) override;
void shouldBeSignalHandlerProperty(AbstractProperty &modelProperty,
const QString &javascript) override;
void shouldBeNodeListProperty(AbstractProperty &modelProperty,

View File

@@ -170,7 +170,8 @@ tst_TestCore::tst_TestCore()
: QObject()
{
QLoggingCategory::setFilterRules(QStringLiteral("qtc.qmljs.imports=false"));
QLoggingCategory::setFilterRules(QStringLiteral("*.info=false\n*.debug=false\n*.warning=false"));
//QLoggingCategory::setFilterRules(QStringLiteral("*.info=false\n*.debug=false\n*.warning=false"));
QLoggingCategory::setFilterRules(QStringLiteral("*.warning=false"));
}
void tst_TestCore::initTestCase()
@@ -1273,6 +1274,7 @@ void tst_TestCore::testRewriterBehaivours()
testRewriterView->setTextModifier(&modifier);
model->attachView(testRewriterView.data());
//qDebug() << testRewriterView->errors().first().toString();
QVERIFY(testRewriterView->errors().isEmpty());
ModelNode rootModelNode = testRewriterView->rootModelNode();
@@ -1345,6 +1347,119 @@ void tst_TestCore::testRewriterBehaivours()
QVERIFY(!newBehavior.isValid());
}
void tst_TestCore::testRewriterSignalDefinition()
{
const QLatin1String qmlString("\n"
"import QtQuick 2.1\n"
"\n"
"Rectangle {\n"
" id: root\n"
" x: 10;\n"
" y: 10;\n"
" signal testSignal()\n"
" signal testSignal2(float i)\n"
" Rectangle {\n"
" id: rectangle1\n"
" x: 10;\n"
" y: 10;\n"
" signal testSignal\n"
" }\n"
"}");
QPlainTextEdit textEdit;
textEdit.setPlainText(qmlString);
NotIndentingTextEditModifier modifier(&textEdit);
QScopedPointer<Model> model(Model::create("QtQuick.Text"));
QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
testRewriterView->setTextModifier(&modifier);
model->attachView(testRewriterView.data());
QVERIFY(testRewriterView->errors().isEmpty());
ModelNode rootModelNode = testRewriterView->rootModelNode();
QVERIFY(rootModelNode.isValid());
QVERIFY(rootModelNode.hasProperty("testSignal"));
QVERIFY(rootModelNode.hasProperty("testSignal2"));
QVERIFY(rootModelNode.property("testSignal").isSignalDeclarationProperty());
QVERIFY(rootModelNode.signalDeclarationProperty("testSignal").isValid());
QCOMPARE(rootModelNode.signalDeclarationProperty("testSignal").signature(), "()");
QVERIFY(rootModelNode.property("testSignal2").isSignalDeclarationProperty());
QVERIFY(rootModelNode.signalDeclarationProperty("testSignal2").isValid());
QCOMPARE(rootModelNode.signalDeclarationProperty("testSignal2").signature(), "(float i)");
ModelNode rectangle = testRewriterView->modelNodeForId("rectangle1");
QVERIFY(rectangle.isValid());
QVERIFY(rectangle.hasProperty("testSignal"));
QVERIFY(rectangle.property("testSignal").isSignalDeclarationProperty());
QVERIFY(rectangle.signalDeclarationProperty("testSignal").isValid());
QCOMPARE(rectangle.signalDeclarationProperty("testSignal").signature(), "()");
rootModelNode.signalDeclarationProperty("addedSignal").setSignature("()");
rootModelNode.signalDeclarationProperty("addedSignal").setSignature("(real i)");
const QLatin1String expectedQmlCode(
"\nimport QtQuick 2.1\n\n"
"Rectangle {\n"
" id: root\n"
" x: 10;\n"
" y: 10;\n"
" signal addedSignal (real i)\n"
" signal testSignal()\n"
" signal testSignal2(float i)\n"
" Rectangle {\n"
" id: rectangle1\n"
" x: 10;\n"
" y: 10;\n"
" signal testSignal\n"
" }\n}");
QCOMPARE(textEdit.toPlainText(), expectedQmlCode);
rootModelNode.removeProperty("addedSignal");
const QLatin1String expectedQmlCode2(
"\nimport QtQuick 2.1\n\n"
"Rectangle {\n"
" id: root\n"
" x: 10;\n"
" y: 10;\n"
" signal testSignal()\n"
" signal testSignal2(float i)\n"
" Rectangle {\n"
" id: rectangle1\n"
" x: 10;\n"
" y: 10;\n"
" signal testSignal\n"
" }\n}");
QCOMPARE(textEdit.toPlainText(), expectedQmlCode2);
testRewriterView->executeInTransaction("identifer", [rectangle](){
ModelNode newRectangle = rectangle.view()->createModelNode(rectangle.type(),
rectangle.majorVersion(),
rectangle.minorVersion());
QVERIFY(newRectangle.isValid());
newRectangle.signalDeclarationProperty("newSignal").setSignature("()");
newRectangle.setIdWithoutRefactoring("newRect");
newRectangle.view()->rootModelNode().defaultNodeListProperty().reparentHere(newRectangle);
});
const QString expectedQmlCode3
= expectedQmlCode2.chopped(1)
+ QLatin1String("\n Rectangle {\n id: newRect\n signal newSignal ()\n }\n}");
QCOMPARE(textEdit.toPlainText(), expectedQmlCode3);
}
void tst_TestCore::testRewriterForGradientMagic()
{
const QLatin1String qmlString("\n"
@@ -6891,6 +7006,29 @@ void tst_TestCore::testModelChangeType()
QCOMPARE(textEdit.toPlainText(), expectedQmlCode2);
}
void tst_TestCore::testModelSignalDefinition()
{
QScopedPointer<Model> model(createModel("QtQuick.Rectangle", 2, 0));
QVERIFY(model.data());
QScopedPointer<TestView> view(new TestView(model.data()));
QVERIFY(view.data());
model->attachView(view.data());
ModelNode rootModelNode(view->rootModelNode());
QVERIFY(rootModelNode.isValid());
QVERIFY(!rootModelNode.hasProperty("mySignal"));
rootModelNode.signalDeclarationProperty("mySignal").setSignature("()");
QVERIFY(rootModelNode.hasProperty("mySignal"));
QVERIFY(rootModelNode.signalDeclarationProperty("mySignal").isValid());
QVERIFY(rootModelNode.property("mySignal").isSignalDeclarationProperty());
QCOMPARE(rootModelNode.signalDeclarationProperty("mySignal").signature(), "()");
}
void tst_TestCore::testModelDefaultProperties()
{
QScopedPointer<Model> model(createModel("QtQuick.Rectangle", 2, 0));

View File

@@ -90,6 +90,7 @@ private slots:
void testModelNodeInHierarchy();
void testModelNodeIsAncestorOf();
void testModelChangeType();
void testModelSignalDefinition();
//
// unit tests Rewriter
@@ -146,6 +147,7 @@ private slots:
void testRewriterTransactionAddingAfterReparenting();
void testRewriterReparentToNewNode();
void testRewriterBehaivours();
void testRewriterSignalDefinition();
//
// unit tests QmlModelNodeFacade/QmlModelState