From 92156cc1d6290e71a7e591552132102457d7c926 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 3 Feb 2022 10:36:40 +0100 Subject: LanguageClient: Indent code coming from the server ... if the client implementation requests it. The server is not necessarily aware of our indentation style, so we might have to apply it to the newly inserted code. Change-Id: I43518575c7124568da42be3b04a28d7f352f6dc2 Reviewed-by: Qt CI Bot Reviewed-by: Reviewed-by: David Schulz --- src/plugins/clangcodemodel/clangdclient.cpp | 7 ++ src/plugins/clangcodemodel/clangdclient.h | 1 + src/plugins/cppeditor/cpprefactoringchanges.cpp | 105 +++++++++------------ src/plugins/cppeditor/cpprefactoringchanges.h | 23 +++++ src/plugins/languageclient/client.cpp | 5 + src/plugins/languageclient/client.h | 3 + .../languageclient/languageclientsymbolsupport.cpp | 2 +- src/plugins/languageclient/languageclientutils.cpp | 13 ++- src/plugins/languageclient/languageclientutils.h | 3 +- src/plugins/texteditor/refactoringchanges.cpp | 6 +- src/plugins/texteditor/refactoringchanges.h | 4 +- 11 files changed, 100 insertions(+), 72 deletions(-) diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index c22f1f7445..c5aed091b2 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -1528,6 +1529,12 @@ const LanguageClient::Client::CustomInspectorTabs ClangdClient::createCustomInsp return {std::make_pair(new MemoryUsageWidget(this), tr("Memory Usage"))}; } +RefactoringChangesData *ClangdClient::createRefactoringChangesBackend() const +{ + return new CppEditor::CppRefactoringChangesData( + CppEditor::CppModelManager::instance()->snapshot()); +} + QVersionNumber ClangdClient::versionNumber() const { if (d->versionNumber) diff --git a/src/plugins/clangcodemodel/clangdclient.h b/src/plugins/clangcodemodel/clangdclient.h index 92ca40d0ff..68a35adbc1 100644 --- a/src/plugins/clangcodemodel/clangdclient.h +++ b/src/plugins/clangcodemodel/clangdclient.h @@ -105,6 +105,7 @@ private: QTextCursor adjustedCursorForHighlighting(const QTextCursor &cursor, TextEditor::TextDocument *doc) override; const CustomInspectorTabs createCustomInspectorTabs() override; + TextEditor::RefactoringChangesData *createRefactoringChangesBackend() const override; class Private; class FollowSymbolData; diff --git a/src/plugins/cppeditor/cpprefactoringchanges.cpp b/src/plugins/cppeditor/cpprefactoringchanges.cpp index 6e48ae1500..10ff7fc62f 100644 --- a/src/plugins/cppeditor/cpprefactoringchanges.cpp +++ b/src/plugins/cppeditor/cpprefactoringchanges.cpp @@ -28,8 +28,6 @@ #include "cppqtstyleindenter.h" #include "cppcodeformatter.h" #include "cppeditorconstants.h" -#include "cppmodelmanager.h" -#include "cppworkingcopy.h" #include @@ -45,63 +43,15 @@ using namespace CPlusPlus; namespace CppEditor { -class CppRefactoringChangesData : public TextEditor::RefactoringChangesData +static std::unique_ptr createIndenter(const Utils::FilePath &filePath, + QTextDocument *textDocument) { - static std::unique_ptr createIndenter(const Utils::FilePath &filePath, - QTextDocument *textDocument) - { - TextEditor::ICodeStylePreferencesFactory *factory - = TextEditor::TextEditorSettings::codeStyleFactory(Constants::CPP_SETTINGS_ID); - std::unique_ptr indenter(factory->createIndenter(textDocument)); - indenter->setFileName(filePath); - return indenter; - } - -public: - explicit CppRefactoringChangesData(const Snapshot &snapshot) - : m_snapshot(snapshot) - , m_modelManager(CppModelManager::instance()) - , m_workingCopy(m_modelManager->workingCopy()) - {} - - void indentSelection(const QTextCursor &selection, - const Utils::FilePath &filePath, - const TextEditor::TextDocument *textDocument) const override - { - 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.toString(), - textDocument); - auto indenter = createIndenter(filePath, selection.document()); - indenter->indent(selection, QChar::Null, tabSettings); - } - } - - void reindentSelection(const QTextCursor &selection, - const Utils::FilePath &filePath, - const TextEditor::TextDocument *textDocument) const override - { - 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.toString(), - textDocument); - auto indenter = createIndenter(filePath, selection.document()); - indenter->reindent(selection, tabSettings); - } - } - - void fileChanged(const Utils::FilePath &filePath) override - { - m_modelManager->updateSourceFiles({filePath.toString()}); - } - - Snapshot m_snapshot; - CppModelManager *m_modelManager; - WorkingCopy m_workingCopy; - -}; + TextEditor::ICodeStylePreferencesFactory *factory + = TextEditor::TextEditorSettings::codeStyleFactory(Constants::CPP_SETTINGS_ID); + std::unique_ptr indenter(factory->createIndenter(textDocument)); + indenter->setFileName(filePath); + return indenter; +} CppRefactoringChanges::CppRefactoringChanges(const Snapshot &snapshot) : RefactoringChanges(new CppRefactoringChangesData(snapshot)) @@ -283,4 +233,43 @@ void CppRefactoringFile::fileChanged() RefactoringFile::fileChanged(); } +CppRefactoringChangesData::CppRefactoringChangesData(const Snapshot &snapshot) + : m_snapshot(snapshot) + , m_modelManager(CppModelManager::instance()) + , m_workingCopy(m_modelManager->workingCopy()) +{} + +void CppRefactoringChangesData::indentSelection(const QTextCursor &selection, + const Utils::FilePath &filePath, + 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.toString(), + textDocument); + auto indenter = createIndenter(filePath, selection.document()); + indenter->indent(selection, QChar::Null, tabSettings); + } +} + +void CppRefactoringChangesData::reindentSelection(const QTextCursor &selection, + const Utils::FilePath &filePath, + 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.toString(), + textDocument); + auto indenter = createIndenter(filePath, selection.document()); + indenter->reindent(selection, tabSettings); + } +} + +void CppRefactoringChangesData::fileChanged(const Utils::FilePath &filePath) +{ + m_modelManager->updateSourceFiles({filePath.toString()}); +} + } // namespace CppEditor diff --git a/src/plugins/cppeditor/cpprefactoringchanges.h b/src/plugins/cppeditor/cpprefactoringchanges.h index a50631856a..2b4d09b9e5 100644 --- a/src/plugins/cppeditor/cpprefactoringchanges.h +++ b/src/plugins/cppeditor/cpprefactoringchanges.h @@ -27,6 +27,9 @@ #include "cppeditor_global.h" +#include "cppmodelmanager.h" +#include "cppworkingcopy.h" + #include #include @@ -79,6 +82,26 @@ protected: friend class CppRefactoringChanges; // for access to constructor }; +class CPPEDITOR_EXPORT CppRefactoringChangesData : public TextEditor::RefactoringChangesData +{ +public: + explicit CppRefactoringChangesData(const CPlusPlus::Snapshot &snapshot); + + void indentSelection(const QTextCursor &selection, + const Utils::FilePath &filePath, + const TextEditor::TextDocument *textDocument) const override; + + void reindentSelection(const QTextCursor &selection, + const Utils::FilePath &filePath, + const TextEditor::TextDocument *textDocument) const override; + + void fileChanged(const Utils::FilePath &filePath) override; + + CPlusPlus::Snapshot m_snapshot; + CppModelManager *m_modelManager; + WorkingCopy m_workingCopy; +}; + class CPPEDITOR_EXPORT CppRefactoringChanges: public TextEditor::RefactoringChanges { public: diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index bc63a2486b..3507c76340 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -1165,6 +1165,11 @@ void Client::log(const QString &message) const } } +TextEditor::RefactoringChangesData *Client::createRefactoringChangesBackend() const +{ + return new TextEditor::RefactoringChangesData; +} + const ServerCapabilities &Client::capabilities() const { return m_serverCapabilities; diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h index a3fb2e6988..3bee895587 100644 --- a/src/plugins/languageclient/client.h +++ b/src/plugins/languageclient/client.h @@ -207,6 +207,9 @@ public: using CustomInspectorTabs = QList; virtual const CustomInspectorTabs createCustomInspectorTabs() { return {}; } + // Caller takes ownership + virtual TextEditor::RefactoringChangesData *createRefactoringChangesBackend() const; + signals: void initialized(const LanguageServerProtocol::ServerCapabilities &capabilities); void capabilitiesChanged(const DynamicCapabilities &capabilities); diff --git a/src/plugins/languageclient/languageclientsymbolsupport.cpp b/src/plugins/languageclient/languageclientsymbolsupport.cpp index 8199084c41..9283dca53c 100644 --- a/src/plugins/languageclient/languageclientsymbolsupport.cpp +++ b/src/plugins/languageclient/languageclientsymbolsupport.cpp @@ -421,7 +421,7 @@ void SymbolSupport::applyRename(const QList &checkedItem } for (auto it = editsForDocuments.begin(), end = editsForDocuments.end(); it != end; ++it) - applyTextEdits(it.key(), it.value()); + applyTextEdits(m_client, it.key(), it.value()); } Core::Search::TextRange SymbolSupport::convertRange(const Range &range) diff --git a/src/plugins/languageclient/languageclientutils.cpp b/src/plugins/languageclient/languageclientutils.cpp index f0a2db61ff..de07c29a6e 100644 --- a/src/plugins/languageclient/languageclientutils.cpp +++ b/src/plugins/languageclient/languageclientutils.cpp @@ -88,17 +88,22 @@ bool applyTextDocumentEdit(const Client *client, const TextDocumentEdit &edit) LanguageClientValue version = edit.textDocument().version(); if (!version.isNull() && version.value(0) < client->documentVersion(filePath)) return false; - return applyTextEdits(uri, edits); + return applyTextEdits(client, uri, edits); } -bool applyTextEdits(const DocumentUri &uri, const QList &edits) +bool applyTextEdits(const Client *client, const DocumentUri &uri, const QList &edits) { if (edits.isEmpty()) return true; - RefactoringChanges changes; + RefactoringChangesData * const backend = client->createRefactoringChangesBackend(); + RefactoringChanges changes(backend); RefactoringFilePtr file; file = changes.file(uri.toFilePath()); file->setChangeSet(editsToChangeSet(edits, file->document())); + if (backend) { + for (const TextEdit &edit : edits) + file->appendIndentRange(convertRange(file->document(), edit.range())); + } return file->apply(); } @@ -130,7 +135,7 @@ bool applyWorkspaceEdit(const Client *client, const WorkspaceEdit &edit) } else { const WorkspaceEdit::Changes &changes = edit.changes().value_or(WorkspaceEdit::Changes()); for (auto it = changes.cbegin(); it != changes.cend(); ++it) - result |= applyTextEdits(it.key(), it.value()); + result |= applyTextEdits(client, it.key(), it.value()); return result; } return result; diff --git a/src/plugins/languageclient/languageclientutils.h b/src/plugins/languageclient/languageclientutils.h index c812076607..f97c9a9930 100644 --- a/src/plugins/languageclient/languageclientutils.h +++ b/src/plugins/languageclient/languageclientutils.h @@ -51,7 +51,8 @@ Utils::ChangeSet editsToChangeSet(const QList bool LANGUAGECLIENT_EXPORT applyWorkspaceEdit(const Client *client, const LanguageServerProtocol::WorkspaceEdit &edit); bool LANGUAGECLIENT_EXPORT applyTextDocumentEdit(const Client *client, const LanguageServerProtocol::TextDocumentEdit &edit); -bool LANGUAGECLIENT_EXPORT applyTextEdits(const LanguageServerProtocol::DocumentUri &uri, +bool LANGUAGECLIENT_EXPORT applyTextEdits(const Client *client, + const LanguageServerProtocol::DocumentUri &uri, const QList &edits); void LANGUAGECLIENT_EXPORT applyTextEdit(TextEditor::TextDocumentManipulatorInterface &manipulator, const LanguageServerProtocol::TextEdit &edit, diff --git a/src/plugins/texteditor/refactoringchanges.cpp b/src/plugins/texteditor/refactoringchanges.cpp index 6872c18c60..690bd745e2 100644 --- a/src/plugins/texteditor/refactoringchanges.cpp +++ b/src/plugins/texteditor/refactoringchanges.cpp @@ -48,12 +48,8 @@ using namespace Utils; namespace TextEditor { -RefactoringChanges::RefactoringChanges() - : m_data(new RefactoringChangesData) -{} - RefactoringChanges::RefactoringChanges(RefactoringChangesData *data) - : m_data(data) + : m_data(data ? data : new RefactoringChangesData) {} RefactoringChanges::~RefactoringChanges() = default; diff --git a/src/plugins/texteditor/refactoringchanges.h b/src/plugins/texteditor/refactoringchanges.h index bce0e5d745..714bdfd683 100644 --- a/src/plugins/texteditor/refactoringchanges.h +++ b/src/plugins/texteditor/refactoringchanges.h @@ -122,7 +122,7 @@ class TEXTEDITOR_EXPORT RefactoringChanges public: using Range = Utils::ChangeSet::Range; - RefactoringChanges(); + explicit RefactoringChanges(RefactoringChangesData *data = nullptr); virtual ~RefactoringChanges(); static RefactoringFilePtr file(TextEditorWidget *editor); @@ -134,8 +134,6 @@ public: bool removeFile(const Utils::FilePath &filePath) const; protected: - explicit RefactoringChanges(RefactoringChangesData *data); - static TextEditorWidget *openEditor(const Utils::FilePath &filePath, bool activate, int line, -- cgit v1.2.3