1// Copyright (C) 2021 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#include "qtextsynchronization_p.h"
5#include "qqmllsutils_p.h"
6#include "qtextdocument_p.h"
7
8using namespace QLspSpecification;
9using namespace Qt::StringLiterals;
10
11QT_BEGIN_NAMESPACE
12
13TextSynchronization::TextSynchronization(QmlLsp::QQmlCodeModel *codeModel, QObject *parent)
14 : QLanguageServerModule(parent), m_codeModel(codeModel)
15{
16}
17
18void TextSynchronization::didCloseTextDocument(const DidCloseTextDocumentParams &params)
19{
20 m_codeModel->closeOpenFile(url: QQmlLSUtils::lspUriToQmlUrl(uri: params.textDocument.uri));
21}
22
23void TextSynchronization::didOpenTextDocument(const DidOpenTextDocumentParams &params)
24{
25 const TextDocumentItem &item = params.textDocument;
26 const QString fileName = m_codeModel->url2Path(url: QQmlLSUtils::lspUriToQmlUrl(uri: item.uri));
27 m_codeModel->newOpenFile(url: QQmlLSUtils::lspUriToQmlUrl(uri: item.uri), version: item.version,
28 docText: QString::fromUtf8(ba: item.text));
29}
30
31void TextSynchronization::didDidChangeTextDocument(const DidChangeTextDocumentParams &params)
32{
33 QByteArray url = QQmlLSUtils::lspUriToQmlUrl(uri: params.textDocument.uri);
34 const QString fileName = m_codeModel->url2Path(url);
35 auto openDoc = m_codeModel->openDocumentByUrl(url);
36 std::shared_ptr<Utils::TextDocument> document = openDoc.textDocument;
37 if (!document) {
38 qCWarning(lspServerLog) << "Ingnoring changes to non open or closed document"
39 << QString::fromUtf8(ba: url);
40 return;
41 }
42 const auto &changes = params.contentChanges;
43 {
44 QMutexLocker l(document->mutex());
45 for (const auto &change : changes) {
46 if (!change.range) {
47 document->setPlainText(QString::fromUtf8(ba: change.text));
48 continue;
49 }
50
51 const auto &range = *change.range;
52 const auto &rangeStart = range.start;
53 const int start =
54 document->findBlockByNumber(blockNumber: rangeStart.line).position() + rangeStart.character;
55 const auto &rangeEnd = range.end;
56 const int end =
57 document->findBlockByNumber(blockNumber: rangeEnd.line).position() + rangeEnd.character;
58
59 document->setPlainText(document->toPlainText().replace(i: start, len: end - start,
60 after: QString::fromUtf8(ba: change.text)));
61 }
62 document->setVersion(params.textDocument.version);
63 qCDebug(lspServerLog).noquote()
64 << "text is\n:----------" << document->toPlainText() << "\n_________";
65 }
66 m_codeModel->addOpenToUpdate(url);
67 m_codeModel->openNeedUpdate();
68}
69
70void TextSynchronization::registerHandlers(QLanguageServer *server, QLanguageServerProtocol *)
71{
72 QObject::connect(sender: server->notifySignals(),
73 signal: &QLspNotifySignals::receivedDidOpenTextDocumentNotification, context: this,
74 slot: &TextSynchronization::didOpenTextDocument);
75
76 QObject::connect(sender: server->notifySignals(),
77 signal: &QLspNotifySignals::receivedDidChangeTextDocumentNotification, context: this,
78 slot: &TextSynchronization::didDidChangeTextDocument);
79
80 QObject::connect(sender: server->notifySignals(),
81 signal: &QLspNotifySignals::receivedDidCloseTextDocumentNotification, context: this,
82 slot: &TextSynchronization::didCloseTextDocument);
83}
84
85QString TextSynchronization::name() const
86{
87 return u"TextSynchonization"_s;
88}
89
90void TextSynchronization::setupCapabilities(const QLspSpecification::InitializeParams &,
91 QLspSpecification::InitializeResult &serverInfo)
92{
93 TextDocumentSyncOptions syncOptions;
94 syncOptions.openClose = true;
95 syncOptions.change = TextDocumentSyncKind::Incremental;
96 serverInfo.capabilities.textDocumentSync = syncOptions;
97}
98
99QT_END_NAMESPACE
100

source code of qtdeclarative/src/qmlls/qtextsynchronization.cpp