Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qqmlhighlightsupport.cpp
Go to the documentation of this file.
1
// Copyright (C) 2024 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
<
qqmlhighlightsupport_p
.
h
>
6
#
include
<
qqmldiffer_p
.
h
>
7
8
QT_BEGIN_NAMESPACE
9
10
using
namespace
Qt::StringLiterals;
11
using
namespace
QLspSpecification;
12
using
namespace
QQmlJS::Dom;
13
using
namespace
QmlHighlighting;
14
15
/*!
16
\internal
17
Make a list of enum names to register the supported token
18
types and modifiers. It is case-sensitive in the protocol
19
thus we need to lower the first characters of the enum names.
20
*/
21
template
<
typename
EnumType>
22
static
QList
<
QByteArray
>
enumToByteArray
()
23
{
24
QList<QByteArray> result;
25
QMetaEnum metaEnum = QMetaEnum::fromType<EnumType>();
26
for
(
auto
i = 0; i < metaEnum.keyCount(); ++i) {
27
auto
&&enumName = QByteArray(metaEnum.key(i));
28
enumName.front() = std::tolower(enumName.front());
29
result.emplace_back(std::move(enumName));
30
}
31
32
return
result;
33
}
34
35
QList
<
QByteArray
>
defaultTokenModifiersList
()
36
{
37
return
enumToByteArray<QLspSpecification::SemanticTokenModifiers>();
38
}
39
40
QList
<
QByteArray
>
extendedTokenTypesList
()
41
{
42
return
enumToByteArray<SemanticTokenProtocolTypes>();
43
}
44
45
static
QList
<
unsigned
>
generateHighlights
(QmlLsp::RegisteredSemanticTokens &cached,
46
const
QmlLsp::OpenDocument &doc,
47
const
std::optional<HighlightsRange> &range,
48
HighlightingMode mode)
49
{
50
DomItem file = doc.snapshot.doc.fileObject(GoTo::MostLikely);
51
const
auto
fileObject = file.ownerAs<QmlFile>();
52
QmlHighlighting::Utils::updateResultID(cached.resultId);
53
if
(!fileObject || !(fileObject && fileObject->isValid())) {
54
if
(
const
auto
lastValidItem = doc.snapshot.validDoc.ownerAs<QmlFile>()) {
55
const
auto
shiftedHighlights = QmlHighlighting::Utils::shiftHighlights(
56
cached.highlights, lastValidItem->code(), doc.textDocument->toPlainText());
57
return
QmlHighlighting::Utils::encodeSemanticTokens(shiftedHighlights, mode);
58
}
else
{
59
const
QString code = doc.textDocument->toPlainText();
60
const
HighlightsContainer highlights =
61
QmlHighlighting::Utils::regexFallbackHighlights(code, range);
62
if
(highlights.isEmpty())
63
return
{};
64
return
QmlHighlighting::Utils::encodeSemanticTokens(highlights, mode);
65
}
66
}
else
{
67
HighlightsContainer highlights = QmlHighlighting::Utils::visitTokens(file, range);
68
if
(highlights.isEmpty())
69
return
{};
70
// Record the highlights for future diffs, only record full highlights
71
if
(!range.has_value() )
72
cached.highlights = highlights;
73
74
return
QmlHighlighting::Utils::encodeSemanticTokens(highlights, mode);
75
}
76
}
77
78
/*!
79
\internal
80
A wrapper class that handles the semantic tokens request for a whole file as described in
81
https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#semanticTokens_fullRequest
82
Sends a QLspSpecification::SemanticTokens data as response that is generated for the entire file.
83
*/
84
SemanticTokenFullHandler
::
SemanticTokenFullHandler
(QmlLsp::QQmlCodeModelManager *codeModelManager)
85
:
QQmlBaseModule
(
codeModelManager
),
m_mode
(
HighlightingMode
::
Default
)
86
{
87
}
88
89
void
SemanticTokenFullHandler
::
process
(
90
QQmlBaseModule<SemanticTokensRequest>::RequestPointerArgument request)
91
{
92
if
(!request) {
93
qCWarning(semanticTokens) <<
"No semantic token request is available!"
;
94
return
;
95
}
96
97
Responses::SemanticTokensResultType result;
98
ResponseScopeGuard guard(result, request->m_response);
99
const
QByteArray uri = QQmlLSUtils::lspUriToQmlUrl(request->m_parameters.textDocument.uri);
100
const
auto
doc = m_codeModelManager->openDocumentByUrl(uri);
101
auto
&cached = m_codeModelManager->registeredTokens(uri);
102
auto
encoded = generateHighlights(cached, doc, std::nullopt, m_mode);
103
104
if
(encoded.isEmpty()) {
105
return
;
106
}
else
{
107
result = SemanticTokens{cached.resultId, std::move(encoded)};
108
}
109
}
110
111
void
SemanticTokenFullHandler
::
registerHandlers
(QLanguageServer *, QLanguageServerProtocol *protocol)
112
{
113
protocol->registerSemanticTokensRequestHandler(getRequestHandler());
114
}
115
116
/*!
117
\internal
118
A wrapper class that handles the semantic tokens delta request for a file
119
https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#semanticTokens_deltaRequest
120
Sends either SemanticTokens or SemanticTokensDelta data as response.
121
This is generally requested when the text document is edited after receiving full highlighting data.
122
*/
123
SemanticTokenDeltaHandler
::
SemanticTokenDeltaHandler
(QmlLsp::QQmlCodeModelManager *codeModelManager)
124
:
QQmlBaseModule
(
codeModelManager
),
m_mode
(
HighlightingMode
::
Default
)
125
{
126
}
127
128
void
SemanticTokenDeltaHandler
::
process
(
129
QQmlBaseModule<SemanticTokensDeltaRequest>::RequestPointerArgument request)
130
{
131
if
(!request) {
132
qCWarning(semanticTokens) <<
"No semantic token request is available!"
;
133
return
;
134
}
135
136
Responses::SemanticTokensDeltaResultType result;
137
ResponseScopeGuard guard(result, request->m_response);
138
const
QByteArray uri = QQmlLSUtils::lspUriToQmlUrl(request->m_parameters.textDocument.uri);
139
const
auto
doc = m_codeModelManager->openDocumentByUrl(uri);
140
auto
&cached = m_codeModelManager->registeredTokens(uri);
141
if
(cached.resultId != request->m_parameters.previousResultId) {
142
// The client is out of sync, send full tokens
143
cached.resultId = request->m_parameters.previousResultId;
144
const
auto
encoded = generateHighlights(cached, doc, std::nullopt, m_mode);
145
result = QLspSpecification::SemanticTokens{ cached.resultId, encoded };
146
}
else
{
147
const
auto
cachedHighlights = QmlHighlighting::Utils::encodeSemanticTokens(cached.highlights);
148
const
auto
encoded = generateHighlights(cached, doc, std::nullopt, m_mode);
149
result = QLspSpecification::SemanticTokensDelta{
150
cached.resultId,
151
QmlHighlighting::Utils::computeDiff(cachedHighlights, encoded)
152
};
153
}
154
}
155
156
void
SemanticTokenDeltaHandler
::
registerHandlers
(QLanguageServer *, QLanguageServerProtocol *protocol)
157
{
158
protocol->registerSemanticTokensDeltaRequestHandler(getRequestHandler());
159
}
160
161
/*!
162
\internal
163
A wrapper class that handles the semantic tokens range request for a file
164
https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#semanticTokens_rangeRequest
165
Sends a QLspSpecification::SemanticTokens data as response that is generated for a range of file.
166
*/
167
SemanticTokenRangeHandler
::
SemanticTokenRangeHandler
(QmlLsp::QQmlCodeModelManager *codeModelManager)
168
:
QQmlBaseModule
(
codeModelManager
),
m_mode
(
HighlightingMode
::
Default
)
169
{
170
}
171
172
void
SemanticTokenRangeHandler
::
process
(
173
QQmlBaseModule<SemanticTokensRangeRequest>::RequestPointerArgument request)
174
{
175
if
(!request) {
176
qCWarning(semanticTokens) <<
"No semantic token request is available!"
;
177
return
;
178
}
179
180
Responses::SemanticTokensRangeResultType result;
181
ResponseScopeGuard guard(result, request->m_response);
182
const
QByteArray uri = QQmlLSUtils::lspUriToQmlUrl(request->m_parameters.textDocument.uri);
183
const
auto
doc = m_codeModelManager->openDocumentByUrl(uri);
184
const
QString code = doc.textDocument->toPlainText();
185
const
auto
range = request->m_parameters.range;
186
int
startOffset =
187
int
(QQmlLSUtils::textOffsetFrom(code, range.start.line, range.end.character));
188
int
endOffset =
int
(QQmlLSUtils::textOffsetFrom(code, range.end.line, range.end.character));
189
auto
&cached = m_codeModelManager->registeredTokens(uri);
190
auto
encodedTokens = generateHighlights(
191
cached,
192
doc,
193
QmlHighlighting::HighlightsRange{ startOffset, endOffset },
194
m_mode);
195
if
(encodedTokens.isEmpty()) {
196
}
else
{
197
result = SemanticTokens{ cached.resultId, std::move(encodedTokens) };
198
}
199
}
200
201
void
SemanticTokenRangeHandler
::
registerHandlers
(QLanguageServer *, QLanguageServerProtocol *protocol)
202
{
203
protocol->registerSemanticTokensRangeRequestHandler(getRequestHandler());
204
}
205
206
QQmlHighlightSupport
::
QQmlHighlightSupport
(QmlLsp::QQmlCodeModelManager *codeModelManager)
207
:
m_full
(
codeModelManager
),
m_delta
(
codeModelManager
),
m_range
(
codeModelManager
)
208
{
209
}
210
211
void
QQmlHighlightSupport
::
registerHandlers
(QLanguageServer *server, QLanguageServerProtocol *protocol)
212
{
213
m_full.registerHandlers(server, protocol);
214
m_delta.registerHandlers(server, protocol);
215
m_range.registerHandlers(server, protocol);
216
217
QObject::connect(server, &QLanguageServer::clientInitialized,
this
,
218
&QQmlHighlightSupport::clientInitialized, Qt::SingleShotConnection);
219
220
QObject::connect(
221
m_full.manager(), &QmlLsp::QQmlCodeModelManager::configurationChanged,
this
,
222
[protocol]() { protocol->requestWorkspaceSemanticTokensRefresh({ }, []() { }); });
223
}
224
225
void
QQmlHighlightSupport
::clientInitialized(QLanguageServer *server)
226
{
227
if
(
auto
clientInitOptions = server->clientInfo().initializationOptions) {
228
if
((*clientInitOptions)[u"qtCreatorHighlighting"_s].toBool(
false
)) {
229
const
auto
mode = HighlightingMode::QtCHighlighting;
230
m_delta.setHighlightingMode(mode);
231
m_full.setHighlightingMode(mode);
232
m_range.setHighlightingMode(mode);
233
}
234
}
235
}
236
237
void
QQmlHighlightSupport
::
setupCapabilities
(QLspSpecification::ServerCapabilities &caps)
238
{
239
QLspSpecification::SemanticTokensOptions options;
240
options.range =
true
;
241
options.full = SemanticTokensFullDelta{
true
};
242
243
options.legend.tokenTypes = extendedTokenTypesList();
244
options.legend.tokenModifiers = defaultTokenModifiersList();
245
caps.semanticTokensProvider = options;
246
}
247
248
QT_END_NAMESPACE
QQmlHighlightSupport
Definition
qqmlhighlightsupport_p.h:83
QQmlHighlightSupport::registerHandlers
void registerHandlers(QLanguageServer *server, QLanguageServerProtocol *protocol) override
Definition
qqmlhighlightsupport.cpp:211
QQmlHighlightSupport::setupCapabilities
void setupCapabilities(QLspSpecification::ServerCapabilities &caps) override
Definition
qqmlhighlightsupport.cpp:237
QQmlHighlightSupport::QQmlHighlightSupport
QQmlHighlightSupport(QmlLsp::QQmlCodeModelManager *codeModel)
Definition
qqmlhighlightsupport.cpp:206
SemanticTokenDeltaHandler
Definition
qqmlhighlightsupport_p.h:59
SemanticTokenDeltaHandler::process
void process(QQmlBaseModule< SemanticTokensDeltaRequest >::RequestPointerArgument req) override
Definition
qqmlhighlightsupport.cpp:128
SemanticTokenDeltaHandler::SemanticTokenDeltaHandler
SemanticTokenDeltaHandler(QmlLsp::QQmlCodeModelManager *codeModel)
Definition
qqmlhighlightsupport.cpp:123
SemanticTokenDeltaHandler::registerHandlers
void registerHandlers(QLanguageServer *, QLanguageServerProtocol *) override
Definition
qqmlhighlightsupport.cpp:156
SemanticTokenFullHandler
Definition
qqmlhighlightsupport_p.h:45
SemanticTokenFullHandler::process
void process(QQmlBaseModule< SemanticTokensRequest >::RequestPointerArgument req) override
Definition
qqmlhighlightsupport.cpp:89
SemanticTokenFullHandler::SemanticTokenFullHandler
SemanticTokenFullHandler(QmlLsp::QQmlCodeModelManager *codeModel)
Definition
qqmlhighlightsupport.cpp:84
SemanticTokenFullHandler::registerHandlers
void registerHandlers(QLanguageServer *, QLanguageServerProtocol *) override
Definition
qqmlhighlightsupport.cpp:111
SemanticTokenRangeHandler
Definition
qqmlhighlightsupport_p.h:71
SemanticTokenRangeHandler::SemanticTokenRangeHandler
SemanticTokenRangeHandler(QmlLsp::QQmlCodeModelManager *codeModel)
Definition
qqmlhighlightsupport.cpp:167
SemanticTokenRangeHandler::process
void process(QQmlBaseModule< SemanticTokensRangeRequest >::RequestPointerArgument req) override
Definition
qqmlhighlightsupport.cpp:172
SemanticTokenRangeHandler::registerHandlers
void registerHandlers(QLanguageServer *, QLanguageServerProtocol *) override
Definition
qqmlhighlightsupport.cpp:201
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
extendedTokenTypesList
QList< QByteArray > extendedTokenTypesList()
Definition
qqmlhighlightsupport.cpp:40
defaultTokenModifiersList
QList< QByteArray > defaultTokenModifiersList()
Definition
qqmlhighlightsupport.cpp:35
enumToByteArray
static QList< QByteArray > enumToByteArray()
Definition
qqmlhighlightsupport.cpp:22
generateHighlights
static QList< unsigned > generateHighlights(QmlLsp::RegisteredSemanticTokens &cached, const QmlLsp::OpenDocument &doc, const std::optional< HighlightsRange > &range, HighlightingMode mode)
Definition
qqmlhighlightsupport.cpp:45
qtdeclarative
src
qmlls
qqmlhighlightsupport.cpp
Generated on
for Qt by
1.18.0