From 6237bbb453eb64456d18c09311c79e48e4600c93 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen <erik.verbruggen@nokia.com> Date: Thu, 22 Apr 2010 18:50:08 +0200 Subject: [PATCH] Fixed rewriting for grouped properties. --- .../filemanager/changepropertyvisitor.cpp | 44 ++++++++++---- .../core/filemanager/changepropertyvisitor.h | 6 +- .../filemanager/removepropertyvisitor.cpp | 59 +++++++++++++++---- .../core/filemanager/removepropertyvisitor.h | 5 +- .../qml/qmldesigner/coretests/testcore.cpp | 24 ++++++-- 5 files changed, 105 insertions(+), 33 deletions(-) diff --git a/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.cpp index 6d0e4972852..9192e95ed8a 100644 --- a/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.cpp +++ b/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.cpp @@ -58,7 +58,7 @@ bool ChangePropertyVisitor::visit(QmlJS::AST::UiObjectDefinition *ast) const quint32 objectStart = ast->firstSourceLocation().offset; if (objectStart == m_parentLocation) { - replaceInMembers(ast->initializer); + replaceInMembers(ast->initializer, m_name); return false; } @@ -73,30 +73,39 @@ bool ChangePropertyVisitor::visit(QmlJS::AST::UiObjectBinding *ast) const quint32 objectStart = ast->qualifiedTypeNameId->identifierToken.offset; if (objectStart == m_parentLocation) { - replaceInMembers(ast->initializer); + replaceInMembers(ast->initializer, m_name); return false; } return !didRewriting(); } -void ChangePropertyVisitor::replaceInMembers(UiObjectInitializer *initializer) +void ChangePropertyVisitor::replaceInMembers(UiObjectInitializer *initializer, + const QString &propertyName) { + QString prefix, suffix; + int dotIdx = propertyName.indexOf(QLatin1Char('.')); + if (dotIdx != -1) { + prefix = propertyName.left(dotIdx); + suffix = propertyName.mid(dotIdx + 1); + } + for (UiObjectMemberList *members = initializer->members; members; members = members->next) { - UiObjectMember *propertyMember = members->member; + UiObjectMember *member = members->member; - if (isMatchingPropertyMember(propertyMember)) { + // for non-grouped properties: + if (isMatchingPropertyMember(propertyName, member)) { switch (m_propertyType) { case QmlRefactoring::ArrayBinding: - insertIntoArray(cast<UiArrayBinding*>(propertyMember)); + insertIntoArray(cast<UiArrayBinding*>(member)); break; case QmlRefactoring::ObjectBinding: - replaceMemberValue(propertyMember, false); + replaceMemberValue(member, false); break; case QmlRefactoring::ScriptBinding: - replaceMemberValue(propertyMember, nextMemberOnSameLine(members)); + replaceMemberValue(member, nextMemberOnSameLine(members)); break; default: @@ -105,6 +114,14 @@ void ChangePropertyVisitor::replaceInMembers(UiObjectInitializer *initializer) break; } + // for grouped properties: + else if (!prefix.isEmpty()) { + if (UiObjectDefinition *def = cast<UiObjectDefinition *>(member)) { + if (flatten(def->qualifiedTypeNameId) == prefix) { + replaceInMembers(def->initializer, suffix); + } + } + } } } @@ -147,16 +164,17 @@ void ChangePropertyVisitor::replaceMemberValue(UiObjectMember *propertyMember, b setDidRewriting(true); } -bool ChangePropertyVisitor::isMatchingPropertyMember(QmlJS::AST::UiObjectMember *member) const +bool ChangePropertyVisitor::isMatchingPropertyMember(const QString &propName, + UiObjectMember *member) { if (UiObjectBinding *objectBinding = AST::cast<UiObjectBinding *>(member)) { - return m_name == flatten(objectBinding->qualifiedId); + return propName == flatten(objectBinding->qualifiedId); } else if (UiScriptBinding *scriptBinding = AST::cast<UiScriptBinding *>(member)) { - return m_name == flatten(scriptBinding->qualifiedId); + return propName == flatten(scriptBinding->qualifiedId); } else if (UiArrayBinding *arrayBinding = AST::cast<UiArrayBinding *>(member)) { - return m_name == flatten(arrayBinding->qualifiedId); + return propName == flatten(arrayBinding->qualifiedId); } else if (UiPublicMember *publicMember = AST::cast<UiPublicMember *>(member)) { - return m_name == publicMember->name->asString(); + return propName == publicMember->name->asString(); } else { return false; } diff --git a/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.h b/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.h index 3728bf3baa0..6dd92c4e687 100644 --- a/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.h +++ b/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.h @@ -50,9 +50,11 @@ protected: virtual bool visit(QmlJS::AST::UiObjectBinding *ast); private: - void replaceInMembers(QmlJS::AST::UiObjectInitializer *initializer); + void replaceInMembers(QmlJS::AST::UiObjectInitializer *initializer, + const QString &propertyName); void replaceMemberValue(QmlJS::AST::UiObjectMember *propertyMember, bool needsSemicolon); - bool isMatchingPropertyMember(QmlJS::AST::UiObjectMember *member) const; + static bool isMatchingPropertyMember(const QString &propName, + QmlJS::AST::UiObjectMember *member); static bool nextMemberOnSameLine(QmlJS::AST::UiObjectMemberList *members); void insertIntoArray(QmlJS::AST::UiArrayBinding* ast); diff --git a/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.cpp index 2c6d04fa151..a3dcd72f77f 100644 --- a/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.cpp +++ b/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.cpp @@ -65,35 +65,68 @@ bool RemovePropertyVisitor::visit(QmlJS::AST::UiObjectDefinition *ast) void RemovePropertyVisitor::removeFrom(QmlJS::AST::UiObjectInitializer *ast) { - UiObjectMember *previousMember = 0, *wantedMember = 0, *nextMember = 0; + QString prefix; + int dotIdx = propertyName.indexOf(QLatin1Char('.')); + if (dotIdx != -1) + prefix = propertyName.left(dotIdx); for (UiObjectMemberList *it = ast->members; it; it = it->next) { - if (memberNameMatchesPropertyName(it->member)) { - wantedMember = it->member; + UiObjectMember *member = it->member; - if (it->next) - nextMember = it->next->member; - - break; + // run full name match (for ungrouped properties): + if (memberNameMatchesPropertyName(propertyName, member)) { + removeMember(member); + } + // check for grouped properties: + else if (!prefix.isEmpty()) { + if (UiObjectDefinition *def = cast<UiObjectDefinition *>(member)) { + if (flatten(def->qualifiedTypeNameId) == prefix) { + removeGroupedProperty(def); + } + } } + } +} + +void RemovePropertyVisitor::removeGroupedProperty(UiObjectDefinition *ast) +{ + int dotIdx = propertyName.indexOf(QLatin1Char('.')); + if (dotIdx == -1) + return; - previousMember = it->member; + const QString propName = propertyName.mid(dotIdx + 1); + + UiObjectMember *wanted = 0; + unsigned memberCount = 0; + for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) { + ++memberCount; + UiObjectMember *member = it->member; + + if (!wanted && memberNameMatchesPropertyName(propName, member)) { + wanted = member; + } } - if (!wantedMember) + if (!wanted) return; + if (memberCount == 1) + removeMember(ast); + else + removeMember(wanted); +} - int start = wantedMember->firstSourceLocation().offset; - int end = wantedMember->lastSourceLocation().end(); +void RemovePropertyVisitor::removeMember(UiObjectMember *member) +{ + int start = member->firstSourceLocation().offset; + int end = member->lastSourceLocation().end(); includeSurroundingWhitespace(start, end); replace(start, end - start, QLatin1String("")); - setDidRewriting(true); } -bool RemovePropertyVisitor::memberNameMatchesPropertyName(QmlJS::AST::UiObjectMember *ast) const +bool RemovePropertyVisitor::memberNameMatchesPropertyName(const QString &propertyName, UiObjectMember *ast) { if (UiPublicMember *publicMember = cast<UiPublicMember*>(ast)) return publicMember->name->asString() == propertyName; diff --git a/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.h b/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.h index 74b313d57c4..4c1908855e3 100644 --- a/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.h +++ b/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.h @@ -50,7 +50,10 @@ protected: private: void removeFrom(QmlJS::AST::UiObjectInitializer *ast); - bool memberNameMatchesPropertyName(QmlJS::AST::UiObjectMember *ast) const; + static bool memberNameMatchesPropertyName(const QString &propertyName, + QmlJS::AST::UiObjectMember *ast); + void removeGroupedProperty(QmlJS::AST::UiObjectDefinition *ast); + void removeMember(QmlJS::AST::UiObjectMember *ast); private: quint32 parentLocation; diff --git a/tests/auto/qml/qmldesigner/coretests/testcore.cpp b/tests/auto/qml/qmldesigner/coretests/testcore.cpp index 8f57c67ad8d..854946b7e01 100644 --- a/tests/auto/qml/qmldesigner/coretests/testcore.cpp +++ b/tests/auto/qml/qmldesigner/coretests/testcore.cpp @@ -545,11 +545,11 @@ void TestCore::testRewriterGroupedProperties() " pointSize: 10\n" " underline: true\n" " }\n" - "}"); + "}\n"); - QPlainTextEdit textEdit1; - textEdit1.setPlainText(qmlString); - NotIndentingTextEditModifier modifier1(&textEdit1); + QPlainTextEdit textEdit; + textEdit.setPlainText(qmlString); + NotIndentingTextEditModifier modifier1(&textEdit); QScopedPointer<Model> model1(Model::create("Qt/Text")); @@ -565,6 +565,22 @@ void TestCore::testRewriterGroupedProperties() ModelNode rootModelNode = testRewriterView1->rootModelNode(); QCOMPARE(rootModelNode.property(QLatin1String("font.pointSize")).toVariantProperty().value().toDouble(), 10.0); QCOMPARE(rootModelNode.property(QLatin1String("font.underline")).toVariantProperty().value().toBool(), true); + + rootModelNode.removeProperty(QLatin1String("font.underline")); + QCOMPARE(rootModelNode.property(QLatin1String("font.pointSize")).toVariantProperty().value().toDouble(), 10.0); + QVERIFY(!rootModelNode.hasProperty(QLatin1String("font.underline"))); + + rootModelNode.variantProperty(QLatin1String("font.pointSize")).setValue(20.0); + QCOMPARE(rootModelNode.property(QLatin1String("font.pointSize")).toVariantProperty().value().toDouble(), 20.0); + + rootModelNode.removeProperty(QLatin1String("font.pointSize")); + const QLatin1String expected("\n" + "import Qt 4.6\n" + "\n" + "Text {\n" + "}\n"); + + QCOMPARE(textEdit.toPlainText(), expected); } void TestCore::loadSubItems() -- GitLab