Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qqmlrangeformatting.cpp
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
5#include <qqmlcodemodel_p.h>
6#include <qqmllsutils_p.h>
7
8#include <QtQmlDom/private/qqmldomitem_p.h>
9#include <QtQmlDom/private/qqmldomindentinglinewriter_p.h>
10#include <QtQmlDom/private/qqmldomcodeformatter_p.h>
11#include <QtQmlDom/private/qqmldomoutwriter_p.h>
12#include <QtQmlDom/private/qqmldommock_p.h>
13#include <QtQmlDom/private/qqmldomcompare_p.h>
14
16
18
20 : QQmlBaseModule(codeModel)
21{
22}
23
25{
26 return u"QQmlRangeFormatting"_s;
27}
28
29void QQmlRangeFormatting::registerHandlers(QLanguageServer *, QLanguageServerProtocol *protocol)
30{
31 protocol->registerDocumentRangeFormattingRequestHandler(getRequestHandler());
32}
33
34void QQmlRangeFormatting::setupCapabilities(const QLspSpecification::InitializeParams &,
35 QLspSpecification::InitializeResult &serverCapabilities)
36{
37 serverCapabilities.capabilities.documentRangeFormattingProvider = true;
38}
39
40void QQmlRangeFormatting::process(RequestPointerArgument request)
41{
42 using namespace QQmlJS::Dom;
43 QList<QLspSpecification::TextEdit> result{};
44
46 QQmlLSUtils::lspUriToQmlUrl(request->m_parameters.textDocument.uri));
47
48 DomItem file = doc.snapshot.doc.fileObject(GoTo::MostLikely);
49 if (!file) {
50 qWarning() << u"Could not find the file"_s << doc.snapshot.doc.toString();
51 return;
52 }
53
54 if (auto envPtr = file.environment().ownerAs<DomEnvironment>())
55 envPtr->clearReferenceCache();
56
57 auto qmlFile = file.ownerAs<QmlFile>();
58 auto code = qmlFile->code();
59
60 // Range requested to be formatted
61 const auto selectedRange = request->m_parameters.range;
62 const auto selectedRangeStartLine = selectedRange.start.line;
63 const auto selectedRangeEndLine = selectedRange.end.line;
64 Q_ASSERT(selectedRangeStartLine >= 0);
65 Q_ASSERT(selectedRangeEndLine >= 0);
66
67 LineWriterOptions options;
68 options.updateOptions = LineWriterOptions::Update::None;
69 options.attributesSequence = LineWriterOptions::AttributesSequence::Preserve;
70
71 QTextStream in(&code);
72 FormatTextStatus status = FormatTextStatus::initialStatus();
73 FormatPartialStatus partialStatus({}, options.formatOptions, status);
74
75 // Get the token status of the previous line without performing write operation
76 int lineNumber = 0;
77 while (!in.atEnd()) {
78 const auto line = in.readLine();
79 partialStatus = formatCodeLine(line, options.formatOptions, partialStatus.currentStatus);
80 if (++lineNumber >= selectedRangeStartLine)
81 break;
82 }
83
84 QString resultText;
85 QTextStream out(&resultText);
86 IndentingLineWriter lw([&out](QStringView writtenText) { out << writtenText.toUtf8(); },
87 QString(), options, partialStatus.currentStatus);
88 OutWriter ow(lw);
89 ow.indentNextlines = true;
90
91 // TODO: This is a workaround and will/should be handled by the actual formatter
92 // once we improve the range-formatter design in QTBUG-116139
93 const auto removeSpaces = [](const QString &line) {
96 bool previousIsSpace = false;
97
98 int newLineCount = 0;
99 for (int i = 0; i < line.length(); ++i) {
100 QChar c = line.at(i);
101 if (c.isSpace()) {
102 if (c == '\n'_L1 && newLineCount < 2) {
103 out << '\n'_L1;
104 ++newLineCount;
105 } else if (c == '\r'_L1 && (i + 1) < line.length() && line.at(i + 1) == '\n'_L1
106 && newLineCount < 2) {
107 out << "\r\n";
108 ++newLineCount;
109 ++i;
110 } else {
111 if (!previousIsSpace)
112 out << ' '_L1;
113 }
114 previousIsSpace = true;
115 } else {
116 out << c;
117 previousIsSpace = false;
118 newLineCount = 0;
119 }
120 }
121
122 out.flush();
123 return result;
124 };
125
126 const auto startOffset = QQmlLSUtils::textOffsetFrom(code, selectedRangeStartLine, 0);
127 const auto endOffset = QQmlLSUtils::textOffsetFrom(code, selectedRangeEndLine + 1, 0);
128 const auto &toFormat = code.mid(startOffset, endOffset - startOffset);
129 ow.write(removeSpaces(toFormat));
130 ow.flush();
131 ow.eof();
132
133 const auto documentLineCount = QQmlLSUtils::textRowAndColumnFrom(code, code.length()).line;
134 code.replace(startOffset, toFormat.length(), resultText);
135
136 QLspSpecification::TextEdit add;
137 add.newText = code.toUtf8();
138 add.range = { { 0, 0 }, { documentLineCount + 1 } };
139 result.append(add);
140
141 request->m_response.sendResponse(result);
142}
143
\inmodule QtCore
Implements a server for the language server protocol.
Represents a consistent set of types organized in modules, it is the top level of the DOM.
DomItem fileObject(GoTo option=GoTo::Strict) const
QString toString() const
A QmlFile, when loaded in a DomEnvironment that has the DomCreationOption::WithSemanticAnalysis,...
static QByteArray lspUriToQmlUrl(const QByteArray &uri)
static qsizetype textOffsetFrom(const QString &code, int row, int character)
Convert a text position from (line, column) into an offset.
static QQmlLSUtilsTextPosition textRowAndColumnFrom(const QString &code, qsizetype offset)
Convert a text position from an offset into (line, column).
void process(RequestPointerArgument req) override
QString name() const override
void setupCapabilities(const QLspSpecification::InitializeParams &clientInfo, QLspSpecification::InitializeResult &) override
void registerHandlers(QLanguageServer *server, QLanguageServerProtocol *protocol) override
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QString & replace(qsizetype i, qsizetype len, QChar after)
Definition qstring.cpp:3824
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1226
QByteArray toUtf8() const &
Definition qstring.h:634
qsizetype length() const noexcept
Returns the number of characters in this string.
Definition qstring.h:191
\inmodule QtCore
OpenDocumentSnapshot snapshot
OpenDocument openDocumentByUrl(const QByteArray &url)
Combined button and popup list for selecting options.
#define qWarning
Definition qlogging.h:166
#define Q_DECLARE_LOGGING_CATEGORY(name)
const GLubyte * c
GLuint in
GLuint64EXT * result
[6]
static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QFile file
[0]
QTextStream out(stdout)
[7]
QNetworkRequest request(url)