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