diff options
author | Alexis Murzeau <amubtdx@gmail.com> | 2020-05-09 02:51:19 +0200 |
---|---|---|
committer | Alexis Murzeau <amubtdx@gmail.com> | 2020-05-11 22:33:45 +0000 |
commit | 3268e5f0bcab8a176100be30ba746c74cad55e44 (patch) | |
tree | 7d9a742c6a4efeff7c66d8e9407c005cabb041cb /src/plugins/languageclient | |
parent | 5868e15c3008cdeb44862225aec34322d9fadc04 (diff) |
LSP: Add setting to provide initializationOptions to the language server
When the language server is initialized, the Initialize request can contain
user provided data in initializationOptions field.
Allow the user to set data inside. This can be required to let the
language server have some context.
Change-Id: Ib057fdb940c21b3fd032853fb84253d42ad1e321
Reviewed-by: David Schulz <david.schulz@qt.io>
Diffstat (limited to 'src/plugins/languageclient')
-rw-r--r-- | src/plugins/languageclient/client.cpp | 9 | ||||
-rw-r--r-- | src/plugins/languageclient/client.h | 2 | ||||
-rw-r--r-- | src/plugins/languageclient/languageclientsettings.cpp | 48 | ||||
-rw-r--r-- | src/plugins/languageclient/languageclientsettings.h | 7 |
4 files changed, 65 insertions, 1 deletions
diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index e49444661a..ebb4b0802a 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -250,6 +250,7 @@ void Client::initialize() InitializeRequest initRequest; auto params = initRequest.params().value_or(InitializeParams()); params.setCapabilities(generateClientCapabilities()); + params.setInitializationOptions(m_initializationOptions); if (m_project) { params.setRootUri(DocumentUri::fromFilePath(m_project->projectDirectory())); params.setWorkSpaceFolders(Utils::transform(SessionManager::projects(), [](Project *pro){ @@ -879,6 +880,11 @@ void Client::setSupportedLanguage(const LanguageFilter &filter) m_languagFilter = filter; } +void Client::setInitializationOptions(const QJsonObject &initializationOptions) +{ + m_initializationOptions = initializationOptions; +} + bool Client::isSupportedDocument(const TextEditor::TextDocument *document) const { QTC_ASSERT(document, return false); @@ -900,7 +906,8 @@ bool Client::needsRestart(const BaseSettings *settings) const { QTC_ASSERT(settings, return false); return m_languagFilter.mimeTypes != settings->m_languageFilter.mimeTypes - || m_languagFilter.filePattern != settings->m_languageFilter.filePattern; + || m_languagFilter.filePattern != settings->m_languageFilter.filePattern + || m_initializationOptions != settings->initializationOptions(); } QList<Diagnostic> Client::diagnosticsAt(const DocumentUri &uri, const Range &range) const diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h index b2a91307f1..2b75602817 100644 --- a/src/plugins/languageclient/client.h +++ b/src/plugins/languageclient/client.h @@ -136,6 +136,7 @@ public: void cancelRequest(const LanguageServerProtocol::MessageId &id); void setSupportedLanguage(const LanguageFilter &filter); + void setInitializationOptions(const QJsonObject& initializationOptions); bool isSupportedDocument(const TextEditor::TextDocument *document) const; bool isSupportedFile(const Utils::FilePath &filePath, const QString &mimeType) const; bool isSupportedUri(const LanguageServerProtocol::DocumentUri &uri) const; @@ -210,6 +211,7 @@ private: QHash<QByteArray, ContentHandler> m_contentHandler; QString m_displayName; LanguageFilter m_languagFilter; + QJsonObject m_initializationOptions; QMap<TextEditor::TextDocument *, QString> m_openedDocument; Core::Id m_id; LanguageServerProtocol::ServerCapabilities m_serverCapabilities; diff --git a/src/plugins/languageclient/languageclientsettings.cpp b/src/plugins/languageclient/languageclientsettings.cpp index 75cff18668..decbfdca76 100644 --- a/src/plugins/languageclient/languageclientsettings.cpp +++ b/src/plugins/languageclient/languageclientsettings.cpp @@ -52,6 +52,7 @@ #include <QDir> #include <QFileInfo> #include <QHeaderView> +#include <QJsonDocument> #include <QLabel> #include <QListView> #include <QMimeData> @@ -68,6 +69,7 @@ constexpr char enabledKey[] = "enabled"; constexpr char startupBehaviorKey[] = "startupBehavior"; constexpr char mimeTypeKey[] = "mimeType"; constexpr char filePatternKey[] = "filePattern"; +constexpr char initializationOptionsKey[] = "initializationOptions"; constexpr char executableKey[] = "executable"; constexpr char argumentsKey[] = "arguments"; constexpr char settingsGroupKey[] = "LanguageClient"; @@ -465,12 +467,19 @@ QModelIndex LanguageClientSettingsModel::indexForSetting(BaseSettings *setting) return index < 0 ? QModelIndex() : createIndex(index, 0, setting); } +QJsonObject BaseSettings::initializationOptions() const +{ + return QJsonDocument::fromJson(Utils::globalMacroExpander()-> + expand(m_initializationOptions).toUtf8()).object(); +} + void BaseSettings::applyFromSettingsWidget(QWidget *widget) { if (auto settingsWidget = qobject_cast<BaseSettingsWidget *>(widget)) { m_name = settingsWidget->name(); m_languageFilter = settingsWidget->filter(); m_startBehavior = settingsWidget->startupBehavior(); + m_initializationOptions = settingsWidget->initializationOptions(); } } @@ -505,6 +514,7 @@ Client *BaseSettings::createClient() auto *client = new Client(interface); client->setName(Utils::globalMacroExpander()->expand(m_name)); client->setSupportedLanguage(m_languageFilter); + client->setInitializationOptions(initializationOptions()); return client; } @@ -517,6 +527,7 @@ QVariantMap BaseSettings::toMap() const map.insert(startupBehaviorKey, m_startBehavior); map.insert(mimeTypeKey, m_languageFilter.mimeTypes); map.insert(filePatternKey, m_languageFilter.filePattern); + map.insert(initializationOptionsKey, m_initializationOptions); return map; } @@ -530,6 +541,7 @@ void BaseSettings::fromMap(const QVariantMap &map) m_languageFilter.mimeTypes = map[mimeTypeKey].toStringList(); m_languageFilter.filePattern = map[filePatternKey].toStringList(); m_languageFilter.filePattern.removeAll({}); // remove empty entries + m_initializationOptions = map[initializationOptionsKey].toString(); } static LanguageClientSettingsPage &settingsPage() @@ -706,13 +718,16 @@ BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *pa , m_mimeTypes(new QLabel(settings->m_languageFilter.mimeTypes.join(filterSeparator), this)) , m_filePattern(new QLineEdit(settings->m_languageFilter.filePattern.join(filterSeparator), this)) , m_startupBehavior(new QComboBox) + , m_initializationOptions(new Utils::FancyLineEdit(this)) { int row = 0; auto *mainLayout = new QGridLayout; + mainLayout->addWidget(new QLabel(tr("Name:")), row, 0); mainLayout->addWidget(m_name, row, 1); auto chooser = new Core::VariableChooser(this); chooser->addSupportedWidget(m_name); + mainLayout->addWidget(new QLabel(tr("Language:")), ++row, 0); auto mimeLayout = new QHBoxLayout; mimeLayout->addWidget(m_mimeTypes); @@ -722,6 +737,7 @@ BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *pa mainLayout->addLayout(mimeLayout, row, 1); m_filePattern->setPlaceholderText(tr("File pattern")); mainLayout->addWidget(m_filePattern, ++row, 1); + mainLayout->addWidget(new QLabel(tr("Startup behavior:")), ++row, 0); for (int behavior = 0; behavior < BaseSettings::LastSentinel ; ++behavior) m_startupBehavior->addItem(startupBehaviorString(BaseSettings::StartBehavior(behavior))); @@ -757,6 +773,33 @@ BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *pa mainLayout->addWidget(createCapabilitiesView(QJsonValue(capabilities)), row, 1); }); } + + mainLayout->addWidget(new QLabel(tr("Initialization options:")), ++row, 0); + mainLayout->addWidget(m_initializationOptions, row, 1); + chooser->addSupportedWidget(m_initializationOptions); + m_initializationOptions->setValidationFunction([](Utils::FancyLineEdit *edit, QString *errorMessage) { + const QString value = Utils::globalMacroExpander()->expand(edit->text()); + + if (value.isEmpty()) + return true; + + QJsonParseError parseInfo; + const QJsonDocument json = QJsonDocument::fromJson(value.toUtf8(), &parseInfo); + + if (json.isNull()) { + if (errorMessage) + *errorMessage = tr("Failed to parse JSON at %1: %2") + .arg(parseInfo.offset) + .arg(parseInfo.errorString()); + return false; + } + return true; + }); + m_initializationOptions->setText(settings->m_initializationOptions); + m_initializationOptions->setPlaceholderText(tr("Language server-specific JSON to pass via " + "\"initializationOptions\" field of \"initialize\" " + "request.")); + setLayout(mainLayout); } @@ -776,6 +819,11 @@ BaseSettings::StartBehavior BaseSettingsWidget::startupBehavior() const return BaseSettings::StartBehavior(m_startupBehavior->currentIndex()); } +QString BaseSettingsWidget::initializationOptions() const +{ + return m_initializationOptions->text(); +} + class MimeTypeModel : public QStringListModel { public: diff --git a/src/plugins/languageclient/languageclientsettings.h b/src/plugins/languageclient/languageclientsettings.h index 579a2e36e9..6e7b5589ef 100644 --- a/src/plugins/languageclient/languageclientsettings.h +++ b/src/plugins/languageclient/languageclientsettings.h @@ -32,6 +32,7 @@ #include <utils/fileutils.h> #include <QAbstractItemModel> +#include <QJsonObject> #include <QLabel> #include <QPointer> #include <QUuid> @@ -45,6 +46,7 @@ QT_END_NAMESPACE namespace Utils { class FilePath; class PathChooser; +class FancyLineEdit; } // namespace Utils namespace Core { class IDocument; } @@ -82,6 +84,9 @@ public: bool m_enabled = true; StartBehavior m_startBehavior = RequiresFile; LanguageFilter m_languageFilter; + QString m_initializationOptions; + + QJsonObject initializationOptions() const; virtual void applyFromSettingsWidget(QWidget *widget); virtual QWidget *createSettingsWidget(QWidget *parent = nullptr) const; @@ -155,6 +160,7 @@ public: BaseSettings::StartBehavior startupBehavior() const; bool alwaysOn() const; bool requiresProject() const; + QString initializationOptions() const; private: void showAddMimeTypeDialog(); @@ -163,6 +169,7 @@ private: QLabel *m_mimeTypes = nullptr; QLineEdit *m_filePattern = nullptr; QComboBox *m_startupBehavior = nullptr; + Utils::FancyLineEdit *m_initializationOptions = nullptr; static constexpr char filterSeparator = ';'; }; |