forked from qt-creator/qt-creator
LanguageClient: Improve formatting
Use Utils::ChangeSet and TextEditor::RefactoringChanges to apply the text edits that are reported from language server to format the current file. Change-Id: Id2f490b6e2791f676ebc751219bfbbf9e178f120 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -67,16 +67,16 @@ static const FormattingOptions formattingOptions(const TextEditor::TabSettings &
|
||||
return options;
|
||||
}
|
||||
|
||||
QFutureWatcher<Utils::Text::Replacements> *LanguageClientFormatter::format(
|
||||
QFutureWatcher<ChangeSet> *LanguageClientFormatter::format(
|
||||
const QTextCursor &cursor, const TextEditor::TabSettings &tabSettings)
|
||||
{
|
||||
cancelCurrentRequest();
|
||||
m_progress = QFutureInterface<Utils::Text::Replacements>();
|
||||
m_progress = QFutureInterface<ChangeSet>();
|
||||
|
||||
const FilePath &filePath = m_document->filePath();
|
||||
const DynamicCapabilities dynamicCapabilities = m_client->dynamicCapabilities();
|
||||
const QString method(DocumentRangeFormattingRequest::methodName);
|
||||
if (Utils::optional<bool> registered = dynamicCapabilities.isRegistered(method)) {
|
||||
if (optional<bool> registered = dynamicCapabilities.isRegistered(method)) {
|
||||
if (!registered.value())
|
||||
return nullptr;
|
||||
const TextDocumentRegistrationOptions option(dynamicCapabilities.option(method).toObject());
|
||||
@@ -107,7 +107,7 @@ QFutureWatcher<Utils::Text::Replacements> *LanguageClientFormatter::format(
|
||||
// ignore first contents changed, because this function is called inside a begin/endEdit block
|
||||
m_ignoreCancel = true;
|
||||
m_progress.reportStarted();
|
||||
auto watcher = new QFutureWatcher<Text::Replacements>();
|
||||
auto watcher = new QFutureWatcher<ChangeSet>();
|
||||
watcher->setFuture(m_progress.future());
|
||||
QObject::connect(watcher, &QFutureWatcher<Text::Replacements>::canceled, [this]() {
|
||||
cancelCurrentRequest();
|
||||
@@ -131,16 +131,12 @@ void LanguageClientFormatter::handleResponse(const DocumentRangeFormattingReques
|
||||
m_currentRequest = nullopt;
|
||||
if (const optional<DocumentRangeFormattingRequest::Response::Error> &error = response.error())
|
||||
m_client->log(*error);
|
||||
Text::Replacements replacements;
|
||||
ChangeSet changeSet;
|
||||
if (optional<LanguageClientArray<TextEdit>> result = response.result()) {
|
||||
if (!result->isNull()) {
|
||||
const QList<TextEdit> results = result->toList();
|
||||
replacements.reserve(results.size());
|
||||
for (const TextEdit &edit : results)
|
||||
replacements.emplace_back(edit.toReplacement(m_document->document()));
|
||||
if (!result->isNull())
|
||||
changeSet = editsToChangeSet(result->toList(), m_document->document());
|
||||
}
|
||||
}
|
||||
m_progress.reportResult(replacements);
|
||||
m_progress.reportResult(changeSet);
|
||||
m_progress.reportFinished();
|
||||
}
|
||||
|
||||
|
@@ -41,7 +41,7 @@ public:
|
||||
LanguageClientFormatter(TextEditor::TextDocument *document, Client *client);
|
||||
~LanguageClientFormatter() override;
|
||||
|
||||
QFutureWatcher<Utils::Text::Replacements> *format(
|
||||
QFutureWatcher<Utils::ChangeSet> *format(
|
||||
const QTextCursor &cursor, const TextEditor::TabSettings &tabSettings) override;
|
||||
|
||||
private:
|
||||
@@ -53,7 +53,7 @@ private:
|
||||
QMetaObject::Connection m_cancelConnection;
|
||||
TextEditor::TextDocument *m_document; // not owned
|
||||
bool m_ignoreCancel = false;
|
||||
QFutureInterface<Utils::Text::Replacements> m_progress;
|
||||
QFutureInterface<Utils::ChangeSet> m_progress;
|
||||
Utils::optional<LanguageServerProtocol::MessageId> m_currentRequest;
|
||||
};
|
||||
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include <languageserverprotocol/languagefeatures.h>
|
||||
|
||||
#include <texteditor/refactoroverlay.h>
|
||||
#include <utils/changeset.h>
|
||||
|
||||
namespace Core { class IEditor; }
|
||||
|
||||
@@ -41,6 +42,8 @@ namespace LanguageClient {
|
||||
|
||||
class Client;
|
||||
|
||||
Utils::ChangeSet editsToChangeSet(const QList<LanguageServerProtocol::TextEdit> &edits,
|
||||
const QTextDocument *doc);
|
||||
bool applyWorkspaceEdit(const LanguageServerProtocol::WorkspaceEdit &edit);
|
||||
bool applyTextDocumentEdit(const LanguageServerProtocol::TextDocumentEdit &edit);
|
||||
bool applyTextEdits(const LanguageServerProtocol::DocumentUri &uri,
|
||||
|
@@ -25,9 +25,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "texteditor_global.h"
|
||||
#include "refactoringchanges.h"
|
||||
|
||||
#include <utils/textutils.h>
|
||||
#include <utils/changeset.h>
|
||||
|
||||
#include <QFutureWatcher>
|
||||
#include <QString>
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
Formatter() = default;
|
||||
virtual ~Formatter() = default;
|
||||
|
||||
virtual QFutureWatcher<Utils::Text::Replacements> *format(
|
||||
virtual QFutureWatcher<Utils::ChangeSet> *format(
|
||||
const QTextCursor & /*cursor*/, const TextEditor::TabSettings & /*tabSettings*/)
|
||||
{
|
||||
return nullptr;
|
||||
@@ -55,14 +55,14 @@ public:
|
||||
|
||||
virtual bool isElectricCharacter(const QChar & /*ch*/) const { return false; }
|
||||
virtual bool supportsAutoFormat() const { return false; }
|
||||
virtual QFutureWatcher<Utils::Text::Replacements> *autoFormat(
|
||||
virtual QFutureWatcher<Utils::ChangeSet> *autoFormat(
|
||||
const QTextCursor & /*cursor*/, const TextEditor::TabSettings & /*tabSettings*/)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual bool supportsFormatOnSave() const { return false; }
|
||||
virtual QFutureWatcher<Utils::Text::Replacements> *formatOnSave(
|
||||
virtual QFutureWatcher<Utils::ChangeSet> *formatOnSave(
|
||||
const QTextCursor & /*cursor*/, const TextEditor::TabSettings & /*tabSettings*/)
|
||||
{
|
||||
return nullptr;
|
||||
|
@@ -518,15 +518,25 @@ void TextDocument::autoFormat(const QTextCursor &cursor)
|
||||
using namespace Utils::Text;
|
||||
if (!d->m_formatter)
|
||||
return;
|
||||
if (QFutureWatcher<Replacements> *watcher = d->m_formatter->format(cursor, tabSettings())) {
|
||||
connect(watcher, &QFutureWatcher<Replacements>::finished, this, [this, watcher]() {
|
||||
if (QFutureWatcher<ChangeSet> *watcher = d->m_formatter->format(cursor, tabSettings())) {
|
||||
connect(watcher, &QFutureWatcher<ChangeSet>::finished, this, [this, watcher]() {
|
||||
if (!watcher->isCanceled())
|
||||
Utils::Text::applyReplacements(document(), watcher->result());
|
||||
applyChangeSet(watcher->result());
|
||||
delete watcher;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool TextDocument::applyChangeSet(const ChangeSet &changeSet)
|
||||
{
|
||||
if (changeSet.isEmpty())
|
||||
return true;
|
||||
RefactoringChanges changes;
|
||||
const RefactoringFilePtr file = changes.file(filePath().toString());
|
||||
file->setChangeSet(changeSet);
|
||||
return file->apply();
|
||||
}
|
||||
|
||||
const ExtraEncodingSettings &TextDocument::extraEncodingSettings() const
|
||||
{
|
||||
return d->m_extraEncodingSettings;
|
||||
|
@@ -101,6 +101,7 @@ public:
|
||||
|
||||
void setFormatter(Formatter *indenter); // transfers ownership
|
||||
void autoFormat(const QTextCursor &cursor);
|
||||
bool applyChangeSet(const Utils::ChangeSet &changeSet);
|
||||
|
||||
TextMarks marks() const;
|
||||
bool addMark(TextMark *mark);
|
||||
|
Reference in New Issue
Block a user