Skip to content

Commit 0f5e3e7

Browse files
committed
refactor(generator): migrate typesystem parser to QXmlStreamReader
- drop the legacy QtXml reader/handler stack in favor of `QXmlStreamReader` - rewrite the typesystem Handler to drive the stream reader directly and wrap `QXmlStreamAttributes` - update attribute helpers and error reporting to match the new streaming API - open typesystem files with QText mode and surface parse failures via `ReportHandler`
1 parent f6fa33d commit 0f5e3e7

File tree

1 file changed

+100
-56
lines changed

1 file changed

+100
-56
lines changed

generator/typesystem.cpp

Lines changed: 100 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -48,25 +48,11 @@
4848

4949
#include <memory>
5050

51-
#include <QtXml>
51+
#include <QFile>
52+
#include <QTextStream>
53+
#include <QXmlStreamReader>
5254
#include <qcompilerdetection.h> // Q_FALLTHROUGH
5355

54-
/* This file needs to be rewritten as documented here:
55-
*
56-
* See: https://doc.qt.io/qt-6/xml-changes-qt6.html
57-
*
58-
* The rewrite may be backward compatible to Qt4.3 APIs because the base
59-
* facilites (QXmlStreamReader) used to relace the 'SAX' parser were apparently
60-
* available then. Use of Xml5Compat is a work round until such a rewrite has
61-
* been done.
62-
*/
63-
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
64-
# if defined(__GNUC__)
65-
# pragma GCC warning "Qt6: implement Qt6 compatible XML reading"
66-
# endif
67-
# include <QtCore5Compat/QXmlDefaultHandler>
68-
#endif
69-
7056
QString strings_Object = QLatin1String("Object");
7157
QString strings_String = QLatin1String("String");
7258
QString strings_Thread = QLatin1String("Thread");
@@ -150,9 +136,48 @@ class StackElement
150136
} value;
151137
};
152138

153-
class Handler : public QXmlDefaultHandler
139+
class Handler
154140
{
155141
public:
142+
class Attributes
143+
{
144+
public:
145+
Attributes() = default;
146+
explicit Attributes(const QXmlStreamAttributes &attributes)
147+
: m_attributes(attributes) {}
148+
149+
int length() const { return m_attributes.size(); }
150+
151+
QString localName(int index) const
152+
{
153+
return m_attributes.at(index).name().toString();
154+
}
155+
156+
QString value(int index) const
157+
{
158+
return m_attributes.at(index).value().toString();
159+
}
160+
161+
QString value(const QString &qualifiedName) const
162+
{
163+
return m_attributes.hasAttribute(qualifiedName)
164+
? m_attributes.value(qualifiedName).toString()
165+
: QString();
166+
}
167+
168+
int index(const QString &qualifiedName) const
169+
{
170+
for (int i = 0; i < m_attributes.size(); ++i) {
171+
if (m_attributes.at(i).name().toString() == qualifiedName)
172+
return i;
173+
}
174+
return -1;
175+
}
176+
177+
private:
178+
QXmlStreamAttributes m_attributes;
179+
};
180+
156181
Handler(TypeDatabase *database, unsigned int qtVersion, bool generate)
157182
: m_database(database)
158183
, m_generate(generate ? TypeEntry::GenerateAll : TypeEntry::GenerateForSubclass)
@@ -197,25 +222,23 @@ class Handler : public QXmlDefaultHandler
197222
tagNames["reference-count"] = StackElement::ReferenceCount;
198223
}
199224

225+
bool parse(QXmlStreamReader &reader);
200226
bool startDocument() { m_nestingLevel = 0; m_disabledLevel = -1; return true; }
201227
bool startElement(const QString &namespaceURI, const QString &localName,
202-
const QString &qName, const QXmlAttributes &atts);
228+
const QString &qName, const Attributes &atts);
203229
bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName);
204230

205231
QString errorString() const { return m_error; }
206-
bool error(const QXmlParseException &exception);
207-
bool fatalError(const QXmlParseException &exception);
208-
bool warning(const QXmlParseException &exception);
209232

210233
bool characters(const QString &ch);
211234

212235
private:
213-
void fetchAttributeValues(const QString &name, const QXmlAttributes &atts,
236+
void fetchAttributeValues(const QString &name, const Attributes &atts,
214237
QHash<QString, QString> *acceptedAttributes);
215238

216-
bool importFileElement(const QXmlAttributes &atts);
239+
bool importFileElement(const Attributes &atts);
217240
bool convertBoolean(const QString &, const QString &, bool);
218-
bool qtVersionMatches(const QXmlAttributes& atts, bool& ok);
241+
bool qtVersionMatches(const Attributes& atts, bool& ok);
219242

220243
TypeDatabase *m_database;
221244
StackElement* current;
@@ -237,31 +260,55 @@ class Handler : public QXmlDefaultHandler
237260
int m_disabledLevel{}; // if this is != 0, elements should be ignored
238261
};
239262

