aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/texteditor/refactoringchanges.cpp
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2023-11-20 11:28:41 +0100
committerChristian Kandeler <christian.kandeler@qt.io>2023-11-22 13:47:16 +0000
commit240748c106678218d7ed85e3a7a2d79db099b0e6 (patch)
tree4e872d9f67ddd6e18b0bc38e11a841b92bcb9f97 /src/plugins/texteditor/refactoringchanges.cpp
parent2bd02671d81dd550881cc7384d9bdf9d2bde4394 (diff)
TextEditor: Get rid of extra indent ranges in RefactoringFile
Having extra indent regions complicates the interface, the implementation and the calling code. Instead, derive the indent regions from the change set and let callers opt out for the relatively few cases where indentation is not desired. Change-Id: I49d2854830a51778534ef260fb5c9f2c7685554a Reviewed-by: David Schulz <david.schulz@qt.io>
Diffstat (limited to 'src/plugins/texteditor/refactoringchanges.cpp')
-rw-r--r--src/plugins/texteditor/refactoringchanges.cpp161
1 files changed, 48 insertions, 113 deletions
diff --git a/src/plugins/texteditor/refactoringchanges.cpp b/src/plugins/texteditor/refactoringchanges.cpp
index 88a2366a8d..1cf089e406 100644
--- a/src/plugins/texteditor/refactoringchanges.cpp
+++ b/src/plugins/texteditor/refactoringchanges.cpp
@@ -3,9 +3,12 @@
#include "refactoringchanges.h"
+#include "icodestylepreferencesfactory.h"
#include "textdocument.h"
#include "texteditor.h"
#include "texteditortr.h"
+#include "texteditorsettings.h"
+#include "textindenter.h"
#include <coreplugin/dialogs/readonlyfilesdialog.h>
#include <coreplugin/documentmanager.h>
@@ -21,6 +24,8 @@
#include <QTextDocument>
#include <QDebug>
+#include <memory>
+
using namespace Core;
using namespace Utils;
@@ -60,7 +65,8 @@ bool RefactoringFile::create(const QString &contents, bool reindent, bool openIn
// Reindent the contents:
if (reindent) {
cursor.select(QTextCursor::Document);
- indentSelection(cursor, nullptr);
+ m_formattingCursors = {cursor};
+ doFormatting();
}
cursor.endEditBlock();
@@ -198,22 +204,6 @@ void RefactoringFile::setChangeSet(const ChangeSet &changeSet)
m_changes = changeSet;
}
-void RefactoringFile::appendIndentRange(const Range &range)
-{
- if (m_filePath.isEmpty())
- return;
-
- m_indentRanges.append(range);
-}
-
-void RefactoringFile::appendReindentRange(const Range &range)
-{
- if (m_filePath.isEmpty())
- return;
-
- m_reindentRanges.append(range);
-}
-
void RefactoringFile::setOpenEditor(bool activate, int pos)
{
m_openEditor = true;
@@ -249,7 +239,7 @@ bool RefactoringFile::apply()
bool result = true;
// apply changes, if any
- if (!m_indentRanges.isEmpty() || !m_changes.isEmpty()) {
+ if (!m_changes.isEmpty()) {
QTextDocument *doc = mutableDocument();
if (doc) {
QTextCursor c = cursor();
@@ -258,24 +248,12 @@ bool RefactoringFile::apply()
else
c.beginEditBlock();
- sort(m_indentRanges);
- sort(m_reindentRanges);
-
- // build indent selections now, applying the changeset will change locations
- const RefactoringSelections &indentSelections = rangesToSelections(doc, m_indentRanges);
- m_indentRanges.clear();
- const RefactoringSelections &reindentSelections
- = rangesToSelections(doc, m_reindentRanges);
- m_reindentRanges.clear();
-
// 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();
@@ -308,27 +286,16 @@ bool RefactoringFile::apply()
return result;
}
-void RefactoringFile::indentOrReindent(const RefactoringSelections &ranges,
- RefactoringFile::IndentType indent)
-{
- TextDocument * document = m_editor ? m_editor->textDocument() : nullptr;
- for (const auto &[position, anchor]: ranges) {
- QTextCursor selection(anchor);
- selection.setPosition(position.position(), QTextCursor::KeepAnchor);
- if (indent == Indent)
- indentSelection(selection, document);
- else
- reindentSelection(selection, document);
- }
-}
-
void RefactoringFile::setupFormattingRanges(const QList<ChangeSet::EditOp> &replaceList)
{
- if (!m_editor || !m_formattingEnabled)
+ if (!m_formattingEnabled)
return;
+ QTextDocument * const doc = m_editor ? m_editor->document() : m_document;
+ QTC_ASSERT(doc, return);
+
for (const ChangeSet::EditOp &op : replaceList) {
- QTextCursor cursor = m_editor->textCursor();
+ QTextCursor cursor(doc);
switch (op.type) {
case ChangeSet::EditOp::Unset:
break;
@@ -361,55 +328,54 @@ void RefactoringFile::setupFormattingRanges(const QList<ChangeSet::EditOp> &repl
void RefactoringFile::doFormatting()
{
- if (m_formattingCursors.empty() || !m_editor)
+ if (m_formattingCursors.empty())
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});
+ QTextDocument *document = nullptr;
+ Indenter *indenter = nullptr;
+ std::unique_ptr<Indenter> indenterOwner;
+ TabSettings tabSettings;
+ if (m_editor) {
+ document = m_editor->document();
+ indenter = m_editor->textDocument()->indenter();
+ tabSettings = m_editor->textDocument()->tabSettings();
+ } else {
+ document = m_document;
+ ICodeStylePreferencesFactory * const factory
+ = TextEditorSettings::codeStyleFactory(indenterId());
+ indenterOwner.reset(factory ? factory->createIndenter(document)
+ : new TextIndenter(document));
+ indenter = indenterOwner.get();
+ tabSettings = TabSettings::settingsForFile(filePath());
}
-
- static const QString clangFormatLineRemovalBlocker("");
- for (const RangeInLines &r : std::as_const(formattingRanges)) {
- QTextBlock b = m_editor->document()->findBlockByNumber(r.startLine - 1);
+ QTC_ASSERT(document, return);
+ QTC_ASSERT(indenter, return);
+
+ Utils::sort(m_formattingCursors, [](const QTextCursor &tc1, const QTextCursor &tc2) {
+ return tc1.selectionStart() < tc2.selectionStart();
+ });
+ const int firstSelectedBlock = document->findBlock(m_formattingCursors.first().selectionStart())
+ .blockNumber();
+ static const QString clangFormatLineRemovalBlocker("// QTC_TEMP");
+ for (const QTextCursor &formattingCursor : std::as_const(m_formattingCursors)) {
+ const QTextBlock firstBlock = document->findBlock(formattingCursor.selectionStart());
+ const QTextBlock lastBlock = document->findBlock(formattingCursor.selectionEnd());
+ QTextBlock b = firstBlock;
while (true) {
QTC_ASSERT(b.isValid(), break);
if (b.text().simplified().isEmpty())
QTextCursor(b).insertText(clangFormatLineRemovalBlocker);
- if (b.blockNumber() == r.endLine - 1)
+ if (b == lastBlock)
break;
b = b.next();
}
}
- // TODO: The proper solution seems to be to call formatOrIndent() here (and not
- // use hardcoded indent regions anymore), but that would require intrusive changes
- // to the C++ quickfixes and tests, where we rely on the built-in indenter behavior.
- m_editor->textDocument()->indenter()->format(formattingRanges,
- Indenter::FormattingMode::Settings);
+ for (const QTextCursor &tc : std::as_const(m_formattingCursors))
+ indenter->autoIndent(tc, tabSettings);
- for (QTextBlock b = m_editor->document()->findBlockByNumber(
- formattingRanges.front().startLine - 1); b.isValid(); b = b.next()) {
+ for (QTextBlock b = document->findBlockByNumber(firstSelectedBlock);
+ b.isValid(); b = b.next()) {
QString blockText = b.text();
if (blockText.remove(clangFormatLineRemovalBlocker) == b.text())
continue;
@@ -420,20 +386,6 @@ void RefactoringFile::doFormatting()
}
}
-void RefactoringFile::indentSelection(const QTextCursor &selection,
- const TextDocument *textDocument) const
-{
- Q_UNUSED(selection)
- Q_UNUSED(textDocument)
-}
-
-void RefactoringFile::reindentSelection(const QTextCursor &selection,
- const TextDocument *textDocument) const
-{
- Q_UNUSED(selection)
- Q_UNUSED(textDocument)
-}
-
TextEditorWidget *RefactoringFile::openEditor(bool activate, int line, int column)
{
EditorManager::OpenEditorFlags flags = EditorManager::IgnoreNavigationHistory;
@@ -450,23 +402,6 @@ TextEditorWidget *RefactoringFile::openEditor(bool activate, int line, int colum
return TextEditorWidget::fromEditor(editor);
}
-RefactoringSelections RefactoringFile::rangesToSelections(QTextDocument *document,
- const QList<Range> &ranges)
-{
- RefactoringSelections selections;
-
- for (const Range &range : ranges) {
- QTextCursor start(document);
- start.setPosition(range.start);
- start.setKeepPositionOnInsert(true);
- QTextCursor end(document);
- end.setPosition(qMin(range.end, document->characterCount() - 1));
- selections.push_back({start, end});
- }
-
- return selections;
-}
-
RefactoringFileFactory::~RefactoringFileFactory() = default;
RefactoringFilePtr PlainRefactoringFileFactory::file(const Utils::FilePath &filePath) const