moc: Parse namespaces from other files
We can parse the namespaces in order to find the enums in them and populate the related metaobjects of the current file's classes. The symbol clashes are avoided by only generating metaobjects for namespaces defined in the same file. Fixes: QTBUG-71966 Fixes: QTBUG-72069 Change-Id: Ibdf21c3f9dae48d95b0952b3e220b4c29e30ecb8 Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
parent
f6cf0442df
commit
ae9be1a63d
@ -565,6 +565,7 @@ void Moc::parse()
|
||||
} else if (!test(SEMIC)) {
|
||||
NamespaceDef def;
|
||||
def.classname = nsName;
|
||||
def.doGenerate = currentFilenames.size() <= 1;
|
||||
|
||||
next(LBRACE);
|
||||
def.begin = index - 1;
|
||||
@ -572,25 +573,22 @@ void Moc::parse()
|
||||
def.end = index;
|
||||
index = def.begin + 1;
|
||||
|
||||
const bool parseNamespace = currentFilenames.size() <= 1;
|
||||
if (parseNamespace) {
|
||||
for (int i = namespaceList.size() - 1; i >= 0; --i) {
|
||||
if (inNamespace(&namespaceList.at(i))) {
|
||||
def.qualified.prepend(namespaceList.at(i).classname + "::");
|
||||
}
|
||||
}
|
||||
for (const QByteArray &ns : nested) {
|
||||
NamespaceDef parentNs;
|
||||
parentNs.classname = ns;
|
||||
parentNs.qualified = def.qualified;
|
||||
def.qualified += ns + "::";
|
||||
parentNs.begin = def.begin;
|
||||
parentNs.end = def.end;
|
||||
namespaceList += parentNs;
|
||||
for (int i = namespaceList.size() - 1; i >= 0; --i) {
|
||||
if (inNamespace(&namespaceList.at(i))) {
|
||||
def.qualified.prepend(namespaceList.at(i).classname + "::");
|
||||
}
|
||||
}
|
||||
for (const QByteArray &ns : nested) {
|
||||
NamespaceDef parentNs;
|
||||
parentNs.classname = ns;
|
||||
parentNs.qualified = def.qualified;
|
||||
def.qualified += ns + "::";
|
||||
parentNs.begin = def.begin;
|
||||
parentNs.end = def.end;
|
||||
namespaceList += parentNs;
|
||||
}
|
||||
|
||||
while (parseNamespace && inNamespace(&def) && hasNext()) {
|
||||
while (inNamespace(&def) && hasNext()) {
|
||||
switch (next()) {
|
||||
case NAMESPACE:
|
||||
if (test(IDENTIFIER)) {
|
||||
@ -915,7 +913,8 @@ void Moc::parse()
|
||||
} else {
|
||||
knownGadgets.insert(def.classname, def.qualified);
|
||||
knownGadgets.insert(def.qualified, def.qualified);
|
||||
classList += def;
|
||||
if (n.doGenerate)
|
||||
classList += def;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -188,6 +188,7 @@ Q_DECLARE_TYPEINFO(ClassDef::Interface, Q_MOVABLE_TYPE);
|
||||
|
||||
struct NamespaceDef : BaseDef {
|
||||
bool hasQNamespace = false;
|
||||
bool doGenerate = false;
|
||||
};
|
||||
Q_DECLARE_TYPEINFO(NamespaceDef, Q_MOVABLE_TYPE);
|
||||
|
||||
|
@ -3847,6 +3847,14 @@ static void checkEnum(const QMetaEnum &enumerator, const QByteArray &name, const
|
||||
}
|
||||
}
|
||||
|
||||
class EnumFromNamespaceClass : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(FooNamespace::Enum1 prop READ prop CONSTANT)
|
||||
public:
|
||||
FooNamespace::Enum1 prop() { return FooNamespace::Enum1::Key2; }
|
||||
};
|
||||
|
||||
void tst_Moc::testQNamespace()
|
||||
{
|
||||
QCOMPARE(TestQNamespace::staticMetaObject.enumeratorCount(), 4);
|
||||
@ -3874,6 +3882,11 @@ void tst_Moc::testQNamespace()
|
||||
QCOMPARE(FooNamespace::staticMetaObject.enumeratorCount(), 1);
|
||||
QCOMPARE(FooNamespace::FooNestedNamespace::staticMetaObject.enumeratorCount(), 2);
|
||||
QCOMPARE(FooNamespace::FooNestedNamespace::FooMoreNestedNamespace::staticMetaObject.enumeratorCount(), 1);
|
||||
|
||||
EnumFromNamespaceClass obj;
|
||||
const QVariant prop = obj.property("prop");
|
||||
QCOMPARE(prop.type(), QMetaType::Int);
|
||||
QCOMPARE(prop.toInt(), int(FooNamespace::Enum1::Key2));
|
||||
}
|
||||
|
||||
void tst_Moc::cxx17Namespaces()
|
||||
|
Loading…
x
Reference in New Issue
Block a user