diff options
Diffstat (limited to 'src/tools/moc/moc.cpp')
-rw-r--r-- | src/tools/moc/moc.cpp | 105 |
1 files changed, 97 insertions, 8 deletions
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 87fb1318f9..3bd87e1f01 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -163,7 +163,7 @@ Type Moc::parseType() case SIGNED: case UNSIGNED: hasSignedOrUnsigned = true; - // fall through + Q_FALLTHROUGH(); case CONST: case VOLATILE: type.name += lexem(); @@ -538,7 +538,6 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def) return true; } - void Moc::parse() { QVector<NamespaceDef> namespaceList; @@ -554,14 +553,76 @@ void Moc::parse() until(SEMIC); } else if (!test(SEMIC)) { NamespaceDef def; - def.name = lexem(); + def.classname = lexem(); next(LBRACE); def.begin = index - 1; until(RBRACE); 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 + "::"); + } + } + } + while (parseNamespace && inNamespace(&def) && hasNext()) { + switch (next()) { + case NAMESPACE: + if (test(IDENTIFIER)) { + if (test(EQ)) { + // namespace Foo = Bar::Baz; + until(SEMIC); + } else if (!test(SEMIC)) { + until(RBRACE); + } + } + break; + case Q_NAMESPACE_TOKEN: + def.hasQNamespace = true; + break; + case Q_ENUMS_TOKEN: + case Q_ENUM_NS_TOKEN: + parseEnumOrFlag(&def, false); + break; + case Q_ENUM_TOKEN: + error("Q_ENUM can't be used in a Q_NAMESPACE, use Q_ENUM_NS instead"); + break; + case Q_FLAGS_TOKEN: + case Q_FLAG_NS_TOKEN: + parseEnumOrFlag(&def, true); + break; + case Q_FLAG_TOKEN: + error("Q_FLAG can't be used in a Q_NAMESPACE, use Q_FLAG_NS instead"); + break; + case Q_DECLARE_FLAGS_TOKEN: + parseFlag(&def); + break; + case Q_CLASSINFO_TOKEN: + parseClassInfo(&def); + break; + case ENUM: { + EnumDef enumDef; + if (parseEnum(&enumDef)) + def.enumList += enumDef; + } break; + case CLASS: + case STRUCT: { + ClassDef classdef; + if (!parseClassHead(&classdef)) + continue; + while (inClass(&classdef) && hasNext()) + next(); // consume all Q_XXXX macros from this class + } break; + default: break; + } + } namespaceList += def; index = rewind; + if (!def.hasQNamespace && (!def.classInfoList.isEmpty() || !def.enumDeclarations.isEmpty())) + error("Namespace declaration lacks Q_NAMESPACE macro."); } } break; @@ -618,7 +679,7 @@ void Moc::parse() for (int i = namespaceList.size() - 1; i >= 0; --i) if (inNamespace(&namespaceList.at(i))) - def.qualified.prepend(namespaceList.at(i).name + "::"); + def.qualified.prepend(namespaceList.at(i).classname + "::"); QHash<QByteArray, QByteArray> &classHash = def.hasQObject ? knownQObjectClasses : knownGadgets; classHash.insert(def.classname, def.qualified); @@ -634,7 +695,7 @@ void Moc::parse() FunctionDef::Access access = FunctionDef::Private; for (int i = namespaceList.size() - 1; i >= 0; --i) if (inNamespace(&namespaceList.at(i))) - def.qualified.prepend(namespaceList.at(i).name + "::"); + def.qualified.prepend(namespaceList.at(i).classname + "::"); while (inClass(&def) && hasNext()) { switch ((t = next())) { case PRIVATE: @@ -698,10 +759,16 @@ void Moc::parse() case Q_ENUM_TOKEN: parseEnumOrFlag(&def, false); break; + case Q_ENUM_NS_TOKEN: + error("Q_ENUM_NS can't be used in a Q_OBJECT/Q_GADGET, use Q_ENUM instead"); + break; case Q_FLAGS_TOKEN: case Q_FLAG_TOKEN: parseEnumOrFlag(&def, true); break; + case Q_FLAG_NS_TOKEN: + error("Q_FLAG_NS can't be used in a Q_OBJECT/Q_GADGET, use Q_FLAG instead"); + break; case Q_DECLARE_FLAGS_TOKEN: parseFlag(&def); break; @@ -802,6 +869,28 @@ void Moc::parse() classHash.insert(def.qualified, def.qualified); } } + for (const auto &n : qAsConst(namespaceList)) { + if (!n.hasQNamespace) + continue; + ClassDef def; + static_cast<BaseDef &>(def) = static_cast<BaseDef>(n); + def.qualified += def.classname; + def.hasQGadget = true; + auto it = std::find_if(classList.begin(), classList.end(), [&def](const ClassDef &val) { + return def.classname == val.classname && def.qualified == val.qualified; + }); + + if (it != classList.end()) { + it->classInfoList += def.classInfoList; + it->enumDeclarations.unite(def.enumDeclarations); + it->enumList += def.enumList; + it->flagAliases.unite(def.flagAliases); + } else { + knownGadgets.insert(def.classname, def.qualified); + knownGadgets.insert(def.qualified, def.qualified); + classList += def; + } + } } static bool any_type_contains(const QVector<PropertyDef> &properties, const QByteArray &pattern) @@ -1248,7 +1337,7 @@ void Moc::parsePrivateProperty(ClassDef *def) def->propertyList += propDef; } -void Moc::parseEnumOrFlag(ClassDef *def, bool isFlag) +void Moc::parseEnumOrFlag(BaseDef *def, bool isFlag) { next(LPAREN); QByteArray identifier; @@ -1263,7 +1352,7 @@ void Moc::parseEnumOrFlag(ClassDef *def, bool isFlag) next(RPAREN); } -void Moc::parseFlag(ClassDef *def) +void Moc::parseFlag(BaseDef *def) { next(LPAREN); QByteArray flagName, enumName; @@ -1287,7 +1376,7 @@ void Moc::parseFlag(ClassDef *def) next(RPAREN); } -void Moc::parseClassInfo(ClassDef *def) +void Moc::parseClassInfo(BaseDef *def) { next(LPAREN); ClassInfoDef infoDef; |