QmlJSEditor: Support dragging of functions

Currently you can drag around items and properties.
Extend this by JS functions.

Fixes: QTCREATORBUG-21993
Change-Id: I2934450cbaf8646620b43ce33fdb523b5d2803ab
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
Christian Stenger
2020-05-26 18:02:38 +02:00
parent b176a24091
commit e2ae2ad41d
4 changed files with 34 additions and 17 deletions

View File

@@ -649,17 +649,20 @@ Rewriter::Range Rewriter::addObject(UiArrayBinding *ast, const QString &content,
return Range(insertionPoint, insertionPoint); return Range(insertionPoint, insertionPoint);
} }
void Rewriter::removeObjectMember(UiObjectMember *member, UiObjectMember *parent) void Rewriter::removeObjectMember(Node *member, UiObjectMember *parent)
{ {
int start = member->firstSourceLocation().offset; int start = member->firstSourceLocation().offset;
int end = member->lastSourceLocation().end(); int end = member->lastSourceLocation().end();
if (UiArrayBinding *parentArray = cast<UiArrayBinding *>(parent)) { auto uiObjMember = member->uiObjectMemberCast();
extendToLeadingOrTrailingComma(parentArray, member, start, end); if (uiObjMember) {
} else { if (UiArrayBinding *parentArray = cast<UiArrayBinding *>(parent)) {
if (UiObjectDefinition *parentObjectDefinition = cast<UiObjectDefinition *>(parent)) extendToLeadingOrTrailingComma(parentArray, uiObjMember, start, end);
includeEmptyGroupedProperty(parentObjectDefinition, member, start, end); } else {
includeSurroundingWhitespace(m_originalText, start, end); if (UiObjectDefinition *parentObjectDefinition = cast<UiObjectDefinition *>(parent))
includeEmptyGroupedProperty(parentObjectDefinition, uiObjMember, start, end);
includeSurroundingWhitespace(m_originalText, start, end);
}
} }
includeLeadingEmptyLine(m_originalText, start); includeLeadingEmptyLine(m_originalText, start);

View File

@@ -75,7 +75,7 @@ public:
Range addObject(AST::UiArrayBinding *ast, const QString &content); Range addObject(AST::UiArrayBinding *ast, const QString &content);
Range addObject(AST::UiArrayBinding *ast, const QString &content, AST::UiArrayMemberList *insertAfter); Range addObject(AST::UiArrayBinding *ast, const QString &content, AST::UiArrayMemberList *insertAfter);
void removeObjectMember(AST::UiObjectMember *member, AST::UiObjectMember *parent); void removeObjectMember(AST::Node *member, AST::UiObjectMember *parent);
static AST::UiObjectMemberList *searchMemberToInsertAfter(AST::UiObjectMemberList *members, const QStringList &propertyOrder); static AST::UiObjectMemberList *searchMemberToInsertAfter(AST::UiObjectMemberList *members, const QStringList &propertyOrder);
static AST::UiArrayMemberList *searchMemberToInsertAfter(AST::UiArrayMemberList *members, const QStringList &propertyOrder); static AST::UiArrayMemberList *searchMemberToInsertAfter(AST::UiArrayMemberList *members, const QStringList &propertyOrder);

View File

@@ -120,7 +120,7 @@ QString QmlOutlineItem::prettyPrint(const Value *value, const ContextPtr &contex
class ObjectMemberParentVisitor : public AST::Visitor class ObjectMemberParentVisitor : public AST::Visitor
{ {
public: public:
QHash<AST::UiObjectMember*,AST::UiObjectMember*> operator()(Document::Ptr doc) { QHash<AST::Node *,AST::UiObjectMember *> operator()(Document::Ptr doc) {
parent.clear(); parent.clear();
if (doc && doc->ast()) if (doc && doc->ast())
doc->ast()->accept(this); doc->ast()->accept(this);
@@ -128,7 +128,7 @@ public:
} }
private: private:
QHash<AST::UiObjectMember*,AST::UiObjectMember*> parent; QHash<AST::Node *, AST::UiObjectMember *> parent;
QList<AST::UiObjectMember *> stack; QList<AST::UiObjectMember *> stack;
bool preVisit(AST::Node *node) override bool preVisit(AST::Node *node) override
@@ -144,6 +144,9 @@ private:
stack.removeLast(); stack.removeLast();
if (!stack.isEmpty()) if (!stack.isEmpty())
parent.insert(objMember, stack.last()); parent.insert(objMember, stack.last());
} else if (AST::FunctionExpression *funcMember = node->asFunctionDefinition()) {
if (!stack.isEmpty())
parent.insert(funcMember, stack.last());
} }
} }
@@ -848,9 +851,14 @@ void QmlOutlineModel::reparentNodes(QmlOutlineItem *targetItem, int row, QList<Q
for (auto outlineItem : itemsToMove) { for (auto outlineItem : itemsToMove) {
AST::UiObjectMember *sourceObjectMember = m_itemToNode.value(outlineItem)->uiObjectMemberCast(); AST::UiObjectMember *sourceObjectMember = m_itemToNode.value(outlineItem)->uiObjectMemberCast();
if (!sourceObjectMember) AST::FunctionExpression *functionMember = nullptr;
return; if (!sourceObjectMember) {
functionMember = m_itemToNode.value(outlineItem)->asFunctionDefinition();
if (!functionMember)
return;
}
m_itemToNode.value(outlineItem)->asFunctionDefinition();
bool insertionOrderSpecified = true; bool insertionOrderSpecified = true;
AST::UiObjectMember *memberToInsertAfter = nullptr; AST::UiObjectMember *memberToInsertAfter = nullptr;
{ {
@@ -866,6 +874,9 @@ void QmlOutlineModel::reparentNodes(QmlOutlineItem *targetItem, int row, QList<Q
if (sourceObjectMember) if (sourceObjectMember)
moveObjectMember(sourceObjectMember, targetObjectMember, insertionOrderSpecified, moveObjectMember(sourceObjectMember, targetObjectMember, insertionOrderSpecified,
memberToInsertAfter, &changeSet, &range); memberToInsertAfter, &changeSet, &range);
else if (functionMember)
moveObjectMember(functionMember, targetObjectMember, insertionOrderSpecified,
memberToInsertAfter, &changeSet, &range);
changedRanges << range; changedRanges << range;
} }
@@ -878,7 +889,7 @@ void QmlOutlineModel::reparentNodes(QmlOutlineItem *targetItem, int row, QList<Q
file->apply(); file->apply();
} }
void QmlOutlineModel::moveObjectMember(AST::UiObjectMember *toMove, void QmlOutlineModel::moveObjectMember(AST::Node *toMove,
AST::UiObjectMember *newParent, AST::UiObjectMember *newParent,
bool insertionOrderSpecified, bool insertionOrderSpecified,
AST::UiObjectMember *insertAfter, AST::UiObjectMember *insertAfter,
@@ -889,7 +900,7 @@ void QmlOutlineModel::moveObjectMember(AST::UiObjectMember *toMove,
Q_ASSERT(newParent); Q_ASSERT(newParent);
Q_ASSERT(changeSet); Q_ASSERT(changeSet);
QHash<AST::UiObjectMember*, AST::UiObjectMember*> parentMembers; QHash<AST::Node *, AST::UiObjectMember *> parentMembers;
{ {
ObjectMemberParentVisitor visitor; ObjectMemberParentVisitor visitor;
parentMembers = visitor(m_semanticInfo.document); parentMembers = visitor(m_semanticInfo.document);
@@ -899,8 +910,11 @@ void QmlOutlineModel::moveObjectMember(AST::UiObjectMember *toMove,
Q_ASSERT(oldParent); Q_ASSERT(oldParent);
// make sure that target parent is actually a direct ancestor of target sibling // make sure that target parent is actually a direct ancestor of target sibling
if (insertAfter) if (insertAfter) {
newParent = parentMembers.value(insertAfter); auto objMember = parentMembers.value(insertAfter);
Q_ASSERT(objMember);
newParent = objMember;
}
const QString documentText = m_semanticInfo.document->source(); const QString documentText = m_semanticInfo.document->source();

View File

@@ -131,7 +131,7 @@ private:
void leaveNode(); void leaveNode();
void reparentNodes(QmlOutlineItem *targetItem, int targetRow, QList<QmlOutlineItem*> itemsToMove); void reparentNodes(QmlOutlineItem *targetItem, int targetRow, QList<QmlOutlineItem*> itemsToMove);
void moveObjectMember(QmlJS::AST::UiObjectMember *toMove, QmlJS::AST::UiObjectMember *newParent, void moveObjectMember(QmlJS::AST::Node *toMove, QmlJS::AST::UiObjectMember *newParent,
bool insertionOrderSpecified, QmlJS::AST::UiObjectMember *insertAfter, bool insertionOrderSpecified, QmlJS::AST::UiObjectMember *insertAfter,
Utils::ChangeSet *changeSet, Utils::ChangeSet::Range *addedRange); Utils::ChangeSet *changeSet, Utils::ChangeSet::Range *addedRange);