[Development] Extending moc to generate easily accessible metatype descriptions

Ulf Hermann ulf.hermann at qt.io
Mon Sep 16 12:32:39 CEST 2019


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).


More information about the Development mailing list