From b4ffbed19625bbf468c660a6dcc35a1101b8791b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 11 Jan 2022 13:55:38 +0100 Subject: shiboken6/Type system parser: Introduce a helper for the code snippets Introduce a helper returning a parser state depending on the element stack and building on that, a helper which returns the code snippet to append to. This is used for character handling and . It also allows for removing StackElement::InjectCodeInFunction, which was a fake element for remembering that the code injection targets a function. Also, add all type entry code snippets directly to the type entry instead of temporarily storing them in StackElementContext::codeSnips. Use the latter for conversions only and rename it accordingly. Pick-to: 6.2 Task-number: PYSIDE-1766 Change-Id: I291ec2db58687fdf63c124ddde26165f8eb09856 Reviewed-by: Christian Tismer --- .../shiboken6/ApiExtractor/typesystemparser.cpp | 169 +++++++++++++-------- sources/shiboken6/ApiExtractor/typesystemparser.h | 7 +- 2 files changed, 107 insertions(+), 69 deletions(-) diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp index af6202691..75ca328d7 100644 --- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp @@ -541,6 +541,19 @@ QString TypeSystemEntityResolver::resolveUndeclaredEntity(const QString &name) return result; } +// State depending on element stack +enum class ParserState +{ + None, + PrimitiveTypeNativeToTargetConversion, + PrimitiveTypeTargetToNativeConversion, + ArgumentConversion, // Argument conversion rule with class attribute + FunctionCodeInjection, + TypeEntryCodeInjection, + TypeSystemCodeInjection, + Template +}; + TypeSystemParser::TypeSystemParser(TypeDatabase *database, bool generate) : m_database(database), m_generate(generate ? TypeEntry::GenerateCode : TypeEntry::GenerateForSubclass) @@ -846,7 +859,6 @@ bool TypeSystemParser::endElement(StackElement element) centry->setAddedFunctions(top->addedFunctions); centry->setFunctionModifications(top->functionMods); centry->setFieldModifications(top->fieldMods); - centry->setCodeSnips(top->codeSnips); centry->setDocModification(top->docModifications); } break; @@ -856,7 +868,7 @@ bool TypeSystemParser::endElement(StackElement element) centry->setAddedFunctions(centry->addedFunctions() + top->addedFunctions); centry->setFunctionModifications(centry->functionModifications() + top->functionMods); centry->setFieldModifications(centry->fieldModifications() + top->fieldMods); - centry->setCodeSnips(centry->codeSnips() + top->codeSnips); + centry->setCodeSnips(centry->codeSnips() + top->entry->codeSnips()); centry->setDocModification(centry->docModifications() + top->docModifications); } break; @@ -879,7 +891,7 @@ bool TypeSystemParser::endElement(StackElement element) return false; } - QString code = top->codeSnips.takeLast().code(); + QString code = top->conversionCodeSnips.takeLast().code(); if (element == StackElement::AddConversion) { if (customConversion->targetToNativeConversions().isEmpty()) { m_error = QLatin1String("CustomConversion's target to native conversions missing."); @@ -901,29 +913,8 @@ bool TypeSystemParser::endElement(StackElement element) m_templateEntry = nullptr; break; case StackElement::InsertTemplate: - switch (m_stack.at(m_stack.size() - 2)) { - case StackElement::InjectCode: - if (m_stack.at(m_stack.size() - 3) == StackElement::Root) { - top->entry->codeSnips().last().addTemplateInstance(m_templateInstance); - break; - } - Q_FALLTHROUGH(); - case StackElement::NativeToTarget: - case StackElement::AddConversion: - top->codeSnips.last().addTemplateInstance(m_templateInstance); - break; - case StackElement::Template: - m_templateEntry->addTemplateInstance(m_templateInstance); - break; - case StackElement::ConversionRule: - top->functionMods.last().argument_mods().last().conversionRules().last().addTemplateInstance(m_templateInstance); - break; - case StackElement::InjectCodeInFunction: - top->functionMods.last().snips().last().addTemplateInstance(m_templateInstance); - break; - default: - break; // nada - } + if (auto *snip = injectCodeTarget(1)) + snip->addTemplateInstance(m_templateInstance); m_templateInstance.reset(); break; default: @@ -938,6 +929,85 @@ bool TypeSystemParser::endElement(StackElement element) return true; } +ParserState TypeSystemParser::parserState(qsizetype offset) const +{ + const auto stackSize = m_stack.size() - offset; + if (stackSize <= 0 || m_contextStack.isEmpty()) + return ParserState::None; + + const auto last = stackSize - 1; + + switch (m_stack.at(last)) { + // Primitive entry with conversion rule + case StackElement::NativeToTarget: // + return ParserState::PrimitiveTypeNativeToTargetConversion; + + case StackElement::AddConversion: // + return ParserState::PrimitiveTypeTargetToNativeConversion; + + case StackElement::ConversionRule: + if (stackSize > 1 && m_stack.at(last - 1) == StackElement::ModifyArgument) + return ParserState::ArgumentConversion; + break; + + case StackElement::InjectCode: + switch (m_stack.value(last - 1, StackElement::None)) { + case StackElement::Root: + return ParserState::TypeSystemCodeInjection; + case StackElement::ModifyFunction: + case StackElement::AddFunction: + return ParserState::FunctionCodeInjection; + case StackElement::NamespaceTypeEntry: + case StackElement::ObjectTypeEntry: + case StackElement::ValueTypeEntry: + case StackElement::InterfaceTypeEntry: + return ParserState::TypeEntryCodeInjection; + default: + break; + } + break; + + case StackElement::Template: + return ParserState::Template; + + default: + break; + } + + return ParserState::None; +} + +// Return where to add injected code depending on elements. +CodeSnipAbstract *TypeSystemParser::injectCodeTarget(qsizetype offset) const +{ + const auto state = parserState(offset); + if (state == ParserState::None) + return nullptr; + + const auto &top = m_contextStack.top(); + switch (state) { + case ParserState::PrimitiveTypeNativeToTargetConversion: + case ParserState::PrimitiveTypeTargetToNativeConversion: + return &top->conversionCodeSnips.last(); + case ParserState::ArgumentConversion: + return &top->functionMods.last().argument_mods().last().conversionRules().last(); + case ParserState::FunctionCodeInjection: { + auto &funcMod = top->functionMods.last(); + funcMod.setModifierFlag(FunctionModification::CodeInjection); + return &funcMod.snips().last(); + } + case ParserState::TypeEntryCodeInjection: + case ParserState::TypeSystemCodeInjection: + return &top->entry->codeSnips().last(); + case ParserState::Template: + return m_templateEntry; + default: + break; + } + + return nullptr; +} + template // QString/QStringRef bool TypeSystemParser::characters(const String &ch) { @@ -959,43 +1029,13 @@ bool TypeSystemParser::characters(const String &ch) return false; } - const auto &top = m_contextStack.top(); - - 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 (type == StackElement::NativeToTarget || type == StackElement::AddConversion) { - top->codeSnips.last().addCode(ch); - return true; - } - - if ((type & StackElement::CodeSnipMask) != 0 && stackSize > 1) { - switch (m_stack.at(stackSize - 2)) { - case StackElement::Root: - top->entry->codeSnips().last().addCode(ch); - 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); - } + if (auto *snip = injectCodeTarget()) { + snip->addCode(ch); return true; } if ((type & StackElement::DocumentationMask) != 0) - top->docModifications.last().setCode(ch); + m_contextStack.top()->docModifications.last().setCode(ch); return true; } @@ -2044,7 +2084,7 @@ bool TypeSystemParser::parseNativeToTarget(const ConditionalStreamReader &, CodeSnip snip; if (!readFileSnippet(attributes, &snip)) return false; - m_contextStack.top()->codeSnips.append(snip); + m_contextStack.top()->conversionCodeSnips.append(snip); return true; } @@ -2074,7 +2114,7 @@ bool TypeSystemParser::parseAddConversion(const ConditionalStreamReader &, } const auto &top = m_contextStack.top(); top->entry->customConversion()->addTargetToNativeConversion(sourceTypeName, typeCheck); - top->codeSnips.append(snip); + top->conversionCodeSnips.append(snip); return true; } @@ -2718,11 +2758,8 @@ bool TypeSystemParser::parseInjectCode(const ConditionalStreamReader &, mod.appendSnip(snip); if (!snip.code().isEmpty()) mod.setModifierFlag(FunctionModification::CodeInjection); - m_stack.top() = StackElement::InjectCodeInFunction; - } else if (topElement == StackElement::Root) { + } else { m_contextStack.top()->entry->addCodeSnip(snip); - } else if (topElement != StackElement::Root) { - m_contextStack.top()->codeSnips << snip; } return true; } @@ -2778,7 +2815,7 @@ TemplateInstance * StackElement topElement, QXmlStreamAttributes *attributes) { - if (!(topElement & StackElement::CodeSnipMask) && + if ((topElement != StackElement::InjectCode) && (topElement != StackElement::Template) && (topElement != StackElement::NativeToTarget) && (topElement != StackElement::AddConversion) && diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.h b/sources/shiboken6/ApiExtractor/typesystemparser.h index 151826d50..d3fbd18cf 100644 --- a/sources/shiboken6/ApiExtractor/typesystemparser.h +++ b/sources/shiboken6/ApiExtractor/typesystemparser.h @@ -44,6 +44,7 @@ class ConditionalStreamReader; class TypeSystemEntityResolver; class TypeDatabase; +enum class ParserState; enum class StackElement : uint64_t { None = 0x0, @@ -94,8 +95,6 @@ enum class StackElement : uint64_t { // Code snip tags (0x1000, 0x2000, ... , 0xf000) InjectCode = 0x4000, - InjectCodeInFunction = 0x8000, - CodeSnipMask = 0xc000, // Function modifier tags (0x010000, 0x020000, ... , 0xf00000) Rename = 0x040000, // (modify-argument) @@ -132,7 +131,7 @@ inline StackElement operator|(StackElement s1, StackElement s2) struct StackElementContext { - CodeSnipList codeSnips; + CodeSnipList conversionCodeSnips; AddedFunctionList addedFunctions; FunctionModificationList functionMods; FieldModificationList fieldMods; @@ -260,6 +259,8 @@ private: QXmlStreamAttributes *); bool checkDuplicatedTypeEntry(const ConditionalStreamReader &reader, StackElement t, const QString &name) const; + ParserState parserState(qsizetype offset = 0) const; + CodeSnipAbstract *injectCodeTarget(qsizetype offset = 0) const; TypeDatabase* m_database; QStack m_stack; -- cgit v1.2.3