diff options
-rw-r--r-- | tests/auto/qml/qmlcachegen/qmlcachegen.pro | 3 | ||||
-rw-r--r-- | tests/auto/qml/qmlcachegen/trickypaths.qrc | 2 | ||||
-rw-r--r-- | tests/auto/qml/qmlcachegen/trickypaths_umlaut.qrc | 5 | ||||
-rw-r--r-- | tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp | 22 | ||||
-rw-r--r-- | tests/auto/qml/qmlcachegen/umlaut.qml | 4 | ||||
-rw-r--r-- | tests/auto/qml/qmlcachegen/versionStyleSuffix-1.2-core-yc.qml | 4 | ||||
-rw-r--r-- | tests/auto/qml/qmlcachegen/versionStyleSuffix-1.2-more.qml | 4 | ||||
-rw-r--r-- | tools/qmlcachegen/generateloader.cpp | 54 |
8 files changed, 88 insertions, 10 deletions
diff --git a/tests/auto/qml/qmlcachegen/qmlcachegen.pro b/tests/auto/qml/qmlcachegen/qmlcachegen.pro index 40de4548a7..6dee2a0454 100644 --- a/tests/auto/qml/qmlcachegen/qmlcachegen.pro +++ b/tests/auto/qml/qmlcachegen/qmlcachegen.pro @@ -16,4 +16,7 @@ RESOURCES += jsimport.qml script.js library.js RESOURCES += Enums.qml +# QTBUG-46375 +!win32: RESOURCES += trickypaths_umlaut.qrc + QT += core-private qml-private testlib diff --git a/tests/auto/qml/qmlcachegen/trickypaths.qrc b/tests/auto/qml/qmlcachegen/trickypaths.qrc index 271cf6571e..57977ccf6d 100644 --- a/tests/auto/qml/qmlcachegen/trickypaths.qrc +++ b/tests/auto/qml/qmlcachegen/trickypaths.qrc @@ -1,5 +1,7 @@ <!DOCTYPE RCC><RCC version="1.0"> <qresource prefix="/directory with spaces"> <file alias="file name with spaces.qml">trickypaths.qml</file> +<file>versionStyleSuffix-1.2-core-yc.qml</file> +<file>versionStyleSuffix-1.2-more.qml</file> </qresource> </RCC> diff --git a/tests/auto/qml/qmlcachegen/trickypaths_umlaut.qrc b/tests/auto/qml/qmlcachegen/trickypaths_umlaut.qrc new file mode 100644 index 0000000000..9ca889d692 --- /dev/null +++ b/tests/auto/qml/qmlcachegen/trickypaths_umlaut.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/"> +<file alias="Bäh.qml">umlaut.qml</file> +</qresource> +</RCC> diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp index 3b7d268f7b..6dc54a323e 100644 --- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp +++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp @@ -53,6 +53,7 @@ private slots: void workerScripts(); + void trickyPaths_data(); void trickyPaths(); void scriptImport(); @@ -408,13 +409,26 @@ void tst_qmlcachegen::functionExpressions() QCOMPARE(obj->property("h_connections_handler_called").toBool(), true); } +void tst_qmlcachegen::trickyPaths_data() +{ + QTest::addColumn<QString>("filePath"); + QTest::newRow("path with spaces") << QStringLiteral(":/directory with spaces/file name with spaces.qml"); + QTest::newRow("version style suffix 1") << QStringLiteral(":/directory with spaces/versionStyleSuffix-1.2-core-yc.qml"); + QTest::newRow("version style suffix 2") << QStringLiteral(":/directory with spaces/versionStyleSuffix-1.2-more.qml"); + + // QTBUG-46375 +#if !defined(Q_OS_WIN) + QTest::newRow("path with umlaut") << QStringLiteral(":/Bäh.qml"); +#endif +} + void tst_qmlcachegen::trickyPaths() { - QString pathWithSpaces(QStringLiteral(":/directory with spaces/file name with spaces.qml")); - QVERIFY2(QFile::exists(pathWithSpaces), qPrintable(pathWithSpaces)); - QCOMPARE(QFileInfo(pathWithSpaces).size(), 0); + QFETCH(QString, filePath); + QVERIFY2(QFile::exists(filePath), qPrintable(filePath)); + QCOMPARE(QFileInfo(filePath).size(), 0); QQmlEngine engine; - QQmlComponent component(&engine, QUrl("qrc" + pathWithSpaces)); + QQmlComponent component(&engine, QUrl("qrc" + filePath)); QScopedPointer<QObject> obj(component.create()); QVERIFY(!obj.isNull()); QCOMPARE(obj->property("success").toInt(), 42); diff --git a/tests/auto/qml/qmlcachegen/umlaut.qml b/tests/auto/qml/qmlcachegen/umlaut.qml new file mode 100644 index 0000000000..0836808dc2 --- /dev/null +++ b/tests/auto/qml/qmlcachegen/umlaut.qml @@ -0,0 +1,4 @@ +import QtQml 2.0 +QtObject { + property int success: 42 +} diff --git a/tests/auto/qml/qmlcachegen/versionStyleSuffix-1.2-core-yc.qml b/tests/auto/qml/qmlcachegen/versionStyleSuffix-1.2-core-yc.qml new file mode 100644 index 0000000000..0836808dc2 --- /dev/null +++ b/tests/auto/qml/qmlcachegen/versionStyleSuffix-1.2-core-yc.qml @@ -0,0 +1,4 @@ +import QtQml 2.0 +QtObject { + property int success: 42 +} diff --git a/tests/auto/qml/qmlcachegen/versionStyleSuffix-1.2-more.qml b/tests/auto/qml/qmlcachegen/versionStyleSuffix-1.2-more.qml new file mode 100644 index 0000000000..0836808dc2 --- /dev/null +++ b/tests/auto/qml/qmlcachegen/versionStyleSuffix-1.2-more.qml @@ -0,0 +1,4 @@ +import QtQml 2.0 +QtObject { + property int success: 42 +} diff --git a/tools/qmlcachegen/generateloader.cpp b/tools/qmlcachegen/generateloader.cpp index 96528a9477..178a109791 100644 --- a/tools/qmlcachegen/generateloader.cpp +++ b/tools/qmlcachegen/generateloader.cpp @@ -35,6 +35,52 @@ #include <QFileInfo> #include <QSaveFile> +/*! + * \internal + * Mangles \a str to be a unique C++ identifier. Characters that are invalid for C++ identifiers + * are replaced by the pattern \c _0x<hex>_ where <hex> is the hexadecimal unicode + * representation of the character. As identifiers with leading underscores followed by either + * another underscore or a capital letter are reserved in C++, we also escape those, by escaping + * the first underscore, using the above method. + * + * \note + * Although C++11 allows for non-ascii (unicode) characters to be used in identifiers, + * many compilers forgot to read the spec and do not implement this. Some also do not + * implement C99 identifiers, because that is \e {at the implementation's discretion}. So, + * we are stuck with plain old boring identifiers. + */ +QString mangledIdentifier(const QString &str) +{ + Q_ASSERT(!str.isEmpty()); + + QString mangled; + mangled.reserve(str.size()); + + int i = 0; + if (str.startsWith(QLatin1Char('_')) && str.size() > 1) { + QChar ch = str.at(1); + if (ch == QLatin1Char('_') + || (ch >= QLatin1Char('A') && ch <= QLatin1Char('Z'))) { + mangled += QLatin1String("_0x5f_"); + ++i; + } + } + + for (int ei = str.length(); i != ei; ++i) { + auto c = str.at(i).unicode(); + if ((c >= QLatin1Char('0') && c <= QLatin1Char('9')) + || (c >= QLatin1Char('a') && c <= QLatin1Char('z')) + || (c >= QLatin1Char('A') && c <= QLatin1Char('Z')) + || c == QLatin1Char('_')) { + mangled += c; + } else { + mangled += QLatin1String("_0x") + QString::number(c, 16) + QLatin1Char('_'); + } + } + + return mangled; +} + QString symbolNamespaceForPath(const QString &relativePath) { QFileInfo fi(relativePath); @@ -47,12 +93,8 @@ QString symbolNamespaceForPath(const QString &relativePath) } symbol += fi.baseName(); symbol += QLatin1Char('_'); - symbol += fi.suffix(); - symbol.replace(QLatin1Char('.'), QLatin1Char('_')); - symbol.replace(QLatin1Char('+'), QLatin1Char('_')); - symbol.replace(QLatin1Char('-'), QLatin1Char('_')); - symbol.replace(QLatin1Char(' '), QLatin1Char('_')); - return symbol; + symbol += fi.completeSuffix(); + return mangledIdentifier(symbol); } struct VirtualDirectoryEntry |