aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-02-26 15:24:12 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-03-05 11:20:27 +0100
commitd1604053e9ae354963a2b2447b3d196fc5dda73e (patch)
tree2bcfae6884c4de3147427b40cd0d7fb7ad45f649
parente88f08c180bc30aa52887bd5cc27fe0fe1a33b2b (diff)
Change the dumpcodemodel tool to output typesystem XML
Make the previously existing debug output an option and output typesystem XML by default. Change-Id: I3d95bdb56446097377880e1ca0b54d3b8b93ea24 Reviewed-by: Christian Tismer <tismer@stackless.com>
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.cpp14
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.h2
-rw-r--r--sources/shiboken2/tests/dumpcodemodel/main.cpp143
3 files changed, 148 insertions, 11 deletions
diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp
index 099ab8860..4fafa0c2c 100644
--- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp
+++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp
@@ -1127,6 +1127,20 @@ void _FunctionModelItem::setInvokable(bool isInvokable)
m_isInvokable = isInvokable;
}
+QString _FunctionModelItem::typeSystemSignature() const // For dumping out type system files
+{
+ QString result;
+ QTextStream str(&result);
+ str << name() << '(';
+ for (int a = 0, size = m_arguments.size(); a < size; ++a) {
+ if (a)
+ str << ',';
+ str << m_arguments.at(a)->type().qualifiedName().join(QLatin1String("::"));
+ }
+ str << ')';
+ return result;
+}
+
#ifndef QT_NO_DEBUG_STREAM
void _FunctionModelItem::formatDebug(QDebug &d) const
{
diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h
index 80db2cce5..e851c9c8e 100644
--- a/sources/shiboken2/ApiExtractor/parser/codemodel.h
+++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h
@@ -618,6 +618,8 @@ public:
ExceptionSpecification exceptionSpecification() const;
void setExceptionSpecification(ExceptionSpecification e);
+ QString typeSystemSignature() const; // For dumping out type system files
+
#ifndef QT_NO_DEBUG_STREAM
void formatDebug(QDebug &d) const override;
#endif
diff --git a/sources/shiboken2/tests/dumpcodemodel/main.cpp b/sources/shiboken2/tests/dumpcodemodel/main.cpp
index e132c97b3..52d64be94 100644
--- a/sources/shiboken2/tests/dumpcodemodel/main.cpp
+++ b/sources/shiboken2/tests/dumpcodemodel/main.cpp
@@ -33,9 +33,11 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QCommandLineOption>
#include <QtCore/QCommandLineParser>
+#include <QtCore/QDateTime>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFile>
+#include <QtCore/QXmlStreamWriter>
#include <iostream>
#include <algorithm>
@@ -48,23 +50,146 @@ static inline QString languageLevelDescription()
+ QLatin1Char(')');
}
+static void formatDebugOutput(const FileModelItem &dom, bool verbose)
+{
+ QString output;
+ {
+ QDebug debug(&output);
+ if (verbose)
+ debug.setVerbosity(3);
+ debug << dom.data();
+ }
+ std::cout << qPrintable(output) << '\n';
+}
+
+static const char *primitiveTypes[] = {
+ "int", "unsigned", "short", "unsigned short", "long", "unsigned long",
+ "float", "double"
+};
+
+static inline QString nameAttribute() { return QStringLiteral("name"); }
+
+static void formatXmlNamespace(QXmlStreamWriter &writer, const NamespaceModelItem &nsp);
+static void formatXmlClass(QXmlStreamWriter &writer, const ClassModelItem &klass);
+
+static void formatXmlEnum(QXmlStreamWriter &writer, const EnumModelItem &en)
+{
+ writer.writeStartElement(QStringLiteral("enum-type"));
+ writer.writeAttribute(nameAttribute(), en->name());
+ writer.writeEndElement();
+}
+
+static void formatXmlScopeMembers(QXmlStreamWriter &writer, const ScopeModelItem &nsp)
+{
+ for (const auto &klass : nsp->classes()) {
+ if (klass->classType() != CodeModel::Union && klass->templateParameters().isEmpty())
+ formatXmlClass(writer, klass);
+ }
+ for (const auto &en : nsp->enums())
+ formatXmlEnum(writer, en);
+}
+
+static bool isPublicCopyConstructor(const FunctionModelItem &f)
+{
+ return f->functionType() == CodeModel::CopyConstructor
+ && f->accessPolicy() == CodeModel::Public && !f->isDeleted();
+}
+
+static void formatXmlClass(QXmlStreamWriter &writer, const ClassModelItem &klass)
+{
+ // Heuristics for value types: check on public copy constructors.
+ const auto functions = klass->functions();
+ const bool isValueType = std::any_of(functions.cbegin(), functions.cend(),
+ isPublicCopyConstructor);
+ writer.writeStartElement(isValueType ? QStringLiteral("value-type")
+ : QStringLiteral("object-type"));
+ writer.writeAttribute(nameAttribute(), klass->name());
+ formatXmlScopeMembers(writer, klass);
+ writer.writeEndElement();
+}
+
+static void formatXmlNamespaceMembers(QXmlStreamWriter &writer, const NamespaceModelItem &nsp)
+{
+ for (const auto &nested : nsp->namespaces())
+ formatXmlNamespace(writer, nested);
+ for (auto func : nsp->functions()) {
+ const QString signature = func->typeSystemSignature();
+ if (!signature.contains(QLatin1String("operator"))) { // Skip free operators
+ writer.writeStartElement(QStringLiteral("function"));
+ writer.writeAttribute(QStringLiteral("signature"), signature);
+ writer.writeEndElement();
+ }
+ }
+ formatXmlScopeMembers(writer, nsp);
+}
+
+static void formatXmlNamespace(QXmlStreamWriter &writer, const NamespaceModelItem &nsp)
+{
+ writer.writeStartElement(QStringLiteral("namespace-type"));
+ writer.writeAttribute(nameAttribute(), nsp->name());
+ formatXmlNamespaceMembers(writer, nsp);
+ writer.writeEndElement();
+}
+
+static void formatXmlOutput(const FileModelItem &dom)
+{
+ QString output;
+ QXmlStreamWriter writer(&output);
+ writer.setAutoFormatting(true);
+ writer.writeStartDocument();
+ writer.writeStartElement(QStringLiteral("typesystem"));
+ writer.writeAttribute(QStringLiteral("package"), QStringLiteral("insert_name"));
+ writer.writeComment(QStringLiteral("Auto-generated ") +
+ QDateTime::currentDateTime().toString(Qt::ISODate));
+ for (auto p : primitiveTypes) {
+ writer.writeStartElement(QStringLiteral("primitive-type"));
+ writer.writeAttribute(nameAttribute(), QLatin1String(p));
+ writer.writeEndElement();
+ }
+ formatXmlNamespaceMembers(writer, dom);
+ writer.writeEndElement();
+ writer.writeEndDocument();
+ std::cout << qPrintable(output) << '\n';
+}
+
+static const char descriptionFormat[] = R"(
+Type system dumper
+
+Parses a C++ header and dumps out the classes found in typesystem XML syntax.
+Arguments are arguments to the compiler the last of which should be the header
+or source file.
+It is recommended to create a .hh include file including the desired headers
+and pass that along with the required include paths.
+
+Based on Qt %1 and LibClang v%2.)";
+
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
QCommandLineParser parser;
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
- parser.setApplicationDescription(QStringLiteral("Code model tester"));
+ parser.setOptionsAfterPositionalArgumentsMode(QCommandLineParser::ParseAsPositionalArguments);
+ const QString description =
+ QString::fromLatin1(descriptionFormat).arg(QLatin1String(qVersion()),
+ clang::libClangVersion().toString());
+ parser.setApplicationDescription(description);
parser.addHelpOption();
parser.addVersionOption();
- QCommandLineOption verboseOption(QStringLiteral("d"),
+ QCommandLineOption verboseOption(QStringLiteral("verbose"),
QStringLiteral("Display verbose output about types"));
parser.addOption(verboseOption);
+ QCommandLineOption debugOption(QStringLiteral("debug"),
+ QStringLiteral("Display debug output"));
+ parser.addOption(debugOption);
+
QCommandLineOption languageLevelOption(QStringLiteral("std"),
languageLevelDescription(),
QStringLiteral("level"));
parser.addOption(languageLevelOption);
- parser.addPositionalArgument(QStringLiteral("file"), QStringLiteral("C++ source file"));
+ parser.addPositionalArgument(QStringLiteral("argument"),
+ QStringLiteral("C++ compiler argument"),
+ QStringLiteral("argument(s)"));
parser.process(app);
const QStringList &positionalArguments = parser.positionalArguments();
@@ -93,14 +218,10 @@ int main(int argc, char **argv)
return -2;
}
- QString output;
- {
- QDebug debug(&output);
- if (parser.isSet(verboseOption))
- debug.setVerbosity(3);
- debug << dom.data();
- }
- std::cout << qPrintable(output) << '\n';
+ if (parser.isSet(debugOption))
+ formatDebugOutput(dom, parser.isSet(verboseOption));
+ else
+ formatXmlOutput(dom);
return 0;
}