Revision control
++ // Copyright (C) 2021 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #include "qqmllanguageserver_p.h"
++ #include "qtextsynchronization_p.h"
++ #include "qlanguageserver_p.h"
++ #include "qlspcustomtypes_p.h"
++
++ #include <QtCore/qdir.h>
++
++ #include <iostream>
++ #include <algorithm>
++
++ QT_BEGIN_NAMESPACE
++
++ namespace QmlLsp {
++
++ using namespace QLspSpecification;
++ using namespace Qt::StringLiterals;
++ /*!
++ \internal
++ \class QmlLsp::QQmlLanguageServer
++ \brief Sets up a QmlLanguageServer.
++
++ This class sets up a QML language server.
++
++ Use the following function to send replies:
++
++ \code
++ std::function<void(const QByteArray &)> sendData
++ \endcode
++
++ And, feed the data that the function receives to the \c {server()->receive()}
++ method.
++
++ Call this method only from a single thread, and do not block. To achieve this,
++ avoid direct calls, and connect the method as a slot, while reading from another
++ thread.
++
++ The various tasks of the language server are divided between
++ QLanguageServerModule instances. Each instance is responsible for handling a
++ certain subset of client requests. For example, one instance handles completion
++ requests, another one updates the code in the code model when the client sends a
++ new file version, and so on. The QLanguageServerModule instances are
++ constructed and registered with QLanguageServer in the constructor of
++ this class.
++
++ Generally, do all operations in the object thread and always call handlers from
++ it. However, the operations can delegate the response to another thread, as the
++ response handler is thread safe. All the methods of the \c server() object are
++ also thread safe.
++
++ The code model starts other threads to update its state. See its documentation
++ for more information.
++ */
++ QQmlLanguageServer::QQmlLanguageServer(std::function<void(const QByteArray &)> sendData,
++ QQmlToolingSharedSettings *settings)
++ : QLanguageServer(sendData),
++ m_codeModelManager(nullptr, settings),
++ m_textSynchronization(&m_codeModelManager),
++ m_workspace(&m_codeModelManager),
++ m_completionSupport(&m_codeModelManager),
++ m_navigationSupport(&m_codeModelManager),
++ m_definitionSupport(&m_codeModelManager),
++ m_referencesSupport(&m_codeModelManager),
++ m_documentFormatting(&m_codeModelManager),
++ m_renameSupport(&m_codeModelManager),
++ m_rangeFormatting(&m_codeModelManager),
++ m_hover(&m_codeModelManager),
++ m_codeActionSupport(&m_codeModelManager),
++ m_highlightSupport(&m_codeModelManager),
++ m_documentSymbolSupport(&m_codeModelManager),
++ m_progressSupport(&m_codeModelManager),
++ m_lint(this, &m_codeModelManager)
++ {
++ QObject::connect(this, &QLanguageServer::lifecycleError, this, &QQmlLanguageServer::errorExit);
++ QObject::connect(this, &QLanguageServer::exit, this, &QQmlLanguageServer::exit);
++
++ registerModule(&m_textSynchronization);
++ registerModule(&m_codeActionSupport);
++ registerModule(&m_workspace);
++ registerModule(&m_completionSupport);
++ registerModule(&m_navigationSupport);
++ registerModule(&m_definitionSupport);
++ registerModule(&m_referencesSupport);
++ registerModule(&m_documentFormatting);
++ registerModule(&m_renameSupport);
++ registerModule(&m_rangeFormatting);
++ registerModule(&m_hover);
++ registerModule(&m_documentSymbolSupport);
++ registerModule(&m_progressSupport);
++ registerModule(&m_highlightSupport);
++
++ qCDebug(lspServerLog) << "Did Setup";
++ }
++
++ QQmlLanguageServer::~QQmlLanguageServer()
++ {
++ // note: the server modules might be in use by the QQmlCodeModel thread, so wait for the
++ // QQmlCodeModel threads to finish before destroying the server modules.
++ m_codeModelManager.prepareForShutdown();
++ }
++
++ void QQmlLanguageServer::errorExit()
++ {
++ qCWarning(lspServerLog) << "Error exit";
++ fclose(stdin);
++ }
++
++ void QQmlLanguageServer::exit()
++ {
++ m_returnValue = 0;
++ fclose(stdin);
++ }
++
++ int QQmlLanguageServer::returnValue() const
++ {
++ return m_returnValue;
++ }
++
++ QQmlCodeModelManager *QQmlLanguageServer::codeModelManager()
++ {
++ return &m_codeModelManager;
++ }
++
++ } // namespace QmlLsp
++
++ QT_END_NAMESPACE