Commit 1c1b3840 authored by Leandro Melo's avatar Leandro Melo

Editors: Fix refactoring changes indent ranges selections

This also fix an error by 1 when reindenting for the extract function quickfix.

Change-Id: Icd666edf4c4473322a4d4d9ed5f3ca7fbbfb7d83
Reviewed-by: default avatarRoberto Raggi <>
parent 761bef0a
......@@ -458,11 +458,8 @@ public:
if (!extract.endsWith(QLatin1Char('\n')) && m_funcReturn)
// FIXME: There are a couple related issues on the refactoring interface. You cannot
// simply have distinct indentation ranges within a chunk of content to be added, regardless
// of whether this is done through more than on change. That's why we actually apply twice,
// initially indenting the definition stub and the reindenting the original extraction.
// More details on the refactorings impl. where ranges are transformed into cursors.
// Since we need an indent range and a nested reindent range (based on the original
// formatting) it's simpler to have two different change sets.
Utils::ChangeSet change;
int position = currentFile->startOf(m_refFuncDef);
change.insert(position, funcDef);
......@@ -472,8 +469,8 @@ public:
QTextCursor tc = currentFile->document()->find(QLatin1String("{"), position);
QTC_ASSERT(!tc.isNull(), return);
position = tc.position() + 2;
QTC_ASSERT(tc.hasSelection(), return);
position = tc.selectionEnd() + 1;
change.insert(position, extract);
......@@ -73,26 +73,19 @@ BaseTextEditorWidget *RefactoringChanges::editorForFile(const QString &fileName)
return 0;
QList<QTextCursor> RefactoringChanges::rangesToSelections(QTextDocument *document, const QList<Range> &ranges)
QList<QPair<QTextCursor, QTextCursor > > RefactoringChanges::rangesToSelections(QTextDocument *document,
const QList<Range> &ranges)
QList<QTextCursor> selections;
QList<QPair<QTextCursor, QTextCursor> > selections;
foreach (const Range &range, ranges) {
QTextCursor selection(document);
// FIXME: The subtraction below for the start range might create a selection on a different
// block, which could cause unexpected effects on indentation for example when the range is
// precisely calculate. Since this cursor moves when content is inserted, it might not be
// possible to compensate for such a difference in advance because the value could be
// negative (which would eventually be right after content is inserted) and then taken as 0.
// A proper way for allowing fine granularly specified ranges would be to have two cursors
// and the first one with *keepPositionOnInsert*, for example, like it's done for the text
// editor overlay.
// ### workaround for moving the textcursor when inserting text at the beginning of the range.
selection.setPosition(qMax(0, range.start - 1));
selection.setPosition(qMin(range.end, document->characterCount() - 1), QTextCursor::KeepAnchor);
QTextCursor start(document);
QTextCursor end(document);
end.setPosition(qMin(range.end, document->characterCount() - 1));
selections.append(qMakePair(start, end));
return selections;
......@@ -363,10 +356,10 @@ void RefactoringFile::apply()
// build indent selections now, applying the changeset will change locations
const QList<QTextCursor> &indentSelections =
const QList<QPair<QTextCursor, QTextCursor> > &indentSelections =
RefactoringChanges::rangesToSelections(doc, m_indentRanges);
const QList<QTextCursor> &reindentSelections =
const QList<QPair<QTextCursor, QTextCursor> > &reindentSelections =
RefactoringChanges::rangesToSelections(doc, m_reindentRanges);
......@@ -374,10 +367,8 @@ void RefactoringFile::apply()
foreach (const QTextCursor &selection, indentSelections)
m_data->indentSelection(selection, m_fileName, m_editor);
foreach (const QTextCursor &selection, reindentSelections)
m_data->reindentSelection(selection, m_fileName, m_editor);
indentOrReindent(&RefactoringChangesData::indentSelection, indentSelections);
indentOrReindent(&RefactoringChangesData::reindentSelection, reindentSelections);
......@@ -396,6 +387,20 @@ void RefactoringFile::apply()
m_appliedOnce = true;
void RefactoringFile::indentOrReindent(void (RefactoringChangesData::*mf)(const QTextCursor &,
const QString &,
const BaseTextEditorWidget *) const,
const QList<QPair<QTextCursor, QTextCursor> > &ranges)
QPair<QTextCursor, QTextCursor> p;
foreach (p, ranges) {
QTextCursor selection(p.first.document());
selection.setPosition(p.second.position(), QTextCursor::KeepAnchor);
((*m_data).*(mf))(selection, m_fileName, m_editor);
void RefactoringFile::fileChanged()
if (!m_fileName.isEmpty())
......@@ -40,6 +40,7 @@
#include <QtCore/QList>
#include <QtCore/QString>
#include <QtCore/QSharedPointer>
#include <QtCore/QPair>
class QTextDocument;
......@@ -96,6 +97,11 @@ protected:
// derived classes may want to clear language specific extra data
virtual void fileChanged();
void indentOrReindent(void (RefactoringChangesData::*mf)(const QTextCursor &,
const QString &,
const BaseTextEditorWidget *) const,
const QList<QPair<QTextCursor, QTextCursor> > &ranges);
QString m_fileName;
QSharedPointer<RefactoringChangesData> m_data;
......@@ -138,7 +144,8 @@ protected:
static BaseTextEditorWidget *openEditor(const QString &fileName, bool activate, int line, int column);
static QList<QTextCursor> rangesToSelections(QTextDocument *document, const QList<Range> &ranges);
static QList<QPair<QTextCursor, QTextCursor> > rangesToSelections(QTextDocument *document,
const QList<Range> &ranges);
QSharedPointer<RefactoringChangesData> m_data;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment