diff --git a/src/plugins/android/CMakeLists.txt b/src/plugins/android/CMakeLists.txt index a65936c1197..2759888b03d 100644 --- a/src/plugins/android/CMakeLists.txt +++ b/src/plugins/android/CMakeLists.txt @@ -1,6 +1,6 @@ add_qtc_plugin(Android DEPENDS QtcSsh QmlDebug Qt5::Xml - PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport + PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport LanguageClient SOURCES adbcommandswidget.cpp adbcommandswidget.h adbcommandswidget.ui addnewavddialog.ui @@ -48,6 +48,7 @@ add_qtc_plugin(Android createandroidmanifestwizard.cpp createandroidmanifestwizard.h javaeditor.cpp javaeditor.h javaindenter.cpp javaindenter.h + javalanguageserver.cpp javalanguageserver.h javaparser.cpp javaparser.h splashscreencontainerwidget.cpp splashscreencontainerwidget.h splashscreenwidget.cpp splashscreenwidget.h diff --git a/src/plugins/android/android.pro b/src/plugins/android/android.pro index f5f550a9900..701194791c2 100644 --- a/src/plugins/android/android.pro +++ b/src/plugins/android/android.pro @@ -53,7 +53,8 @@ HEADERS += \ createandroidmanifestwizard.h \ androidsdkdownloader.h \ splashscreencontainerwidget.h \ - splashscreenwidget.h + splashscreenwidget.h \ + javalanguageserver.h \ SOURCES += \ androidconfigurations.cpp \ @@ -99,7 +100,8 @@ SOURCES += \ createandroidmanifestwizard.cpp \ androidsdkdownloader.cpp \ splashscreencontainerwidget.cpp \ - splashscreenwidget.cpp + splashscreenwidget.cpp \ + javalanguageserver.cpp \ FORMS += \ androidsettingswidget.ui \ diff --git a/src/plugins/android/android.qbs b/src/plugins/android/android.qbs index 02e0b1b1791..2cd4722b24b 100644 --- a/src/plugins/android/android.qbs +++ b/src/plugins/android/android.qbs @@ -7,6 +7,7 @@ Project { Depends { name: "Qt"; submodules: ["widgets", "xml", "network"] } Depends { name: "Core" } Depends { name: "Debugger" } + Depends { name: "LanguageClient" } Depends { name: "ProParser" } Depends { name: "ProjectExplorer" } Depends { name: "QmlDebug" } @@ -109,6 +110,8 @@ Project { "javaeditor.h", "javaindenter.cpp", "javaindenter.h", + "javalanguageserver.cpp", + "javalanguageserver.h", "javaparser.cpp", "javaparser.h", "splashscreencontainerwidget.cpp", diff --git a/src/plugins/android/android_dependencies.pri b/src/plugins/android/android_dependencies.pri index f471fb4fe91..c0bd7fe84e7 100644 --- a/src/plugins/android/android_dependencies.pri +++ b/src/plugins/android/android_dependencies.pri @@ -4,7 +4,8 @@ QTC_PLUGIN_DEPENDS += \ debugger \ projectexplorer \ qtsupport \ - texteditor + texteditor \ + languageclient QTC_LIB_DEPENDS += \ extensionsystem \ diff --git a/src/plugins/android/androidconstants.h b/src/plugins/android/androidconstants.h index f5d8857f39a..5dd62d743ab 100644 --- a/src/plugins/android/androidconstants.h +++ b/src/plugins/android/androidconstants.h @@ -60,6 +60,7 @@ const char ANDROID_KIT_SDK[] = "Android.SDK"; const char ANDROID_BUILDDIRECTORY[] = "android-build"; const char JAVA_EDITOR_ID[] = "java.editor"; +const char JLS_SETTINGS_ID[] = "Java::JLSSettingsID"; const char JAVA_MIMETYPE[] = "text/x-java"; const char ANDROID_ARCHITECTURE[] = "Android.Architecture"; const char ANDROID_PACKAGE_SOURCE_DIR[] = "ANDROID_PACKAGE_SOURCE_DIR"; diff --git a/src/plugins/android/androidplugin.cpp b/src/plugins/android/androidplugin.cpp index 4156965b93b..f135b427a16 100644 --- a/src/plugins/android/androidplugin.cpp +++ b/src/plugins/android/androidplugin.cpp @@ -41,6 +41,7 @@ #include "androidsettingswidget.h" #include "androidtoolchain.h" #include "javaeditor.h" +#include "javalanguageserver.h" #ifdef HAVE_QBS # include "androidqbspropertyprovider.h" @@ -50,6 +51,8 @@ #include #include +#include + #include #include #include @@ -162,6 +165,10 @@ bool AndroidPlugin::initialize(const QStringList &arguments, QString *errorMessa connect(KitManager::instance(), &KitManager::kitsLoaded, this, &AndroidPlugin::kitsRestored); + LanguageClient::LanguageClientSettings::registerClientType({Android::Constants::JLS_SETTINGS_ID, + tr("Java Language Server"), + []() { return new JLSSettings; }}); + return true; } diff --git a/src/plugins/android/javalanguageserver.cpp b/src/plugins/android/javalanguageserver.cpp new file mode 100644 index 00000000000..60ead987446 --- /dev/null +++ b/src/plugins/android/javalanguageserver.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "javalanguageserver.h" + +#include "androidconstants.h" + +#include +#include +#include + +#include +#include + +using namespace Utils; + +constexpr char languageServerKey[] = "languageServer"; +constexpr char workspaceKey[] = "workspace"; + +namespace Android { +namespace Internal { + +class JLSSettingsWidget : public QWidget +{ + Q_DECLARE_TR_FUNCTIONS(JLSSettingsWidget) +public: + JLSSettingsWidget(const JLSSettings *settings, QWidget *parent); + + QString name() const { return m_name->text(); } + QString java() const { return m_java->filePath().toString(); } + QString languageServer() const { return m_ls->filePath().toString(); } + QString workspace() const { return m_workspace->filePath().toString(); } + +private: + QLineEdit *m_name = nullptr; + PathChooser *m_java = nullptr; + PathChooser *m_ls = nullptr; + PathChooser *m_workspace = nullptr; +}; + +JLSSettingsWidget::JLSSettingsWidget(const JLSSettings *settings, QWidget *parent) + : QWidget(parent) + , m_name(new QLineEdit(settings->m_name, this)) + , m_java(new PathChooser(this)) + , m_ls(new PathChooser(this)) + , m_workspace(new PathChooser(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 VariableChooser(this); + chooser->addSupportedWidget(m_name); + + mainLayout->addWidget(new QLabel(tr("Java:")), ++row, 0); + m_java->setExpectedKind(Utils::PathChooser::ExistingCommand); + m_java->setPath(QDir::toNativeSeparators(settings->m_executable)); + mainLayout->addWidget(m_java, row, 1); + + mainLayout->addWidget(new QLabel(tr("Java Language Server:")), ++row, 0); + m_ls->setExpectedKind(Utils::PathChooser::File); + m_ls->lineEdit()->setPlaceholderText(tr("Path to equinox launcher jar")); + m_ls->setPromptDialogFilter("org.eclipse.equinox.launcher_*.jar"); + m_ls->setPath(QDir::toNativeSeparators(settings->m_languageServer)); + mainLayout->addWidget(m_ls, row, 1); + + mainLayout->addWidget(new QLabel(tr("Workspace:")), ++row, 0); + m_workspace->setExpectedKind(Utils::PathChooser::Directory); + m_workspace->setPath(QDir::toNativeSeparators(settings->m_workspace)); + mainLayout->addWidget(m_workspace, row, 1); + + setLayout(mainLayout); +} + +JLSSettings::JLSSettings() +{ + m_settingsTypeId = Constants::JLS_SETTINGS_ID; + m_name = "Java Language Server"; + m_startBehavior = RequiresProject; + m_languageFilter.mimeTypes = QStringList(Constants::JAVA_MIMETYPE); + const FilePath &javaPath = Utils::Environment::systemEnvironment().searchInPath("java"); + if (javaPath.exists()) + m_executable = javaPath.toString(); +} + +bool JLSSettings::applyFromSettingsWidget(QWidget *widget) +{ + bool changed = false; + auto jlswidget = static_cast(widget); + changed |= m_name != jlswidget->name(); + m_name = jlswidget->name(); + + changed |= m_languageServer != jlswidget->languageServer(); + m_languageServer = jlswidget->languageServer(); + + changed |= m_workspace != jlswidget->workspace(); + m_workspace = jlswidget->workspace(); + + changed |= m_executable != jlswidget->java(); + m_executable = jlswidget->java(); + + QString arguments = "-Declipse.application=org.eclipse.jdt.ls.core.id1 " + "-Dosgi.bundles.defaultStartLevel=4 " + "-Declipse.product=org.eclipse.jdt.ls.core.product " + "-Dlog.level=WARNING " + "-noverify " + "-Xmx1G " + "-jar \"%1\" " + "-configuration \"%2\" " + "-data \"%3\""; + + QFileInfo languageServerFileInfo(m_languageServer); + QDir configDir = languageServerFileInfo.absoluteDir(); + if (configDir.exists()) { + configDir.cdUp(); + if constexpr (HostOsInfo::hostOs() == OsTypeWindows) + configDir.cd("config_win"); + else if constexpr (HostOsInfo::hostOs() == OsTypeLinux) + configDir.cd("config_linux"); + else if constexpr (HostOsInfo::hostOs() == OsTypeMac) + configDir.cd("config_mac"); + } + if (configDir.exists()) { + arguments = arguments.arg(m_languageServer, configDir.absolutePath(), m_workspace); + changed |= m_arguments != arguments; + m_arguments = arguments; + } + return changed; +} + +QWidget *JLSSettings::createSettingsWidget(QWidget *parent) const +{ + return new JLSSettingsWidget(this, parent); +} + +bool JLSSettings::isValid() const +{ + return StdIOSettings::isValid() && !m_languageServer.isEmpty() && !m_workspace.isEmpty(); +} + +QVariantMap JLSSettings::toMap() const +{ + QVariantMap map = StdIOSettings::toMap(); + map.insert(languageServerKey, m_languageServer); + map.insert(workspaceKey, m_workspace); + return map; +} + +void JLSSettings::fromMap(const QVariantMap &map) +{ + StdIOSettings::fromMap(map); + m_languageServer = map[languageServerKey].toString(); + m_workspace = map[workspaceKey].toString(); +} + +LanguageClient::BaseSettings *JLSSettings::copy() const +{ + return new JLSSettings(*this); +} + +} // namespace Internal +} // namespace Android diff --git a/src/plugins/android/javalanguageserver.h b/src/plugins/android/javalanguageserver.h new file mode 100644 index 00000000000..ac2179db84a --- /dev/null +++ b/src/plugins/android/javalanguageserver.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +namespace Android { +namespace Internal { + +class JLSSettings final : public LanguageClient::StdIOSettings +{ +public: + JLSSettings(); + + bool applyFromSettingsWidget(QWidget *widget) final; + QWidget *createSettingsWidget(QWidget *parent) const final; + bool isValid() const final; + QVariantMap toMap() const final; + void fromMap(const QVariantMap &map) final; + LanguageClient::BaseSettings *copy() const final; + + QString m_languageServer; + QString m_workspace; + +private: + JLSSettings(const JLSSettings &other) = default; +}; + +} // namespace Internal +} // namespace Android