SourceLocation QmlJS::locationFromRange(const SourceLocation &start, const SourceLocation &end) { return SourceLocation(start.offset, end.end() - start.begin(), start.startLine, start.startColumn); }
void out(const QString &str, const SourceLocation &lastLoc = SourceLocation()) { if (lastLoc.isValid()) { QList<SourceLocation> comments = _doc->engine()->comments(); for (; _nextComment < comments.size(); ++_nextComment) { SourceLocation commentLoc = comments.at(_nextComment); if (commentLoc.end() > lastLoc.end()) break; outComment(commentLoc); } } QStringList lines = str.split(QLatin1Char('\n')); for (int i = 0; i < lines.size(); ++i) { _line += lines.at(i); if (i != lines.size() - 1) newLine(); } _hadEmptyLine = false; }
QmlJS::AST::SourceLocation QMLRewriter::calculateLocation(QmlJS::AST::UiQualifiedId *id) { Q_ASSERT(id != 0); const SourceLocation startLocation = id->identifierToken; UiQualifiedId *nextId = id; while (nextId->next) { nextId = nextId->next; } const SourceLocation endLocation = nextId->identifierToken; return SourceLocation(startLocation.offset, endLocation.end() - startLocation.offset); }
Rewriter::Range Rewriter::addBinding(AST::UiObjectInitializer *ast, const QString &propertyName, const QString &propertyValue, BindingType bindingType, UiObjectMemberList *insertAfter) { SourceLocation endOfPreviousMember; SourceLocation startOfNextMember; if (insertAfter == 0 || insertAfter->member == 0) { // insert as first member endOfPreviousMember = ast->lbraceToken; if (ast->members && ast->members->member) startOfNextMember = ast->members->member->firstSourceLocation(); else startOfNextMember = ast->rbraceToken; } else { endOfPreviousMember = insertAfter->member->lastSourceLocation(); if (insertAfter->next && insertAfter->next->member) startOfNextMember = insertAfter->next->member->firstSourceLocation(); else startOfNextMember = ast->rbraceToken; } 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 (ast->members) { // we're inserting before a member (and not the rbrace) needsTrailingSemicolon = bindingType == 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 = bindingType == 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 (bindingType) { case ArrayBinding: newPropertyTemplate = QLatin1String("%1: [\n%2\n]"); break; case ObjectBinding: newPropertyTemplate = QLatin1String("%1: %2"); break; case ScriptBinding: newPropertyTemplate = QLatin1String("%1: %2"); break; default: Q_ASSERT(!"unknown property type"); } if (isOneLiner) { if (needsPreceedingSemicolon) newPropertyTemplate.prepend(QLatin1Char(';')); newPropertyTemplate.prepend(QLatin1Char(' ')); if (needsTrailingSemicolon) newPropertyTemplate.append(QLatin1Char(';')); } else { newPropertyTemplate.prepend(QLatin1Char('\n')); } m_changeSet->insert(endOfPreviousMember.end(), newPropertyTemplate.arg(propertyName, propertyValue)); return Range(endOfPreviousMember.end(), endOfPreviousMember.end()); }
// FIXME: duplicate code in the QmlJS::Rewriter class, remove this void AddPropertyVisitor::addInMembers(QmlJS::AST::UiObjectInitializer *initializer) { UiObjectMemberList *insertAfter = searchMemberToInsertAfter(initializer->members, m_name, m_propertyOrder); SourceLocation endOfPreviousMember; 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 = QLatin1String("%1: [\n%2\n]"); m_value = addIndentation(m_value, 4); break; case QmlRefactoring::ObjectBinding: newPropertyTemplate = QLatin1String("%1: %2"); break; case QmlRefactoring::ScriptBinding: newPropertyTemplate = QLatin1String("%1: %2"); break; default: Q_ASSERT(!"unknown property type"); } 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(m_name, m_value), depth); replace(endOfPreviousMember.end(), 0, newPropertyText); setDidRewriting(true); }
bool ScopeAstPath::containsOffset(SourceLocation start, SourceLocation end) { return _offset >= start.begin() && _offset <= end.end(); }