forked from qt-creator/qt-creator
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 <qt_ci_bot@qt-project.org> Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -51,6 +51,7 @@
|
||||
#include <cppeditor/cppeditorwidget.h>
|
||||
#include <cppeditor/cppfindreferences.h>
|
||||
#include <cppeditor/cppmodelmanager.h>
|
||||
#include <cppeditor/cpprefactoringchanges.h>
|
||||
#include <cppeditor/cpptoolsreuse.h>
|
||||
#include <cppeditor/cppvirtualfunctionassistprovider.h>
|
||||
#include <cppeditor/cppvirtualfunctionproposalitem.h>
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
#include "cppqtstyleindenter.h"
|
||||
#include "cppcodeformatter.h"
|
||||
#include "cppeditorconstants.h"
|
||||
#include "cppmodelmanager.h"
|
||||
#include "cppworkingcopy.h"
|
||||
|
||||
#include <projectexplorer/editorconfiguration.h>
|
||||
|
||||
@@ -45,63 +43,15 @@ using namespace CPlusPlus;
|
||||
|
||||
namespace CppEditor {
|
||||
|
||||
class CppRefactoringChangesData : public TextEditor::RefactoringChangesData
|
||||
static std::unique_ptr<TextEditor::Indenter> createIndenter(const Utils::FilePath &filePath,
|
||||
QTextDocument *textDocument)
|
||||
{
|
||||
static std::unique_ptr<TextEditor::Indenter> createIndenter(const Utils::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;
|
||||
}
|
||||
|
||||
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<TextEditor::Indenter> 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
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
|
||||
#include "cppeditor_global.h"
|
||||
|
||||
#include "cppmodelmanager.h"
|
||||
#include "cppworkingcopy.h"
|
||||
|
||||
#include <cplusplus/CppDocument.h>
|
||||
|
||||
#include <texteditor/refactoringchanges.h>
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -207,6 +207,9 @@ public:
|
||||
using CustomInspectorTabs = QList<CustomInspectorTab>;
|
||||
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);
|
||||
|
||||
@@ -421,7 +421,7 @@ void SymbolSupport::applyRename(const QList<Core::SearchResultItem> &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)
|
||||
|
||||
@@ -88,17 +88,22 @@ bool applyTextDocumentEdit(const Client *client, const TextDocumentEdit &edit)
|
||||
LanguageClientValue<int> 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<TextEdit> &edits)
|
||||
bool applyTextEdits(const Client *client, const DocumentUri &uri, const QList<TextEdit> &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;
|
||||
|
||||
@@ -51,7 +51,8 @@ Utils::ChangeSet editsToChangeSet(const QList<LanguageServerProtocol::TextEdit>
|
||||
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<LanguageServerProtocol::TextEdit> &edits);
|
||||
void LANGUAGECLIENT_EXPORT applyTextEdit(TextEditor::TextDocumentManipulatorInterface &manipulator,
|
||||
const LanguageServerProtocol::TextEdit &edit,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user