Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmltyperegistrarutils.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3// Qt-Security score:critical reason:data-parser
4
7
8#include <QtCore/qcborarray.h>
9#include <QtCore/qcbormap.h>
10#include <QtCore/qcborvalue.h>
11#include <QtCore/qdebug.h>
12#include <QtCore/qfile.h>
13#include <QtCore/qdiriterator.h>
14#include <QtCore/private/qduplicatetracker_p.h>
15#include <QtCore/qtextstream.h>
16
17using namespace Qt::Literals::StringLiterals;
18
19QT_BEGIN_NAMESPACE
20
21QTypeRevision handleInMinorVersion(QTypeRevision revision, int majorVersion)
22{
23 if (!revision.hasMajorVersion() && revision.hasMinorVersion()) {
24 // this version has been obtained by QML_{ADDED,REMOVED}_IN_MINOR_VERSION
25 revision = QTypeRevision::fromVersion(majorVersion, revision.minorVersion());
26 }
27 return revision;
28}
29
31{
32 return iface.className;
33}
34
35static QDebug message(QDebug base, QAnyStringView message, QAnyStringView fileName, int lineNumber)
36{
37 // Formatted such that it becomes a link in QtCreator (even with "::" ending)
38 const QString lineString = lineNumber ? QString::number(lineNumber) : QString();
39 return (base.noquote().nospace()
40 << message << ": " << fileName << ":" << lineString << ":").space();
41}
42
43QDebug warning(QAnyStringView fileName, int lineNumber)
44{
45 return message(qWarning(), "Warning", fileName, lineNumber);
46}
47
48QDebug warning(const MetaType &classDef)
49{
50 const QAnyStringView file = classDef.inputFile();
51 int lineNo = classDef.lineNumber();
52 if (!file.isEmpty())
53 return warning(file, lineNo);
54
55 return warning(classDef.qualifiedClassName());
56}
57
58QDebug error(QAnyStringView fileName, int lineNumber)
59{
60 return message(qCritical(), "Error", fileName, lineNumber);
61}
62
63/*!
64 \internal
65 \a pathToList points to a file listing all qt.parts.conf files
66 \a pathToFinalQtConfsList points to a file that lists the final merged qt.conf file location
67 for each qt.parts.conf file
68 In any given directory, there might be more than one qt.parts.conf file (especially on Winodws).
69 We need to merge all import paths for a given folder (but want to avoid duplicate entries).
70
71 The order of the import paths is significant: the QML engine resolves a module against its
72 import paths in order and uses the first match. We therefore preserve the order in which the
73 paths are listed within each qt.parts.conf file, so that the file's author decides which of
74 two paths providing the same module wins. The order between separate qt.parts.conf files in
75 the same directory is however that of QDirIterator, and so arbitrary.
76 */
77int mergeQtConfFiles(const QString &pathToList, const QString &pathToMergedQtConfsList)
78{
79 QFile listFile(pathToList);
80 if (!listFile.open(QFile::ReadOnly | QFile::Text))
81 return EXIT_FAILURE;
82 QHash<QString, QStringList> directoryToNecessaryImports;
83 while (!listFile.atEnd()) {
84 QByteArray partFilePath = listFile.readLine().trimmed();
85 QString directoryPath = QFileInfo(QString::fromUtf8(partFilePath)).absolutePath();
86 QDirIterator dirIt(directoryPath, { "*_qt.part.conf"_L1 }, QDir::Filter::Files );
87 while (dirIt.hasNext()) {
88 QFile partialFile(dirIt.next());
89 if (!partialFile.open(QFile::ReadOnly | QFile::Text)) {
90 qCritical() << "could not open" << partialFile.fileName();
91 return EXIT_FAILURE;
92 }
93 while (!partialFile.atEnd()) {
94 QByteArray import = partialFile.readLine().trimmed();
95 directoryToNecessaryImports[directoryPath].append(QString::fromUtf8(import));
96 }
97 }
98 }
99
100 // Collect the merged qt paths.
101 QFile mergedPathsListFile(pathToMergedQtConfsList);
102 if (!mergedPathsListFile.open(QFile::ReadOnly | QFile::Text)) {
103 qCritical() << "could not open" << mergedPathsListFile.fileName();
104 return EXIT_FAILURE;
105 }
106 QHash<QString, QString> partialPathToMergedPath;
107 while (!mergedPathsListFile.atEnd()) {
108 QByteArray row = mergedPathsListFile.readLine().trimmed();
109 QList<QByteArray> parts = row.split(';');
110 Q_ASSERT(parts.size() == 2);
111 const QString partialFileDirectoryPath =
112 QFileInfo(QString::fromUtf8(parts[0])).absolutePath();
113 const QString mergedFilePath = QString::fromUtf8(parts[1]);
114 partialPathToMergedPath.insert(partialFileDirectoryPath, mergedFilePath);
115 }
116
117 for (const QString &directoryPath: directoryToNecessaryImports.keys()) {
118 if (!partialPathToMergedPath.contains(directoryPath)) {
119 qCritical() << "no merged qt.conf file found for directory" << directoryPath;
120 return EXIT_FAILURE;
121 }
122 const QString mergedQtConfFilePath = partialPathToMergedPath.value(directoryPath);
123
124 // Pre-create the directory in case it doesn't exist yet. Especially relevant for the
125 // 'Resources' subdirectory for macOS bundles.
126 QDir().mkpath(QFileInfo(mergedQtConfFilePath).absolutePath());
127
128 QFile consolidatedQtConfFile(mergedQtConfFilePath);
129 if (!consolidatedQtConfFile.open(QFile::WriteOnly | QFile::Text)) {
130 qCritical() << "could not open" << consolidatedQtConfFile.fileName();
131 return EXIT_FAILURE;
132 }
133 QTextStream out(&consolidatedQtConfFile);
134 QStringList allIncludes = directoryToNecessaryImports.value(directoryPath);
135 allIncludes.removeDuplicates();
136 out << "[Config]\nMergeQtConf = true\n"
137 << "[Paths]\nQmlImports = "
138 << allIncludes.join(u",") << Qt::endl;
139 }
140 QFile outfile(pathToList + u".done");
141 if (!outfile.open(QFile::WriteOnly | QFile::Text))
142 return EXIT_FAILURE;
143 outfile.write(QByteArray::number(QDateTime::currentSecsSinceEpoch()));
144 return EXIT_SUCCESS;
145}
146
147QT_END_NAMESPACE
static QDebug message(QDebug base, QAnyStringView message, QAnyStringView fileName, int lineNumber)
QAnyStringView interfaceName(const Interface &iface)
QDebug warning(const MetaType &classDef)
int mergeQtConfFiles(const QString &pathToList, const QString &pathToMergedQtConfsList)
QDebug error(QAnyStringView fileName, int lineNumber=0)
QDebug warning(QAnyStringView fileName, int lineNumber=0)