5#include <QtCore/QCoreApplication>
6#include <QtCore/QRegularExpression>
13 const SinkF &innerSink,
const QString &fileName,
const LineWriterOptions &options,
14 int lineNr,
int columnNr,
int utf16Offset,
const QString ¤tLine)
28 int nToAdd = nNewline;
31 if (m_currentLine.trimmed().isEmpty()) {
33 if (m_committedEmptyLines >=
unsigned(nToAdd))
35 nToAdd -= m_committedEmptyLines;
37 for (
int i = 0; i < nToAdd; ++i)
44 if (!m_currentLine.isEmpty() && !m_currentLine.at(m_currentLine.size() - 1).isSpace())
51 if (!m_currentLine.isEmpty() && m_currentLine.back() != u';')
58 int tabSize = m_options.formatOptions.tabSize;
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);
67 int len = m_currentLine.size();
69 while (i != 0 && m_currentLine.at(i - 1).isSpace())
71 QStringView trailingSpace = QStringView(m_currentLine).mid(i, len - i);
72 int trailingSpaceStartColumn =
74 IndentInfo indExisting(trailingSpace, tabSize, trailingSpaceStartColumn);
75 if (trailingSpaceStartColumn != 0)
76 ind =
IndentInfo(space, tabSize, trailingSpaceStartColumn);
80 m_currentLine.replace(
81 i, len - i, ind.trailingString.toString());
85 write(QStringLiteral(u" ").repeated(ind.column - indExisting.column), t);
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");
102 return QStringLiteral(u"\n");
105template<
typename String,
typename ...Args>
108 return re.matchView(s, args...);
115 static QRegularExpression eolRe(QLatin1String(
117 QRegularExpressionMatch m = matchHelper(eolRe, v);
120 auto i = m.capturedStart(1);
121 auto iEnd = m.capturedEnd(1);
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);
134 write(v.mid(iEnd, v.size() - iEnd));
137 QStringView toAdd = v.mid(0, i);
138 if (!toAdd.trimmed().isEmpty())
139 textAddCallback(tAdd);
141 m_currentLine.append(toAdd);
143 IndentInfo(toAdd, m_options.formatOptions.tabSize, m_currentColumnNr).column;
146 if (!v.trimmed().isEmpty())
147 textAddCallback(tAdd);
148 m_counter += v.size();
149 m_currentLine.append(v);
151 IndentInfo(v, m_options.formatOptions.tabSize, m_currentColumnNr).column;
155 || (m_options.maxLineLength > 0 && m_currentColumnNr > m_options.maxLineLength)) {
156 reindentAndSplit(eol);
163 if (m_currentLine.size() > 0)
164 commitLine(QString());
169 if (shouldEnsureNewline)
171 reindentAndSplit(QString(),
true);
181 int nextId = ++m_lastCallbackId;
182 Q_ASSERT(nextId != 0);
184 m_textAddCallbacks.insert(nextId, callback);
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);
209 int startNonSpace = 0;
210 while (startNonSpace < m_currentLine.size() && m_currentLine.at(startNonSpace).isSpace())
212 int oldColumn =
column(startNonSpace
);
213 if (indentAmount >= 0) {
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);
219 indent = QStringLiteral(u" ").repeated(indentAmount);
221 if (indent != m_currentLine.mid(0, startNonSpace)) {
222 quint32 colChange = indentAmount - oldColumn;
224 m_currentLine = indent + m_currentLine.mid(startNonSpace);
253 if (!eol.isEmpty() || eof) {
254 handleTrailingSpace(m_options.codeTrailingSpace);
261 return SourceLocation(m_utf16Offset + m_currentLine.size(), 0,
m_lineNr,
262 m_lineUtf16Offset + m_currentLine.size());
267 if (index > m_currentLine.size())
268 index = m_currentLine.size();
269 IndentInfo iInfo(QStringView(m_currentLine).mid(0, index), m_options.formatOptions.tabSize,
276 if (m_textAddCallbacks.isEmpty())
278 int iNow = (--m_textAddCallbacks.end()).key() + 1;
280 auto it = m_textAddCallbacks.lowerBound(iNow);
281 if (it == m_textAddCallbacks.begin())
285 if (!it.value()(*
this, t))
286 m_textAddCallbacks.erase(it);
293 untilChar = m_currentLine.size();
294 bool isSpaceOnly = QStringView(m_currentLine).mid(0, untilChar).trimmed().isEmpty();
295 bool isEmptyNewline = !eol.isEmpty() && isSpaceOnly;
298 for (SinkF &sink : m_innerSinks)
299 sink(m_currentLine.mid(0, untilChar));
301 if (!eol.isEmpty()) {
303 for (SinkF &sink : m_innerSinks)
312 if (untilChar == m_currentLine.size()) {
314 m_currentLine.clear();
316 QString nextLine = m_currentLine.mid(untilChar);
317 m_currentLine = m_currentLine.mid(0, untilChar);
320 m_currentLine = nextLine;
324 TextAddType notifyType = tType;
326 case TextAddType::Normal:
328 notifyType = TextAddType::PartialCommit;
330 notifyType = TextAddType::Newline;
332 case TextAddType::Extra:
334 notifyType = TextAddType::NewlineExtra;
336 notifyType = TextAddType::PartialCommit;
338 case TextAddType::Newline:
339 case TextAddType::NewlineSplit:
340 case TextAddType::NewlineExtra:
341 case TextAddType::PartialCommit:
342 case TextAddType::Eof:
346 ++m_committedEmptyLines;
347 else if (!isSpaceOnly)
348 m_committedEmptyLines = 0;
350 textAddCallback(notifyType);
357#include "moc_qqmldomlinewriter_p.cpp"
virtual void lineChanged()
LineWriter & write(QStringView v, TextAddType tType=TextAddType::Normal)
LineWriter & ensureSemicolon(TextAddType t=TextAddType::Extra)
int column(int localIndex)
LineWriter & ensureNewline(int nNewlines=1, TextAddType t=TextAddType::Extra)
LineWriter & ensureSpace(TextAddType t=TextAddType::Extra)
void eof(bool ensureNewline=true)
int addNewlinesAutospacerCallback(int nLines)
virtual void reindentAndSplit(const QString &eol, bool eof=false)
void commitLine(const QString &eol, TextAddType t=TextAddType::Normal, int untilChar=-1)
SourceLocation currentSourceLocation() const
LineWriter & ensureSpace(QStringView space, TextAddType t=TextAddType::Extra)
virtual void willCommit()
SourceLocation committedLocation() const
void setLineIndent(int indentAmount)
int addTextAddCallback(std::function< bool(LineWriter &, TextAddType)> callback)
void textAddCallback(TextAddType t)
LineWriter(const SinkF &innerSink, const QString &fileName, const LineWriterOptions &options=LineWriterOptions(), int lineNr=0, int columnNr=0, int utf16Offset=0, const QString ¤tLine=QString())
static QRegularExpressionMatch matchHelper(QRegularExpression &re, String &&s, Args &&...args)
Combined button and popup list for selecting options.