diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-01-11 17:50:36 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-01-18 16:33:25 +0100 |
commit | c1e64f5e5583ba6e9e36bf54327747018a2541bc (patch) | |
tree | ffa8b7cd64b671cdcc2432fab6ed2bc9fc7cf493 | |
parent | 26a1b40e4fa878a11995528dcf04158b44477477 (diff) |
shiboken6/Type system parser: Handle native-to-target and vv in argument conversion rules
Introduce new parser states and handle it accordingly
in </native-to-target> and </target-to-native>.
Use it in the sample tests.
Pick-to: 6.2
Fixes: PYSIDE-1766
Change-Id: Id00dd3ad65799c497b008499c02fbf7ee2e5f856
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Christian Tismer <tismer@stackless.com>
-rw-r--r-- | sources/shiboken6/ApiExtractor/typesystemparser.cpp | 86 | ||||
-rw-r--r-- | sources/shiboken6/tests/samplebinding/typesystem_sample.xml | 28 |
2 files changed, 80 insertions, 34 deletions
diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp index 77dbeedae..6302b9ba4 100644 --- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp @@ -548,6 +548,8 @@ enum class ParserState PrimitiveTypeNativeToTargetConversion, PrimitiveTypeTargetToNativeConversion, ArgumentConversion, // Argument conversion rule with class attribute + ArgumentNativeToTargetConversion, + ArgumentTargetToNativeConversion, FunctionCodeInjection, TypeEntryCodeInjection, TypeSystemCodeInjection, @@ -884,27 +886,47 @@ bool TypeSystemParser::endElement(StackElement element) while (modIndex < top->functionMods.size()) top->addedFunctions.last()->modifications.append(top->functionMods.takeAt(modIndex)); } - break; + break; case StackElement::NativeToTarget: - case StackElement::AddConversion: { - auto *customConversion = top->entry->customConversion(); - if (!customConversion) { - m_error = QLatin1String("CustomConversion object is missing."); - return false; - } - - QString code = top->conversionCodeSnips.takeLast().code(); - if (element == StackElement::AddConversion) { - if (customConversion->targetToNativeConversions().isEmpty()) { - m_error = QLatin1String("CustomConversion's target to native conversions missing."); + case StackElement::AddConversion: + switch (parserState()) { + case ParserState::PrimitiveTypeNativeToTargetConversion: + case ParserState::PrimitiveTypeTargetToNativeConversion: + if (auto *customConversion = top->entry->customConversion()) { + QString code = top->conversionCodeSnips.constLast().code(); + if (element == StackElement::AddConversion) { + if (customConversion->targetToNativeConversions().isEmpty()) { + m_error = u"CustomConversion's target to native conversions missing."_qs; + return false; + } + customConversion->targetToNativeConversions().last()->setConversion(code); + } else { + customConversion->setNativeToTargetConversion(code); + } + } else { + m_error = QLatin1String("CustomConversion object is missing."); return false; } - customConversion->targetToNativeConversions().last()->setConversion(code); - } else { - customConversion->setNativeToTargetConversion(code); + break; + + case ParserState::ArgumentNativeToTargetConversion: { + top->conversionCodeSnips.last().language = TypeSystem::TargetLangCode; + auto &lastArgMod = m_contextStack.top()->functionMods.last().argument_mods().last(); + lastArgMod.conversionRules().append(top->conversionCodeSnips.constLast()); } - } - break; + break; + case ParserState::ArgumentTargetToNativeConversion: { + top->conversionCodeSnips.last().language = TypeSystem::NativeCode; + auto &lastArgMod = m_contextStack.top()->functionMods.last().argument_mods().last(); + lastArgMod.conversionRules().append(top->conversionCodeSnips.constLast()); + } + break; + default: + break; + } + top->conversionCodeSnips.clear(); + break; + case StackElement::EnumTypeEntry: top->entry->setDocModification(top->docModifications); top->docModifications = DocModificationList(); @@ -947,9 +969,13 @@ ParserState TypeSystemParser::parserState(qsizetype offset) const switch (m_stack.at(last)) { // Primitive entry with conversion rule case StackElement::NativeToTarget: // <conversion-rule><native-to-target> + if (stackSize > 2 && m_stack.at(last - 2) == StackElement::ModifyArgument) + return ParserState::ArgumentNativeToTargetConversion; return ParserState::PrimitiveTypeNativeToTargetConversion; case StackElement::AddConversion: // <conversion-rule><target-to-native><add-conversion> + if (stackSize > 3 && m_stack.at(last - 3) == StackElement::ModifyArgument) + return ParserState::ArgumentTargetToNativeConversion; return ParserState::PrimitiveTypeTargetToNativeConversion; case StackElement::ConversionRule: @@ -995,6 +1021,8 @@ CodeSnipAbstract *TypeSystemParser::injectCodeTarget(qsizetype offset) const switch (state) { case ParserState::PrimitiveTypeNativeToTargetConversion: case ParserState::PrimitiveTypeTargetToNativeConversion: + case ParserState::ArgumentNativeToTargetConversion: + case ParserState::ArgumentTargetToNativeConversion: return &top->conversionCodeSnips.last(); case ParserState::ArgumentConversion: return &top->functionMods.last().argument_mods().last().conversionRules().last(); @@ -2108,6 +2136,13 @@ bool TypeSystemParser::parseAddConversion(const ConditionalStreamReader &, CodeSnip snip; if (!readFileSnippet(attributes, &snip)) return false; + + const auto &top = m_contextStack.top(); + top->conversionCodeSnips.append(snip); + + if (parserState() == ParserState::ArgumentTargetToNativeConversion) + return true; + for (int i = attributes->size() - 1; i >= 0; --i) { const auto name = attributes->at(i).qualifiedName(); if (name == QLatin1String("type")) @@ -2115,13 +2150,12 @@ bool TypeSystemParser::parseAddConversion(const ConditionalStreamReader &, else if (name == QLatin1String("check")) typeCheck = attributes->takeAt(i).value().toString(); } + if (sourceTypeName.isEmpty()) { m_error = QLatin1String("Target to Native conversions must specify the input type with the 'type' attribute."); return false; } - const auto &top = m_contextStack.top(); top->entry->customConversion()->addTargetToNativeConversion(sourceTypeName, typeCheck); - top->conversionCodeSnips.append(snip); return true; } @@ -3165,11 +3199,15 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack m_error = QLatin1String("Target to Native conversions can only be specified for custom conversion rules."); return false; } - const int replaceIndex = indexOfAttribute(attributes, replaceAttribute()); - const bool replace = replaceIndex == -1 - || convertBoolean(attributes.takeAt(replaceIndex).value(), - replaceAttribute(), true); - top->entry->customConversion()->setReplaceOriginalTargetToNativeConversions(replace); + + const auto topParent = m_stack.value(m_stack.size() - 3, StackElement::None); + if ((topParent & StackElement::TypeEntryMask) != 0) { + const int replaceIndex = indexOfAttribute(attributes, replaceAttribute()); + const bool replace = replaceIndex == -1 + || convertBoolean(attributes.takeAt(replaceIndex).value(), + replaceAttribute(), true); + top->entry->customConversion()->setReplaceOriginalTargetToNativeConversions(replace); + } } break; case StackElement::AddConversion: diff --git a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml index 5ec2c6302..7d463b3a5 100644 --- a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml +++ b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml @@ -486,8 +486,12 @@ <modify-function signature="doSomethingWithArray(const unsigned char*, unsigned int, const char*)"> <modify-argument index="1"> <replace-type modified-type="const char*"/> - <conversion-rule class="native"> - const unsigned char* %out = reinterpret_cast<const unsigned char*>(Shiboken::String::toCString(%PYARG_1)); + <conversion-rule> + <target-to-native> + <add-conversion> + const unsigned char* %out = reinterpret_cast<const unsigned char*>(Shiboken::String::toCString(%PYARG_1)); + </add-conversion> + </target-to-native> </conversion-rule> </modify-argument> <modify-argument index="2"> @@ -1161,14 +1165,18 @@ </modify-argument> <modify-argument index="return"> <replace-type modified-type="PySequence"/> - <conversion-rule class="native"> - Shiboken::AutoDecRef _py_ok_(PySequence_GetItem(%PYARG_0, 0)); - Shiboken::AutoDecRef _py_ret_(PySequence_GetItem(%PYARG_0, 1)); - *%2 = %CONVERTTOCPP[bool](_py_ok_); - %RETURN_TYPE %out = %CONVERTTOCPP[%RETURN_TYPE](_py_ret_); - </conversion-rule> - <conversion-rule class="target"> - <insert-template name="differenceOfPointCoordinates_returnTarget"/> + <conversion-rule> + <target-to-native> + <add-conversion> + Shiboken::AutoDecRef _py_ok_(PySequence_GetItem(%PYARG_0, 0)); + Shiboken::AutoDecRef _py_ret_(PySequence_GetItem(%PYARG_0, 1)); + *%2 = %CONVERTTOCPP[bool](_py_ok_); + %RETURN_TYPE %out = %CONVERTTOCPP[%RETURN_TYPE](_py_ret_); + </add-conversion> + </target-to-native> + <native-to-target> + <insert-template name="differenceOfPointCoordinates_returnTarget"/> + </native-to-target> </conversion-rule> </modify-argument> </modify-function> |