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
cppwriteincludes.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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:insignificant reason:build-tool
4
6#include "driver.h"
7#include "ui4.h"
8#include "uic.h"
9#include "databaseinfo.h"
10
11#include <qdebug.h>
12#include <qfileinfo.h>
13#include <qtextstream.h>
14
15#include <cstdio>
16
17QT_BEGIN_NAMESPACE
18
19using namespace Qt::StringLiterals;
20
21enum { debugWriteIncludes = 0 };
23
24// Format a module header as 'QtCore/QObject'
25static inline QString moduleHeader(const QString &module, const QString &header)
26{
27 QString rc = module;
28 rc += u'/';
29 rc += header;
30 return rc;
31}
32
33namespace CPP {
34
36 m_output(uic->output())
37{
38 // When possible (no namespace) use the "QtModule/QClass" convention
39 // and create a re-mapping of the old header "qclass.h" to it. Do not do this
40 // for the "Phonon::Someclass" classes, however.
41 const QLatin1StringView namespaceDelimiter = "::"_L1;
42 for (const auto &e : classInfoEntries()) {
43 const QString klass = QLatin1StringView(e.klass);
44 const QString module = QLatin1StringView(e.module);
45 QLatin1StringView header(e.header);
46 if (klass.contains(namespaceDelimiter)) {
47 m_classToHeader.insert(klass, moduleHeader(module, header));
48 } else {
49 const QString newHeader = moduleHeader(module, klass);
50 m_classToHeader.insert(klass, newHeader);
51 m_oldHeaderToNewHeader.insert(header, newHeader);
52 }
53 }
54}
55
56void WriteIncludes::acceptUI(DomUI *node)
57{
58 m_localIncludes.clear();
59 m_globalIncludes.clear();
60 m_includeBaseNames.clear();
61
63
64 const auto includeFile = uic()->option().includeFile;
65 if (!includeFile.isEmpty())
66 m_globalIncludes.insert(includeFile);
67
68 writeHeaders(m_globalIncludes, true);
69 writeHeaders(m_localIncludes, false);
70
71 m_output << '\n';
72}
73
74void WriteIncludes::insertIncludeForClass(const QString &className, QString header, bool global)
75{
77 std::fprintf(stderr, "%s %s '%s' %d\n", Q_FUNC_INFO, qPrintable(className), qPrintable(header), global);
78
79 do {
80 if (!header.isEmpty())
81 break;
82
83 // Known class
84 const StringMap::const_iterator it = m_classToHeader.constFind(className);
85 if (it != m_classToHeader.constEnd()) {
86 header = it.value();
87 global = true;
88 break;
89 }
90
91 // Quick check by class name to detect includehints provided for custom widgets.
92 // Remove namespaces
93 QString lowerClassName = className.toLower();
94 static const auto namespaceSeparator = "::"_L1;
95 const auto namespaceIndex = lowerClassName.lastIndexOf(namespaceSeparator);
96 if (namespaceIndex != -1)
97 lowerClassName.remove(0, namespaceIndex + namespaceSeparator.size());
98 if (m_includeBaseNames.contains(lowerClassName)) {
99 header.clear();
100 break;
101 }
102
103 // Last resort: Create default header
104 if (!uic()->option().implicitIncludes)
105 break;
106 header = lowerClassName;
107 header += ".h"_L1;
109 qWarning("%s: Warning: generated header '%s' for class '%s'.",
110 qPrintable(uic()->option().messagePrefix()),
111 qPrintable(header), qPrintable(className));
112
113 }
114
115 global = true;
116 } while (false);
117
118 if (!header.isEmpty())
119 insertInclude(header, global);
120}
121
122void WriteIncludes::doAdd(const QString &className, const DomCustomWidget *dcw)
123{
124 if (dcw != nullptr)
125 addCppCustomWidget(className, dcw);
126 else
127 insertIncludeForClass(className, {}, false);
128}
129
130void WriteIncludes::addCppCustomWidget(const QString &className, const DomCustomWidget *dcw)
131{
132 const DomHeader *domHeader = dcw->elementHeader();
133 if (domHeader != nullptr && !domHeader->text().isEmpty()) {
134 // custom header unless it is a built-in qt class
135 QString header;
136 bool global = false;
137 if (!m_classToHeader.contains(className)) {
138 global = domHeader->attributeLocation().toLower() == "global"_L1;
139 header = domHeader->text();
140 }
141 insertIncludeForClass(className, header, global);
142 return;
143 }
144}
145
146void WriteIncludes::acceptInclude(DomInclude *node)
147{
148 bool global = true;
149 if (node->hasAttributeLocation())
150 global = node->attributeLocation() == "global"_L1;
151 insertInclude(node->text(), global);
152}
153
154void WriteIncludes::insertInclude(const QString &header, bool global)
155{
157 fprintf(stderr, "%s %s %d\n", Q_FUNC_INFO, qPrintable(header), global);
158
159 OrderedSet &includes = global ? m_globalIncludes : m_localIncludes;
160 // Insert (if not already done).
161 const bool isNewHeader = includes.insert(header).second;
162 if (!isNewHeader)
163 return;
164 // Also remember base name for quick check of suspicious custom plugins
165 const QString lowerBaseName = QFileInfo(header).completeBaseName ().toLower();
166 m_includeBaseNames.insert(lowerBaseName);
167}
168
169void WriteIncludes::writeHeaders(const OrderedSet &headers, bool global)
170{
171 const QChar openingQuote = global ? u'<' : u'"';
172 const QChar closingQuote = global ? u'>' : u'"';
173
174 // Check for the old headers 'qslider.h' and replace by 'QtGui/QSlider'
175 for (const QString &header : headers) {
176 const QString value = m_oldHeaderToNewHeader.value(header, header);
177 const auto trimmed = QStringView(value).trimmed();
178 if (!trimmed.isEmpty())
179 m_output << "#include " << openingQuote << trimmed << closingQuote << '\n';
180 }
181}
182
183} // namespace CPP
184
185QT_END_NAMESPACE
void acceptUI(DomUI *node) override
void acceptInclude(DomInclude *node) override
Definition uic.h:31
QTextStream & output()
Definition uic.h:42
void acceptUI(DomUI *node) override
@ debugWriteIncludes
static QString moduleHeader(const QString &module, const QString &header)
@ warnHeaderGeneration
const QString & asString(const QString &s)
Definition qstring.h:1700
#define qPrintable(string)
Definition qstring.h:1705
const char * header
ClassInfoEntries classInfoEntries()