diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2017-07-05 14:22:05 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2017-08-03 06:21:14 +0000 |
commit | 1578d14d1693122d4bcacede0d77527d8e898629 (patch) | |
tree | cb758cad0ab46f1884ecb44dc463a9f482be73dd | |
parent | da3afed804d47d25b5078103d400b5889e67915b (diff) |
Add new <array> argument modification indicating array usage
The modification can be used to indicate that for example
int* is meant to be used as int[].
This is reflected in the NativePointerAsArrayPattern
usage pattern of AbstractMetaType.
Task-number: PYSIDE-354
Task-number: PYSIDE-516
Change-Id: Icaeb3cce4be9ce06caa2cab628d4e8fc1b684819
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
12 files changed, 97 insertions, 11 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 6032b788e..95d700110 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -1990,7 +1990,8 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu } metaFunction->setOriginalAttributes(metaFunction->attributes()); - fixArgumentNames(metaFunction); + if (!metaArguments.isEmpty()) + fixArgumentNames(metaFunction, metaFunction->modifications(m_currentClass)); if (metaClass) { const AbstractMetaArgumentList fargs = metaFunction->arguments(); @@ -2018,11 +2019,8 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu return metaFunction; } -void AbstractMetaBuilderPrivate::fixArgumentNames(AbstractMetaFunction *func) +void AbstractMetaBuilderPrivate::fixArgumentNames(AbstractMetaFunction *func, const FunctionModificationList &mods) { - if (func->arguments().isEmpty()) - return; - const FunctionModificationList &mods = func->modifications(m_currentClass); for (const FunctionModification &mod : mods) { for (const ArgumentModification &argMod : mod.argument_mods) { if (!argMod.renamed_to.isEmpty()) { @@ -2108,6 +2106,39 @@ static inline AbstractMetaFunction::FunctionType functionTypeFromCodeModel(CodeM return result; } +static inline QString msgCannotSetArrayUsage(const QString &function, int i, const QString &reason) +{ + return function + QLatin1String(": Cannot use parameter ") + QString::number(i + 1) + + QLatin1String(" as an array: ") + reason; +} + +bool AbstractMetaBuilderPrivate::setArrayArgumentType(AbstractMetaFunction *func, + const FunctionModelItem &functionItem, + int i) +{ + + AbstractMetaType *metaType = func->arguments().at(i)->type(); + if (metaType->indirections() == 0) { + qCWarning(lcShiboken).noquote() + << msgCannotSetArrayUsage(func->minimalSignature(), i, + QLatin1String("Type does not have indirections.")); + return false; + } + TypeInfo elementType = functionItem->arguments().at(i)->type(); + elementType.setIndirections(elementType.indirections() - 1); + bool ok; + AbstractMetaType *element = translateType(elementType, &ok); + if (element == nullptr || !ok) { + qCWarning(lcShiboken).noquote() + << msgCannotSetArrayUsage(func->minimalSignature(), i, + QLatin1String("Cannot translate element type ") + elementType.toString()); + return false; + } + metaType->setArrayElementType(element); + metaType->setTypeUsagePattern(AbstractMetaType::NativePointerAsArrayPattern); + return true; +} + AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModelItem functionItem) { if (!functionItem->templateParameters().isEmpty()) @@ -2322,7 +2353,16 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel } - fixArgumentNames(metaFunction); + if (!metaArguments.isEmpty()) { + const FunctionModificationList &mods = metaFunction->modifications(m_currentClass); + fixArgumentNames(metaFunction, mods); + for (const FunctionModification &mod : mods) { + for (const ArgumentModification &argMod : mod.argument_mods) { + if (argMod.array) + setArrayArgumentType(metaFunction, functionItem, argMod.index - 1); + } + } + } // Determine class special functions if (m_currentClass && metaFunction->arguments().size() == 1) { diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h index 8c4e4b185..71b69473e 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h @@ -155,7 +155,10 @@ public: void sortLists(); AbstractMetaArgumentList reverseList(const AbstractMetaArgumentList &list); void setInclude(TypeEntry *te, const QString &fileName) const; - void fixArgumentNames(AbstractMetaFunction *func); + void fixArgumentNames(AbstractMetaFunction *func, const FunctionModificationList &mods); + bool setArrayArgumentType(AbstractMetaFunction *func, + const FunctionModelItem &functionItem, int i); + void fillAddedFunctions(AbstractMetaClass *metaClass); AbstractMetaBuilder *q; diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index 7cd9c371e..d38eb8587 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -158,6 +158,9 @@ AbstractMetaTypeCList AbstractMetaType::nestedArrayTypes() const t = elt; } break; + case NativePointerAsArrayPattern: + result.append(m_arrayElementType); + break; default: break; } diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index c838f97e2..0529bed24 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -326,6 +326,7 @@ public: QObjectPattern, ValuePointerPattern, NativePointerPattern, + NativePointerAsArrayPattern, // "int*" as "int[]" ContainerPattern, SmartPointerPattern, VariantPattern, diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp index 9adc5107b..13664c336 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.cpp +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -176,6 +176,7 @@ Handler::Handler(TypeDatabase* database, bool generate) tagNames.insert(QLatin1String("no-null-pointer"), StackElement::NoNullPointers); tagNames.insert(QLatin1String("reference-count"), StackElement::ReferenceCount); tagNames.insert(QLatin1String("parent"), StackElement::ParentOwner); + tagNames.insert(QLatin1String("array"), StackElement::Array); tagNames.insert(QLatin1String("inject-documentation"), StackElement::InjectDocumentation); tagNames.insert(QLatin1String("modify-documentation"), StackElement::ModifyDocumentation); tagNames.insert(QLatin1String("add-function"), StackElement::AddFunction); @@ -1283,6 +1284,9 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts case StackElement::ParentOwner: attributes.insert(QLatin1String("index"), QString()); attributes.insert(QLatin1String("action"), QString()); + break; + case StackElement::Array: + break; default: { }; }; @@ -1875,8 +1879,13 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts m_contextStack.top()->functionMods.last().argument_mods.last().owner = ao; } break; - - + case StackElement::Array: + if (topElement.type != StackElement::ModifyArgument) { + m_error = QLatin1String("array must be child of modify-argument"); + return false; + } + m_contextStack.top()->functionMods.last().argument_mods.last().array = true; + break; case StackElement::InjectCode: { if (!(topElement.type & StackElement::ComplexTypeEntryMask) && (topElement.type != StackElement::AddFunction) diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index b75da48ba..6c65adbe1 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -211,16 +211,17 @@ public: struct ArgumentModification { ArgumentModification() : removedDefaultExpression(false), removed(false), - noNullPointers(false), index(-1), version(0) {} + noNullPointers(false), array(false), index(-1), version(0) {} ArgumentModification(int idx, double vr) : removedDefaultExpression(false), removed(false), - noNullPointers(false), index(idx), version(vr) {} + noNullPointers(false), array(false), index(idx), version(vr) {} // Should the default expression be removed? uint removedDefaultExpression : 1; uint removed : 1; uint noNullPointers : 1; uint resetAfterUse : 1; + uint array : 1; // consider "int*" to be "int[]" // The index of this argument int index; diff --git a/sources/shiboken2/ApiExtractor/typesystem_p.h b/sources/shiboken2/ApiExtractor/typesystem_p.h index f2105a631..d485aad42 100644 --- a/sources/shiboken2/ApiExtractor/typesystem_p.h +++ b/sources/shiboken2/ApiExtractor/typesystem_p.h @@ -107,6 +107,7 @@ class StackElement NoNullPointers = 0x40000000, ReferenceCount = 0x80000000, ParentOwner = 0x90000000, + Array = 0xA0000000, ArgumentModifiers = 0xff000000 }; diff --git a/sources/shiboken2/tests/libsample/functions.cpp b/sources/shiboken2/tests/libsample/functions.cpp index 7a91a7b62..9fa4efc37 100644 --- a/sources/shiboken2/tests/libsample/functions.cpp +++ b/sources/shiboken2/tests/libsample/functions.cpp @@ -209,6 +209,15 @@ double sumDoubleArray(double array[4]) return std::accumulate(array, array + 4, double(0)); } +ArrayModifyTest::ArrayModifyTest() +{ +} + +int ArrayModifyTest::sumIntArray(int n, int *array) +{ + return std::accumulate(array, array + n, 0); +} + ClassWithFunctionPointer::ClassWithFunctionPointer() { callFunctionPointer(0, &ClassWithFunctionPointer::doNothing); diff --git a/sources/shiboken2/tests/libsample/functions.h b/sources/shiboken2/tests/libsample/functions.h index 69d4cdceb..5289d7ce0 100644 --- a/sources/shiboken2/tests/libsample/functions.h +++ b/sources/shiboken2/tests/libsample/functions.h @@ -84,6 +84,13 @@ LIBSAMPLE_API OddBool acceptOddBoolReference(OddBool& x); LIBSAMPLE_API int sumIntArray(int array[4]); LIBSAMPLE_API double sumDoubleArray(double array[4]); +class LIBSAMPLE_API ArrayModifyTest +{ +public: + ArrayModifyTest(); + int sumIntArray(int n, int *array); +}; + class LIBSAMPLE_API ClassWithFunctionPointer { public: diff --git a/sources/shiboken2/tests/samplebinding/CMakeLists.txt b/sources/shiboken2/tests/samplebinding/CMakeLists.txt index 1b97bd0e8..b3c9df0dd 100644 --- a/sources/shiboken2/tests/samplebinding/CMakeLists.txt +++ b/sources/shiboken2/tests/samplebinding/CMakeLists.txt @@ -7,6 +7,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/typesystem_sample.xml set(sample_SRC ${CMAKE_CURRENT_BINARY_DIR}/sample/abstractmodifications_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/abstract_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/arraymodifytest_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/base1_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/base2_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/base3_wrapper.cpp diff --git a/sources/shiboken2/tests/samplebinding/array_sequence_test.py b/sources/shiboken2/tests/samplebinding/array_sequence_test.py index 3c6a23845..0fd2ec636 100644 --- a/sources/shiboken2/tests/samplebinding/array_sequence_test.py +++ b/sources/shiboken2/tests/samplebinding/array_sequence_test.py @@ -40,6 +40,11 @@ class ArrayTester(unittest.TestCase): intList = [1, 2, 3, 4] self.assertEqual(sample.sumIntArray(intList), 10) + def testIntArrayModified(self): + intList = [1, 2, 3, 4] + tester = sample.ArrayModifyTest() + self.assertEqual(tester.sumIntArray(4, intList), 10) + def testDoubleArray(self): doubleList = [1.2, 2.3, 3.4, 4.5] self.assertEqual(sample.sumDoubleArray(doubleList), 11.4) diff --git a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml index 9db4a7928..32fbd8ced 100644 --- a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml +++ b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml @@ -508,6 +508,12 @@ <function signature="overloadedFunc(double)" /> <function signature="overloadedFunc(int)" /> + <value-type name="ArrayModifyTest"> + <modify-function signature="sumIntArray(int, int*)"> + <modify-argument index="2"><array/></modify-argument> + </modify-function> + </value-type> + <value-type name="ClassWithFunctionPointer"> <suppress-warning text="skipping function 'ClassWithFunctionPointer::callFunctionPointer', unmatched parameter type 'void (*)(void*)'" /> </value-type> |