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:
Christian Kandeler
2023-06-26 16:01:57 +02:00
parent 4a51f57aa2
commit 9f6878ddab
4 changed files with 112 additions and 7 deletions

View File

@@ -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)

View File

@@ -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
{

View File

@@ -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())

View File

@@ -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
};