aboutsummaryrefslogtreecommitdiffstats
path: root/src
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
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')
-rw-r--r--src/plugins/clangcodemodel/clangfixitoperation.cpp6
-rw-r--r--src/plugins/cppeditor/cppinsertvirtualmethods.cpp4
-rw-r--r--src/plugins/cppeditor/cppquickfixes.cpp67
-rw-r--r--src/plugins/cppeditor/cpprefactoringchanges.cpp42
-rw-r--r--src/plugins/cppeditor/cpprefactoringchanges.h6
-rw-r--r--src/plugins/languageclient/languageclientutils.cpp2
-rw-r--r--src/plugins/projectexplorer/projectexplorer.cpp6
-rw-r--r--src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp1
-rw-r--r--src/plugins/qmljseditor/qmljsquickfixes.cpp3
-rw-r--r--src/plugins/qmljseditor/qmljswrapinloader.cpp1
-rw-r--r--src/plugins/qmljseditor/qmloutlinemodel.cpp3
-rw-r--r--src/plugins/qmljstools/qmljsrefactoringchanges.cpp41
-rw-r--r--src/plugins/qmljstools/qmljsrefactoringchanges.h5
-rw-r--r--src/plugins/texteditor/basefilefind.cpp1
-rw-r--r--src/plugins/texteditor/refactoringchanges.cpp161
-rw-r--r--src/plugins/texteditor/refactoringchanges.h22
-rw-r--r--src/plugins/texteditor/tabsettings.cpp14
-rw-r--r--src/plugins/texteditor/tabsettings.h9
18 files changed, 121 insertions, 273 deletions
diff --git a/src/plugins/clangcodemodel/clangfixitoperation.cpp b/src/plugins/clangcodemodel/clangfixitoperation.cpp
index b303a755e51..e173592ec06 100644
--- a/src/plugins/clangcodemodel/clangfixitoperation.cpp
+++ b/src/plugins/clangcodemodel/clangfixitoperation.cpp
@@ -3,7 +3,8 @@
#include "clangfixitoperation.h"
-#include <texteditor/refactoringchanges.h>
+#include <cppeditor/cppmodelmanager.h>
+#include <cppeditor/cpprefactoringchanges.h>
#include <utils/qtcassert.h>
@@ -46,7 +47,8 @@ static FileToFixits fixitsPerFile(const QList<ClangFixIt> &fixIts)
void ClangFixItOperation::perform()
{
- const TextEditor::PlainRefactoringFileFactory refactoringChanges;
+ const CppEditor::CppRefactoringChanges refactoringChanges(
+ CppEditor::CppModelManager::snapshot());
const FileToFixits fileToFixIts = fixitsPerFile(fixIts);
for (auto i = fileToFixIts.cbegin(), end = fileToFixIts.cend(); i != end; ++i) {
diff --git a/src/plugins/cppeditor/cppinsertvirtualmethods.cpp b/src/plugins/cppeditor/cppinsertvirtualmethods.cpp
index 7c173c703b4..754042d168d 100644
--- a/src/plugins/cppeditor/cppinsertvirtualmethods.cpp
+++ b/src/plugins/cppeditor/cppinsertvirtualmethods.cpp
@@ -864,8 +864,6 @@ public:
// Write header file
if (!headerChangeSet.isEmpty()) {
headerFile->setChangeSet(headerChangeSet);
- headerFile->appendIndentRange(Utils::ChangeSet::Range(m_insertPosDecl,
- m_insertPosDecl + 1));
headerFile->setOpenEditor(true, m_insertPosDecl);
headerFile->apply();
}
@@ -920,8 +918,6 @@ public:
if (!implementationChangeSet.isEmpty()) {
implementationFile->setChangeSet(implementationChangeSet);
- implementationFile->appendIndentRange(Utils::ChangeSet::Range(insertPos,
- insertPos + 1));
implementationFile->apply();
}
}
diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp
index 0ce5adb798d..e5417ec6c01 100644
--- a/src/plugins/cppeditor/cppquickfixes.cpp
+++ b/src/plugins/cppeditor/cppquickfixes.cpp
@@ -599,7 +599,6 @@ public:
changes.insert(end, QLatin1String(")"));
currentFile->setChangeSet(changes);
- currentFile->appendIndentRange(currentFile->range(pattern));
currentFile->apply();
}
};
@@ -699,7 +698,6 @@ public:
}
currentFile->setChangeSet(changes);
- currentFile->appendIndentRange(currentFile->range(declaration));
currentFile->apply();
}
@@ -774,7 +772,6 @@ public:
changes.insert(end, QLatin1String("\n}"));
currentFile->setChangeSet(changes);
- currentFile->appendIndentRange(ChangeSet::Range(start, end));
currentFile->apply();
}
@@ -848,7 +845,6 @@ public:
changes.insert(insertPos, QLatin1String(";\n"));
currentFile->setChangeSet(changes);
- currentFile->appendIndentRange(currentFile->range(pattern));
currentFile->apply();
}
@@ -924,7 +920,6 @@ public:
changes.insert(insertPos, QLatin1String(";\n"));
currentFile->setChangeSet(changes);
- currentFile->appendIndentRange(currentFile->range(pattern));
currentFile->apply();
}
@@ -1012,7 +1007,6 @@ public:
changes.insert(currentFile->endOf(pattern), QLatin1String("\n}"));
currentFile->setChangeSet(changes);
- currentFile->appendIndentRange(currentFile->range(pattern));
currentFile->apply();
}
@@ -1041,7 +1035,6 @@ public:
changes.remove(lExprEnd, currentFile->startOf(condition->right_expression));
currentFile->setChangeSet(changes);
- currentFile->appendIndentRange(currentFile->range(pattern));
currentFile->apply();
}
@@ -2405,7 +2398,6 @@ public:
+ values.join(QLatin1String(":\nbreak;\ncase "))
+ QLatin1String(":\nbreak;"));
currentFile->setChangeSet(changes);
- currentFile->appendIndentRange(ChangeSet::Range(start, start + 1));
currentFile->apply();
}
@@ -2542,14 +2534,12 @@ public:
QTC_ASSERT(loc.isValid(), return);
CppRefactoringFilePtr targetFile = refactoring.cppFile(m_targetFilePath);
- int targetPosition1 = targetFile->position(loc.line(), loc.column());
- int targetPosition2 = qMax(0, targetFile->position(loc.line(), 1) - 1);
+ int targetPosition = targetFile->position(loc.line(), loc.column());
ChangeSet target;
- target.insert(targetPosition1, loc.prefix() + m_decl);
+ target.insert(targetPosition, loc.prefix() + m_decl);
targetFile->setChangeSet(target);
- targetFile->appendIndentRange(ChangeSet::Range(targetPosition2, targetPosition1));
- targetFile->setOpenEditor(true, targetPosition1);
+ targetFile->setOpenEditor(true, targetPosition);
targetFile->apply();
}
@@ -2708,8 +2698,7 @@ public:
DeclaratorAST *declAST,
Declaration *decl,
const FilePath &targetFilePath,
- ChangeSet *changeSet = nullptr,
- QList<ChangeSet::Range> *indentRanges = nullptr)
+ ChangeSet *changeSet = nullptr)
{
CppRefactoringChanges refactoring(op->snapshot());
if (!loc.isValid())
@@ -2736,10 +2725,6 @@ public:
ChangeSet * const target = changeSet ? changeSet : &localChangeSet;
target->replace(targetPos - 1, targetPos, QLatin1String("\n {\n\n}")); // replace ';'
const ChangeSet::Range indentRange(targetPos, targetPos + 4);
- if (indentRanges)
- indentRanges->append(indentRange);
- else
- targetFile->appendIndentRange(indentRange);
if (!changeSet) {
targetFile->setChangeSet(*target);
@@ -2819,10 +2804,6 @@ public:
ChangeSet * const target = changeSet ? changeSet : &localChangeSet;
target->insert(targetPos, loc.prefix() + defText + loc.suffix());
const ChangeSet::Range indentRange(targetPos2, targetPos);
- if (indentRanges)
- indentRanges->append(indentRange);
- else
- targetFile->appendIndentRange(indentRange);
if (!changeSet) {
targetFile->setChangeSet(*target);
@@ -2995,12 +2976,10 @@ private:
QTC_ASSERT(loc.isValid(), return);
CppRefactoringFilePtr targetFile = refactoring.cppFile(filePath);
- const int targetPosition1 = targetFile->position(loc.line(), loc.column());
- const int targetPosition2 = qMax(0, targetFile->position(loc.line(), 1) - 1);
+ const int targetPosition = targetFile->position(loc.line(), loc.column());
ChangeSet target;
- target.insert(targetPosition1, loc.prefix() + decl + ";\n");
+ target.insert(targetPosition, loc.prefix() + decl + ";\n");
targetFile->setChangeSet(target);
- targetFile->appendIndentRange(ChangeSet::Range(targetPosition2, targetPosition1));
targetFile->apply();
}
@@ -3558,7 +3537,7 @@ private:
SimpleDeclarationAST *m_decl = nullptr;
};
- QHash<FilePath, QPair<ChangeSet, QList<ChangeSet::Range>>> changeSets;
+ QHash<FilePath, ChangeSet> changeSets;
for (const MemberFunctionImplSetting &setting : std::as_const(settings)) {
DeclFinder finder(currentFile().data(), setting.func);
finder.accept(m_classAST);
@@ -3572,17 +3551,14 @@ private:
currentFile()->lineAndColumn(currentFile()->endOf(finder.decl()), &line, &column);
loc = InsertionLocation(filePath(), QString(), QString(), line, column);
}
- auto &changeSet = changeSets[targetFilePath];
+ ChangeSet &changeSet = changeSets[targetFilePath];
InsertDefOperation::insertDefinition(
this, loc, setting.defPos, finder.decl()->declarator_list->value,
- setting.func->asDeclaration(),targetFilePath,
- &changeSet.first, &changeSet.second);
+ setting.func->asDeclaration(),targetFilePath, &changeSet);
}
for (auto it = changeSets.cbegin(); it != changeSets.cend(); ++it) {
const CppRefactoringFilePtr file = refactoring.cppFile(it.key());
- for (const ChangeSet::Range &r : it.value().second)
- file->appendIndentRange(r);
- file->setChangeSet(it.value().first);
+ file->setChangeSet(it.value());
file->apply();
}
}
@@ -3763,11 +3739,9 @@ protected:
const InsertionLocation &loc,
const QString &text)
{
- int targetPosition1 = file->position(loc.line(), loc.column());
- int targetPosition2 = qMax(0, file->position(loc.line(), 1) - 1);
+ int targetPosition = file->position(loc.line(), loc.column());
ChangeSet &changeSet = file == m_headerFile ? m_headerFileChangeSet : m_sourceFileChangeSet;
- changeSet.insert(targetPosition1, loc.prefix() + text + loc.suffix());
- file->appendIndentRange(ChangeSet::Range(targetPosition2, targetPosition1));
+ changeSet.insert(targetPosition, loc.prefix() + text + loc.suffix());
}
FullySpecifiedType makeConstRef(FullySpecifiedType type)
@@ -5190,7 +5164,6 @@ public:
change.insert(position, funcDef);
change.replace(m_extractionStart, m_extractionEnd, funcCall);
currentFile->setChangeSet(change);
- currentFile->appendIndentRange(ChangeSet::Range(position, position + 1));
currentFile->apply();
QTextCursor tc = currentFile->document()->find(QLatin1String("{"), position);
@@ -5199,7 +5172,6 @@ public:
change.clear();
change.insert(position, extract + '\n');
currentFile->setChangeSet(change);
- currentFile->appendReindentRange(ChangeSet::Range(position, position + 1));
currentFile->apply();
// Write declaration, if necessary.
@@ -5213,7 +5185,6 @@ public:
position = declFile->position(location.line(), location.column());
change.insert(position, location.prefix() + funcDecl + location.suffix());
declFile->setChangeSet(change);
- declFile->appendIndentRange(ChangeSet::Range(position, position + 1));
declFile->apply();
}
}
@@ -6579,7 +6550,6 @@ public:
// insert definition at new position
m_toFileChangeSet.insert(insertPos, funcDef);
- m_toFile->appendIndentRange(ChangeSet::Range(insertPos, insertPos + funcDef.size()));
m_toFile->setOpenEditor(true, insertPos);
// remove definition from fromFile
@@ -6605,6 +6575,7 @@ public:
}
if (!m_fromFileChangeSet.isEmpty()) {
m_fromFile->setChangeSet(m_fromFileChangeSet);
+ m_fromFile->skipFormatting();
m_fromFile->apply();
}
}
@@ -6836,7 +6807,6 @@ private:
if (m_toFilePath == m_fromFilePath)
toTarget.remove(m_fromRange);
toFile->setChangeSet(toTarget);
- toFile->appendIndentRange(m_toRange);
toFile->setOpenEditor(true, m_toRange.start);
toFile->apply();
if (m_toFilePath != m_fromFilePath) {
@@ -7649,6 +7619,13 @@ private:
CppRefactoringChanges refactoring(snapshot());
CppRefactoringFilePtr currentFile = refactoring.cppFile(filePath());
currentFile->setChangeSet(m_changes);
+
+ // It would probably be unexpected to users if we were to re-format here, though
+ // an argument could also be made for doing it, especially if "format instead of indent"
+ // is enabled, as a difference in line length might trigger a different ClangFormat
+ // re-flowing.
+ currentFile->skipFormatting();
+
currentFile->apply();
}
@@ -8426,8 +8403,10 @@ private:
processIncludes(refactoring, filePath());
}
- for (auto &file : std::as_const(m_changes))
+ for (auto &file : std::as_const(m_changes)) {
+ file->skipFormatting();
file->apply();
+ }
}
/**
diff --git a/src/plugins/cppeditor/cpprefactoringchanges.cpp b/src/plugins/cppeditor/cpprefactoringchanges.cpp
index 207d359cb88..68d18db7492 100644
--- a/src/plugins/cppeditor/cpprefactoringchanges.cpp
+++ b/src/plugins/cppeditor/cpprefactoringchanges.cpp
@@ -36,16 +36,6 @@ public:
using namespace Internal;
-static std::unique_ptr<TextEditor::Indenter> createIndenter(const FilePath &filePath,
- QTextDocument *textDocument)
-{
- TextEditor::ICodeStylePreferencesFactory *factory
- = TextEditor::TextEditorSettings::codeStyleFactory(Constants::CPP_SETTINGS_ID);
- std::unique_ptr<TextEditor::Indenter> indenter(factory->createIndenter(textDocument));
- indenter->setFileName(filePath);
- return indenter;
-}
-
CppRefactoringChanges::CppRefactoringChanges(const Snapshot &snapshot)
: m_data(new CppRefactoringChangesData(snapshot))
{
@@ -89,19 +79,16 @@ CppRefactoringFile::CppRefactoringFile(const FilePath &filePath, const QSharedPo
{
const Snapshot &snapshot = data->m_snapshot;
m_cppDocument = snapshot.document(filePath);
- enableFormatting();
}
CppRefactoringFile::CppRefactoringFile(QTextDocument *document, const FilePath &filePath)
: RefactoringFile(document, filePath)
{
- enableFormatting();
}
CppRefactoringFile::CppRefactoringFile(TextEditor::TextEditorWidget *editor)
: RefactoringFile(editor)
{
- enableFormatting();
}
Document::Ptr CppRefactoringFile::cppDocument() const
@@ -253,6 +240,11 @@ void CppRefactoringFile::fileChanged()
CppModelManager::updateSourceFiles({filePath()});
}
+Id CppRefactoringFile::indenterId() const
+{
+ return Constants::CPP_SETTINGS_ID;
+}
+
int CppRefactoringFile::tokenIndexForPosition(const std::vector<CPlusPlus::Token> &tokens,
int pos, int startIndex) const
{
@@ -281,28 +273,4 @@ CppRefactoringChangesData::CppRefactoringChangesData(const Snapshot &snapshot)
, m_workingCopy(CppModelManager::workingCopy())
{}
-void CppRefactoringFile::indentSelection(const QTextCursor &selection,
- const TextEditor::TextDocument *textDocument) const
-{
- if (textDocument) { // use the indenter from the textDocument if there is one, can be ClangFormat
- textDocument->indenter()->indent(selection, QChar::Null, textDocument->tabSettings());
- } else {
- const auto &tabSettings = ProjectExplorer::actualTabSettings(filePath(), textDocument);
- auto indenter = createIndenter(filePath(), selection.document());
- indenter->indent(selection, QChar::Null, tabSettings);
- }
-}
-
-void CppRefactoringFile::reindentSelection(const QTextCursor &selection,
- const TextEditor::TextDocument *textDocument) const
-{
- if (textDocument) { // use the indenter from the textDocument if there is one, can be ClangFormat
- textDocument->indenter()->reindent(selection, textDocument->tabSettings());
- } else {
- const auto &tabSettings = ProjectExplorer::actualTabSettings(filePath(), textDocument);
- auto indenter = createIndenter(filePath(), selection.document());
- indenter->reindent(selection, tabSettings);
- }
-}
-
} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cpprefactoringchanges.h b/src/plugins/cppeditor/cpprefactoringchanges.h
index 35e26940de0..9a9cb09dc14 100644
--- a/src/plugins/cppeditor/cpprefactoringchanges.h
+++ b/src/plugins/cppeditor/cpprefactoringchanges.h
@@ -55,11 +55,7 @@ private:
explicit CppRefactoringFile(TextEditor::TextEditorWidget *editor);
void fileChanged() override;
- void indentSelection(const QTextCursor &selection,
- const TextEditor::TextDocument *textDocument) const override;
- virtual void reindentSelection(const QTextCursor &selection,
- const TextEditor::TextDocument *textDocument) const override;
-
+ Utils::Id indenterId() const override;
int tokenIndexForPosition(const std::vector<CPlusPlus::Token> &tokens, int pos,
int startIndex) const;
diff --git a/src/plugins/languageclient/languageclientutils.cpp b/src/plugins/languageclient/languageclientutils.cpp
index 76c3cdb2933..8edf1666c8b 100644
--- a/src/plugins/languageclient/languageclientutils.cpp
+++ b/src/plugins/languageclient/languageclientutils.cpp
@@ -91,8 +91,6 @@ bool applyTextEdits(const Client *client,
return true;
const RefactoringFilePtr file = client->createRefactoringFile(filePath);
file->setChangeSet(editsToChangeSet(edits, file->document()));
- for (const TextEdit &edit : edits)
- file->appendIndentRange(convertRange(file->document(), edit.range()));
return file->apply();
}
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index 1229d3e1a92..f0cf98190e8 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -40,6 +40,7 @@
#include "devicesupport/devicesettingspage.h"
#include "devicesupport/sshsettings.h"
#include "devicesupport/sshsettingspage.h"
+#include "editorconfiguration.h"
#include "editorsettingspropertiespage.h"
#include "environmentaspect.h"
#include "filesinallprojectsfind.h"
@@ -116,6 +117,7 @@
#include <extensionsystem/pluginspec.h>
#include <texteditor/findinfiles.h>
+#include <texteditor/tabsettings.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditorconstants.h>
#include <texteditor/texteditorsettings.h>
@@ -833,6 +835,10 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
IWizardFactory::registerFeatureProvider(new KitFeatureProvider);
IWizardFactory::registerFactoryCreator([] { return new SimpleProjectWizard; });
+ TextEditor::TabSettings::setRetriever([](const FilePath &filePath) {
+ return actualTabSettings(filePath, nullptr);
+ });
+
ProjectManager *sessionManager = &dd->m_sessionManager;
connect(sessionManager, &ProjectManager::projectAdded,
this, &ProjectExplorerPlugin::fileListChanged);
diff --git a/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp b/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp
index 41fa6df2924..134baa58274 100644
--- a/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp
+++ b/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp
@@ -190,7 +190,6 @@ public:
Utils::ChangeSet changes;
changes.replace(start, end, replacement);
currentFile->setChangeSet(changes);
- currentFile->appendIndentRange(Range(start, end + 1));
currentFile->apply();
Core::IVersionControl *versionControl = Core::VcsManager::findVersionControlForDirectory(
diff --git a/src/plugins/qmljseditor/qmljsquickfixes.cpp b/src/plugins/qmljseditor/qmljsquickfixes.cpp
index 44ee1bd5226..126361451e2 100644
--- a/src/plugins/qmljseditor/qmljsquickfixes.cpp
+++ b/src/plugins/qmljseditor/qmljsquickfixes.cpp
@@ -71,8 +71,6 @@ public:
QLatin1String("\n"));
currentFile->setChangeSet(changes);
- currentFile->appendIndentRange(Range(currentFile->startOf(_objectInitializer->lbraceToken),
- currentFile->startOf(_objectInitializer->rbraceToken)));
currentFile->apply();
}
};
@@ -123,7 +121,6 @@ public:
const int insertLoc = _message.location.begin() - _message.location.startColumn + 1;
changes.insert(insertLoc, QString::fromLatin1("// %1\n").arg(_message.suppressionString()));
currentFile->setChangeSet(changes);
- currentFile->appendIndentRange(Range(insertLoc, insertLoc + 1));
currentFile->apply();
}
};
diff --git a/src/plugins/qmljseditor/qmljswrapinloader.cpp b/src/plugins/qmljseditor/qmljswrapinloader.cpp
index 70dc321f419..bf5fd44d4a7 100644
--- a/src/plugins/qmljseditor/qmljswrapinloader.cpp
+++ b/src/plugins/qmljseditor/qmljswrapinloader.cpp
@@ -147,7 +147,6 @@ public:
" sourceComponent: %1\n"
"}\n").arg(componentId, loaderId));
currentFile->setChangeSet(changes);
- currentFile->appendIndentRange(Range(objDefStart, objDefEnd));
currentFile->apply();
}
};
diff --git a/src/plugins/qmljseditor/qmloutlinemodel.cpp b/src/plugins/qmljseditor/qmloutlinemodel.cpp
index 432628330f7..015e8a41eb1 100644
--- a/src/plugins/qmljseditor/qmloutlinemodel.cpp
+++ b/src/plugins/qmljseditor/qmloutlinemodel.cpp
@@ -860,9 +860,6 @@ void QmlOutlineModel::reparentNodes(QmlOutlineItem *targetItem, int row, QList<Q
QmlJSRefactoringChanges refactoring(ModelManagerInterface::instance(), m_semanticInfo.snapshot);
TextEditor::RefactoringFilePtr file = refactoring.file(m_semanticInfo.document->fileName());
file->setChangeSet(changeSet);
- for (const Utils::ChangeSet::Range &range : std::as_const(changedRanges)) {
- file->appendIndentRange(range);
- }
file->apply();
}
diff --git a/src/plugins/qmljstools/qmljsrefactoringchanges.cpp b/src/plugins/qmljstools/qmljsrefactoringchanges.cpp
index ddc2ca25c83..fea9c5d87a5 100644
--- a/src/plugins/qmljstools/qmljsrefactoringchanges.cpp
+++ b/src/plugins/qmljstools/qmljsrefactoringchanges.cpp
@@ -2,9 +2,11 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "qmljsrefactoringchanges.h"
+
#include "qmljsqtstylecodeformatter.h"
#include "qmljsmodelmanager.h"
#include "qmljsindenter.h"
+#include "qmljstoolsconstants.h"
#include <qmljs/parser/qmljsast_p.h>
#include <texteditor/textdocument.h>
@@ -139,44 +141,9 @@ void QmlJSRefactoringFile::fileChanged()
m_data->m_modelManager->updateSourceFiles({filePath()}, true);
}
-void QmlJSRefactoringFile::indentSelection(const QTextCursor &selection,
- const TextEditor::TextDocument *textDocument) const
-{
- // ### shares code with QmlJSTextEditor::indent
- QTextDocument *doc = selection.document();
-
- QTextBlock block = doc->findBlock(selection.selectionStart());
- const QTextBlock end = doc->findBlock(selection.selectionEnd()).next();
-
- const TextEditor::TabSettings &tabSettings =
- ProjectExplorer::actualTabSettings(filePath(), textDocument);
- CreatorCodeFormatter codeFormatter(tabSettings);
- codeFormatter.updateStateUntil(block);
- do {
- int depth = codeFormatter.indentFor(block);
- if (depth != -1) {
- if (QStringView(block.text()).trimmed().isEmpty()) {
- // we do not want to indent empty lines (as one is indentent when pressing tab
- // assuming that the user will start writing something), and get rid of that
- // space if one had pressed tab in an empty line just before refactoring.
- // If depth == -1 (inside a multiline string for example) leave the spaces.
- depth = 0;
- }
- tabSettings.indentLine(block, depth);
- }
- codeFormatter.updateLineStateChange(block);
- block = block.next();
- } while (block.isValid() && block != end);
-}
-
-void QmlJSRefactoringFile::reindentSelection(const QTextCursor &selection,
- const TextEditor::TextDocument *textDocument) const
+Utils::Id QmlJSRefactoringFile::indenterId() const
{
- const TextEditor::TabSettings &tabSettings =
- ProjectExplorer::actualTabSettings(filePath(), textDocument);
-
- QmlJSEditor::Internal::Indenter indenter(selection.document());
- indenter.reindent(selection, tabSettings);
+ return Constants::QML_JS_SETTINGS_ID;
}
} // namespace QmlJSTools
diff --git a/src/plugins/qmljstools/qmljsrefactoringchanges.h b/src/plugins/qmljstools/qmljsrefactoringchanges.h
index 56051d4dfa3..a5b995c0ea1 100644
--- a/src/plugins/qmljstools/qmljsrefactoringchanges.h
+++ b/src/plugins/qmljstools/qmljsrefactoringchanges.h
@@ -40,10 +40,7 @@ private:
QmlJSRefactoringFile(TextEditor::TextEditorWidget *editor, QmlJS::Document::Ptr document);
void fileChanged() override;
- void indentSelection(const QTextCursor &selection,
- const TextEditor::TextDocument *textDocument) const override;
- void reindentSelection(const QTextCursor &selection,
- const TextEditor::TextDocument *textDocument) const override;
+ Utils::Id indenterId() const override;
mutable QmlJS::Document::Ptr m_qmljsDocument;
QSharedPointer<QmlJSRefactoringChangesData> m_data;
diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp
index 399e275fe4f..83a799caaad 100644
--- a/src/plugins/texteditor/basefilefind.cpp
+++ b/src/plugins/texteditor/basefilefind.cpp
@@ -595,6 +595,7 @@ FilePaths BaseFileFind::replaceAll(const QString &text, const SearchResultItems
changeSet.replace(start, end, replacement);
}
file->setChangeSet(changeSet);
+ file->skipFormatting();
file->apply();
}
diff --git a/src/plugins/texteditor/refactoringchanges.cpp b/src/plugins/texteditor/refactoringchanges.cpp
index 88a2366a8d9..1cf089e4069 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
diff --git a/src/plugins/texteditor/refactoringchanges.h b/src/plugins/texteditor/refactoringchanges.h
index 5155f162fd6..94028825bc6 100644
--- a/src/plugins/texteditor/refactoringchanges.h
+++ b/src/plugins/texteditor/refactoringchanges.h
@@ -8,6 +8,7 @@
#include <texteditor/texteditor_global.h>
#include <utils/changeset.h>
#include <utils/fileutils.h>
+#include <utils/id.h>
#include <utils/textfileformat.h>
#include <QList>
@@ -55,12 +56,13 @@ public:
Utils::ChangeSet changeSet() const;
void setChangeSet(const Utils::ChangeSet &changeSet);
- void appendIndentRange(const Range &range);
- void appendReindentRange(const Range &range);
void setOpenEditor(bool activate = false, int pos = -1);
bool apply();
bool create(const QString &contents, bool reindent, bool openInEditor);
+ // TODO: Per EditOp?
+ void skipFormatting() { m_formattingEnabled = false; }
+
protected:
// users may only get const access to RefactoringFiles created through
// this constructor, because it can't be used to apply changes
@@ -70,25 +72,15 @@ protected:
RefactoringFile(const Utils::FilePath &filePath);
void invalidate() { m_filePath.clear(); }
- void enableFormatting() { m_formattingEnabled = true; }
private:
virtual void fileChanged() {} // derived classes may want to clear language specific extra data
- virtual void indentSelection(const QTextCursor &selection,
- const TextDocument *textDocument) const;
- virtual void reindentSelection(const QTextCursor &selection,
- const TextDocument *textDocument) const;
-
- enum IndentType {Indent, Reindent};
- void indentOrReindent(const RefactoringSelections &ranges, IndentType indent);
+ virtual Utils::Id indenterId() const { return {} ;}
void setupFormattingRanges(const QList<Utils::ChangeSet::EditOp> &replaceList);
void doFormatting();
TextEditorWidget *openEditor(bool activate, int line, int column);
- static RefactoringSelections rangesToSelections(QTextDocument *document,
- const QList<Range> &ranges);
-
QTextDocument *mutableDocument() const;
Utils::FilePath m_filePath;
@@ -96,14 +88,12 @@ private:
mutable QTextDocument *m_document = nullptr;
TextEditorWidget *m_editor = nullptr;
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;
+ bool m_formattingEnabled = true;
};
class TEXTEDITOR_EXPORT RefactoringFileFactory
diff --git a/src/plugins/texteditor/tabsettings.cpp b/src/plugins/texteditor/tabsettings.cpp
index e0c5142dcce..222335133d5 100644
--- a/src/plugins/texteditor/tabsettings.cpp
+++ b/src/plugins/texteditor/tabsettings.cpp
@@ -3,6 +3,9 @@
#include "tabsettings.h"
+#include "icodestylepreferences.h"
+#include "texteditorsettings.h"
+
#include <QDebug>
#include <QTextCursor>
#include <QTextDocument>
@@ -347,4 +350,15 @@ bool TabSettings::equals(const TabSettings &ts) const
&& m_continuationAlignBehavior == ts.m_continuationAlignBehavior;
}
+static TabSettings::Retriever g_retriever = [](const FilePath &) {
+ return TextEditorSettings::codeStyle()->tabSettings();
+};
+
+void TabSettings::setRetriever(const Retriever &retriever) { g_retriever = retriever; }
+
+TabSettings TabSettings::settingsForFile(const Utils::FilePath &filePath)
+{
+ return g_retriever(filePath);
+}
+
} // namespace TextEditor
diff --git a/src/plugins/texteditor/tabsettings.h b/src/plugins/texteditor/tabsettings.h
index 9a446738d0c..6d9c08e6264 100644
--- a/src/plugins/texteditor/tabsettings.h
+++ b/src/plugins/texteditor/tabsettings.h
@@ -5,11 +5,14 @@
#include "texteditor_global.h"
-#include <utils/store.h>
+#include <utils/filepath.h>
#include <utils/qtcsettings.h>
+#include <utils/store.h>
#include <QTextBlock>
+#include <functional>
+
namespace TextEditor {
// Tab settings: Data type the GeneralSettingsPage acts on
@@ -71,6 +74,10 @@ public:
ContinuationAlignBehavior m_continuationAlignBehavior = ContinuationAlignWithSpaces;
bool equals(const TabSettings &ts) const;
+
+ using Retriever = std::function<TabSettings(const Utils::FilePath &)>;
+ static void setRetriever(const Retriever &retriever);
+ static TabSettings settingsForFile(const Utils::FilePath &filePath);
};
} // namespace TextEditor