diff options
-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 716145668..2253b2350 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, @@ -882,27 +884,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(); @@ -940,9 +962,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: @@ -988,6 +1014,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(); @@ -2094,6 +2122,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")) @@ -2101,13 +2136,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; } @@ -3151,11 +3185,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 7950aa796..f601202ac 100644 --- a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml +++ b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml @@ -556,8 +556,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"> @@ -1231,14 +1235,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> |