Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qqmldomlinewriter.cpp
Go to the documentation of this file.
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
"qqmldomlinewriter_p.h"
5
#
include
<
QtCore
/
QCoreApplication
>
6
#
include
<
QtCore
/
QRegularExpression
>
7
8
QT_BEGIN_NAMESPACE
9
namespace
QQmlJS
{
10
namespace
Dom
{
11
12
LineWriter
::
LineWriter
(
13
const
SinkF &innerSink,
const
QString &fileName,
const
LineWriterOptions
&options,
14
int
lineNr,
int
columnNr,
int
utf16Offset,
const
QString ¤tLine)
15
:
m_innerSinks
({
innerSink
}),
16
m_fileName
(
fileName
),
17
m_lineNr
(lineNr),
18
m_columnNr
(columnNr),
19
m_currentColumnNr
(columnNr),
20
m_utf16Offset
(utf16Offset),
21
m_currentLine
(
currentLine
),
22
m_options
(
options
)
23
{
24
}
25
26
LineWriter
&
LineWriter
::
ensureNewline
(
int
nNewline, TextAddType t)
27
{
28
int
nToAdd = nNewline;
29
if
(nToAdd <= 0)
30
return
*
this
;
31
if
(m_currentLine.trimmed().isEmpty()) {
32
--nToAdd;
33
if
(m_committedEmptyLines >=
unsigned
(nToAdd))
34
return
*
this
;
35
nToAdd -= m_committedEmptyLines;
36
}
37
for
(
int
i = 0; i < nToAdd; ++i)
38
write(u"\n", t);
39
return
*
this
;
40
}
41
42
LineWriter
&
LineWriter
::
ensureSpace
(TextAddType t)
43
{
44
if
(!m_currentLine.isEmpty() && !m_currentLine.at(m_currentLine.size() - 1).isSpace())
45
write(u" ", t);
46
return
*
this
;
47
}
48
49
LineWriter
&
LineWriter
::
ensureSemicolon
(TextAddType t)
50
{
51
if
(!m_currentLine.isEmpty() && m_currentLine.back() != u';')
52
write(u";", t);
53
return
*
this
;
54
}
55
56
LineWriter
&
LineWriter
::
ensureSpace
(QStringView space, TextAddType t)
57
{
58
int
tabSize = m_options.formatOptions.tabSize;
59
IndentInfo
ind(space, tabSize);
60
auto
cc = counter();
61
if
(ind.nNewlines > 0)
62
ensureNewline(ind.nNewlines, t);
63
if
(cc != counter() || m_currentLine.isEmpty()
64
|| !m_currentLine.at(m_currentLine.size() - 1).isSpace())
65
write(ind.trailingString, t);
66
else
{
67
int
len = m_currentLine.size();
68
int
i = len;
69
while
(i != 0 && m_currentLine.at(i - 1).isSpace())
70
--i;
71
QStringView trailingSpace = QStringView(m_currentLine).mid(i, len - i);
72
int
trailingSpaceStartColumn =
73
IndentInfo
(QStringView(m_currentLine).mid(0, i), tabSize,
m_columnNr
)
.
column
;
74
IndentInfo
indExisting(trailingSpace, tabSize, trailingSpaceStartColumn);
75
if
(trailingSpaceStartColumn != 0)
76
ind =
IndentInfo
(space, tabSize, trailingSpaceStartColumn);
77
if
(i == 0) {
78
if
(indExisting
.
column
< ind
.
column
) {
79
m_currentColumnNr
+= ind.trailingString.size() - trailingSpace.size();
80
m_currentLine.replace(
81
i, len - i, ind.trailingString.toString());
// invalidates most QStringViews
82
lineChanged
(
)
;
83
}
84
}
else
if
(indExisting
.
column
< ind
.
column
) {
// use just spaces if not at start of a line
85
write(QStringLiteral(u" ").repeated(ind.column - indExisting.column), t);
86
}
87
}
88
return
*
this
;
89
}
90
91
QString
LineWriter
::eolToWrite()
const
92
{
93
switch
(m_options.lineEndings) {
94
case
LineWriterOptions::LineEndings::Unix:
95
return
QStringLiteral(u"\n");
96
case
LineWriterOptions::LineEndings::Windows:
97
return
QStringLiteral(u"\r\n");
98
case
LineWriterOptions::LineEndings::OldMacOs:
99
return
QStringLiteral(u"\r");
100
}
101
Q_ASSERT(
false
);
102
return
QStringLiteral(u"\n");
103
}
104
105
template
<
typename
String,
typename
...Args>
106
static
QRegularExpressionMatch
matchHelper
(QRegularExpression &re, String &&s, Args &&...args)
107
{
108
return
re.matchView(s, args...);
109
}
110
111
LineWriter
&
LineWriter
::
write
(QStringView v, TextAddType tAdd)
112
{
113
QString eol;
114
// split multiple lines
115
static
QRegularExpression eolRe(QLatin1String(
116
"(\r?\n|\r)"
));
// does not support split of \r and \n for windows style line endings
117
QRegularExpressionMatch m = matchHelper(eolRe, v);
118
if
(m.hasMatch()) {
119
// add line by line
120
auto
i = m.capturedStart(1);
121
auto
iEnd = m.capturedEnd(1);
122
eol = eolToWrite();
123
// offset change (eol used vs input) cannot affect things,
124
// because we cannot have already opened or closed a PendingSourceLocation
125
if
(iEnd < v.size()) {
126
write(v.mid(0, iEnd));
127
m = matchHelper(eolRe, v, iEnd);
128
while
(m.hasMatch()) {
129
write(v.mid(iEnd, m.capturedEnd(1) - iEnd));
130
iEnd = m.capturedEnd(1);
131
m = matchHelper(eolRe, v, iEnd);
132
}
133
if
(iEnd < v.size())
134
write(v.mid(iEnd, v.size() - iEnd));
135
return
*
this
;
136
}
137
QStringView toAdd = v.mid(0, i);
138
if
(!toAdd.trimmed().isEmpty())
139
textAddCallback(tAdd);
140
m_counter += i;
141
m_currentLine.append(toAdd);
142
m_currentColumnNr
+=
143
IndentInfo(toAdd, m_options.formatOptions.tabSize, m_currentColumnNr).column;
144
lineChanged
(
)
;
145
}
else
{
146
if
(!v.trimmed().isEmpty())
147
textAddCallback(tAdd);
148
m_counter += v.size();
149
m_currentLine.append(v);
150
m_currentColumnNr
+=
151
IndentInfo(v, m_options.formatOptions.tabSize, m_currentColumnNr).column;
152
lineChanged
(
)
;
153
}
154
if
(!eol.isEmpty()
155
|| (m_options.maxLineLength > 0 && m_currentColumnNr > m_options.maxLineLength)) {
156
reindentAndSplit(eol);
157
}
158
return
*
this
;
159
}
160
161
void
LineWriter
::
flush
()
162
{
163
if
(m_currentLine.size() > 0)
164
commitLine(QString());
165
}
166
167
void
LineWriter
::
eof
(
bool
shouldEnsureNewline)
168
{
169
if
(shouldEnsureNewline)
170
ensureNewline();
171
reindentAndSplit(QString(),
true
);
172
}
173
174
SourceLocation
LineWriter
::
committedLocation
()
const
175
{
176
return
SourceLocation(
m_utf16Offset
, 0,
m_lineNr
,
m_lineUtf16Offset
);
177
}
178
179
int
LineWriter
::
addTextAddCallback
(
std
::function<
bool
(
LineWriter
&, TextAddType)> callback)
180
{
181
int
nextId = ++m_lastCallbackId;
182
Q_ASSERT(nextId != 0);
183
if
(callback)
184
m_textAddCallbacks.insert(nextId, callback);
185
return
nextId;
186
}
187
188
int
LineWriter
::
addNewlinesAutospacerCallback
(
int
nLines)
189
{
190
return
addTextAddCallback
([nLines](
LineWriter
&self, TextAddType t) {
191
if
(t == TextAddType::Normal) {
192
quint32 c = self.counter();
193
QString spacesToPreserve;
194
bool
spaceOnly = QStringView(self.m_currentLine).trimmed().isEmpty();
195
if
(spaceOnly && !self.m_currentLine.isEmpty())
196
spacesToPreserve = self.m_currentLine;
197
self.ensureNewline(nLines, LineWriter::TextAddType::Extra);
198
if
(self.counter() != c && !spacesToPreserve.isEmpty())
199
self.write(spacesToPreserve, TextAddType::Extra);
200
return
false
;
201
}
else
{
202
return
true
;
203
}
204
});
205
}
206
207
void
LineWriter
::
setLineIndent
(
int
indentAmount)
208
{
209
int
startNonSpace = 0;
210
while
(startNonSpace < m_currentLine.size() && m_currentLine.at(startNonSpace).isSpace())
211
++startNonSpace;
212
int
oldColumn =
column
(
startNonSpace
)
;
213
if
(indentAmount >= 0) {
214
QString indent;
215
if
(m_options.formatOptions.useTabs) {
216
indent = QStringLiteral(u"\t").repeated(indentAmount / m_options.formatOptions.tabSize)
217
+ QStringLiteral(u" ").repeated(indentAmount % m_options.formatOptions.tabSize);
218
}
else
{
219
indent = QStringLiteral(u" ").repeated(indentAmount);
220
}
221
if
(indent != m_currentLine.mid(0, startNonSpace)) {
222
quint32 colChange = indentAmount - oldColumn;
223
m_currentColumnNr
+= colChange;
224
m_currentLine = indent + m_currentLine.mid(startNonSpace);
225
m_currentColumnNr
=
column
(m_currentLine.size());
226
lineChanged
(
)
;
227
}
228
}
229
}
230
231
void
LineWriter
::
handleTrailingSpace
(
LineWriterOptions
::
TrailingSpace
trailingSpace)
232
{
233
switch
(trailingSpace) {
234
case
LineWriterOptions
::
TrailingSpace
::
Preserve
:
235
break
;
236
case
LineWriterOptions
::
TrailingSpace
::
Remove
: {
237
int
lastNonSpace = m_currentLine.size();
238
while
(lastNonSpace > 0 && m_currentLine.at(lastNonSpace - 1).isSpace())
239
--lastNonSpace;
240
if
(lastNonSpace != m_currentLine.size()) {
241
m_currentLine = m_currentLine.mid(0, lastNonSpace);
242
m_currentColumnNr
=
243
column
(m_currentLine.size());
// to be extra accurate in the potential split
244
lineChanged
(
)
;
245
}
246
}
break
;
247
}
248
}
249
250
void
LineWriter
::
reindentAndSplit
(
const
QString &eol,
bool
eof)
251
{
252
// maybe write out
253
if
(!eol.isEmpty() || eof) {
254
handleTrailingSpace
(m_options.codeTrailingSpace);
255
commitLine(eol);
256
}
257
}
258
259
SourceLocation
LineWriter
::
currentSourceLocation
()
const
260
{
261
return
SourceLocation(m_utf16Offset + m_currentLine.size(), 0,
m_lineNr
,
262
m_lineUtf16Offset + m_currentLine.size());
263
}
264
265
int
LineWriter
::
column
(
int
index)
266
{
267
if
(index > m_currentLine.size())
268
index = m_currentLine.size();
269
IndentInfo
iInfo(QStringView(m_currentLine).mid(0, index), m_options.formatOptions.tabSize,
270
m_columnNr);
271
return
iInfo
.
column
;
272
}
273
274
void
LineWriter
::
textAddCallback
(LineWriter::TextAddType t)
275
{
276
if
(m_textAddCallbacks.isEmpty())
277
return
;
278
int
iNow = (--m_textAddCallbacks.end()).key() + 1;
279
while
(
true
) {
280
auto
it = m_textAddCallbacks.lowerBound(iNow);
281
if
(it == m_textAddCallbacks.begin())
282
break
;
283
--it;
284
iNow = it.key();
285
if
(!it.value()(*
this
, t))
286
m_textAddCallbacks.erase(it);
287
}
288
}
289
290
void
LineWriter
::
commitLine
(
const
QString &eol, TextAddType tType,
int
untilChar)
291
{
292
if
(untilChar == -1)
293
untilChar = m_currentLine.size();
294
bool
isSpaceOnly = QStringView(m_currentLine).mid(0, untilChar).trimmed().isEmpty();
295
bool
isEmptyNewline = !eol.isEmpty() && isSpaceOnly;
296
// update position, lineNr,...
297
// write out
298
for
(SinkF &sink : m_innerSinks)
299
sink(m_currentLine.mid(0, untilChar));
300
m_utf16Offset
+= untilChar;
301
if
(!eol.isEmpty()) {
302
m_utf16Offset
+= eol.size();
303
for
(SinkF &sink : m_innerSinks)
304
sink(eol);
305
++
m_lineNr
;
306
m_columnNr
= 0;
307
m_lineUtf16Offset
= 0;
308
}
else
{
309
m_columnNr
=
column
(
untilChar
)
;
310
m_lineUtf16Offset
+= untilChar;
311
}
312
if
(untilChar == m_currentLine.size()) {
313
willCommit
(
)
;
314
m_currentLine.clear();
315
}
else
{
316
QString nextLine = m_currentLine.mid(untilChar);
317
m_currentLine = m_currentLine.mid(0, untilChar);
318
lineChanged
(
)
;
319
willCommit
(
)
;
320
m_currentLine = nextLine;
321
}
322
lineChanged
(
)
;
323
m_currentColumnNr
=
column
(m_currentLine.size());
324
TextAddType notifyType = tType;
325
switch
(tType) {
326
case
TextAddType::Normal:
327
if
(eol.isEmpty())
328
notifyType = TextAddType::PartialCommit;
329
else
330
notifyType = TextAddType::Newline;
331
break
;
332
case
TextAddType::Extra:
333
if
(eol.isEmpty())
334
notifyType = TextAddType::NewlineExtra;
335
else
336
notifyType = TextAddType::PartialCommit;
337
break
;
338
case
TextAddType::Newline:
339
case
TextAddType::NewlineSplit:
340
case
TextAddType::NewlineExtra:
341
case
TextAddType::PartialCommit:
342
case
TextAddType::Eof:
343
break
;
344
}
345
if
(isEmptyNewline)
346
++m_committedEmptyLines;
347
else
if
(!isSpaceOnly)
348
m_committedEmptyLines = 0;
349
// notify
350
textAddCallback(notifyType);
351
}
352
353
}
// namespace Dom
354
}
// namespace QQmlJS
355
QT_END_NAMESPACE
356
357
#
include
"moc_qqmldomlinewriter_p.cpp"
QQmlJS::Dom::IndentInfo
Definition
qqmldomlinewriter_p.h:32
QQmlJS::Dom::IndentInfo::column
int column
Definition
qqmldomlinewriter_p.h:37
QQmlJS::Dom::LineWriterOptions
Definition
qqmldomlinewriter_p.h:75
QQmlJS::Dom::LineWriterOptions::TrailingSpace
TrailingSpace
Definition
qqmldomlinewriter_p.h:80
QQmlJS::Dom::LineWriterOptions::TrailingSpace::Remove
@ Remove
Definition
qqmldomlinewriter_p.h:80
QQmlJS::Dom::LineWriterOptions::TrailingSpace::Preserve
@ Preserve
Definition
qqmldomlinewriter_p.h:80
QQmlJS::Dom::LineWriter
Definition
qqmldomlinewriter_p.h:112
QQmlJS::Dom::LineWriter::lineChanged
virtual void lineChanged()
Definition
qqmldomlinewriter_p.h:161
QQmlJS::Dom::LineWriter::m_currentColumnNr
int m_currentColumnNr
Definition
qqmldomlinewriter_p.h:179
QQmlJS::Dom::LineWriter::write
LineWriter & write(QStringView v, TextAddType tType=TextAddType::Normal)
Definition
qqmldomlinewriter.cpp:111
QQmlJS::Dom::LineWriter::ensureSemicolon
LineWriter & ensureSemicolon(TextAddType t=TextAddType::Extra)
Definition
qqmldomlinewriter.cpp:49
QQmlJS::Dom::LineWriter::handleTrailingSpace
void handleTrailingSpace(LineWriterOptions::TrailingSpace s)
Definition
qqmldomlinewriter.cpp:231
QQmlJS::Dom::LineWriter::column
int column(int localIndex)
Definition
qqmldomlinewriter.cpp:265
QQmlJS::Dom::LineWriter::ensureNewline
LineWriter & ensureNewline(int nNewlines=1, TextAddType t=TextAddType::Extra)
Definition
qqmldomlinewriter.cpp:26
QQmlJS::Dom::LineWriter::ensureSpace
LineWriter & ensureSpace(TextAddType t=TextAddType::Extra)
Definition
qqmldomlinewriter.cpp:42
QQmlJS::Dom::LineWriter::m_lineNr
int m_lineNr
Definition
qqmldomlinewriter_p.h:175
QQmlJS::Dom::LineWriter::eof
void eof(bool ensureNewline=true)
Definition
qqmldomlinewriter.cpp:167
QQmlJS::Dom::LineWriter::m_columnNr
int m_columnNr
Definition
qqmldomlinewriter_p.h:176
QQmlJS::Dom::LineWriter::addNewlinesAutospacerCallback
int addNewlinesAutospacerCallback(int nLines)
Definition
qqmldomlinewriter.cpp:188
QQmlJS::Dom::LineWriter::reindentAndSplit
virtual void reindentAndSplit(const QString &eol, bool eof=false)
Definition
qqmldomlinewriter.cpp:250
QQmlJS::Dom::LineWriter::m_lineUtf16Offset
int m_lineUtf16Offset
Definition
qqmldomlinewriter_p.h:177
QQmlJS::Dom::LineWriter::commitLine
void commitLine(const QString &eol, TextAddType t=TextAddType::Normal, int untilChar=-1)
Definition
qqmldomlinewriter.cpp:290
QQmlJS::Dom::LineWriter::currentSourceLocation
SourceLocation currentSourceLocation() const
Definition
qqmldomlinewriter.cpp:259
QQmlJS::Dom::LineWriter::m_utf16Offset
int m_utf16Offset
Definition
qqmldomlinewriter_p.h:180
QQmlJS::Dom::LineWriter::flush
void flush()
Definition
qqmldomlinewriter.cpp:161
QQmlJS::Dom::LineWriter::ensureSpace
LineWriter & ensureSpace(QStringView space, TextAddType t=TextAddType::Extra)
Definition
qqmldomlinewriter.cpp:56
QQmlJS::Dom::LineWriter::willCommit
virtual void willCommit()
Definition
qqmldomlinewriter_p.h:163
QQmlJS::Dom::LineWriter::committedLocation
SourceLocation committedLocation() const
Definition
qqmldomlinewriter.cpp:174
QQmlJS::Dom::LineWriter::setLineIndent
void setLineIndent(int indentAmount)
Definition
qqmldomlinewriter.cpp:207
QQmlJS::Dom::LineWriter::addTextAddCallback
int addTextAddCallback(std::function< bool(LineWriter &, TextAddType)> callback)
Definition
qqmldomlinewriter.cpp:179
QQmlJS::Dom::LineWriter::textAddCallback
void textAddCallback(TextAddType t)
Definition
qqmldomlinewriter.cpp:274
QQmlJS::Dom::LineWriter::LineWriter
LineWriter(const SinkF &innerSink, const QString &fileName, const LineWriterOptions &options=LineWriterOptions(), int lineNr=0, int columnNr=0, int utf16Offset=0, const QString ¤tLine=QString())
Definition
qqmldomlinewriter.cpp:12
QQmlJS::Dom
Definition
qqmljsimportvisitor_p.h:38
QQmlJS::Dom::matchHelper
static QRegularExpressionMatch matchHelper(QRegularExpression &re, String &&s, Args &&...args)
Definition
qqmldomlinewriter.cpp:106
QQmlJS
Definition
qv4bytecodegenerator_p.h:27
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
std
[33]
Definition
src_corelib_tools_qhash.cpp:421
qtdeclarative
src
qmldom
qqmldomlinewriter.cpp
Generated on
for Qt by
1.18.0