Commit 56bbc3aa authored by Mark Nauwelaerts's avatar Mark Nauwelaerts

lspclient: optionally perform incremental document sync

parent 0d0f7294
......@@ -55,6 +55,7 @@ LSPClientConfigPage::LSPClientConfigPage(QWidget *parent, LSPClientPlugin *plugi
m_complDoc = new QCheckBox(i18n("Show selected completion documentation"));
m_refDeclaration = new QCheckBox(i18n("Include declaration in references"));
m_onTypeFormatting = new QCheckBox(i18n("Format on typing"));
m_incrementalSync = new QCheckBox(i18n("Incremental document synchronization"));
QHBoxLayout *diagLayout = new QHBoxLayout();
m_diagnostics = new QCheckBox(i18n("Show diagnostics notifications"));
m_diagnosticsHighlight = new QCheckBox(i18n("Add highlights"));
......@@ -62,6 +63,7 @@ LSPClientConfigPage::LSPClientConfigPage(QWidget *parent, LSPClientPlugin *plugi
top->addWidget(m_complDoc);
top->addWidget(m_refDeclaration);
top->addWidget(m_onTypeFormatting);
top->addWidget(m_incrementalSync);
diagLayout->addWidget(m_diagnostics);
diagLayout->addStretch(1);
diagLayout->addWidget(m_diagnosticsHighlight);
......@@ -82,7 +84,7 @@ LSPClientConfigPage::LSPClientConfigPage(QWidget *parent, LSPClientPlugin *plugi
for (const auto & cb : {m_symbolDetails, m_symbolExpand, m_symbolSort, m_symbolTree,
m_complDoc, m_refDeclaration, m_diagnostics, m_diagnosticsMark,
m_onTypeFormatting})
m_onTypeFormatting, m_incrementalSync})
connect(cb, &QCheckBox::toggled, this, &LSPClientConfigPage::changed);
connect(m_configPath, &KUrlRequester::textChanged, this, &LSPClientConfigPage::changed);
connect(m_configPath, &KUrlRequester::urlSelected, this, &LSPClientConfigPage::changed);
......@@ -127,6 +129,7 @@ void LSPClientConfigPage::apply()
m_plugin->m_diagnosticsMark = m_diagnosticsMark->isChecked();
m_plugin->m_onTypeFormatting = m_onTypeFormatting->isChecked();
m_plugin->m_incrementalSync = m_incrementalSync->isChecked();
m_plugin->m_configPath = m_configPath->url();
......@@ -148,6 +151,7 @@ void LSPClientConfigPage::reset()
m_diagnosticsMark->setChecked(m_plugin->m_diagnosticsMark);
m_onTypeFormatting->setChecked(m_plugin->m_onTypeFormatting);
m_incrementalSync->setChecked(m_plugin->m_incrementalSync);
m_configPath->setUrl(m_plugin->m_configPath);
}
......
......@@ -62,6 +62,7 @@ class LSPClientConfigPage : public KTextEditor::ConfigPage
QCheckBox* m_diagnosticsHighlight;
QCheckBox* m_diagnosticsMark;
QCheckBox* m_onTypeFormatting;
QCheckBox* m_incrementalSync;
KUrlRequester *m_configPath;
LSPClientPlugin *m_plugin;
......
......@@ -43,6 +43,7 @@ static const QString CONFIG_SYMBOL_SORT { QStringLiteral("SymbolSort") };
static const QString CONFIG_COMPLETION_DOC { QStringLiteral("CompletionDocumentation") };
static const QString CONFIG_REFERENCES_DECLARATION { QStringLiteral("ReferencesDeclaration") };
static const QString CONFIG_TYPE_FORMATTING { QStringLiteral("TypeFormatting") };
static const QString CONFIG_INCREMENTAL_SYNC { QStringLiteral("IncrementalSync") };
static const QString CONFIG_DIAGNOSTICS { QStringLiteral("Diagnostics") };
static const QString CONFIG_DIAGNOSTICS_HIGHLIGHT { QStringLiteral("DiagnosticsHighlight") };
static const QString CONFIG_DIAGNOSTICS_MARK { QStringLiteral("DiagnosticsMark") };
......@@ -101,6 +102,7 @@ void LSPClientPlugin::readConfig()
m_complDoc = config.readEntry(CONFIG_COMPLETION_DOC, true);
m_refDeclaration = config.readEntry(CONFIG_REFERENCES_DECLARATION, true);
m_onTypeFormatting = config.readEntry(CONFIG_TYPE_FORMATTING, false);
m_incrementalSync = config.readEntry(CONFIG_INCREMENTAL_SYNC, false);
m_diagnostics = config.readEntry(CONFIG_DIAGNOSTICS, true);
m_diagnosticsHighlight = config.readEntry(CONFIG_DIAGNOSTICS_HIGHLIGHT, true);
m_diagnosticsMark = config.readEntry(CONFIG_DIAGNOSTICS_MARK, true);
......@@ -119,6 +121,7 @@ void LSPClientPlugin::writeConfig() const
config.writeEntry(CONFIG_COMPLETION_DOC, m_complDoc);
config.writeEntry(CONFIG_REFERENCES_DECLARATION, m_refDeclaration);
config.writeEntry(CONFIG_TYPE_FORMATTING, m_onTypeFormatting);
config.writeEntry(CONFIG_INCREMENTAL_SYNC, m_incrementalSync);
config.writeEntry(CONFIG_DIAGNOSTICS, m_diagnostics);
config.writeEntry(CONFIG_DIAGNOSTICS_HIGHLIGHT, m_diagnosticsHighlight);
config.writeEntry(CONFIG_DIAGNOSTICS_MARK, m_diagnosticsMark);
......
......@@ -58,6 +58,7 @@ class LSPClientPlugin : public KTextEditor::Plugin
bool m_diagnosticsHighlight;
bool m_diagnosticsMark;
bool m_onTypeFormatting;
bool m_incrementalSync;
QUrl m_configPath;
// debug mode?
......
......@@ -225,6 +225,7 @@ class LSPClientActionView : public QObject
QPointer<QAction> m_complDocOn;
QPointer<QAction> m_refDeclaration;
QPointer<QAction> m_onTypeFormatting;
QPointer<QAction> m_incrementalSync;
QPointer<QAction> m_diagnostics;
QPointer<QAction> m_diagnosticsHighlight;
QPointer<QAction> m_diagnosticsMark;
......@@ -315,6 +316,9 @@ public:
m_onTypeFormatting = actionCollection()->addAction(QStringLiteral("lspclient_type_formatting"), this, &self_type::displayOptionChanged);
m_onTypeFormatting->setText(i18n("Format on typing"));
m_onTypeFormatting->setCheckable(true);
m_incrementalSync = actionCollection()->addAction(QStringLiteral("lspclient_incremental_sync"), this, &self_type::displayOptionChanged);
m_incrementalSync->setText(i18n("Incremental document synchronization"));
m_incrementalSync->setCheckable(true);
// diagnostics
m_diagnostics = actionCollection()->addAction(QStringLiteral("lspclient_diagnostics"), this, &self_type::displayOptionChanged);
......@@ -347,6 +351,7 @@ public:
menu->addAction(m_complDocOn);
menu->addAction(m_refDeclaration);
menu->addAction(m_onTypeFormatting);
menu->addAction(m_incrementalSync);
menu->addSeparator();
menu->addAction(m_diagnostics);
menu->addAction(m_diagnosticsHighlight);
......@@ -427,6 +432,7 @@ public:
m_diagnosticsTreeOwn.reset(m_diagnosticsTree);
m_tabWidget->removeTab(index);
}
m_serverManager->setIncrementalSync(m_incrementalSync->isChecked());
updateState();
}
......@@ -438,6 +444,8 @@ public:
m_refDeclaration->setChecked(m_plugin->m_refDeclaration);
if (m_onTypeFormatting)
m_onTypeFormatting->setChecked(m_plugin->m_onTypeFormatting);
if (m_incrementalSync)
m_incrementalSync->setChecked(m_plugin->m_incrementalSync);
if (m_diagnostics)
m_diagnostics->setChecked(m_plugin->m_diagnostics);
if (m_diagnosticsHighlight)
......
......@@ -278,8 +278,10 @@ class LSPClientServerManagerImpl : public LSPClientServerManager
KTextEditor::MovingInterface *movingInterface;
QUrl url;
qint64 version;
bool open;
bool modified;
bool open:1;
bool modified:1;
// used for incremental update (if non-empty)
QList<LSPTextDocumentContentChangeEvent> changes;
};
LSPClientPlugin *m_plugin;
......@@ -289,6 +291,7 @@ class LSPClientServerManagerImpl : public LSPClientServerManager
// root -> (mode -> server)
QMap<QUrl, QMap<QString, QSharedPointer<LSPClientServer>>> m_servers;
QHash<KTextEditor::Document*, DocumentInfo> m_docs;
bool m_incrementalSync = false;
typedef QVector<QSharedPointer<LSPClientServer>> ServerList;
......@@ -352,6 +355,9 @@ public:
}
}
void setIncrementalSync(bool inc) override
{ m_incrementalSync = inc; }
QSharedPointer<LSPClientServer>
findServer(KTextEditor::Document *document, bool updatedoc = true) override
{
......@@ -625,13 +631,18 @@ private:
auto it = m_docs.find(doc);
if (it == m_docs.end()) {
KTextEditor::MovingInterface* miface = qobject_cast<KTextEditor::MovingInterface*>(doc);
it = m_docs.insert(doc, {server, miface, doc->url(), 0, false, true});
it = m_docs.insert(doc, {server, miface, doc->url(), 0, false, false, {}});
// track document
connect(doc, &KTextEditor::Document::documentUrlChanged, this, &self_type::untrack, Qt::UniqueConnection);
connect(doc, &KTextEditor::Document::highlightingModeChanged, this, &self_type::untrack, Qt::UniqueConnection);
connect(doc, &KTextEditor::Document::aboutToClose, this, &self_type::untrack, Qt::UniqueConnection);
connect(doc, &KTextEditor::Document::destroyed, this, &self_type::untrack, Qt::UniqueConnection);
connect(doc, &KTextEditor::Document::textChanged, this, &self_type::onTextChanged, Qt::UniqueConnection);
// in case of incremental change
connect(doc, &KTextEditor::Document::textInserted, this, &self_type::onTextInserted, Qt::UniqueConnection);
connect(doc, &KTextEditor::Document::textRemoved, this, &self_type::onTextRemoved, Qt::UniqueConnection);
connect(doc, &KTextEditor::Document::lineWrapped, this, &self_type::onLineWrapped, Qt::UniqueConnection);
connect(doc, &KTextEditor::Document::lineUnwrapped, this, &self_type::onLineUnwrapped, Qt::UniqueConnection);
} else {
it->server = server;
}
......@@ -680,15 +691,21 @@ private:
} else if (it->modified) {
++it->version;
}
if (!m_incrementalSync) {
it->changes.clear();
}
if (it->open) {
if (it->modified || force) {
(it->server)->didChange(it->url, it->version, doc->text());
it->modified = false;
(it->server)->didChange(it->url, it->version,
(it->changes.size() == 0) ? doc->text() : QString(),
it->changes);
}
} else {
(it->server)->didOpen(it->url, it->version, languageId(doc->highlightingMode()), doc->text());
it->open = true;
}
it->modified = false;
it->changes.clear();
}
}
......@@ -713,6 +730,61 @@ private:
it->modified = true;
}
}
DocumentInfo*
getDocumentInfo(KTextEditor::Document *doc)
{
if (!m_incrementalSync)
return nullptr;
auto it = m_docs.find(doc);
if (it != m_docs.end() && it->server) {
const auto& caps = it->server->capabilities();
if (caps.textDocumentSync == LSPDocumentSyncKind::Incremental) {
return &(*it);
}
}
return nullptr;
}
void onTextInserted(KTextEditor::Document *doc, const KTextEditor::Cursor &position, const QString &text)
{
auto info = getDocumentInfo(doc);
if (info) {
info->changes.push_back({LSPRange{position, position}, text});
}
}
void onTextRemoved(KTextEditor::Document *doc, const KTextEditor::Range &range, const QString &text)
{
(void)text;
auto info = getDocumentInfo(doc);
if (info) {
info->changes.push_back({range, QString()});
}
}
void onLineWrapped(KTextEditor::Document *doc, const KTextEditor::Cursor &position)
{
// so a 'newline' has been inserted at position
// could have been UNIX style or other kind, let's ask the document
auto text = doc->text({position, {position.line() + 1, 0}});
onTextInserted(doc, position, text);
}
void onLineUnwrapped(KTextEditor::Document *doc, int line)
{
// lines line-1 and line got replaced by current content of line-1
Q_ASSERT(line > 0);
auto info = getDocumentInfo(doc);
if (info) {
LSPRange oldrange {{line - 1, 0}, {line + 1, 0}};
LSPRange newrange {{line - 1, 0}, {line, 0}};
auto text = doc->text(newrange);
info->changes.push_back({oldrange, text});
}
}
};
QSharedPointer<LSPClientServerManager>
......
......@@ -67,6 +67,8 @@ public:
virtual void restart(LSPClientServer *server) = 0;
virtual void setIncrementalSync(bool inc) = 0;
// latest sync'ed revision of doc (-1 if N/A)
virtual qint64 revision(KTextEditor::Document *doc) = 0;
......
......@@ -15,6 +15,7 @@
<Action name="lspclient_completion_doc"/>
<Action name="lspclient_references_declaration"/>
<Action name="lspclient_type_formatting"/>
<Action name="lspclient_incremental_sync"/>
<Separator/>
<Action name="lspclient_diagnostics"/>
<Action name="lspclient_diagnostics_highlight"/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment