aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2022-01-11 13:55:38 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-01-15 16:10:21 +0000
commit5b2b3d51c4843ada13903f4fe9ff238443883587 (patch)
tree30a6efa6845bc0878f170f73a3412e0cd403b741
parenta5ed4422e5cfd7a63a712d6a32220c6922c3d4c8 (diff)
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 <insert-template>. 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. Task-number: PYSIDE-1766 Change-Id: I291ec2db58687fdf63c124ddde26165f8eb09856 Reviewed-by: Christian Tismer <tismer@stackless.com> (cherry picked from commit b4ffbed19625bbf468c660a6dcc35a1101b8791b) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--sources/shiboken6/ApiExtractor/typesystemparser.cpp169
-rw-r--r--sources/shiboken6/ApiExtractor/typesystemparser.h7
2 files changed, 107 insertions, 69 deletions
diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
index bfa00643e..716145668 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: // <conversion-rule><native-to-target>
+ return ParserState::PrimitiveTypeNativeToTargetConversion;
+
+ case StackElement::AddConversion: // <conversion-rule><target-to-native><add-conversion>
+ 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 <class String> // 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;
}
@@ -2037,7 +2077,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;
}
@@ -2067,7 +2107,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;
}
@@ -2711,11 +2751,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;
}
@@ -2771,7 +2808,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<StackElement> m_stack;