Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qqmlbasemodule_p.h
Go to the documentation of this file.
1// Copyright (C) 2023 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
4#ifndef QQMLBASEMODULE_P_H
5#define QQMLBASEMODULE_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include "qlanguageserver_p.h"
19#include "qqmlcodemodel_p.h"
20#include "qqmllsutils_p.h"
21
22#include <QObject>
23#include <unordered_map>
24
25template<typename ParametersT, typename ResponseT>
27{
28 // allow using Parameters and Response type aliases in the
29 // implementations of the different requests.
30 using Parameters = ParametersT;
31 using Response = ResponseT;
32
33 // The version of the code on which the typedefinition request was made.
34 // Request is received: mark it with the current version of the textDocument.
35 // Then, wait for the codemodel to finish creating a snapshot version that is newer or equal to
36 // the textDocument version at request-received-time.
40
42};
43
44template<typename RequestType>
46{
47 using RequestParameters = typename RequestType::Parameters;
48 using RequestResponse = typename RequestType::Response;
49 using RequestPointer = std::unique_ptr<RequestType>;
52
55
56 void requestHandler(const RequestParameters &parameters, RequestResponse &&response);
57 decltype(auto) getRequestHandler();
58 // processes a request in a different thread.
59 virtual void process(RequestPointerArgument toBeProcessed) = 0;
60 std::optional<QList<QQmlLSUtilsItemLocation>> itemsForRequest(const RequestPointer &request);
61
62public Q_SLOTS:
63 void updatedSnapshot(const QByteArray &uri);
64
65protected:
67 std::unordered_multimap<QString, RequestPointer> m_pending;
69};
70
71template<typename Parameters, typename Response>
73 Response &&response)
74{
75 Q_UNUSED(doc);
76 m_parameters = params;
77 m_response = std::move(response);
78
79 if (!doc.textDocument) {
80 qDebug() << "Cannot find document in qmlls's codemodel, did you open it before accessing "
81 "it?";
82 return false;
83 }
84
85 {
86 QMutexLocker l(doc.textDocument->mutex());
87 m_minVersion = doc.textDocument->version().value_or(0);
88 }
89 return true;
90}
91
92template<typename RequestType>
94 : m_codeModel(codeModel)
95{
98}
99
100template<typename RequestType>
102{
103 QMutexLocker l(&m_pending_mutex);
104 m_pending.clear(); // empty the m_pending while the mutex is hold
105}
106
107template<typename RequestType>
109{
110 auto handler = [this](const QByteArray &, const RequestParameters &parameters,
111 RequestResponse &&response) {
112 requestHandler(parameters, std::move(response));
113 };
114 return handler;
115}
116
117template<typename RequestType>
119 RequestResponse &&response)
120{
121 auto req = std::make_unique<RequestType>();
122 QmlLsp::OpenDocument doc = m_codeModel->openDocumentByUrl(
123 QQmlLSUtils::lspUriToQmlUrl(parameters.textDocument.uri));
124
125 if (!req->fillFrom(doc, parameters, std::move(response))) {
126 req->m_response.sendErrorResponse(0, "Received invalid request", parameters);
127 return;
128 }
129 const int minVersion = req->m_minVersion;
130 {
131 QMutexLocker l(&m_pending_mutex);
132 m_pending.insert({ QString::fromUtf8(req->m_parameters.textDocument.uri), std::move(req) });
133 }
134
135 if (doc.snapshot.docVersion && *doc.snapshot.docVersion >= minVersion)
136 updatedSnapshot(QQmlLSUtils::lspUriToQmlUrl(parameters.textDocument.uri));
137}
138
139template<typename RequestType>
141{
142 QmlLsp::OpenDocumentSnapshot doc = m_codeModel->snapshotByUrl(url);
143 std::vector<RequestPointer> toCompl;
144 {
145 QMutexLocker l(&m_pending_mutex);
146 for (auto [it, end] = m_pending.equal_range(QString::fromUtf8(url)); it != end;) {
147 if (auto &[key, value] = *it;
148 doc.docVersion && value->m_minVersion <= *doc.docVersion) {
149 toCompl.push_back(std::move(value));
150 it = m_pending.erase(it);
151 } else {
152 ++it;
153 }
154 }
155 }
156 for (auto it = toCompl.rbegin(), end = toCompl.rend(); it != end; ++it) {
157 process(std::move(*it));
158 }
159}
160
161template<typename RequestType>
162std::optional<QList<QQmlLSUtilsItemLocation>>
164{
165
166 QmlLsp::OpenDocument doc = m_codeModel->openDocumentByUrl(
167 QQmlLSUtils::lspUriToQmlUrl(request->m_parameters.textDocument.uri));
168
170 // clear reference cache to resolve latest versions (use a local env instead?)
171 if (auto envPtr = file.environment().ownerAs<QQmlJS::Dom::DomEnvironment>())
172 envPtr->clearReferenceCache();
173 if (!file) {
174 qWarning() << u"Could not find file in Dom Environment from Codemodel :"_s
175 << doc.snapshot.doc.toString();
176 return {};
177 }
178
179 auto itemsFound = QQmlLSUtils::itemsFromTextLocation(file, request->m_parameters.position.line,
180 request->m_parameters.position.character);
181
182 if (itemsFound.isEmpty()) {
183 qWarning() << u"Could not find any items at given text location."_s;
184 return {};
185 }
186 return itemsFound;
187}
188
189#endif // QQMLBASEMODULE_P_H
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
Definition qmutex.h:317
\inmodule QtCore
Definition qmutex.h:285
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
Represents a consistent set of types organized in modules, it is the top level of the DOM.
DomItem fileObject(GoTo option=GoTo::Strict)
static QByteArray lspUriToQmlUrl(const QByteArray &uri)
static QList< QQmlLSUtilsItemLocation > itemsFromTextLocation(QQmlJS::Dom::DomItem file, int line, int character)
Find the DomItem representing the object situated in file at given line and character/column.
iterator erase(const_iterator i)
Definition qset.h:145
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
std::optional< int > docVersion
QQmlJS::Dom::DomItem validDoc
std::shared_ptr< Utils::TextDocument > textDocument
OpenDocumentSnapshot snapshot
void updatedSnapshot(const QByteArray &url)
QSet< QString >::iterator it
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qDebug
[1]
Definition qlogging.h:160
#define qWarning
Definition qlogging.h:162
GLuint64 key
GLuint GLuint end
void ** params
#define Q_SLOTS
#define Q_UNUSED(x)
QFile file
[0]
QUrl url("example.com")
[constructor-url-reference]
QNetworkRequest request(url)
Parameters m_parameters
ResponseT Response
ParametersT Parameters
Response m_response
bool fillFrom(QmlLsp::OpenDocument doc, const Parameters &params, Response &&response)
std::optional< QList< QQmlLSUtilsItemLocation > > itemsForRequest(const RequestPointer &request)
decltype(auto) getRequestHandler()
QQmlBaseModule(QmlLsp::QQmlCodeModel *codeModel)
QmlLsp::QQmlCodeModel * m_codeModel
void updatedSnapshot(const QByteArray &uri)
void requestHandler(const RequestParameters &parameters, RequestResponse &&response)
RequestPointer && RequestPointerArgument
typename RequestType::Response RequestResponse
virtual void process(RequestPointerArgument toBeProcessed)=0
std::unique_ptr< RequestType > RequestPointer
typename RequestType::Parameters RequestParameters
std::unordered_multimap< QString, RequestPointer > m_pending