aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmldom/qqmldomlinewriter_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qmldom/qqmldomlinewriter_p.h')
-rw-r--r--src/qmldom/qqmldomlinewriter_p.h225
1 files changed, 225 insertions, 0 deletions
diff --git a/src/qmldom/qqmldomlinewriter_p.h b/src/qmldom/qqmldomlinewriter_p.h
new file mode 100644
index 0000000000..86da8d6f54
--- /dev/null
+++ b/src/qmldom/qqmldomlinewriter_p.h
@@ -0,0 +1,225 @@
+// 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
+
+#ifndef QQMLDOMLINEWRITER_P
+#define QQMLDOMLINEWRITER_P
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qqmldom_global.h"
+#include "qqmldomstringdumper_p.h"
+
+#include <QtQml/private/qqmljssourcelocation_p.h>
+#include <QtCore/QObject>
+#include <QtCore/QAtomicInt>
+#include <QtCore/QMap>
+#include <functional>
+
+QT_BEGIN_NAMESPACE
+namespace QQmlJS {
+namespace Dom {
+
+class IndentInfo
+{
+public:
+ QStringView string;
+ QStringView trailingString;
+ int nNewlines = 0;
+ int column = 0;
+
+ IndentInfo(QStringView line, int tabSize, int initialColumn = 0)
+ {
+ string = line;
+ int fixup = 0;
+ if (initialColumn < 0) // we do not want % of negative numbers
+ fixup = (-initialColumn + tabSize - 1) / tabSize * tabSize;
+ column = initialColumn + fixup;
+ const QChar tab = QLatin1Char('\t');
+ int iStart = 0;
+ int len = line.size();
+ for (int i = 0; i < len; i++) {
+ if (line[i] == tab)
+ column = ((column / tabSize) + 1) * tabSize;
+ else if (line[i] == QLatin1Char('\n')
+ || (line[i] == QLatin1Char('\r')
+ && (i + 1 == len || line[i + 1] != QLatin1Char('\n')))) {
+ iStart = i + 1;
+ ++nNewlines;
+ column = 0;
+ } else if (!line[i].isLowSurrogate())
+ column++;
+ }
+ column -= fixup;
+ trailingString = line.mid(iStart);
+ }
+};
+
+class QMLDOM_EXPORT FormatOptions
+{
+public:
+ int tabSize = 4;
+ int indentSize = 4;
+ bool useTabs = false;
+};
+
+class QMLDOM_EXPORT LineWriterOptions
+{
+ Q_GADGET
+public:
+ enum class LineEndings { Unix, Windows, OldMacOs };
+ Q_ENUM(LineEndings)
+ enum class TrailingSpace { Preserve, Remove };
+ Q_ENUM(TrailingSpace)
+ enum class Update { None = 0, Expressions = 0x1, Locations = 0x2, All = 0x3, Default = All };
+ Q_ENUM(Update)
+ Q_DECLARE_FLAGS(Updates, Update)
+ enum class AttributesSequence { Normalize, Preserve };
+ Q_ENUM(AttributesSequence)
+
+ int maxLineLength = -1;
+ int strongMaxLineExtra = 20;
+ int minContentLength = 10;
+#if defined (Q_OS_WIN)
+ LineEndings lineEndings = LineEndings::Windows;
+#else
+ LineEndings lineEndings = LineEndings::Unix;
+#endif
+ TrailingSpace codeTrailingSpace = TrailingSpace::Remove;
+ TrailingSpace commentTrailingSpace = TrailingSpace::Remove;
+ TrailingSpace stringTrailingSpace = TrailingSpace::Preserve;
+ FormatOptions formatOptions;
+ Updates updateOptions = Update::Default;
+ AttributesSequence attributesSequence = AttributesSequence::Normalize;
+ bool objectsSpacing = false;
+ bool functionsSpacing = false;
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(LineWriterOptions::Updates)
+
+using PendingSourceLocationId = int;
+using PendingSourceLocationIdAtomic = QAtomicInt;
+class LineWriter;
+
+class QMLDOM_EXPORT PendingSourceLocation
+{
+ Q_GADGET
+public:
+ quint32 utf16Start() const;
+ quint32 utf16End() const;
+ void changeAtOffset(quint32 offset, qint32 change, qint32 colChange, qint32 lineChange);
+ void commit();
+ PendingSourceLocationId id;
+ SourceLocation value;
+ SourceLocation *toUpdate = nullptr;
+ std::function<void(SourceLocation)> updater = nullptr;
+ bool open = true;
+};
+
+class QMLDOM_EXPORT LineWriter
+{
+ Q_GADGET
+public:
+ enum class TextAddType {
+ Normal,
+ Extra,
+ Newline,
+ NewlineSplit,
+ NewlineExtra,
+ PartialCommit,
+ Eof
+ };
+
+ LineWriter(const SinkF &innerSink, const QString &fileName,
+ const LineWriterOptions &options = LineWriterOptions(), int lineNr = 0,
+ int columnNr = 0, int utf16Offset = 0, const QString &currentLine = QString());
+ std::function<void(QStringView)> sink()
+ {
+ return [this](QStringView s) { this->write(s); };
+ }
+
+ virtual ~LineWriter() { }
+
+ QList<SinkF> innerSinks() { return m_innerSinks; }
+ void addInnerSink(const SinkF &s) { m_innerSinks.append(s); }
+ LineWriter &ensureNewline(int nNewlines = 1, TextAddType t = TextAddType::Extra);
+ LineWriter &ensureSpace(TextAddType t = TextAddType::Extra);
+ LineWriter &ensureSpace(QStringView space, TextAddType t = TextAddType::Extra);
+
+ LineWriter &newline()
+ {
+ write(u"\n");
+ return *this;
+ }
+ LineWriter &space()
+ {
+ write(u" ");
+ return *this;
+ }
+ LineWriter &write(QStringView v, TextAddType tType = TextAddType::Normal);
+ LineWriter &write(QStringView v, SourceLocation *toUpdate)
+ {
+ auto pLoc = startSourceLocation(toUpdate);
+ write(v);
+ endSourceLocation(pLoc);
+ return *this;
+ }
+ void commitLine(const QString &eol, TextAddType t = TextAddType::Normal, int untilChar = -1);
+ void flush();
+ void eof(bool ensureNewline = true);
+ SourceLocation committedLocation() const;
+ PendingSourceLocationId startSourceLocation(SourceLocation *);
+ PendingSourceLocationId startSourceLocation(std::function<void(SourceLocation)>);
+ void endSourceLocation(PendingSourceLocationId);
+ quint32 counter() const { return m_counter; }
+ int addTextAddCallback(std::function<bool(LineWriter &, TextAddType)> callback);
+ bool removeTextAddCallback(int i) { return m_textAddCallbacks.remove(i); }
+ int addNewlinesAutospacerCallback(int nLines);
+ void handleTrailingSpace(LineWriterOptions::TrailingSpace s);
+ void setLineIndent(int indentAmount);
+ QString fileName() const { return m_fileName; }
+ const QString &currentLine() const { return m_currentLine; }
+ const LineWriterOptions &options() const { return m_options; }
+ virtual void lineChanged() { }
+ virtual void reindentAndSplit(const QString &eol, bool eof = false);
+ virtual void willCommit() { }
+
+private:
+ Q_DISABLE_COPY_MOVE(LineWriter)
+protected:
+ void changeAtOffset(quint32 offset, qint32 change, qint32 colChange, qint32 lineChange);
+ QString eolToWrite() const;
+ SourceLocation currentSourceLocation() const;
+ int column(int localIndex);
+ void textAddCallback(TextAddType t);
+
+ QList<SinkF> m_innerSinks;
+ QString m_fileName;
+ int m_lineNr = 0;
+ int m_columnNr = 0; // columnNr (starts at 0) of committed data
+ int m_lineUtf16Offset = 0; // utf16 offset since last newline (what is typically stores as
+ // SourceLocation::startColumn
+ int m_currentColumnNr = 0; // current columnNr (starts at 0)
+ int m_utf16Offset = 0; // utf16 offset since start for committed data
+ QString m_currentLine;
+ LineWriterOptions m_options;
+ PendingSourceLocationIdAtomic m_lastSourceLocationId;
+ QMap<PendingSourceLocationId, PendingSourceLocation> m_pendingSourceLocations;
+ QAtomicInt m_lastCallbackId;
+ QMap<int, std::function<bool(LineWriter &, TextAddType)>> m_textAddCallbacks;
+ quint32 m_counter = 0;
+ quint32 m_committedEmptyLines = 0x7FFFFFFF;
+ bool m_reindent = true;
+};
+
+} // namespace Dom
+} // namespace QQmlJS
+QT_END_NAMESPACE
+#endif