forked from qt-creator/qt-creator
QbsProjectManager: Add a language client
... and use it to follow symbols that QmlJSEditor does not know about. For now, the only implemented case on the server side is getting to a product or module via a Depends item. More functionality will follow. Change-Id: I597c7ab10f4bf6962684ed26357dfc0eef3a6c15 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -2,7 +2,7 @@ add_qtc_plugin(QbsProjectManager
|
|||||||
DEPENDS Qt::Qml Qt::Widgets QmlJS
|
DEPENDS Qt::Qml Qt::Widgets QmlJS
|
||||||
DEFINES
|
DEFINES
|
||||||
IDE_LIBRARY_BASENAME="${IDE_LIBRARY_BASE_PATH}"
|
IDE_LIBRARY_BASENAME="${IDE_LIBRARY_BASE_PATH}"
|
||||||
PLUGIN_DEPENDS Core ProjectExplorer CppEditor QtSupport QmlJSTools
|
PLUGIN_DEPENDS Core CppEditor LanguageClient ProjectExplorer QmlJSTools QmlJSEditor QtSupport
|
||||||
SOURCES
|
SOURCES
|
||||||
customqbspropertiesdialog.cpp customqbspropertiesdialog.h
|
customqbspropertiesdialog.cpp customqbspropertiesdialog.h
|
||||||
defaultpropertyprovider.cpp defaultpropertyprovider.h
|
defaultpropertyprovider.cpp defaultpropertyprovider.h
|
||||||
@@ -10,8 +10,10 @@ add_qtc_plugin(QbsProjectManager
|
|||||||
qbsbuildconfiguration.cpp qbsbuildconfiguration.h
|
qbsbuildconfiguration.cpp qbsbuildconfiguration.h
|
||||||
qbsbuildstep.cpp qbsbuildstep.h
|
qbsbuildstep.cpp qbsbuildstep.h
|
||||||
qbscleanstep.cpp qbscleanstep.h
|
qbscleanstep.cpp qbscleanstep.h
|
||||||
|
qbseditor.cpp qbseditor.h
|
||||||
qbsinstallstep.cpp qbsinstallstep.h
|
qbsinstallstep.cpp qbsinstallstep.h
|
||||||
qbskitaspect.cpp qbskitaspect.h
|
qbskitaspect.cpp qbskitaspect.h
|
||||||
|
qbslanguageclient.cpp qbslanguageclient.h
|
||||||
qbsnodes.cpp qbsnodes.h
|
qbsnodes.cpp qbsnodes.h
|
||||||
qbsnodetreebuilder.cpp qbsnodetreebuilder.h
|
qbsnodetreebuilder.cpp qbsnodetreebuilder.h
|
||||||
qbspmlogging.cpp qbspmlogging.h
|
qbspmlogging.cpp qbspmlogging.h
|
||||||
|
|||||||
60
src/plugins/qbsprojectmanager/qbseditor.cpp
Normal file
60
src/plugins/qbsprojectmanager/qbseditor.cpp
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "qbseditor.h"
|
||||||
|
|
||||||
|
#include "qbslanguageclient.h"
|
||||||
|
#include "qbsprojectmanagertr.h"
|
||||||
|
|
||||||
|
#include <languageclient/languageclientmanager.h>
|
||||||
|
#include <utils/mimeconstants.h>
|
||||||
|
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
|
using namespace LanguageClient;
|
||||||
|
using namespace QmlJSEditor;
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
|
namespace QbsProjectManager::Internal {
|
||||||
|
|
||||||
|
class QbsEditorWidget : public QmlJSEditorWidget
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void findLinkAt(const QTextCursor &cursor,
|
||||||
|
const LinkHandler &processLinkCallback,
|
||||||
|
bool resolveTarget = true,
|
||||||
|
bool inNextSplit = false) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
QbsEditorFactory::QbsEditorFactory() : QmlJSEditorFactory("QbsEditor.QbsEditor")
|
||||||
|
{
|
||||||
|
setDisplayName(Tr::tr("Qbs Editor"));
|
||||||
|
setMimeTypes({Utils::Constants::QBS_MIMETYPE});
|
||||||
|
setEditorWidgetCreator([] { return new QbsEditorWidget; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void QbsEditorWidget::findLinkAt(const QTextCursor &cursor, const LinkHandler &processLinkCallback,
|
||||||
|
bool resolveTarget, bool inNextSplit)
|
||||||
|
{
|
||||||
|
const LinkHandler extendedCallback = [self = QPointer(this), cursor, processLinkCallback,
|
||||||
|
resolveTarget](const Link &link) {
|
||||||
|
if (link.hasValidTarget())
|
||||||
|
return processLinkCallback(link);
|
||||||
|
if (!self)
|
||||||
|
return;
|
||||||
|
const auto doc = self->textDocument();
|
||||||
|
if (!doc)
|
||||||
|
return;
|
||||||
|
const QList<Client *> &candidates = LanguageClientManager::clientsSupportingDocument(doc);
|
||||||
|
for (Client * const candidate : candidates) {
|
||||||
|
const auto qbsClient = qobject_cast<QbsLanguageClient *>(candidate);
|
||||||
|
if (!qbsClient || !qbsClient->isActive() || !qbsClient->documentOpen(doc))
|
||||||
|
continue;
|
||||||
|
qbsClient->findLinkAt(doc, cursor, processLinkCallback, resolveTarget,
|
||||||
|
LinkTarget::SymbolDef);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
QmlJSEditorWidget::findLinkAt(cursor, extendedCallback, resolveTarget, inNextSplit);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QbsProjectManager::Internal
|
||||||
16
src/plugins/qbsprojectmanager/qbseditor.h
Normal file
16
src/plugins/qbsprojectmanager/qbseditor.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <qmljseditor/qmljseditor.h>
|
||||||
|
|
||||||
|
namespace QbsProjectManager::Internal {
|
||||||
|
|
||||||
|
class QbsEditorFactory : public QmlJSEditor::QmlJSEditorFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QbsEditorFactory();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QbsProjectManager::Internal
|
||||||
90
src/plugins/qbsprojectmanager/qbslanguageclient.cpp
Normal file
90
src/plugins/qbsprojectmanager/qbslanguageclient.cpp
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "qbslanguageclient.h"
|
||||||
|
|
||||||
|
#include "qbsproject.h"
|
||||||
|
#include "qbssettings.h"
|
||||||
|
|
||||||
|
#include <coreplugin/editormanager/documentmodel.h>
|
||||||
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
|
#include <languageclient/languageclientinterface.h>
|
||||||
|
#include <languageclient/languageclientsettings.h>
|
||||||
|
#include <projectexplorer/buildconfiguration.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <utils/filepath.h>
|
||||||
|
#include <utils/mimeconstants.h>
|
||||||
|
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
|
using namespace Core;
|
||||||
|
using namespace LanguageClient;
|
||||||
|
using namespace TextEditor;
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
|
namespace QbsProjectManager::Internal {
|
||||||
|
|
||||||
|
class QbsLanguageClientInterface : public LocalSocketClientInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QbsLanguageClientInterface(const QString &serverPath)
|
||||||
|
: LocalSocketClientInterface(serverPath),
|
||||||
|
m_qbsExecutable(QbsSettings::qbsExecutableFilePath()) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Utils::FilePath serverDeviceTemplate() const override{ return m_qbsExecutable; };
|
||||||
|
|
||||||
|
const FilePath m_qbsExecutable;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QbsLanguageClient::Private
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Private(QbsLanguageClient * q) : q(q) {}
|
||||||
|
|
||||||
|
void checkDocument(IDocument *document);
|
||||||
|
|
||||||
|
QbsLanguageClient * const q;
|
||||||
|
QPointer<QbsBuildSystem> buildSystem;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
QbsLanguageClient::QbsLanguageClient(const QString &serverPath, QbsBuildSystem *buildSystem)
|
||||||
|
: Client(new QbsLanguageClientInterface(serverPath)), d(new Private(this))
|
||||||
|
{
|
||||||
|
d->buildSystem = buildSystem;
|
||||||
|
setName(QString::fromLatin1("qbs@%1").arg(serverPath));
|
||||||
|
setCurrentProject(buildSystem->project());
|
||||||
|
LanguageFilter langFilter;
|
||||||
|
langFilter.mimeTypes << Utils::Constants::QBS_MIMETYPE;
|
||||||
|
setSupportedLanguage(langFilter);
|
||||||
|
connect(EditorManager::instance(), &EditorManager::documentOpened,
|
||||||
|
this, [this](IDocument *document) { d->checkDocument(document); });
|
||||||
|
const QList<IDocument *> &allDocuments = DocumentModel::openedDocuments();
|
||||||
|
for (IDocument * const document : allDocuments)
|
||||||
|
d->checkDocument(document);
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
QbsLanguageClient::~QbsLanguageClient() { delete d; }
|
||||||
|
|
||||||
|
bool QbsLanguageClient::isActive() const
|
||||||
|
{
|
||||||
|
if (!d->buildSystem)
|
||||||
|
return false;
|
||||||
|
if (!d->buildSystem->target()->activeBuildConfiguration())
|
||||||
|
return false;
|
||||||
|
if (d->buildSystem->target()->activeBuildConfiguration()->buildSystem() != d->buildSystem)
|
||||||
|
return false;
|
||||||
|
if (d->buildSystem->project()->activeTarget() != d->buildSystem->target())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QbsLanguageClient::Private::checkDocument(IDocument *document)
|
||||||
|
{
|
||||||
|
if (const auto doc = qobject_cast<TextDocument *>(document))
|
||||||
|
q->openDocument(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QbsProjectManager::Internal
|
||||||
25
src/plugins/qbsprojectmanager/qbslanguageclient.h
Normal file
25
src/plugins/qbsprojectmanager/qbslanguageclient.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <languageclient/client.h>
|
||||||
|
|
||||||
|
namespace QbsProjectManager::Internal {
|
||||||
|
class QbsBuildSystem;
|
||||||
|
|
||||||
|
class QbsLanguageClient : public LanguageClient::Client
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
QbsLanguageClient(const QString &serverPath, QbsBuildSystem *buildSystem);
|
||||||
|
~QbsLanguageClient() override;
|
||||||
|
|
||||||
|
bool isActive() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Private;
|
||||||
|
Private * const d;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QbsProjectManager::Internal
|
||||||
@@ -11,11 +11,13 @@ QtcPlugin {
|
|||||||
Depends { name: "QmlJS" }
|
Depends { name: "QmlJS" }
|
||||||
Depends { name: "Utils" }
|
Depends { name: "Utils" }
|
||||||
|
|
||||||
Depends { name: "ProjectExplorer" }
|
|
||||||
Depends { name: "Core" }
|
Depends { name: "Core" }
|
||||||
Depends { name: "CppEditor" }
|
Depends { name: "CppEditor" }
|
||||||
Depends { name: "QtSupport" }
|
Depends { name: "LanguageClient" }
|
||||||
|
Depends { name: "ProjectExplorer" }
|
||||||
|
Depends { name: "QmlJSEditor" }
|
||||||
Depends { name: "QmlJSTools" }
|
Depends { name: "QmlJSTools" }
|
||||||
|
Depends { name: "QtSupport" }
|
||||||
|
|
||||||
files: [
|
files: [
|
||||||
"customqbspropertiesdialog.h",
|
"customqbspropertiesdialog.h",
|
||||||
@@ -29,10 +31,14 @@ QtcPlugin {
|
|||||||
"qbsbuildstep.h",
|
"qbsbuildstep.h",
|
||||||
"qbscleanstep.cpp",
|
"qbscleanstep.cpp",
|
||||||
"qbscleanstep.h",
|
"qbscleanstep.h",
|
||||||
|
"qbseditor.cpp",
|
||||||
|
"qbseditor.h",
|
||||||
"qbsinstallstep.cpp",
|
"qbsinstallstep.cpp",
|
||||||
"qbsinstallstep.h",
|
"qbsinstallstep.h",
|
||||||
"qbskitaspect.cpp",
|
"qbskitaspect.cpp",
|
||||||
"qbskitaspect.h",
|
"qbskitaspect.h",
|
||||||
|
"qbslanguageclient.cpp",
|
||||||
|
"qbslanguageclient.h",
|
||||||
"qbsnodes.cpp",
|
"qbsnodes.cpp",
|
||||||
"qbsnodes.h",
|
"qbsnodes.h",
|
||||||
"qbsnodetreebuilder.cpp",
|
"qbsnodetreebuilder.cpp",
|
||||||
@@ -48,7 +54,8 @@ QtcPlugin {
|
|||||||
"qbsprojectimporter.cpp",
|
"qbsprojectimporter.cpp",
|
||||||
"qbsprojectimporter.h",
|
"qbsprojectimporter.h",
|
||||||
"qbsprojectmanager.qrc",
|
"qbsprojectmanager.qrc",
|
||||||
"qbsprojectmanager_global.h", "qbsprojectmanagertr.h",
|
"qbsprojectmanager_global.h",
|
||||||
|
"qbsprojectmanagertr.h",
|
||||||
"qbsprojectmanagerconstants.h",
|
"qbsprojectmanagerconstants.h",
|
||||||
"qbsprojectmanagerplugin.cpp",
|
"qbsprojectmanagerplugin.cpp",
|
||||||
"qbsprojectmanagerplugin.h",
|
"qbsprojectmanagerplugin.h",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "qbsbuildconfiguration.h"
|
#include "qbsbuildconfiguration.h"
|
||||||
#include "qbsbuildstep.h"
|
#include "qbsbuildstep.h"
|
||||||
#include "qbscleanstep.h"
|
#include "qbscleanstep.h"
|
||||||
|
#include "qbseditor.h"
|
||||||
#include "qbsinstallstep.h"
|
#include "qbsinstallstep.h"
|
||||||
#include "qbsnodes.h"
|
#include "qbsnodes.h"
|
||||||
#include "qbsprofilessettingspage.h"
|
#include "qbsprofilessettingspage.h"
|
||||||
@@ -68,6 +69,7 @@ public:
|
|||||||
QbsInstallStepFactory installStepFactory;
|
QbsInstallStepFactory installStepFactory;
|
||||||
QbsSettingsPage settingsPage;
|
QbsSettingsPage settingsPage;
|
||||||
QbsProfilesSettingsPage profilesSetttingsPage;
|
QbsProfilesSettingsPage profilesSetttingsPage;
|
||||||
|
QbsEditorFactory editorFactory;
|
||||||
};
|
};
|
||||||
|
|
||||||
QbsProjectManagerPlugin::~QbsProjectManagerPlugin()
|
QbsProjectManagerPlugin::~QbsProjectManagerPlugin()
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
#include "qbssession.h"
|
#include "qbssession.h"
|
||||||
|
|
||||||
|
#include "qbslanguageclient.h"
|
||||||
#include "qbspmlogging.h"
|
#include "qbspmlogging.h"
|
||||||
|
#include "qbsproject.h"
|
||||||
#include "qbsprojectmanagerconstants.h"
|
#include "qbsprojectmanagerconstants.h"
|
||||||
#include "qbsprojectmanagertr.h"
|
#include "qbsprojectmanagertr.h"
|
||||||
#include "qbssettings.h"
|
#include "qbssettings.h"
|
||||||
@@ -130,6 +132,7 @@ class QbsSession::Private
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Process *qbsProcess = nullptr;
|
Process *qbsProcess = nullptr;
|
||||||
|
QbsLanguageClient *languageClient = nullptr;
|
||||||
PacketReader *packetReader = nullptr;
|
PacketReader *packetReader = nullptr;
|
||||||
QJsonObject currentRequest;
|
QJsonObject currentRequest;
|
||||||
QJsonObject projectData;
|
QJsonObject projectData;
|
||||||
@@ -140,7 +143,7 @@ public:
|
|||||||
State state = State::Inactive;
|
State state = State::Inactive;
|
||||||
};
|
};
|
||||||
|
|
||||||
QbsSession::QbsSession(QObject *parent) : QObject(parent), d(new Private)
|
QbsSession::QbsSession(QbsBuildSystem *buildSystem) : QObject(buildSystem), d(new Private)
|
||||||
{
|
{
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
@@ -449,6 +452,12 @@ void QbsSession::handlePacket(const QJsonObject &packet)
|
|||||||
setError(Error::VersionMismatch);
|
setError(Error::VersionMismatch);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (packet.value("api-level").toInt() > 4) {
|
||||||
|
const QString lspSocket = packet.value("lsp-socket").toString();
|
||||||
|
if (!lspSocket.isEmpty())
|
||||||
|
d->languageClient = new QbsLanguageClient(lspSocket,
|
||||||
|
static_cast<QbsBuildSystem *>(parent()));
|
||||||
|
}
|
||||||
d->state = State::Active;
|
d->state = State::Active;
|
||||||
sendQueuedRequest();
|
sendQueuedRequest();
|
||||||
} else if (type == "project-resolved") {
|
} else if (type == "project-resolved") {
|
||||||
@@ -567,6 +576,7 @@ void QbsSession::setInactive()
|
|||||||
if (d->qbsProcess->state() == QProcess::Running)
|
if (d->qbsProcess->state() == QProcess::Running)
|
||||||
sendQuitPacket();
|
sendQuitPacket();
|
||||||
d->qbsProcess = nullptr;
|
d->qbsProcess = nullptr;
|
||||||
|
d->languageClient = nullptr; // Owned by LanguageClientManager
|
||||||
}
|
}
|
||||||
|
|
||||||
FileChangeResult QbsSession::updateFileList(const char *action, const QStringList &files,
|
FileChangeResult QbsSession::updateFileList(const char *action, const QStringList &files,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ namespace ProjectExplorer { class Target; }
|
|||||||
|
|
||||||
namespace QbsProjectManager {
|
namespace QbsProjectManager {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
class QbsBuildSystem;
|
||||||
|
|
||||||
class ErrorInfoItem
|
class ErrorInfoItem
|
||||||
{
|
{
|
||||||
@@ -96,7 +97,7 @@ class QbsSession : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit QbsSession(QObject *parent = nullptr);
|
explicit QbsSession(QbsBuildSystem *buildSystem);
|
||||||
~QbsSession() override;
|
~QbsSession() override;
|
||||||
|
|
||||||
enum class State { Initializing, Active, Inactive };
|
enum class State { Initializing, Active, Inactive };
|
||||||
|
|||||||
@@ -1134,7 +1134,6 @@ QmlJSEditorFactory::QmlJSEditorFactory(Utils::Id _id)
|
|||||||
using namespace Utils::Constants;
|
using namespace Utils::Constants;
|
||||||
addMimeType(QML_MIMETYPE);
|
addMimeType(QML_MIMETYPE);
|
||||||
addMimeType(QMLPROJECT_MIMETYPE);
|
addMimeType(QMLPROJECT_MIMETYPE);
|
||||||
addMimeType(QBS_MIMETYPE);
|
|
||||||
addMimeType(QMLTYPES_MIMETYPE);
|
addMimeType(QMLTYPES_MIMETYPE);
|
||||||
addMimeType(JS_MIMETYPE);
|
addMimeType(JS_MIMETYPE);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user