240-
bool Handler::error(const QXmlParseException &e)
263+
bool Handler::parse(QXmlStreamReader &reader)
241264
{
242-
qWarning() << "Error: line=" << e.lineNumber()
243-
<< ", column=" << e.columnNumber()
244-
<< ", message=" << e.message() << "\n";
245-
return false;
246-
}
265+
if (!startDocument())
266+
return false;
247267

248-
bool Handler::fatalError(const QXmlParseException &e)
249-
{
250-
qWarning() << "Fatal error: line=" << e.lineNumber()
251-
<< ", column=" << e.columnNumber()
252-
<< ", message=" << e.message() << "\n";
253-
return false;
254-
}
268+
while (!reader.atEnd()) {
269+
const auto token = reader.readNext();
270+
switch (token) {
271+
case QXmlStreamReader::StartElement: {
272+
Attributes attributes(reader.attributes());
273+
if (!startElement(reader.namespaceUri().toString(),
274+
reader.name().toString(),
275+
reader.qualifiedName().toString(),
276+
attributes)) {
277+
return false;
278+
}
279+
break;
280+
}
281+
case QXmlStreamReader::EndElement:
282+
if (!endElement(reader.namespaceUri().toString(),
283+
reader.name().toString(),
284+
reader.qualifiedName().toString())) {
285+
return false;
286+
}
287+
break;
288+
case QXmlStreamReader::Characters:
289+
case QXmlStreamReader::EntityReference:
290+
if (!characters(reader.text().toString())) {
291+
return false;
292+
}
293+
break;
294+
default:
295+
break;
296+
}
297+
}
255298

256-
bool Handler::warning(const QXmlParseException &e)
257-
{
258-
qWarning() << "Warning: line=" << e.lineNumber()
259-
<< ", column=" << e.columnNumber()
260-
<< ", message=" << e.message() << "\n";
261-
return false;
299+
if (reader.hasError()) {
300+
m_error = QStringLiteral("Parse error at line %1, column %2: %3")
301+
.arg(reader.lineNumber())
302+
.arg(reader.columnNumber())
303+
.arg(reader.errorString());
304+
qWarning() << m_error;
305+
return false;
306+
}
307+
308+
return true;
262309
}
263310

264-
void Handler::fetchAttributeValues(const QString &name, const QXmlAttributes &atts,
311+
void Handler::fetchAttributeValues(const QString &name, const Attributes &atts,
265312
QHash<QString, QString> *acceptedAttributes)
266313
{
267314
Q_ASSERT(acceptedAttributes != 0);
@@ -398,7 +445,7 @@ bool Handler::characters(const QString &ch)
398445
return true;
399446
}
400447

401-
bool Handler::importFileElement(const QXmlAttributes &atts)
448+
bool Handler::importFileElement(const Attributes &atts)
402449
{
403450
QString fileName = atts.value("name");
404451
if(fileName.isEmpty()){
@@ -470,7 +517,7 @@ bool Handler::convertBoolean(const QString &_value, const QString &attributeName
470517
}
471518
}
472519

473-
bool Handler::qtVersionMatches(const QXmlAttributes& atts, bool& ok)
520+
bool Handler::qtVersionMatches(const Attributes& atts, bool& ok)
474521
{
475522
ok = true;
476523
int beforeIndex = atts.index("before-version");
@@ -501,7 +548,7 @@ bool Handler::qtVersionMatches(const QXmlAttributes& atts, bool& ok)
501548
}
502549

503550
bool Handler::startElement(const QString &, const QString &n,
504-
const QString &, const QXmlAttributes &atts)
551+
const QString &, const Attributes &atts)
505552
{
506553
QString tagName = n.toLower();
507554
m_nestingLevel++;
@@ -1605,22 +1652,19 @@ bool TypeDatabase::parseFile(const QString &filename, unsigned int qtVersion, bo
16051652
// If opening fails, attempt to load from Qt resources
16061653
file.setFileName(":/trolltech/generator/" + filename);
16071654
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
1608-
qWarning() << "Could not open file:" << filename;
1655+
ReportHandler::warning(QString::fromLatin1("Could not open typesystem file: '%1'").arg(filename));
16091656
return false;
16101657
}
16111658
}
16121659

1613-
QXmlInputSource source(&file);
1614-
16151660
int count = m_entries.size();
16161661

1617-
QXmlSimpleReader reader;
16181662
Handler handler(this, qtVersion, generate);
1663+
QXmlStreamReader reader(&file);
16191664

1620-
reader.setContentHandler(&handler);
1621-
reader.setErrorHandler(&handler);
1622-
1623-
bool ok = reader.parse(&source, false);
1665+
bool ok = handler.parse(reader);
1666+
if (!ok && !handler.errorString().isEmpty())
1667+
ReportHandler::warning(handler.errorString());
16241668

16251669
int newCount = m_entries.size();
16261670

0 commit comments

Comments
 (0)