Commit eb749ec3 authored by Roberto Raggi's avatar Roberto Raggi
Browse files

Generalized the changeset operations.

parent b13d6ae3
......@@ -131,7 +131,7 @@ void ChangeSet::clear()
m_error = false;
}
bool ChangeSet::replace(int pos, int length, const QString &replacement)
bool ChangeSet::replace_helper(int pos, int length, const QString &replacement)
{
if (hasOverlap(pos, length))
m_error = true;
......@@ -145,7 +145,7 @@ bool ChangeSet::replace(int pos, int length, const QString &replacement)
return !m_error;
}
bool ChangeSet::move(int pos, int length, int to)
bool ChangeSet::move_helper(int pos, int length, int to)
{
if (hasOverlap(pos, length)
|| hasOverlap(to, 0)
......@@ -174,7 +174,7 @@ bool ChangeSet::insert(int pos, const QString &text)
return !m_error;
}
bool ChangeSet::remove(int pos, int length)
bool ChangeSet::remove_helper(int pos, int length)
{
if (hasOverlap(pos, length))
m_error = true;
......@@ -187,7 +187,7 @@ bool ChangeSet::remove(int pos, int length)
return !m_error;
}
bool ChangeSet::flip(int pos1, int length1, int pos2, int length2)
bool ChangeSet::flip_helper(int pos1, int length1, int pos2, int length2)
{
if (hasOverlap(pos1, length1)
|| hasOverlap(pos2, length2)
......@@ -204,7 +204,7 @@ bool ChangeSet::flip(int pos1, int length1, int pos2, int length2)
return !m_error;
}
bool ChangeSet::copy(int pos, int length, int to)
bool ChangeSet::copy_helper(int pos, int length, int to)
{
if (hasOverlap(pos, length)
|| hasOverlap(to, 0)
......@@ -220,27 +220,27 @@ bool ChangeSet::copy(int pos, int length, int to)
return !m_error;
}
void ChangeSet::doReplace(const EditOp &replace, QList<EditOp> *replaceList)
void ChangeSet::doReplace(const EditOp &replace_helper, QList<EditOp> *replaceList)
{
Q_ASSERT(replace.type == EditOp::Replace);
Q_ASSERT(replace_helper.type == EditOp::Replace);
{
QMutableListIterator<EditOp> i(*replaceList);
while (i.hasNext()) {
EditOp &c = i.next();
if (replace.pos1 <= c.pos1)
c.pos1 += replace.text.size();
if (replace.pos1 < c.pos1)
c.pos1 -= replace.length1;
if (replace_helper.pos1 <= c.pos1)
c.pos1 += replace_helper.text.size();
if (replace_helper.pos1 < c.pos1)
c.pos1 -= replace_helper.length1;
}
}
if (m_string) {
m_string->replace(replace.pos1, replace.length1, replace.text);
m_string->replace(replace_helper.pos1, replace_helper.length1, replace_helper.text);
} else if (m_cursor) {
m_cursor->setPosition(replace.pos1);
m_cursor->setPosition(replace.pos1 + replace.length1, QTextCursor::KeepAnchor);
m_cursor->insertText(replace.text);
m_cursor->setPosition(replace_helper.pos1);
m_cursor->setPosition(replace_helper.pos1 + replace_helper.length1, QTextCursor::KeepAnchor);
m_cursor->insertText(replace_helper.text);
}
}
......
......@@ -77,6 +77,17 @@ public:
QString text;
};
struct Range {
Range()
: start(0), end(0) {}
Range(int start, int end)
: start(start), end(end) {}
int start;
int end;
};
public:
ChangeSet();
......@@ -86,12 +97,38 @@ public:
void clear();
bool replace(int pos, int length, const QString &replacement);
bool move(int pos, int length, int to);
bool replace(const Range &range, const QString &replacement)
{ return replace(range.start, range.end, replacement); }
bool remove(const Range &range)
{ return remove(range.start, range.end); }
bool move(const Range &range, int to)
{ return move(range.start, range.end, to); }
bool flip(const Range &range1, const Range &range2)
{ return flip(range1.start, range1.end, range2.start, range2.end); }
bool copy(const Range &range, int to)
{ return copy(range.start, range.end, to); }
bool replace(int start, int end, const QString &replacement)
{ return replace_helper(start, end - start, replacement); }
bool remove(int start, int end)
{ return remove_helper(start, end - start); }
bool move(int start, int end, int to)
{ return move_helper(start, end - start, to); }
bool flip(int start1, int end1, int start2, int end2)
{ return flip_helper(start1, end1 - start1, start2, end2 - start2); }
bool copy(int start, int end, int to)
{ return copy_helper(start, end - start, to); }
bool insert(int pos, const QString &text);
bool remove(int pos, int length);
bool flip(int pos1, int length1, int pos2, int length2);
bool copy(int pos, int length, int to);
bool hadErrors();
......@@ -99,6 +136,12 @@ public:
void apply(QTextCursor *textCursor);
private:
bool replace_helper(int pos, int length, const QString &replacement);
bool move_helper(int pos, int length, int to);
bool remove_helper(int pos, int length);
bool flip_helper(int pos1, int length1, int pos2, int length2);
bool copy_helper(int pos, int length, int to);
bool hasOverlap(int pos, int length);
QString textAt(int pos, int length);
......
......@@ -141,14 +141,14 @@ public:
ChangeSet changes;
if (negation) {
// can't remove parentheses since that might break precedence
remove(&changes, negation->unary_op_token);
changes.remove(range(negation->unary_op_token));
} else if (nested) {
changes.insert(startOf(nested), "!");
} else {
changes.insert(startOf(binary), "!(");
changes.insert(endOf(binary), ")");
}
replace(&changes, binary->binary_op_token, replacement);
changes.replace(range(binary->binary_op_token), replacement);
refactoringChanges()->changeFile(fileName(), changes);
}
......@@ -228,9 +228,9 @@ public:
{
ChangeSet changes;
flip(&changes, binary->left_expression, binary->right_expression);
changes.flip(range(binary->left_expression), range(binary->right_expression));
if (! replacement.isEmpty())
replace(&changes, binary->binary_op_token, replacement);
changes.replace(range(binary->binary_op_token), replacement);
refactoringChanges()->changeFile(fileName(), changes);
}
......@@ -293,16 +293,16 @@ public:
virtual void createChanges()
{
ChangeSet changes;
replace(&changes, pattern->binary_op_token, QLatin1String("||"));
remove(&changes, left->unary_op_token);
remove(&changes, right->unary_op_token);
changes.replace(range(pattern->binary_op_token), QLatin1String("||"));
changes.remove(range(left->unary_op_token));
changes.remove(range(right->unary_op_token));
const int start = startOf(pattern);
const int end = endOf(pattern);
changes.insert(start, QLatin1String("!("));
changes.insert(end, QLatin1String(")"));
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->reindent(fileName(), range(start, end));
refactoringChanges()->reindent(fileName(), range(pattern));
}
private:
......@@ -401,20 +401,19 @@ public:
DeclaratorAST *declarator = it->value;
changes.insert(insertPos, QLatin1String("\n"));
changes.copy(declSpecifiersStart, declSpecifiersEnd - declSpecifiersStart, insertPos);
changes.copy(declSpecifiersStart, declSpecifiersEnd, insertPos);
changes.insert(insertPos, QLatin1String(" "));
move(&changes, declarator, insertPos);
changes.move(range(declarator), insertPos);
changes.insert(insertPos, QLatin1String(";"));
const int prevDeclEnd = endOf(prevDeclarator);
changes.remove(prevDeclEnd, startOf(declarator) - prevDeclEnd);
changes.remove(prevDeclEnd, startOf(declarator));
prevDeclarator = declarator;
}
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->reindent(fileName(), range(startOf(declaration->firstToken()),
endOf(declaration->lastToken() - 1)));
refactoringChanges()->reindent(fileName(), range(declaration));
}
private:
......@@ -531,15 +530,14 @@ public:
{
ChangeSet changes;
copy(&changes, core, startOf(condition));
changes.copy(range(core), startOf(condition));
int insertPos = startOf(pattern);
move(&changes, condition, insertPos);
changes.move(range(condition), insertPos);
changes.insert(insertPos, QLatin1String(";\n"));
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->reindent(fileName(), range(startOf(pattern),
endOf(pattern)));
refactoringChanges()->reindent(fileName(), range(pattern));
}
private:
......@@ -610,13 +608,12 @@ public:
int insertPos = startOf(pattern);
const int conditionStart = startOf(condition);
changes.move(conditionStart, startOf(core) - conditionStart, insertPos);
copy(&changes, core, insertPos);
changes.move(conditionStart, startOf(core), insertPos);
changes.copy(range(core), insertPos);
changes.insert(insertPos, QLatin1String(";\n"));
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->reindent(fileName(), range(startOf(pattern),
endOf(pattern)));
refactoringChanges()->reindent(fileName(), range(pattern));
}
private:
......@@ -721,17 +718,15 @@ public:
int startPos = startOf(pattern);
changes.insert(startPos, QLatin1String("if ("));
move(&changes, condition->left_expression, startPos);
changes.move(range(condition->left_expression), startPos);
changes.insert(startPos, QLatin1String(") {\n"));
const int lExprEnd = endOf(condition->left_expression);
changes.remove(lExprEnd,
startOf(condition->right_expression) - lExprEnd);
changes.remove(lExprEnd, startOf(condition->right_expression));
changes.insert(endOf(pattern), QLatin1String("\n}"));
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->reindent(fileName(), range(startOf(pattern),
endOf(pattern)));
refactoringChanges()->reindent(fileName(), range(pattern));
}
void splitOrCondition()
......@@ -749,19 +744,17 @@ public:
changes.insert(insertPos, QLatin1String("else if ("));
const int rExprStart = startOf(condition->right_expression);
changes.move(rExprStart, startOf(pattern->rparen_token) - rExprStart,
insertPos);
changes.move(rExprStart, startOf(pattern->rparen_token), insertPos);
changes.insert(insertPos, QLatin1String(")"));
const int rParenEnd = endOf(pattern->rparen_token);
changes.copy(rParenEnd, endOf(pattern->statement) - rParenEnd, insertPos);
changes.copy(rParenEnd, endOf(pattern->statement), insertPos);
const int lExprEnd = endOf(condition->left_expression);
changes.remove(lExprEnd, startOf(condition->right_expression) - lExprEnd);
changes.remove(lExprEnd, startOf(condition->right_expression));
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->reindent(fileName(), range(startOf(pattern),
endOf(pattern)));
refactoringChanges()->reindent(fileName(), range(pattern));
}
private:
......@@ -833,7 +826,7 @@ public:
const QLatin1String replacement("QLatin1String(");
if (isObjCStringLiteral)
changes.replace(startPos, 1, replacement);
changes.replace(startPos, startPos + 1, replacement);
else
changes.insert(startPos, replacement);
......@@ -905,11 +898,8 @@ public:
ChangeSet changes;
if (qlatin1Call) {
changes.replace(startOf(qlatin1Call),
startOf(stringLiteral) - startOf(qlatin1Call),
QLatin1String("@"));
changes.remove(endOf(stringLiteral),
endOf(qlatin1Call) - endOf(stringLiteral));
changes.replace(startOf(qlatin1Call), startOf(stringLiteral), QLatin1String("@"));
changes.remove(endOf(stringLiteral), endOf(qlatin1Call));
} else {
changes.insert(startOf(stringLiteral), "@");
}
......@@ -948,6 +938,17 @@ int CppQuickFixOperation::match(TextEditor::QuickFixState *state)
return match(s->path);
}
Utils::ChangeSet::Range CppQuickFixOperation::range(unsigned tokenIndex) const
{
const CPlusPlus::Token &token = tokenAt(tokenIndex);
return Utils::ChangeSet::Range(token.begin(), token.end());
}
Utils::ChangeSet::Range CppQuickFixOperation::range(CPlusPlus::AST *ast) const
{
return Utils::ChangeSet::Range(startOf(ast), endOf(ast));
}
QString CppQuickFixOperation::fileName() const
{ return document()->fileName(); }
......@@ -1034,93 +1035,6 @@ bool CppQuickFixOperation::isCursorOn(const CPlusPlus::AST *ast) const
return false;
}
void CppQuickFixOperation::move(ChangeSet *changeSet, unsigned tokenIndex,
int to)
{
Q_ASSERT(changeSet);
int start, end;
startAndEndOf(tokenIndex, &start, &end);
changeSet->move(start, end - start, to);
}
void CppQuickFixOperation::move(ChangeSet *changeSet, const CPlusPlus::AST *ast,
int to)
{
Q_ASSERT(changeSet);
const int start = startOf(ast);
changeSet->move(start, endOf(ast) - start, to);
}
void CppQuickFixOperation::replace(ChangeSet *changeSet, unsigned tokenIndex,
const QString &replacement)
{
Q_ASSERT(changeSet);
int start, end;
startAndEndOf(tokenIndex, &start, &end);
changeSet->replace(start, end - start, replacement);
}
void CppQuickFixOperation::replace(ChangeSet *changeSet,
const CPlusPlus::AST *ast,
const QString &replacement)
{
Q_ASSERT(changeSet);
const int start = startOf(ast);
changeSet->replace(start, endOf(ast) - start, replacement);
}
void CppQuickFixOperation::remove(ChangeSet *changeSet, unsigned tokenIndex)
{
Q_ASSERT(changeSet);
int start, end;
startAndEndOf(tokenIndex, &start, &end);
changeSet->remove(start, end - start);
}
void CppQuickFixOperation::remove(ChangeSet *changeSet, const CPlusPlus::AST *ast)
{
Q_ASSERT(changeSet);
const int start = startOf(ast);
changeSet->remove(start, endOf(ast) - start);
}
void CppQuickFixOperation::flip(ChangeSet *changeSet,
const CPlusPlus::AST *ast1,
const CPlusPlus::AST *ast2)
{
Q_ASSERT(changeSet);
const int start1 = startOf(ast1);
const int start2 = startOf(ast2);
changeSet->flip(start1, endOf(ast1) - start1,
start2, endOf(ast2) - start2);
}
void CppQuickFixOperation::copy(ChangeSet *changeSet, unsigned tokenIndex,
int to)
{
Q_ASSERT(changeSet);
int start, end;
startAndEndOf(tokenIndex, &start, &end);
changeSet->copy(start, end - start, to);
}
void CppQuickFixOperation::copy(ChangeSet *changeSet, const CPlusPlus::AST *ast,
int to)
{
Q_ASSERT(changeSet);
const int start = startOf(ast);
changeSet->copy(start, endOf(ast) - start, to);
}
QString CppQuickFixOperation::textOf(const AST *ast) const
{
return textOf(startOf(ast), endOf(ast));
......
......@@ -66,6 +66,11 @@ public:
virtual int match(TextEditor::QuickFixState *state);
protected:
using TextEditor::QuickFixOperation::range;
Utils::ChangeSet::Range range(unsigned tokenIndex) const;
Utils::ChangeSet::Range range(CPlusPlus::AST *ast) const;
QString fileName() const;
virtual void apply();
......@@ -85,19 +90,6 @@ protected:
using TextEditor::QuickFixOperation::textOf;
using TextEditor::QuickFixOperation::charAt;
void move(Utils::ChangeSet *changeSet, unsigned tokenIndex, int to);
void move(Utils::ChangeSet *changeSet, const CPlusPlus::AST *ast, int to);
void replace(Utils::ChangeSet *changeSet, unsigned tokenIndex,
const QString &replacement);
void replace(Utils::ChangeSet *changeSet, const CPlusPlus::AST *ast,
const QString &replacement);
void remove(Utils::ChangeSet *changeSet, unsigned tokenIndex);
void remove(Utils::ChangeSet *changeSet, const CPlusPlus::AST *ast);
void flip(Utils::ChangeSet *changeSet, const CPlusPlus::AST *ast1,
const CPlusPlus::AST *ast2);
void copy(Utils::ChangeSet *changeSet, unsigned tokenIndex, int to);
void copy(Utils::ChangeSet *changeSet, const CPlusPlus::AST *ast, int to);
QString textOf(const CPlusPlus::AST *ast) const;
private:
......
......@@ -76,11 +76,11 @@ void PlainTextEditModifier::replace(int offset, int length, const QString &repla
const int replacementLength = replacement.length();
if (m_changeSet) {
m_changeSet->replace(offset, length, replacement);
m_changeSet->replace(offset, offset + length, replacement);
emit replaced(offset, length, replacementLength);
} else {
ChangeSet changeSet;
changeSet.replace(offset, length, replacement);
changeSet.replace(offset, offset + length, replacement);
emit replaced(offset, length, replacementLength);
runRewriting(&changeSet);
}
......@@ -97,18 +97,18 @@ void PlainTextEditModifier::move(const MoveInfo &moveInfo)
if (m_changeSet) {
m_changeSet->insert(moveInfo.destination, moveInfo.prefixToInsert);
m_changeSet->move(moveInfo.objectStart, moveInfo.objectEnd - moveInfo.objectStart, moveInfo.destination);
m_changeSet->move(moveInfo.objectStart, moveInfo.objectEnd, moveInfo.destination);
m_changeSet->insert(moveInfo.destination, moveInfo.suffixToInsert);
m_changeSet->remove(moveInfo.objectStart - moveInfo.leadingCharsToRemove, moveInfo.leadingCharsToRemove);
m_changeSet->remove(moveInfo.objectEnd, moveInfo.trailingCharsToRemove);
m_changeSet->remove(moveInfo.objectStart - moveInfo.leadingCharsToRemove, moveInfo.objectStart);
m_changeSet->remove(moveInfo.objectEnd, moveInfo.objectEnd + moveInfo.trailingCharsToRemove);
emit moved(moveInfo);
} else {
ChangeSet changeSet;
changeSet.insert(moveInfo.destination, moveInfo.prefixToInsert);
changeSet.move(moveInfo.objectStart, moveInfo.objectEnd - moveInfo.objectStart, moveInfo.destination);
changeSet.move(moveInfo.objectStart, moveInfo.objectEnd, moveInfo.destination);
changeSet.insert(moveInfo.destination, moveInfo.suffixToInsert);
changeSet.remove(moveInfo.objectStart - moveInfo.leadingCharsToRemove, moveInfo.leadingCharsToRemove);
changeSet.remove(moveInfo.objectEnd, moveInfo.trailingCharsToRemove);
changeSet.remove(moveInfo.objectStart - moveInfo.leadingCharsToRemove, moveInfo.objectStart);
changeSet.remove(moveInfo.objectEnd, moveInfo.objectEnd + moveInfo.trailingCharsToRemove);
emit moved(moveInfo);
runRewriting(&changeSet);
}
......
......@@ -103,7 +103,7 @@ void ComponentFromObjectDef::createChanges()
const QString txt = imports + textOf(start, end) + QLatin1String("}\n");
Utils::ChangeSet changes;
changes.replace(start, end - start, componentName + QLatin1String(" {\n"));
changes.replace(start, end, componentName + QLatin1String(" {\n"));
qmljsRefactoringChanges()->changeFile(fileName(), changes);
qmljsRefactoringChanges()->reindent(fileName(), range(start, end + 1));
......
......@@ -880,7 +880,7 @@ void QmlJSTextEditor::renameIdUnderCursor()
Utils::ChangeSet changeSet;
foreach (const AST::SourceLocation &loc, m_semanticInfo.idLocations.value(id)) {
changeSet.replace(loc.offset, loc.length, newId);
changeSet.replace(loc.begin(), loc.end(), newId);
}
QTextCursor tc = textCursor();
......
......@@ -73,7 +73,7 @@ QStringList RefactoringChanges::apply()
foreach (const Range &range, m_indentRangesByFile.value(fileName, QList<Range>())) {
QTextCursor indentCursor = editor->textCursor();
indentCursor.setPosition(range.begin);
indentCursor.setPosition(range.start);
indentCursor.setPosition(range.end, QTextCursor::KeepAnchor);
editor->indentInsertedText(indentCursor);
}
......@@ -97,7 +97,7 @@ QStringList RefactoringChanges::apply()
foreach (const Range &range, m_indentRangesByFile.value(fileName, QList<Range>())) {
QTextCursor start = editor->textCursor();
QTextCursor end = editor->textCursor();
start.setPosition(range.begin);
start.setPosition(range.start);
end.setPosition(range.end);
cursorPairs.append(qMakePair(start, end));
}
......@@ -133,7 +133,7 @@ QStringList RefactoringChanges::apply()
foreach (const Range &range, m_indentRangesByFile.value(fileName, QList<Range>())) {
QTextCursor indentCursor = editor->textCursor();
indentCursor.setPosition(range.begin);
indentCursor.setPosition(range.start);
indentCursor.setPosition(range.end, QTextCursor::KeepAnchor);
editor->indentInsertedText(indentCursor);
}
......
......@@ -43,22 +43,7 @@ namespace TextEditor {
class TEXTEDITOR_EXPORT RefactoringChanges
{
public:
struct Range {
Range()
: begin(0)
, end(0)
{}
Range(int beginPosition, int endPosition)
: begin(beginPosition)
, end(endPosition)
{}
bool isNull() const
{ return begin == 0 || end == 0; }
int begin;
int end;
};
typedef Utils::ChangeSet::Range Range;