aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/qmldom/CMakeLists.txt22
-rw-r--r--src/qmldom/qmldom.pro16
-rw-r--r--src/qmldom/qqmldom_global.h57
-rw-r--r--src/qmldom/qqmldomconstants_p.h87
-rw-r--r--src/qmldom/qqmldomstringdumper.cpp238
-rw-r--r--src/qmldom/qqmldomstringdumper_p.h152
-rw-r--r--src/src.pro2
-rw-r--r--sync.profile1
-rw-r--r--tests/auto/.prev_CMakeLists.txt1
-rw-r--r--tests/auto/CMakeLists.txt1
-rw-r--r--tests/auto/auto.pro1
-rw-r--r--tests/auto/qmldom/CMakeLists.txt3
-rw-r--r--tests/auto/qmldom/qmldom.pro4
-rw-r--r--tests/auto/qmldom/stringdumper/CMakeLists.txt20
-rw-r--r--tests/auto/qmldom/stringdumper/stringdumper.pro26
-rw-r--r--tests/auto/qmldom/stringdumper/tst_qmldomstringdumper.cpp115
17 files changed, 747 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index bac92c5a38..18c5f50c01 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -38,6 +38,7 @@ add_subdirectory(plugins)
if(QT_FEATURE_qml_devtools)
add_subdirectory(qmldevtools)
+ add_subdirectory(qmldom)
add_subdirectory(qmlcompiler)
# Build qmlcachegen now, so that we can use it in src/imports.
diff --git a/src/qmldom/CMakeLists.txt b/src/qmldom/CMakeLists.txt
new file mode 100644
index 0000000000..2e7134dd40
--- /dev/null
+++ b/src/qmldom/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Generated from qmldom.pro.
+
+#####################################################################
+## QmlCompiler Module:
+#####################################################################
+
+qt_internal_add_module(QmlDom
+ STATIC
+ INTERNAL_MODULE
+ SOURCES
+ qqmldom_global.h
+ qqmldomconstants_p.h
+ qqmldomstringdumper.cpp qqmldomstringdumper_p.h
+ DEFINES
+ QMLDOM_LIBRARY
+ PUBLIC_LIBRARIES
+ Qt::CorePrivate
+ Qt::QmlDevToolsPrivate
+)
+
+#### Keys ignored in scope 1:.:.:qmlcompiler.pro:<TRUE>:
+# _OPTION = "host_build"
diff --git a/src/qmldom/qmldom.pro b/src/qmldom/qmldom.pro
new file mode 100644
index 0000000000..282566cc9d
--- /dev/null
+++ b/src/qmldom/qmldom.pro
@@ -0,0 +1,16 @@
+option(host_build)
+TARGET = QtQmlDom
+QT = core-private qmldevtools-private
+CONFIG += minimal_syncqt internal_module generated_privates
+
+DEFINES += QMLDOM_LIBRARY
+
+SOURCES += \
+ $$PWD/qqmldomstringdumper.cpp
+
+HEADERS += \
+ $$PWD/qqmldom_global.h \
+ $$PWD/qqmldomconstants_p.h \
+ $$PWD/qqmldomstringdumper_p.h
+
+load(qt_module)
diff --git a/src/qmldom/qqmldom_global.h b/src/qmldom/qqmldom_global.h
new file mode 100644
index 0000000000..d76f6efeac
--- /dev/null
+++ b/src/qmldom/qqmldom_global.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**/
+#ifndef QMLDOM_GLOBAL_H
+#define QMLDOM_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(QMLDOM_DYNAMIC)
+#if defined(QMLDOM_LIBRARY)
+# define QMLDOM_EXPORT Q_DECL_EXPORT
+#else
+# define QMLDOM_EXPORT Q_DECL_IMPORT
+#endif
+#else
+# define QMLDOM_EXPORT
+#endif
+
+QT_BEGIN_NAMESPACE
+// avoid annoying warning about missing QT_BEGIN_NAMESPACE...
+QT_END_NAMESPACE
+
+#endif // QMLDOM_GLOBAL_H
diff --git a/src/qmldom/qqmldomconstants_p.h b/src/qmldom/qqmldomconstants_p.h
new file mode 100644
index 0000000000..43cbbdda28
--- /dev/null
+++ b/src/qmldom/qqmldomconstants_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**/
+#ifndef QQMLDOMCONSTANTS_P_H
+#define QQMLDOMCONSTANTS_P_H
+
+//
+// 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 <QtCore/QObject>
+#include <QtCore/QMetaObject>
+
+QT_BEGIN_NAMESPACE
+
+namespace QQmlJS{
+namespace Dom {
+
+Q_NAMESPACE_EXPORT(QMLDOM_EXPORT)
+
+enum class EscapeOptions{
+ OuterQuotes,
+ NoOuterQuotes
+};
+Q_ENUM_NS(EscapeOptions)
+
+enum class ErrorLevel{
+ Debug,
+ Info,
+ Hint, // cosmetic or convention
+ MaybeWarning, // possibly a warning, insufficient information
+ Warning,
+ MaybeError,
+ Error,
+ Fatal
+};
+Q_ENUM_NS(ErrorLevel)
+
+} // end namespace Dom
+} // end namespace QQmlJS
+
+QT_END_NAMESPACE
+
+#endif // QQMLDOMCONSTANTS_P_H
diff --git a/src/qmldom/qqmldomstringdumper.cpp b/src/qmldom/qqmldomstringdumper.cpp
new file mode 100644
index 0000000000..1788d79d3d
--- /dev/null
+++ b/src/qmldom/qqmldomstringdumper.cpp
@@ -0,0 +1,238 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**/
+#include "qqmldomstringdumper_p.h"
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace QQmlJS {
+namespace Dom {
+
+/*!
+ * \internal
+ * \tn QQmlJS::Dom::Sink
+ * \brief A Sink is a function that accepts a QStringView as input
+ *
+ * A Sink it the core element of a text based stream oriented output.
+ * It is simply a function accepting a QStringView as input.
+ */
+
+/*!
+ * \internal
+ * \tn QQmlJS::Dom::sinkInt
+ * \brief writes an integer to a sink without any axtra heap allocation
+ * \param sink where to write
+ * \param i the integer to write out
+ *
+ * mainly for debugging/fatal errors
+ */
+
+/*!
+ * \internal
+ * \class QQmlJS::Dom::Dumper
+ * \brief Helper class to accept eithe a string or a dumper (a function that writes to a sink)
+ *
+ * Using a Dumper as input parameter one always obtains a dumper (i.e. a
+ * std::function<void(std::function<void(QStringView)>)> , but can pass in any
+ * object accepted by QStringView, and it is automatically converted to a dumper.
+ */
+
+/*!
+ * \internal
+ * \brief Converts a dumper to a string
+ * \param writer The dumper convert to a string
+ */
+QString dumperToString(Dumper writer)
+{
+ QString s;
+ QTextStream d(&s);
+ writer([&d](QStringView s){ d << s; });
+ d.flush();
+ return s;
+}
+
+/*!
+ * \internal
+ * \brief dumps a string as quoted string (escaping things like quotes or newlines)
+ * \param sink The sink to write the quoted string to
+ * \param s The string to sink
+ * \param options If quotes should be outputted around the string (defaults to yes)
+ */
+void sinkEscaped(Sink sink, QStringView s, EscapeOptions options) {
+ if (options == EscapeOptions::OuterQuotes)
+ sink(u"\"");
+ int it0=0;
+ for (int it = 0; it < s.length();++it) {
+ QChar c=s[it];
+ bool noslash = c != QLatin1Char('\\');
+ bool noquote = c != QLatin1Char('"');
+ bool nonewline = c != QLatin1Char('\n');
+ bool noreturn = c != QLatin1Char('\r');
+ if (noslash && noquote && nonewline && noreturn)
+ continue;
+ sink(s.mid(it0, it - it0));
+ it0 = it + 1;
+ if (!noslash)
+ sink(u"\\\\");
+ else if (!noquote)
+ sink(u"\\\"");
+ else if (!nonewline)
+ sink(u"\\n");
+ else if (!noreturn)
+ sink(u"\\r");
+ else
+ Q_ASSERT(0);
+ }
+ sink(s.mid(it0, s.length() - it0));
+ if (options == EscapeOptions::OuterQuotes)
+ sink(u"\"");
+}
+
+/*!
+ * \internal
+ * \brief Dumps a string describing the given error level (ErrorLevel::Error -> Error,...)
+ * \param s the sink to write to
+ * \param level the level to describe
+ */
+void dumpErrorLevel(Sink s, ErrorLevel level)
+{
+ switch (level) {
+ case ErrorLevel::Debug:
+ s(u"Debug");
+ break;
+ case ErrorLevel::Info:
+ s(u"Info");
+ break;
+ case ErrorLevel::Hint:
+ s(u"Hint");
+ break;
+ case ErrorLevel::MaybeWarning:
+ s(u"MaybeWarn");
+ break;
+ case ErrorLevel::Warning:
+ s(u"Warning");
+ break;
+ case ErrorLevel::MaybeError:
+ s(u"MaybeErr");
+ break;
+ case ErrorLevel::Error:
+ s(u"Error");
+ break;
+ case ErrorLevel::Fatal:
+ s(u"Fatal");
+ break;
+ }
+
+}
+
+void dumperToQDebug(Dumper dumper, QDebug debug)
+{
+ QDebug & d = debug.noquote().nospace();
+ dumper([&d](QStringView s){
+ d << s;
+ });
+}
+
+/*!
+ * \internal
+ * \brief writes the dumper to the QDebug object corrsponding to the given error level
+ * \param level the error level of the message
+ * \param dumper the dumper that writes a message
+ */
+void dumperToQDebug(Dumper dumper, ErrorLevel level)
+{
+ QDebug d = qDebug().noquote().nospace();
+ switch (level) {
+ case ErrorLevel::Debug:
+ break;
+ case ErrorLevel::Info:
+ case ErrorLevel::Hint:
+ d = qInfo().noquote().nospace();
+ break;
+ case ErrorLevel::MaybeWarning:
+ case ErrorLevel::Warning:
+ d = qWarning().noquote().nospace();
+ break;
+ case ErrorLevel::MaybeError:
+ case ErrorLevel::Error:
+ case ErrorLevel::Fatal: // should be handled differently (avoid allocations...), we try to catch them before ending up here
+ d = qCritical().noquote().nospace();
+ break;
+ }
+ dumper([&d](QStringView s){
+ d << s;
+ });
+}
+
+/*!
+ * \internal
+ * \brief sinks the requested amount of spaces
+ */
+void sinkIndent(Sink s, int indent)
+{
+ if (indent > 0) {
+ QStringView spaces = u" ";
+ while (indent > spaces.length()) {
+ s(spaces);
+ indent -= spaces.length();
+ }
+ s(spaces.left(indent));
+ }
+}
+
+/*!
+ * \internal
+ * \brief sinks a neline and indents by the given amount
+ */
+void sinkNewline(Sink s, int indent)
+{
+ s(u"\n");
+ if (indent > 0)
+ sinkIndent(s, indent);
+}
+
+/*!
+ * \internal
+ * \fn QQmlJS::Dom::devNull
+ * \brief A sink that ignores whatever it receives
+ */
+
+} // end namespace Dom
+} // end namespace QQmlJS
+
+QT_END_NAMESPACE
diff --git a/src/qmldom/qqmldomstringdumper_p.h b/src/qmldom/qqmldomstringdumper_p.h
new file mode 100644
index 0000000000..7669bfc882
--- /dev/null
+++ b/src/qmldom/qqmldomstringdumper_p.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**/
+#ifndef DUMPER_H
+#define DUMPER_H
+
+//
+// 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 "qqmldomconstants_p.h"
+
+#include <QtCore/QString>
+#include <QtCore/QStringView>
+#include <QtCore/QDebug>
+
+#include <type_traits>
+
+QT_BEGIN_NAMESPACE
+
+namespace QQmlJS {
+namespace Dom {
+
+using Sink = std::function<void(QStringView)>;
+using DumperFunction = std::function<void(Sink)>;
+
+class Dumper{
+public:
+ DumperFunction dumper;
+private:
+ // We want to avoid the limit of one user conversion:
+ // after doing (* -> QStringView) we cannot have QStringView -> Dumper, as it
+ // would be the second user defined conversion.
+ // For a similar reason we have a template to accept function<void(Sink)> .
+ // The end result is that void f(Dumper) can be called nicely, and avoid overloads:
+ // f(u"bla"), f(QLatin1String("bla")), f(QString()), f([](Sink s){...}),...
+ template <typename T>
+ using if_compatible_dumper = typename
+ std::enable_if<std::is_convertible<T, DumperFunction>::value, bool>::type;
+
+ template<typename T>
+ using if_string_view_convertible = typename
+ std::enable_if<std::is_convertible_v<T, QStringView>, bool>::type;
+
+public:
+ Dumper(QStringView s):
+ dumper([s](Sink sink){ sink(s); }) {}
+
+ Dumper(std::nullptr_t): Dumper(QStringView(nullptr)) {}
+
+ template <typename Stringy, if_string_view_convertible<Stringy> = true>
+ Dumper(Stringy string):
+ Dumper(QStringView(string)) {}
+
+ template <typename U, if_compatible_dumper<U> = true>
+ Dumper(U f): dumper(f) {}
+
+ void operator()(Sink s) { dumper(s); }
+};
+
+template <typename T>
+void sinkInt(Sink s, T i) {
+ const int BUFSIZE = 42; // safe up to 128 bits
+ QChar buf[BUFSIZE];
+ int ibuf = BUFSIZE;
+ buf[--ibuf] = QChar(0);
+ bool neg = false;
+ if (i < 0)
+ neg=true;
+ int digit = i % 10;
+ i = i / 10;
+ if constexpr (std::is_signed_v<T>) {
+ if (neg) { // we change the sign here because -numeric_limits<T>::min() == numeric_limits<T>::min()
+ i = -i;
+ digit = - digit;
+ }
+ }
+ buf[--ibuf] = QChar::fromLatin1('0' + digit);
+ while (i > 0 && ibuf > 0) {
+ digit = i % 10;
+ buf[--ibuf] = QChar::fromLatin1('0' + digit);
+ i = i / 10;
+ }
+ if (neg && ibuf > 0)
+ buf[--ibuf] = QChar::fromLatin1('-');
+ s(QStringView(&buf[ibuf], BUFSIZE - ibuf -1));
+}
+
+QMLDOM_EXPORT QString dumperToString(Dumper writer);
+
+QMLDOM_EXPORT void sinkEscaped(Sink sink, QStringView s,
+ EscapeOptions options = EscapeOptions::OuterQuotes);
+
+inline void devNull(QStringView) {}
+
+QMLDOM_EXPORT void sinkIndent(Sink s, int indent);
+
+QMLDOM_EXPORT void sinkNewline(Sink s, int indent = 0);
+
+QMLDOM_EXPORT void dumpErrorLevel(Sink s, ErrorLevel level);
+
+QMLDOM_EXPORT void dumperToQDebug(Dumper dumper, QDebug debug);
+
+QMLDOM_EXPORT void dumperToQDebug(Dumper dumper, ErrorLevel level = ErrorLevel::Debug);
+
+} // end namespace Dom
+} // end namespace QQmlJS
+QT_END_NAMESPACE
+
+#endif // DUMPER_H
diff --git a/src/src.pro b/src/src.pro
index d4e66be413..bd62073bd2 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -41,10 +41,12 @@ SUBDIRS += \
qtConfig(qml-devtools) {
SUBDIRS += \
qmldevtools \
+ qmldom \
qmlcompiler
qmldevtools.depends = qml
qmlcompiler.depends = qmldevtools
+ qmldom.depends = qmldevtools
}
diff --git a/sync.profile b/sync.profile
index eac24770f1..2ec61fb90d 100644
--- a/sync.profile
+++ b/sync.profile
@@ -10,6 +10,7 @@
"QtQmlModels" => "$basedir/src/qmlmodels",
"QtQmlWorkerScript" => "$basedir/src/qmlworkerscript",
"QtQmlCompiler" => "$basedir/src/qmlcompiler",
+ "QtQmlDom" => "$basedir/src/qmldom",
);
%inject_headers = (
"$basedir/src/qml" => [ "^qqmljsgrammar_p.h", "^qqmljsparser_p.h", "^qml_compile_hash_p.h" ],
diff --git a/tests/auto/.prev_CMakeLists.txt b/tests/auto/.prev_CMakeLists.txt
index addaaa6bde..c9bc48d151 100644
--- a/tests/auto/.prev_CMakeLists.txt
+++ b/tests/auto/.prev_CMakeLists.txt
@@ -1,6 +1,7 @@
# Generated from auto.pro.
add_subdirectory(qml)
+add_subdirectory(qmldom)
add_subdirectory(quick)
add_subdirectory(quicktest)
add_subdirectory(qmldevtools)
diff --git a/tests/auto/CMakeLists.txt b/tests/auto/CMakeLists.txt
index cdec7346eb..e3102d18c4 100644
--- a/tests/auto/CMakeLists.txt
+++ b/tests/auto/CMakeLists.txt
@@ -1,6 +1,7 @@
# Generated from auto.pro.
add_subdirectory(qml)
+add_subdirectory(qmldom)
add_subdirectory(quick)
add_subdirectory(quicktest)
add_subdirectory(qmldevtools)
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index 35dfe5dfbd..071d67f4f2 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -11,6 +11,7 @@ SUBDIRS=\
qtHaveModule(gui): SUBDIRS += particles
qtHaveModule(widgets): SUBDIRS += quickwidgets
+qtHaveModule(qmldom): SUBDIRS += qmldom
# console applications not supported
uikit: SUBDIRS -= qmltest
diff --git a/tests/auto/qmldom/CMakeLists.txt b/tests/auto/qmldom/CMakeLists.txt
new file mode 100644
index 0000000000..897069f608
--- /dev/null
+++ b/tests/auto/qmldom/CMakeLists.txt
@@ -0,0 +1,3 @@
+# Generated from qmldom.pro.
+
+add_subdirectory(stringdumper)
diff --git a/tests/auto/qmldom/qmldom.pro b/tests/auto/qmldom/qmldom.pro
new file mode 100644
index 0000000000..6a7b30274c
--- /dev/null
+++ b/tests/auto/qmldom/qmldom.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+
+SUBDIRS += \
+ stringdumper
diff --git a/tests/auto/qmldom/stringdumper/CMakeLists.txt b/tests/auto/qmldom/stringdumper/CMakeLists.txt
new file mode 100644
index 0000000000..c72467caf9
--- /dev/null
+++ b/tests/auto/qmldom/stringdumper/CMakeLists.txt
@@ -0,0 +1,20 @@
+# Generated from stringdumper.pro.
+
+#####################################################################
+## tst_qmldomstringdumper Binary:
+#####################################################################
+
+qt_internal_add_test(tst_qmldomstringdumper
+ SOURCES
+ tst_qmldomstringdumper.cpp
+ DEFINES
+ QT_DEPRECATED_WARNINGS
+ PUBLIC_LIBRARIES
+ Qt::Core
+ Qt::QmlDevToolsPrivate
+ Qt::QmlDomPrivate
+ Qt::Test
+)
+
+## Scopes:
+#####################################################################
diff --git a/tests/auto/qmldom/stringdumper/stringdumper.pro b/tests/auto/qmldom/stringdumper/stringdumper.pro
new file mode 100644
index 0000000000..dc9f1a4257
--- /dev/null
+++ b/tests/auto/qmldom/stringdumper/stringdumper.pro
@@ -0,0 +1,26 @@
+QT = core qmldevtools-private testlib
+TARGET = tst_qmldomstringdumper
+
+
+INCLUDEPATH += ../../../../src/qmldom
+
+
+CONFIG += c++11 console
+CONFIG -= app_bundle
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+SOURCES += \
+ tst_qmldomstringdumper.cpp
+
+
+load(qt_common)
diff --git a/tests/auto/qmldom/stringdumper/tst_qmldomstringdumper.cpp b/tests/auto/qmldom/stringdumper/tst_qmldomstringdumper.cpp
new file mode 100644
index 0000000000..04b9899d0f
--- /dev/null
+++ b/tests/auto/qmldom/stringdumper/tst_qmldomstringdumper.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**/
+#include <QtQmlDom/private/qqmldomstringdumper_p.h>
+
+#include <QtTest/QtTest>
+#include <QTextStream>
+#include <QDebug>
+
+#include <limits>
+
+QT_BEGIN_NAMESPACE
+namespace QQmlJS {
+namespace Dom {
+
+class TestStringDumper: public QObject
+{
+ Q_OBJECT
+private slots:
+ void testDumperToString() {
+ QCOMPARE(dumperToString(u"bla"), QStringLiteral(u"bla"));
+ QCOMPARE(dumperToString([](Sink s) { s(u"bla"); s(u"bla"); }), QStringLiteral(u"blabla"));
+ }
+
+ void testSinkInt() {
+ QCOMPARE(dumperToString([](Sink s) { sinkInt(s, 1); }), QStringLiteral(u"1"));
+ QCOMPARE(dumperToString([](Sink s) { sinkInt(s, 0); }), QStringLiteral(u"0"));
+ QCOMPARE(dumperToString([](Sink s) { sinkInt(s, -1); }), QStringLiteral(u"-1"));
+ QCOMPARE(dumperToString([](Sink s) { sinkInt(s, std::numeric_limits<qint32>::max()); }), QStringLiteral(u"2147483647"));
+ QCOMPARE(dumperToString([](Sink s) { sinkInt(s, std::numeric_limits<qint32>::min()); }), QStringLiteral(u"-2147483648"));
+ QCOMPARE(dumperToString([](Sink s) { sinkInt(s, std::numeric_limits<quint32>::max()); }), QStringLiteral(u"4294967295"));
+ QCOMPARE(dumperToString([](Sink s) { sinkInt(s, std::numeric_limits<qint64>::min()); }), QStringLiteral(u"-9223372036854775808"));
+ QCOMPARE(dumperToString([](Sink s) { sinkInt(s, std::numeric_limits<qint64>::max()); }), QStringLiteral(u"9223372036854775807"));
+ QCOMPARE(dumperToString([](Sink s) { sinkInt(s, std::numeric_limits<quint64>::max()); }), QStringLiteral(u"18446744073709551615"));
+ }
+
+ void testSinkEscaped() {
+ QCOMPARE(dumperToString([](Sink s) { sinkEscaped(s, u""); }), QStringLiteral(u"\"\""));
+ QStringView s1 = u"bla:\"bla\\\""; // uR"(bla:"bla\")";
+ QStringView s1Escaped = u"\"bla:\\\"bla\\\\\\\"\"";
+ QCOMPARE(dumperToString([s1](Sink s) { sinkEscaped(s, s1); }), s1Escaped);
+ QCOMPARE(dumperToString([](Sink s) { sinkEscaped(s, u"", EscapeOptions::NoOuterQuotes); }), QStringLiteral(u""));
+ QStringView s2 = u"bla:\"bla\\\"\n";
+ QStringView s2Escaped = u"bla:\\\"bla\\\\\\\"\\n"; // uR"(bla:\"bla\\\"\n)"
+ QCOMPARE(dumperToString([s2](Sink s) { sinkEscaped(s, s2, EscapeOptions::NoOuterQuotes); }), s2Escaped);
+ }
+
+ void testDevNull() {
+ sinkEscaped(devNull, u"");
+ sinkEscaped(devNull, u"bla:\"bla\\\"\n");
+ }
+
+ void testSinkIndent() {
+ QCOMPARE(dumperToString([](Sink s) { sinkIndent(s, 0); }), QStringLiteral(u""));
+ QCOMPARE(dumperToString([](Sink s) { sinkIndent(s, 1); }), QStringLiteral(u" "));
+ QCOMPARE(dumperToString([](Sink s) { sinkIndent(s, 10); }), QStringLiteral(u" "));
+ QCOMPARE(dumperToString([](Sink s) { sinkIndent(s, 40); }), QStringLiteral(u" ").repeated(4));
+ }
+
+
+ void testSinkNewline(){
+ QCOMPARE(dumperToString([](Sink s) { sinkNewline(s); }), QStringLiteral(u"\n"));
+ QCOMPARE(dumperToString([](Sink s) { sinkNewline(s, 0); }), QStringLiteral(u"\n"));
+ QCOMPARE(dumperToString([](Sink s) { sinkNewline(s, 1); }), QStringLiteral(u"\n "));
+ QCOMPARE(dumperToString([](Sink s) { sinkNewline(s, 10); }), QStringLiteral(u"\n "));
+ QCOMPARE(dumperToString([](Sink s) { sinkNewline(s, 40); }), QStringLiteral(u"\n") + QStringLiteral(u" ").repeated(4));
+ }
+
+ void testDumpErrorLevel(){
+ QCOMPARE(dumperToString([](Sink s) { dumpErrorLevel(s, ErrorLevel::Hint); }), QStringLiteral(u"Hint"));
+ QCOMPARE(dumperToString([](Sink s) { dumpErrorLevel(s, ErrorLevel::Error); }), QStringLiteral(u"Error"));
+ QCOMPARE(dumperToString([](Sink s) { dumpErrorLevel(s, ErrorLevel::Warning); }), QStringLiteral(u"Warning"));
+ }
+};
+
+} // namespace Dom
+} // namespace QQmlJS
+QT_END_NAMESPACE
+
+QTEST_MAIN(QQmlJS::Dom::TestStringDumper)
+#include "tst_qmldomstringdumper.moc"