From 876cb4ceba6cc793acdd92b657227e7344d80ec8 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Wed, 21 Aug 2019 20:49:06 +0200 Subject: [PATCH] lspclient: sprinkle some clang-format --- addons/lspclient/lspclientcompletion.cpp | 104 ++- addons/lspclient/lspclientcompletion.h | 10 +- addons/lspclient/lspclientconfigpage.cpp | 9 +- addons/lspclient/lspclientconfigpage.h | 56 +- addons/lspclient/lspclientplugin.cpp | 14 +- addons/lspclient/lspclientplugin.h | 63 +- addons/lspclient/lspclientpluginview.cpp | 553 +++++++------- addons/lspclient/lspclientpluginview.h | 6 +- addons/lspclient/lspclientprotocol.h | 112 +-- addons/lspclient/lspclientserver.cpp | 764 ++++++++++---------- addons/lspclient/lspclientserver.h | 131 ++-- addons/lspclient/lspclientservermanager.cpp | 240 +++--- addons/lspclient/lspclientservermanager.h | 25 +- addons/lspclient/lspclientsymbolview.cpp | 124 ++-- addons/lspclient/lspclientsymbolview.h | 10 +- 15 files changed, 1109 insertions(+), 1112 deletions(-) diff --git a/addons/lspclient/lspclientcompletion.cpp b/addons/lspclient/lspclientcompletion.cpp index 1e6614171..8e597951a 100644 --- a/addons/lspclient/lspclientcompletion.cpp +++ b/addons/lspclient/lspclientcompletion.cpp @@ -36,17 +36,15 @@ #include -#define RETURN_CACHED_ICON(name) \ -{ \ - static QIcon icon(QIcon::fromTheme(QStringLiteral(name))); \ - return icon; \ -} +#define RETURN_CACHED_ICON(name) \ + { \ + static QIcon icon(QIcon::fromTheme(QStringLiteral(name))); \ + return icon; \ + } -static QIcon -kind_icon(LSPCompletionItemKind kind) +static QIcon kind_icon(LSPCompletionItemKind kind) { - switch (kind) - { + switch (kind) { case LSPCompletionItemKind::Method: case LSPCompletionItemKind::Function: case LSPCompletionItemKind::Constructor: @@ -78,8 +76,7 @@ kind_property(LSPCompletionItemKind kind) using CompletionProperty = KTextEditor::CodeCompletionModel::CompletionProperty; auto p = CompletionProperty::NoProperty; - switch (kind) - { + switch (kind) { case LSPCompletionItemKind::Method: case LSPCompletionItemKind::Function: case LSPCompletionItemKind::Constructor: @@ -96,7 +93,7 @@ kind_property(LSPCompletionItemKind kind) p = CompletionProperty::Class; break; case LSPCompletionItemKind::Module: - p =CompletionProperty::Namespace; + p = CompletionProperty::Namespace; break; case LSPCompletionItemKind::Enum: case LSPCompletionItemKind::EnumMember: @@ -108,24 +105,22 @@ kind_property(LSPCompletionItemKind kind) return p; } -struct LSPClientCompletionItem : public LSPCompletionItem -{ +struct LSPClientCompletionItem : public LSPCompletionItem { int argumentHintDepth = 0; QString prefix; QString postfix; - LSPClientCompletionItem(const LSPCompletionItem & item) - : LSPCompletionItem(item) + LSPClientCompletionItem(const LSPCompletionItem &item) : LSPCompletionItem(item) { // transform for later display // sigh, remove (leading) whitespace (looking at clangd here) // could skip the [] if empty detail, but it is a handy watermark anyway ;-) - label = QString(label.simplified() + QStringLiteral(" [") + - detail.simplified() + QStringLiteral("]")); + label = QString(label.simplified() + QStringLiteral(" [") + detail.simplified() + + QStringLiteral("]")); } - LSPClientCompletionItem(const LSPSignatureInformation & sig, - int activeParameter, const QString & _sortText) + LSPClientCompletionItem(const LSPSignatureInformation &sig, int activeParameter, + const QString &_sortText) { argumentHintDepth = 1; documentation = sig.documentation; @@ -133,10 +128,9 @@ struct LSPClientCompletionItem : public LSPCompletionItem sortText = _sortText; // transform into prefix, name, suffix if active if (activeParameter >= 0 && activeParameter < sig.parameters.length()) { - const auto& param = sig.parameters.at(activeParameter); - if (param.start >= 0 && param.start < label.length() && - param.end >= 0 && param.end < label.length() && - param.start < param.end) { + const auto ¶m = sig.parameters.at(activeParameter); + if (param.start >= 0 && param.start < label.length() && param.end >= 0 + && param.end < label.length() && param.start < param.end) { prefix = label.mid(0, param.start); postfix = label.mid(param.end); label = label.mid(param.start, param.end - param.start); @@ -145,10 +139,10 @@ struct LSPClientCompletionItem : public LSPCompletionItem } }; - -static bool compare_match (const LSPCompletionItem & a, const LSPCompletionItem b) -{ return a.sortText < b.sortText; } - +static bool compare_match(const LSPCompletionItem &a, const LSPCompletionItem b) +{ + return a.sortText < b.sortText; +} class LSPClientCompletionImpl : public LSPClientCompletion { @@ -177,7 +171,7 @@ public: { m_server = server; if (m_server) { - const auto& caps = m_server->capabilities(); + const auto &caps = m_server->capabilities(); m_triggersCompletion = caps.completionProvider.triggerCharacters; m_triggersSignature = caps.signatureHelpProvider.triggerCharacters; } else { @@ -186,8 +180,7 @@ public: } } - virtual void setSelectedDocumentation(bool s) override - { m_selectedDocumentation = s; } + virtual void setSelectedDocumentation(bool s) override { m_selectedDocumentation = s; } QVariant data(const QModelIndex &index, int role) const override { @@ -205,7 +198,8 @@ public: } else if (index.column() == KTextEditor::CodeCompletionModel::Postfix) { return match.postfix; } - } else if (role == Qt::DecorationRole && index.column() == KTextEditor::CodeCompletionModel::Icon) { + } else if (role == Qt::DecorationRole + && index.column() == KTextEditor::CodeCompletionModel::Icon) { return kind_icon(match.kind); } else if (role == KTextEditor::CodeCompletionModel::CompletionRole) { return kind_property(match.kind); @@ -216,14 +210,14 @@ public: return index.row(); } else if (role == KTextEditor::CodeCompletionModel::IsExpandable) { return !match.documentation.value.isEmpty(); - } else if (role == KTextEditor::CodeCompletionModel::ExpandingWidget && - !match.documentation.value.isEmpty()) { + } else if (role == KTextEditor::CodeCompletionModel::ExpandingWidget + && !match.documentation.value.isEmpty()) { // probably plaintext, but let's show markdown as-is for now // FIXME better presentation of markdown return match.documentation.value; - } else if (role == KTextEditor::CodeCompletionModel::ItemSelected && - !match.argumentHintDepth && !match.documentation.value.isEmpty() && - m_selectedDocumentation) { + } else if (role == KTextEditor::CodeCompletionModel::ItemSelected + && !match.argumentHintDepth && !match.documentation.value.isEmpty() + && m_selectedDocumentation) { return match.documentation.value; } @@ -231,7 +225,7 @@ public: } bool shouldStartCompletion(KTextEditor::View *view, const QString &insertedText, - bool userInsertion, const KTextEditor::Cursor &position) override + bool userInsertion, const KTextEditor::Cursor &position) override { qCInfo(LSPCLIENT) << "should start " << userInsertion << insertedText; @@ -240,12 +234,12 @@ public: } // covers most already ... - bool complete = CodeCompletionModelControllerInterface::shouldStartCompletion(view, - insertedText, userInsertion, position); + bool complete = CodeCompletionModelControllerInterface::shouldStartCompletion( + view, insertedText, userInsertion, position); QChar lastChar = insertedText.at(insertedText.count() - 1); m_triggerSignature = false; - complete = complete || m_triggersCompletion.contains(lastChar); + complete = complete || m_triggersCompletion.contains(lastChar); if (m_triggersSignature.contains(lastChar)) { complete = true; m_triggerSignature = true; @@ -254,7 +248,8 @@ public: return complete; } - void completionInvoked(KTextEditor::View *view, const KTextEditor::Range &range, InvocationType it) override + void completionInvoked(KTextEditor::View *view, const KTextEditor::Range &range, + InvocationType it) override { Q_UNUSED(it) @@ -262,21 +257,21 @@ public: // maybe use WaitForReset ?? // but more complex and already looks good anyway - auto handler = [this] (const QList & compl) { + auto handler = [this](const QList & compl) { beginResetModel(); qCInfo(LSPCLIENT) << "adding completions " << compl.size(); - for (const auto & item : compl) + for (const auto &item : compl) m_matches.push_back(item); std::stable_sort(m_matches.begin(), m_matches.end(), compare_match); setRowCount(m_matches.size()); endResetModel(); }; - auto sigHandler = [this] (const LSPSignatureHelp & sig) { + auto sigHandler = [this](const LSPSignatureHelp &sig) { beginResetModel(); qCInfo(LSPCLIENT) << "adding signatures " << sig.signatures.size(); int index = 0; - for (const auto & item : sig.signatures) { + for (const auto &item : sig.signatures) { int sortIndex = 10 + index; int active = -1; if (index == sig.activeSignature) { @@ -284,7 +279,8 @@ public: active = sig.activeParameter; } // trick active first, others after that - m_matches.push_back({item, active, QString(QStringLiteral("%1").arg(sortIndex, 3, 10))}); + m_matches.push_back( + { item, active, QString(QStringLiteral("%1").arg(sortIndex, 3, 10)) }); ++index; } std::stable_sort(m_matches.begin(), m_matches.end(), compare_match); @@ -303,17 +299,18 @@ public: auto cursor = qMax(range.start(), qMin(range.end(), position)); m_manager->update(document, false); if (!m_triggerSignature) { - m_handle = m_server->documentCompletion(document->url(), - {cursor.line(), cursor.column()}, this, handler); + m_handle = m_server->documentCompletion( + document->url(), { cursor.line(), cursor.column() }, this, handler); } - m_handleSig = m_server->signatureHelp(document->url(), - {cursor.line(), cursor.column()}, this, sigHandler); + m_handleSig = m_server->signatureHelp( + document->url(), { cursor.line(), cursor.column() }, this, sigHandler); } setRowCount(m_matches.size()); endResetModel(); } - void executeCompletionItem(KTextEditor::View *view, const KTextEditor::Range &word, const QModelIndex &index) const override + void executeCompletionItem(KTextEditor::View *view, const KTextEditor::Range &word, + const QModelIndex &index) const override { if (index.row() < m_matches.size()) view->document()->replaceText(word, m_matches.at(index.row()).insertText); @@ -331,8 +328,7 @@ public: } }; -LSPClientCompletion* -LSPClientCompletion::new_(QSharedPointer manager) +LSPClientCompletion *LSPClientCompletion::new_(QSharedPointer manager) { return new LSPClientCompletionImpl(manager); } diff --git a/addons/lspclient/lspclientcompletion.h b/addons/lspclient/lspclientcompletion.h index da3d62a29..3c161057a 100644 --- a/addons/lspclient/lspclientcompletion.h +++ b/addons/lspclient/lspclientcompletion.h @@ -31,20 +31,18 @@ #include #include -class LSPClientCompletion : public KTextEditor::CodeCompletionModel, public KTextEditor::CodeCompletionModelControllerInterface +class LSPClientCompletion : public KTextEditor::CodeCompletionModel, + public KTextEditor::CodeCompletionModelControllerInterface { Q_OBJECT Q_INTERFACES(KTextEditor::CodeCompletionModelControllerInterface) public: - // implementation factory method - static LSPClientCompletion* new_(QSharedPointer manager); + static LSPClientCompletion *new_(QSharedPointer manager); - LSPClientCompletion(QObject * parent) - : KTextEditor::CodeCompletionModel(parent) - {} + LSPClientCompletion(QObject *parent) : KTextEditor::CodeCompletionModel(parent) {} virtual void setServer(QSharedPointer server) = 0; virtual void setSelectedDocumentation(bool) = 0; diff --git a/addons/lspclient/lspclientconfigpage.cpp b/addons/lspclient/lspclientconfigpage.cpp index 63f5903f6..c438117c6 100644 --- a/addons/lspclient/lspclientconfigpage.cpp +++ b/addons/lspclient/lspclientconfigpage.cpp @@ -82,16 +82,15 @@ LSPClientConfigPage::LSPClientConfigPage(QWidget *parent, LSPClientPlugin *plugi reset(); - for (const auto & cb : {m_symbolDetails, m_symbolExpand, m_symbolSort, m_symbolTree, - m_complDoc, m_refDeclaration, m_diagnostics, m_diagnosticsMark, - m_onTypeFormatting, m_incrementalSync}) + for (const auto &cb : { m_symbolDetails, m_symbolExpand, m_symbolSort, m_symbolTree, m_complDoc, + m_refDeclaration, m_diagnostics, m_diagnosticsMark, 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); // custom control logic - auto h = [this] () - { + auto h = [this]() { bool enabled = m_diagnostics->isChecked(); m_diagnosticsHighlight->setEnabled(enabled); m_diagnosticsMark->setEnabled(enabled); diff --git a/addons/lspclient/lspclientconfigpage.h b/addons/lspclient/lspclientconfigpage.h index b623e5fb1..299e2b54e 100644 --- a/addons/lspclient/lspclientconfigpage.h +++ b/addons/lspclient/lspclientconfigpage.h @@ -38,34 +38,34 @@ class LSPClientConfigPage : public KTextEditor::ConfigPage { Q_OBJECT - public: - explicit LSPClientConfigPage(QWidget *parent = nullptr, LSPClientPlugin *plugin = nullptr); - ~LSPClientConfigPage() override {}; - - QString name() const override; - QString fullName() const override; - QIcon icon() const override; - - public Q_SLOTS: - void apply() override; - void defaults() override; - void reset() override; - - private: - QCheckBox* m_symbolDetails; - QCheckBox* m_symbolExpand; - QCheckBox* m_symbolTree; - QCheckBox* m_symbolSort; - QCheckBox* m_complDoc; - QCheckBox* m_refDeclaration; - QCheckBox* m_diagnostics; - QCheckBox* m_diagnosticsHighlight; - QCheckBox* m_diagnosticsMark; - QCheckBox* m_onTypeFormatting; - QCheckBox* m_incrementalSync; - KUrlRequester *m_configPath; - - LSPClientPlugin *m_plugin; +public: + explicit LSPClientConfigPage(QWidget *parent = nullptr, LSPClientPlugin *plugin = nullptr); + ~LSPClientConfigPage() override {}; + + QString name() const override; + QString fullName() const override; + QIcon icon() const override; + +public Q_SLOTS: + void apply() override; + void defaults() override; + void reset() override; + +private: + QCheckBox *m_symbolDetails; + QCheckBox *m_symbolExpand; + QCheckBox *m_symbolTree; + QCheckBox *m_symbolSort; + QCheckBox *m_complDoc; + QCheckBox *m_refDeclaration; + QCheckBox *m_diagnostics; + QCheckBox *m_diagnosticsHighlight; + QCheckBox *m_diagnosticsMark; + QCheckBox *m_onTypeFormatting; + QCheckBox *m_incrementalSync; + KUrlRequester *m_configPath; + + LSPClientPlugin *m_plugin; }; #endif diff --git a/addons/lspclient/lspclientplugin.cpp b/addons/lspclient/lspclientplugin.cpp index b572afd4b..6c8087ee1 100644 --- a/addons/lspclient/lspclientplugin.cpp +++ b/addons/lspclient/lspclientplugin.cpp @@ -49,8 +49,8 @@ static const QString CONFIG_DIAGNOSTICS_HIGHLIGHT { QStringLiteral("DiagnosticsH static const QString CONFIG_DIAGNOSTICS_MARK { QStringLiteral("DiagnosticsMark") }; static const QString CONFIG_SERVER_CONFIG { QStringLiteral("ServerConfiguration") }; - -K_PLUGIN_FACTORY_WITH_JSON(LSPClientPluginFactory, "lspclientplugin.json", registerPlugin();) +K_PLUGIN_FACTORY_WITH_JSON(LSPClientPluginFactory, "lspclientplugin.json", + registerPlugin();) LSPClientPlugin::LSPClientPlugin(QObject *parent, const QList &) : KTextEditor::Plugin(parent) @@ -61,17 +61,17 @@ LSPClientPlugin::LSPClientPlugin(QObject *parent, const QList &) */ m_debugMode = (qgetenv("LSPCLIENT_DEBUG") == QByteArray("1")); if (!m_debugMode) { - QLoggingCategory::setFilterRules(QStringLiteral("katelspclientplugin.debug=false\nkatelspclientplugin.info=false")); + QLoggingCategory::setFilterRules( + QStringLiteral("katelspclientplugin.debug=false\nkatelspclientplugin.info=false")); } else { - QLoggingCategory::setFilterRules(QStringLiteral("katelspclientplugin.debug=true\nkatelspclientplugin.info=true")); + QLoggingCategory::setFilterRules( + QStringLiteral("katelspclientplugin.debug=true\nkatelspclientplugin.info=true")); } readConfig(); } -LSPClientPlugin::~LSPClientPlugin() -{ -} +LSPClientPlugin::~LSPClientPlugin() {} QObject *LSPClientPlugin::createView(KTextEditor::MainWindow *mainWindow) { diff --git a/addons/lspclient/lspclientplugin.h b/addons/lspclient/lspclientplugin.h index 977b030bb..293203c93 100644 --- a/addons/lspclient/lspclientplugin.h +++ b/addons/lspclient/lspclientplugin.h @@ -35,39 +35,40 @@ class LSPClientPlugin : public KTextEditor::Plugin { Q_OBJECT - public: - explicit LSPClientPlugin(QObject *parent = nullptr, const QList & = QList()); - ~LSPClientPlugin() override; - - QObject *createView(KTextEditor::MainWindow *mainWindow) override; - - int configPages() const override; - KTextEditor::ConfigPage *configPage(int number = 0, QWidget *parent = nullptr) override; - - void readConfig(); - void writeConfig() const; - - // settings - bool m_symbolDetails; - bool m_symbolExpand; - bool m_symbolTree; - bool m_symbolSort; - bool m_complDoc; - bool m_refDeclaration; - bool m_diagnostics; - bool m_diagnosticsHighlight; - bool m_diagnosticsMark; - bool m_onTypeFormatting; - bool m_incrementalSync; - QUrl m_configPath; - - // debug mode? - bool m_debugMode = false; +public: + explicit LSPClientPlugin(QObject *parent = nullptr, + const QList & = QList()); + ~LSPClientPlugin() override; + + QObject *createView(KTextEditor::MainWindow *mainWindow) override; + + int configPages() const override; + KTextEditor::ConfigPage *configPage(int number = 0, QWidget *parent = nullptr) override; + + void readConfig(); + void writeConfig() const; + + // settings + bool m_symbolDetails; + bool m_symbolExpand; + bool m_symbolTree; + bool m_symbolSort; + bool m_complDoc; + bool m_refDeclaration; + bool m_diagnostics; + bool m_diagnosticsHighlight; + bool m_diagnosticsMark; + bool m_onTypeFormatting; + bool m_incrementalSync; + QUrl m_configPath; + + // debug mode? + bool m_debugMode = false; private: - Q_SIGNALS: - // signal settings update - void update() const; +Q_SIGNALS: + // signal settings update + void update() const; }; #endif diff --git a/addons/lspclient/lspclientpluginview.cpp b/addons/lspclient/lspclientpluginview.cpp index d9349264e..46f69c6ee 100644 --- a/addons/lspclient/lspclientpluginview.cpp +++ b/addons/lspclient/lspclientpluginview.cpp @@ -65,8 +65,7 @@ #include #include -namespace RangeData -{ +namespace RangeData { enum { // preserve UserRole for generic use where needed @@ -79,54 +78,50 @@ class KindEnum { public: enum _kind { - Text = (int) LSPDocumentHighlightKind::Text, - Read = (int) LSPDocumentHighlightKind::Read, - Write = (int) LSPDocumentHighlightKind::Write, - Error = 10 + (int) LSPDiagnosticSeverity::Error, - Warning = 10 + (int) LSPDiagnosticSeverity::Warning, - Information = 10 + (int) LSPDiagnosticSeverity::Information, - Hint = 10 + (int) LSPDiagnosticSeverity::Hint, + Text = (int)LSPDocumentHighlightKind::Text, + Read = (int)LSPDocumentHighlightKind::Read, + Write = (int)LSPDocumentHighlightKind::Write, + Error = 10 + (int)LSPDiagnosticSeverity::Error, + Warning = 10 + (int)LSPDiagnosticSeverity::Warning, + Information = 10 + (int)LSPDiagnosticSeverity::Information, + Hint = 10 + (int)LSPDiagnosticSeverity::Hint, Related }; - KindEnum(int v) - { m_value = (_kind) v; } + KindEnum(int v) { m_value = (_kind)v; } - KindEnum(LSPDocumentHighlightKind hl) - : KindEnum((_kind) (hl)) - {} + KindEnum(LSPDocumentHighlightKind hl) : KindEnum((_kind)(hl)) {} - KindEnum(LSPDiagnosticSeverity sev) - : KindEnum(_kind(10 + (int) sev)) - {} + KindEnum(LSPDiagnosticSeverity sev) : KindEnum(_kind(10 + (int)sev)) {} - operator _kind() - { return m_value; } + operator _kind() { return m_value; } private: _kind m_value; }; -static constexpr KTextEditor::MarkInterface::MarkTypes markType = KTextEditor::MarkInterface::markType31; -static constexpr KTextEditor::MarkInterface::MarkTypes markTypeDiagError = KTextEditor::MarkInterface::Error; -static constexpr KTextEditor::MarkInterface::MarkTypes markTypeDiagWarning = KTextEditor::MarkInterface::Warning; -static constexpr KTextEditor::MarkInterface::MarkTypes markTypeDiagOther = KTextEditor::MarkInterface::markType30; +static constexpr KTextEditor::MarkInterface::MarkTypes markType = + KTextEditor::MarkInterface::markType31; +static constexpr KTextEditor::MarkInterface::MarkTypes markTypeDiagError = + KTextEditor::MarkInterface::Error; +static constexpr KTextEditor::MarkInterface::MarkTypes markTypeDiagWarning = + KTextEditor::MarkInterface::Warning; +static constexpr KTextEditor::MarkInterface::MarkTypes markTypeDiagOther = + KTextEditor::MarkInterface::markType30; static constexpr KTextEditor::MarkInterface::MarkTypes markTypeDiagAll = - KTextEditor::MarkInterface::MarkTypes (markTypeDiagError | markTypeDiagWarning | markTypeDiagOther); + KTextEditor::MarkInterface::MarkTypes(markTypeDiagError | markTypeDiagWarning + | markTypeDiagOther); } - -static QIcon -diagnosticsIcon(LSPDiagnosticSeverity severity) +static QIcon diagnosticsIcon(LSPDiagnosticSeverity severity) { -#define RETURN_CACHED_ICON(name) \ -{ \ -static QIcon icon(QIcon::fromTheme(QStringLiteral(name))); \ -return icon; \ -} - switch (severity) - { +#define RETURN_CACHED_ICON(name) \ + { \ + static QIcon icon(QIcon::fromTheme(QStringLiteral(name))); \ + return icon; \ + } + switch (severity) { case LSPDiagnosticSeverity::Error: RETURN_CACHED_ICON("dialog-error") case LSPDiagnosticSeverity::Warning: @@ -140,18 +135,16 @@ return icon; \ return QIcon(); } -static QIcon -codeActionIcon() +static QIcon codeActionIcon() { static QIcon icon(QIcon::fromTheme(QStringLiteral("insert-text"))); return icon; } -KTextEditor::Document* -findDocument(KTextEditor::MainWindow *mainWindow, const QUrl & url) +KTextEditor::Document *findDocument(KTextEditor::MainWindow *mainWindow, const QUrl &url) { auto views = mainWindow->views(); - for (const auto v: views) { + for (const auto v : views) { auto doc = v->document(); if (doc && doc->url() == url) return doc; @@ -168,11 +161,7 @@ class FileLineReader QString lastLine; public: - FileLineReader(const QUrl & url) - : file(url.path()) - { - file.open(QIODevice::ReadOnly); - } + FileLineReader(const QUrl &url) : file(url.path()) { file.open(QIODevice::ReadOnly); } // called with non-descending lineno QString line(int lineno) @@ -189,7 +178,7 @@ public: if (state.invalidChars > 0) { text = QString::fromLatin1(line); } - while (text.size() && text.at(text.size() -1).isSpace()) + while (text.size() && text.at(text.size() - 1).isSpace()) text.chop(1); lastLine = text; return text; @@ -199,7 +188,6 @@ public: } }; - class LSPClientActionView : public QObject { Q_OBJECT @@ -238,10 +226,10 @@ class LSPClientActionView : public QObject QScopedPointer m_toolView; QPointer m_tabWidget; // applied search ranges - typedef QMultiHash RangeCollection; + typedef QMultiHash RangeCollection; RangeCollection m_ranges; // applied marks - typedef QSet DocumentCollection; + typedef QSet DocumentCollection; DocumentCollection m_marks; // modelis either owned by tree added to tabwidget or owned here QScopedPointer m_ownedModel; @@ -280,72 +268,101 @@ class LSPClientActionView : public QObject // characters to trigger format request QVector m_onTypeFormattingTriggers; - KActionCollection *actionCollection() const - { return m_client->actionCollection(); } + KActionCollection *actionCollection() const { return m_client->actionCollection(); } public: LSPClientActionView(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin, KXMLGUIClient *client, QSharedPointer serverManager) - : QObject(mainWin), m_plugin(plugin), m_mainWindow(mainWin), m_client(client), + : QObject(mainWin), + m_plugin(plugin), + m_mainWindow(mainWin), + m_client(client), m_serverManager(serverManager), m_completion(LSPClientCompletion::new_(m_serverManager)), m_hover(LSPClientHover::new_(m_serverManager)), m_symbolView(LSPClientSymbolView::new_(plugin, mainWin, m_serverManager)) { connect(m_mainWindow, &KTextEditor::MainWindow::viewChanged, this, &self_type::updateState); - connect(m_mainWindow, &KTextEditor::MainWindow::unhandledShortcutOverride, this, &self_type::handleEsc); - connect(m_serverManager.data(), &LSPClientServerManager::serverChanged, this, &self_type::updateState); + connect(m_mainWindow, &KTextEditor::MainWindow::unhandledShortcutOverride, this, + &self_type::handleEsc); + connect(m_serverManager.data(), &LSPClientServerManager::serverChanged, this, + &self_type::updateState); - m_findDef = actionCollection()->addAction(QStringLiteral("lspclient_find_definition"), this, &self_type::goToDefinition); + m_findDef = actionCollection()->addAction(QStringLiteral("lspclient_find_definition"), this, + &self_type::goToDefinition); m_findDef->setText(i18n("Go to Definition")); - m_findDecl = actionCollection()->addAction(QStringLiteral("lspclient_find_declaration"), this, &self_type::goToDeclaration); + m_findDecl = actionCollection()->addAction(QStringLiteral("lspclient_find_declaration"), + this, &self_type::goToDeclaration); m_findDecl->setText(i18n("Go to Declaration")); - m_findRef = actionCollection()->addAction(QStringLiteral("lspclient_find_references"), this, &self_type::findReferences); + m_findRef = actionCollection()->addAction(QStringLiteral("lspclient_find_references"), this, + &self_type::findReferences); m_findRef->setText(i18n("Find References")); - m_triggerHighlight = actionCollection()->addAction(QStringLiteral("lspclient_highlight"), this, &self_type::highlight); + m_triggerHighlight = actionCollection()->addAction(QStringLiteral("lspclient_highlight"), + this, &self_type::highlight); m_triggerHighlight->setText(i18n("Highlight")); // perhaps hover suggests to do so on mouse-over, // but let's just use a (convenient) action/shortcut for it - m_triggerHover = actionCollection()->addAction(QStringLiteral("lspclient_hover"), this, &self_type::hover); + m_triggerHover = actionCollection()->addAction(QStringLiteral("lspclient_hover"), this, + &self_type::hover); m_triggerHover->setText(i18n("Hover")); - m_triggerFormat = actionCollection()->addAction(QStringLiteral("lspclient_format"), this, &self_type::format); + m_triggerFormat = actionCollection()->addAction(QStringLiteral("lspclient_format"), this, + &self_type::format); m_triggerFormat->setText(i18n("Format")); - m_triggerRename = actionCollection()->addAction(QStringLiteral("lspclient_rename"), this, &self_type::rename); + m_triggerRename = actionCollection()->addAction(QStringLiteral("lspclient_rename"), this, + &self_type::rename); m_triggerRename->setText(i18n("Rename")); // general options - m_complDocOn = actionCollection()->addAction(QStringLiteral("lspclient_completion_doc"), this, &self_type::displayOptionChanged); + m_complDocOn = actionCollection()->addAction(QStringLiteral("lspclient_completion_doc"), + this, &self_type::displayOptionChanged); m_complDocOn->setText(i18n("Show selected completion documentation")); m_complDocOn->setCheckable(true); - m_refDeclaration = actionCollection()->addAction(QStringLiteral("lspclient_references_declaration"), this, &self_type::displayOptionChanged); + m_refDeclaration = + actionCollection()->addAction(QStringLiteral("lspclient_references_declaration"), + this, &self_type::displayOptionChanged); m_refDeclaration->setText(i18n("Include declaration in references")); m_refDeclaration->setCheckable(true); - m_onTypeFormatting = actionCollection()->addAction(QStringLiteral("lspclient_type_formatting"), this, &self_type::displayOptionChanged); + 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 = + 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); + m_diagnostics = actionCollection()->addAction(QStringLiteral("lspclient_diagnostics"), this, + &self_type::displayOptionChanged); m_diagnostics->setText(i18n("Show diagnostics notifications")); m_diagnostics->setCheckable(true); - m_diagnosticsHighlight = actionCollection()->addAction(QStringLiteral("lspclient_diagnostics_highlight"), this, &self_type::displayOptionChanged); + m_diagnosticsHighlight = + actionCollection()->addAction(QStringLiteral("lspclient_diagnostics_highlight"), + this, &self_type::displayOptionChanged); m_diagnosticsHighlight->setText(i18n("Show diagnostics highlights")); m_diagnosticsHighlight->setCheckable(true); - m_diagnosticsMark = actionCollection()->addAction(QStringLiteral("lspclient_diagnostics_mark"), this, &self_type::displayOptionChanged); + m_diagnosticsMark = + actionCollection()->addAction(QStringLiteral("lspclient_diagnostics_mark"), this, + &self_type::displayOptionChanged); m_diagnosticsMark->setText(i18n("Show diagnostics marks")); m_diagnosticsMark->setCheckable(true); - m_diagnosticsSwitch = actionCollection()->addAction(QStringLiteral("lspclient_diagnostic_switch"), this, &self_type::switchToDiagnostics); + m_diagnosticsSwitch = + actionCollection()->addAction(QStringLiteral("lspclient_diagnostic_switch"), this, + &self_type::switchToDiagnostics); m_diagnosticsSwitch->setText(i18n("Switch to diagnostics tab")); - m_diagnosticsCloseNon = actionCollection()->addAction(QStringLiteral("lspclient_diagnostic_close_non"), this, &self_type::closeNonDiagnostics); + m_diagnosticsCloseNon = + actionCollection()->addAction(QStringLiteral("lspclient_diagnostic_close_non"), + this, &self_type::closeNonDiagnostics); m_diagnosticsCloseNon->setText(i18n("Close all non-diagnostics tabs")); // server control - m_restartServer = actionCollection()->addAction(QStringLiteral("lspclient_restart_server"), this, &self_type::restartCurrent); + m_restartServer = actionCollection()->addAction(QStringLiteral("lspclient_restart_server"), + this, &self_type::restartCurrent); m_restartServer->setText(i18n("Restart LSP Server")); - m_restartAll = actionCollection()->addAction(QStringLiteral("lspclient_restart_all"), this, &self_type::restartAll); + m_restartAll = actionCollection()->addAction(QStringLiteral("lspclient_restart_all"), this, + &self_type::restartAll); m_restartAll->setText(i18n("Restart All LSP Servers")); // popup menu @@ -377,10 +394,10 @@ public: connect(m_plugin, &LSPClientPlugin::update, this, &self_type::configUpdated); // toolview - m_toolView.reset(mainWin->createToolView(plugin, QStringLiteral("kate_lspclient"), - KTextEditor::MainWindow::Bottom, - QIcon::fromTheme(QStringLiteral("application-x-ms-dos-executable")), - i18n("LSP Client"))); + m_toolView.reset(mainWin->createToolView( + plugin, QStringLiteral("kate_lspclient"), KTextEditor::MainWindow::Bottom, + QIcon::fromTheme(QStringLiteral("application-x-ms-dos-executable")), + i18n("LSP Client"))); m_tabWidget = new QTabWidget(m_toolView.data()); m_toolView->layout()->addWidget(m_tabWidget); m_tabWidget->setFocusPolicy(Qt::NoFocus); @@ -401,7 +418,8 @@ public: // track position in view to sync diagnostics list m_viewTracker.reset(LSPClientViewTracker::new_(plugin, mainWin, 0, 500)); - connect(m_viewTracker.data(), &LSPClientViewTracker::newState, this, &self_type::onViewState); + connect(m_viewTracker.data(), &LSPClientViewTracker::newState, this, + &self_type::onViewState); configUpdated(); updateState(); @@ -411,12 +429,14 @@ public: { // unregister all code-completion providers, else we might crash for (auto view : qAsConst(m_completionViews)) { - qobject_cast(view)->unregisterCompletionModel(m_completion.data()); + qobject_cast(view)->unregisterCompletionModel( + m_completion.data()); } // unregister all text-hint providers, else we might crash for (auto view : qAsConst(m_hoverViews)) { - qobject_cast(view)->unregisterTextHintProvider(m_hover.data()); + qobject_cast(view)->unregisterTextHintProvider( + m_hover.data()); } clearAllLocationMarks(); @@ -477,19 +497,16 @@ public: m_serverManager->restart(server.data()); } - void restartAll() - { - m_serverManager->restart(nullptr); - } + void restartAll() { m_serverManager->restart(nullptr); } - static - void clearMarks(KTextEditor::Document *doc, RangeCollection & ranges, DocumentCollection & docs, uint markType) + static void clearMarks(KTextEditor::Document *doc, RangeCollection &ranges, + DocumentCollection &docs, uint markType) { - KTextEditor::MarkInterface* iface = - docs.contains(doc) ? qobject_cast(doc) : nullptr; + KTextEditor::MarkInterface *iface = + docs.contains(doc) ? qobject_cast(doc) : nullptr; if (iface) { - const QHash marks = iface->marks(); - QHashIterator i(marks); + const QHash marks = iface->marks(); + QHashIterator i(marks); while (i.hasNext()) { i.next(); if (i.value()->type & markType) { @@ -505,8 +522,7 @@ public: } } - static - void clearMarks(RangeCollection & ranges, DocumentCollection & docs, uint markType) + static void clearMarks(RangeCollection &ranges, DocumentCollection &docs, uint markType) { while (!ranges.empty()) { clearMarks(ranges.begin().key(), ranges, docs, markType); @@ -532,13 +548,15 @@ public: clearMarks(m_diagnosticsRanges, m_diagnosticsMarks, RangeData::markTypeDiagAll); } - void addMarks(KTextEditor::Document *doc, QStandardItem *item, RangeCollection * ranges, DocumentCollection * docs) + void addMarks(KTextEditor::Document *doc, QStandardItem *item, RangeCollection *ranges, + DocumentCollection *docs) { Q_ASSERT(item); - KTextEditor::MovingInterface* miface = qobject_cast(doc); - KTextEditor::MarkInterface* iface = qobject_cast(doc); - KTextEditor::View* activeView = m_mainWindow->activeView(); - KTextEditor::ConfigInterface* ciface = qobject_cast(activeView); + KTextEditor::MovingInterface *miface = qobject_cast(doc); + KTextEditor::MarkInterface *iface = qobject_cast(doc); + KTextEditor::View *activeView = m_mainWindow->activeView(); + KTextEditor::ConfigInterface *ciface = + qobject_cast(activeView); if (!miface || !iface) return; @@ -549,20 +567,20 @@ public: KTextEditor::Range range = item->data(RangeData::RangeRole).value(); auto line = range.start().line(); - RangeData::KindEnum kind = (RangeData::KindEnum) item->data(RangeData::KindRole).toInt(); + RangeData::KindEnum kind = (RangeData::KindEnum)item->data(RangeData::KindRole).toInt(); KTextEditor::Attribute::Ptr attr(new KTextEditor::Attribute()); - bool enabled = m_diagnostics && m_diagnostics->isChecked() - && m_diagnosticsHighlight && m_diagnosticsHighlight->isChecked(); + bool enabled = m_diagnostics && m_diagnostics->isChecked() && m_diagnosticsHighlight + && m_diagnosticsHighlight->isChecked(); KTextEditor::MarkInterface::MarkTypes markType = RangeData::markType; switch (kind) { - case RangeData::KindEnum::Text: - { + case RangeData::KindEnum::Text: { // well, it's a bit like searching for something, so re-use that color QColor rangeColor = Qt::yellow; if (ciface) { - rangeColor = ciface->configValue(QStringLiteral("search-highlight-color")).value(); + rangeColor = ciface->configValue(QStringLiteral("search-highlight-color")) + .value(); } attr->setBackground(rangeColor); enabled = true; @@ -597,12 +615,13 @@ public: break; } if (activeView) { - attr->setForeground(activeView->defaultStyleAttribute(KTextEditor::dsNormal)->foreground().color()); + attr->setForeground( + activeView->defaultStyleAttribute(KTextEditor::dsNormal)->foreground().color()); } // highlight the range if (enabled && ranges) { - KTextEditor::MovingRange* mr = miface->newMovingRange(range); + KTextEditor::MovingRange *mr = miface->newMovingRange(range); mr->setAttribute(attr); mr->setZDepth(-90000.0); // Set the z-depth to slightly worse than the selection mr->setAttributeOnlyForViews(true); @@ -612,8 +631,8 @@ public: // add match mark for range const int ps = 32; bool handleClick = true; - enabled = m_diagnostics && m_diagnostics->isChecked() - && m_diagnosticsMark && m_diagnosticsMark->isChecked(); + enabled = m_diagnostics && m_diagnostics->isChecked() && m_diagnosticsMark + && m_diagnosticsMark->isChecked(); switch (markType) { case RangeData::markType: iface->setMarkDescription(markType, i18n("RangeHighLight")); @@ -623,15 +642,18 @@ public: break; case RangeData::markTypeDiagError: iface->setMarkDescription(markType, i18n("Error")); - iface->setMarkPixmap(markType, diagnosticsIcon(LSPDiagnosticSeverity::Error).pixmap(ps, ps)); + iface->setMarkPixmap(markType, + diagnosticsIcon(LSPDiagnosticSeverity::Error).pixmap(ps, ps)); break; case RangeData::markTypeDiagWarning: iface->setMarkDescription(markType, i18n("Warning")); - iface->setMarkPixmap(markType, diagnosticsIcon(LSPDiagnosticSeverity::Warning).pixmap(ps, ps)); + iface->setMarkPixmap(markType, + diagnosticsIcon(LSPDiagnosticSeverity::Warning).pixmap(ps, ps)); break; case RangeData::markTypeDiagOther: iface->setMarkDescription(markType, i18n("Information")); - iface->setMarkPixmap(markType, diagnosticsIcon(LSPDiagnosticSeverity::Information).pixmap(ps, ps)); + iface->setMarkPixmap( + markType, diagnosticsIcon(LSPDiagnosticSeverity::Information).pixmap(ps, ps)); break; default: Q_ASSERT(false); @@ -643,18 +665,20 @@ public: } // ensure runtime match - connect(doc, SIGNAL(aboutToInvalidateMovingInterfaceContent(KTextEditor::Document*)), - this, SLOT(clearAllMarks(KTextEditor::Document*)), Qt::UniqueConnection); - connect(doc, SIGNAL(aboutToDeleteMovingInterfaceContent(KTextEditor::Document*)), - this, SLOT(clearAllMarks(KTextEditor::Document*)), Qt::UniqueConnection); + connect(doc, SIGNAL(aboutToInvalidateMovingInterfaceContent(KTextEditor::Document *)), this, + SLOT(clearAllMarks(KTextEditor::Document *)), Qt::UniqueConnection); + connect(doc, SIGNAL(aboutToDeleteMovingInterfaceContent(KTextEditor::Document *)), this, + SLOT(clearAllMarks(KTextEditor::Document *)), Qt::UniqueConnection); if (handleClick) { - connect(doc, SIGNAL(markClicked(KTextEditor::Document*, KTextEditor::Mark, bool&)), - this, SLOT(onMarkClicked(KTextEditor::Document*,KTextEditor::Mark, bool&)), Qt::UniqueConnection); + connect(doc, SIGNAL(markClicked(KTextEditor::Document *, KTextEditor::Mark, bool &)), + this, SLOT(onMarkClicked(KTextEditor::Document *, KTextEditor::Mark, bool &)), + Qt::UniqueConnection); } } - void addMarksRec(KTextEditor::Document *doc, QStandardItem *item, RangeCollection * ranges, DocumentCollection * docs) + void addMarksRec(KTextEditor::Document *doc, QStandardItem *item, RangeCollection *ranges, + DocumentCollection *docs) { Q_ASSERT(item); addMarks(doc, item, ranges, docs); @@ -663,7 +687,8 @@ public: } } - void addMarks(KTextEditor::Document *doc, QStandardItemModel *treeModel, RangeCollection & ranges, DocumentCollection & docs) + void addMarks(KTextEditor::Document *doc, QStandardItemModel *treeModel, + RangeCollection &ranges, DocumentCollection &docs) { // check if already added auto oranges = ranges.contains(doc) ? nullptr : &ranges; @@ -676,7 +701,7 @@ public: addMarksRec(doc, treeModel->invisibleRootItem(), oranges, odocs); } - void goToDocumentLocation(const QUrl & uri, int line, int column) + void goToDocumentLocation(const QUrl &uri, int line, int column) { KTextEditor::View *activeView = m_mainWindow->activeView(); if (!activeView || uri.isEmpty() || line < 0 || column < 0) @@ -695,7 +720,7 @@ public: } } - void goToItemLocation(const QModelIndex & index) + void goToItemLocation(const QModelIndex &index) { auto url = index.data(RangeData::FileUrlRole).toUrl(); auto start = index.data(RangeData::RangeRole).value().start(); @@ -704,41 +729,38 @@ public: // custom item subclass that captures additional attributes; // a bit more convenient than the variant/role way - struct DiagnosticItem : public QStandardItem - { + struct DiagnosticItem : public QStandardItem { LSPDiagnostic m_diagnostic; LSPCodeAction m_codeAction; QSharedPointer m_snapshot; - DiagnosticItem(const LSPDiagnostic & d) : - m_diagnostic(d) - {} + DiagnosticItem(const LSPDiagnostic &d) : m_diagnostic(d) {} - DiagnosticItem(const LSPCodeAction & c, QSharedPointer s) : - m_codeAction(c), m_snapshot(s) - { m_diagnostic.range = LSPRange::invalid(); } + DiagnosticItem(const LSPCodeAction &c, QSharedPointer s) + : m_codeAction(c), m_snapshot(s) + { + m_diagnostic.range = LSPRange::invalid(); + } - bool isCodeAction() - { return !m_diagnostic.range.isValid() && m_codeAction.title.size(); } + bool isCodeAction() { return !m_diagnostic.range.isValid() && m_codeAction.title.size(); } }; - // double click on: // diagnostic item -> request and add actions (below item) // code action -> perform action (literal edit and/or execute command) // (execution of command may lead to an applyEdit request from server) - void triggerCodeAction(const QModelIndex & index) + void triggerCodeAction(const QModelIndex &index) { KTextEditor::View *activeView = m_mainWindow->activeView(); QPointer document = activeView->document(); auto server = m_serverManager->findServer(activeView); - auto it = dynamic_cast(m_diagnosticsModel->itemFromIndex(index)); + auto it = dynamic_cast(m_diagnosticsModel->itemFromIndex(index)); if (!server || !document || !it) return; // click on an action ? if (it->isCodeAction()) { - auto& action = it->m_codeAction; + auto &action = it->m_codeAction; // apply edit before command applyWorkspaceEdit(action.edit, it->m_snapshot.data()); const auto &command = action.command; @@ -764,21 +786,21 @@ public: // store some things to find item safely later on QPersistentModelIndex pindex(index); - QSharedPointer snapshot(m_serverManager->snapshot(server.data())); - auto h = [this, url, snapshot, pindex] (const QList actions) - { + QSharedPointer snapshot( + m_serverManager->snapshot(server.data())); + auto h = [this, url, snapshot, pindex](const QList actions) { if (!pindex.isValid()) return; auto child = m_diagnosticsModel->itemFromIndex(pindex); if (!child) return; // add actions below diagnostic item - for (const auto &action: actions) { + for (const auto &action : actions) { auto item = new DiagnosticItem(action, snapshot); child->appendRow(item); - auto text = action.kind.size() ? - QStringLiteral("[%1] %2").arg(action.kind).arg(action.title) : - action.title; + auto text = action.kind.size() + ? QStringLiteral("[%1] %2").arg(action.kind).arg(action.title) + : action.title; item->setData(text, Qt::DisplayRole); item->setData(codeActionIcon(), Qt::DecorationRole); } @@ -791,7 +813,7 @@ public: if (!range.isValid()) { range = document->documentRange(); } - server->documentCodeAction(url, range, {}, {it->m_diagnostic}, this, h); + server->documentCodeAction(url, range, {}, { it->m_diagnostic }, this, h); } void tabCloseRequested(int index) @@ -813,7 +835,7 @@ public: void closeNonDiagnostics() { - for (int i = 0; i < m_tabWidget->count(); ) { + for (int i = 0; i < m_tabWidget->count();) { if (m_tabWidget->widget(i) != m_diagnosticsTree) { tabCloseRequested(i); } else { @@ -823,28 +845,25 @@ public: } // local helper to overcome some differences in LSP types - struct RangeItem - { + struct RangeItem { QUrl uri; LSPRange range; LSPDocumentHighlightKind kind; }; - static - bool compareRangeItem(const RangeItem & a, const RangeItem & b) - { return (a.uri < b.uri) || ((a.uri == b.uri) && a.range < b.range); } + static bool compareRangeItem(const RangeItem &a, const RangeItem &b) + { + return (a.uri < b.uri) || ((a.uri == b.uri) && a.range < b.range); + } // provide Qt::DisplayRole (text) line lazily; // only find line's text content when so requested // This may then involve opening reading some file, at which time // all items for that file will be resolved in one go. - struct LineItem : public QStandardItem - { + struct LineItem : public QStandardItem { KTextEditor::MainWindow *m_mainWindow; - LineItem(KTextEditor::MainWindow *mainWindow) : - m_mainWindow(mainWindow) - {} + LineItem(KTextEditor::MainWindow *mainWindow) : m_mainWindow(mainWindow) {} QVariant data(int role = Qt::UserRole + 1) const override { @@ -881,10 +900,10 @@ public: // should work ok return data(role); } - }; - LSPRange transformRange(const QUrl & url, const LSPClientRevisionSnapshot & snapshot, const LSPRange & range) + LSPRange transformRange(const QUrl &url, const LSPClientRevisionSnapshot &snapshot, + const LSPRange &range) { KTextEditor::MovingInterface *miface; qint64 revision; @@ -898,18 +917,19 @@ public: return result; } - void fillItemRoles(QStandardItem * item, const QUrl & url, const LSPRange _range, - RangeData::KindEnum kind, const LSPClientRevisionSnapshot * snapshot = nullptr) + void fillItemRoles(QStandardItem *item, const QUrl &url, const LSPRange _range, + RangeData::KindEnum kind, + const LSPClientRevisionSnapshot *snapshot = nullptr) { auto range = snapshot ? transformRange(url, *snapshot, _range) : _range; item->setData(QVariant(url), RangeData::FileUrlRole); QVariant vrange; vrange.setValue(range); item->setData(vrange, RangeData::RangeRole); - item->setData((int) kind, RangeData::KindRole); + item->setData((int)kind, RangeData::KindRole); } - void makeTree(const QVector & locations, const LSPClientRevisionSnapshot * snapshot) + void makeTree(const QVector &locations, const LSPClientRevisionSnapshot *snapshot) { // group by url, assuming input is suitably sorted that way auto treeModel = new QStandardItemModel(); @@ -917,10 +937,11 @@ public: QUrl lastUrl; QStandardItem *parent = nullptr; - for (const auto & loc: locations) { + for (const auto &loc : locations) { if (loc.uri != lastUrl) { if (parent) { - parent->setText(QStringLiteral("%1: %2").arg(lastUrl.path()).arg(parent->rowCount())); + parent->setText( + QStringLiteral("%1: %2").arg(lastUrl.path()).arg(parent->rowCount())); } lastUrl = loc.uri; parent = new QStandardItem(); @@ -944,7 +965,7 @@ public: m_markModel = treeModel; } - void showTree(const QString & title, QPointer *targetTree) + void showTree(const QString &title, QPointer *targetTree) { // clean up previous target if any if (targetTree && *targetTree) { @@ -977,10 +998,11 @@ public: m_mainWindow->showToolView(m_toolView.data()); } - void showMessage(const QString & text, KTextEditor::Message::MessageType level) + void showMessage(const QString &text, KTextEditor::Message::MessageType level) { KTextEditor::View *view = m_mainWindow->activeView(); - if (!view || !view->document()) return; + if (!view || !view->document()) + return; auto kmsg = new KTextEditor::Message(text, level); kmsg->setPosition(KTextEditor::Message::BottomInView); @@ -991,7 +1013,8 @@ public: void handleEsc(QEvent *e) { - if (!m_mainWindow) return; + if (!m_mainWindow) + return; QKeyEvent *k = static_cast(e); if (k->key() == Qt::Key_Escape && k->modifiers() == Qt::NoModifier) { @@ -1004,13 +1027,14 @@ public: } template - using LocationRequest = std::function; + using LocationRequest = + std::function; template - void positionRequest(const LocationRequest & req, const Handler & h, - QScopedPointer * snapshot = nullptr) + void positionRequest(const LocationRequest &req, const Handler &h, + QScopedPointer *snapshot = nullptr) { KTextEditor::View *activeView = m_mainWindow->activeView(); auto server = m_serverManager->findServer(activeView); @@ -1028,7 +1052,7 @@ public: m_req_timeout = false; QTimer::singleShot(1000, this, [this] { m_req_timeout = true; }); m_handle.cancel() = req(*server, activeView->document()->url(), - {cursor.line(), cursor.column()}, this, h); + { cursor.line(), cursor.column() }, this, h); } QString currentWord() @@ -1043,24 +1067,27 @@ public: } // some template and function type trickery here, but at least that buck stops here then ... - template>> - void processLocations(const QString & title, - const typename utils::identity>::type & req, bool onlyshow, - const std::function & itemConverter, - QPointer *targetTree = nullptr) + template>> + void processLocations(const QString &title, + const typename utils::identity>::type &req, + bool onlyshow, + const std::function &itemConverter, + QPointer *targetTree = nullptr) { // no capture for move only using initializers available (yet), so shared outer type // the additional level of indirection is so it can be 'filled-in' after lambda creation - QSharedPointer> s(new QScopedPointer); - auto h = [this, title, onlyshow, itemConverter, targetTree, s] (const QList & defs) - { + QSharedPointer> s( + new QScopedPointer); + auto h = [this, title, onlyshow, itemConverter, targetTree, + s](const QList &defs) { if (defs.count() == 0) { showMessage(i18n("No results"), KTextEditor::Message::Information); } else { // convert to helper type QVector ranges; ranges.reserve(defs.size()); - for (const auto & def: defs) { + for (const auto &def : defs) { ranges.push_back(itemConverter(def)); } // ... so we can sort it also @@ -1087,31 +1114,33 @@ public: positionRequest(req, h, s.data()); } - static RangeItem - locationToRangeItem(const LSPLocation & loc) - { return {loc.uri, loc.range, LSPDocumentHighlightKind::Text}; } + static RangeItem locationToRangeItem(const LSPLocation &loc) + { + return { loc.uri, loc.range, LSPDocumentHighlightKind::Text }; + } void goToDefinition() { auto title = i18nc("@title:tab", "Definition: %1", currentWord()); - processLocations(title, &LSPClientServer::documentDefinition, - false, &self_type::locationToRangeItem, &m_defTree); + processLocations(title, &LSPClientServer::documentDefinition, false, + &self_type::locationToRangeItem, &m_defTree); } void goToDeclaration() { auto title = i18nc("@title:tab", "Declaration: %1", currentWord()); - processLocations(title, &LSPClientServer::documentDeclaration, - false, &self_type::locationToRangeItem, &m_declTree); + processLocations(title, &LSPClientServer::documentDeclaration, false, + &self_type::locationToRangeItem, &m_declTree); } void findReferences() { auto title = i18nc("@title:tab", "References: %1", currentWord()); bool decl = m_refDeclaration->isChecked(); - auto req = [decl] (LSPClientServer & server, const QUrl & document, const LSPPosition & pos, - const QObject *context, const DocumentDefinitionReplyHandler & h) - { return server.documentReferences(document, pos, decl, context, h); }; + auto req = [decl](LSPClientServer &server, const QUrl &document, const LSPPosition &pos, + const QObject *context, const DocumentDefinitionReplyHandler &h) { + return server.documentReferences(document, pos, decl, context, h); + }; processLocations(title, req, true, &self_type::locationToRangeItem); } @@ -1120,16 +1149,18 @@ public: { // determine current url to capture and use later on QUrl url; - const KTextEditor::View* viewForRequest(m_mainWindow->activeView()); + const KTextEditor::View *viewForRequest(m_mainWindow->activeView()); if (viewForRequest && viewForRequest->document()) { url = viewForRequest->document()->url(); } auto title = i18nc("@title:tab", "Highlight: %1", currentWord()); - auto converter = [url] (const LSPDocumentHighlight & hl) - { return RangeItem {url, hl.range, hl.kind}; }; + auto converter = [url](const LSPDocumentHighlight &hl) { + return RangeItem { url, hl.range, hl.kind }; + }; - processLocations(title, &LSPClientServer::documentHighlight, true, converter); + processLocations(title, &LSPClientServer::documentHighlight, + true, converter); } void hover() @@ -1140,10 +1171,10 @@ public: } } - void applyEdits(KTextEditor::Document * doc, const LSPClientRevisionSnapshot * snapshot, - const QList & edits) + void applyEdits(KTextEditor::Document *doc, const LSPClientRevisionSnapshot *snapshot, + const QList &edits) { - KTextEditor::MovingInterface* miface = qobject_cast(doc); + KTextEditor::MovingInterface *miface = qobject_cast(doc); if (!miface) return; @@ -1156,8 +1187,8 @@ public: // all coordinates in edits are wrt original document, // so create moving ranges that will adjust to preceding edits as they are applied - QVector ranges; - for (const auto &edit: edits) { + QVector ranges; + for (const auto &edit : edits) { auto range = snapshot ? transformRange(doc->url(), *snapshot, edit.range) : edit.range; KTextEditor::MovingRange *mr = miface->newMovingRange(range); ranges.append(mr); @@ -1174,7 +1205,7 @@ public: qDeleteAll(ranges); } - void applyWorkspaceEdit(const LSPWorkspaceEdit & edit, const LSPClientRevisionSnapshot * snapshot) + void applyWorkspaceEdit(const LSPWorkspaceEdit &edit, const LSPClientRevisionSnapshot *snapshot) { auto currentView = m_mainWindow->activeView(); for (auto it = edit.changes.begin(); it != edit.changes.end(); ++it) { @@ -1192,7 +1223,8 @@ public: } } - void onApplyEdit(const LSPApplyWorkspaceEditParams & edit, const ApplyEditReplyHandler & h, bool &handled) + void onApplyEdit(const LSPApplyWorkspaceEditParams &edit, const ApplyEditReplyHandler &h, + bool &handled) { if (handled) return; @@ -1204,20 +1236,20 @@ public: } else { qCInfo(LSPCLIENT) << "ignoring edit"; } - h({m_accept_edit, QString()}); + h({ m_accept_edit, QString() }); } template - void checkEditResult(const Collection & c) + void checkEditResult(const Collection &c) { if (c.size() == 0) { showMessage(i18n("No edits"), KTextEditor::Message::Information); } } - void delayCancelRequest(LSPClientServer::RequestHandle && h, int timeout_ms = 4000) + void delayCancelRequest(LSPClientServer::RequestHandle &&h, int timeout_ms = 4000) { - QTimer::singleShot(timeout_ms, this, [h] () mutable { h.cancel(); }); + QTimer::singleShot(timeout_ms, this, [h]() mutable { h.cancel(); }); } void format(QChar lastChar = QChar()) @@ -1230,7 +1262,7 @@ public: int tabSize = 4; bool insertSpaces = true; - auto cfgiface = qobject_cast(document); + auto cfgiface = qobject_cast(document); if (cfgiface) { tabSize = cfgiface->configValue(QStringLiteral("tab-width")).toInt(); insertSpaces = cfgiface->configValue(QStringLiteral("replace-tabs")).toBool(); @@ -1238,9 +1270,9 @@ public: // sigh, no move initialization capture ... // (again) assuming reply ranges wrt revisions submitted at this time - QSharedPointer snapshot(m_serverManager->snapshot(server.data())); - auto h = [this, document, snapshot, lastChar] (const QList & edits) - { + QSharedPointer snapshot( + m_serverManager->snapshot(server.data())); + auto h = [this, document, snapshot, lastChar](const QList &edits) { if (lastChar.isNull()) { checkEditResult(edits); } @@ -1249,15 +1281,14 @@ public: } }; - auto options = LSPFormattingOptions {tabSize, insertSpaces, QJsonObject()}; - auto handle = !lastChar.isNull() ? - server->documentOnTypeFormatting(document->url(), activeView->cursorPosition(), - lastChar, options, this, h) : - (activeView->selection() ? - server->documentRangeFormatting(document->url(), activeView->selectionRange(), - options, this, h) : - server->documentFormatting(document->url(), - options, this, h)); + auto options = LSPFormattingOptions { tabSize, insertSpaces, QJsonObject() }; + auto handle = !lastChar.isNull() + ? server->documentOnTypeFormatting(document->url(), activeView->cursorPosition(), + lastChar, options, this, h) + : (activeView->selection() + ? server->documentRangeFormatting( + document->url(), activeView->selectionRange(), options, this, h) + : server->documentFormatting(document->url(), options, this, h)); delayCancelRequest(std::move(handle)); } @@ -1273,27 +1304,26 @@ public: // results are typically (too) limited // due to server implementation or limited view/scope // so let's add a disclaimer that it's not our fault - QString newName = QInputDialog::getText(activeView, - i18nc("@title:window", "Rename"), - i18nc("@label:textbox", "New name (caution: not all references may be replaced)"), - QLineEdit::Normal, QString(), &ok); + QString newName = QInputDialog::getText( + activeView, i18nc("@title:window", "Rename"), + i18nc("@label:textbox", "New name (caution: not all references may be replaced)"), + QLineEdit::Normal, QString(), &ok); if (!ok) { return; } - QSharedPointer snapshot(m_serverManager->snapshot(server.data())); - auto h = [this, snapshot] (const LSPWorkspaceEdit & edit) - { + QSharedPointer snapshot( + m_serverManager->snapshot(server.data())); + auto h = [this, snapshot](const LSPWorkspaceEdit &edit) { checkEditResult(edit.changes); applyWorkspaceEdit(edit, snapshot.data()); }; - auto handle = server->documentRename(document->url(), - activeView->cursorPosition(), newName, this, h); + auto handle = server->documentRename(document->url(), activeView->cursorPosition(), newName, + this, h); delayCancelRequest(std::move(handle)); } - static QStandardItem* - getItem(const QStandardItemModel &model, const QUrl & url) + static QStandardItem *getItem(const QStandardItemModel &model, const QUrl &url) { auto l = model.findItems(url.path()); if (l.length()) { @@ -1350,7 +1380,7 @@ public: // select top item on view change, // but otherwise leave selection unchanged if no match - switch(newState) { + switch (newState) { case LSPClientViewTracker::ViewChanged: syncDiagnostics(view->document(), view->cursorPosition().line(), true, false); break; @@ -1363,15 +1393,17 @@ public: } } - Q_SLOT void onMarkClicked(KTextEditor::Document *document, KTextEditor::Mark mark, bool &handled) + Q_SLOT void onMarkClicked(KTextEditor::Document *document, KTextEditor::Mark mark, + bool &handled) { // no action if no mark was sprinkled here - if (m_diagnosticsMarks.contains(document) && syncDiagnostics(document, mark.line, false, true)) { + if (m_diagnosticsMarks.contains(document) + && syncDiagnostics(document, mark.line, false, true)) { handled = true; } } - void onDiagnostics(const LSPPublishDiagnosticsParams & diagnostics) + void onDiagnostics(const LSPPublishDiagnosticsParams &diagnostics) { if (!m_diagnosticsTree) return; @@ -1391,7 +1423,7 @@ public: topItem->setRowCount(0); } - for (const auto & diag : diagnostics.diagnostics) { + for (const auto &diag : diagnostics.diagnostics) { auto item = new DiagnosticItem(diag); topItem->appendRow(item); QString source; @@ -1405,11 +1437,13 @@ public: if (!related.location.uri.isEmpty()) { auto relatedItemMessage = new QStandardItem(); relatedItemMessage->setText(related.message); - fillItemRoles(relatedItemMessage, related.location.uri, related.location.range, RangeData::KindEnum::Related); + fillItemRoles(relatedItemMessage, related.location.uri, related.location.range, + RangeData::KindEnum::Related); auto relatedItemPath = new QStandardItem(); auto basename = QFileInfo(related.location.uri.path()).fileName(); - relatedItemPath->setText(QStringLiteral("%1:%2").arg(basename).arg(related.location.range.start().line())); - item->appendRow({relatedItemMessage, relatedItemPath}); + relatedItemPath->setText(QStringLiteral("%1:%2").arg(basename).arg( + related.location.range.start().line())); + item->appendRow({ relatedItemMessage, relatedItemPath }); m_diagnosticsTree->setExpanded(item->index(), true); } } @@ -1439,7 +1473,7 @@ public: // but in either case (url change or close); remove lingering diagnostics // collect active urls QSet fpaths; - for (const auto &view: m_mainWindow->views()) { + for (const auto &view : m_mainWindow->views()) { if (auto doc = view->document()) { fpaths.insert(doc->url().path()); } @@ -1469,8 +1503,9 @@ public: // NOTE the intendation mode should probably be set to None, // so as not to experience unpleasant interference auto cursor = activeView->cursorPosition(); - QChar lastChar = cursor.column() == 0 ? QChar::fromLatin1('\n') : - doc->characterAt({cursor.line(), cursor.column() - 1}); + QChar lastChar = cursor.column() == 0 + ? QChar::fromLatin1('\n') + : doc->characterAt({ cursor.line(), cursor.column() - 1 }); if (m_onTypeFormattingTriggers.contains(lastChar)) { format(lastChar); } @@ -1487,7 +1522,7 @@ public: bool renameEnabled = false; if (server) { - const auto& caps = server->capabilities(); + const auto &caps = server->capabilities(); defEnabled = caps.definitionProvider; // FIXME no real official protocol way to detect, so enable anyway declEnabled = caps.declarationProvider || true; @@ -1497,24 +1532,24 @@ public: formatEnabled = caps.documentFormattingProvider || caps.documentRangeFormattingProvider; renameEnabled = caps.renameProvider; - connect(server.data(), &LSPClientServer::publishDiagnostics, - this, &self_type::onDiagnostics, Qt::UniqueConnection); - connect(server.data(), &LSPClientServer::applyEdit, - this, &self_type::onApplyEdit, Qt::UniqueConnection); + connect(server.data(), &LSPClientServer::publishDiagnostics, this, + &self_type::onDiagnostics, Qt::UniqueConnection); + connect(server.data(), &LSPClientServer::applyEdit, this, &self_type::onApplyEdit, + Qt::UniqueConnection); // update format trigger characters - const auto & fmt = caps.documentOnTypeFormattingProvider; + const auto &fmt = caps.documentOnTypeFormattingProvider; if (fmt.provider && m_onTypeFormatting->isChecked()) { - m_onTypeFormattingTriggers = fmt.triggerCharacters; + m_onTypeFormattingTriggers = fmt.triggerCharacters; } else { m_onTypeFormattingTriggers.clear(); } // and monitor for such if (doc) { - connect(doc, &KTextEditor::Document::textChanged, - this, &self_type::onTextChanged, Qt::UniqueConnection); - connect(doc, &KTextEditor::Document::documentUrlChanged, - this, &self_type::onDocumentUrlChanged, Qt::UniqueConnection); + connect(doc, &KTextEditor::Document::textChanged, this, &self_type::onTextChanged, + Qt::UniqueConnection); + connect(doc, &KTextEditor::Document::documentUrlChanged, this, + &self_type::onDocumentUrlChanged, Qt::UniqueConnection); } } @@ -1557,9 +1592,8 @@ public: // connect for cleanup stuff if (activeView) - connect(activeView, &KTextEditor::View::destroyed, this, - &self_type::viewDestroyed, - Qt::UniqueConnection); + connect(activeView, &KTextEditor::View::destroyed, this, &self_type::viewDestroyed, + Qt::UniqueConnection); } void viewDestroyed(QObject *view) @@ -1568,11 +1602,12 @@ public: m_hoverViews.remove(static_cast(view)); } - void updateCompletion(KTextEditor::View *view, LSPClientServer * server) + void updateCompletion(KTextEditor::View *view, LSPClientServer *server) { bool registered = m_completionViews.contains(view); - KTextEditor::CodeCompletionInterface *cci = qobject_cast(view); + KTextEditor::CodeCompletionInterface *cci = + qobject_cast(view); if (!cci) { return; @@ -1591,7 +1626,7 @@ public: } } - void updateHover(KTextEditor::View *view, LSPClientServer * server) + void updateHover(KTextEditor::View *view, LSPClientServer *server) { bool registered = m_hoverViews.contains(view); @@ -1615,7 +1650,6 @@ public: } }; - class LSPClientPluginViewImpl : public QObject, public KXMLGUIClient { Q_OBJECT @@ -1628,7 +1662,8 @@ class LSPClientPluginViewImpl : public QObject, public KXMLGUIClient public: LSPClientPluginViewImpl(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin) - : QObject(mainWin), m_mainWindow(mainWin), + : QObject(mainWin), + m_mainWindow(mainWin), m_serverManager(LSPClientServerManager::new_(plugin, mainWin)), m_actionView(new LSPClientActionView(plugin, mainWin, this, m_serverManager)) { @@ -1650,9 +1685,7 @@ public: } }; - -QObject* -LSPClientPluginView::new_(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin) +QObject *LSPClientPluginView::new_(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin) { return new LSPClientPluginViewImpl(plugin, mainWin); } diff --git a/addons/lspclient/lspclientpluginview.h b/addons/lspclient/lspclientpluginview.h index 47255a3ac..c9832a76f 100644 --- a/addons/lspclient/lspclientpluginview.h +++ b/addons/lspclient/lspclientpluginview.h @@ -30,16 +30,14 @@ class LSPClientPlugin; namespace KTextEditor { - class MainWindow; +class MainWindow; } class LSPClientPluginView { public: // only needs a factory; no other public interface - static QObject* - new_(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin); + static QObject *new_(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin); }; #endif - diff --git a/addons/lspclient/lspclientprotocol.h b/addons/lspclient/lspclientprotocol.h index 9730fdcfa..b779c9de0 100644 --- a/addons/lspclient/lspclientprotocol.h +++ b/addons/lspclient/lspclientprotocol.h @@ -41,8 +41,7 @@ // Moreover, to avoid introducing a custom 'optional' type, absence of an optional // part/member is usually signalled by some 'invalid' marker (empty, negative). -enum class LSPErrorCode -{ +enum class LSPErrorCode { // Defined by JSON RPC ParseError = -32700, InvalidRequest = -32600, @@ -59,31 +58,24 @@ enum class LSPErrorCode ContentModified = -32801 }; -enum class LSPDocumentSyncKind -{ - None = 0, - Full = 1, - Incremental = 2 -}; +enum class LSPDocumentSyncKind { None = 0, Full = 1, Incremental = 2 }; -struct LSPCompletionOptions -{ +struct LSPCompletionOptions { bool provider = false; bool resolveProvider = false; QVector triggerCharacters; }; -struct LSPSignatureHelpOptions -{ +struct LSPSignatureHelpOptions { bool provider = false; QVector triggerCharacters; }; // ensure distinct type -struct LSPDocumentOnTypeFormattingOptions : public LSPSignatureHelpOptions {}; +struct LSPDocumentOnTypeFormattingOptions : public LSPSignatureHelpOptions { +}; -struct LSPServerCapabilities -{ +struct LSPServerCapabilities { LSPDocumentSyncKind textDocumentSync = LSPDocumentSyncKind::None; bool hoverProvider = false; LSPCompletionOptions completionProvider; @@ -102,15 +94,9 @@ struct LSPServerCapabilities bool codeActionProvider = false; }; -enum class LSPMarkupKind -{ - None = 0, - PlainText = 1, - MarkDown = 2 -}; +enum class LSPMarkupKind { None = 0, PlainText = 1, MarkDown = 2 }; -struct LSPMarkupContent -{ +struct LSPMarkupContent { LSPMarkupKind kind = LSPMarkupKind::None; QString value; }; @@ -129,34 +115,26 @@ using LSPPosition = KTextEditor::Cursor; */ using LSPRange = KTextEditor::Range; -struct LSPLocation -{ +struct LSPLocation { QUrl uri; LSPRange range; }; -struct LSPTextDocumentContentChangeEvent -{ +struct LSPTextDocumentContentChangeEvent { LSPRange range; QString text; }; -enum class LSPDocumentHighlightKind -{ - Text = 1, - Read = 2, - Write = 3 -}; +enum class LSPDocumentHighlightKind { Text = 1, Read = 2, Write = 3 }; -struct LSPDocumentHighlight -{ +struct LSPDocumentHighlight { LSPRange range; LSPDocumentHighlightKind kind; }; -struct LSPHover -{ - // vector for contents to support all three variants: MarkedString | MarkedString[] | MarkupContent +struct LSPHover { + // vector for contents to support all three variants: + // MarkedString | MarkedString[] | MarkupContent // vector variant is still in use e.g. by Rust rls QVector contents; LSPRange range; @@ -183,12 +161,12 @@ enum class LSPSymbolKind { Array = 18, }; -struct LSPSymbolInformation -{ - LSPSymbolInformation(const QString & _name, LSPSymbolKind _kind, - LSPRange _range, const QString & _detail) +struct LSPSymbolInformation { + LSPSymbolInformation(const QString &_name, LSPSymbolKind _kind, LSPRange _range, + const QString &_detail) : name(_name), detail(_detail), kind(_kind), range(_range) - {} + { + } QString name; QString detail; LSPSymbolKind kind; @@ -196,8 +174,7 @@ struct LSPSymbolInformation QList children; }; -enum class LSPCompletionItemKind -{ +enum class LSPCompletionItemKind { Text = 1, Method = 2, Function = 3, @@ -225,8 +202,7 @@ enum class LSPCompletionItemKind TypeParameter = 25, }; -struct LSPCompletionItem -{ +struct LSPCompletionItem { QString label; LSPCompletionItemKind kind; QString detail; @@ -235,44 +211,38 @@ struct LSPCompletionItem QString insertText; }; -struct LSPParameterInformation -{ +struct LSPParameterInformation { // offsets into overall signature label // (-1 if invalid) int start; int end; }; -struct LSPSignatureInformation -{ +struct LSPSignatureInformation { QString label; LSPMarkupContent documentation; QList parameters; }; -struct LSPSignatureHelp -{ +struct LSPSignatureHelp { QList signatures; int activeSignature; int activeParameter; }; -struct LSPFormattingOptions -{ +struct LSPFormattingOptions { int tabSize; bool insertSpaces; // additional fields QJsonObject extra; }; -struct LSPTextEdit -{ +struct LSPTextEdit { LSPRange range; QString newText; }; -enum class LSPDiagnosticSeverity -{ +enum class LSPDiagnosticSeverity { Unknown = 0, Error = 1, Warning = 2, @@ -280,15 +250,13 @@ enum class LSPDiagnosticSeverity Hint = 4, }; -struct LSPDiagnosticRelatedInformation -{ +struct LSPDiagnosticRelatedInformation { // empty url / invalid range when absent LSPLocation location; QString message; }; -struct LSPDiagnostic -{ +struct LSPDiagnostic { LSPRange range; LSPDiagnosticSeverity severity; QString code; @@ -297,28 +265,24 @@ struct LSPDiagnostic LSPDiagnosticRelatedInformation relatedInformation; }; -struct LSPPublishDiagnosticsParams -{ +struct LSPPublishDiagnosticsParams { QUrl uri; QList diagnostics; }; -struct LSPCommand -{ +struct LSPCommand { QString title; QString command; // pretty opaque QJsonArray arguments; }; -struct LSPWorkspaceEdit -{ +struct LSPWorkspaceEdit { // supported part for now QHash> changes; }; -struct LSPCodeAction -{ +struct LSPCodeAction { QString title; QString kind; QList diagnostics; @@ -326,14 +290,12 @@ struct LSPCodeAction LSPCommand command; }; -struct LSPApplyWorkspaceEditParams -{ +struct LSPApplyWorkspaceEditParams { QString label; LSPWorkspaceEdit edit; }; -struct LSPApplyWorkspaceEditResponse -{ +struct LSPApplyWorkspaceEditResponse { bool applied; QString failureReason; }; diff --git a/addons/lspclient/lspclientserver.cpp b/addons/lspclient/lspclientserver.cpp index 61fd35c12..237ed749d 100644 --- a/addons/lspclient/lspclientserver.cpp +++ b/addons/lspclient/lspclientserver.cpp @@ -38,7 +38,7 @@ #include // good/bad old school; allows easier concatenate -#define CONTENT_LENGTH "Content-Length" +#define CONTENT_LENGTH "Content-Length" static const QString MEMBER_ID = QStringLiteral("id"); static const QString MEMBER_METHOD = QStringLiteral("method"); @@ -69,51 +69,37 @@ static const QString MEMBER_ARGUMENTS = QStringLiteral("arguments"); static const QString MEMBER_DIAGNOSTICS = QStringLiteral("diagnostics"); // message construction helpers -static QJsonObject -to_json(const LSPPosition & pos) +static QJsonObject to_json(const LSPPosition &pos) { - return QJsonObject { - { MEMBER_LINE, pos.line() }, - { MEMBER_CHARACTER, pos.column() } - }; + return QJsonObject { { MEMBER_LINE, pos.line() }, { MEMBER_CHARACTER, pos.column() } }; } -static QJsonObject -to_json(const LSPRange & range) +static QJsonObject to_json(const LSPRange &range) { - return QJsonObject { - { MEMBER_START, to_json(range.start()) }, - { MEMBER_END, to_json(range.end()) } - }; + return QJsonObject { { MEMBER_START, to_json(range.start()) }, + { MEMBER_END, to_json(range.end()) } }; } -static QJsonValue -to_json(const LSPLocation & location) +static QJsonValue to_json(const LSPLocation &location) { if (location.uri.isValid()) { - return QJsonObject { - { MEMBER_URI, location.uri.toString() }, - { MEMBER_RANGE, to_json(location.range) } - }; + return QJsonObject { { MEMBER_URI, location.uri.toString() }, + { MEMBER_RANGE, to_json(location.range) } }; } return QJsonValue(); } -static QJsonValue -to_json(const LSPDiagnosticRelatedInformation & related) +static QJsonValue to_json(const LSPDiagnosticRelatedInformation &related) { auto loc = to_json(related.location); if (loc.isObject()) { - return QJsonObject { - { MEMBER_LOCATION, to_json(related.location) }, - { MEMBER_MESSAGE, related.message } - }; + return QJsonObject { { MEMBER_LOCATION, to_json(related.location) }, + { MEMBER_MESSAGE, related.message } }; } return QJsonValue(); } -static QJsonObject -to_json(const LSPDiagnostic & diagnostic) +static QJsonObject to_json(const LSPDiagnostic &diagnostic) { // required auto result = QJsonObject(); @@ -123,7 +109,7 @@ to_json(const LSPDiagnostic & diagnostic) if (!diagnostic.code.isEmpty()) result[QStringLiteral("code")] = diagnostic.code; if (diagnostic.severity != LSPDiagnosticSeverity::Unknown) - result[QStringLiteral("severity")] = (int) diagnostic.severity; + result[QStringLiteral("severity")] = (int)diagnostic.severity; if (!diagnostic.source.isEmpty()) result[QStringLiteral("source")] = diagnostic.source; auto related = to_json(diagnostic.relatedInformation); @@ -133,21 +119,17 @@ to_json(const LSPDiagnostic & diagnostic) return result; } -static QJsonArray -to_json(const QList & changes) +static QJsonArray to_json(const QList &changes) { QJsonArray result; - for (const auto &change: changes) { - result.push_back(QJsonObject { - {MEMBER_RANGE, to_json(change.range)}, - {MEMBER_TEXT, change.text} - }); + for (const auto &change : changes) { + result.push_back(QJsonObject { { MEMBER_RANGE, to_json(change.range) }, + { MEMBER_TEXT, change.text } }); } return result; } -static QJsonObject -versionedTextDocumentIdentifier(const QUrl & document, int version = -1) +static QJsonObject versionedTextDocumentIdentifier(const QUrl &document, int version = -1) { QJsonObject map { { MEMBER_URI, document.toString() } }; if (version >= 0) @@ -155,9 +137,8 @@ versionedTextDocumentIdentifier(const QUrl & document, int version = -1) return map; } -static QJsonObject -textDocumentItem(const QUrl & document, const QString & lang, - const QString & text, int version) +static QJsonObject textDocumentItem(const QUrl &document, const QString &lang, const QString &text, + int version) { auto map = versionedTextDocumentIdentifier(document, version); map[MEMBER_TEXT] = text; @@ -165,38 +146,32 @@ textDocumentItem(const QUrl & document, const QString & lang, return map; } -static QJsonObject -textDocumentParams(const QJsonObject & m) +static QJsonObject textDocumentParams(const QJsonObject &m) { - return QJsonObject { - { QStringLiteral("textDocument"), m} - }; + return QJsonObject { { QStringLiteral("textDocument"), m } }; } -static QJsonObject -textDocumentParams(const QUrl & document, int version = -1) -{ return textDocumentParams(versionedTextDocumentIdentifier(document, version)); } +static QJsonObject textDocumentParams(const QUrl &document, int version = -1) +{ + return textDocumentParams(versionedTextDocumentIdentifier(document, version)); +} -static QJsonObject -textDocumentPositionParams(const QUrl & document, LSPPosition pos) +static QJsonObject textDocumentPositionParams(const QUrl &document, LSPPosition pos) { auto params = textDocumentParams(document); params[MEMBER_POSITION] = to_json(pos); return params; } -static QJsonObject -referenceParams(const QUrl & document, LSPPosition pos, bool decl) +static QJsonObject referenceParams(const QUrl &document, LSPPosition pos, bool decl) { auto params = textDocumentPositionParams(document, pos); - params[QStringLiteral("context")] = QJsonObject { - { QStringLiteral("includeDeclaration"), decl } - }; + params[QStringLiteral("context")] = + QJsonObject { { QStringLiteral("includeDeclaration"), decl } }; return params; } -static QJsonObject -formattingOptions(const LSPFormattingOptions & _options) +static QJsonObject formattingOptions(const LSPFormattingOptions &_options) { auto options = _options.extra; options[QStringLiteral("tabSize")] = _options.tabSize; @@ -204,9 +179,8 @@ formattingOptions(const LSPFormattingOptions & _options) return options; } -static QJsonObject -documentRangeFormattingParams(const QUrl & document, const LSPRange *range, - const LSPFormattingOptions & _options) +static QJsonObject documentRangeFormattingParams(const QUrl &document, const LSPRange *range, + const LSPFormattingOptions &_options) { auto params = textDocumentParams(document); if (range) { @@ -216,9 +190,9 @@ documentRangeFormattingParams(const QUrl & document, const LSPRange *range, return params; } -static QJsonObject -documentOnTypeFormattingParams(const QUrl & document, const LSPPosition & pos, - const QChar & lastChar, const LSPFormattingOptions & _options) +static QJsonObject documentOnTypeFormattingParams(const QUrl &document, const LSPPosition &pos, + const QChar &lastChar, + const LSPFormattingOptions &_options) { auto params = textDocumentPositionParams(document, pos); params[QStringLiteral("ch")] = QString(lastChar); @@ -226,23 +200,22 @@ documentOnTypeFormattingParams(const QUrl & document, const LSPPosition & pos, return params; } -static QJsonObject -renameParams(const QUrl & document, const LSPPosition & pos, const QString & newName) +static QJsonObject renameParams(const QUrl &document, const LSPPosition &pos, + const QString &newName) { auto params = textDocumentPositionParams(document, pos); params[QStringLiteral("newName")] = newName; return params; } -static QJsonObject -codeActionParams(const QUrl & document, const LSPRange & range, - QList kinds, QList diagnostics) +static QJsonObject codeActionParams(const QUrl &document, const LSPRange &range, + QList kinds, QList diagnostics) { auto params = textDocumentParams(document); params[MEMBER_RANGE] = to_json(range); QJsonObject context; QJsonArray diags; - for (const auto& diagnostic: diagnostics) { + for (const auto &diagnostic : diagnostics) { diags.push_back(to_json(diagnostic)); } context[MEMBER_DIAGNOSTICS] = diags; @@ -252,36 +225,27 @@ codeActionParams(const QUrl & document, const LSPRange & range, return params; } -static QJsonObject -executeCommandParams(const QString & command, const QJsonValue & args) +static QJsonObject executeCommandParams(const QString &command, const QJsonValue &args) { - return QJsonObject { - { MEMBER_COMMAND, command }, - { MEMBER_ARGUMENTS, args } - }; + return QJsonObject { { MEMBER_COMMAND, command }, { MEMBER_ARGUMENTS, args } }; } -static QJsonObject -applyWorkspaceEditResponse(const LSPApplyWorkspaceEditResponse & response) +static QJsonObject applyWorkspaceEditResponse(const LSPApplyWorkspaceEditResponse &response) { - return QJsonObject { - { QStringLiteral("applied"), response.applied }, - { QStringLiteral("failureReason"), response.failureReason } - }; + return QJsonObject { { QStringLiteral("applied"), response.applied }, + { QStringLiteral("failureReason"), response.failureReason } }; } -static void -from_json(QVector & trigger, const QJsonValue & json) +static void from_json(QVector &trigger, const QJsonValue &json) { - for (const auto & t : json.toArray()) { + for (const auto &t : json.toArray()) { auto st = t.toString(); if (st.length()) trigger.push_back(st.at(0)); } } -static void -from_json(LSPCompletionOptions & options, const QJsonValue & json) +static void from_json(LSPCompletionOptions &options, const QJsonValue &json) { if (json.isObject()) { auto ob = json.toObject(); @@ -291,8 +255,7 @@ from_json(LSPCompletionOptions & options, const QJsonValue & json) } } -static void -from_json(LSPSignatureHelpOptions & options, const QJsonValue & json) +static void from_json(LSPSignatureHelpOptions &options, const QJsonValue &json) { if (json.isObject()) { auto ob = json.toObject(); @@ -301,8 +264,7 @@ from_json(LSPSignatureHelpOptions & options, const QJsonValue & json) } } -static void -from_json(LSPDocumentOnTypeFormattingOptions & options, const QJsonValue & json) +static void from_json(LSPDocumentOnTypeFormattingOptions &options, const QJsonValue &json) { if (json.isObject()) { auto ob = json.toObject(); @@ -315,12 +277,13 @@ from_json(LSPDocumentOnTypeFormattingOptions & options, const QJsonValue & json) } } -static void -from_json(LSPServerCapabilities & caps, const QJsonObject & json) +static void from_json(LSPServerCapabilities &caps, const QJsonObject &json) { auto sync = json.value(QStringLiteral("textDocumentSync")); - caps.textDocumentSync = (LSPDocumentSyncKind) - (sync.isObject() ? sync.toObject().value(QStringLiteral("change")) : sync).toInt((int)LSPDocumentSyncKind::None); + caps.textDocumentSync = + (LSPDocumentSyncKind)(sync.isObject() ? sync.toObject().value(QStringLiteral("change")) + : sync) + .toInt((int)LSPDocumentSyncKind::None); caps.hoverProvider = json.value(QStringLiteral("hoverProvider")).toBool(); from_json(caps.completionProvider, json.value(QStringLiteral("completionProvider"))); from_json(caps.signatureHelpProvider, json.value(QStringLiteral("signatureHelpProvider"))); @@ -328,10 +291,14 @@ from_json(LSPServerCapabilities & caps, const QJsonObject & json) caps.declarationProvider = json.value(QStringLiteral("declarationProvider")).toBool(); caps.referencesProvider = json.value(QStringLiteral("referencesProvider")).toBool(); caps.documentSymbolProvider = json.value(QStringLiteral("documentSymbolProvider")).toBool(); - caps.documentHighlightProvider = json.value(QStringLiteral("documentHighlightProvider")).toBool(); - caps.documentFormattingProvider = json.value(QStringLiteral("documentFormattingProvider")).toBool(); - caps.documentRangeFormattingProvider = json.value(QStringLiteral("documentRangeFormattingProvider")).toBool(); - from_json(caps.documentOnTypeFormattingProvider, json.value(QStringLiteral("documentOnTypeFormattingProvider"))); + caps.documentHighlightProvider = + json.value(QStringLiteral("documentHighlightProvider")).toBool(); + caps.documentFormattingProvider = + json.value(QStringLiteral("documentFormattingProvider")).toBool(); + caps.documentRangeFormattingProvider = + json.value(QStringLiteral("documentRangeFormattingProvider")).toBool(); + from_json(caps.documentOnTypeFormattingProvider, + json.value(QStringLiteral("documentOnTypeFormattingProvider"))); caps.renameProvider = json.value(QStringLiteral("renameProvider")).toBool(); auto codeActionProvider = json.value(QStringLiteral("codeActionProvider")); caps.codeActionProvider = codeActionProvider.toBool() || codeActionProvider.isObject(); @@ -340,8 +307,7 @@ from_json(LSPServerCapabilities & caps, const QJsonObject & json) // follow suit; as performed in kate docmanager // normalize at this stage/layer to avoid surprises elsewhere // sadly this is not a single QUrl method as one might hope ... -static QUrl -normalizeUrl(const QUrl & url) +static QUrl normalizeUrl(const QUrl &url) { // Resolve symbolic links for local files (done anyway in KTextEditor) if (url.isLocalFile()) { @@ -355,12 +321,11 @@ normalizeUrl(const QUrl & url) return url.adjusted(QUrl::NormalizePathSegments); } -static LSPMarkupContent -parseMarkupContent(const QJsonValue & v) +static LSPMarkupContent parseMarkupContent(const QJsonValue &v) { LSPMarkupContent ret; if (v.isObject()) { - const auto& vm = v.toObject(); + const auto &vm = v.toObject(); ret.value = vm.value(QStringLiteral("value")).toString(); auto kind = vm.value(MEMBER_KIND).toString(); if (kind == QStringLiteral("plaintext")) { @@ -375,50 +340,48 @@ parseMarkupContent(const QJsonValue & v) return ret; } -static LSPPosition -parsePosition(const QJsonObject & m) +static LSPPosition parsePosition(const QJsonObject &m) { auto line = m.value(MEMBER_LINE).toInt(-1); auto column = m.value(MEMBER_CHARACTER).toInt(-1); - return {line, column}; + return { line, column }; } -static bool -isPositionValid(const LSPPosition & pos) -{ return pos.isValid(); } +static bool isPositionValid(const LSPPosition &pos) +{ + return pos.isValid(); +} -static LSPRange -parseRange(const QJsonObject & range) +static LSPRange parseRange(const QJsonObject &range) { auto startpos = parsePosition(range.value(MEMBER_START).toObject()); auto endpos = parsePosition(range.value(MEMBER_END).toObject()); - return {startpos, endpos}; + return { startpos, endpos }; } -static LSPLocation -parseLocation(const QJsonObject & loc) +static LSPLocation parseLocation(const QJsonObject &loc) { auto uri = normalizeUrl(QUrl(loc.value(MEMBER_URI).toString())); auto range = parseRange(loc.value(MEMBER_RANGE).toObject()); - return {QUrl(uri), range}; + return { QUrl(uri), range }; } -static LSPDocumentHighlight -parseDocumentHighlight(const QJsonValue & result) +static LSPDocumentHighlight parseDocumentHighlight(const QJsonValue &result) { auto hover = result.toObject(); auto range = parseRange(hover.value(MEMBER_RANGE).toObject()); - auto kind = (LSPDocumentHighlightKind)hover.value(MEMBER_KIND).toInt((int)LSPDocumentHighlightKind::Text); // default is DocumentHighlightKind.Text - return {range, kind}; + auto kind = (LSPDocumentHighlightKind)hover.value(MEMBER_KIND) + .toInt((int)LSPDocumentHighlightKind::Text); // default is + // DocumentHighlightKind.Text + return { range, kind }; } -static QList -parseDocumentHighlightList(const QJsonValue & result) +static QList parseDocumentHighlightList(const QJsonValue &result) { QList ret; // could be array if (result.isArray()) { - for (const auto & def : result.toArray()) { + for (const auto &def : result.toArray()) { ret.push_back(parseDocumentHighlight(def)); } } else if (result.isObject()) { @@ -428,8 +391,7 @@ parseDocumentHighlightList(const QJsonValue & result) return ret; } -static LSPMarkupContent -parseHoverContentElement(const QJsonValue & contents) +static LSPMarkupContent parseHoverContentElement(const QJsonValue &contents) { LSPMarkupContent result; if (contents.isString()) { @@ -450,8 +412,7 @@ parseHoverContentElement(const QJsonValue & contents) return result; } -static LSPHover -parseHover(const QJsonValue & result) +static LSPHover parseHover(const QJsonValue &result) { LSPHover ret; auto hover = result.toObject(); @@ -461,7 +422,7 @@ parseHover(const QJsonValue & result) // support the deprecated MarkedString[] variant, used by e.g. Rust rls if (contents.isArray()) { - for (const auto & c : contents.toArray()) { + for (const auto &c : contents.toArray()) { ret.contents.push_back(parseHoverContentElement(c)); } } else { @@ -471,8 +432,7 @@ parseHover(const QJsonValue & result) return ret; } -static QList -parseDocumentSymbols(const QJsonValue & result) +static QList parseDocumentSymbols(const QJsonValue &result) { // the reply could be old SymbolInformation[] or new (hierarchical) DocumentSymbol[] // try to parse it adaptively in any case @@ -483,45 +443,44 @@ parseDocumentSymbols(const QJsonValue & result) // then it is the last instance that is used as a parent QList ret; - QMap index; - - std::function parseSymbol = - [&] (const QJsonObject & symbol, LSPSymbolInformation *parent) { - // if flat list, try to find parent by name - if (!parent) { - auto container = symbol.value(QStringLiteral("containerName")).toString(); - parent = index.value(container, nullptr); - } - auto list = parent ? &parent->children : &ret; - const auto& location = symbol.value(MEMBER_LOCATION).toObject(); - const auto& mrange = symbol.contains(MEMBER_RANGE) ? - symbol.value(MEMBER_RANGE) : location.value(MEMBER_RANGE); - auto range = parseRange(mrange.toObject()); - if (isPositionValid(range.start()) && isPositionValid(range.end())) { - auto name = symbol.value(QStringLiteral("name")).toString(); - auto kind = (LSPSymbolKind) symbol.value(MEMBER_KIND).toInt(); - auto detail = symbol.value(MEMBER_DETAIL).toString(); - list->push_back({name, kind, range, detail}); - index[name] = &list->back(); - // proceed recursively - for (const auto &child : symbol.value(QStringLiteral("children")).toArray()) - parseSymbol(child.toObject(), &list->back()); - } - }; + QMap index; + + std::function parseSymbol = + [&](const QJsonObject &symbol, LSPSymbolInformation *parent) { + // if flat list, try to find parent by name + if (!parent) { + auto container = symbol.value(QStringLiteral("containerName")).toString(); + parent = index.value(container, nullptr); + } + auto list = parent ? &parent->children : &ret; + const auto &location = symbol.value(MEMBER_LOCATION).toObject(); + const auto &mrange = symbol.contains(MEMBER_RANGE) ? symbol.value(MEMBER_RANGE) + : location.value(MEMBER_RANGE); + auto range = parseRange(mrange.toObject()); + if (isPositionValid(range.start()) && isPositionValid(range.end())) { + auto name = symbol.value(QStringLiteral("name")).toString(); + auto kind = (LSPSymbolKind)symbol.value(MEMBER_KIND).toInt(); + auto detail = symbol.value(MEMBER_DETAIL).toString(); + list->push_back({ name, kind, range, detail }); + index[name] = &list->back(); + // proceed recursively + for (const auto &child : symbol.value(QStringLiteral("children")).toArray()) + parseSymbol(child.toObject(), &list->back()); + } + }; - for (const auto& info : result.toArray()) { + for (const auto &info : result.toArray()) { parseSymbol(info.toObject(), nullptr); } return ret; } -static QList -parseDocumentLocation(const QJsonValue & result) +static QList parseDocumentLocation(const QJsonValue &result) { QList ret; // could be array if (result.isArray()) { - for (const auto & def : result.toArray()) { + for (const auto &def : result.toArray()) { ret.push_back(parseLocation(def.toObject())); } } else if (result.isObject()) { @@ -531,8 +490,7 @@ parseDocumentLocation(const QJsonValue & result) return ret; } -static QList -parseDocumentCompletion(const QJsonValue & result) +static QList parseDocumentCompletion(const QJsonValue &result) { QList ret; QJsonArray items = result.toArray(); @@ -540,8 +498,8 @@ parseDocumentCompletion(const QJsonValue & result) if (items.size() == 0) { items = result.toObject().value(QStringLiteral("items")).toArray(); } - for (const auto & vitem : items) { - const auto & item = vitem.toObject(); + for (const auto &vitem : items) { + const auto &item = vitem.toObject(); auto label = item.value(MEMBER_LABEL).toString(); auto detail = item.value(MEMBER_DETAIL).toString(); auto doc = parseMarkupContent(item.value(MEMBER_DOCUMENTATION)); @@ -551,20 +509,19 @@ parseDocumentCompletion(const QJsonValue & result) auto insertText = item.value(QStringLiteral("insertText")).toString(); if (insertText.isEmpty()) insertText = label; - auto kind = (LSPCompletionItemKind) item.value(MEMBER_KIND).toInt(); - ret.push_back({label, kind, detail, doc, sortText, insertText}); + auto kind = (LSPCompletionItemKind)item.value(MEMBER_KIND).toInt(); + ret.push_back({ label, kind, detail, doc, sortText, insertText }); } return ret; } -static LSPSignatureInformation -parseSignatureInformation(const QJsonObject & json) +static LSPSignatureInformation parseSignatureInformation(const QJsonObject &json) { LSPSignatureInformation info; info.label = json.value(MEMBER_LABEL).toString(); info.documentation = parseMarkupContent(json.value(MEMBER_DOCUMENTATION)); - for (const auto & rpar : json.value(QStringLiteral("parameters")).toArray()) { + for (const auto &rpar : json.value(QStringLiteral("parameters")).toArray()) { auto par = rpar.toObject(); auto label = par.value(MEMBER_LABEL); int begin = -1, end = -1; @@ -587,18 +544,17 @@ parseSignatureInformation(const QJsonObject & json) } } } - info.parameters.push_back({begin, end}); + info.parameters.push_back({ begin, end }); } return info; } -static LSPSignatureHelp -parseSignatureHelp(const QJsonValue & result) +static LSPSignatureHelp parseSignatureHelp(const QJsonValue &result) { LSPSignatureHelp ret; QJsonObject sig = result.toObject(); - for (const auto & info: sig.value(QStringLiteral("signatures")).toArray()) { + for (const auto &info : sig.value(QStringLiteral("signatures")).toArray()) { ret.signatures.push_back(parseSignatureInformation(info.toObject())); } ret.activeSignature = sig.value(QStringLiteral("activeSignature")).toInt(0); @@ -608,32 +564,29 @@ parseSignatureHelp(const QJsonValue & result) return ret; } -static QList -parseTextEdit(const QJsonValue & result) +static QList parseTextEdit(const QJsonValue &result) { QList ret; - for (const auto &redit: result.toArray()) { + for (const auto &redit : result.toArray()) { auto edit = redit.toObject(); auto text = edit.value(QStringLiteral("newText")).toString(); auto range = parseRange(edit.value(MEMBER_RANGE).toObject()); - ret.push_back({range, text}); + ret.push_back({ range, text }); } return ret; } -static LSPWorkspaceEdit -parseWorkSpaceEdit(const QJsonValue & result) +static LSPWorkspaceEdit parseWorkSpaceEdit(const QJsonValue &result) { QHash> ret; auto changes = result.toObject().value(QStringLiteral("changes")).toObject(); for (auto it = changes.begin(); it != changes.end(); ++it) { ret.insert(normalizeUrl(QUrl(it.key())), parseTextEdit(it.value())); } - return {ret}; + return { ret }; } -static LSPCommand -parseCommand(const QJsonObject & result) +static LSPCommand parseCommand(const QJsonObject &result) { auto title = result.value(MEMBER_TITLE).toString(); auto command = result.value(MEMBER_COMMAND).toString(); @@ -641,30 +594,28 @@ parseCommand(const QJsonObject & result) return { title, command, args }; } -static QList -parseDiagnostics(const QJsonArray &result) +static QList parseDiagnostics(const QJsonArray &result) { QList ret; - for (const auto & vdiag : result) { + for (const auto &vdiag : result) { auto diag = vdiag.toObject(); auto range = parseRange(diag.value(MEMBER_RANGE).toObject()); - auto severity = (LSPDiagnosticSeverity) diag.value(QStringLiteral("severity")).toInt(); + auto severity = (LSPDiagnosticSeverity)diag.value(QStringLiteral("severity")).toInt(); auto code = diag.value(QStringLiteral("code")).toString(); auto source = diag.value(QStringLiteral("source")).toString(); auto message = diag.value(MEMBER_MESSAGE).toString(); auto related = diag.value(QStringLiteral("relatedInformation")).toObject(); auto relLocation = parseLocation(related.value(MEMBER_LOCATION).toObject()); auto relMessage = related.value(MEMBER_MESSAGE).toString(); - ret.push_back({range, severity, code, source, message, relLocation, relMessage}); + ret.push_back({ range, severity, code, source, message, relLocation, relMessage }); } return ret; } -static QList -parseCodeAction(const QJsonValue & result) +static QList parseCodeAction(const QJsonValue &result) { QList ret; - for (const auto &vaction: result.toArray()) { + for (const auto &vaction : result.toArray()) { auto action = vaction.toObject(); // entry could be Command or CodeAction if (!action.value(MEMBER_COMMAND).isString()) { @@ -674,18 +625,17 @@ parseCodeAction(const QJsonValue & result) auto command = parseCommand(action.value(MEMBER_COMMAND).toObject()); auto edit = parseWorkSpaceEdit(action.value(MEMBER_EDIT)); auto diagnostics = parseDiagnostics(action.value(MEMBER_DIAGNOSTICS).toArray()); - ret.push_back({title, kind, diagnostics, edit, command}); + ret.push_back({ title, kind, diagnostics, edit, command }); } else { // Command auto command = parseCommand(action); - ret.push_back({command.title, QString(), {}, {}, command}); + ret.push_back({ command.title, QString(), {}, {}, command }); } } return ret; } -static LSPPublishDiagnosticsParams -parseDiagnostics(const QJsonObject & result) +static LSPPublishDiagnosticsParams parseDiagnostics(const QJsonObject &result) { LSPPublishDiagnosticsParams ret; @@ -694,8 +644,7 @@ parseDiagnostics(const QJsonObject & result) return ret; } -static LSPApplyWorkspaceEditParams -parseApplyWorkspaceEditParams(const QJsonObject & result) +static LSPApplyWorkspaceEditParams parseApplyWorkspaceEditParams(const QJsonObject &result) { LSPApplyWorkspaceEditParams ret; @@ -704,7 +653,6 @@ parseApplyWorkspaceEditParams(const QJsonObject & result) return ret; } - using GenericReplyType = QJsonValue; using GenericReplyHandler = ReplyHandler; @@ -733,38 +681,26 @@ class LSPClientServer::LSPClientServerPrivate QHash m_handlers; // pending request responses static constexpr int MAX_REQUESTS = 5; - QVector m_requests{MAX_REQUESTS + 1}; + QVector m_requests { MAX_REQUESTS + 1 }; public: - LSPClientServerPrivate(LSPClientServer * _q, const QStringList & server, - const QUrl & root, const QJsonValue & init) + LSPClientServerPrivate(LSPClientServer *_q, const QStringList &server, const QUrl &root, + const QJsonValue &init) : q(_q), m_server(server), m_root(root), m_init(init) { // setup async reading QObject::connect(&m_sproc, &QProcess::readyRead, utils::mem_fun(&self_type::read, this)); - QObject::connect(&m_sproc, &QProcess::stateChanged, utils::mem_fun(&self_type::onStateChanged, this)); + QObject::connect(&m_sproc, &QProcess::stateChanged, + utils::mem_fun(&self_type::onStateChanged, this)); } - ~LSPClientServerPrivate() - { - stop(TIMEOUT_SHUTDOWN, TIMEOUT_SHUTDOWN); - } + ~LSPClientServerPrivate() { stop(TIMEOUT_SHUTDOWN, TIMEOUT_SHUTDOWN); } - const QStringList& cmdline() const - { - return m_server; - } + const QStringList &cmdline() const { return m_server; } - State state() - { - return m_state; - } + State state() { return m_state; } - const LSPServerCapabilities& - capabilities() - { - return m_capabilities; - } + const LSPServerCapabilities &capabilities() { return m_capabilities; } int cancel(int reqid) { @@ -784,7 +720,8 @@ private: } } - RequestHandle write(const QJsonObject & msg, const GenericReplyHandler & h = nullptr, const int * id = nullptr) + RequestHandle write(const QJsonObject &msg, const GenericReplyHandler &h = nullptr, + const int *id = nullptr) { RequestHandle ret; ret.m_server = q; @@ -818,8 +755,7 @@ private: return ret; } - RequestHandle - send(const QJsonObject & msg, const GenericReplyHandler & h = nullptr) + RequestHandle send(const QJsonObject &msg, const GenericReplyHandler &h = nullptr) { if (m_state == State::Running) return write(msg, h); @@ -875,7 +811,7 @@ private: buffer.remove(0, msgstart + length); qCInfo(LSPCLIENT) << "got message payload size " << length; qCDebug(LSPCLIENT) << "message payload:\n" << payload; - QJsonParseError error{}; + QJsonParseError error {}; auto msg = QJsonDocument::fromJson(payload, &error); if (error.error != QJsonParseError::NoError || !msg.isObject()) { qCWarning(LSPCLIENT) << "invalid response payload"; @@ -914,39 +850,25 @@ private: } } - static QJsonObject - init_error(const LSPErrorCode code, const QString & msg) + static QJsonObject init_error(const LSPErrorCode code, const QString &msg) { return QJsonObject { - { MEMBER_ERROR, QJsonObject { - { MEMBER_CODE, (int) code }, - { MEMBER_MESSAGE, msg } - } - } + { MEMBER_ERROR, QJsonObject { { MEMBER_CODE, (int)code }, { MEMBER_MESSAGE, msg } } } }; } - static QJsonObject - init_request(const QString & method, const QJsonObject & params = QJsonObject()) + static QJsonObject init_request(const QString &method, + const QJsonObject ¶ms = QJsonObject()) { - return QJsonObject { - { MEMBER_METHOD, method }, - { MEMBER_PARAMS, params } - }; + return QJsonObject { { MEMBER_METHOD, method }, { MEMBER_PARAMS, params } }; } - static QJsonObject - init_response(const QJsonValue & result = QJsonValue()) + static QJsonObject init_response(const QJsonValue &result = QJsonValue()) { - return QJsonObject { - { MEMBER_RESULT, result } - }; + return QJsonObject { { MEMBER_RESULT, result } }; } - bool running() - { - return m_sproc.state() == QProcess::Running; - } + bool running() { return m_sproc.state() == QProcess::Running; } void onStateChanged(QProcess::ProcessState nstate) { @@ -971,10 +893,11 @@ private: } } - void onInitializeReply(const QJsonValue & value) + void onInitializeReply(const QJsonValue &value) { // only parse parts that we use later on - from_json(m_capabilities, value.toObject().value(QStringLiteral("capabilities")).toObject()); + from_json(m_capabilities, + value.toObject().value(QStringLiteral("capabilities")).toObject()); // finish init initialized(); } @@ -982,39 +905,32 @@ private: void initialize() { QJsonObject codeAction { - { QStringLiteral("codeActionLiteralSupport"), QJsonObject { - { QStringLiteral("codeActionKind"), QJsonObject { - { QStringLiteral("valueSet"), QJsonArray() } - } - } - } - } + { QStringLiteral("codeActionLiteralSupport"), + QJsonObject { { QStringLiteral("codeActionKind"), + QJsonObject { { QStringLiteral("valueSet"), QJsonArray() } } } } } }; QJsonObject capabilities { { QStringLiteral("textDocument"), - QJsonObject { - { QStringLiteral("documentSymbol"), - QJsonObject { { QStringLiteral("hierarchicalDocumentSymbolSupport"), true } }, - }, - { QStringLiteral("publishDiagnostics"), - QJsonObject { { QStringLiteral("relatedInformation"), true } } - }, - { QStringLiteral("codeAction"), codeAction } - } - } + QJsonObject { + { + QStringLiteral("documentSymbol"), + QJsonObject { { QStringLiteral("hierarchicalDocumentSymbolSupport"), + true } }, + }, + { QStringLiteral("publishDiagnostics"), + QJsonObject { { QStringLiteral("relatedInformation"), true } } }, + { QStringLiteral("codeAction"), codeAction } } } }; // NOTE a typical server does not use root all that much, // other than for some corner case (in) requests - QJsonObject params { - { QStringLiteral("processId"), QCoreApplication::applicationPid() }, - { QStringLiteral("rootPath"), m_root.path() }, - { QStringLiteral("rootUri"), m_root.toString() }, - { QStringLiteral("capabilities"), capabilities }, - { QStringLiteral("initializationOptions"), m_init } - }; + QJsonObject params { { QStringLiteral("processId"), QCoreApplication::applicationPid() }, + { QStringLiteral("rootPath"), m_root.path() }, + { QStringLiteral("rootUri"), m_root.toString() }, + { QStringLiteral("capabilities"), capabilities }, + { QStringLiteral("initializationOptions"), m_init } }; // write(init_request(QStringLiteral("initialize"), params), - utils::mem_fun(&self_type::onInitializeReply, this)); + utils::mem_fun(&self_type::onInitializeReply, this)); } void initialized() @@ -1063,134 +979,136 @@ public: } } - RequestHandle documentSymbols(const QUrl & document, const GenericReplyHandler & h) + RequestHandle documentSymbols(const QUrl &document, const GenericReplyHandler &h) { auto params = textDocumentParams(document); return send(init_request(QStringLiteral("textDocument/documentSymbol"), params), h); } - RequestHandle documentDefinition(const QUrl & document, const LSPPosition & pos, - const GenericReplyHandler & h) + RequestHandle documentDefinition(const QUrl &document, const LSPPosition &pos, + const GenericReplyHandler &h) { auto params = textDocumentPositionParams(document, pos); return send(init_request(QStringLiteral("textDocument/definition"), params), h); } - RequestHandle documentDeclaration(const QUrl & document, const LSPPosition & pos, - const GenericReplyHandler & h) + RequestHandle documentDeclaration(const QUrl &document, const LSPPosition &pos, + const GenericReplyHandler &h) { auto params = textDocumentPositionParams(document, pos); return send(init_request(QStringLiteral("textDocument/declaration"), params), h); } - RequestHandle documentHover(const QUrl & document, const LSPPosition & pos, - const GenericReplyHandler & h) + RequestHandle documentHover(const QUrl &document, const LSPPosition &pos, + const GenericReplyHandler &h) { auto params = textDocumentPositionParams(document, pos); return send(init_request(QStringLiteral("textDocument/hover"), params), h); } - RequestHandle documentHighlight(const QUrl & document, const LSPPosition & pos, - const GenericReplyHandler & h) + RequestHandle documentHighlight(const QUrl &document, const LSPPosition &pos, + const GenericReplyHandler &h) { auto params = textDocumentPositionParams(document, pos); return send(init_request(QStringLiteral("textDocument/documentHighlight"), params), h); } - RequestHandle documentReferences(const QUrl & document, const LSPPosition & pos, bool decl, - const GenericReplyHandler & h) + RequestHandle documentReferences(const QUrl &document, const LSPPosition &pos, bool decl, + const GenericReplyHandler &h) { auto params = referenceParams(document, pos, decl); return send(init_request(QStringLiteral("textDocument/references"), params), h); } - RequestHandle documentCompletion(const QUrl & document, const LSPPosition & pos, - const GenericReplyHandler & h) + RequestHandle documentCompletion(const QUrl &document, const LSPPosition &pos, + const GenericReplyHandler &h) { auto params = textDocumentPositionParams(document, pos); return send(init_request(QStringLiteral("textDocument/completion"), params), h); } - RequestHandle signatureHelp(const QUrl & document, const LSPPosition & pos, - const GenericReplyHandler & h) + RequestHandle signatureHelp(const QUrl &document, const LSPPosition &pos, + const GenericReplyHandler &h) { auto params = textDocumentPositionParams(document, pos); return send(init_request(QStringLiteral("textDocument/signatureHelp"), params), h); } - RequestHandle documentFormatting(const QUrl & document, const LSPFormattingOptions & options, - const GenericReplyHandler & h) + RequestHandle documentFormatting(const QUrl &document, const LSPFormattingOptions &options, + const GenericReplyHandler &h) { auto params = documentRangeFormattingParams(document, nullptr, options); return send(init_request(QStringLiteral("textDocument/formatting"), params), h); } - RequestHandle documentRangeFormatting(const QUrl & document, const LSPRange & range, - const LSPFormattingOptions & options, const GenericReplyHandler & h) + RequestHandle documentRangeFormatting(const QUrl &document, const LSPRange &range, + const LSPFormattingOptions &options, + const GenericReplyHandler &h) { auto params = documentRangeFormattingParams(document, &range, options); return send(init_request(QStringLiteral("textDocument/rangeFormatting"), params), h); } - RequestHandle documentOnTypeFormatting(const QUrl & document, const LSPPosition & pos, - QChar lastChar, const LSPFormattingOptions & options, const GenericReplyHandler & h) + RequestHandle documentOnTypeFormatting(const QUrl &document, const LSPPosition &pos, + QChar lastChar, const LSPFormattingOptions &options, + const GenericReplyHandler &h) { auto params = documentOnTypeFormattingParams(document, pos, lastChar, options); return send(init_request(QStringLiteral("textDocument/onTypeFormatting"), params), h); } - RequestHandle documentRename(const QUrl & document, const LSPPosition & pos, - const QString newName, const GenericReplyHandler & h) + RequestHandle documentRename(const QUrl &document, const LSPPosition &pos, + const QString newName, const GenericReplyHandler &h) { auto params = renameParams(document, pos, newName); return send(init_request(QStringLiteral("textDocument/rename"), params), h); } - RequestHandle documentCodeAction(const QUrl & document, const LSPRange & range, - const QList & kinds, QList diagnostics, - const GenericReplyHandler & h) + RequestHandle documentCodeAction(const QUrl &document, const LSPRange &range, + const QList &kinds, QList diagnostics, + const GenericReplyHandler &h) { auto params = codeActionParams(document, range, kinds, diagnostics); return send(init_request(QStringLiteral("textDocument/codeAction"), params), h); } - void executeCommand(const QString & command, const QJsonValue & args) + void executeCommand(const QString &command, const QJsonValue &args) { auto params = executeCommandParams(command, args); send(init_request(QStringLiteral("workspace/executeCommand"), params)); } - void didOpen(const QUrl & document, int version, const QString & langId, const QString & text) + void didOpen(const QUrl &document, int version, const QString &langId, const QString &text) { auto params = textDocumentParams(textDocumentItem(document, langId, text, version)); send(init_request(QStringLiteral("textDocument/didOpen"), params)); } - void didChange(const QUrl & document, int version, const QString & text, - const QList & changes) + void didChange(const QUrl &document, int version, const QString &text, + const QList &changes) { Q_ASSERT(text.size() == 0 || changes.size() == 0); auto params = textDocumentParams(document, version); params[QStringLiteral("contentChanges")] = text.size() - ? QJsonArray { QJsonObject {{MEMBER_TEXT, text}} } + ? QJsonArray { QJsonObject { { MEMBER_TEXT, text } } } : to_json(changes); send(init_request(QStringLiteral("textDocument/didChange"), params)); } - void didSave(const QUrl & document, const QString & text) + void didSave(const QUrl &document, const QString &text) { auto params = textDocumentParams(document); params[QStringLiteral("text")] = text; send(init_request(QStringLiteral("textDocument/didSave"), params)); } - void didClose(const QUrl & document) + void didClose(const QUrl &document) { auto params = textDocumentParams(document); send(init_request(QStringLiteral("textDocument/didClose"), params)); } - void processNotification(const QJsonObject & msg) + void processNotification(const QJsonObject &msg) { auto method = msg[MEMBER_METHOD].toString(); if (method == QStringLiteral("textDocument/publishDiagnostics")) { @@ -1201,16 +1119,18 @@ public: } template - static GenericReplyHandler make_handler(const ReplyHandler & h, - const QObject *context, - typename utils::identity>::type c) + static GenericReplyHandler make_handler( + const ReplyHandler &h, const QObject *context, + typename utils::identity>::type c) { QPointer ctx(context); - return [ctx, h, c] (const GenericReplyType & m) { if (ctx) h(c(m)); }; + return [ctx, h, c](const GenericReplyType &m) { + if (ctx) + h(c(m)); + }; } - GenericReplyHandler - prepareResponse(int msgid) + GenericReplyHandler prepareResponse(int msgid) { // allow limited number of outstanding requests auto ctx = QPointer(q); @@ -1218,8 +1138,7 @@ public: if (m_requests.size() > MAX_REQUESTS) { m_requests.pop_front(); } - auto h = [ctx, this, msgid] (const GenericReplyType & response) - { + auto h = [ctx, this, msgid](const GenericReplyType &response) { if (!ctx) { return; } @@ -1235,19 +1154,23 @@ public: } template - static ReplyHandler responseHandler(const GenericReplyHandler & h, - typename utils::identity>::type c) - { return [h, c] (const ReplyType & m) { h(c(m)); }; } + static ReplyHandler responseHandler( + const GenericReplyHandler &h, + typename utils::identity>::type c) + { + return [h, c](const ReplyType &m) { h(c(m)); }; + } // pretty rare and limited use, but anyway - void processRequest(const QJsonObject & msg) + void processRequest(const QJsonObject &msg) { auto method = msg[MEMBER_METHOD].toString(); auto msgid = msg[MEMBER_ID].toInt(); auto params = msg[MEMBER_PARAMS]; bool handled = false; if (method == QStringLiteral("workspace/applyEdit")) { - auto h = responseHandler(prepareResponse(msgid), applyWorkspaceEditResponse); + auto h = responseHandler(prepareResponse(msgid), + applyWorkspaceEditResponse); emit q->applyEdit(parseApplyWorkspaceEditParams(params.toObject()), h, handled); } else { write(init_error(LSPErrorCode::MethodNotFound, method), nullptr, &msgid); @@ -1256,129 +1179,188 @@ public: } }; - // generic convert handler // sprinkle some connection-like context safety // not so likely relevant/needed due to typical sequence of events, // but in case the latter would be changed in surprising ways ... template -static GenericReplyHandler make_handler(const ReplyHandler & h, - const QObject *context, - typename utils::identity>::type c) +static GenericReplyHandler +make_handler(const ReplyHandler &h, const QObject *context, + typename utils::identity>::type c) { QPointer ctx(context); - return [ctx, h, c] (const GenericReplyType & m) { if (ctx) h(c(m)); }; + return [ctx, h, c](const GenericReplyType &m) { + if (ctx) + h(c(m)); + }; } - -LSPClientServer::LSPClientServer(const QStringList & server, const QUrl & root, - const QJsonValue & init) +LSPClientServer::LSPClientServer(const QStringList &server, const QUrl &root, + const QJsonValue &init) : d(new LSPClientServerPrivate(this, server, root, init)) -{} +{ +} LSPClientServer::~LSPClientServer() -{ delete d; } +{ + delete d; +} -const QStringList& LSPClientServer::cmdline() const -{ return d->cmdline(); } +const QStringList &LSPClientServer::cmdline() const +{ + return d->cmdline(); +} LSPClientServer::State LSPClientServer::state() const -{ return d->state(); } +{ + return d->state(); +} -const LSPServerCapabilities& -LSPClientServer::capabilities() const -{ return d->capabilities(); } +const LSPServerCapabilities &LSPClientServer::capabilities() const +{ + return d->capabilities(); +} bool LSPClientServer::start() -{ return d->start(); } +{ + return d->start(); +} void LSPClientServer::stop(int to_t, int to_k) -{ return d->stop(to_t, to_k); } +{ + return d->stop(to_t, to_k); +} int LSPClientServer::cancel(int reqid) -{ return d->cancel(reqid); } +{ + return d->cancel(reqid); +} LSPClientServer::RequestHandle -LSPClientServer::documentSymbols(const QUrl & document, const QObject *context, - const DocumentSymbolsReplyHandler & h) -{ return d->documentSymbols(document, make_handler(h, context, parseDocumentSymbols)); } +LSPClientServer::documentSymbols(const QUrl &document, const QObject *context, + const DocumentSymbolsReplyHandler &h) +{ + return d->documentSymbols(document, make_handler(h, context, parseDocumentSymbols)); +} LSPClientServer::RequestHandle -LSPClientServer::documentDefinition(const QUrl & document, const LSPPosition & pos, - const QObject *context, const DocumentDefinitionReplyHandler & h) -{ return d->documentDefinition(document, pos, make_handler(h, context, parseDocumentLocation)); } +LSPClientServer::documentDefinition(const QUrl &document, const LSPPosition &pos, + const QObject *context, const DocumentDefinitionReplyHandler &h) +{ + return d->documentDefinition(document, pos, make_handler(h, context, parseDocumentLocation)); +} LSPClientServer::RequestHandle -LSPClientServer::documentDeclaration(const QUrl & document, const LSPPosition & pos, - const QObject *context, const DocumentDefinitionReplyHandler & h) -{ return d->documentDeclaration(document, pos, make_handler(h, context, parseDocumentLocation)); } +LSPClientServer::documentDeclaration(const QUrl &document, const LSPPosition &pos, + const QObject *context, + const DocumentDefinitionReplyHandler &h) +{ + return d->documentDeclaration(document, pos, make_handler(h, context, parseDocumentLocation)); +} -LSPClientServer::RequestHandle -LSPClientServer::documentHover(const QUrl & document, const LSPPosition & pos, - const QObject *context, const DocumentHoverReplyHandler & h) -{ return d->documentHover(document, pos, make_handler(h, context, parseHover)); } +LSPClientServer::RequestHandle LSPClientServer::documentHover(const QUrl &document, + const LSPPosition &pos, + const QObject *context, + const DocumentHoverReplyHandler &h) +{ + return d->documentHover(document, pos, make_handler(h, context, parseHover)); +} LSPClientServer::RequestHandle -LSPClientServer::documentHighlight(const QUrl & document, const LSPPosition & pos, - const QObject *context, const DocumentHighlightReplyHandler & h) -{ return d->documentHighlight(document, pos, make_handler(h, context, parseDocumentHighlightList)); } +LSPClientServer::documentHighlight(const QUrl &document, const LSPPosition &pos, + const QObject *context, const DocumentHighlightReplyHandler &h) +{ + return d->documentHighlight(document, pos, + make_handler(h, context, parseDocumentHighlightList)); +} LSPClientServer::RequestHandle -LSPClientServer::documentReferences(const QUrl & document, const LSPPosition & pos, bool decl, - const QObject *context, const DocumentDefinitionReplyHandler & h) -{ return d->documentReferences(document, pos, decl, make_handler(h, context, parseDocumentLocation)); } +LSPClientServer::documentReferences(const QUrl &document, const LSPPosition &pos, bool decl, + const QObject *context, const DocumentDefinitionReplyHandler &h) +{ + return d->documentReferences(document, pos, decl, + make_handler(h, context, parseDocumentLocation)); +} LSPClientServer::RequestHandle -LSPClientServer::documentCompletion(const QUrl & document, const LSPPosition & pos, - const QObject *context, const DocumentCompletionReplyHandler & h) -{ return d->documentCompletion(document, pos, make_handler(h, context, parseDocumentCompletion)); } +LSPClientServer::documentCompletion(const QUrl &document, const LSPPosition &pos, + const QObject *context, const DocumentCompletionReplyHandler &h) +{ + return d->documentCompletion(document, pos, make_handler(h, context, parseDocumentCompletion)); +} -LSPClientServer::RequestHandle -LSPClientServer::signatureHelp(const QUrl & document, const LSPPosition & pos, - const QObject *context, const SignatureHelpReplyHandler & h) -{ return d->signatureHelp(document, pos, make_handler(h, context, parseSignatureHelp)); } +LSPClientServer::RequestHandle LSPClientServer::signatureHelp(const QUrl &document, + const LSPPosition &pos, + const QObject *context, + const SignatureHelpReplyHandler &h) +{ + return d->signatureHelp(document, pos, make_handler(h, context, parseSignatureHelp)); +} LSPClientServer::RequestHandle -LSPClientServer::documentFormatting(const QUrl & document, const LSPFormattingOptions & options, - const QObject *context, const FormattingReplyHandler & h) -{ return d->documentFormatting(document, options, make_handler(h, context, parseTextEdit)); } +LSPClientServer::documentFormatting(const QUrl &document, const LSPFormattingOptions &options, + const QObject *context, const FormattingReplyHandler &h) +{ + return d->documentFormatting(document, options, make_handler(h, context, parseTextEdit)); +} LSPClientServer::RequestHandle -LSPClientServer::documentRangeFormatting(const QUrl & document, const LSPRange & range, - const LSPFormattingOptions & options, - const QObject *context, const FormattingReplyHandler & h) -{ return d->documentRangeFormatting(document, range, options, make_handler(h, context, parseTextEdit)); } +LSPClientServer::documentRangeFormatting(const QUrl &document, const LSPRange &range, + const LSPFormattingOptions &options, + const QObject *context, const FormattingReplyHandler &h) +{ + return d->documentRangeFormatting(document, range, options, + make_handler(h, context, parseTextEdit)); +} LSPClientServer::RequestHandle -LSPClientServer::documentOnTypeFormatting(const QUrl & document, const LSPPosition & pos, - const QChar lastChar, const LSPFormattingOptions & options, - const QObject *context, const FormattingReplyHandler & h) -{ return d->documentOnTypeFormatting(document, pos, lastChar, options, make_handler(h, context, parseTextEdit)); } +LSPClientServer::documentOnTypeFormatting(const QUrl &document, const LSPPosition &pos, + const QChar lastChar, const LSPFormattingOptions &options, + const QObject *context, const FormattingReplyHandler &h) +{ + return d->documentOnTypeFormatting(document, pos, lastChar, options, + make_handler(h, context, parseTextEdit)); +} LSPClientServer::RequestHandle -LSPClientServer::documentRename(const QUrl & document, const LSPPosition & pos, - const QString newName, - const QObject *context, const WorkspaceEditReplyHandler & h) -{ return d->documentRename(document, pos, newName, make_handler(h, context, parseWorkSpaceEdit)); } +LSPClientServer::documentRename(const QUrl &document, const LSPPosition &pos, const QString newName, + const QObject *context, const WorkspaceEditReplyHandler &h) +{ + return d->documentRename(document, pos, newName, make_handler(h, context, parseWorkSpaceEdit)); +} LSPClientServer::RequestHandle -LSPClientServer::documentCodeAction(const QUrl & document, const LSPRange & range, - const QList & kinds, QList diagnostics, - const QObject *context, const CodeActionReplyHandler & h) -{ return d->documentCodeAction(document, range, kinds, diagnostics, make_handler(h, context, parseCodeAction)); } +LSPClientServer::documentCodeAction(const QUrl &document, const LSPRange &range, + const QList &kinds, QList diagnostics, + const QObject *context, const CodeActionReplyHandler &h) +{ + return d->documentCodeAction(document, range, kinds, diagnostics, + make_handler(h, context, parseCodeAction)); +} -void LSPClientServer::executeCommand(const QString & command, const QJsonValue & args) -{ return d->executeCommand(command, args); } +void LSPClientServer::executeCommand(const QString &command, const QJsonValue &args) +{ + return d->executeCommand(command, args); +} -void LSPClientServer::didOpen(const QUrl & document, int version, const QString & langId, const QString & text) -{ return d->didOpen(document, version, langId, text); } +void LSPClientServer::didOpen(const QUrl &document, int version, const QString &langId, + const QString &text) +{ + return d->didOpen(document, version, langId, text); +} -void LSPClientServer::didChange(const QUrl & document, int version, const QString & text, - const QList & changes) -{ return d->didChange(document, version, text, changes); } +void LSPClientServer::didChange(const QUrl &document, int version, const QString &text, + const QList &changes) +{ + return d->didChange(document, version, text, changes); +} -void LSPClientServer::didSave(const QUrl & document, const QString & text) -{ return d->didSave(document, text); } +void LSPClientServer::didSave(const QUrl &document, const QString &text) +{ + return d->didSave(document, text); +} -void LSPClientServer::didClose(const QUrl & document) -{ return d->didClose(document); } +void LSPClientServer::didClose(const QUrl &document) +{ + return d->didClose(document); +} diff --git a/addons/lspclient/lspclientserver.h b/addons/lspclient/lspclientserver.h index d2dccd1d3..bcb843229 100644 --- a/addons/lspclient/lspclientserver.h +++ b/addons/lspclient/lspclientserver.h @@ -37,35 +37,30 @@ #include -namespace utils -{ +namespace utils { // template helper // function bind helpers template -inline std::function -mem_fun(R (T::*pm)(Args ...), Tp object) +inline std::function mem_fun(R (T::*pm)(Args...), Tp object) { - return [object, pm](Args... args) { - return (object->*pm)(std::forward(args)...); - }; + return [object, pm](Args... args) { return (object->*pm)(std::forward(args)...); }; } template -inline std::function -mem_fun(R (T::*pm)(Args ...) const, Tp object) +inline std::function mem_fun(R (T::*pm)(Args...) const, Tp object) { - return [object, pm](Args... args) { - return (object->*pm)(std::forward(args)...); - }; + return [object, pm](Args... args) { return (object->*pm)(std::forward(args)...); }; } // prevent argument deduction -template struct identity { typedef T type; }; +template +struct identity { + typedef T type; +}; } // namespace utils - static const int TIMEOUT_SHUTDOWN = 200; template @@ -87,13 +82,7 @@ class LSPClientServer : public QObject Q_OBJECT public: - enum class State - { - None, - Started, - Running, - Shutdown - }; + enum class State { None, Started, Running, Shutdown }; class LSPClientServerPrivate; class RequestHandle @@ -101,8 +90,9 @@ public: friend class LSPClientServerPrivate; QPointer m_server; int m_id = -1; + public: - RequestHandle& cancel() + RequestHandle &cancel() { if (m_server) m_server->cancel(m_id); @@ -110,8 +100,8 @@ public: } }; - LSPClientServer(const QStringList & server, const QUrl & root, - const QJsonValue & init = QJsonValue()); + LSPClientServer(const QStringList &server, const QUrl &root, + const QJsonValue &init = QJsonValue()); ~LSPClientServer(); // server management @@ -123,65 +113,70 @@ public: int cancel(int id); // properties - const QStringList& cmdline() const; + const QStringList &cmdline() const; State state() const; - Q_SIGNAL void stateChanged(LSPClientServer * server); + Q_SIGNAL void stateChanged(LSPClientServer *server); - const LSPServerCapabilities& capabilities() const; + const LSPServerCapabilities &capabilities() const; // language - RequestHandle documentSymbols(const QUrl & document, const QObject *context, - const DocumentSymbolsReplyHandler & h); - RequestHandle documentDefinition(const QUrl & document, const LSPPosition & pos, - const QObject *context, const DocumentDefinitionReplyHandler & h); - RequestHandle documentDeclaration(const QUrl & document, const LSPPosition & pos, - const QObject *context, const DocumentDefinitionReplyHandler & h); - RequestHandle documentHighlight(const QUrl & document, const LSPPosition & pos, - const QObject *context, const DocumentHighlightReplyHandler & h); - RequestHandle documentHover(const QUrl & document, const LSPPosition & pos, - const QObject *context, const DocumentHoverReplyHandler & h); - RequestHandle documentReferences(const QUrl & document, const LSPPosition & pos, bool decl, - const QObject *context, const DocumentDefinitionReplyHandler & h); - RequestHandle documentCompletion(const QUrl & document, const LSPPosition & pos, - const QObject *context, const DocumentCompletionReplyHandler & h); - RequestHandle signatureHelp(const QUrl & document, const LSPPosition & pos, - const QObject *context, const SignatureHelpReplyHandler & h); - - RequestHandle documentFormatting(const QUrl & document, const LSPFormattingOptions & options, - const QObject *context, const FormattingReplyHandler & h); - RequestHandle documentRangeFormatting(const QUrl & document, const LSPRange & range, - const LSPFormattingOptions & options, - const QObject *context, const FormattingReplyHandler & h); - RequestHandle documentOnTypeFormatting(const QUrl & document, const LSPPosition & pos, - QChar lastChar, const LSPFormattingOptions & options, - const QObject *context, const FormattingReplyHandler & h); - RequestHandle documentRename(const QUrl & document, const LSPPosition & pos, - const QString newName, - const QObject *context, const WorkspaceEditReplyHandler & h); - - RequestHandle documentCodeAction(const QUrl & document, const LSPRange & range, - const QList & kinds, QList diagnostics, - const QObject *context, const CodeActionReplyHandler & h); - void executeCommand(const QString & command, const QJsonValue & args); + RequestHandle documentSymbols(const QUrl &document, const QObject *context, + const DocumentSymbolsReplyHandler &h); + RequestHandle documentDefinition(const QUrl &document, const LSPPosition &pos, + const QObject *context, + const DocumentDefinitionReplyHandler &h); + RequestHandle documentDeclaration(const QUrl &document, const LSPPosition &pos, + const QObject *context, + const DocumentDefinitionReplyHandler &h); + RequestHandle documentHighlight(const QUrl &document, const LSPPosition &pos, + const QObject *context, const DocumentHighlightReplyHandler &h); + RequestHandle documentHover(const QUrl &document, const LSPPosition &pos, + const QObject *context, const DocumentHoverReplyHandler &h); + RequestHandle documentReferences(const QUrl &document, const LSPPosition &pos, bool decl, + const QObject *context, + const DocumentDefinitionReplyHandler &h); + RequestHandle documentCompletion(const QUrl &document, const LSPPosition &pos, + const QObject *context, + const DocumentCompletionReplyHandler &h); + RequestHandle signatureHelp(const QUrl &document, const LSPPosition &pos, + const QObject *context, const SignatureHelpReplyHandler &h); + + RequestHandle documentFormatting(const QUrl &document, const LSPFormattingOptions &options, + const QObject *context, const FormattingReplyHandler &h); + RequestHandle documentRangeFormatting(const QUrl &document, const LSPRange &range, + const LSPFormattingOptions &options, + const QObject *context, const FormattingReplyHandler &h); + RequestHandle documentOnTypeFormatting(const QUrl &document, const LSPPosition &pos, + QChar lastChar, const LSPFormattingOptions &options, + const QObject *context, const FormattingReplyHandler &h); + RequestHandle documentRename(const QUrl &document, const LSPPosition &pos, + const QString newName, const QObject *context, + const WorkspaceEditReplyHandler &h); + + RequestHandle documentCodeAction(const QUrl &document, const LSPRange &range, + const QList &kinds, QList diagnostics, + const QObject *context, const CodeActionReplyHandler &h); + void executeCommand(const QString &command, const QJsonValue &args); // sync - void didOpen(const QUrl & document, int version, const QString & langId, const QString & text); + void didOpen(const QUrl &document, int version, const QString &langId, const QString &text); // only 1 of text or changes should be non-empty and is considered - void didChange(const QUrl & document, int version, const QString & text, - const QList & changes = {}); - void didSave(const QUrl & document, const QString & text); - void didClose(const QUrl & document); + void didChange(const QUrl &document, int version, const QString &text, + const QList &changes = {}); + void didSave(const QUrl &document, const QString &text); + void didClose(const QUrl &document); // notifcation = signal Q_SIGNALS: - void publishDiagnostics(const LSPPublishDiagnosticsParams & ); + void publishDiagnostics(const LSPPublishDiagnosticsParams &); // request = signal - void applyEdit(const LSPApplyWorkspaceEditParams &req, const ApplyEditReplyHandler &h, bool &handled); + void applyEdit(const LSPApplyWorkspaceEditParams &req, const ApplyEditReplyHandler &h, + bool &handled); private: // pimpl data holder - LSPClientServerPrivate * const d; + LSPClientServerPrivate *const d; }; #endif diff --git a/addons/lspclient/lspclientservermanager.cpp b/addons/lspclient/lspclientservermanager.cpp index 5769126b2..29118dbb3 100644 --- a/addons/lspclient/lspclientservermanager.cpp +++ b/addons/lspclient/lspclientservermanager.cpp @@ -93,7 +93,8 @@ #include // helper to find a proper root dir for the given document & file name that indicate the root dir -static QString rootForDocumentAndRootIndicationFileName(KTextEditor::Document *document, const QString &rootIndicationFileName) +static QString rootForDocumentAndRootIndicationFileName(KTextEditor::Document *document, + const QString &rootIndicationFileName) { // search only feasible if document is local file if (!document->url().isLocalFile()) { @@ -126,13 +127,12 @@ static QString rootForDocumentAndRootIndicationFileName(KTextEditor::Document *d // local helper; // recursively merge top json top onto bottom json -static QJsonObject -merge(const QJsonObject & bottom, const QJsonObject & top) +static QJsonObject merge(const QJsonObject &bottom, const QJsonObject &top) { QJsonObject result; for (auto item = top.begin(); item != top.end(); item++) { - const auto & key = item.key(); - if (item.value().isObject()) { + const auto &key = item.key(); + if (item.value().isObject()) { result.insert(key, merge(bottom.value(key).toObject(), item.value().toObject())); } else { result.insert(key, item.value()); @@ -148,8 +148,7 @@ merge(const QJsonObject & bottom, const QJsonObject & top) } // map (highlight)mode to lsp languageId -static QString -languageId(const QString & mode) +static QString languageId(const QString &mode) { // special cases static QHash m; @@ -164,16 +163,15 @@ languageId(const QString & mode) } // helper guard to handle revision (un)lock -struct RevisionGuard -{ +struct RevisionGuard { QPointer m_doc; KTextEditor::MovingInterface *m_movingInterface = nullptr; qint64 m_revision = -1; - RevisionGuard(KTextEditor::Document *doc = nullptr) : - m_doc(doc), - m_movingInterface(qobject_cast(doc)), - m_revision(-1) + RevisionGuard(KTextEditor::Document *doc = nullptr) + : m_doc(doc), + m_movingInterface(qobject_cast(doc)), + m_revision(-1) { if (m_movingInterface) { m_revision = m_movingInterface->revision(); @@ -182,7 +180,7 @@ struct RevisionGuard } // really only need/allow this one (out of 5) - RevisionGuard(RevisionGuard && other) : RevisionGuard(nullptr) + RevisionGuard(RevisionGuard &&other) : RevisionGuard(nullptr) { std::swap(m_doc, other.m_doc); std::swap(m_movingInterface, other.m_movingInterface); @@ -204,7 +202,6 @@ struct RevisionGuard } }; - class LSPClientRevisionSnapshotImpl : public LSPClientRevisionSnapshot { Q_OBJECT @@ -217,7 +214,7 @@ class LSPClientRevisionSnapshotImpl : public LSPClientRevisionSnapshot Q_SLOT void clearRevisions(KTextEditor::Document *doc) { - for (auto &item: m_guards) { + for (auto &item : m_guards) { if (item.second.m_doc == doc) { item.second.release(); } @@ -231,16 +228,18 @@ public: // make sure revision is cleared when needed and no longer used (to unlock or otherwise) // see e.g. implementation in katetexthistory.cpp and assert's in place there - auto conn = connect(doc, SIGNAL(aboutToInvalidateMovingInterfaceContent(KTextEditor::Document*)), - this, SLOT(clearRevisions(KTextEditor::Document*))); + auto conn = connect( + doc, SIGNAL(aboutToInvalidateMovingInterfaceContent(KTextEditor::Document *)), this, + SLOT(clearRevisions(KTextEditor::Document *))); Q_ASSERT(conn); - conn = connect(doc, SIGNAL(aboutToDeleteMovingInterfaceContent(KTextEditor::Document*)), - this, SLOT(clearRevisions(KTextEditor::Document*))); + conn = connect(doc, SIGNAL(aboutToDeleteMovingInterfaceContent(KTextEditor::Document *)), + this, SLOT(clearRevisions(KTextEditor::Document *))); Q_ASSERT(conn); m_guards.emplace(doc->url(), doc); } - void find(const QUrl & url, KTextEditor::MovingInterface* & miface, qint64 & revision) const override + void find(const QUrl &url, KTextEditor::MovingInterface *&miface, + qint64 &revision) const override { auto it = m_guards.find(url); if (it != m_guards.end()) { @@ -260,14 +259,13 @@ class LSPClientServerManagerImpl : public LSPClientServerManager typedef LSPClientServerManagerImpl self_type; - struct DocumentInfo - { + struct DocumentInfo { QSharedPointer server; KTextEditor::MovingInterface *movingInterface; QUrl url; qint64 version; - bool open:1; - bool modified:1; + bool open : 1; + bool modified : 1; // used for incremental update (if non-empty) QList changes; }; @@ -278,14 +276,14 @@ class LSPClientServerManagerImpl : public LSPClientServerManager QJsonObject m_serverConfig; // root -> (mode -> server) QMap>> m_servers; - QHash m_docs; + QHash m_docs; bool m_incrementalSync = false; typedef QVector> ServerList; public: LSPClientServerManagerImpl(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin) - : m_plugin(plugin) , m_mainWindow(mainWin) + : m_plugin(plugin), m_mainWindow(mainWin) { connect(plugin, &LSPClientPlugin::update, this, &self_type::updateServerConfig); QTimer::singleShot(100, this, &self_type::updateServerConfig); @@ -305,18 +303,18 @@ public: QTimer t; connect(&t, &QTimer::timeout, &q, &QEventLoop::quit); - auto run = [&q, &t] (int ms) { + auto run = [&q, &t](int ms) { t.setSingleShot(true); t.start(ms); q.exec(); }; int count = 0; - for (const auto & el: m_servers) { - for (const auto & s: el) { + for (const auto &el : m_servers) { + for (const auto &s : el) { disconnect(s.data(), nullptr, this, nullptr); if (s->state() != LSPClientServer::State::None) { - auto handler = [&q, &count, s] () { + auto handler = [&q, &count, s]() { if (s->state() != LSPClientServer::State::None) { if (--count == 0) { q.quit(); @@ -334,8 +332,8 @@ public: // stage 2 and 3 count = 0; for (count = 0; count < 2; ++count) { - for (const auto & el: m_servers) { - for (const auto & s: el) { + for (const auto &el : m_servers) { + for (const auto &s : el) { s->stop(count == 0 ? 1 : -1, count == 0 ? -1 : 1); } } @@ -343,11 +341,10 @@ public: } } - void setIncrementalSync(bool inc) override - { m_incrementalSync = inc; } + void setIncrementalSync(bool inc) override { m_incrementalSync = inc; } - QSharedPointer - findServer(KTextEditor::Document *document, bool updatedoc = true) override + QSharedPointer findServer(KTextEditor::Document *document, + bool updatedoc = true) override { if (!document || document->url().isEmpty()) return nullptr; @@ -364,17 +361,19 @@ public: return server; } - QSharedPointer - findServer(KTextEditor::View *view, bool updatedoc = true) override - { return view ? findServer(view->document(), updatedoc) : nullptr; } + QSharedPointer findServer(KTextEditor::View *view, + bool updatedoc = true) override + { + return view ? findServer(view->document(), updatedoc) : nullptr; + } // restart a specific server or all servers if server == nullptr - void restart(LSPClientServer * server) override + void restart(LSPClientServer *server) override { ServerList servers; // find entry for server(s) and move out - for (auto & m : m_servers) { - for (auto it = m.begin() ; it != m.end(); ) { + for (auto &m : m_servers) { + for (auto it = m.begin(); it != m.end();) { if (!server || it->data() == server) { servers.push_back(*it); it = m.erase(it); @@ -392,7 +391,7 @@ public: return it != m_docs.end() ? it->version : -1; } - virtual LSPClientRevisionSnapshot* snapshot(LSPClientServer *server) override + virtual LSPClientRevisionSnapshot *snapshot(LSPClientServer *server) override { auto result = new LSPClientRevisionSnapshotImpl; for (auto it = m_docs.begin(); it != m_docs.end(); ++it) { @@ -409,7 +408,8 @@ private: void showMessage(const QString &msg, KTextEditor::Message::MessageType level) { KTextEditor::View *view = m_mainWindow->activeView(); - if (!view || !view->document()) return; + if (!view || !view->document()) + return; auto kmsg = new KTextEditor::Message(xi18nc("@info", "LSP Client: %1", msg), level); kmsg->setPosition(KTextEditor::Message::AboveView); @@ -420,13 +420,13 @@ private: } // caller ensures that servers are no longer present in m_servers - void restart(const ServerList & servers) + void restart(const ServerList &servers) { // close docs - for (const auto & server : servers) { + for (const auto &server : servers) { // controlling server here, so disable usual state tracking response disconnect(server.data(), nullptr, this, nullptr); - for (auto it = m_docs.begin(); it != m_docs.end(); ) { + for (auto it = m_docs.begin(); it != m_docs.end();) { auto &item = it.value(); if (item.server == server) { // no need to close if server not in proper state @@ -441,8 +441,8 @@ private: } // helper captures servers - auto stopservers = [servers] (int t, int k) { - for (const auto & server : servers) { + auto stopservers = [servers](int t, int k) { + for (const auto &server : servers) { server->stop(t, k); } }; @@ -452,13 +452,13 @@ private: // initiate delayed stages (TERM and KILL) // async, so give a bit more time - QTimer::singleShot(2 * TIMEOUT_SHUTDOWN, this, [stopservers] () { stopservers(1, -1); }); - QTimer::singleShot(4 * TIMEOUT_SHUTDOWN, this, [stopservers] () { stopservers(-1, 1); }); + QTimer::singleShot(2 * TIMEOUT_SHUTDOWN, this, [stopservers]() { stopservers(1, -1); }); + QTimer::singleShot(4 * TIMEOUT_SHUTDOWN, this, [stopservers]() { stopservers(-1, 1); }); // as for the start part // trigger interested parties, which will again request a server as needed // let's delay this; less chance for server instances to trip over each other - QTimer::singleShot(6 * TIMEOUT_SHUTDOWN, this, [this] () { emit serverChanged(); }); + QTimer::singleShot(6 * TIMEOUT_SHUTDOWN, this, [this]() { emit serverChanged(); }); } void onStateChanged(LSPClientServer *server) @@ -468,24 +468,29 @@ private: emit serverChanged(); } else if (server->state() == LSPClientServer::State::None) { // went down - showMessage(i18n("Server terminated unexpectedly: %1", server->cmdline().join(QLatin1Char(' '))), - KTextEditor::Message::Warning); + showMessage(i18n("Server terminated unexpectedly: %1", + server->cmdline().join(QLatin1Char(' '))), + KTextEditor::Message::Warning); restart(server); } } - QSharedPointer - _findServer(KTextEditor::Document *document) + QSharedPointer _findServer(KTextEditor::Document *document) { QObject *projectView = m_mainWindow->pluginView(QStringLiteral("kateprojectplugin")); - const auto projectBase = QDir(projectView ? projectView->property("projectBaseDir").toString() : QString()); - const auto& projectMap = projectView ? projectView->property("projectMap").toMap() : QVariantMap(); + const auto projectBase = + QDir(projectView ? projectView->property("projectBaseDir").toString() : QString()); + const auto &projectMap = + projectView ? projectView->property("projectMap").toMap() : QVariantMap(); // compute the LSP standardized language id auto langId = languageId(document->highlightingMode()); // merge with project specific - auto projectConfig = QJsonDocument::fromVariant(projectMap).object().value(QStringLiteral("lspclient")).toObject(); + auto projectConfig = QJsonDocument::fromVariant(projectMap) + .object() + .value(QStringLiteral("lspclient")) + .toObject(); auto serverConfig = merge(m_serverConfig, projectConfig); // locate server config @@ -496,7 +501,7 @@ private: used << langId; config = serverConfig.value(QStringLiteral("servers")).toObject().value(langId); if (config.isObject()) { - const auto & base = config.toObject().value(QStringLiteral("use")).toString(); + const auto &base = config.toObject().value(QStringLiteral("use")).toString(); // basic cycle detection if (!base.isEmpty() && !used.contains(base)) { langId = base; @@ -510,7 +515,8 @@ private: return nullptr; // merge global settings - serverConfig = merge(serverConfig.value(QStringLiteral("global")).toObject(), config.toObject()); + serverConfig = + merge(serverConfig.value(QStringLiteral("global")).toObject(), config.toObject()); QString rootpath; auto rootv = serverConfig.value(QStringLiteral("root")); @@ -525,16 +531,19 @@ private: /** * no explicit set root dir? search for a matching root based on some name filters - * this is required for some LSP servers like rls that don't handle that on their own like clangd does + * this is required for some LSP servers like rls that don't handle that on their own like + * clangd does */ if (rootpath.isEmpty()) { - const auto fileNamesForDetection = serverConfig.value(QStringLiteral("rootIndicationFileNames")); + const auto fileNamesForDetection = + serverConfig.value(QStringLiteral("rootIndicationFileNames")); if (fileNamesForDetection.isArray()) { // we try each file name alternative in the listed order // this allows to have preferences for (auto name : fileNamesForDetection.toArray()) { if (name.isString()) { - rootpath = rootForDocumentAndRootIndicationFileName(document, name.toString()); + rootpath = + rootForDocumentAndRootIndicationFileName(document, name.toString()); if (!rootpath.isEmpty()) { break; } @@ -554,7 +563,9 @@ private: QStringList cmdline; // choose debug command line for debug mode, fallback to command - auto vcmdline = serverConfig.value(m_plugin->m_debugMode ? QStringLiteral("commandDebug") : QStringLiteral("command")); + auto vcmdline = + serverConfig.value(m_plugin->m_debugMode ? QStringLiteral("commandDebug") + : QStringLiteral("command")); if (vcmdline.isUndefined()) { vcmdline = serverConfig.value(QStringLiteral("command")); } @@ -563,18 +574,20 @@ private: if (!scmdline.isEmpty()) { cmdline = scmdline.split(QLatin1Char(' ')); } else { - for (const auto& c : vcmdline.toArray()) { + for (const auto &c : vcmdline.toArray()) { cmdline.push_back(c.toString()); } } if (cmdline.length() > 0) { - server.reset(new LSPClientServer(cmdline, root, serverConfig.value(QStringLiteral("initializationOptions")))); + server.reset(new LSPClientServer( + cmdline, root, + serverConfig.value(QStringLiteral("initializationOptions")))); m_servers[root][langId] = server; - connect(server.data(), &LSPClientServer::stateChanged, - this, &self_type::onStateChanged, Qt::UniqueConnection); + connect(server.data(), &LSPClientServer::stateChanged, this, + &self_type::onStateChanged, Qt::UniqueConnection); if (!server->start()) { showMessage(i18n("Failed to start server: %1", cmdline.join(QLatin1Char(' '))), - KTextEditor::Message::Error); + KTextEditor::Message::Error); } } } @@ -590,7 +603,7 @@ private: m_serverConfig = QJsonDocument::fromJson(defaultConfigFile.readAll()).object(); // consider specified configuration - const auto& configPath = m_plugin->m_configPath.path(); + const auto &configPath = m_plugin->m_configPath.path(); if (!configPath.isEmpty()) { QFile f(configPath); if (f.open(QIODevice::ReadOnly)) { @@ -600,11 +613,11 @@ private: m_serverConfig = merge(m_serverConfig, json.object()); } else { showMessage(i18n("Failed to parse server configuration: %1", configPath), - KTextEditor::Message::Error); + KTextEditor::Message::Error); } } else { showMessage(i18n("Failed to read server configuration: %1", configPath), - KTextEditor::Message::Error); + KTextEditor::Message::Error); } } @@ -618,26 +631,35 @@ private: { auto it = m_docs.find(doc); if (it == m_docs.end()) { - KTextEditor::MovingInterface* miface = qobject_cast(doc); - it = m_docs.insert(doc, {server, miface, doc->url(), 0, false, false, {}}); + KTextEditor::MovingInterface *miface = + qobject_cast(doc); + 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); + 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); + 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; } } - decltype(m_docs)::iterator - _close(decltype(m_docs)::iterator it, bool remove) + decltype(m_docs)::iterator _close(decltype(m_docs)::iterator it, bool remove) { if (it != m_docs.end()) { if (it->open) { @@ -663,14 +685,13 @@ private: void untrack(QObject *doc) { - _close(qobject_cast(doc), true); + _close(qobject_cast(doc), true); emit serverChanged(); } - void close(KTextEditor::Document *doc) - { _close(doc, false); } + void close(KTextEditor::Document *doc) { _close(doc, false); } - void update(const decltype(m_docs)::iterator & it, bool force) + void update(const decltype(m_docs)::iterator &it, bool force) { auto doc = it.key(); if (it != m_docs.end() && it->server) { @@ -684,12 +705,15 @@ private: } if (it->open) { if (it->modified || force) { - (it->server)->didChange(it->url, it->version, - (it->changes.size() == 0) ? doc->text() : QString(), - it->changes); + (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->server) + ->didOpen(it->url, it->version, languageId(doc->highlightingMode()), + doc->text()); it->open = true; } it->modified = false; @@ -702,7 +726,7 @@ private: update(m_docs.find(doc), force); } - void update(LSPClientServer * server, bool force) + void update(LSPClientServer *server, bool force) { for (auto it = m_docs.begin(); it != m_docs.end(); ++it) { if (it->server == server) { @@ -719,15 +743,14 @@ private: } } - DocumentInfo* - getDocumentInfo(KTextEditor::Document *doc) + 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(); + const auto &caps = it->server->capabilities(); if (caps.textDocumentSync == LSPDocumentSyncKind::Incremental) { return &(*it); } @@ -735,20 +758,22 @@ private: return nullptr; } - void onTextInserted(KTextEditor::Document *doc, const KTextEditor::Cursor &position, const QString &text) + 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}); + info->changes.push_back({ LSPRange { position, position }, text }); } } - void onTextRemoved(KTextEditor::Document *doc, const KTextEditor::Range &range, const QString &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()}); + info->changes.push_back({ range, QString() }); } } @@ -756,7 +781,7 @@ private: { // 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}}); + auto text = doc->text({ position, { position.line() + 1, 0 } }); onTextInserted(doc, position, text); } @@ -766,13 +791,12 @@ private: 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}}; + 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}); + info->changes.push_back({ oldrange, text }); } } - }; QSharedPointer diff --git a/addons/lspclient/lspclientservermanager.h b/addons/lspclient/lspclientservermanager.h index 5925c8157..e7ac71ba2 100644 --- a/addons/lspclient/lspclientservermanager.h +++ b/addons/lspclient/lspclientservermanager.h @@ -31,10 +31,10 @@ #include namespace KTextEditor { - class MainWindow; - class Document; - class View; - class MovingInterface; +class MainWindow; +class Document; +class View; +class MovingInterface; } class LSPClientRevisionSnapshot; @@ -54,14 +54,14 @@ class LSPClientServerManager : public QObject public: // factory method; private implementation by interface - static QSharedPointer - new_(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin); + static QSharedPointer new_(LSPClientPlugin *plugin, + KTextEditor::MainWindow *mainWin); - virtual QSharedPointer - findServer(KTextEditor::Document *document, bool updatedoc = true) = 0; + virtual QSharedPointer findServer(KTextEditor::Document *document, + bool updatedoc = true) = 0; - virtual QSharedPointer - findServer(KTextEditor::View *view, bool updatedoc = true) = 0; + virtual QSharedPointer findServer(KTextEditor::View *view, + bool updatedoc = true) = 0; virtual void update(KTextEditor::Document *doc, bool force) = 0; @@ -74,7 +74,7 @@ public: // lock all relevant documents' current revision and sync that to server // locks are released when returned snapshot is delete'd - virtual LSPClientRevisionSnapshot* snapshot(LSPClientServer *server) = 0; + virtual LSPClientRevisionSnapshot *snapshot(LSPClientServer *server) = 0; public: Q_SIGNALS: @@ -87,7 +87,8 @@ class LSPClientRevisionSnapshot : public QObject public: // find a locked revision for url in snapshot - virtual void find(const QUrl & url, KTextEditor::MovingInterface* & miface, qint64 & revision) const = 0; + virtual void find(const QUrl &url, KTextEditor::MovingInterface *&miface, + qint64 &revision) const = 0; }; #endif diff --git a/addons/lspclient/lspclientsymbolview.cpp b/addons/lspclient/lspclientsymbolview.cpp index 9fe236d32..020f0cd7e 100644 --- a/addons/lspclient/lspclientsymbolview.cpp +++ b/addons/lspclient/lspclientsymbolview.cpp @@ -58,16 +58,17 @@ class LSPClientViewTrackerImpl : public LSPClientViewTracker int m_oldCursorLine = -1; public: - LSPClientViewTrackerImpl(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin, int change_ms, int motion_ms) + LSPClientViewTrackerImpl(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin, + int change_ms, int motion_ms) : m_plugin(plugin), m_mainWindow(mainWin), m_change(change_ms), m_motion(motion_ms) { // get updated m_changeTimer.setSingleShot(true); - auto ch = [this] () { emit newState(m_mainWindow->activeView(), TextChanged); }; + auto ch = [this]() { emit newState(m_mainWindow->activeView(), TextChanged); }; connect(&m_changeTimer, &QTimer::timeout, this, ch); m_motionTimer.setSingleShot(true); - auto mh = [this] () { emit newState(m_mainWindow->activeView(), LineChanged); }; + auto mh = [this]() { emit newState(m_mainWindow->activeView(), LineChanged); }; connect(&m_motionTimer, &QTimer::timeout, this, mh); // track views @@ -81,10 +82,12 @@ public: if (view) { if (m_motion) { - connect(view, &KTextEditor::View::cursorPositionChanged, this, &self_type::cursorPositionChanged, Qt::UniqueConnection); + connect(view, &KTextEditor::View::cursorPositionChanged, this, + &self_type::cursorPositionChanged, Qt::UniqueConnection); } if (m_change > 0 && view->document()) { - connect(view->document(), &KTextEditor::Document::textChanged, this, &self_type::textChanged, Qt::UniqueConnection); + connect(view->document(), &KTextEditor::Document::textChanged, this, + &self_type::textChanged, Qt::UniqueConnection); } emit newState(view, ViewChanged); m_oldCursorLine = view->cursorPosition().line(); @@ -111,9 +114,9 @@ public: } }; -LSPClientViewTracker* -LSPClientViewTracker::new_(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin, - int change_ms, int motion_ms) +LSPClientViewTracker *LSPClientViewTracker::new_(LSPClientPlugin *plugin, + KTextEditor::MainWindow *mainWin, int change_ms, + int motion_ms) { return new LSPClientViewTrackerImpl(plugin, mainWin, change_ms, motion_ms); } @@ -147,8 +150,7 @@ class LSPClientSymbolViewImpl : public QObject, public LSPClientSymbolView // outstanding request LSPClientServer::RequestHandle m_handle; // cached outline models - struct ModelData - { + struct ModelData { KTextEditor::Document *document; qint64 revision; std::shared_ptr model; @@ -170,13 +172,16 @@ class LSPClientSymbolViewImpl : public QObject, public LSPClientSymbolView public: LSPClientSymbolViewImpl(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin, - QSharedPointer manager) - : m_plugin(plugin), m_mainWindow(mainWin), m_serverManager(manager), m_outline(new QStandardItemModel()) + QSharedPointer manager) + : m_plugin(plugin), + m_mainWindow(mainWin), + m_serverManager(manager), + m_outline(new QStandardItemModel()) { - m_toolview.reset(m_mainWindow->createToolView(plugin, QStringLiteral("lspclient_symbol_outline"), - KTextEditor::MainWindow::Right, - QIcon::fromTheme(QStringLiteral("code-context")), - i18n("LSP Client Symbol Outline"))); + m_toolview.reset(m_mainWindow->createToolView( + plugin, QStringLiteral("lspclient_symbol_outline"), KTextEditor::MainWindow::Right, + QIcon::fromTheme(QStringLiteral("code-context")), + i18n("LSP Client Symbol Outline"))); m_symbols = new QTreeView(m_toolview.data()); m_symbols->setFocusPolicy(Qt::NoFocus); @@ -205,7 +210,8 @@ public: m_symbols->setModel(&m_filterModel); delete m; - connect(m_symbols, &QTreeView::customContextMenuRequested, this, &self_type::showContextMenu); + connect(m_symbols, &QTreeView::customContextMenuRequested, this, + &self_type::showContextMenu); connect(m_symbols, &QTreeView::activated, this, &self_type::goToSymbol); connect(m_symbols, &QTreeView::clicked, this, &self_type::goToSymbol); @@ -213,11 +219,14 @@ public: m_popup.reset(new QMenu(m_symbols)); m_treeOn = m_popup->addAction(i18n("Tree Mode"), this, &self_type::displayOptionChanged); m_treeOn->setCheckable(true); - m_expandOn = m_popup->addAction(i18n("Automatically Expand Tree"), this, &self_type::displayOptionChanged); + m_expandOn = m_popup->addAction(i18n("Automatically Expand Tree"), this, + &self_type::displayOptionChanged); m_expandOn->setCheckable(true); - m_sortOn = m_popup->addAction(i18n("Sort Alphabetically"), this, &self_type::displayOptionChanged); + m_sortOn = m_popup->addAction(i18n("Sort Alphabetically"), this, + &self_type::displayOptionChanged); m_sortOn->setCheckable(true); - m_detailsOn = m_popup->addAction(i18n("Show Details"), this, &self_type::displayOptionChanged); + m_detailsOn = + m_popup->addAction(i18n("Show Details"), this, &self_type::displayOptionChanged); m_detailsOn->setCheckable(true); m_popup->addSeparator(); m_popup->addAction(i18n("Expand All"), m_symbols.data(), &QTreeView::expandAll); @@ -228,9 +237,10 @@ public: // get updated m_viewTracker.reset(LSPClientViewTracker::new_(plugin, mainWin, 500, 100)); - connect(m_viewTracker.data(), &LSPClientViewTracker::newState, this, &self_type::onViewState); - connect(m_serverManager.data(), &LSPClientServerManager::serverChanged, - this, [this] () { refresh(false); }); + connect(m_viewTracker.data(), &LSPClientViewTracker::newState, this, + &self_type::onViewState); + connect(m_serverManager.data(), &LSPClientServerManager::serverChanged, this, + [this]() { refresh(false); }); // limit cached models; will not go beyond capacity set here m_models.reserve(MAX_MODELS + 1); @@ -254,14 +264,11 @@ public: displayOptionChanged(); } - void showContextMenu(const QPoint&) - { - m_popup->popup(QCursor::pos(), m_treeOn); - } + void showContextMenu(const QPoint &) { m_popup->popup(QCursor::pos(), m_treeOn); } void onViewState(KTextEditor::View *, LSPClientViewTracker::State newState) { - switch(newState) { + switch (newState) { case LSPClientViewTracker::ViewChanged: refresh(true); break; @@ -274,12 +281,11 @@ public: } } - void makeNodes(const QList & symbols, bool tree, - bool show_detail, QStandardItemModel * model, QStandardItem * parent, - bool &details) + void makeNodes(const QList &symbols, bool tree, bool show_detail, + QStandardItemModel *model, QStandardItem *parent, bool &details) { const QIcon *icon = nullptr; - for (const auto& symbol: symbols) { + for (const auto &symbol : symbols) { switch (symbol.kind) { case LSPSymbolKind::File: case LSPSymbolKind::Module: @@ -316,12 +322,11 @@ public: icon = &m_icon_var; } - auto node = new QStandardItem(); if (parent && tree) - parent->appendRow(node); - else - model->appendRow(node); + parent->appendRow(node); + else + model->appendRow(node); if (!symbol.detail.isEmpty()) details = true; @@ -339,7 +344,8 @@ public: onDocumentSymbolsOrProblem(outline, QString(), true); } - void onDocumentSymbolsOrProblem(const QList &outline, const QString &problem = QString(), bool cache = false) + void onDocumentSymbolsOrProblem(const QList &outline, + const QString &problem = QString(), bool cache = false) { if (!m_symbols) return; @@ -350,7 +356,8 @@ public: // if we have some problem, just report that, else construct model bool details = false; if (problem.isEmpty()) { - makeNodes(outline, m_treeOn->isChecked(), m_detailsOn->isChecked(), newModel.get(), nullptr, details); + makeNodes(outline, m_treeOn->isChecked(), m_detailsOn->isChecked(), newModel.get(), + nullptr, details); if (cache) { // last request has been placed at head of model list Q_ASSERT(!m_models.isEmpty()); @@ -364,7 +371,7 @@ public: newModel->invisibleRootItem()->setData(details); // fixup headers - QStringList headers{i18n("Symbols")}; + QStringList headers { i18n("Symbols") }; newModel->setHorizontalHeaderLabels(headers); setModel(newModel); @@ -436,7 +443,7 @@ public: if (it != m_models.end()) { // move to most recently used head m_models.move(it - m_models.begin(), 0); - auto& model = m_models.front(); + auto &model = m_models.front(); // re-use if possible if (revision == model.revision && model.model) { setModel(model.model); @@ -444,7 +451,7 @@ public: } it->revision = revision; } else { - m_models.insert(0, {doc, revision, nullptr}); + m_models.insert(0, { doc, revision, nullptr }); if (m_models.size() > MAX_MODELS) { m_models.pop_back(); } @@ -457,14 +464,16 @@ public: } // else: inform that no server is there - onDocumentSymbolsOrProblem(QList(), i18n("No LSP server for this document.")); + onDocumentSymbolsOrProblem(QList(), + i18n("No LSP server for this document.")); } - QStandardItem* getCurrentItem(QStandardItem * item, int line) + QStandardItem *getCurrentItem(QStandardItem *item, int line) { // first traverse the child items to have deepest match! // only do this if our stuff is expanded - if (item == m_outline->invisibleRootItem() || m_symbols->isExpanded(m_filterModel.mapFromSource(m_outline->indexFromItem(item)))) { + if (item == m_outline->invisibleRootItem() + || m_symbols->isExpanded(m_filterModel.mapFromSource(m_outline->indexFromItem(item)))) { for (int i = 0; i < item->rowCount(); i++) { if (auto citem = getCurrentItem(item->child(i), line)) { return citem; @@ -473,12 +482,13 @@ public: } // does the line match our item? - return item->data(Qt::UserRole).value().overlapsLine(line) ? item : nullptr; + return item->data(Qt::UserRole).value().overlapsLine(line) ? item + : nullptr; } void updateCurrentTreeItem() { - KTextEditor::View* editView = m_mainWindow->activeView(); + KTextEditor::View *editView = m_mainWindow->activeView(); if (!editView || !m_symbols) { return; } @@ -486,7 +496,8 @@ public: /** * get item if any */ - QStandardItem *item = getCurrentItem(m_outline->invisibleRootItem(), editView->cursorPositionVirtual().line()); + QStandardItem *item = getCurrentItem(m_outline->invisibleRootItem(), + editView->cursorPositionVirtual().line()); if (!item) { return; } @@ -496,16 +507,17 @@ public: */ QModelIndex index = m_filterModel.mapFromSource(m_outline->indexFromItem(item)); m_symbols->scrollTo(index); - m_symbols->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Clear | QItemSelectionModel::Select); + m_symbols->selectionModel()->setCurrentIndex( + index, QItemSelectionModel::Clear | QItemSelectionModel::Select); } void goToSymbol(const QModelIndex &index) { - KTextEditor::View *kv = m_mainWindow->activeView(); - const auto range = index.data(Qt::UserRole).value(); - if (kv && range.isValid()) { - kv->setCursorPosition(range.start()); - } + KTextEditor::View *kv = m_mainWindow->activeView(); + const auto range = index.data(Qt::UserRole).value(); + if (kv && range.isValid()) { + kv->setCursorPosition(range.start()); + } } private Q_SLOTS: @@ -533,10 +545,8 @@ private Q_SLOTS: } }; - -QObject* -LSPClientSymbolView::new_(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin, - QSharedPointer manager) +QObject *LSPClientSymbolView::new_(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin, + QSharedPointer manager) { return new LSPClientSymbolViewImpl(plugin, mainWin, manager); } diff --git a/addons/lspclient/lspclientsymbolview.h b/addons/lspclient/lspclientsymbolview.h index 515c801fa..33a8e6290 100644 --- a/addons/lspclient/lspclientsymbolview.h +++ b/addons/lspclient/lspclientsymbolview.h @@ -35,9 +35,8 @@ class LSPClientSymbolView { public: // only needs a factory; no other public interface - static QObject* - new_(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin, - QSharedPointer manager); + static QObject *new_(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin, + QSharedPointer manager); }; class LSPClientViewTracker : public QObject @@ -45,9 +44,8 @@ class LSPClientViewTracker : public QObject Q_OBJECT public: // factory method; private implementation by interface - static LSPClientViewTracker* - new_(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin, - int change_ms, int motion_ms); + static LSPClientViewTracker *new_(LSPClientPlugin *plugin, KTextEditor::MainWindow *mainWin, + int change_ms, int motion_ms); enum State { ViewChanged, -- 2.24.1