diff options
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 |