[Development] Extending moc to generate easily accessible metatype descriptions
Ulf Hermann
ulf.hermann at qt.io
Mon Sep 16 12:32:39 CEST 2019
Hi,
in an effort to enable better tooling for QML, it would be of great
value to have easily accessible per-module descriptions of our meta
types available. This would allow us to analyze the availability of
properties, signals, enums, invokable methods, and slots statically at
compile time. In turn, we could use this information to write a better
QML linter, a QML language server, and an improved QML code model for Qt
Creator. The information would also be helpful for a QML compiler that
compiles QML to C++.
We need not only metatype information from types introduces in modules
that define QML types, but also metatype information for types those QML
types derive from because all the properties etc are inherited. In
addition, some modules and plugins register "foreign" types under their
own QML type URI, such as the state machine plugin registering
QHistoryState (for example). Therefore a proper solution to the problem
needs to be applied at least to QtCore and QtGui, in addition to the
modules in qtdeclarative.
The way type information is passed to any tools right now is via files
called "plugins.qmltypes" places alongside QML plugins in Qt's plugin
directories. These are generated by running the "qmlplugindump" tool on
the plugins in question. qmlplugindump loads the plugins and examines
the run time QMetaObject instances to retrieve the required information.
There are some downsides to this approach:
1. It does not work for cross-compiled Qt builds. Obviously we cannot
load plugins for a different architecture on the host system at build time.
2. Loading the plugins executes unrelated code in the plugins. For our
own plugins we can keep the side effects under control. However, we want
to be able to generate type descriptions also for custom types
introduced by application developers, and we don't know what happens if
we load their plugins with qmlplugindump.
3. It only works for plugins. You can call qmlRegisterType() directly in
main() and qmlplugindump will never see that. Having to refactor your
application into plugins just to have the type descriptions available is
a burden.
4. It does not work for static builds. Obviously qmlplugindump cannot
load static plugins.
The place where all the metatypes are known at compile time is inside
moc. moc analyzes the headers for specific macros and transforms those
into C++ representations. Those C++ representations are geared for
run-time performance and rather hard to parse later on. However, it
would be easy for moc to generate additional files with the same content
in more easily accessible form.
Therefore I propose an additional parameter "--json" for moc that would
generate just such files, in JSON format, to be processed by further
tools. In addition, moc should also gain the ability to collect multiple
such per-C++-file JSON files into one per-module JSON file. The latter
is a pure JSON transformation and doesn't require any insight about the
actual types.
The proposed change to moc is
https://codereview.qt-project.org/c/qt/qtbase/+/248470 and a proposed
qmltyperegistrar which would use the metatype information to generate
plugins.qmltypes files at compile time can be seen at
https://codereview.qt-project.org/c/qt/qtdeclarative/+/248471 (mind the
dependency chain).
Ulf
More information about the Development
mailing list