forked from qt-creator/qt-creator
CppEditor: Format code inserted by quickfixes
Task-number: QTCREATORBUG-10807 Task-number: QTCREATORBUG-19158 Change-Id: Ieac52e1a1a10afad91fea56290e7dcfd1d302e7f Reviewed-by: Christian Kandeler <christian.kandeler@qt.io> Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -334,10 +334,8 @@ void ChangeSet::apply_helper()
|
||||
{
|
||||
// convert all ops to replace
|
||||
QList<EditOp> replaceList;
|
||||
{
|
||||
while (!m_operationList.isEmpty())
|
||||
convertToReplace(m_operationList.takeFirst(), &replaceList);
|
||||
}
|
||||
while (!m_operationList.isEmpty())
|
||||
convertToReplace(m_operationList.takeFirst(), &replaceList);
|
||||
|
||||
// execute replaces
|
||||
if (m_cursor)
|
||||
|
@@ -75,15 +75,20 @@ CppRefactoringFile::CppRefactoringFile(const FilePath &filePath, const QSharedPo
|
||||
{
|
||||
const Snapshot &snapshot = this->data()->m_snapshot;
|
||||
m_cppDocument = snapshot.document(filePath);
|
||||
m_formattingEnabled = true;
|
||||
}
|
||||
|
||||
CppRefactoringFile::CppRefactoringFile(QTextDocument *document, const FilePath &filePath)
|
||||
: RefactoringFile(document, filePath)
|
||||
{ }
|
||||
{
|
||||
m_formattingEnabled = true;
|
||||
}
|
||||
|
||||
CppRefactoringFile::CppRefactoringFile(TextEditor::TextEditorWidget *editor)
|
||||
: RefactoringFile(editor)
|
||||
{ }
|
||||
{
|
||||
m_formattingEnabled = true;
|
||||
}
|
||||
|
||||
Document::Ptr CppRefactoringFile::cppDocument() const
|
||||
{
|
||||
|
@@ -340,12 +340,15 @@ bool RefactoringFile::apply()
|
||||
RefactoringChanges::rangesToSelections(doc, m_reindentRanges);
|
||||
m_reindentRanges.clear();
|
||||
|
||||
// apply changes and reindent
|
||||
// apply changes
|
||||
setupFormattingRanges(m_changes.operationList());
|
||||
m_changes.apply(&c);
|
||||
m_changes.clear();
|
||||
|
||||
// Do indentation and formatting.
|
||||
indentOrReindent(indentSelections, Indent);
|
||||
indentOrReindent(reindentSelections, Reindent);
|
||||
doFormatting();
|
||||
|
||||
c.endEditBlock();
|
||||
|
||||
@@ -391,6 +394,98 @@ void RefactoringFile::indentOrReindent(const RefactoringSelections &ranges,
|
||||
}
|
||||
}
|
||||
|
||||
void RefactoringFile::setupFormattingRanges(const QList<ChangeSet::EditOp> &replaceList)
|
||||
{
|
||||
if (!m_editor || !m_formattingEnabled)
|
||||
return;
|
||||
|
||||
for (const ChangeSet::EditOp &op : replaceList) {
|
||||
QTextCursor cursor = m_editor->textCursor();
|
||||
switch (op.type) {
|
||||
case ChangeSet::EditOp::Unset:
|
||||
break;
|
||||
case ChangeSet::EditOp::Replace:
|
||||
case ChangeSet::EditOp::Insert:
|
||||
case ChangeSet::EditOp::Remove:
|
||||
cursor.setKeepPositionOnInsert(true);
|
||||
cursor.setPosition(op.pos1 + op.length1);
|
||||
cursor.setPosition(op.pos1, QTextCursor::KeepAnchor);
|
||||
m_formattingCursors << cursor;
|
||||
break;
|
||||
case ChangeSet::EditOp::Flip:
|
||||
case ChangeSet::EditOp::Move:
|
||||
cursor.setKeepPositionOnInsert(true);
|
||||
cursor.setPosition(op.pos1 + op.length1);
|
||||
cursor.setPosition(op.pos1, QTextCursor::KeepAnchor);
|
||||
m_formattingCursors << cursor;
|
||||
cursor.setPosition(op.pos2 + op.length2);
|
||||
cursor.setPosition(op.pos2, QTextCursor::KeepAnchor);
|
||||
m_formattingCursors << cursor;
|
||||
break;
|
||||
case ChangeSet::EditOp::Copy:
|
||||
cursor.setKeepPositionOnInsert(true);
|
||||
cursor.setPosition(op.pos2, QTextCursor::KeepAnchor);
|
||||
m_formattingCursors << cursor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RefactoringFile::doFormatting()
|
||||
{
|
||||
if (m_formattingCursors.empty() || !m_editor)
|
||||
return;
|
||||
|
||||
RangesInLines formattingRanges;
|
||||
|
||||
QTextCursor cursor = m_editor->textCursor();
|
||||
auto lineForPosition = [&](int pos) {
|
||||
cursor.setPosition(pos);
|
||||
return cursor.blockNumber() + 1;
|
||||
};
|
||||
QList<int> affectedLines;
|
||||
for (const QTextCursor &formattingCursor : std::as_const(m_formattingCursors)) {
|
||||
int startLine = lineForPosition(formattingCursor.selectionStart());
|
||||
int endLine = lineForPosition(formattingCursor.selectionEnd());
|
||||
for (int line = startLine; line <= endLine; ++line) {
|
||||
const auto it = std::lower_bound(affectedLines.begin(), affectedLines.end(), line);
|
||||
if (it == affectedLines.end() || *it > line)
|
||||
affectedLines.insert(it, line);
|
||||
}
|
||||
}
|
||||
|
||||
for (int line : std::as_const(affectedLines)) {
|
||||
if (!formattingRanges.empty() && formattingRanges.back().endLine == line - 1)
|
||||
formattingRanges.back().endLine = line;
|
||||
else
|
||||
formattingRanges.push_back({line, line});
|
||||
}
|
||||
|
||||
static const QString clangFormatLineRemovalBlocker("// QTC_TEMP");
|
||||
for (const RangeInLines &r : std::as_const(formattingRanges)) {
|
||||
QTextBlock b = m_editor->document()->findBlockByNumber(r.startLine - 1);
|
||||
while (true) {
|
||||
QTC_ASSERT(b.isValid(), break);
|
||||
if (b.text().simplified().isEmpty())
|
||||
QTextCursor(b).insertText(clangFormatLineRemovalBlocker);
|
||||
if (b.blockNumber() == r.endLine)
|
||||
break;
|
||||
b = b.next();
|
||||
}
|
||||
}
|
||||
m_editor->textDocument()->indenter()->format(formattingRanges);
|
||||
for (QTextBlock b = m_editor->document()->findBlockByNumber(
|
||||
formattingRanges.front().startLine - 1); b.isValid(); b = b.next()) {
|
||||
QString blockText = b.text();
|
||||
if (blockText.remove(clangFormatLineRemovalBlocker) == b.text())
|
||||
continue;
|
||||
QTextCursor c(b);
|
||||
c.select(QTextCursor::LineUnderCursor);
|
||||
c.removeSelectedText();
|
||||
c.insertText(blockText);
|
||||
}
|
||||
}
|
||||
|
||||
void RefactoringFile::fileChanged()
|
||||
{
|
||||
if (!m_filePath.isEmpty())
|
||||
|
@@ -3,6 +3,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "indenter.h"
|
||||
|
||||
#include <texteditor/texteditor_global.h>
|
||||
#include <utils/changeset.h>
|
||||
#include <utils/fileutils.h>
|
||||
@@ -75,6 +77,9 @@ protected:
|
||||
enum IndentType {Indent, Reindent};
|
||||
void indentOrReindent(const RefactoringSelections &ranges, IndentType indent);
|
||||
|
||||
void setupFormattingRanges(const QList<Utils::ChangeSet::EditOp> &replaceList);
|
||||
void doFormatting();
|
||||
|
||||
Utils::FilePath m_filePath;
|
||||
QSharedPointer<RefactoringChangesData> m_data;
|
||||
mutable Utils::TextFileFormat m_textFileFormat;
|
||||
@@ -83,10 +88,12 @@ protected:
|
||||
Utils::ChangeSet m_changes;
|
||||
QList<Range> m_indentRanges;
|
||||
QList<Range> m_reindentRanges;
|
||||
QList<QTextCursor> m_formattingCursors;
|
||||
bool m_openEditor = false;
|
||||
bool m_activateEditor = false;
|
||||
int m_editorCursorPosition = -1;
|
||||
bool m_appliedOnce = false;
|
||||
bool m_formattingEnabled = false;
|
||||
|
||||
friend class RefactoringChanges; // access to constructor
|
||||
};
|
||||
|
Reference in New Issue
Block a user