Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmllanguageserver.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
9
10#include <QtCore/qdir.h>
11
12#include <iostream>
13#include <algorithm>
14
15QT_BEGIN_NAMESPACE
16
17namespace QmlLsp {
18
19using namespace QLspSpecification;
20using namespace Qt::StringLiterals;
21/*!
22\internal
23\class QmlLsp::QQmlLanguageServer
24\brief Sets up a QmlLanguageServer.
25
26This class sets up a QML language server.
27
28Use the following function to send replies:
29
30\code
31std::function<void(const QByteArray &)> sendData
32\endcode
33
34And, feed the data that the function receives to the \c {server()->receive()}
35method.
36
37Call this method only from a single thread, and do not block. To achieve this,
38avoid direct calls, and connect the method as a slot, while reading from another
39thread.
40
41The various tasks of the language server are divided between
42QLanguageServerModule instances. Each instance is responsible for handling a
43certain subset of client requests. For example, one instance handles completion
44requests, another one updates the code in the code model when the client sends a
45new file version, and so on. The QLanguageServerModule instances are
46constructed and registered with QLanguageServer in the constructor of
47this class.
48
49Generally, do all operations in the object thread and always call handlers from
50it. However, the operations can delegate the response to another thread, as the
51response handler is thread safe. All the methods of the \c server() object are
52also thread safe.
53
54The code model starts other threads to update its state. See its documentation
55for more information.
56*/
57QQmlLanguageServer::QQmlLanguageServer(std::function<void(const QByteArray &)> sendData,
58 QQmlToolingSharedSettings *settings)
59 : m_codeModelManager(nullptr, settings),
60 m_server(sendData),
61 m_textSynchronization(&m_codeModelManager),
62 m_workspace(&m_codeModelManager),
63 m_completionSupport(&m_codeModelManager),
64 m_navigationSupport(&m_codeModelManager),
65 m_definitionSupport(&m_codeModelManager),
66 m_referencesSupport(&m_codeModelManager),
67 m_documentFormatting(&m_codeModelManager),
68 m_renameSupport(&m_codeModelManager),
69 m_rangeFormatting(&m_codeModelManager),
70 m_hover(&m_codeModelManager),
71 m_highlightSupport(&m_codeModelManager),
72 m_documentSymbolSupport(&m_codeModelManager),
73 m_progressSupport(&m_codeModelManager),
74 m_lint(&m_server, &m_codeModelManager)
75{
76 m_server.addServerModule(this);
77 m_server.addServerModule(&m_textSynchronization);
78 m_server.addServerModule(&m_lint);
79 m_server.addServerModule(&m_workspace);
80 m_server.addServerModule(&m_completionSupport);
81 m_server.addServerModule(&m_navigationSupport);
82 m_server.addServerModule(&m_definitionSupport);
83 m_server.addServerModule(&m_referencesSupport);
84 m_server.addServerModule(&m_documentFormatting);
85 m_server.addServerModule(&m_renameSupport);
86 m_server.addServerModule(&m_rangeFormatting);
87 m_server.addServerModule(&m_hover);
88 m_server.addServerModule(&m_documentSymbolSupport);
89 m_server.addServerModule(&m_progressSupport);
90 m_server.addServerModule(&m_highlightSupport);
91 m_server.finishSetup();
92 qCWarning(lspServerLog) << "Did Setup";
93}
94
96{
97 // note: the server modules might be in use by the QQmlCodeModel thread, so wait for the
98 // QQmlCodeModel threads to finish before destroying the server modules.
99 m_codeModelManager.prepareForShutdown();
100}
101
102void QQmlLanguageServer::registerHandlers(QLanguageServer *server,
103 QLanguageServerProtocol *protocol)
104{
105 Q_UNUSED(protocol);
106 QObject::connect(server, &QLanguageServer::lifecycleError, this,
107 &QQmlLanguageServer::errorExit);
108 QObject::connect(server, &QLanguageServer::exit, this, &QQmlLanguageServer::exit);
109 QObject::connect(
110 server, &QLanguageServer::runStatusChanged, this,
111 [](QLanguageServer::RunStatus r) { qCDebug(lspServerLog) << "runStatus" << int(r); });
112 protocol->typedRpc()->registerNotificationHandler<Notifications::AddBuildDirsParams>(
114 [this](const QByteArray &, const Notifications::AddBuildDirsParams &params) {
115 for (const auto &buildDirs : params.buildDirsToSet) {
116 QStringList dirPaths;
117 dirPaths.resize(buildDirs.buildDirs.size());
118 std::transform(buildDirs.buildDirs.begin(), buildDirs.buildDirs.end(),
119 dirPaths.begin(), [](const QByteArray &utf8Str) {
120 return QString::fromUtf8(utf8Str);
121 });
122 m_codeModelManager.setBuildPathsForRootUrl(buildDirs.baseUri, dirPaths);
123 }
124 });
125}
126
127void QQmlLanguageServer::setupCapabilities(const QLspSpecification::InitializeParams &,
128 QLspSpecification::InitializeResult &serverInfo)
129{
130 QJsonObject expCap;
131 if (serverInfo.capabilities.experimental.has_value() && serverInfo.capabilities.experimental->isObject())
132 expCap = serverInfo.capabilities.experimental->toObject();
133 expCap.insert(u"addBuildDirs"_s, QJsonObject({ { u"supported"_s, true } }));
134 serverInfo.capabilities.experimental = expCap;
135}
136
138{
139 return u"QQmlLanguageServer"_s;
140}
141
143{
144 qCWarning(lspServerLog) << "Error exit";
145 fclose(stdin);
146}
147
149{
150 m_returnValue = 0;
151 fclose(stdin);
152}
153
155{
156 return m_returnValue;
157}
158
160{
161 return &m_codeModelManager;
162}
163
165{
166 return &m_server;
167}
168
170{
171 return &m_textSynchronization;
172}
173
175{
176 return &m_lint;
177}
178
180{
181 return &m_workspace;
182}
183
184} // namespace QmlLsp
185
186QT_END_NAMESPACE
Implements a server for the language server protocol.
Sets up a QmlLanguageServer.
TextSynchronization * textSynchronization()
QQmlCodeModelManager * codeModelManager()
void setupCapabilities(const QLspSpecification::InitializeParams &clientInfo, QLspSpecification::InitializeResult &serverInfo) final