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
qqmlprogresssupport.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 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
5#include <QtCore/qstring.h>
6
8
9using namespace Qt::StringLiterals;
10
11QT_BEGIN_NAMESPACE
12
13QQmlProgressSupport::QQmlProgressSupport(QmlLsp::QQmlCodeModelManager *manager)
14 : m_codeModelManager(manager)
15{
16}
17
19{
20 return "QQmlProgress"_L1;
21}
22
24 QLanguageServerProtocol *protocol)
25{
26 m_protocol = protocol;
27 QObject::connect(server, &QLanguageServer::clientInitialized, this,
28 &QQmlProgressSupport::clientInitialized);
29}
30
31void QQmlProgressSupport::clientInitialized(QLanguageServer *server)
32{
33 if (auto window = server->clientInfo().capabilities.window;
34 !window || !window->value("workDoneProgress"_L1).toBool(false)) {
35 return;
36 }
37
38 QObject::connect(m_codeModelManager, &QmlLsp::QQmlCodeModelManager::backgroundBuildStarted,
39 this, &QQmlProgressSupport::onBackgroundBuildStarted);
40 QObject::connect(m_codeModelManager, &QmlLsp::QQmlCodeModelManager::backgroundBuildFinished,
41 this, &QQmlProgressSupport::onBackgroundBuildDone);
42
43 QObject::connect(server->notifySignals(),
44 &QLspNotifySignals::receivedWorkDoneProgressCancelNotification, this,
45 &QQmlProgressSupport::onBackgroundBuildCancelRequested);
46}
47
48int QQmlProgressSupport::Tokens::createUniqueToken(const QByteArray &uri)
49{
50 const int token = m_idForBackgroundBuilds++;
51 m_tokens.insert(uri, { uri, token, InCreation });
52 m_uriByToken.insert(token, uri);
53 return token;
54}
55
56QQmlProgressSupport::UriWithToken *QQmlProgressSupport::Tokens::find(const QByteArray &uri)
57{
58 const auto it = m_tokens.find(uri);
59 return it == m_tokens.end() ? nullptr : &*it;
60}
61
62std::optional<QQmlProgressSupport::UriWithToken> QQmlProgressSupport::Tokens::takeToken(int token)
63{
64 const auto it = m_uriByToken.find(token);
65 if (it == m_uriByToken.end())
66 return {};
67
68 const auto it2 = m_tokens.find(*it);
69 m_uriByToken.erase(it);
70 if (it2 == m_tokens.end())
71 return {};
72 std::optional<QQmlProgressSupport::UriWithToken> result = std::move(*it2);
73 m_tokens.erase(it2);
74 return result;
75}
76
77void QQmlProgressSupport::Tokens::removeToken(const QByteArray &uri)
78{
79 const auto it = m_tokens.find(uri);
80 if (it != m_tokens.end())
81 return;
82
83 if (const auto it2 = m_uriByToken.find(it->token); it2 != m_uriByToken.end())
84 m_uriByToken.erase(it2);
85 m_tokens.erase(it);
86}
87
88void QQmlProgressSupport::onBackgroundBuildStarted(const QByteArray &uri)
89{
90 QLspSpecification::Requests::WorkDoneProgressCreateParamsType p;
91 const int token = m_tokens.createUniqueToken(uri);
92 p.token = token;
93 m_protocol->requestWorkDoneProgressCreate(p, [this, uri, token]() {
94 QLspSpecification::ProgressParams beginParams{ token };
95 QLspSpecification::WorkDoneProgressBegin workDoneProgressBegin{};
96 workDoneProgressBegin.title = "Qmlls running background build";
97 workDoneProgressBegin.cancellable = true;
98 workDoneProgressBegin.message =
99 "Building \"" + QUrl::fromEncoded(uri).toLocalFile().toUtf8() + "\"";
100 workDoneProgressBegin.cancellable = true;
101 beginParams.value = workDoneProgressBegin;
102 m_protocol->notifyProgress(beginParams);
103
104 const auto token = m_tokens.find(uri);
105 if (!token)
106 return;
107
108 switch (token->status) {
109 case InCreation:
110 token->status = Created;
111 break;
112 case Created:
113 Q_ASSERT(false);
114 case Finished:
115 onBackgroundBuildDone(token->uri);
116 break;
117 }
118 });
119}
120
121void QQmlProgressSupport::onBackgroundBuildDone(const QByteArray &uri)
122{
123 const auto token = m_tokens.find(uri);
124 if (!token)
125 return;
126
127 switch (token->status) {
128 case InCreation:
129 // We can't report progress if the WorkDoneProgressCreate request didn't finish yet. Let the
130 // WorkDoneProgressCreate callback call this method again after the request was created.
131 token->status = Finished;
132 return;
133 case Finished:
134 case Created:
135 QLspSpecification::WorkDoneProgressEnd workDoneProgressEnd;
136 workDoneProgressEnd.message = "Build terminated";
137 const QLspSpecification::ProgressParams endParams{ token->token, workDoneProgressEnd };
138 m_protocol->notifyProgress(endParams);
139 m_tokens.removeToken(token->uri);
140 }
141}
142
143void QQmlProgressSupport::onBackgroundBuildCancelRequested(
144 const QLspSpecification::Notifications::WorkDoneProgressCancelParamsType &p)
145{
146 const auto tokenNumber = std::get_if<int>(&p.token);
147 if (!tokenNumber) {
148 qCWarning(lspServerLog) << "Ignoring unknown token" << std::get<QByteArray>(p.token)
149 << "in cancellation request.";
150 return;
151 }
152
153 const auto token = m_tokens.takeToken(*tokenNumber);
154 if (!token) {
155 qCWarning(lspServerLog) << "Ignoring unknown token" << *tokenNumber
156 << "in cancellation request.";
157 return;
158 }
159
160 m_codeModelManager->cancelBackgroundBuild(token->uri);
161}
162
163void QQmlProgressSupport::setupCapabilities(const QLspSpecification::InitializeParams &,
164 QLspSpecification::InitializeResult &)
165{
166}
167
168QT_END_NAMESPACE
Implements a server for the language server protocol.
void registerHandlers(QLanguageServer *server, QLanguageServerProtocol *protocol) final
QQmlProgressSupport(QmlLsp::QQmlCodeModelManager *manager)
QString name() const final
void setupCapabilities(const QLspSpecification::InitializeParams &clientInfo, QLspSpecification::InitializeResult &) final