QmlJS::AST::SourceLocation QMLRewriter::calculateLocation(QmlJS::AST::UiQualifiedId *id) { Q_ASSERT(id != 0); const QmlJS::AST::SourceLocation startLocation = id->identifierToken; QmlJS::AST::UiQualifiedId *nextId = id; while (nextId->next) { nextId = nextId->next; } const QmlJS::AST::SourceLocation endLocation = nextId->identifierToken; return QmlJS::AST::SourceLocation(startLocation.offset, endLocation.end() - startLocation.offset); }
// FIXME: duplicate code in the QmlJS::Rewriter class, remove this void AddPropertyVisitor::addInMembers(QmlJS::AST::UiObjectInitializer *initializer) { QmlJS::AST::UiObjectMemberList *insertAfter = searchMemberToInsertAfter(initializer->members, m_name, m_propertyOrder); QmlJS::AST::SourceLocation endOfPreviousMember; QmlJS::AST::SourceLocation startOfNextMember; unsigned depth; if (insertAfter == 0 || insertAfter->member == 0) { // insert as first member endOfPreviousMember = initializer->lbraceToken; if (initializer->members && initializer->members->member) startOfNextMember = initializer->members->member->firstSourceLocation(); else startOfNextMember = initializer->rbraceToken; depth = calculateIndentDepth(endOfPreviousMember) + indentDepth(); } else { endOfPreviousMember = insertAfter->member->lastSourceLocation(); if (insertAfter->next && insertAfter->next->member) startOfNextMember = insertAfter->next->member->firstSourceLocation(); else startOfNextMember = initializer->rbraceToken; depth = calculateIndentDepth(endOfPreviousMember); } const bool isOneLiner = endOfPreviousMember.startLine == startOfNextMember.startLine; bool needsPreceedingSemicolon = false; bool needsTrailingSemicolon = false; if (isOneLiner) { if (insertAfter == 0) { // we're inserting after an lbrace if (initializer->members) { // we're inserting before a member (and not the rbrace) needsTrailingSemicolon = m_propertyType == QmlRefactoring::ScriptBinding; } } else { // we're inserting after a member, not after the lbrace if (endOfPreviousMember.isValid()) { // there already is a semicolon after the previous member if (insertAfter->next && insertAfter->next->member) { // and the after us there is a member, not an rbrace, so: needsTrailingSemicolon = m_propertyType == QmlRefactoring::ScriptBinding; } } else { // there is no semicolon after the previous member (probably because there is an rbrace after us/it, so: needsPreceedingSemicolon = true; } } } QString newPropertyTemplate; switch (m_propertyType) { case QmlRefactoring::ArrayBinding: newPropertyTemplate = QStringLiteral("%1: [\n%2\n]"); m_value = addIndentation(m_value, 4); break; case QmlRefactoring::ObjectBinding: newPropertyTemplate = QStringLiteral("%1: %2"); break; case QmlRefactoring::ScriptBinding: newPropertyTemplate = QStringLiteral("%1: %2"); break; default: Q_ASSERT(!"unknown property type"); } if (!m_dynamicTypeName.isEmpty()) newPropertyTemplate.prepend(QStringLiteral("property %1 ").arg(QString::fromUtf8(m_dynamicTypeName))); if (isOneLiner) { if (needsPreceedingSemicolon) newPropertyTemplate.prepend(QLatin1Char(';')); newPropertyTemplate.prepend(QLatin1Char(' ')); if (needsTrailingSemicolon) newPropertyTemplate.append(QLatin1Char(';')); depth = 0; } else { newPropertyTemplate.prepend(QLatin1Char('\n')); } const QString newPropertyText = addIndentation(newPropertyTemplate.arg(QString::fromLatin1(m_name), m_value), depth); replace(endOfPreviousMember.end(), 0, newPropertyText); setDidRewriting(true); }
void MoveObjectBeforeObjectVisitor::doMove() { Q_ASSERT(movingObject); Q_ASSERT(!movingObjectParents.isEmpty()); TextModifier::MoveInfo moveInfo; QmlJS::AST::Node *parent = movingObjectParent(); QmlJS::AST::UiArrayMemberList *arrayMember = 0, *otherArrayMember = 0; QString separator; if (!inDefaultProperty) { QmlJS::AST::UiArrayBinding *initializer = QmlJS::AST::cast<QmlJS::AST::UiArrayBinding*>(parent); Q_ASSERT(initializer); otherArrayMember = 0; for (QmlJS::AST::UiArrayMemberList *cur = initializer->members; cur; cur = cur->next) { if (cur->member == movingObject) { arrayMember = cur; if (cur->next) otherArrayMember = cur->next; break; } otherArrayMember = cur; } Q_ASSERT(arrayMember && otherArrayMember); separator = QStringLiteral(","); } moveInfo.objectStart = movingObject->firstSourceLocation().offset; moveInfo.objectEnd = movingObject->lastSourceLocation().end(); int start = moveInfo.objectStart; int end = moveInfo.objectEnd; if (!inDefaultProperty) { if (arrayMember->commaToken.isValid()) start = arrayMember->commaToken.begin(); else end = otherArrayMember->commaToken.end(); } includeSurroundingWhitespace(start, end); moveInfo.leadingCharsToRemove = moveInfo.objectStart - start; moveInfo.trailingCharsToRemove = end - moveInfo.objectEnd; if (beforeObject) { moveInfo.destination = beforeObject->firstSourceLocation().offset; int dummy = -1; includeSurroundingWhitespace(moveInfo.destination, dummy); moveInfo.prefixToInsert = QString(moveInfo.leadingCharsToRemove, QLatin1Char(' ')); moveInfo.suffixToInsert = separator + QStringLiteral("\n\n"); } else { const QmlJS::AST::SourceLocation insertionPoint = lastParentLocation(); Q_ASSERT(insertionPoint.isValid()); moveInfo.destination = insertionPoint.offset; int dummy = -1; includeSurroundingWhitespace(moveInfo.destination, dummy); moveInfo.prefixToInsert = separator + QString(moveInfo.leadingCharsToRemove, QLatin1Char(' ')); moveInfo.suffixToInsert = QStringLiteral("\n"); } move(moveInfo); setDidRewriting(true); }