5#ifndef QQMLBASEMODULE_P_H
6#define QQMLBASEMODULE_P_H
22#include <QtQmlDom/private/qqmldom_utils_p.h>
26#include <unordered_map>
28template<
typename ParametersT,
typename ResponseT>
48
49
50
51
52
54template<
typename Result,
typename ResponseCallback>
70 template<
typename... T>
74 "ResponseScopeGuard::setErrorFrom was passed a variant that never contains"
75 " an error message.");
84
85
86
87
88
89
90
91
92
104 std::visit(qOverloadedVisitor{ [
this](Result *result) { m_callback.sendResponse(*result); },
105 [
this](
const QQmlLSUtils::ErrorMessage &error) {
106 m_callback.sendErrorResponse(error.code,
107 error.message.toUtf8());
113template<
typename RequestType>
128 virtual void process(RequestPointerArgument toBeProcessed) = 0;
133 itemsForRequest(
const RequestPointer &request,
const QLspSpecification::Position &position);
144template<
typename Parameters,
typename Response>
152 if (!doc.textDocument) {
153 qDebug() <<
"Cannot find document in qmlls's codemodel, did you open it before accessing "
159 QMutexLocker l(doc.textDocument->mutex());
165template <
typename RequestType>
169 QObject::connect(m_codeModelManager, &QmlLsp::QQmlCodeModelManager::updatedSnapshot,
this,
170 &QQmlBaseModule<RequestType>::updatedSnapshot);
173template<
typename RequestType>
176 QMutexLocker l(&m_pending_mutex);
180template<
typename RequestType>
190template<
typename RequestType>
194 auto req =
std::make_unique<RequestType>();
196 QQmlLSUtils::lspUriToQmlUrl(parameters.textDocument.uri));
198 if (!req->fillFrom(doc, parameters,
std::move(response))) {
199 req->m_response.sendErrorResponse(0,
"Received invalid request.", parameters);
202 const int minVersion = req->m_minVersion;
204 QMutexLocker l(&m_pending_mutex);
205 m_pending.insert({ QString::fromUtf8(req->m_parameters.textDocument.uri), std::move(req) });
208 if (doc.snapshot.docVersion && *doc.snapshot.docVersion >= minVersion)
209 updatedSnapshot(QQmlLSUtils::lspUriToQmlUrl(parameters.textDocument.uri));
212template<
typename RequestType>
216 std::vector<RequestPointer> toCompl;
218 QMutexLocker l(&m_pending_mutex);
219 for (
auto [it, end] = m_pending.equal_range(QString::fromUtf8(url)); it != end;) {
220 if (
auto &[key, value] = *it;
221 doc.docVersion && value->m_minVersion <= *doc.docVersion) {
222 toCompl.push_back(std::move(value));
223 it = m_pending.erase(it);
229 for (
auto it = toCompl.rbegin(), end = toCompl.rend(); it != end; ++it) {
230 process(std::move(*it));
235template <
typename RequestType>
239 return itemsForRequest(request, request->m_parameters.position);
243template <
typename RequestType>
246 const QLspSpecification::Position &position)
250 QQmlLSUtils::lspUriToQmlUrl(request->m_parameters.textDocument.uri));
252 if (!doc.snapshot.validDocVersion || doc.snapshot.validDocVersion != doc.snapshot.docVersion) {
253 return QQmlLSUtils::ErrorMessage{ 0,
254 u"Cannot proceed: current QML document is invalid! Fix"
255 u" all the errors in your QML code and try again."_s };
258 QQmlJS::Dom::DomItem file = doc.snapshot.validDoc.fileObject(QQmlJS::Dom::GoTo::MostLikely);
260 if (
auto envPtr = file.environment().ownerAs<QQmlJS::Dom::DomEnvironment>())
261 envPtr->clearReferenceCache();
263 return QQmlLSUtils::ErrorMessage{
265 u"Could not find file %1 in project."_s.arg(doc.snapshot.doc.toString()),
269 auto itemsFound = QQmlLSUtils::itemsFromTextLocation(file, position.line, position.character);
271 if (itemsFound.isEmpty()) {
272 return QQmlLSUtils::ErrorMessage{
274 u"Could not find any items at given text location."_s,
virtual void setupCapabilities(QLspSpecification::ServerCapabilities &)=0
Implements a server for the language server protocol.
void registerHandlers(QLanguageServerProtocol *protocol)
const QLspSpecification::InitializeParams & clientInfo() const
void registerModule(QLanguageServerModule *serverModule)
QLspNotifySignals * notifySignals()
RunStatus runStatus() const
void typeDefinitionRequestHandler(const QByteArray &, const QLspSpecification::TypeDefinitionParams ¶ms, ReferencesRequest::Response &&response)
void registerHandlers(QLanguageServer *server, QLanguageServerProtocol *protocol) override
void process(RequestPointerArgument request) override
void setupCapabilities(QLspSpecification::ServerCapabilities &caps) override
Combined button and popup list for selecting options.
bool fillFrom(QmlLsp::OpenDocument doc, const Parameters ¶ms, Response &&response)
QQmlBaseModule< RequestType > BaseT
std::variant< QList< QQmlLSUtils::ItemLocation >, QQmlLSUtils::ErrorMessage > itemsForRequest(const RequestPointer &request, const QLspSpecification::Position &position)
decltype(auto) getRequestHandler()
QmlLsp::QQmlCodeModelManager * m_codeModelManager
std::variant< QList< QQmlLSUtils::ItemLocation >, QQmlLSUtils::ErrorMessage > itemsForRequest(const RequestPointer &request)
void requestHandler(const RequestParameters ¶meters, RequestResponse &&response)
typename RequestType::Response RequestResponse
virtual void process(RequestPointerArgument toBeProcessed)=0
QQmlBaseModule(QmlLsp::QQmlCodeModelManager *codeModel)
typename RequestType::Parameters RequestParameters
std::unordered_multimap< QString, RequestPointer > m_pending
This class sends a result or an error when going out of scope.
bool setErrorFrom(const std::optional< QQmlLSUtils::ErrorMessage > &error)
ResponseCallback & m_callback
void setError(const QQmlLSUtils::ErrorMessage &error)
ResponseScopeGuard(Result &results, ResponseCallback &callback)
bool setErrorFrom(const std::variant< T... > &variant)