diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-01-10 13:16:44 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2022-01-14 00:11:57 +0000 |
commit | aa94804234d821e4028bbf7e07ab13ce0fb05192 (patch) | |
tree | bea14e961a5a650a97b4b63e9985dd274e0c5535 | |
parent | 5682e43fab98c403d2091cc7b9723af4bdb1fff5 (diff) |
shiboken6/Type system parser: Remove class StackElement
Change the ElementType enum to be a global enum class
and replace the linked list of StackElement in the parser by
a stack of the enum.
Fix a broken parent check for inject documentation.
Task-number: PYSIDE-1766
Change-Id: I0d80713bcff3f6a7077998aae91841bb0785a7e5
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
(cherry picked from commit 197dc883975b46742cb0dc8a0e2b2028f66ceefa)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | sources/shiboken6/ApiExtractor/typesystemparser.cpp | 345 | ||||
-rw-r--r-- | sources/shiboken6/ApiExtractor/typesystemparser.h | 78 |
2 files changed, 211 insertions, 212 deletions
diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp index a7ffb1d3e..6d9b75fd1 100644 --- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp @@ -365,7 +365,7 @@ ENUM_LOOKUP_BEGIN(TypeSystem::ExceptionHandling, Qt::CaseSensitive, }; ENUM_LOOKUP_LINEAR_SEARCH() -ENUM_LOOKUP_BEGIN(StackElement::ElementType, Qt::CaseInsensitive, +ENUM_LOOKUP_BEGIN(StackElement, Qt::CaseInsensitive, elementFromTag) { {u"add-conversion", StackElement::AddConversion}, // sorted! @@ -381,6 +381,7 @@ ENUM_LOOKUP_BEGIN(StackElement::ElementType, Qt::CaseInsensitive, {u"enum-type", StackElement::EnumTypeEntry}, {u"extra-includes", StackElement::ExtraIncludes}, {u"function", StackElement::FunctionTypeEntry}, + {u"import-file", StackElement::ImportFile}, {u"include", StackElement::Include}, {u"inject-code", StackElement::InjectCode}, {u"inject-documentation", StackElement::InjectDocumentation}, @@ -703,18 +704,25 @@ bool TypeSystemParser::parseXml(ConditionalStreamReader &reader) case QXmlStreamReader::Invalid: m_error = msgReaderError(reader, reader.errorString()); return false; - case QXmlStreamReader::StartElement: - if (!startElement(reader)) { + case QXmlStreamReader::StartElement: { + const auto elementTypeOpt = elementFromTag(reader.name()); + if (!elementTypeOpt.has_value()) { + m_error = u"Unknown tag name: '"_qs + reader.name().toString() + u'\''; + return false; + } + m_stack.push(elementTypeOpt.value()); + if (!startElement(reader, m_stack.top())) { m_error = msgReaderError(reader, m_error); return false; } - + } break; case QXmlStreamReader::EndElement: - if (!endElement(reader.name())) { + if (!endElement(m_stack.top())) { m_error = msgReaderError(reader, m_error); return false; } + m_stack.pop(); break; case QXmlStreamReader::Characters: if (!characters(reader.text())) { @@ -790,7 +798,7 @@ bool TypeSystemParser::setupSmartPointerInstantiations() return true; } -bool TypeSystemParser::endElement(QStringView localName) +bool TypeSystemParser::endElement(StackElement element) { if (m_ignoreDepth) { --m_ignoreDepth; @@ -802,7 +810,7 @@ bool TypeSystemParser::endElement(QStringView localName) return true; } - if (!localName.compare(QLatin1String("import-file"), Qt::CaseInsensitive)) + if (element == StackElement::ImportFile) return true; if (m_contextStack.isEmpty()) @@ -810,7 +818,7 @@ bool TypeSystemParser::endElement(QStringView localName) const auto &top = m_contextStack.top(); - switch (m_current->type) { + switch (element) { case StackElement::Unimplemented: return true; case StackElement::Root: @@ -872,7 +880,7 @@ bool TypeSystemParser::endElement(QStringView localName) } QString code = top->codeSnips.takeLast().code(); - if (m_current->type == StackElement::AddConversion) { + if (element == StackElement::AddConversion) { if (customConversion->targetToNativeConversions().isEmpty()) { m_error = QLatin1String("CustomConversion's target to native conversions missing."); return false; @@ -893,9 +901,9 @@ bool TypeSystemParser::endElement(QStringView localName) m_templateEntry = nullptr; break; case StackElement::InsertTemplate: - switch (m_current->parent->type) { + switch (m_stack.at(m_stack.size() - 2)) { case StackElement::InjectCode: - if (m_current->parent->parent->type == StackElement::Root) { + if (m_stack.at(m_stack.size() - 3) == StackElement::Root) { CodeSnipList snips = top->entry->codeSnips(); CodeSnip snip = snips.takeLast(); snip.addTemplateInstance(m_templateInstance); @@ -926,27 +934,26 @@ bool TypeSystemParser::endElement(QStringView localName) break; } - if ((m_current->type & StackElement::TypeEntryMask) != 0 - || m_current->type == StackElement::Root) { + if ((element & StackElement::TypeEntryMask) != 0 + || element == StackElement::Root) { m_contextStack.pop(); } - StackElement *child = m_current; - m_current = m_current->parent; - delete(child); - return true; } template <class String> // QString/QStringRef bool TypeSystemParser::characters(const String &ch) { + const auto stackSize = m_stack.size(); if (m_currentDroppedEntryDepth != 0 || m_ignoreDepth != 0 - || m_current->type == StackElement::Unimplemented) { + || stackSize == 0 || m_stack.top() == StackElement::Unimplemented) { return true; } - if (m_current->type == StackElement::Template) { + const StackElement type = m_stack.top(); + + if (type == StackElement::Template) { m_templateEntry->addCode(ch); return true; } @@ -958,45 +965,43 @@ bool TypeSystemParser::characters(const String &ch) const auto &top = m_contextStack.top(); - if (m_current->type == StackElement::ConversionRule - && m_current->parent->type == StackElement::ModifyArgument) { + if (type == StackElement::ConversionRule && stackSize > 1 + && m_stack.at(stackSize - 2) == StackElement::ModifyArgument) { top->functionMods.last().argument_mods().last().conversionRules().last().addCode(ch); return true; } - if (m_current->type == StackElement::NativeToTarget || m_current->type == StackElement::AddConversion) { + if (type == StackElement::NativeToTarget || type == StackElement::AddConversion) { top->codeSnips.last().addCode(ch); return true; } - if (m_current->parent) { - if ((m_current->type & StackElement::CodeSnipMask)) { - CodeSnipList snips; - switch (m_current->parent->type) { - case StackElement::Root: - snips = top->entry->codeSnips(); - snips.last().addCode(ch); - top->entry->setCodeSnips(snips); - break; - case StackElement::ModifyFunction: - case StackElement::AddFunction: - top->functionMods.last().snips().last().addCode(ch); - top->functionMods.last().setModifierFlag(FunctionModification::CodeInjection); - break; - case StackElement::NamespaceTypeEntry: - case StackElement::ObjectTypeEntry: - case StackElement::ValueTypeEntry: - case StackElement::InterfaceTypeEntry: - top->codeSnips.last().addCode(ch); - break; - default: - Q_ASSERT(false); - } - return true; + if ((type & StackElement::CodeSnipMask) != 0 && stackSize > 1) { + CodeSnipList snips; + switch (m_stack.at(stackSize - 2)) { + case StackElement::Root: + snips = top->entry->codeSnips(); + snips.last().addCode(ch); + top->entry->setCodeSnips(snips); + break; + case StackElement::ModifyFunction: + case StackElement::AddFunction: + top->functionMods.last().snips().last().addCode(ch); + top->functionMods.last().setModifierFlag(FunctionModification::CodeInjection); + break; + case StackElement::NamespaceTypeEntry: + case StackElement::ObjectTypeEntry: + case StackElement::ValueTypeEntry: + case StackElement::InterfaceTypeEntry: + top->codeSnips.last().addCode(ch); + break; + default: + Q_ASSERT(false); } + return true; } - if (m_current->type & StackElement::DocumentationMask) + if ((type & StackElement::DocumentationMask) != 0) top->docModifications.last().setCode(ch); return true; @@ -1575,14 +1580,14 @@ FunctionTypeEntry * TypedefEntry * TypeSystemParser::parseTypedefEntry(const ConditionalStreamReader &reader, - const QString &name, + const QString &name, StackElement topElement, const QVersionNumber &since, QXmlStreamAttributes *attributes) { if (!checkRootElement()) return nullptr; - if (m_current && m_current->type != StackElement::Root - && m_current->type != StackElement::NamespaceTypeEntry) { + if (topElement != StackElement::Root + && topElement != StackElement::NamespaceTypeEntry) { m_error = QLatin1String("typedef entries must be nested in namespaces or type system."); return nullptr; } @@ -1762,15 +1767,16 @@ bool TypeSystemParser::parseRenameFunction(const ConditionalStreamReader &, return true; } -bool TypeSystemParser::parseInjectDocumentation(const ConditionalStreamReader &, +bool TypeSystemParser::parseInjectDocumentation(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *attributes) { const auto validParent = StackElement::TypeEntryMask | StackElement::ModifyFunction - | StackElement::ModifyField; - if (!m_current->parent || (m_current->parent->type & validParent) == 0) { - m_error = QLatin1String("inject-documentation must be inside modify-function, " - "modify-field or other tags that creates a type"); + | StackElement::ModifyField + | StackElement::AddFunction; + if ((topElement & validParent) == 0) { + m_error = u"inject-documentation must be inside modify-function, add-function" + "modify-field or other tags that creates a type"_qs; return false; } @@ -1797,7 +1803,7 @@ bool TypeSystemParser::parseInjectDocumentation(const ConditionalStreamReader &, } } - QString signature = m_current->type & StackElement::TypeEntryMask + QString signature = topElement & StackElement::TypeEntryMask ? QString() : m_currentSignature; DocModification mod(mode, signature); mod.setFormat(lang); @@ -1806,12 +1812,13 @@ bool TypeSystemParser::parseInjectDocumentation(const ConditionalStreamReader &, } bool TypeSystemParser::parseModifyDocumentation(const ConditionalStreamReader &, + StackElement topElement, QXmlStreamAttributes *attributes) { const auto validParent = StackElement::TypeEntryMask | StackElement::ModifyFunction | StackElement::ModifyField; - if (!m_current->parent || (m_current->parent->type & validParent) == 0) { + if ((topElement & validParent) == 0) { m_error = QLatin1String("modify-documentation must be inside modify-function, " "modify-field or other tags that creates a type"); return false; @@ -1824,7 +1831,7 @@ bool TypeSystemParser::parseModifyDocumentation(const ConditionalStreamReader &, } const QString xpath = attributes->takeAt(xpathIndex).value().toString(); - QString signature = (m_current->type & StackElement::TypeEntryMask) ? QString() : m_currentSignature; + QString signature = (topElement & StackElement::TypeEntryMask) ? QString() : m_currentSignature; m_contextStack.top()->docModifications << DocModification(xpath, signature); return true; @@ -1933,10 +1940,10 @@ bool TypeSystemParser::parseRejectEnumValue(const ConditionalStreamReader &, } bool TypeSystemParser::parseReplaceArgumentType(const ConditionalStreamReader &, - const StackElement &topElement, + StackElement topElement, QXmlStreamAttributes *attributes) { - if (topElement.type != StackElement::ModifyArgument) { + if (topElement != StackElement::ModifyArgument) { m_error = QLatin1String("Type replacement can only be specified for argument modifications"); return false; } @@ -1951,13 +1958,13 @@ bool TypeSystemParser::parseReplaceArgumentType(const ConditionalStreamReader &, } bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &, - const StackElement &topElement, + StackElement topElement, QXmlStreamAttributes *attributes) { - if (topElement.type != StackElement::ModifyArgument - && topElement.type != StackElement::ValueTypeEntry - && topElement.type != StackElement::PrimitiveTypeEntry - && topElement.type != StackElement::ContainerTypeEntry) { + if (topElement != StackElement::ModifyArgument + && topElement != StackElement::ValueTypeEntry + && topElement != StackElement::PrimitiveTypeEntry + && topElement != StackElement::ContainerTypeEntry) { m_error = QLatin1String("Conversion rules can only be specified for argument modification, " "value-type, primitive-type or container-type conversion."); return false; @@ -1984,7 +1991,7 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &, } const auto &top = m_contextStack.top(); - if (topElement.type == StackElement::ModifyArgument) { + if (topElement == StackElement::ModifyArgument) { CodeSnip snip; snip.language = lang; top->functionMods.last().argument_mods().last().conversionRules().append(snip); @@ -2027,10 +2034,10 @@ bool TypeSystemParser::parseCustomConversion(const ConditionalStreamReader &, } bool TypeSystemParser::parseNativeToTarget(const ConditionalStreamReader &, - const StackElement &topElement, + StackElement topElement, QXmlStreamAttributes *attributes) { - if (topElement.type != StackElement::ConversionRule) { + if (topElement != StackElement::ConversionRule) { m_error = QLatin1String("Native to Target conversion code can only be specified for custom conversion rules."); return false; } @@ -2042,10 +2049,10 @@ bool TypeSystemParser::parseNativeToTarget(const ConditionalStreamReader &, } bool TypeSystemParser::parseAddConversion(const ConditionalStreamReader &, - const StackElement &topElement, + StackElement topElement, QXmlStreamAttributes *attributes) { - if (topElement.type != StackElement::TargetToNative) { + if (topElement != StackElement::TargetToNative) { m_error = QLatin1String("Target to Native conversions can only be added inside 'target-to-native' tags."); return false; } @@ -2094,13 +2101,13 @@ static bool parseArgumentIndex(const QString &index, int *result, QString *error } bool TypeSystemParser::parseModifyArgument(const ConditionalStreamReader &, - const StackElement &topElement, QXmlStreamAttributes *attributes) + StackElement topElement, QXmlStreamAttributes *attributes) { - if (topElement.type != StackElement::ModifyFunction - && topElement.type != StackElement::AddFunction) { + if (topElement != StackElement::ModifyFunction + && topElement != StackElement::AddFunction) { m_error = QString::fromLatin1("argument modification requires function" " modification as parent, was %1") - .arg(topElement.type, 0, 16); + .arg(uint64_t(topElement), 0, 16); return false; } @@ -2140,9 +2147,9 @@ bool TypeSystemParser::parseModifyArgument(const ConditionalStreamReader &, } bool TypeSystemParser::parseNoNullPointer(const ConditionalStreamReader &reader, - const StackElement &topElement, QXmlStreamAttributes *attributes) + StackElement topElement, QXmlStreamAttributes *attributes) { - if (topElement.type != StackElement::ModifyArgument) { + if (topElement != StackElement::ModifyArgument) { m_error = QLatin1String("no-null-pointer requires argument modification as parent"); return false; } @@ -2161,10 +2168,10 @@ bool TypeSystemParser::parseNoNullPointer(const ConditionalStreamReader &reader, } bool TypeSystemParser::parseDefineOwnership(const ConditionalStreamReader &, - const StackElement &topElement, + StackElement topElement, QXmlStreamAttributes *attributes) { - if (topElement.type != StackElement::ModifyArgument) { + if (topElement != StackElement::ModifyArgument) { m_error = QLatin1String("define-ownership requires argument modification as parent"); return false; } @@ -2211,10 +2218,10 @@ bool TypeSystemParser::parseDefineOwnership(const ConditionalStreamReader &, // ### fixme PySide7: remove (replaced by attribute). bool TypeSystemParser::parseRename(const ConditionalStreamReader &, - const StackElement &topElement, + StackElement topElement, QXmlStreamAttributes *attributes) { - if (topElement.type != StackElement::ModifyArgument) { + if (topElement != StackElement::ModifyArgument) { m_error = QLatin1String("Argument modification parent required"); return false; } @@ -2280,14 +2287,14 @@ static bool parseOverloadNumber(const QXmlStreamAttribute &attribute, int *overl } bool TypeSystemParser::parseAddFunction(const ConditionalStreamReader &, - const StackElement &topElement, - StackElement::ElementType t, + StackElement topElement, + StackElement t, QXmlStreamAttributes *attributes) { - if (!(topElement.type + if (!(topElement & (StackElement::ComplexTypeEntryMask | StackElement::Root | StackElement::ContainerTypeEntry))) { m_error = QString::fromLatin1("Add/Declare function requires a complex/container type or a root tag as parent" - ", was=%1").arg(topElement.type, 0, 16); + ", was=%1").arg(uint64_t(topElement), 0, 16); return false; } QString originalSignature; @@ -2366,12 +2373,12 @@ bool TypeSystemParser::parseAddFunction(const ConditionalStreamReader &, return true; } -bool TypeSystemParser::parseProperty(const ConditionalStreamReader &, const StackElement &topElement, +bool TypeSystemParser::parseProperty(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *attributes) { - if ((topElement.type & StackElement::ComplexTypeEntryMask) == 0) { + if ((topElement & StackElement::ComplexTypeEntryMask) == 0) { m_error = QString::fromLatin1("Add property requires a complex type as parent" - ", was=%1").arg(topElement.type, 0, 16); + ", was=%1").arg(uint64_t(topElement), 0, 16); return false; } @@ -2401,12 +2408,12 @@ bool TypeSystemParser::parseProperty(const ConditionalStreamReader &, const Stac } bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader, - const StackElement &topElement, + StackElement topElement, QXmlStreamAttributes *attributes) { - if (!(topElement.type & StackElement::ComplexTypeEntryMask)) { + if (!(topElement & StackElement::ComplexTypeEntryMask)) { m_error = QString::fromLatin1("Modify function requires complex type as parent" - ", was=%1").arg(topElement.type, 0, 16); + ", was=%1").arg(uint64_t(topElement), 0, 16); return false; } @@ -2533,10 +2540,10 @@ bool TypeSystemParser::parseModifyFunction(const ConditionalStreamReader &reader } bool TypeSystemParser::parseReplaceDefaultExpression(const ConditionalStreamReader &, - const StackElement &topElement, + StackElement topElement, QXmlStreamAttributes *attributes) { - if (!(topElement.type & StackElement::ModifyArgument)) { + if (!(topElement & StackElement::ModifyArgument)) { m_error = QLatin1String("Replace default expression only allowed as child of argument modification"); return false; } @@ -2552,10 +2559,10 @@ bool TypeSystemParser::parseReplaceDefaultExpression(const ConditionalStreamRead } bool TypeSystemParser::parseReferenceCount(const ConditionalStreamReader &reader, - const StackElement &topElement, + StackElement topElement, QXmlStreamAttributes *attributes) { - if (topElement.type != StackElement::ModifyArgument) { + if (topElement != StackElement::ModifyArgument) { m_error = QLatin1String("reference-count must be child of modify-argument"); return false; } @@ -2590,10 +2597,10 @@ bool TypeSystemParser::parseReferenceCount(const ConditionalStreamReader &reader } bool TypeSystemParser::parseParentOwner(const ConditionalStreamReader &, - const StackElement &topElement, + StackElement topElement, QXmlStreamAttributes *attributes) { - if (topElement.type != StackElement::ModifyArgument) { + if (topElement != StackElement::ModifyArgument) { m_error = QLatin1String("parent-policy must be child of modify-argument"); return false; } @@ -2665,13 +2672,13 @@ bool TypeSystemParser::readFileSnippet(QXmlStreamAttributes *attributes, CodeSni } bool TypeSystemParser::parseInjectCode(const ConditionalStreamReader &, - const StackElement &topElement, - StackElement* element, QXmlStreamAttributes *attributes) + StackElement topElement, + QXmlStreamAttributes *attributes) { - if (!(topElement.type & StackElement::ComplexTypeEntryMask) - && (topElement.type != StackElement::AddFunction) - && (topElement.type != StackElement::ModifyFunction) - && (topElement.type != StackElement::Root)) { + if (!(topElement & StackElement::ComplexTypeEntryMask) + && (topElement != StackElement::AddFunction) + && (topElement != StackElement::ModifyFunction) + && (topElement != StackElement::Root)) { m_error = QLatin1String("wrong parent type for code injection"); return false; } @@ -2705,23 +2712,23 @@ bool TypeSystemParser::parseInjectCode(const ConditionalStreamReader &, snip.position = position; snip.language = lang; - if (topElement.type == StackElement::ModifyFunction - || topElement.type == StackElement::AddFunction) { + if (topElement == StackElement::ModifyFunction + || topElement == StackElement::AddFunction) { FunctionModification &mod = m_contextStack.top()->functionMods.last(); mod.appendSnip(snip); if (!snip.code().isEmpty()) mod.setModifierFlag(FunctionModification::CodeInjection); - element->type = StackElement::InjectCodeInFunction; - } else if (topElement.type == StackElement::Root) { + m_stack.top() = StackElement::InjectCodeInFunction; + } else if (topElement == StackElement::Root) { m_contextStack.top()->entry->addCodeSnip(snip); - } else if (topElement.type != StackElement::Root) { + } else if (topElement != StackElement::Root) { m_contextStack.top()->codeSnips << snip; } return true; } bool TypeSystemParser::parseInclude(const ConditionalStreamReader &, - const StackElement &topElement, + StackElement topElement, TypeEntry *entry, QXmlStreamAttributes *attributes) { QString fileName; @@ -2742,10 +2749,10 @@ bool TypeSystemParser::parseInclude(const ConditionalStreamReader &, } Include inc(location, fileName); - if (topElement.type + if (topElement & (StackElement::ComplexTypeEntryMask | StackElement::PrimitiveTypeEntry)) { entry->setInclude(inc); - } else if (topElement.type == StackElement::ExtraIncludes) { + } else if (topElement == StackElement::ExtraIncludes) { entry->addExtraInclude(inc); } else { m_error = QLatin1String("Only supported parent tags are primitive-type, complex types or extra-includes"); @@ -2768,14 +2775,14 @@ bool TypeSystemParser::parseSystemInclude(const ConditionalStreamReader &, TemplateInstance * TypeSystemParser::parseInsertTemplate(const ConditionalStreamReader &, - const StackElement &topElement, + StackElement topElement, QXmlStreamAttributes *attributes) { - if (!(topElement.type & StackElement::CodeSnipMask) && - (topElement.type != StackElement::Template) && - (topElement.type != StackElement::NativeToTarget) && - (topElement.type != StackElement::AddConversion) && - (topElement.type != StackElement::ConversionRule)) { + if (!(topElement & StackElement::CodeSnipMask) && + (topElement != StackElement::Template) && + (topElement != StackElement::NativeToTarget) && + (topElement != StackElement::AddConversion) && + (topElement != StackElement::ConversionRule)) { m_error = QLatin1String("Can only insert templates into code snippets, templates, "\ "conversion-rule, native-to-target or add-conversion tags."); return nullptr; @@ -2789,10 +2796,9 @@ TemplateInstance * } bool TypeSystemParser::parseReplace(const ConditionalStreamReader &, - const StackElement &topElement, - StackElement *, QXmlStreamAttributes *attributes) + StackElement topElement, QXmlStreamAttributes *attributes) { - if (topElement.type != StackElement::InsertTemplate) { + if (topElement != StackElement::InsertTemplate) { m_error = QLatin1String("Can only insert replace rules into insert-template."); return false; } @@ -2814,7 +2820,7 @@ bool TypeSystemParser::parseReplace(const ConditionalStreamReader &, // or it's not possible to cover all primitive target language // types (which we need to do in order to support fake meta objects) bool TypeSystemParser::checkDuplicatedTypeEntry(const ConditionalStreamReader &reader, - StackElement::ElementType t, + StackElement t, const QString &name) const { if (t == StackElement::PrimitiveTypeEntry || t == StackElement::FunctionTypeEntry) @@ -2845,7 +2851,7 @@ static bool parseVersion(const QString &versionSpec, const QString &package, return true; } -bool TypeSystemParser::startElement(const ConditionalStreamReader &reader) +bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, StackElement element) { if (m_ignoreDepth) { ++m_ignoreDepth; @@ -2879,34 +2885,25 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader) } } - if (tagName.compare(QLatin1String("import-file"), Qt::CaseInsensitive) == 0) + if (element == StackElement::ImportFile) return importFileElement(attributes); - const auto elementTypeOpt = elementFromTag(tagName); - if (!elementTypeOpt.has_value()) { - m_error = u"Unknown tag name: '"_qs + tagName.toString() + u'\''; - return false; - } - if (m_currentDroppedEntryDepth) { ++m_currentDroppedEntryDepth; return true; } - std::unique_ptr<StackElement> element(new StackElement(m_current)); - element->type = elementTypeOpt.value(); - - if (element->type == StackElement::Root && m_generate == TypeEntry::GenerateCode) + if (element == StackElement::Root && m_generate == TypeEntry::GenerateCode) customConversionsForReview.clear(); - if (element->type == StackElement::Unimplemented) { + if (element == StackElement::Unimplemented) { qCWarning(lcShiboken, "%s", qPrintable(msgUnimplementedElementWarning(reader, tagName))); return true; } - if ((element->type & StackElement::TypeEntryMask) != 0 - || element->type == StackElement::Root) { + if ((element & StackElement::TypeEntryMask) != 0 + || element == StackElement::Root) { m_contextStack.push(StackElementContextPtr(new StackElementContext())); } @@ -2916,27 +2913,28 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader) } const auto &top = m_contextStack.top(); + const StackElement topElement = m_stack.value(m_stack.size() - 2, StackElement::None); - if (element->type & StackElement::TypeEntryMask) { + if (element & StackElement::TypeEntryMask) { QString name; - if (element->type != StackElement::FunctionTypeEntry) { + if (element != StackElement::FunctionTypeEntry) { const int nameIndex = indexOfAttribute(attributes, nameAttribute()); if (nameIndex != -1) { name = attributes.takeAt(nameIndex).value().toString(); - } else if (element->type != StackElement::EnumTypeEntry) { // anonymous enum? + } else if (element != StackElement::EnumTypeEntry) { // anonymous enum? m_error = msgMissingAttribute(nameAttribute()); return false; } } // Allow for primitive and/or std:: types only, else require proper nesting. - if (element->type != StackElement::PrimitiveTypeEntry && name.contains(QLatin1Char(':')) + if (element != StackElement::PrimitiveTypeEntry && name.contains(QLatin1Char(':')) && !name.contains(QLatin1String("std::"))) { m_error = msgIncorrectlyNestedName(name); return false; } if (m_database->hasDroppedTypeEntries()) { - const QString identifier = element->type == StackElement::FunctionTypeEntry + const QString identifier = element == StackElement::FunctionTypeEntry ? attributes.value(signatureAttribute()).toString() : name; if (shouldDropTypeEntry(m_database, m_contextStack, identifier)) { m_currentDroppedEntryDepth = 1; @@ -2951,7 +2949,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader) // The top level tag 'function' has only the 'signature' tag // and we should extract the 'name' value from it. - if (element->type == StackElement::FunctionTypeEntry + if (element == StackElement::FunctionTypeEntry && !parseRenameFunction(reader, &name, &attributes)) { return false; } @@ -2959,15 +2957,15 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader) // We need to be able to have duplicate primitive type entries, // or it's not possible to cover all primitive target language // types (which we need to do in order to support fake meta objects) - if (element->type != StackElement::PrimitiveTypeEntry - && element->type != StackElement::FunctionTypeEntry) { + if (element != StackElement::PrimitiveTypeEntry + && element != StackElement::FunctionTypeEntry) { TypeEntry *tmp = m_database->findType(name); if (tmp && !tmp->isNamespace()) qCWarning(lcShiboken).noquote().nospace() << "Duplicate type entry: '" << name << '\''; } - if (element->type == StackElement::EnumTypeEntry) { + if (element == StackElement::EnumTypeEntry) { const int enumIdentifiedByIndex = indexOfAttribute(attributes, enumIdentifiedByValueAttribute()); const QString identifiedByValue = enumIdentifiedByIndex != -1 ? attributes.takeAt(enumIdentifiedByIndex).value().toString() : QString(); @@ -2984,7 +2982,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader) return false; } - switch (element->type) { + switch (element) { case StackElement::CustomTypeEntry: top->entry = parseCustomTypeEntry(reader, name, versionRange.since, &attributes); if (Q_UNLIKELY(!top->entry)) @@ -3049,7 +3047,8 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader) return false; break; case StackElement::TypedefTypeEntry: - if (TypedefEntry *te = parseTypedefEntry(reader, name, versionRange.since, &attributes)) { + if (TypedefEntry *te = parseTypedefEntry(reader, name, topElement, + versionRange.since, &attributes)) { applyComplexTypeAttributes(reader, te, &attributes); top->entry = te; } else { @@ -3061,7 +3060,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader) } if (top->entry) { - if (checkDuplicatedTypeEntry(reader, element->type, top->entry->name()) + if (checkDuplicatedTypeEntry(reader, element, top->entry->name()) && !m_database->addType(top->entry, &m_error)) { return false; } @@ -3070,35 +3069,32 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader) << u"Type: "_qs + name + u" was rejected by typesystem"_qs; } - } else if (element->type == StackElement::InjectDocumentation) { - if (!parseInjectDocumentation(reader, &attributes)) + } else if (element == StackElement::InjectDocumentation) { + if (!parseInjectDocumentation(reader, topElement, &attributes)) return false; - } else if (element->type == StackElement::ModifyDocumentation) { - if (!parseModifyDocumentation(reader, &attributes)) + } else if (element == StackElement::ModifyDocumentation) { + if (!parseModifyDocumentation(reader, topElement, &attributes)) return false; - } else if (element->type != StackElement::None) { - bool topLevel = element->type == StackElement::Root - || element->type == StackElement::SuppressedWarning - || element->type == StackElement::Rejection - || element->type == StackElement::LoadTypesystem - || element->type == StackElement::InjectCode - || element->type == StackElement::ExtraIncludes - || element->type == StackElement::SystemInclude - || element->type == StackElement::ConversionRule - || element->type == StackElement::AddFunction - || element->type == StackElement::Template; - - if (!topLevel && m_current->type == StackElement::Root) { + } else if (element != StackElement::None) { + bool topLevel = element == StackElement::Root + || element == StackElement::SuppressedWarning + || element == StackElement::Rejection + || element == StackElement::LoadTypesystem + || element == StackElement::InjectCode + || element == StackElement::ExtraIncludes + || element == StackElement::SystemInclude + || element == StackElement::ConversionRule + || element == StackElement::AddFunction + || element == StackElement::Template; + + if (!topLevel && m_stack.at(m_stack.size() - 2) == StackElement::Root) { m_error = u"Tag requires parent: '"_qs + tagName.toString() + u'\''; return false; } - StackElement topElement = !m_current ? StackElement(nullptr) : *m_current; - - switch (element->type) { + switch (element) { case StackElement::Root: top->entry = parseRootElement(reader, versionRange.since, &attributes); - element->type = StackElement::Root; break; case StackElement::LoadTypesystem: if (!loadTypesystem(reader, &attributes)) @@ -3121,7 +3117,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader) return false; break; case StackElement::TargetToNative: { - if (topElement.type != StackElement::ConversionRule) { + if (topElement != StackElement::ConversionRule) { m_error = QLatin1String("Target to Native conversions can only be specified for custom conversion rules."); return false; } @@ -3165,7 +3161,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader) return false; break; case StackElement::RemoveArgument: - if (topElement.type != StackElement::ModifyArgument) { + if (topElement != StackElement::ModifyArgument) { m_error = QLatin1String("Removing argument requires argument modification as parent"); return false; } @@ -3179,7 +3175,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader) break; case StackElement::DeclareFunction: case StackElement::AddFunction: - if (!parseAddFunction(reader, topElement, element->type, &attributes)) + if (!parseAddFunction(reader, topElement, element, &attributes)) return false; break; case StackElement::Property: @@ -3206,14 +3202,14 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader) return false; break; case StackElement::Array: - if (topElement.type != StackElement::ModifyArgument) { + if (topElement != StackElement::ModifyArgument) { m_error = QLatin1String("array must be child of modify-argument"); return false; } top->functionMods.last().argument_mods().last().setArray(true); break; case StackElement::InjectCode: - if (!parseInjectCode(reader, topElement, element.get(), &attributes)) + if (!parseInjectCode(reader, topElement, &attributes)) return false; break; case StackElement::Include: @@ -3244,7 +3240,7 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader) return false; break; case StackElement::Replace: - if (!parseReplace(reader, topElement, element.get(), &attributes)) + if (!parseReplace(reader, topElement, &attributes)) return false; break; default: @@ -3257,6 +3253,5 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader) qCWarning(lcShiboken, "%s", qPrintable(msgReaderWarning(reader, message))); } - m_current = element.release(); return true; } diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.h b/sources/shiboken6/ApiExtractor/typesystemparser.h index c03bc47e7..151826d50 100644 --- a/sources/shiboken6/ApiExtractor/typesystemparser.h +++ b/sources/shiboken6/ApiExtractor/typesystemparser.h @@ -45,10 +45,7 @@ class ConditionalStreamReader; class TypeSystemEntityResolver; class TypeDatabase; -class StackElement -{ - public: - enum ElementType : uint64_t { +enum class StackElement : uint64_t { None = 0x0, // Type tags (0x1, ... , 0xff) @@ -119,14 +116,19 @@ class StackElement Array = 0xA0000000, ArgumentModifiers = 0xff000000, - Unimplemented = 0x100000000 - }; + ImportFile = 0x100000000, + Unimplemented = 0x200000000 +}; - StackElement(StackElement *p) : type(None), parent(p) { } +inline uint64_t operator&(StackElement s1, StackElement s2) +{ + return uint64_t(s1) & uint64_t(s2); +} - ElementType type; - StackElement *parent; -}; +inline StackElement operator|(StackElement s1, StackElement s2) +{ + return StackElement(uint64_t(s1) | uint64_t(s2)); +} struct StackElementContext { @@ -157,12 +159,12 @@ public: private: bool parseXml(ConditionalStreamReader &reader); bool setupSmartPointerInstantiations(); - bool startElement(const ConditionalStreamReader &reader); + bool startElement(const ConditionalStreamReader &reader, StackElement element); SmartPointerTypeEntry *parseSmartPointerEntry(const ConditionalStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes); - bool endElement(QStringView localName); + bool endElement(StackElement element); template <class String> // QString/QStringRef bool characters(const String &ch); @@ -202,63 +204,65 @@ private: const QVersionNumber &since, QXmlStreamAttributes *); TypedefEntry * parseTypedefEntry(const ConditionalStreamReader &, const QString &name, + StackElement topElement, const QVersionNumber &since, QXmlStreamAttributes *); void applyComplexTypeAttributes(const ConditionalStreamReader &, ComplexTypeEntry *ctype, QXmlStreamAttributes *) const; bool parseRenameFunction(const ConditionalStreamReader &, QString *name, QXmlStreamAttributes *); - bool parseInjectDocumentation(const ConditionalStreamReader &, QXmlStreamAttributes *); - bool parseModifyDocumentation(const ConditionalStreamReader &, QXmlStreamAttributes *); + bool parseInjectDocumentation(const ConditionalStreamReader &, StackElement topElement, + QXmlStreamAttributes *); + bool parseModifyDocumentation(const ConditionalStreamReader &, StackElement topElement, + QXmlStreamAttributes *); TypeSystemTypeEntry * parseRootElement(const ConditionalStreamReader &, const QVersionNumber &since, QXmlStreamAttributes *); bool loadTypesystem(const ConditionalStreamReader &, QXmlStreamAttributes *); bool parseRejectEnumValue(const ConditionalStreamReader &, QXmlStreamAttributes *); - bool parseReplaceArgumentType(const ConditionalStreamReader &, const StackElement &topElement, + bool parseReplaceArgumentType(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); - bool parseCustomConversion(const ConditionalStreamReader &, const StackElement &topElement, + bool parseCustomConversion(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); - bool parseAddConversion(const ConditionalStreamReader &, const StackElement &topElement, + bool parseAddConversion(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); - bool parseNativeToTarget(const ConditionalStreamReader &, const StackElement &topElement, + bool parseNativeToTarget(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *attributes); - bool parseModifyArgument(const ConditionalStreamReader &, const StackElement &topElement, + bool parseModifyArgument(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *attributes); - bool parseNoNullPointer(const ConditionalStreamReader &, const StackElement &topElement, + bool parseNoNullPointer(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *attributes); - bool parseDefineOwnership(const ConditionalStreamReader &, const StackElement &topElement, + bool parseDefineOwnership(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); - bool parseRename(const ConditionalStreamReader &, const StackElement &topElement, + bool parseRename(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); bool parseModifyField(const ConditionalStreamReader &, QXmlStreamAttributes *); - bool parseAddFunction(const ConditionalStreamReader &, const StackElement &topElement, - StackElement::ElementType t, QXmlStreamAttributes *); - bool parseProperty(const ConditionalStreamReader &, const StackElement &topElement, + bool parseAddFunction(const ConditionalStreamReader &, StackElement topElement, + StackElement t, QXmlStreamAttributes *); + bool parseProperty(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); - bool parseModifyFunction(const ConditionalStreamReader &, const StackElement &topElement, + bool parseModifyFunction(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); bool parseReplaceDefaultExpression(const ConditionalStreamReader &, - const StackElement &topElement, QXmlStreamAttributes *); - bool parseReferenceCount(const ConditionalStreamReader &, const StackElement &topElement, + StackElement topElement, QXmlStreamAttributes *); + bool parseReferenceCount(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); - bool parseParentOwner(const ConditionalStreamReader &, const StackElement &topElement, + bool parseParentOwner(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); bool readFileSnippet(QXmlStreamAttributes *attributes, CodeSnip *snip); - bool parseInjectCode(const ConditionalStreamReader &, const StackElement &topElement, - StackElement* element, QXmlStreamAttributes *); - bool parseInclude(const ConditionalStreamReader &, const StackElement &topElement, + bool parseInjectCode(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); + bool parseInclude(const ConditionalStreamReader &, StackElement topElement, TypeEntry *entry, QXmlStreamAttributes *); bool parseSystemInclude(const ConditionalStreamReader &, QXmlStreamAttributes *); TemplateInstance - *parseInsertTemplate(const ConditionalStreamReader &, const StackElement &topElement, + *parseInsertTemplate(const ConditionalStreamReader &, StackElement topElement, QXmlStreamAttributes *); - bool parseReplace(const ConditionalStreamReader &, const StackElement &topElement, - StackElement *element, QXmlStreamAttributes *); + bool parseReplace(const ConditionalStreamReader &, StackElement topElement, + QXmlStreamAttributes *); bool checkDuplicatedTypeEntry(const ConditionalStreamReader &reader, - StackElement::ElementType t, const QString &name) const; + StackElement t, const QString &name) const; TypeDatabase* m_database; - StackElement* m_current = nullptr; + QStack<StackElement> m_stack; int m_currentDroppedEntryDepth = 0; int m_ignoreDepth = 0; QString m_defaultPackage; |